diff --git a/orca-applications/src/main/groovy/com/netflix/spinnaker/orca/applications/tasks/VerifyApplicationHasNoDependenciesTask.groovy b/orca-applications/src/main/groovy/com/netflix/spinnaker/orca/applications/tasks/VerifyApplicationHasNoDependenciesTask.groovy index ac391ed4c1..b74368ff21 100644 --- a/orca-applications/src/main/groovy/com/netflix/spinnaker/orca/applications/tasks/VerifyApplicationHasNoDependenciesTask.groovy +++ b/orca-applications/src/main/groovy/com/netflix/spinnaker/orca/applications/tasks/VerifyApplicationHasNoDependenciesTask.groovy @@ -21,8 +21,8 @@ import com.netflix.spinnaker.orca.api.pipeline.models.ExecutionStatus import com.netflix.spinnaker.orca.api.pipeline.Task import com.netflix.spinnaker.orca.api.pipeline.models.StageExecution import com.netflix.spinnaker.orca.api.pipeline.TaskResult +import com.netflix.spinnaker.orca.clouddriver.CloudDriverService import com.netflix.spinnaker.orca.clouddriver.MortService -import com.netflix.spinnaker.orca.clouddriver.OortService import com.netflix.spinnaker.orca.front50.model.Application import groovy.util.logging.Slf4j import org.springframework.beans.factory.annotation.Autowired @@ -35,7 +35,7 @@ import javax.annotation.Nonnull @Slf4j class VerifyApplicationHasNoDependenciesTask implements Task { @Autowired - OortService oortService + CloudDriverService cloudDriverService @Autowired MortService mortService @@ -50,7 +50,7 @@ class VerifyApplicationHasNoDependenciesTask implements Task { def existingDependencyTypes = [] try { - def oortResult = getOortResult(application.name as String) + def oortResult = cloudDriverService.getApplication(application.name as String) if (oortResult && oortResult.clusters) { existingDependencyTypes << "clusters" } @@ -91,11 +91,6 @@ class VerifyApplicationHasNoDependenciesTask implements Task { ]]).build() } - protected Map getOortResult(String applicationName) { - def oortResponse = oortService.getApplication(applicationName) - return objectMapper.readValue(oortResponse.body.in().text, Map) - } - protected List getMortResults(String applicationName, String type) { def mortResults = mortService.getSearchResults(applicationName, type) return mortResults ? mortResults[0].results : [] diff --git a/orca-applications/src/test/groovy/com/netflix/spinnaker/orca/applications/tasks/VerifyApplicationHasNoDependenciesTaskSpec.groovy b/orca-applications/src/test/groovy/com/netflix/spinnaker/orca/applications/tasks/VerifyApplicationHasNoDependenciesTaskSpec.groovy index 9c80b2565a..0bccda2349 100644 --- a/orca-applications/src/test/groovy/com/netflix/spinnaker/orca/applications/tasks/VerifyApplicationHasNoDependenciesTaskSpec.groovy +++ b/orca-applications/src/test/groovy/com/netflix/spinnaker/orca/applications/tasks/VerifyApplicationHasNoDependenciesTaskSpec.groovy @@ -18,6 +18,7 @@ package com.netflix.spinnaker.orca.applications.tasks import com.fasterxml.jackson.databind.ObjectMapper import com.netflix.spinnaker.orca.api.pipeline.models.ExecutionStatus +import com.netflix.spinnaker.orca.clouddriver.CloudDriverService import com.netflix.spinnaker.orca.pipeline.model.TaskExecutionImpl import spock.lang.Shared import spock.lang.Specification @@ -35,16 +36,14 @@ class VerifyApplicationHasNoDependenciesTaskSpec extends Specification { } } + CloudDriverService cloudDriverService = Mock() + @Unroll void "should be TERMINAL when application has clusters or security groups"() { given: def fixedSecurityGroups = securityGroups def fixedClusters = clusters def task = new VerifyApplicationHasNoDependenciesTask() { - @Override - protected Map getOortResult(String applicationName) { - return [clusters: fixedClusters] - } @Override protected List getMortResults(String applicationName, String type) { @@ -52,8 +51,11 @@ class VerifyApplicationHasNoDependenciesTaskSpec extends Specification { } } task.objectMapper = new ObjectMapper() + task.cloudDriverService = cloudDriverService + cloudDriverService.getApplication(_) >> [clusters: fixedClusters] and: + def stage = pipeline.stages.first() stage.tasks = [new TaskExecutionImpl(name: "T1"), new TaskExecutionImpl(name: "T2")] diff --git a/orca-clouddriver-provider-titus/src/main/java/com/netflix/spinnaker/orca/clouddriver/tasks/servergroup/TitusInterestingHealthProviderNamesSupplier.java b/orca-clouddriver-provider-titus/src/main/java/com/netflix/spinnaker/orca/clouddriver/tasks/servergroup/TitusInterestingHealthProviderNamesSupplier.java index 7bc9c1bdf4..327714db8b 100644 --- a/orca-clouddriver-provider-titus/src/main/java/com/netflix/spinnaker/orca/clouddriver/tasks/servergroup/TitusInterestingHealthProviderNamesSupplier.java +++ b/orca-clouddriver-provider-titus/src/main/java/com/netflix/spinnaker/orca/clouddriver/tasks/servergroup/TitusInterestingHealthProviderNamesSupplier.java @@ -16,9 +16,8 @@ package com.netflix.spinnaker.orca.clouddriver.tasks.servergroup; -import com.fasterxml.jackson.databind.ObjectMapper; import com.netflix.spinnaker.orca.api.pipeline.models.StageExecution; -import com.netflix.spinnaker.orca.clouddriver.OortService; +import com.netflix.spinnaker.orca.clouddriver.CloudDriverService; import com.netflix.spinnaker.orca.kato.pipeline.support.SourceResolver; import com.netflix.spinnaker.orca.kato.pipeline.support.StageData; import java.util.Arrays; @@ -29,7 +28,6 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import retrofit.client.Response; @Component public class TitusInterestingHealthProviderNamesSupplier @@ -42,16 +40,14 @@ public class TitusInterestingHealthProviderNamesSupplier private static final List SUPPORTED_STAGES = Arrays.asList("cloneservergroup", "enableservergroup"); - private final OortService oortService; - private final ObjectMapper objectMapper; + private final CloudDriverService cloudDriverService; private final SourceResolver sourceResolver; @Autowired public TitusInterestingHealthProviderNamesSupplier( - OortService oortService, SourceResolver sourceResolver, ObjectMapper objectMapper) { - this.oortService = oortService; + CloudDriverService cloudDriverService, SourceResolver sourceResolver) { + this.cloudDriverService = cloudDriverService; this.sourceResolver = sourceResolver; - this.objectMapper = objectMapper; } @Override @@ -73,8 +69,8 @@ public List process(String cloudProvider, StageExecution stage) { String serverGroupName = source.getServerGroupName() != null ? source.getServerGroupName() : source.getAsgName(); - Response response = - oortService.getServerGroupFromCluster( + Map serverGroup = + cloudDriverService.getServerGroupFromCluster( stageData.getApplication(), source.getAccount(), stageData.getCluster(), @@ -82,7 +78,6 @@ public List process(String cloudProvider, StageExecution stage) { source.getRegion(), cloudProvider); - Map serverGroup = objectMapper.readValue(response.getBody().in(), Map.class); Map titusServerGroupLabels = (Map) serverGroup.get("labels"); if (titusServerGroupLabels != null diff --git a/orca-clouddriver-provider-titus/src/test/groovy/com/netflix/spinnaker/orca/clouddriver/tasks/servergroup/TitusInterestingHealthProviderNamesSupplierSpec.groovy b/orca-clouddriver-provider-titus/src/test/groovy/com/netflix/spinnaker/orca/clouddriver/tasks/servergroup/TitusInterestingHealthProviderNamesSupplierSpec.groovy index 5ef69bc8e2..ee61f9b514 100644 --- a/orca-clouddriver-provider-titus/src/test/groovy/com/netflix/spinnaker/orca/clouddriver/tasks/servergroup/TitusInterestingHealthProviderNamesSupplierSpec.groovy +++ b/orca-clouddriver-provider-titus/src/test/groovy/com/netflix/spinnaker/orca/clouddriver/tasks/servergroup/TitusInterestingHealthProviderNamesSupplierSpec.groovy @@ -16,23 +16,19 @@ package com.netflix.spinnaker.orca.clouddriver.tasks.servergroup -import com.netflix.spinnaker.orca.clouddriver.OortService -import com.netflix.spinnaker.orca.jackson.OrcaObjectMapper +import com.netflix.spinnaker.orca.clouddriver.CloudDriverService import com.netflix.spinnaker.orca.kato.pipeline.support.SourceResolver import com.netflix.spinnaker.orca.pipeline.model.PipelineExecutionImpl import com.netflix.spinnaker.orca.pipeline.model.StageExecutionImpl -import retrofit.client.Response -import retrofit.mime.TypedString import spock.lang.Specification import spock.lang.Subject import spock.lang.Unroll class TitusInterestingHealthProviderNamesSupplierSpec extends Specification { - def oortService = Mock(OortService) - def mapper = OrcaObjectMapper.newInstance() + CloudDriverService cloudDriverService = Mock() @Subject - def titusInterestingHealthProviderNamesSupplier = new TitusInterestingHealthProviderNamesSupplier(oortService, new SourceResolver(), mapper) + def titusInterestingHealthProviderNamesSupplier = new TitusInterestingHealthProviderNamesSupplier(cloudDriverService, new SourceResolver()) @Unroll def "should only support if cloudProvider is titus and stage type in [enableServerGroup, cloneServerGroup]"() { @@ -56,15 +52,15 @@ class TitusInterestingHealthProviderNamesSupplierSpec extends Specification { def "should process interestingHealthNames by inspecting labels on titus serverGroup"() { given: def stage = new StageExecutionImpl(PipelineExecutionImpl.newPipeline("orca"), "createServerGroup", stageContext) - def response = mapper.writeValueAsString([ + def response = [ application: "app", region: "region", account: "test", labels: labels - ]) + ] and: - 1 * oortService.getServerGroupFromCluster(*_) >> new Response('oort', 200, 'ok', [], new TypedString(response)) + 1 * cloudDriverService.getServerGroupFromCluster(*_) >> response when: def interestingHealthProviderNames = titusInterestingHealthProviderNamesSupplier.process("titus", stage) diff --git a/orca-clouddriver/src/main/groovy/com/netflix/spinnaker/orca/clouddriver/OortService.groovy b/orca-clouddriver/src/main/groovy/com/netflix/spinnaker/orca/clouddriver/OortService.groovy index 98043cb676..322587a3ab 100644 --- a/orca-clouddriver/src/main/groovy/com/netflix/spinnaker/orca/clouddriver/OortService.groovy +++ b/orca-clouddriver/src/main/groovy/com/netflix/spinnaker/orca/clouddriver/OortService.groovy @@ -125,7 +125,7 @@ interface OortService { @Path("name") String name) @GET("/{type}/images/{account}/{region}/{imageId}") - List getByAmiId(@Path("type") String type, + List> getByAmiId(@Path("type") String type, @Path("account") String account, @Path("region") String region, @Path("imageId") imageId) @@ -138,7 +138,7 @@ interface OortService { @QueryMap Map additionalFilters) @GET("/tags") - List getEntityTags(@Query("cloudProvider") String cloudProvider, + List> getEntityTags(@Query("cloudProvider") String cloudProvider, @Query("entityType") String entityType, @Query("entityId") String entityId, @Query("account") String account, diff --git a/orca-clouddriver/src/main/groovy/com/netflix/spinnaker/orca/clouddriver/tasks/instance/AbstractInstancesCheckTask.groovy b/orca-clouddriver/src/main/groovy/com/netflix/spinnaker/orca/clouddriver/tasks/instance/AbstractInstancesCheckTask.groovy index 212f31dd0c..87840d6679 100644 --- a/orca-clouddriver/src/main/groovy/com/netflix/spinnaker/orca/clouddriver/tasks/instance/AbstractInstancesCheckTask.groovy +++ b/orca-clouddriver/src/main/groovy/com/netflix/spinnaker/orca/clouddriver/tasks/instance/AbstractInstancesCheckTask.groovy @@ -17,17 +17,16 @@ package com.netflix.spinnaker.orca.clouddriver.tasks.instance import com.netflix.spinnaker.orca.api.pipeline.models.StageExecution +import com.netflix.spinnaker.orca.clouddriver.CloudDriverService import com.netflix.spinnaker.orca.clouddriver.utils.MonikerHelper import java.time.Duration import java.util.concurrent.TimeUnit -import com.fasterxml.jackson.databind.ObjectMapper import com.netflix.frigga.Names import com.netflix.spinnaker.moniker.Moniker import com.netflix.spinnaker.orca.api.pipeline.models.ExecutionStatus import com.netflix.spinnaker.orca.api.pipeline.OverridableTimeoutRetryableTask import com.netflix.spinnaker.orca.api.pipeline.TaskResult -import com.netflix.spinnaker.orca.clouddriver.OortService import com.netflix.spinnaker.orca.clouddriver.tasks.AbstractCloudProviderAwareTask import com.netflix.spinnaker.orca.clouddriver.tasks.servergroup.ServerGroupCacheForceRefreshTask import com.netflix.spinnaker.orca.clouddriver.utils.OortHelper @@ -43,10 +42,7 @@ abstract class AbstractInstancesCheckTask extends AbstractCloudProviderAwareTask long serverGroupWaitTime = TimeUnit.MINUTES.toMillis(10) @Autowired - OortService oortService - - @Autowired - ObjectMapper objectMapper + CloudDriverService cloudDriverService @Autowired ServerGroupCacheForceRefreshTask serverGroupCacheForceRefreshTask @@ -213,16 +209,15 @@ abstract class AbstractInstancesCheckTask extends AbstractCloudProviderAwareTask Names names = Names.parseName(serverGroupsByRegion.values().flatten()[0]) def appName = moniker?.app ?: names.app def clusterName = moniker?.cluster ?: names.cluster - def response = oortService.getCluster(appName, account, clusterName, cloudProvider) - def cluster = objectMapper.readValue(response.body.in().text, Map) + def cluster = cloudDriverService.getCluster(appName, account, clusterName, cloudProvider) return cluster.serverGroups ?: [] } else { def region = serverGroupsByRegion.keySet()[0] def serverGroupName = serverGroupsByRegion[region][0] try { - def response = oortService.getServerGroup(account, region, serverGroupName) - return [objectMapper.readValue(response.body.in().text, Map)] + def response = cloudDriverService.getServerGroup(account, region, serverGroupName) + return [response] } catch (RetrofitError e) { if (e.response?.status != 404 || waitForUpServerGroup()) { throw e diff --git a/orca-clouddriver/src/main/groovy/com/netflix/spinnaker/orca/clouddriver/utils/OortHelper.groovy b/orca-clouddriver/src/main/groovy/com/netflix/spinnaker/orca/clouddriver/utils/OortHelper.groovy index 16c63c048a..c6522fee79 100644 --- a/orca-clouddriver/src/main/groovy/com/netflix/spinnaker/orca/clouddriver/utils/OortHelper.groovy +++ b/orca-clouddriver/src/main/groovy/com/netflix/spinnaker/orca/clouddriver/utils/OortHelper.groovy @@ -31,18 +31,25 @@ import retrofit.converter.JacksonConverter */ @Component class OortHelper { - @Autowired - OortService oortService + + private final OortService oortService + + private final ObjectMapper objectMapper + + private final JacksonConverter converter @Autowired - ObjectMapper objectMapper + OortHelper(OortService oortService, ObjectMapper objectMapper) { + this.oortService = oortService + this.objectMapper = objectMapper + converter = new JacksonConverter(objectMapper) + } List getSearchResults(String searchTerm, String type, String platform) { convert(oortService.getSearchResults(searchTerm, type, platform), List) } private T convert(Response response, Class type) { - def converter = new JacksonConverter(objectMapper) try { return type.cast(converter.fromBody(response.body, type)) } catch (ConversionException ce) { @@ -80,10 +87,10 @@ class OortHelper { // infer the app from the cluster prefix since this is used by quip and we want to be able to quick patch different apps from the same pipeline def app def clusterName - if(expectedAsgName) { + if (expectedAsgName) { app = expectedAsgName.substring(0, expectedAsgName.indexOf("-")) clusterName = expectedAsgName.substring(0, expectedAsgName.lastIndexOf("-")) - } else if(context?.clusterName?.indexOf("-") > 0) { + } else if (context?.clusterName?.indexOf("-") > 0) { app = context.clusterName.substring(0, context.clusterName.indexOf("-")) clusterName = context.clusterName } else { @@ -101,7 +108,7 @@ class OortHelper { def region = context.region ?: context.source.region - if(!region) { + if (!region) { throw new RuntimeException("unable to determine region") } @@ -111,24 +118,24 @@ class OortHelper { def searchAsg if (expectOneAsg) { - if(asgsForCluster.size() != 1) { + if (asgsForCluster.size() != 1) { throw new RuntimeException("there is more than one server group in the cluster : ${clusterName}:${region}") } searchAsg = asgsForCluster.get(0) - } else if(expectedAsgName) { + } else if (expectedAsgName) { searchAsg = asgsForCluster.findResult { - if(it.name == expectedAsgName) { - return it + if (it.name == expectedAsgName) { + return it } } - if(!searchAsg) { + if (!searchAsg) { throw new RuntimeException("did not find the expected asg name : ${expectedAsgName}") } } searchAsg.instances.each { instance -> String hostName = instance.publicDnsName - if(!hostName || hostName.isEmpty()) { // some instances dont have a public address, fall back to the private ip + if (!hostName || hostName.isEmpty()) { // some instances dont have a public address, fall back to the private ip hostName = instance.privateIpAddress } @@ -146,14 +153,14 @@ class OortHelper { } }?.status - if(failIfAnyInstancesUnhealthy && (!healthCheckUrl || !status || status != "UP")) { + if (failIfAnyInstancesUnhealthy && (!healthCheckUrl || !status || status != "UP")) { throw new RuntimeException("at least one instance is DOWN or in the STARTING state, exiting") } Map instanceInfo = [ - hostName : hostName, - healthCheckUrl : healthCheckUrl, - privateIpAddress: instance.privateIpAddress + hostName: hostName, + healthCheckUrl: healthCheckUrl, + privateIpAddress: instance.privateIpAddress ] instanceMap.put(instance.instanceId, instanceInfo) } diff --git a/orca-clouddriver/src/main/groovy/com/netflix/spinnaker/orca/kato/tasks/rollingpush/DetermineTerminationCandidatesTask.groovy b/orca-clouddriver/src/main/groovy/com/netflix/spinnaker/orca/kato/tasks/rollingpush/DetermineTerminationCandidatesTask.groovy index e57dc3570d..111f985e3b 100644 --- a/orca-clouddriver/src/main/groovy/com/netflix/spinnaker/orca/kato/tasks/rollingpush/DetermineTerminationCandidatesTask.groovy +++ b/orca-clouddriver/src/main/groovy/com/netflix/spinnaker/orca/kato/tasks/rollingpush/DetermineTerminationCandidatesTask.groovy @@ -16,12 +16,12 @@ package com.netflix.spinnaker.orca.kato.tasks.rollingpush -import com.fasterxml.jackson.databind.ObjectMapper -import com.netflix.spinnaker.orca.api.pipeline.models.ExecutionStatus + import com.netflix.spinnaker.orca.api.pipeline.Task -import com.netflix.spinnaker.orca.api.pipeline.models.StageExecution import com.netflix.spinnaker.orca.api.pipeline.TaskResult -import com.netflix.spinnaker.orca.clouddriver.OortService +import com.netflix.spinnaker.orca.api.pipeline.models.ExecutionStatus +import com.netflix.spinnaker.orca.api.pipeline.models.StageExecution +import com.netflix.spinnaker.orca.clouddriver.CloudDriverService import com.netflix.spinnaker.orca.kato.pipeline.support.StageData import org.springframework.beans.factory.annotation.Autowired import org.springframework.stereotype.Component @@ -32,9 +32,7 @@ import javax.annotation.Nonnull class DetermineTerminationCandidatesTask implements Task { @Autowired - OortService oortService - @Autowired - ObjectMapper objectMapper + CloudDriverService cloudDriverService @Autowired(required = false) List serverGroupInstanceIdCollectors = [] @@ -42,8 +40,7 @@ class DetermineTerminationCandidatesTask implements Task { @Override TaskResult execute(@Nonnull StageExecution stage) { def stageData = stage.mapTo(StageData) - def response = oortService.getServerGroupFromCluster(stageData.application, stageData.account, stageData.cluster, stage.context.asgName, stage.context.region, stage.context.cloudProvider ?: 'aws') - def serverGroup = objectMapper.readValue(response.body.in(), Map) + def serverGroup = cloudDriverService.getServerGroupFromCluster(stageData.application, stageData.account, stageData.cluster, stage.context.asgName, stage.context.region, stage.context.cloudProvider ?: 'aws') boolean ascending = stage.context.termination?.order != 'newest' def serverGroupInstances = serverGroup.instances.sort { ascending ? it.launchTime : -it.launchTime } // need to use id instead of instanceIds for titus as the titus API doesn't yet support this yet. diff --git a/orca-clouddriver/src/main/groovy/com/netflix/spinnaker/orca/kato/tasks/rollingpush/WaitForNewUpInstancesLaunchTask.groovy b/orca-clouddriver/src/main/groovy/com/netflix/spinnaker/orca/kato/tasks/rollingpush/WaitForNewUpInstancesLaunchTask.groovy index ae05a77803..345f7f06bb 100644 --- a/orca-clouddriver/src/main/groovy/com/netflix/spinnaker/orca/kato/tasks/rollingpush/WaitForNewUpInstancesLaunchTask.groovy +++ b/orca-clouddriver/src/main/groovy/com/netflix/spinnaker/orca/kato/tasks/rollingpush/WaitForNewUpInstancesLaunchTask.groovy @@ -18,13 +18,12 @@ package com.netflix.spinnaker.orca.kato.tasks.rollingpush import com.netflix.spinnaker.orca.api.pipeline.OverridableTimeoutRetryableTask import com.netflix.spinnaker.orca.api.pipeline.models.StageExecution +import com.netflix.spinnaker.orca.clouddriver.CloudDriverService import com.netflix.spinnaker.orca.clouddriver.utils.HealthHelper import java.util.concurrent.TimeUnit -import com.fasterxml.jackson.databind.ObjectMapper import com.netflix.spinnaker.orca.api.pipeline.models.ExecutionStatus import com.netflix.spinnaker.orca.api.pipeline.TaskResult -import com.netflix.spinnaker.orca.clouddriver.OortService import com.netflix.spinnaker.orca.kato.pipeline.support.StageData import org.springframework.beans.factory.annotation.Autowired import org.springframework.stereotype.Component @@ -32,8 +31,7 @@ import org.springframework.stereotype.Component @Component class WaitForNewUpInstancesLaunchTask implements OverridableTimeoutRetryableTask { - @Autowired OortService oortService - @Autowired ObjectMapper objectMapper + @Autowired CloudDriverService cloudDriverService @Autowired(required = false) List serverGroupInstanceIdCollectors = [] long getBackoffPeriod() { TimeUnit.SECONDS.toMillis(10) } @@ -45,14 +43,12 @@ class WaitForNewUpInstancesLaunchTask implements OverridableTimeoutRetryableTask StageData stageData = stage.mapTo(StageData) // similar check in `AbstractInstancesCheckTask` - def response = oortService.getServerGroup( + Map serverGroup = cloudDriverService.getServerGroup( stageData.account, stage.context.region as String, stage.context.asgName as String ) - Map serverGroup = objectMapper.readValue(response.body.in(), Map) - List serverGroupInstances = serverGroup.instances as List Set knownInstanceIds = new HashSet(stage.context.knownInstanceIds as List) diff --git a/orca-clouddriver/src/main/java/com/netflix/spinnaker/orca/clouddriver/CloudDriverService.java b/orca-clouddriver/src/main/java/com/netflix/spinnaker/orca/clouddriver/CloudDriverService.java new file mode 100644 index 0000000000..5a00df77fc --- /dev/null +++ b/orca-clouddriver/src/main/java/com/netflix/spinnaker/orca/clouddriver/CloudDriverService.java @@ -0,0 +1,94 @@ +package com.netflix.spinnaker.orca.clouddriver; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.netflix.spinnaker.orca.clouddriver.model.EntityTags; +import com.netflix.spinnaker.orca.clouddriver.model.ServerGroup; +import java.util.List; +import java.util.Map; +import lombok.SneakyThrows; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import retrofit.client.Response; + +@Component +public class CloudDriverService { + + private static final TypeReference> SERVER_GROUPS = new TypeReference<>() {}; + private static final TypeReference> JSON_MAP = new TypeReference<>() {}; + private static final TypeReference> ENTITY_TAGS = new TypeReference<>() {}; + + private final OortService oortService; + + private final ObjectMapper objectMapper; + + @Autowired + public CloudDriverService(OortService oortService, ObjectMapper objectMapper) { + this.oortService = oortService; + this.objectMapper = objectMapper; + } + + public Map getApplication(String application) { + Response response = oortService.getApplication(application); + return readBody(response, JSON_MAP); + } + + public List getServerGroups(String application) { + Response response = oortService.getServerGroups(application); + return readBody(response, SERVER_GROUPS); + } + + public Map getServerGroup(String account, String region, String serverGroup) { + Response response = oortService.getServerGroup(account, region, serverGroup); + return readBody(response, JSON_MAP); + } + + public ServerGroup getServerGroupTyped(String account, String region, String serverGroup) { + Response response = oortService.getServerGroup(account, region, serverGroup); + return readBody(response, ServerGroup.class); + } + + public Map getServerGroupFromCluster( + String app, + String account, + String cluster, + String serverGroup, + String region, + String cloudProvider) { + Response response = + oortService.getServerGroupFromCluster( + app, account, cluster, serverGroup, region, cloudProvider); + return readBody(response, JSON_MAP); + } + + public List> getEntityTags( + String cloudProvider, String entityType, String entityId, String account, String region) { + return oortService.getEntityTags(cloudProvider, entityType, entityId, account, region); + } + + public List getEntityTagsTyped(Map parameters) { + List response = oortService.getEntityTags(parameters); + return objectMapper.convertValue(response, ENTITY_TAGS); + } + + public List> getByAmiId( + String type, String account, String region, Object imageId) { + return oortService.getByAmiId(type, account, region, imageId); + } + + public Map getCluster( + String app, String account, String cluster, String cloudProvider) { + Response response = oortService.getCluster(app, account, cluster, cloudProvider); + return readBody(response, JSON_MAP); + } + + @SneakyThrows // code may have depended on the exceptions thrown that groovy was hiding + private T readBody(Response response, Class type) { + return objectMapper.readValue(response.getBody().in(), type); + } + + @SneakyThrows // code may have depended on the exceptions thrown that groovy was hiding + private T readBody(Response response, TypeReference valueTypeRef) { + return objectMapper.readValue(response.getBody().in(), valueTypeRef); + } +} diff --git a/orca-clouddriver/src/main/java/com/netflix/spinnaker/orca/clouddriver/DelegatingOortService.java b/orca-clouddriver/src/main/java/com/netflix/spinnaker/orca/clouddriver/DelegatingOortService.java index 61df9672f1..985465b84c 100644 --- a/orca-clouddriver/src/main/java/com/netflix/spinnaker/orca/clouddriver/DelegatingOortService.java +++ b/orca-clouddriver/src/main/java/com/netflix/spinnaker/orca/clouddriver/DelegatingOortService.java @@ -142,7 +142,8 @@ public List getLoadBalancerDetails( } @Override - public List getByAmiId(String type, String account, String region, Object imageId) { + public List> getByAmiId( + String type, String account, String region, Object imageId) { return getService().getByAmiId(type, account, region, imageId); } @@ -153,7 +154,7 @@ public List findImage( } @Override - public List getEntityTags( + public List> getEntityTags( String cloudProvider, String entityType, String entityId, String account, String region) { return getService().getEntityTags(cloudProvider, entityType, entityId, account, region); } diff --git a/orca-clouddriver/src/main/java/com/netflix/spinnaker/orca/clouddriver/pollers/EntityTags.java b/orca-clouddriver/src/main/java/com/netflix/spinnaker/orca/clouddriver/model/EntityTags.java similarity index 86% rename from orca-clouddriver/src/main/java/com/netflix/spinnaker/orca/clouddriver/pollers/EntityTags.java rename to orca-clouddriver/src/main/java/com/netflix/spinnaker/orca/clouddriver/model/EntityTags.java index 5fcce2503c..083adc0093 100644 --- a/orca-clouddriver/src/main/java/com/netflix/spinnaker/orca/clouddriver/pollers/EntityTags.java +++ b/orca-clouddriver/src/main/java/com/netflix/spinnaker/orca/clouddriver/model/EntityTags.java @@ -14,22 +14,22 @@ * limitations under the License. */ -package com.netflix.spinnaker.orca.clouddriver.pollers; +package com.netflix.spinnaker.orca.clouddriver.model; import java.util.List; -class EntityTags { +public class EntityTags { public String id; public List tags; public EntityRef entityRef; - static class Tag { + public static class Tag { public String name; public Object value; } - static class EntityRef { + public static class EntityRef { public String cloudProvider; public String application; public String account; diff --git a/orca-clouddriver/src/main/java/com/netflix/spinnaker/orca/clouddriver/model/ServerGroup.java b/orca-clouddriver/src/main/java/com/netflix/spinnaker/orca/clouddriver/model/ServerGroup.java new file mode 100644 index 0000000000..eb60bdc978 --- /dev/null +++ b/orca-clouddriver/src/main/java/com/netflix/spinnaker/orca/clouddriver/model/ServerGroup.java @@ -0,0 +1,29 @@ +package com.netflix.spinnaker.orca.clouddriver.model; + +import lombok.Data; + +@Data +public class ServerGroup { + public String name; + public String account; + public String region; + public String cluster; + public String cloudProvider; + + public Moniker moniker; + public Long createdTime; + + public Capacity capacity; + + @Data + public static class Moniker { + public String app; + } + + @Data + public static class Capacity { + public Integer min; + public Integer desired; + public Integer max; + } +} diff --git a/orca-clouddriver/src/main/java/com/netflix/spinnaker/orca/clouddriver/pipeline/servergroup/rollback/PreviousImageRollbackSupport.java b/orca-clouddriver/src/main/java/com/netflix/spinnaker/orca/clouddriver/pipeline/servergroup/rollback/PreviousImageRollbackSupport.java index 15ed5bf225..4c20c8e7c9 100644 --- a/orca-clouddriver/src/main/java/com/netflix/spinnaker/orca/clouddriver/pipeline/servergroup/rollback/PreviousImageRollbackSupport.java +++ b/orca-clouddriver/src/main/java/com/netflix/spinnaker/orca/clouddriver/pipeline/servergroup/rollback/PreviousImageRollbackSupport.java @@ -50,7 +50,7 @@ public PreviousImageRollbackSupport( public ImageDetails getImageDetailsFromEntityTags( String cloudProvider, String credentials, String region, String serverGroupName) { - List entityTags = null; + List> entityTags = null; try { entityTags = diff --git a/orca-clouddriver/src/main/java/com/netflix/spinnaker/orca/clouddriver/pollers/EphemeralServerGroupsPoller.java b/orca-clouddriver/src/main/java/com/netflix/spinnaker/orca/clouddriver/pollers/EphemeralServerGroupsPoller.java index 1437a8534d..e02b29dae7 100644 --- a/orca-clouddriver/src/main/java/com/netflix/spinnaker/orca/clouddriver/pollers/EphemeralServerGroupsPoller.java +++ b/orca-clouddriver/src/main/java/com/netflix/spinnaker/orca/clouddriver/pollers/EphemeralServerGroupsPoller.java @@ -19,7 +19,6 @@ import static com.netflix.spinnaker.orca.clouddriver.tasks.servergroup.EphemeralServerGroupEntityTagGenerator.TTL_TAG; import static java.lang.String.format; -import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.collect.ImmutableMap; import com.netflix.spectator.api.Counter; @@ -28,8 +27,10 @@ import com.netflix.spinnaker.kork.core.RetrySupport; import com.netflix.spinnaker.kork.exceptions.SystemException; import com.netflix.spinnaker.orca.api.pipeline.models.ExecutionType; -import com.netflix.spinnaker.orca.clouddriver.OortService; +import com.netflix.spinnaker.orca.clouddriver.CloudDriverService; import com.netflix.spinnaker.orca.clouddriver.config.PollerConfigurationProperties; +import com.netflix.spinnaker.orca.clouddriver.model.EntityTags; +import com.netflix.spinnaker.orca.clouddriver.model.ServerGroup; import com.netflix.spinnaker.orca.front50.Front50Service; import com.netflix.spinnaker.orca.front50.model.Application; import com.netflix.spinnaker.orca.notifications.AbstractPollingNotificationAgent; @@ -57,7 +58,7 @@ public class EphemeralServerGroupsPoller extends AbstractPollingNotificationAgen private static final Logger log = LoggerFactory.getLogger(EphemeralServerGroupsPoller.class); private final ObjectMapper objectMapper; - private final OortService oortService; + private final CloudDriverService cloudDriverService; private final RetrySupport retrySupport; private final Registry registry; private final ExecutionLauncher executionLauncher; @@ -73,7 +74,7 @@ public class EphemeralServerGroupsPoller extends AbstractPollingNotificationAgen public EphemeralServerGroupsPoller( NotificationClusterLock notificationClusterLock, ObjectMapper objectMapper, - OortService oortService, + CloudDriverService cloudDriverService, RetrySupport retrySupport, Registry registry, ExecutionLauncher executionLauncher, @@ -82,14 +83,14 @@ public EphemeralServerGroupsPoller( super(notificationClusterLock); this.objectMapper = objectMapper; - this.oortService = oortService; + this.cloudDriverService = cloudDriverService; this.retrySupport = retrySupport; this.registry = registry; this.executionLauncher = executionLauncher; this.front50Service = front50Service; this.pollerConfigurationProperties = pollerConfigurationProperties; - this.pollerSupport = new PollerSupport(objectMapper, retrySupport, oortService); + this.pollerSupport = new PollerSupport(retrySupport, cloudDriverService); this.triggeredCounterId = registry.createId("poller.ephemeralServerGroups.triggered"); this.errorsCounter = registry.counter("poller.ephemeralServerGroups.errors"); @@ -114,8 +115,18 @@ protected String getNotificationType() { protected void tick() { log.info("Checking for ephemeral server groups"); - List ephemeralServerGroupTags = fetchEphemeralServerGroupTags(); - log.info("Found {} ephemeral server groups", ephemeralServerGroupTags.size()); + List ephemeralServerGroupTags = new ArrayList<>(); + + try { + ephemeralServerGroupTags.addAll(fetchEphemeralServerGroupTags()); + log.info( + "Found {} ephemeral server groups: {}", + ephemeralServerGroupTags.size(), + ephemeralServerGroupTags); + } catch (Exception e) { + log.error("Unable to fetch ephemeral server groups", e); + errorsCounter.increment(); + } if (ephemeralServerGroupTags.isEmpty()) { return; @@ -194,13 +205,8 @@ private List fetchEphemeralServerGroupTags() { () -> retrySupport.retry( () -> - objectMapper.convertValue( - oortService.getEntityTags( - ImmutableMap.builder() - .put("tag:" + TTL_TAG, "*") - .put("entityType", "servergroup") - .build()), - new TypeReference>() {}), + cloudDriverService.getEntityTagsTyped( + Map.of("tag:" + TTL_TAG, "*", "entityType", "servergroup")), 15, 2000, false)); diff --git a/orca-clouddriver/src/main/java/com/netflix/spinnaker/orca/clouddriver/pollers/PollerSupport.java b/orca-clouddriver/src/main/java/com/netflix/spinnaker/orca/clouddriver/pollers/PollerSupport.java index 9bdf8912ce..042a2dad57 100644 --- a/orca-clouddriver/src/main/java/com/netflix/spinnaker/orca/clouddriver/pollers/PollerSupport.java +++ b/orca-clouddriver/src/main/java/com/netflix/spinnaker/orca/clouddriver/pollers/PollerSupport.java @@ -18,31 +18,27 @@ import static java.lang.String.format; -import com.fasterxml.jackson.databind.ObjectMapper; import com.netflix.spinnaker.kork.core.RetrySupport; -import com.netflix.spinnaker.orca.clouddriver.OortService; +import com.netflix.spinnaker.orca.clouddriver.CloudDriverService; +import com.netflix.spinnaker.orca.clouddriver.model.ServerGroup; import java.util.Optional; import retrofit.RetrofitError; -import retrofit.client.Response; public class PollerSupport { - private final ObjectMapper objectMapper; private final RetrySupport retrySupport; - private final OortService oortService; + private final CloudDriverService cloudDriverService; - public PollerSupport( - ObjectMapper objectMapper, RetrySupport retrySupport, OortService oortService) { - this.objectMapper = objectMapper; + public PollerSupport(RetrySupport retrySupport, CloudDriverService cloudDriverService) { this.retrySupport = retrySupport; - this.oortService = oortService; + this.cloudDriverService = cloudDriverService; } public Optional fetchServerGroup(String account, String region, String name) { return retrySupport.retry( () -> { try { - Response response = oortService.getServerGroup(account, region, name); - return Optional.of(objectMapper.readValue(response.getBody().in(), ServerGroup.class)); + ServerGroup response = cloudDriverService.getServerGroupTyped(account, region, name); + return Optional.of(response); } catch (Exception e) { if (e instanceof RetrofitError) { RetrofitError re = (RetrofitError) e; diff --git a/orca-clouddriver/src/main/java/com/netflix/spinnaker/orca/clouddriver/pollers/RestorePinnedServerGroupsPoller.java b/orca-clouddriver/src/main/java/com/netflix/spinnaker/orca/clouddriver/pollers/RestorePinnedServerGroupsPoller.java index 2e5ab889b8..2f232350bb 100644 --- a/orca-clouddriver/src/main/java/com/netflix/spinnaker/orca/clouddriver/pollers/RestorePinnedServerGroupsPoller.java +++ b/orca-clouddriver/src/main/java/com/netflix/spinnaker/orca/clouddriver/pollers/RestorePinnedServerGroupsPoller.java @@ -19,7 +19,6 @@ import static com.netflix.spinnaker.orca.clouddriver.tasks.servergroup.PinnedServerGroupTagGenerator.PINNED_CAPACITY_TAG; import static java.lang.String.format; -import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableMap; @@ -28,7 +27,9 @@ import com.netflix.spinnaker.kork.core.RetrySupport; import com.netflix.spinnaker.orca.api.pipeline.models.ExecutionType; import com.netflix.spinnaker.orca.api.pipeline.models.PipelineExecution; -import com.netflix.spinnaker.orca.clouddriver.OortService; +import com.netflix.spinnaker.orca.clouddriver.CloudDriverService; +import com.netflix.spinnaker.orca.clouddriver.model.EntityTags; +import com.netflix.spinnaker.orca.clouddriver.model.ServerGroup; import com.netflix.spinnaker.orca.notifications.AbstractPollingNotificationAgent; import com.netflix.spinnaker.orca.notifications.NotificationClusterLock; import com.netflix.spinnaker.orca.pipeline.ExecutionLauncher; @@ -51,7 +52,7 @@ public class RestorePinnedServerGroupsPoller extends AbstractPollingNotification private static final Logger log = LoggerFactory.getLogger(RestorePinnedServerGroupsPoller.class); private final ObjectMapper objectMapper; - private final OortService oortService; + private final CloudDriverService cloudDriverService; private final RetrySupport retrySupport; private final ExecutionLauncher executionLauncher; private final ExecutionRepository executionRepository; @@ -67,7 +68,7 @@ public class RestorePinnedServerGroupsPoller extends AbstractPollingNotification public RestorePinnedServerGroupsPoller( NotificationClusterLock notificationClusterLock, ObjectMapper objectMapper, - OortService oortService, + CloudDriverService cloudDriverService, RetrySupport retrySupport, Registry registry, ExecutionLauncher executionLauncher, @@ -76,20 +77,20 @@ public RestorePinnedServerGroupsPoller( this( notificationClusterLock, objectMapper, - oortService, + cloudDriverService, retrySupport, registry, executionLauncher, executionRepository, username, - new PollerSupport(objectMapper, retrySupport, oortService)); + new PollerSupport(retrySupport, cloudDriverService)); } @VisibleForTesting public RestorePinnedServerGroupsPoller( NotificationClusterLock notificationClusterLock, ObjectMapper objectMapper, - OortService oortService, + CloudDriverService cloudDriverService, RetrySupport retrySupport, Registry registry, ExecutionLauncher executionLauncher, @@ -99,7 +100,7 @@ public RestorePinnedServerGroupsPoller( super(notificationClusterLock); this.objectMapper = objectMapper; - this.oortService = oortService; + this.cloudDriverService = cloudDriverService; this.retrySupport = retrySupport; this.executionLauncher = executionLauncher; this.executionRepository = executionRepository; @@ -202,13 +203,8 @@ public List fetchPinnedServerGroupTags() { () -> retrySupport.retry( () -> - objectMapper.convertValue( - oortService.getEntityTags( - ImmutableMap.builder() - .put("tag:" + PINNED_CAPACITY_TAG, "*") - .put("entityType", "servergroup") - .build()), - new TypeReference>() {}), + cloudDriverService.getEntityTagsTyped( + Map.of("tag:" + PINNED_CAPACITY_TAG, "*", "entityType", "servergroup")), 15, 2000, false)); diff --git a/orca-clouddriver/src/main/java/com/netflix/spinnaker/orca/clouddriver/pollers/ServerGroup.java b/orca-clouddriver/src/main/java/com/netflix/spinnaker/orca/clouddriver/pollers/ServerGroup.java deleted file mode 100644 index 5390227a52..0000000000 --- a/orca-clouddriver/src/main/java/com/netflix/spinnaker/orca/clouddriver/pollers/ServerGroup.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2018 Netflix, 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.orca.clouddriver.pollers; - -class ServerGroup { - public Moniker moniker; - public Long createdTime; - - public Capacity capacity; - - static class Moniker { - public String app; - } - - static class Capacity { - public Integer min; - public Integer desired; - public Integer max; - } -} diff --git a/orca-clouddriver/src/main/java/com/netflix/spinnaker/orca/clouddriver/tasks/image/MonitorDeleteImageTask.java b/orca-clouddriver/src/main/java/com/netflix/spinnaker/orca/clouddriver/tasks/image/MonitorDeleteImageTask.java index 5ebdf3a905..bd911b7923 100644 --- a/orca-clouddriver/src/main/java/com/netflix/spinnaker/orca/clouddriver/tasks/image/MonitorDeleteImageTask.java +++ b/orca-clouddriver/src/main/java/com/netflix/spinnaker/orca/clouddriver/tasks/image/MonitorDeleteImageTask.java @@ -20,7 +20,7 @@ import com.netflix.spinnaker.orca.api.pipeline.TaskResult; import com.netflix.spinnaker.orca.api.pipeline.models.ExecutionStatus; import com.netflix.spinnaker.orca.api.pipeline.models.StageExecution; -import com.netflix.spinnaker.orca.clouddriver.OortService; +import com.netflix.spinnaker.orca.clouddriver.CloudDriverService; import com.netflix.spinnaker.orca.clouddriver.pipeline.image.DeleteImageStage; import com.netflix.spinnaker.orca.clouddriver.tasks.AbstractCloudProviderAwareTask; import com.netflix.spinnaker.orca.retrofit.exceptions.RetrofitExceptionHandler; @@ -38,11 +38,11 @@ public class MonitorDeleteImageTask extends AbstractCloudProviderAwareTask implements OverridableTimeoutRetryableTask { private static final Logger log = LoggerFactory.getLogger(MonitorDeleteImageTask.class); - private final OortService oortService; + private final CloudDriverService cloudDriverService; @Autowired - public MonitorDeleteImageTask(OortService oortService) { - this.oortService = oortService; + public MonitorDeleteImageTask(CloudDriverService cloudDriverService) { + this.cloudDriverService = cloudDriverService; } @Override @@ -60,7 +60,7 @@ public TaskResult execute(@Nonnull StageExecution stage) { .forEach( imageId -> { try { - oortService.getByAmiId( + cloudDriverService.getByAmiId( deleteImageRequest.getCloudProvider(), deleteImageRequest.getCredentials(), deleteImageRequest.getRegion(), diff --git a/orca-clouddriver/src/main/java/com/netflix/spinnaker/orca/kato/tasks/rollingpush/CleanUpTagsTask.java b/orca-clouddriver/src/main/java/com/netflix/spinnaker/orca/kato/tasks/rollingpush/CleanUpTagsTask.java index 9bc9f2637f..cf458d4ead 100644 --- a/orca-clouddriver/src/main/java/com/netflix/spinnaker/orca/kato/tasks/rollingpush/CleanUpTagsTask.java +++ b/orca-clouddriver/src/main/java/com/netflix/spinnaker/orca/kato/tasks/rollingpush/CleanUpTagsTask.java @@ -18,12 +18,11 @@ import static com.netflix.spinnaker.orca.api.pipeline.models.ExecutionStatus.SUCCEEDED; -import com.fasterxml.jackson.databind.ObjectMapper; import com.netflix.spinnaker.orca.api.pipeline.RetryableTask; import com.netflix.spinnaker.orca.api.pipeline.TaskResult; import com.netflix.spinnaker.orca.api.pipeline.models.StageExecution; +import com.netflix.spinnaker.orca.clouddriver.CloudDriverService; import com.netflix.spinnaker.orca.clouddriver.KatoService; -import com.netflix.spinnaker.orca.clouddriver.OortService; import com.netflix.spinnaker.orca.clouddriver.model.TaskId; import com.netflix.spinnaker.orca.clouddriver.tasks.AbstractCloudProviderAwareTask; import com.netflix.spinnaker.orca.clouddriver.utils.MonikerHelper; @@ -37,7 +36,6 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import retrofit.client.Response; @Component public class CleanUpTagsTask extends AbstractCloudProviderAwareTask implements RetryableTask { @@ -46,12 +44,10 @@ public class CleanUpTagsTask extends AbstractCloudProviderAwareTask implements R @Autowired KatoService katoService; - @Autowired OortService oortService; + @Autowired CloudDriverService cloudDriverService; @Autowired SourceResolver sourceResolver; - @Autowired ObjectMapper objectMapper; - @Autowired MonikerHelper monikerHelper; @Override @@ -62,8 +58,8 @@ public TaskResult execute(StageExecution stage) { Optional.ofNullable(source.getServerGroupName()).orElse(source.getAsgName()); String cloudProvider = getCloudProvider(stage); - Response serverGroupResponse = - oortService.getServerGroupFromCluster( + Map serverGroup = + cloudDriverService.getServerGroupFromCluster( monikerHelper.getAppNameFromStage(stage, serverGroupName), source.getAccount(), monikerHelper.getClusterNameFromStage(stage, serverGroupName), @@ -71,11 +67,10 @@ public TaskResult execute(StageExecution stage) { source.getRegion(), cloudProvider); - Map serverGroup = objectMapper.readValue(serverGroupResponse.getBody().in(), Map.class); String imageId = (String) ((Map) serverGroup.get("launchConfig")).get("imageId"); - List tags = - oortService.getEntityTags( + List> tags = + cloudDriverService.getEntityTags( cloudProvider, "servergroup", serverGroupName, diff --git a/orca-clouddriver/src/test/groovy/com/netflix/spinnaker/orca/clouddriver/pollers/RestorePinnedServerGroupsPollerSpec.groovy b/orca-clouddriver/src/test/groovy/com/netflix/spinnaker/orca/clouddriver/pollers/RestorePinnedServerGroupsPollerSpec.groovy index 7a3859407e..2e3a470330 100644 --- a/orca-clouddriver/src/test/groovy/com/netflix/spinnaker/orca/clouddriver/pollers/RestorePinnedServerGroupsPollerSpec.groovy +++ b/orca-clouddriver/src/test/groovy/com/netflix/spinnaker/orca/clouddriver/pollers/RestorePinnedServerGroupsPollerSpec.groovy @@ -22,7 +22,8 @@ import com.netflix.spectator.api.Id import com.netflix.spectator.api.Registry import com.netflix.spinnaker.kork.core.RetrySupport import com.netflix.spinnaker.orca.api.pipeline.models.ExecutionType -import com.netflix.spinnaker.orca.clouddriver.OortService +import com.netflix.spinnaker.orca.clouddriver.CloudDriverService +import com.netflix.spinnaker.orca.clouddriver.model.ServerGroup import com.netflix.spinnaker.orca.notifications.NotificationClusterLock import com.netflix.spinnaker.orca.pipeline.ExecutionLauncher import com.netflix.spinnaker.orca.pipeline.persistence.ExecutionRepository @@ -34,7 +35,7 @@ class RestorePinnedServerGroupsPollerSpec extends Specification { tryAcquireLock(_, _) >> true } def objectMapper = new ObjectMapper() - def oortService = Mock(OortService) + CloudDriverService cloudDriverService = Mock() def executionLauncher = Mock(ExecutionLauncher) def executionRepository = Mock(ExecutionRepository) def pollerSupport = Mock(PollerSupport) @@ -84,7 +85,7 @@ class RestorePinnedServerGroupsPollerSpec extends Specification { constructorArgs: [ notificationClusterLock, objectMapper, - oortService, + cloudDriverService, retrySupport, registry, executionLauncher, diff --git a/orca-clouddriver/src/test/groovy/com/netflix/spinnaker/orca/clouddriver/tasks/cluster/WaitForClusterShrinkTaskSpec.groovy b/orca-clouddriver/src/test/groovy/com/netflix/spinnaker/orca/clouddriver/tasks/cluster/WaitForClusterShrinkTaskSpec.groovy index a611dd9b13..22a25f6dcb 100644 --- a/orca-clouddriver/src/test/groovy/com/netflix/spinnaker/orca/clouddriver/tasks/cluster/WaitForClusterShrinkTaskSpec.groovy +++ b/orca-clouddriver/src/test/groovy/com/netflix/spinnaker/orca/clouddriver/tasks/cluster/WaitForClusterShrinkTaskSpec.groovy @@ -34,7 +34,7 @@ class WaitForClusterShrinkTaskSpec extends Specification { def oortService = Mock(OortService) def objectMapper = new ObjectMapper() @Subject def task = new WaitForClusterShrinkTask( - oortHelper: new OortHelper(oortService: oortService, objectMapper: objectMapper) + oortHelper: new OortHelper(oortService, objectMapper) ) def "does not complete if previous ASG is still there"() { diff --git a/orca-clouddriver/src/test/groovy/com/netflix/spinnaker/orca/clouddriver/tasks/instance/AbstractInstancesCheckTaskSpec.groovy b/orca-clouddriver/src/test/groovy/com/netflix/spinnaker/orca/clouddriver/tasks/instance/AbstractInstancesCheckTaskSpec.groovy index d7c89c5200..354f5e4063 100644 --- a/orca-clouddriver/src/test/groovy/com/netflix/spinnaker/orca/clouddriver/tasks/instance/AbstractInstancesCheckTaskSpec.groovy +++ b/orca-clouddriver/src/test/groovy/com/netflix/spinnaker/orca/clouddriver/tasks/instance/AbstractInstancesCheckTaskSpec.groovy @@ -19,6 +19,7 @@ package com.netflix.spinnaker.orca.clouddriver.tasks.instance import com.fasterxml.jackson.databind.ObjectMapper import com.netflix.spinnaker.moniker.Moniker import com.netflix.spinnaker.orca.api.pipeline.models.StageExecution +import com.netflix.spinnaker.orca.clouddriver.CloudDriverService import com.netflix.spinnaker.orca.clouddriver.OortService import com.netflix.spinnaker.orca.jackson.OrcaObjectMapper import com.netflix.spinnaker.orca.pipeline.model.PipelineExecutionImpl @@ -60,7 +61,7 @@ class AbstractInstancesCheckTaskSpec extends Specification { } } - @Subject task = new TestInstancesCheckTask(oortService: Mock(OortService), objectMapper: new ObjectMapper()) + @Subject task = new TestInstancesCheckTask(cloudDriverService: Mock(CloudDriverService)) Closure constructResponse = { int status, String body -> new Response("", status, "", [], new TypedInput() { @@ -82,8 +83,7 @@ class AbstractInstancesCheckTaskSpec extends Specification { } void "should be provided with health provider names"() { - task.oortService = Mock(OortService) - task.objectMapper = OrcaObjectMapper.newInstance() + task.cloudDriverService = Mock(CloudDriverService) task.hasSucceededSpy = Mock(HasSucceededSpy) def pipeline = PipelineExecutionImpl.newPipeline("orca") @@ -98,23 +98,22 @@ class AbstractInstancesCheckTaskSpec extends Specification { task.execute(stage) then: - 1 * task.oortService.getServerGroup("test", "us-west-1", "front50-v000") >> constructResponse(200, ''' -{ + 1 * task.cloudDriverService.getServerGroup("test", "us-west-1", "front50-v000") >> +[ "name": "front50-v000", "region": "us-west-1", - "asg": { + "asg": [ "minSize": 1 - }, - "capacity": { + ], + "capacity": [ "min": 1 - }, + ], "instances": [ - { + [ "name": "i-12345678" - } + ] ] -} -''') +] and: 1 * task.hasSucceededSpy.hasSucceeded(_, [['name': 'i-12345678']], ['JustTrustMeBroItIsHealthy']) @@ -122,8 +121,7 @@ class AbstractInstancesCheckTaskSpec extends Specification { @Unroll void 'should reset zeroDesiredCapacityCount when targetDesiredCapacity is not zero, otherwise increment'() { - task.oortService = Mock(OortService) - task.objectMapper = OrcaObjectMapper.newInstance() + task.cloudDriverService = Mock(CloudDriverService) task.hasSucceededSpy = Mock(HasSucceededSpy) def pipeline = PipelineExecutionImpl.newPipeline("orca") @@ -144,25 +142,24 @@ class AbstractInstancesCheckTaskSpec extends Specification { then: result.context.zeroDesiredCapacityCount == expected - 1 * task.oortService.getServerGroup("test", "us-west-1", "front50-v000") >> constructResponse(200, ''' -{ + 1 * task.cloudDriverService.getServerGroup("test", "us-west-1", "front50-v000") >> +[ "name": "front50-v000", "region": "us-west-1", - "asg": { + "asg": [ "minSize": 1, - "desiredCapacity": ''' + desiredCapacity + ''' - }, - "capacity": { + "desiredCapacity": desiredCapacity + ], + "capacity": [ "min": 1, - "desired": ''' + desiredCapacity + ''' - }, + "desired": desiredCapacity + ], "instances": [ - { + [ "name": "i-12345678" - } + ] ] -} -''') +] and: 1 * task.hasSucceededSpy.hasSucceeded(_, _, _) >> false @@ -174,8 +171,7 @@ class AbstractInstancesCheckTaskSpec extends Specification { } void 'should set zeroDesiredCapacityCount when targetDesiredCapacity is zero and no zeroDesiredCapacityCount is not present on context'() { - task.oortService = Mock(OortService) - task.objectMapper = OrcaObjectMapper.newInstance() + task.cloudDriverService = Mock(CloudDriverService) task.hasSucceededSpy = Mock(HasSucceededSpy) def pipeline = PipelineExecutionImpl.newPipeline("orca") @@ -190,25 +186,24 @@ class AbstractInstancesCheckTaskSpec extends Specification { then: result.context.zeroDesiredCapacityCount == 1 - 1 * task.oortService.getServerGroup("test", "us-west-1", "front50-v000") >> constructResponse(200, ''' -{ + 1 * task.cloudDriverService.getServerGroup("test", "us-west-1", "front50-v000") >> +[ "name": "front50-v000", "region": "us-west-1", - "asg": { + "asg": [ "minSize": 1, "desiredCapacity": 0 - }, - "capacity": { + ], + "capacity": [ "min": 1, "desired": 0 - }, + ], "instances": [ - { + [ "name": "i-12345678" - } + ] ] -} -''') +] and: 1 * task.hasSucceededSpy.hasSucceeded(_, _, _) >> false @@ -230,9 +225,9 @@ class AbstractInstancesCheckTaskSpec extends Specification { } then: - 1 * task.oortService.getServerGroup("test", "us-west-2", serverGroupName) >> { + 1 * task.cloudDriverService.getServerGroup("test", "us-west-2", serverGroupName) >> { if (statusCode == 200) { - return new Response("http://clouddriver", statusCode, "OK", [], new TypedString("""{"name": "${serverGroupName}"}""")) + return ["name": serverGroupName] } throw RetrofitError.httpError( diff --git a/orca-clouddriver/src/test/groovy/com/netflix/spinnaker/orca/clouddriver/tasks/instance/WaitForUpInstancesTaskSpec.groovy b/orca-clouddriver/src/test/groovy/com/netflix/spinnaker/orca/clouddriver/tasks/instance/WaitForUpInstancesTaskSpec.groovy index 913d28394e..fcf71e537e 100644 --- a/orca-clouddriver/src/test/groovy/com/netflix/spinnaker/orca/clouddriver/tasks/instance/WaitForUpInstancesTaskSpec.groovy +++ b/orca-clouddriver/src/test/groovy/com/netflix/spinnaker/orca/clouddriver/tasks/instance/WaitForUpInstancesTaskSpec.groovy @@ -17,6 +17,7 @@ package com.netflix.spinnaker.orca.clouddriver.tasks.instance import com.netflix.spinnaker.orca.api.pipeline.models.StageExecution +import com.netflix.spinnaker.orca.clouddriver.CloudDriverService import java.util.concurrent.TimeUnit import com.netflix.spinnaker.orca.api.pipeline.models.ExecutionStatus @@ -50,8 +51,7 @@ class WaitForUpInstancesTaskSpec extends Specification { void "should check cluster to get server groups"() { given: def pipeline = PipelineExecutionImpl.newPipeline("orca") - task.objectMapper = mapper - def response = new Response('oort', 200, 'ok', [], new TypedString(mapper.writeValueAsString([ + def response = [ name : "front50", serverGroups: [ [ @@ -85,8 +85,8 @@ class WaitForUpInstancesTaskSpec extends Specification { ] ] ] - ]))) - def response2 = new Response('oort', 200, 'ok', [], new TypedString(mapper.writeValueAsString([ + ] + def response2 = [ name : "front50", serverGroups: [ [ @@ -105,8 +105,8 @@ class WaitForUpInstancesTaskSpec extends Specification { ] ] ] - ]))) - task.oortService = Stub(OortService) { + ] + task.cloudDriverService = Stub(CloudDriverService) { getCluster(*_) >>> [response, response2] } diff --git a/orca-clouddriver/src/test/groovy/com/netflix/spinnaker/orca/clouddriver/tasks/providers/aws/WaitForAllNetflixAWSInstancesDownTaskSpec.groovy b/orca-clouddriver/src/test/groovy/com/netflix/spinnaker/orca/clouddriver/tasks/providers/aws/WaitForAllNetflixAWSInstancesDownTaskSpec.groovy index c762ea2e07..79bb4c1804 100644 --- a/orca-clouddriver/src/test/groovy/com/netflix/spinnaker/orca/clouddriver/tasks/providers/aws/WaitForAllNetflixAWSInstancesDownTaskSpec.groovy +++ b/orca-clouddriver/src/test/groovy/com/netflix/spinnaker/orca/clouddriver/tasks/providers/aws/WaitForAllNetflixAWSInstancesDownTaskSpec.groovy @@ -17,6 +17,7 @@ package com.netflix.spinnaker.orca.clouddriver.tasks.providers.aws import com.netflix.spinnaker.orca.api.pipeline.models.StageExecution +import com.netflix.spinnaker.orca.clouddriver.CloudDriverService import java.util.concurrent.TimeUnit import com.netflix.spinnaker.orca.api.pipeline.models.ExecutionStatus @@ -50,8 +51,7 @@ class WaitForAllNetflixAWSInstancesDownTaskSpec extends Specification { void "should fetch server group"() { given: def pipeline = PipelineExecutionImpl.newPipeline("orca") - task.objectMapper = mapper - def response = mapper.writeValueAsString([ + def response = [ region : "us-west-1", name : "front50-v000", asg : [ @@ -62,11 +62,11 @@ class WaitForAllNetflixAWSInstancesDownTaskSpec extends Specification { health: [[state: "Down"]] ] ] - ]) + ] - task.oortService = Stub(OortService) { - getServerGroup(*_) >> new Response('oort', 200, 'ok', [], new TypedString(response)) + task.cloudDriverService = Stub(CloudDriverService) { + getServerGroup(*_) >> response } and: diff --git a/orca-clouddriver/src/test/groovy/com/netflix/spinnaker/orca/clouddriver/tasks/servergroup/WaitForCapacityMatchTaskSpec.groovy b/orca-clouddriver/src/test/groovy/com/netflix/spinnaker/orca/clouddriver/tasks/servergroup/WaitForCapacityMatchTaskSpec.groovy index be0a120eb8..f25975bda4 100644 --- a/orca-clouddriver/src/test/groovy/com/netflix/spinnaker/orca/clouddriver/tasks/servergroup/WaitForCapacityMatchTaskSpec.groovy +++ b/orca-clouddriver/src/test/groovy/com/netflix/spinnaker/orca/clouddriver/tasks/servergroup/WaitForCapacityMatchTaskSpec.groovy @@ -16,28 +16,19 @@ package com.netflix.spinnaker.orca.clouddriver.tasks.servergroup -import com.fasterxml.jackson.databind.ObjectMapper import com.netflix.spinnaker.orca.api.pipeline.models.ExecutionStatus import com.netflix.spinnaker.orca.api.pipeline.models.StageExecution -import com.netflix.spinnaker.orca.clouddriver.OortService -import com.netflix.spinnaker.orca.jackson.OrcaObjectMapper +import com.netflix.spinnaker.orca.clouddriver.CloudDriverService import com.netflix.spinnaker.orca.pipeline.model.PipelineExecutionImpl import com.netflix.spinnaker.orca.pipeline.model.StageExecutionImpl -import retrofit.client.Response -import retrofit.mime.TypedString -import spock.lang.Shared import spock.lang.Specification import spock.lang.Subject import spock.lang.Unroll class WaitForCapacityMatchTaskSpec extends Specification { - @Shared OortService oort - @Shared ObjectMapper mapper = OrcaObjectMapper.newInstance() + CloudDriverService cloudDriverService = Mock() @Subject WaitForCapacityMatchTask task = new WaitForCapacityMatchTask() { - { - objectMapper = mapper - } @Override void verifyServerGroupsExist(StageExecution stage) { @@ -47,9 +38,8 @@ class WaitForCapacityMatchTaskSpec extends Specification { void "should properly wait for a scale up operation"() { setup: - oort = Stub(OortService) - oort.getServerGroup("test", "us-east-1", "kato-main-v000") >> { new Response('kato', 200, 'ok', [], new TypedString(mapper.writeValueAsString(serverGroup))) } - task.oortService = oort + task.cloudDriverService = cloudDriverService + cloudDriverService.getServerGroup("test", "us-east-1", "kato-main-v000") >> serverGroup def context = [account: "test", "deploy.server.groups": ["us-east-1": ["kato-main-v000"]]] def stage = new StageExecutionImpl(PipelineExecutionImpl.newOrchestration("orca"), "resizeServerGroup", context) @@ -87,7 +77,6 @@ class WaitForCapacityMatchTaskSpec extends Specification { @Unroll void "should return status #status for a scale up operation when server group is not disabled and instance health is #healthState"() { setup: - oort = Stub(OortService) def serverGroup = [ name: "kato-main-v000", region: "us-east-1", @@ -104,8 +93,8 @@ class WaitForCapacityMatchTaskSpec extends Specification { ] ] - oort.getServerGroup("test", "us-east-1", "kato-main-v000") >> { new Response('kato', 200, 'ok', [], new TypedString(mapper.writeValueAsString(serverGroup))) } - task.oortService = oort + task.cloudDriverService = cloudDriverService + cloudDriverService.getServerGroup("test", "us-east-1", "kato-main-v000") >> serverGroup def context = [account: "test", "deploy.server.groups": ["us-east-1": ["kato-main-v000"]]] def stage = new StageExecutionImpl(PipelineExecutionImpl.newOrchestration("orca"), "resizeServerGroup", context) @@ -136,9 +125,8 @@ class WaitForCapacityMatchTaskSpec extends Specification { void "should properly wait for a scale down operation"() { setup: - oort = Stub(OortService) - oort.getServerGroup("test", "us-east-1", "kato-main-v000") >> { new Response('kato', 200, 'ok', [], new TypedString(mapper.writeValueAsString(serverGroup))) } - task.oortService = oort + task.cloudDriverService = cloudDriverService + cloudDriverService.getServerGroup("test", "us-east-1", "kato-main-v000") >> serverGroup def context = [account: "test", "deploy.server.groups": ["us-east-1": ["kato-main-v000"]]] def stage = new StageExecutionImpl(PipelineExecutionImpl.newOrchestration("orca"), "resizeServerGroup", context) diff --git a/orca-clouddriver/src/test/groovy/com/netflix/spinnaker/orca/clouddriver/tasks/servergroup/WaitForRequiredInstancesDownTaskSpec.groovy b/orca-clouddriver/src/test/groovy/com/netflix/spinnaker/orca/clouddriver/tasks/servergroup/WaitForRequiredInstancesDownTaskSpec.groovy index 558cfde454..a7e449119d 100644 --- a/orca-clouddriver/src/test/groovy/com/netflix/spinnaker/orca/clouddriver/tasks/servergroup/WaitForRequiredInstancesDownTaskSpec.groovy +++ b/orca-clouddriver/src/test/groovy/com/netflix/spinnaker/orca/clouddriver/tasks/servergroup/WaitForRequiredInstancesDownTaskSpec.groovy @@ -18,6 +18,7 @@ package com.netflix.spinnaker.orca.clouddriver.tasks.servergroup import com.netflix.spinnaker.orca.api.pipeline.models.ExecutionStatus import com.netflix.spinnaker.orca.api.pipeline.TaskResult +import com.netflix.spinnaker.orca.clouddriver.CloudDriverService import com.netflix.spinnaker.orca.clouddriver.OortService import com.netflix.spinnaker.orca.clouddriver.pipeline.servergroup.support.TargetServerGroup import com.netflix.spinnaker.orca.clouddriver.utils.OortHelper @@ -41,8 +42,7 @@ class WaitForRequiredInstancesDownTaskSpec extends Specification { void "should fetch server groups"() { given: def pipeline = PipelineExecutionImpl.newPipeline("orca") - task.objectMapper = mapper - def response = mapper.writeValueAsString([ + def response = [ region : 'us-east-1', name : 'front50-v000', asg : [ @@ -53,10 +53,10 @@ class WaitForRequiredInstancesDownTaskSpec extends Specification { health: [[state: 'Down']] ] ] - ]) + ] - task.oortService = Stub(OortService) { - getServerGroup(*_) >> new Response('oort', 200, 'ok', [], new TypedString(response)) + task.cloudDriverService = Stub(CloudDriverService) { + getServerGroup(*_) >> response } task.serverGroupCacheForceRefreshTask = Mock(ServerGroupCacheForceRefreshTask) { 2 * execute(_) >> TaskResult.ofStatus(ExecutionStatus.SUCCEEDED) diff --git a/orca-clouddriver/src/test/groovy/com/netflix/spinnaker/orca/clouddriver/utils/OortHelperSpec.groovy b/orca-clouddriver/src/test/groovy/com/netflix/spinnaker/orca/clouddriver/utils/OortHelperSpec.groovy index f225054636..bc632271c2 100644 --- a/orca-clouddriver/src/test/groovy/com/netflix/spinnaker/orca/clouddriver/utils/OortHelperSpec.groovy +++ b/orca-clouddriver/src/test/groovy/com/netflix/spinnaker/orca/clouddriver/utils/OortHelperSpec.groovy @@ -29,16 +29,12 @@ import spock.lang.Unroll import static java.net.HttpURLConnection.HTTP_NOT_FOUND class OortHelperSpec extends Specification { - @Subject oortHelper = Spy(OortHelper) - OortService oortService = Mock(OortService) - - def setup() { - oortHelper.oortService = oortService - oortHelper.objectMapper = new ObjectMapper() - } + ObjectMapper objectMapper = new ObjectMapper() + OortService oortService = Mock() + @Subject oortHelper = new OortHelper(oortService, objectMapper) def "getInstancesForCluster fails if > 1 asg in the cluster"() { - when: + given: def oortResponse = '''\ { "serverGroups":[{ @@ -61,6 +57,8 @@ class OortHelperSpec extends Specification { Response response = new Response('http://oort', 200, 'OK', [], new TypedString(oortResponse)) Map deployContext = ["region" : "us-west-2", "account" : "prod", "kato.tasks" : [[resultObjects : [[ancestorServerGroupNameByRegion: ["us-west-2" : "myapp-v000"]],[serverGroupNameByRegion : ["us-west-2" : "myapp-v002"]]]]]] 1 * oortService.getCluster("myapp", "prod", "myapp", "aws") >> response + + when: oortHelper.getInstancesForCluster(deployContext, "myapp-v002", true, true) then: @@ -69,7 +67,7 @@ class OortHelperSpec extends Specification { } def "getInstancesForCluster fails if any instances are down/starting"() { - when: + given: def oortResponse = '''\ { "serverGroups":[{ @@ -85,7 +83,9 @@ class OortHelperSpec extends Specification { Response response = new Response('http://oort', 200, 'OK', [], new TypedString(oortResponse)) Map deployContext = ["region" : "us-west-2", "account" : "prod", "kato.tasks" : [[resultObjects : [[ancestorServerGroupNameByRegion: ["us-west-2" : "myapp-v000"]],[serverGroupNameByRegion : ["us-west-2" : "myapp-v002"]]]]]] 1 * oortService.getCluster("myapp", "prod", "myapp", "aws") >> response - oortHelper.getInstancesForCluster(deployContext, "myapp-v002", true, true) + + when: + oortHelper.getInstancesForCluster(deployContext, "myapp-v002", true, true) then: def e = thrown(RuntimeException) @@ -93,7 +93,7 @@ class OortHelperSpec extends Specification { } def "getInstancesForCluster works with deploy context"() { - when: + given: def oortResponse = '''\ { "serverGroups":[{ @@ -109,6 +109,8 @@ class OortHelperSpec extends Specification { Response response = new Response('http://oort', 200, 'OK', [], new TypedString(oortResponse)) Map deployContext = ["region" : "us-west-2", "account" : "prod", "kato.tasks" : [[resultObjects : [[ancestorServerGroupNameByRegion: ["us-west-2" : "myapp-v000"]],[serverGroupNameByRegion : ["us-west-2" : "myapp-v002"]]]]]] 1 * oortService.getCluster("myapp", "prod", "myapp", "aws") >> response + + when: def result = oortHelper.getInstancesForCluster(deployContext, "myapp-v002", true, true) then: @@ -117,7 +119,7 @@ class OortHelperSpec extends Specification { } def "getInstancesForCluster passes if any instances are down/starting and failIfAnyInstancesUnhealthy == false"() { - when: + given: def oortResponse = '''\ { "serverGroups":[{ @@ -137,6 +139,8 @@ class OortHelperSpec extends Specification { Response response = new Response('http://oort', 200, 'OK', [], new TypedString(oortResponse)) Map deployContext = ["region" : "us-west-2", "account" : "prod", "kato.tasks" : [[resultObjects : [[ancestorServerGroupNameByRegion: ["us-west-2" : "myapp-v000"]],[serverGroupNameByRegion : ["us-west-2" : "myapp-v002"]]]]]] 1 * oortService.getCluster("myapp", "prod", "myapp", "aws") >> response + + when: def result = oortHelper.getInstancesForCluster(deployContext, "myapp-v002", true, false) then: diff --git a/orca-clouddriver/src/test/groovy/com/netflix/spinnaker/orca/kato/tasks/rollingpush/CleanUpTagsTaskSpec.groovy b/orca-clouddriver/src/test/groovy/com/netflix/spinnaker/orca/kato/tasks/rollingpush/CleanUpTagsTaskSpec.groovy index baeac2fba3..f324ab5f2e 100644 --- a/orca-clouddriver/src/test/groovy/com/netflix/spinnaker/orca/kato/tasks/rollingpush/CleanUpTagsTaskSpec.groovy +++ b/orca-clouddriver/src/test/groovy/com/netflix/spinnaker/orca/kato/tasks/rollingpush/CleanUpTagsTaskSpec.groovy @@ -1,15 +1,13 @@ package com.netflix.spinnaker.orca.kato.tasks.rollingpush -import com.fasterxml.jackson.databind.ObjectMapper + +import com.netflix.spinnaker.orca.clouddriver.CloudDriverService import com.netflix.spinnaker.orca.clouddriver.KatoService -import com.netflix.spinnaker.orca.clouddriver.OortService import com.netflix.spinnaker.orca.clouddriver.model.TaskId import com.netflix.spinnaker.orca.clouddriver.utils.MonikerHelper import com.netflix.spinnaker.orca.kato.pipeline.support.SourceResolver import com.netflix.spinnaker.orca.pipeline.model.PipelineExecutionImpl import com.netflix.spinnaker.orca.pipeline.model.StageExecutionImpl -import retrofit.client.Response -import retrofit.mime.TypedByteArray import spock.lang.Specification class CleanUpTagsTaskSpec extends Specification { @@ -68,16 +66,13 @@ class CleanUpTagsTaskSpec extends Specification { ] ] - def serverGroup = new TypedByteArray('application/json', new ObjectMapper().writeValueAsBytes([ + def serverGroup = [ launchConfig: [ imageId: "imageId" ] - ])) - - Response oortResponse = new Response('http://oort', 200, 'OK', [], serverGroup); + ] List operations = [] - task.objectMapper = new ObjectMapper(); task.monikerHelper = Mock(MonikerHelper) { 1* getAppNameFromStage(stage, "app-v00") >> { "app" @@ -87,9 +82,9 @@ class CleanUpTagsTaskSpec extends Specification { } 0 * _ } - task.oortService = Mock(OortService) { + task.cloudDriverService = Mock(CloudDriverService) { 1* getServerGroupFromCluster("app","test", "app", "app-v00", "us-east-1", "aws") >> { - oortResponse + serverGroup } 1* getEntityTags("aws", "servergroup", "app-v00", "test", "us-east-1") >> { diff --git a/orca-clouddriver/src/test/groovy/com/netflix/spinnaker/orca/kato/tasks/rollingpush/DetermineTerminationCandidatesTaskSpec.groovy b/orca-clouddriver/src/test/groovy/com/netflix/spinnaker/orca/kato/tasks/rollingpush/DetermineTerminationCandidatesTaskSpec.groovy index 8d0cf3e8d7..9764ef893b 100644 --- a/orca-clouddriver/src/test/groovy/com/netflix/spinnaker/orca/kato/tasks/rollingpush/DetermineTerminationCandidatesTaskSpec.groovy +++ b/orca-clouddriver/src/test/groovy/com/netflix/spinnaker/orca/kato/tasks/rollingpush/DetermineTerminationCandidatesTaskSpec.groovy @@ -16,19 +16,16 @@ package com.netflix.spinnaker.orca.kato.tasks.rollingpush -import com.fasterxml.jackson.databind.ObjectMapper -import com.netflix.spinnaker.orca.clouddriver.OortService +import com.netflix.spinnaker.orca.clouddriver.CloudDriverService import com.netflix.spinnaker.orca.pipeline.model.PipelineExecutionImpl import com.netflix.spinnaker.orca.pipeline.model.StageExecutionImpl -import retrofit.client.Response -import retrofit.mime.TypedByteArray import spock.lang.Specification import spock.lang.Unroll class DetermineTerminationCandidatesTaskSpec extends Specification { - def oortService = Mock(OortService) - def task = new DetermineTerminationCandidatesTask(oortService: oortService, objectMapper: new ObjectMapper()) + CloudDriverService cloudDriverService = Mock() + def task = new DetermineTerminationCandidatesTask(cloudDriverService: cloudDriverService) @Unroll def 'should order and filter instances correctly'() { @@ -48,15 +45,15 @@ class DetermineTerminationCandidatesTaskSpec extends Specification { def stage = new StageExecutionImpl(PipelineExecutionImpl.newOrchestration("orca"), 'test', context) - def oortResponse = oortResponse([ + def oortResponse = [ instances: knownInstanceIds.inject([]) { List l, id -> l << [instanceId: id, launchTime: l.size()] } - ]) + ] when: def response = task.execute(stage) then: - 1 * oortService.getServerGroupFromCluster(application, account, cluster, serverGroup, region, cloudProvider) >> oortResponse + 1 * cloudDriverService.getServerGroupFromCluster(application, account, cluster, serverGroup, region, cloudProvider) >> oortResponse response.context.terminationInstanceIds == expectedTerminations response.context.knownInstanceIds.toSet() == knownInstanceIds.toSet() expectedTerminations == response.context.terminationInstanceIds @@ -106,9 +103,4 @@ class DetermineTerminationCandidatesTaskSpec extends Specification { return termination } - - Response oortResponse(Map response) { - def bytes = new TypedByteArray('application/json', task.objectMapper.writeValueAsBytes(response)) - new Response('http://oortse.cx', 200, 'OK', [], bytes) - } } diff --git a/orca-clouddriver/src/test/groovy/com/netflix/spinnaker/orca/kato/tasks/rollingpush/WaitForNewUpInstancesLaunchTaskSpec.groovy b/orca-clouddriver/src/test/groovy/com/netflix/spinnaker/orca/kato/tasks/rollingpush/WaitForNewUpInstancesLaunchTaskSpec.groovy index 1edf659ff1..95f685e5db 100644 --- a/orca-clouddriver/src/test/groovy/com/netflix/spinnaker/orca/kato/tasks/rollingpush/WaitForNewUpInstancesLaunchTaskSpec.groovy +++ b/orca-clouddriver/src/test/groovy/com/netflix/spinnaker/orca/kato/tasks/rollingpush/WaitForNewUpInstancesLaunchTaskSpec.groovy @@ -16,19 +16,16 @@ package com.netflix.spinnaker.orca.kato.tasks.rollingpush -import com.fasterxml.jackson.databind.ObjectMapper import com.netflix.spinnaker.orca.api.pipeline.models.ExecutionStatus -import com.netflix.spinnaker.orca.clouddriver.OortService +import com.netflix.spinnaker.orca.clouddriver.CloudDriverService import com.netflix.spinnaker.orca.pipeline.model.PipelineExecutionImpl import com.netflix.spinnaker.orca.pipeline.model.StageExecutionImpl -import retrofit.client.Response -import retrofit.mime.TypedByteArray import spock.lang.Specification import spock.lang.Unroll class WaitForNewUpInstancesLaunchTaskSpec extends Specification { - def oortService = Mock(OortService) - def task = new WaitForNewUpInstancesLaunchTask(oortService: oortService, objectMapper: new ObjectMapper()) + CloudDriverService cloudDriverService = Mock() + def task = new WaitForNewUpInstancesLaunchTask(cloudDriverService: cloudDriverService) @Unroll def 'waits for new instances to be launched and healthy'() { @@ -46,15 +43,15 @@ class WaitForNewUpInstancesLaunchTaskSpec extends Specification { def stage = new StageExecutionImpl(PipelineExecutionImpl.newOrchestration("orca"), 'test', context) - def oortResponse = oortResponse([ + def oortResponse = [ instances: currentInstances.collect { [instanceId: it, health: [ [type: 'Discovery', state: healthState] ] ] } - ]) + ] when: def response = task.execute(stage) then: - 1 * oortService.getServerGroup(account, region, serverGroup) >> oortResponse + 1 * cloudDriverService.getServerGroup(account, region, serverGroup) >> oortResponse response.status == expectedStatus @@ -79,10 +76,4 @@ class WaitForNewUpInstancesLaunchTaskSpec extends Specification { cloudProvider = 'aws' } - - Response oortResponse(Map response) { - def bytes = new TypedByteArray('application/json', task.objectMapper.writeValueAsBytes(response)) - new Response('http://oortse.cx', 200, 'OK', [], bytes) - } - } diff --git a/orca-clouddriver/src/test/groovy/com/netflix/spinnaker/orca/tasks/image/MonitorDeleteImageTaskSpec.groovy b/orca-clouddriver/src/test/groovy/com/netflix/spinnaker/orca/tasks/image/MonitorDeleteImageTaskSpec.groovy index 9e0e29f4d6..0eb177fd70 100644 --- a/orca-clouddriver/src/test/groovy/com/netflix/spinnaker/orca/tasks/image/MonitorDeleteImageTaskSpec.groovy +++ b/orca-clouddriver/src/test/groovy/com/netflix/spinnaker/orca/tasks/image/MonitorDeleteImageTaskSpec.groovy @@ -17,6 +17,7 @@ package com.netflix.spinnaker.orca.tasks.image import com.netflix.spinnaker.orca.api.pipeline.models.ExecutionStatus +import com.netflix.spinnaker.orca.clouddriver.CloudDriverService import com.netflix.spinnaker.orca.clouddriver.OortService import com.netflix.spinnaker.orca.clouddriver.tasks.image.MonitorDeleteImageTask import com.netflix.spinnaker.orca.pipeline.model.PipelineExecutionImpl @@ -26,6 +27,9 @@ import retrofit.client.Response import spock.lang.Specification class MonitorDeleteImageTaskSpec extends Specification { + + CloudDriverService cloudDriverService = Mock() + def "should monitor image deletion"() { given: def context = [ @@ -35,13 +39,11 @@ class MonitorDeleteImageTaskSpec extends Specification { imageIds: ["ami-123", "ami-321"] ] - def oortService = Mock(OortService) { - 1 * getByAmiId("aws", "test", "us-east-1", "ami-123") >> { error(404) } - 1 * getByAmiId("aws", "test", "us-east-1", "ami-321") >> { error(404) } - } + 1 * cloudDriverService.getByAmiId("aws", "test", "us-east-1", "ami-123") >> { error(404) } + 1 * cloudDriverService.getByAmiId("aws", "test", "us-east-1", "ami-321") >> { error(404) } def stage = new StageExecutionImpl(PipelineExecutionImpl.newPipeline("orca"), "deleteImage", context) - def task = new MonitorDeleteImageTask(oortService) + def task = new MonitorDeleteImageTask(cloudDriverService) expect: task.execute(stage).status == ExecutionStatus.SUCCEEDED @@ -56,13 +58,11 @@ class MonitorDeleteImageTaskSpec extends Specification { imageIds: ["ami-123", "ami-321"] ] - def oortService = Mock(OortService) { - 1 * getByAmiId("aws", "test", "us-east-1", "ami-123") >> { error(404) } - 1 * getByAmiId("aws", "test", "us-east-1", "ami-321") >> { error(500) } - } + 1 * cloudDriverService.getByAmiId("aws", "test", "us-east-1", "ami-123") >> { error(404) } + 1 * cloudDriverService.getByAmiId("aws", "test", "us-east-1", "ami-321") >> { error(500) } def stage = new StageExecutionImpl(PipelineExecutionImpl.newPipeline("orca"), "deleteImage", context) - def task = new MonitorDeleteImageTask(oortService) + def task = new MonitorDeleteImageTask(cloudDriverService) expect: task.execute(stage).status == ExecutionStatus.RUNNING diff --git a/orca-igor/src/main/groovy/com/netflix/spinnaker/orca/igor/tasks/GetCommitsTask.groovy b/orca-igor/src/main/groovy/com/netflix/spinnaker/orca/igor/tasks/GetCommitsTask.groovy index e16eb8ecef..6aa731384f 100644 --- a/orca-igor/src/main/groovy/com/netflix/spinnaker/orca/igor/tasks/GetCommitsTask.groovy +++ b/orca-igor/src/main/groovy/com/netflix/spinnaker/orca/igor/tasks/GetCommitsTask.groovy @@ -17,13 +17,11 @@ package com.netflix.spinnaker.orca.igor.tasks import com.netflix.spinnaker.orca.api.pipeline.models.StageExecution +import com.netflix.spinnaker.orca.clouddriver.CloudDriverService import java.util.concurrent.TimeUnit -import com.fasterxml.jackson.core.type.TypeReference -import com.fasterxml.jackson.databind.ObjectMapper import com.netflix.spinnaker.orca.api.pipeline.models.ExecutionStatus import com.netflix.spinnaker.orca.api.pipeline.TaskResult -import com.netflix.spinnaker.orca.clouddriver.OortService import com.netflix.spinnaker.orca.front50.Front50Service import com.netflix.spinnaker.orca.front50.model.Application import com.netflix.spinnaker.orca.igor.ScmService @@ -44,10 +42,7 @@ class GetCommitsTask implements DiffTask { // always set this higher than retries * backoffPeriod would take @Autowired - OortService oortService - - @Autowired - ObjectMapper objectMapper + CloudDriverService cloudDriverService @Autowired(required = false) ScmService scmService @@ -157,7 +152,7 @@ class GetCommitsTask implements DiffTask { } Map resolveInfoFromAmi(String ami, String account, String region) { - List amiDetails = oortService.getByAmiId("aws", account, region, ami) + List> amiDetails = cloudDriverService.getByAmiId("aws", account, region, ami) def appVersion = amiDetails[0]?.tags?.appversion def buildInfo = [:] @@ -209,10 +204,9 @@ class GetCommitsTask implements DiffTask { sourceCluster = ancestorAsg } - TypeReference jsonMapType = new TypeReference() {} - Map sourceServerGroup = objectMapper.readValue(oortService.getServerGroupFromCluster(context.application, + Map sourceServerGroup = cloudDriverService.getServerGroupFromCluster(context.application, account, sourceCluster, - ancestorAsg, region, "aws").body.in(), jsonMapType) + ancestorAsg, region, "aws") return sourceServerGroup.launchConfig.imageId } } diff --git a/orca-igor/src/test/groovy/com/netflix/spinnaker/orca/igor/tasks/GetCommitsTaskSpec.groovy b/orca-igor/src/test/groovy/com/netflix/spinnaker/orca/igor/tasks/GetCommitsTaskSpec.groovy index 392ae24c53..18cba2a446 100644 --- a/orca-igor/src/test/groovy/com/netflix/spinnaker/orca/igor/tasks/GetCommitsTaskSpec.groovy +++ b/orca-igor/src/test/groovy/com/netflix/spinnaker/orca/igor/tasks/GetCommitsTaskSpec.groovy @@ -19,6 +19,7 @@ package com.netflix.spinnaker.orca.igor.tasks import com.fasterxml.jackson.databind.ObjectMapper import com.netflix.spinnaker.orca.api.pipeline.models.ExecutionStatus import com.netflix.spinnaker.orca.api.pipeline.TaskResult +import com.netflix.spinnaker.orca.clouddriver.CloudDriverService import com.netflix.spinnaker.orca.clouddriver.OortService import com.netflix.spinnaker.orca.front50.Front50Service import com.netflix.spinnaker.orca.front50.model.Application @@ -30,6 +31,7 @@ import com.netflix.spinnaker.orca.test.model.ExecutionBuilder import retrofit.RetrofitError import retrofit.client.Response import retrofit.mime.TypedString +import spock.lang.IgnoreRest import spock.lang.Shared import spock.lang.Specification import spock.lang.Subject @@ -42,9 +44,9 @@ class GetCommitsTaskSpec extends Specification { @Subject GetCommitsTask task = new GetCommitsTask() - ScmService scmService = Mock(ScmService) - OortService oortService = Mock(OortService) - Front50Service front50Service = Mock(Front50Service) + ScmService scmService = Mock() + CloudDriverService cloudDriverService = Mock() + Front50Service front50Service = Mock() @Shared def pipeline = ExecutionBuilder.pipeline {} @@ -69,11 +71,11 @@ class GetCommitsTaskSpec extends Specification { def "get commits from a deploy stage"() { given: String katoTasks = "[{\"resultObjects\": [" + - "{\"ancestorServerGroupNameByRegion\": { \"${region}\":\"${serverGroup}\"}}," + - "{\"messages\" : [ ], \"serverGroupNameByRegion\": {\"${region}\": \"${targetServerGroup}\"},\"serverGroupNames\": [\"${region}:${targetServerGroup}\"]}],\"status\": {\"completed\": true,\"failed\": false}}]" + "{\"ancestorServerGroupNameByRegion\": { \"${region}\":\"${serverGroup}\"}}," + + "{\"messages\" : [ ], \"serverGroupNameByRegion\": {\"${region}\": \"${targetServerGroup}\"},\"serverGroupNames\": [\"${region}:${targetServerGroup}\"]}],\"status\": {\"completed\": true,\"failed\": false}}]" def katoMap = getObjectMapper().readValue(katoTasks, List) def contextMap = [application: app, account: account, - source : [asgName: serverGroup, region: region, account: account], "deploy.server.groups": ["us-west-1": [targetServerGroup]], deploymentDetails: [[imageId: "ami-foo", ami: "amiFooName", region: "us-east-1"], [imageId: targetImage, ami: targetImageName, region: region]], "kato.tasks": katoMap] + source: [asgName: serverGroup, region: region, account: account], "deploy.server.groups": ["us-west-1": [targetServerGroup]], deploymentDetails: [[imageId: "ami-foo", ami: "amiFooName", region: "us-east-1"], [imageId: targetImage, ami: targetImageName, region: region]], "kato.tasks": katoMap] def stage = setupGetCommits(contextMap, account, app, sourceImage, targetImage, region, cluster, serverGroup) when: @@ -101,11 +103,11 @@ class GetCommitsTaskSpec extends Specification { def "get commits from a copy last asg stage"() { given: String katoTasks = "[{\"resultObjects\": [" + - "{\"ancestorServerGroupNameByRegion\": { \"${region}\":\"${serverGroup}\"}}," + - "{\"messages\" : [ ], \"serverGroupNameByRegion\": {\"${region}\": \"${targetServerGroup}\"},\"serverGroupNames\": [\"${region}:${targetServerGroup}\"]}],\"status\": {\"completed\": true,\"failed\": false}}]" + "{\"ancestorServerGroupNameByRegion\": { \"${region}\":\"${serverGroup}\"}}," + + "{\"messages\" : [ ], \"serverGroupNameByRegion\": {\"${region}\": \"${targetServerGroup}\"},\"serverGroupNames\": [\"${region}:${targetServerGroup}\"]}],\"status\": {\"completed\": true,\"failed\": false}}]" def katoMap = getObjectMapper().readValue(katoTasks, List) def contextMap = [application: app, account: account, - source : [asgName: serverGroup, region: region, account: account], imageId: targetImage, amiName: targetImageName, "kato.tasks": katoMap] + source: [asgName: serverGroup, region: region, account: account], imageId: targetImage, amiName: targetImageName, "kato.tasks": katoMap] def stage = setupGetCommits(contextMap, account, app, sourceImage, targetImageName, region, cluster, serverGroup) when: @@ -129,10 +131,10 @@ class GetCommitsTaskSpec extends Specification { def "get commits from a single region canary stage"() { given: - def contextMap = [application : app, account: account, - source : [asgName: serverGroup, region: region, account: account], + def contextMap = [application: app, account: account, + source: [asgName: serverGroup, region: region, account: account], clusterPairs: - [[baseline: [amiName: sourceImage, availabilityZones: [(region): ["${region}-1c"]]], canary: [imageId: targetImage, amiName: targetImageName, availabilityZones: [(region): ["${region}-1c"]]]]] + [[baseline: [amiName: sourceImage, availabilityZones: [(region): ["${region}-1c"]]], canary: [imageId: targetImage, amiName: targetImageName, availabilityZones: [(region): ["${region}-1c"]]]]] ] def stage = setupGetCommits(contextMap, account, app, sourceImage, targetImageName, region, cluster, serverGroup, 0) @@ -157,12 +159,12 @@ class GetCommitsTaskSpec extends Specification { def "get commits from a multi-region canary stage"() { given: - def contextMap = [application : app, account: account, - source : [asgName: serverGroup, region: region, account: account], + def contextMap = [application: app, account: account, + source: [asgName: serverGroup, region: region, account: account], clusterPairs: [ - [baseline: [amiName: "ami-fake", availabilityZones: ["us-east-1": ["us-east-1-1c"]]], canary: [amiName: "ami-fake2", availabilityZones: ["us-east-1": ["us-east-1-1c"]]]], - [baseline: [amiName: sourceImage, availabilityZones: [(region): ["${region}-1c"]]], canary: [amiName: targetImage, availabilityZones: [(region): ["${region}-1c"]]]], - [baseline: [amiName: "ami-fake3", availabilityZones: ["eu-west-1": ["eu-west-1-1c"]]], canary: [amiName: "ami-fake4", availabilityZones: ["eu-west-1": ["eu-west-1-1c"]]]] + [baseline: [amiName: "ami-fake", availabilityZones: ["us-east-1": ["us-east-1-1c"]]], canary: [amiName: "ami-fake2", availabilityZones: ["us-east-1": ["us-east-1-1c"]]]], + [baseline: [amiName: sourceImage, availabilityZones: [(region): ["${region}-1c"]]], canary: [amiName: targetImage, availabilityZones: [(region): ["${region}-1c"]]]], + [baseline: [amiName: "ami-fake3", availabilityZones: ["eu-west-1": ["eu-west-1-1c"]]], canary: [amiName: "ami-fake4", availabilityZones: ["eu-west-1": ["eu-west-1-1c"]]]] ] ] def stage = setupGetCommits(contextMap, account, app, sourceImage, targetImage, region, cluster, serverGroup, 0) @@ -197,15 +199,13 @@ class GetCommitsTaskSpec extends Specification { task.front50Service = front50Service 1 * front50Service.get(app) >> new Application(repoSlug: "repositorySlug", repoProjectKey: "projectKey", repoType: "stash") - task.objectMapper = getObjectMapper() - def oortResponse = "{\"launchConfig\" : {\"imageId\" : \"${sourceImage}\"}}".stripIndent() - Response response = new Response('http://oort', 200, 'OK', [], new TypedString(oortResponse)) - task.oortService = oortService - serverGroupCalls * oortService.getServerGroupFromCluster(app, account, cluster, serverGroup, region, "aws") >> response + def oortResponse = [launchConfig: [imageId: sourceImage]] + task.cloudDriverService = cloudDriverService + serverGroupCalls * cloudDriverService.getServerGroupFromCluster(app, account, cluster, serverGroup, region, "aws") >> oortResponse List sourceResponse = [["tags": ["appversion": "myapp-1.143-h216.186605b/MYAPP-package-myapp/216"]]] List targetResponse = [["tags": ["appversion": "myapp-1.144-h217.a86305d/MYAPP-package-myapp/217"]]] - oortCalls * oortService.getByAmiId("aws", account, region, sourceImage) >> sourceResponse - oortCalls * oortService.getByAmiId("aws", account, region, targetImage) >> targetResponse + oortCalls * cloudDriverService.getByAmiId("aws", account, region, sourceImage) >> sourceResponse + oortCalls * cloudDriverService.getByAmiId("aws", account, region, targetImage) >> targetResponse return stage } @@ -228,30 +228,29 @@ class GetCommitsTaskSpec extends Specification { return true } + @Unroll def "returns running where there is an error talking to igor"() { given: String katoTasks = "[{\"resultObjects\": [" + - "{\"ancestorServerGroupNameByRegion\": { \"${region}\":\"${serverGroup}\"}}," + - "{\"messages\" : [ ], \"serverGroupNameByRegion\": {\"${region}\": \"${targetServerGroup}\"},\"serverGroupNames\": [\"${region}:${targetServerGroup}\"]}],\"status\": {\"completed\": true,\"failed\": false}}]" + "{\"ancestorServerGroupNameByRegion\": { \"${region}\":\"${serverGroup}\"}}," + + "{\"messages\" : [ ], \"serverGroupNameByRegion\": {\"${region}\": \"${targetServerGroup}\"},\"serverGroupNames\": [\"${region}:${targetServerGroup}\"]}],\"status\": {\"completed\": true,\"failed\": false}}]" def katoMap = getObjectMapper().readValue(katoTasks, List) def stage = new StageExecutionImpl(pipeline, "stash", [application: app, account: account, - source : [asgName: serverGroup, region: region, account: account], "deploy.server.groups": ["us-west-1": [targetServerGroup]], deploymentDetails: [[ami: "ami-foo", region: "us-east-1"], [imageId: targetImage, ami: targetImageName, region: region]], "kato.tasks": katoMap]) + source: [asgName: serverGroup, region: region, account: account], "deploy.server.groups": ["us-west-1": [targetServerGroup]], deploymentDetails: [[ami: "ami-foo", region: "us-east-1"], [imageId: targetImage, ami: targetImageName, region: region]], "kato.tasks": katoMap]) and: task.front50Service = front50Service 1 * front50Service.get(app) >> new Application(repoSlug: "repositorySlug", repoProjectKey: "projectKey", repoType: "stash") and: - task.objectMapper = getObjectMapper() - def oortResponse = "{\"launchConfig\" : {\"imageId\" : \"${sourceImage}\"}}".stripIndent() - Response response = new Response('http://oort', 200, 'OK', [], new TypedString(oortResponse)) + def response = [launchConfig: [imageId: sourceImage]] List sourceResponse = [["tags": ["appversion": "myapp-1.143-h216.186605b/MYAPP-package-myapp/216"]]] List targetResponse = [["tags": ["appversion": "myapp-1.144-h217.a86305d/MYAPP-package-myapp/217"]]] - task.oortService = oortService - 1 * oortService.getServerGroupFromCluster(app, account, cluster, serverGroup, region, "aws") >> response - 1 * oortService.getByAmiId("aws", account, region, sourceImage) >> sourceResponse - 1 * oortService.getByAmiId("aws", account, region, targetImage) >> targetResponse + task.cloudDriverService = cloudDriverService + 1 * cloudDriverService.getServerGroupFromCluster(app, account, cluster, serverGroup, region, "aws") >> response + 1 * cloudDriverService.getByAmiId("aws", account, region, sourceImage) >> sourceResponse + 1 * cloudDriverService.getByAmiId("aws", account, region, targetImage) >> targetResponse and: task.scmService = scmService @@ -262,7 +261,7 @@ class GetCommitsTaskSpec extends Specification { then: 1 * scmService.compareCommits("stash", "projectKey", "repositorySlug", ['to': '186605b', 'from': 'a86305d', 'limit': 100]) >> { throw new RetrofitError(null, null, - new Response("http://stash.com", 500, "test reason", [], null), null, null, null, null) + new Response("http://stash.com", 500, "test reason", [], null), null, null, null, null) } result.status == taskStatus @@ -308,8 +307,8 @@ class GetCommitsTaskSpec extends Specification { def "return info from ami or empty map if not in the right format"() { given: - task.oortService = oortService - 1 * oortService.getByAmiId("aws", account, region, image) >> [["tags": ["appversion": appVersion]]] + task.cloudDriverService = cloudDriverService + 1 * cloudDriverService.getByAmiId("aws", account, region, image) >> [["tags": ["appversion": appVersion]]] when: Map result = task.resolveInfoFromAmi(image, account, region) @@ -332,11 +331,11 @@ class GetCommitsTaskSpec extends Specification { def "returns success if commit info is missing"() { given: String katoTasks = "[{\"resultObjects\": [" + - "{\"ancestorServerGroupNameByRegion\": { \"${region}\":\"${serverGroup}\"}}," + - "{\"messages\" : [ ], \"serverGroupNameByRegion\": {\"${region}\": \"${targetServerGroup}\"},\"serverGroupNames\": [\"${region}:${targetServerGroup}\"]}],\"status\": {\"completed\": true,\"failed\": false}}]" + "{\"ancestorServerGroupNameByRegion\": { \"${region}\":\"${serverGroup}\"}}," + + "{\"messages\" : [ ], \"serverGroupNameByRegion\": {\"${region}\": \"${targetServerGroup}\"},\"serverGroupNames\": [\"${region}:${targetServerGroup}\"]}],\"status\": {\"completed\": true,\"failed\": false}}]" def katoMap = getObjectMapper().readValue(katoTasks, List) def stage = new StageExecutionImpl(pipeline, "stash", [application: app, account: account, - source : [asgName: serverGroup, region: region, account: account], "deploy.server.groups": ["us-west-1": [targetServerGroup]], deploymentDetails: [[ami: "ami-foo", region: "us-east-1"], [ami: targetImageName, imageId: targetImage, region: region]], "kato.tasks": katoMap]) + source: [asgName: serverGroup, region: region, account: account], "deploy.server.groups": ["us-west-1": [targetServerGroup]], deploymentDetails: [[ami: "ami-foo", region: "us-east-1"], [ami: targetImageName, imageId: targetImage, region: region]], "kato.tasks": katoMap]) and: task.scmService = Stub(ScmService) { @@ -349,13 +348,11 @@ class GetCommitsTaskSpec extends Specification { 1 * front50Service.get(app) >> new Application(repoSlug: "repositorySlug", repoProjectKey: "projectKey", repoType: "stash") and: - task.objectMapper = getObjectMapper() - def oortResponse = "{\"launchConfig\" : {\"imageId\" : \"${sourceImage}\"}}".stripIndent() - Response response = new Response('http://oort', 200, 'OK', [], new TypedString(oortResponse)) - task.oortService = oortService - 1 * oortService.getServerGroupFromCluster(app, account, cluster, serverGroup, region, "aws") >> response - oortService.getByAmiId("aws", account, region, sourceImage) >> sourceTags - oortService.getByAmiId("aws", account, region, targetImage) >> targetTags + def response = [launchConfig: [imageId: sourceImage]] + task.cloudDriverService = cloudDriverService + 1 * cloudDriverService.getServerGroupFromCluster(app, account, cluster, serverGroup, region, "aws") >> response + cloudDriverService.getByAmiId("aws", account, region, sourceImage) >> sourceTags + cloudDriverService.getByAmiId("aws", account, region, targetImage) >> targetTags when: def result = task.execute(stage) @@ -378,14 +375,15 @@ class GetCommitsTaskSpec extends Specification { "myapp" | "myapp-v001" | "myapp-v002" | [["tags": []]] | [["tags": ["appversion": "myapp-1.143-h216.186605b/MYAPP-package-myapp/216"]]] } + @Unroll def "oort service 404 results in success"() { given: String katoTasks = "[{\"resultObjects\": [" + - "{\"ancestorServerGroupNameByRegion\": { \"${region}\":\"${serverGroup}\"}}," + - "{\"messages\" : [ ], \"serverGroupNameByRegion\": {\"${region}\": \"${targetServerGroup}\"},\"serverGroupNames\": [\"${region}:${targetServerGroup}\"]}],\"status\": {\"completed\": true,\"failed\": false}}]" + "{\"ancestorServerGroupNameByRegion\": { \"${region}\":\"${serverGroup}\"}}," + + "{\"messages\" : [ ], \"serverGroupNameByRegion\": {\"${region}\": \"${targetServerGroup}\"},\"serverGroupNames\": [\"${region}:${targetServerGroup}\"]}],\"status\": {\"completed\": true,\"failed\": false}}]" def katoMap = getObjectMapper().readValue(katoTasks, List) def stage = new StageExecutionImpl(pipeline, "stash", [application: app, account: account, - source : [asgName: serverGroup, region: region, account: account], "deploy.server.groups": ["us-west-1": [targetServerGroup]], deploymentDetails: [[ami: "ami-foo", region: "us-east-1"], [ami: targetImageName, imageId: targetImage, region: region]], "kato.tasks": katoMap]) + source: [asgName: serverGroup, region: region, account: account], "deploy.server.groups": ["us-west-1": [targetServerGroup]], deploymentDetails: [[ami: "ami-foo", region: "us-east-1"], [ami: targetImageName, imageId: targetImage, region: region]], "kato.tasks": katoMap]) and: task.scmService = Stub(ScmService) { @@ -398,30 +396,24 @@ class GetCommitsTaskSpec extends Specification { 1 * front50Service.get(app) >> new Application(repoSlug: "repositorySlug", repoProjectKey: "projectKey", repoType: "stash") and: - task.objectMapper = getObjectMapper() - def oortResponse = "{\"launchConfig\" : {\"imageId\" : \"${sourceImage}\"}}".stripIndent() - Response response = new Response('http://oort', 200, 'OK', [], new TypedString(oortResponse)) + def response = [launchConfig: [imageId: sourceImage]] List sourceResponse = [["tags": ["appversion": "myapp-1.143-h216.186605b/MYAPP-package-myapp/216"]]] List targetResponse = [["tags": ["appversion": "myapp-1.144-h217.a86305d/MYAPP-package-myapp/217"]]] - task.oortService = oortService - 1 * oortService.getServerGroupFromCluster(app, account, cluster, serverGroup, region, "aws") >>> response + task.cloudDriverService = cloudDriverService + 1 * cloudDriverService.getServerGroupFromCluster(app, account, cluster, serverGroup, region, "aws") >> response - if (sourceThrowRetrofitError) { - 1 * oortService.getByAmiId("aws", account, region, sourceImage) >> { + 1 * cloudDriverService.getByAmiId("aws", account, region, sourceImage) >> { + if (sourceThrowRetrofitError) { throw new RetrofitError(null, null, new Response("http://stash.com", 404, "test reason", [], null), null, null, null, null) } - } else { - 1 * oortService.getByAmiId("aws", account, region, sourceImage) >> sourceResponse - + return sourceResponse } - if (targetThrowRetrofitError) { - (sourceThrowRetrofitError ? 0 : 1) * oortService.getByAmiId("aws", account, region, targetImage) >> { + (sourceThrowRetrofitError ? 0 : 1) * cloudDriverService.getByAmiId("aws", account, region, targetImage) >> { + if (targetThrowRetrofitError) { throw new RetrofitError(null, null, new Response("http://stash.com", 404, "test reason", [], null), null, null, null, null) } - } else { - (sourceThrowRetrofitError ? 0 : 1) * oortService.getByAmiId("aws", account, region, targetImage) >> targetResponse - + return targetResponse } when: @@ -449,11 +441,11 @@ class GetCommitsTaskSpec extends Specification { def "igor service 404 results in success"() { given: String katoTasks = "[{\"resultObjects\": [" + - "{\"ancestorServerGroupNameByRegion\": { \"${region}\":\"${serverGroup}\"}}," + - "{\"messages\" : [ ], \"serverGroupNameByRegion\": {\"${region}\": \"${targetServerGroup}\"},\"serverGroupNames\": [\"${region}:${targetServerGroup}\"]}],\"status\": {\"completed\": true,\"failed\": false}}]" + "{\"ancestorServerGroupNameByRegion\": { \"${region}\":\"${serverGroup}\"}}," + + "{\"messages\" : [ ], \"serverGroupNameByRegion\": {\"${region}\": \"${targetServerGroup}\"},\"serverGroupNames\": [\"${region}:${targetServerGroup}\"]}],\"status\": {\"completed\": true,\"failed\": false}}]" def katoMap = getObjectMapper().readValue(katoTasks, List) def stage = new StageExecutionImpl(pipeline, "stash", [application: app, account: account, - source : [asgName: serverGroup, region: region, account: account], "deploy.server.groups": ["us-west-1": [targetServerGroup]], deploymentDetails: [[ami: "ami-foo", region: "us-east-1"], [ami: targetImageName, imageId: targetImage, region: region]], "kato.tasks": katoMap]) + source: [asgName: serverGroup, region: region, account: account], "deploy.server.groups": ["us-west-1": [targetServerGroup]], deploymentDetails: [[ami: "ami-foo", region: "us-east-1"], [ami: targetImageName, imageId: targetImage, region: region]], "kato.tasks": katoMap]) and: task.scmService = Stub(ScmService) { @@ -467,15 +459,13 @@ class GetCommitsTaskSpec extends Specification { 1 * front50Service.get(app) >> new Application(repoSlug: "repositorySlug", repoProjectKey: "projectKey", repoType: "stash") and: - task.objectMapper = getObjectMapper() - def oortResponse = "{\"launchConfig\" : {\"imageId\" : \"${sourceImage}\"}}".stripIndent() - Response response = new Response('http://oort', 200, 'OK', [], new TypedString(oortResponse)) + def response = [launchConfig: [imageId: sourceImage]] List sourceResponse = [["tags": ["appversion": "myapp-1.143-h216.186605b/MYAPP-package-myapp/216"]]] List targetResponse = [["tags": ["appversion": "myapp-1.144-h217.a86305d/MYAPP-package-myapp/217"]]] - task.oortService = oortService - 1 * oortService.getServerGroupFromCluster(app, account, cluster, serverGroup, region, "aws") >> response - 1 * oortService.getByAmiId("aws", account, region, sourceImage) >> sourceResponse - 1 * oortService.getByAmiId("aws", account, region, targetImage) >> targetResponse + task.cloudDriverService = cloudDriverService + 1 * cloudDriverService.getServerGroupFromCluster(app, account, cluster, serverGroup, region, "aws") >> response + 1 * cloudDriverService.getByAmiId("aws", account, region, sourceImage) >> sourceResponse + 1 * cloudDriverService.getByAmiId("aws", account, region, targetImage) >> targetResponse when: def result = task.execute(stage) @@ -512,10 +502,10 @@ class GetCommitsTaskSpec extends Specification { def "return success if there is no ancestor asg"() { given: String katoTasks = "[{\"resultObjects\": [" + - "{\"messages\" : [ ], \"serverGroupNameByRegion\": {\"${region}\": \"${targetServerGroup}\"},\"serverGroupNames\": [\"${region}:${targetServerGroup}\"]}],\"status\": {\"completed\": true,\"failed\": false}}]" + "{\"messages\" : [ ], \"serverGroupNameByRegion\": {\"${region}\": \"${targetServerGroup}\"},\"serverGroupNames\": [\"${region}:${targetServerGroup}\"]}],\"status\": {\"completed\": true,\"failed\": false}}]" def katoMap = getObjectMapper().readValue(katoTasks, List) def contextMap = [application: app, account: account, - source : [asgName: serverGroup, region: region, account: account], "deploy.server.groups": ["us-west-1": [targetServerGroup]], deploymentDetails: [[ami: "ami-foo", region: "us-east-1"], [ami: targetImageName, imageId: targetImage, region: region]], "kato.tasks": katoMap] + source: [asgName: serverGroup, region: region, account: account], "deploy.server.groups": ["us-west-1": [targetServerGroup]], deploymentDetails: [[ami: "ami-foo", region: "us-east-1"], [ami: targetImageName, imageId: targetImage, region: region]], "kato.tasks": katoMap] def stage = setupGetCommits(contextMap, account, app, sourceImage, targetImage, region, cluster, serverGroup, 0, 0) when: @@ -576,14 +566,14 @@ class GetCommitsTaskSpec extends Specification { def "add the ancestor and target build info to the result"() { given: String katoTasks = "[{\"resultObjects\": [" + - "{\"ancestorServerGroupNameByRegion\": { \"${region}\":\"${serverGroup}\"}}," + - "{\"messages\" : [ ], \"serverGroupNameByRegion\": {\"${region}\": \"${targetServerGroup}\"},\"serverGroupNames\": [\"${region}:${targetServerGroup}\"]}],\"status\": {\"completed\": true,\"failed\": false}}]" + "{\"ancestorServerGroupNameByRegion\": { \"${region}\":\"${serverGroup}\"}}," + + "{\"messages\" : [ ], \"serverGroupNameByRegion\": {\"${region}\": \"${targetServerGroup}\"},\"serverGroupNames\": [\"${region}:${targetServerGroup}\"]}],\"status\": {\"completed\": true,\"failed\": false}}]" def katoMap = getObjectMapper().readValue(katoTasks, List) - def contextMap = [application : app, - account : account, - source : [region: region, account: account], + def contextMap = [application: app, + account: account, + source: [region: region, account: account], deploymentDetails: [[imageId: targetImage, ami: targetImageName, region: region]], - "kato.tasks" : katoMap] + "kato.tasks": katoMap] def stage = setupGetCommits(contextMap, account, app, sourceImage, targetImage, region, cluster, serverGroup) when: @@ -612,11 +602,11 @@ class GetCommitsTaskSpec extends Specification { def "get commits from parent pipelines"() { given: String katoTasks = "[{\"resultObjects\": [" + - "{\"ancestorServerGroupNameByRegion\": { \"${region}\":\"${serverGroup}\"}}," + - "{\"messages\" : [ ], \"serverGroupNameByRegion\": {\"${region}\": \"${targetServerGroup}\"},\"serverGroupNames\": [\"${region}:${targetServerGroup}\"]}],\"status\": {\"completed\": true,\"failed\": false}}]" + "{\"ancestorServerGroupNameByRegion\": { \"${region}\":\"${serverGroup}\"}}," + + "{\"messages\" : [ ], \"serverGroupNameByRegion\": {\"${region}\": \"${targetServerGroup}\"},\"serverGroupNames\": [\"${region}:${targetServerGroup}\"]}],\"status\": {\"completed\": true,\"failed\": false}}]" def katoMap = getObjectMapper().readValue(katoTasks, List) def contextMap = [application: app, account: account, - source : [asgName: serverGroup, region: region, account: account], "deploy.server.groups": ["us-west-1": [targetServerGroup]], "kato.tasks": katoMap] + source: [asgName: serverGroup, region: region, account: account], "deploy.server.groups": ["us-west-1": [targetServerGroup]], "kato.tasks": katoMap] def parentPipeline = ExecutionBuilder.pipeline { name = "parentPipeline" } def childPipeline = ExecutionBuilder.pipeline {