com.netflix.spinnaker.clouddriver.google.provider.agent.AbstractGoogleLoadBalancerCachingAgent.groovy Maven / Gradle / Ivy
/*
* Copyright 2017 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License")
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.netflix.spinnaker.clouddriver.google.provider.agent
import com.fasterxml.jackson.core.type.TypeReference
import com.fasterxml.jackson.databind.ObjectMapper
import com.netflix.spectator.api.Registry
import com.netflix.spinnaker.cats.agent.AgentDataType
import com.netflix.spinnaker.cats.agent.CacheResult
import com.netflix.spinnaker.cats.cache.CacheData
import com.netflix.spinnaker.cats.cache.DefaultCacheData
import com.netflix.spinnaker.cats.provider.ProviderCache
import com.netflix.spinnaker.clouddriver.cache.OnDemandAgent
import com.netflix.spinnaker.clouddriver.cache.OnDemandMetricsSupport
import com.netflix.spinnaker.clouddriver.cache.OnDemandType
import com.netflix.spinnaker.clouddriver.google.GoogleCloudProvider
import com.netflix.spinnaker.clouddriver.google.cache.CacheResultBuilder
import com.netflix.spinnaker.clouddriver.google.cache.Keys
import com.netflix.spinnaker.clouddriver.google.model.callbacks.Utils
import com.netflix.spinnaker.clouddriver.google.model.health.GoogleLoadBalancerHealth
import com.netflix.spinnaker.clouddriver.google.model.loadbalancing.GoogleLoadBalancer
import com.netflix.spinnaker.clouddriver.google.security.GoogleNamedAccountCredentials
import groovy.transform.Canonical
import groovy.util.logging.Slf4j
import java.util.concurrent.TimeUnit
import static com.netflix.spinnaker.cats.agent.AgentDataType.Authority.AUTHORITATIVE
import static com.netflix.spinnaker.cats.agent.AgentDataType.Authority.INFORMATIVE
import static com.netflix.spinnaker.clouddriver.google.cache.Keys.Namespace.*
@Slf4j
abstract class AbstractGoogleLoadBalancerCachingAgent extends AbstractGoogleCachingAgent implements OnDemandAgent {
String agentType = "${accountName}/${region}/${this.class.simpleName}"
String onDemandAgentType = "${agentType}-OnDemand"
final String region
final OnDemandMetricsSupport metricsSupport
final Set providedDataTypes = [
AUTHORITATIVE.forType(LOAD_BALANCERS.ns),
INFORMATIVE.forType(INSTANCES.ns),
] as Set
AbstractGoogleLoadBalancerCachingAgent(String clouddriverUserAgentApplicationName,
GoogleNamedAccountCredentials credentials,
ObjectMapper objectMapper,
Registry registry,
String region) {
super(clouddriverUserAgentApplicationName,
credentials,
objectMapper,
registry)
this.region = region
this.metricsSupport = new OnDemandMetricsSupport(
registry,
this,
"${GoogleCloudProvider.ID}:${OnDemandType.LoadBalancer}")
}
@Override
boolean handles(OnDemandType type, String cloudProvider) {
type == OnDemandType.LoadBalancer && cloudProvider == GoogleCloudProvider.ID
}
@Override
OnDemandAgent.OnDemandResult handle(ProviderCache providerCache, Map data) {
if (!data.containsKey("loadBalancerName") || data.account != accountName || data.region != region) {
return null
}
GoogleLoadBalancer loadBalancer
try {
loadBalancer = metricsSupport.readData {
getLoadBalancer(data.loadBalancerName as String)
}
} catch (IllegalArgumentException e) {
// If after retrieving the root of the load balancer resource tree, the caching agent determines that it is not
// responsible for caching the type of load balancer retrieved, it will throw this exception. We then return
// null to avoid evicting the load balancer from the on demand namespace (since the correct caching agent will
// have added it there).
return null
}
def loadBalancerKey
Collection identifiers = []
if (loadBalancer) {
loadBalancerKey = Keys.getLoadBalancerKey(loadBalancer.region, accountName, loadBalancer.name)
} else {
loadBalancerKey = Keys.getLoadBalancerKey(region, accountName, data.loadBalancerName as String)
// TODO(duftler): Is this right? Seems like this should use a wildcard.
// No load balancer was found, so need to find identifiers for all load balancers in the region.
identifiers = providerCache.filterIdentifiers(LOAD_BALANCERS.ns, loadBalancerKey)
}
def cacheResultBuilder = new CacheResultBuilder(startTime: Long.MAX_VALUE)
CacheResult result = metricsSupport.transformData {
buildCacheResult(cacheResultBuilder, loadBalancer ? [loadBalancer] : [])
}
if (result.cacheResults.values().flatten().empty) {
// Avoid writing an empty onDemand cache record (instead delete any that may have previously existed).
providerCache.evictDeletedItems(ON_DEMAND.ns, identifiers)
} else {
metricsSupport.onDemandStore {
def cacheData = new DefaultCacheData(
loadBalancerKey,
TimeUnit.MINUTES.toSeconds(10) as Integer, // ttl
[
cacheTime : System.currentTimeMillis(),
cacheResults : objectMapper.writeValueAsString(result.cacheResults),
processedCount: 0,
processedTime : null
],
[:]
)
providerCache.putCacheData(ON_DEMAND.ns, cacheData)
}
}
Map> evictions = [:].withDefault {_ -> []}
if (!loadBalancer) {
evictions[LOAD_BALANCERS.ns].addAll(identifiers)
}
log.debug("On demand cache refresh succeeded. Data: ${data}. Added ${loadBalancer ? 1 : 0} items to the cache.")
return new OnDemandAgent.OnDemandResult(
sourceAgentType: getOnDemandAgentType(),
cacheResult: result,
evictions: evictions,
// Do not include "authoritativeTypes" here, as it will result in all other cache entries getting deleted!
)
}
@Override
Collection
© 2015 - 2025 Weber Informatics LLC | Privacy Policy