Skip to content

Commit

Permalink
fix(gcp): Relaxed health check for GCP accounts (backport #6200) (#6201)
Browse files Browse the repository at this point in the history
* fix(gcp): Relaxed health check for GCP accounts (#6200)

(cherry picked from commit 28599eb)

# Conflicts:
#	clouddriver-google/src/main/groovy/com/netflix/spinnaker/clouddriver/google/health/GoogleHealthIndicator.groovy

* fix: Fixes PR to match 1.28 versions of credential repository APIs

---------

Co-authored-by: Christos Arvanitis <christos.arvanitis@armory.io>
Co-authored-by: Jason McIntosh <jason.mcintosh@harness.io>
  • Loading branch information
3 people authored May 7, 2024
1 parent 860f4a4 commit 95d0e68
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package com.netflix.spinnaker.clouddriver.google.health

import com.netflix.spectator.api.Registry
import com.netflix.spinnaker.clouddriver.google.GoogleExecutorTraits
import com.netflix.spinnaker.clouddriver.google.config.GoogleConfigurationProperties
import com.netflix.spinnaker.clouddriver.google.security.GoogleCredentials
import com.netflix.spinnaker.clouddriver.google.security.GoogleNamedAccountCredentials
import com.netflix.spinnaker.clouddriver.security.AccountCredentialsProvider
Expand Down Expand Up @@ -47,6 +48,9 @@ class GoogleHealthIndicator implements HealthIndicator, GoogleExecutorTraits {

private final AtomicReference<Exception> lastException = new AtomicReference<>(null)

@Autowired
GoogleConfigurationProperties googleConfigurationProperties

@Override
Health health() {
def ex = lastException.get()
Expand All @@ -61,21 +65,25 @@ class GoogleHealthIndicator implements HealthIndicator, GoogleExecutorTraits {
@Scheduled(fixedDelay = 300000L)
void checkHealth() {
try {
Set<GoogleNamedAccountCredentials> googleCredentialsSet = accountCredentialsProvider.all.findAll {
it instanceof GoogleNamedAccountCredentials
} as Set<GoogleNamedAccountCredentials>

for (GoogleNamedAccountCredentials accountCredentials in googleCredentialsSet) {
try {
// This verifies that the specified credentials are sufficient to access the referenced project.
timeExecute(accountCredentials.compute.projects().get(accountCredentials.project),
"compute.projects.get",
TAG_SCOPE, SCOPE_GLOBAL)
} catch (IOException e) {
throw new GoogleIOException(e)
if (googleConfigurationProperties.getHealth().getVerifyAccountHealth()) {
LOG.info("google.health.verifyAccountHealth flag is enabled - verifying connection to the Google accounts")
Set<GoogleNamedAccountCredentials> googleCredentialsSet = accountCredentialsProvider.all.findAll {
it instanceof GoogleNamedAccountCredentials
} as Set<GoogleNamedAccountCredentials>

for (GoogleNamedAccountCredentials accountCredentials in googleCredentialsSet) {
try {
// This verifies that the specified credentials are sufficient to access the referenced project.
timeExecute(accountCredentials.compute.projects().get(accountCredentials.project),
"compute.projects.get",
TAG_SCOPE, SCOPE_GLOBAL)
} catch (IOException e) {
throw new GoogleIOException(e)
}
}
} else {
LOG.info("google.health.verifyAccountHealth flag is disabled - Not verifying connection to the Google accounts");
}

lastException.set(null)
} catch (Exception ex) {
LOG.warn "Unhealthy", ex
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,6 @@ class GoogleConfiguration {
new GoogleConfigurationProperties()
}

@Bean
@ConditionalOnProperty("google.health.verifyAccountHealth")
GoogleHealthIndicator googleHealthIndicator() {
new GoogleHealthIndicator()
}

@Bean
GoogleOperationPoller googleOperationPoller() {
new GoogleOperationPoller()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import com.google.common.collect.ImmutableList
import com.google.common.collect.ImmutableMap
import com.netflix.spectator.api.NoopRegistry
import com.netflix.spectator.api.Registry
import com.netflix.spinnaker.clouddriver.google.config.GoogleConfigurationProperties
import com.netflix.spinnaker.clouddriver.google.provider.agent.StubComputeFactory
import com.netflix.spinnaker.clouddriver.google.security.GoogleNamedAccountCredentials
import com.netflix.spinnaker.clouddriver.security.DefaultAccountCredentialsProvider
Expand Down Expand Up @@ -62,7 +63,7 @@ class GoogleHealthIndicatorSpec extends Specification {

def accountCredentialsProvider = new DefaultAccountCredentialsProvider(credentialsRepository)

def indicator = new GoogleHealthIndicator()
def indicator = new GoogleHealthIndicator(googleConfigurationProperties: new GoogleConfigurationProperties())
indicator.registry = REGISTRY
indicator.accountCredentialsProvider = accountCredentialsProvider

Expand Down Expand Up @@ -101,7 +102,7 @@ class GoogleHealthIndicatorSpec extends Specification {

def accountCredentialsProvider = new DefaultAccountCredentialsProvider(credentialsRepository)

def indicator = new GoogleHealthIndicator()
def indicator = new GoogleHealthIndicator(googleConfigurationProperties: new GoogleConfigurationProperties())
indicator.registry = REGISTRY
indicator.accountCredentialsProvider = accountCredentialsProvider

Expand All @@ -114,4 +115,45 @@ class GoogleHealthIndicatorSpec extends Specification {

health == null
}

@Unroll
def "health succeeds when google is unreachable and verifyAccountHealth is false"() {
setup:
def project = new Project()
project.setName(PROJECT)

def compute = new StubComputeFactory()
.setProjects(project)
.setProjectException(new IOException("Read timed out"))
.create()

def googleNamedAccountCredentials =
new GoogleNamedAccountCredentials.Builder()
.project(PROJECT)
.name(ACCOUNT_NAME)
.compute(compute)
.regionToZonesMap(ImmutableMap.of(REGION, ImmutableList.of(ZONE)))
.build()

def credentials = [googleNamedAccountCredentials]
def credentialsRepository = Stub(MapBackedAccountCredentialsRepository) {
getAll() >> credentials
}

def accountCredentialsProvider = new DefaultAccountCredentialsProvider(credentialsRepository)


def indicator = new GoogleHealthIndicator(googleConfigurationProperties: new GoogleConfigurationProperties())
indicator.googleConfigurationProperties.health.setVerifyAccountHealth(false)
indicator.registry = REGISTRY


when:
indicator.checkHealth()
def health = indicator.health()

then:
health.status == Status.UP
health.details.isEmpty()
}
}

0 comments on commit 95d0e68

Please sign in to comment.