{"action":"created","comment":{"url":"https://api.github.com/repos/spinnaker/clouddriver/pulls/comments/70304693","id":70304693,"diff_hunk":"@@ -0,0 +1,271 @@\n+/*\n+ * Copyright 2016 Netflix, Inc.\n+ *\n+ * Licensed under the Apache License, Version 2.0 (the \"License\")\n+ * you may not use this file except in compliance with the License.\n+ * You may obtain a copy of the License at\n+ *\n+ *   http://www.apache.org/licenses/LICENSE-2.0\n+ *\n+ * Unless required by applicable law or agreed to in writing, software\n+ * distributed under the License is distributed on an \"AS IS\" BASIS,\n+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n+ * See the License for the specific language governing permissions and\n+ * limitations under the License.\n+ */\n+\n+package com.netflix.spinnaker.clouddriver.aws.deploy.handlers;\n+\n+import com.amazonaws.services.autoscaling.model.AutoScalingGroup;\n+import com.amazonaws.services.autoscaling.model.LaunchConfiguration;\n+import com.amazonaws.services.autoscaling.model.SuspendedProcess;\n+import com.netflix.frigga.Names;\n+import com.netflix.spinnaker.clouddriver.aws.AwsConfiguration.DeployDefaults;\n+import com.netflix.spinnaker.clouddriver.aws.deploy.description.BasicAmazonDeployDescription;\n+import com.netflix.spinnaker.clouddriver.aws.deploy.description.BasicAmazonDeployDescription.Capacity;\n+import com.netflix.spinnaker.clouddriver.aws.deploy.description.BasicAmazonDeployDescription.Source;\n+import com.netflix.spinnaker.clouddriver.aws.deploy.ops.loadbalancer.LoadBalancerMigrator;\n+import com.netflix.spinnaker.clouddriver.aws.deploy.ops.loadbalancer.LoadBalancerMigrator.LoadBalancerLocation;\n+import com.netflix.spinnaker.clouddriver.aws.deploy.ops.loadbalancer.MigrateLoadBalancerResult;\n+import com.netflix.spinnaker.clouddriver.aws.deploy.ops.securitygroup.MigrateSecurityGroupResult;\n+import com.netflix.spinnaker.clouddriver.aws.deploy.ops.securitygroup.SecurityGroupLookupFactory.SecurityGroupLookup;\n+import com.netflix.spinnaker.clouddriver.aws.deploy.ops.securitygroup.SecurityGroupMigrator;\n+import com.netflix.spinnaker.clouddriver.aws.deploy.ops.securitygroup.SecurityGroupMigrator.SecurityGroupLocation;\n+import com.netflix.spinnaker.clouddriver.aws.deploy.ops.servergroup.MigrateServerGroupResult;\n+import com.netflix.spinnaker.clouddriver.aws.deploy.ops.servergroup.ServerGroupMigrator.ServerGroupLocation;\n+import com.netflix.spinnaker.clouddriver.aws.security.AmazonClientProvider;\n+import com.netflix.spinnaker.clouddriver.aws.services.AsgService;\n+import com.netflix.spinnaker.clouddriver.aws.services.RegionScopedProviderFactory;\n+import com.netflix.spinnaker.clouddriver.deploy.DeploymentResult;\n+\n+import java.util.*;\n+import java.util.stream.Collectors;\n+\n+public abstract class MigrateServerGroupStrategy {\n+\n+  protected SecurityGroupLookup sourceLookup;\n+  protected SecurityGroupLookup targetLookup;\n+  protected MigrateSecurityGroupStrategy migrateSecurityGroupStrategy;\n+  protected MigrateLoadBalancerStrategy getMigrateLoadBalancerStrategy;\n+\n+  abstract AmazonClientProvider getAmazonClientProvider();\n+\n+  abstract RegionScopedProviderFactory getRegionScopedProviderFactory();\n+\n+  abstract DeployDefaults getDeployDefaults();\n+\n+  abstract BasicAmazonDeployHandler getBasicAmazonDeployHandler();\n+\n+\n+  /**\n+   * Migrates a server group and its associated load balancers and security groups from one location to another\n+   *\n+   * @param source                       the source server group\n+   * @param target                       the target location in which to migrate\n+   * @param sourceLookup                 a security group lookup cache for the source region\n+   * @param targetLookup                 a security group lookup cache for the target region (may be the same object as the sourceLookup)\n+   * @param migrateLoadBalancerStrategy  the load balancer migration strategy\n+   * @param migrateSecurityGroupStrategy the security group migration strategy\n+   * @param subnetType                   the subnetType in which to migrate the server group (should be null for EC Classic migrations)\n+   * @param iamRole                      the iamRole to use when migrating (optional)\n+   * @param keyPair                      the keyPair to use when migrating (optional)\n+   * @param targetAmi                    the target imageId to use when migrating (optional)\n+   * @param dryRun                       whether to perform the migration or simply calculate the migration\n+   * @return a result set indicating the components required to perform the migration (if a dry run), or the objects\n+   * updated by the migration (if not a dry run)\n+   */\n+  public MigrateServerGroupResult generateResults(ServerGroupLocation source, ServerGroupLocation target,\n+                                                  SecurityGroupLookup sourceLookup, SecurityGroupLookup targetLookup,\n+                                                  MigrateLoadBalancerStrategy migrateLoadBalancerStrategy,\n+                                                  MigrateSecurityGroupStrategy migrateSecurityGroupStrategy,\n+                                                  String subnetType, String iamRole, String keyPair, String targetAmi,\n+                                                  boolean dryRun) {\n+\n+    this.sourceLookup = sourceLookup;\n+    this.targetLookup = targetLookup;\n+    this.migrateSecurityGroupStrategy = migrateSecurityGroupStrategy;\n+    this.getMigrateLoadBalancerStrategy = migrateLoadBalancerStrategy;\n+\n+    AsgService asgService = getRegionScopedProviderFactory().forRegion(source.getCredentials(), source.getRegion())\n+      .getAsgService();\n+\n+    AutoScalingGroup sourceGroup = asgService.getAutoScalingGroup(source.getName());\n+\n+    if (sourceGroup == null) {\n+      throw new IllegalStateException(\"Error retrieving source server group: \" + source.getName());\n+    }\n+\n+    LaunchConfiguration launchConfig = asgService.getLaunchConfiguration(sourceGroup.getLaunchConfigurationName());\n+\n+    if (launchConfig == null) {\n+      throw new IllegalStateException(\"Could not find launch config: \" + sourceGroup.getLaunchConfigurationName());\n+    }\n+\n+    Names names = Names.parseName(source.getName());\n+\n+    List<MigrateLoadBalancerResult> targetLoadBalancers = generateTargetLoadBalancers(\n+      sourceGroup, source, target, subnetType, dryRun);\n+\n+    MigrateServerGroupResult migrateResult = new MigrateServerGroupResult();\n+\n+    List<MigrateSecurityGroupResult> targetSecurityGroups = generateTargetSecurityGroups(launchConfig, source,  target,\n+      migrateResult, dryRun);\n+\n+    Map<String, List<String>> zones = new HashMap<>();\n+    zones.put(target.getRegion(), target.getAvailabilityZones());\n+\n+    DeploymentResult result;\n+    if (!dryRun) {\n+      Capacity capacity = getCapacity();\n+      BasicAmazonDeployDescription deployDescription = new BasicAmazonDeployDescription();\n+      deployDescription.setSource(getSource(source));\n+      deployDescription.setCredentials(target.getCredentials());\n+      deployDescription.setAmiName(targetAmi != null ? targetAmi : launchConfig.getImageId());\n+      deployDescription.setApplication(names.getApp());\n+      deployDescription.setStack(names.getStack());\n+      deployDescription.setFreeFormDetails(names.getDetail());\n+      deployDescription.setInstanceMonitoring(launchConfig.getInstanceMonitoring().getEnabled());\n+      deployDescription.setInstanceType(launchConfig.getInstanceType());\n+      deployDescription.setIamRole(iamRole != null ? iamRole : launchConfig.getIamInstanceProfile());\n+      deployDescription.setKeyPair(keyPair != null ? keyPair : launchConfig.getKeyName());\n+      deployDescription.setAssociatePublicIpAddress(launchConfig.getAssociatePublicIpAddress());\n+      deployDescription.setCooldown(sourceGroup.getDefaultCooldown());\n+      deployDescription.setHealthCheckGracePeriod(sourceGroup.getHealthCheckGracePeriod());\n+      deployDescription.setHealthCheckType(sourceGroup.getHealthCheckType());\n+      deployDescription.setSuspendedProcesses(sourceGroup.getSuspendedProcesses().stream()\n+        .map(SuspendedProcess::getProcessName).collect(Collectors.toSet()));\n+      deployDescription.setTerminationPolicies(sourceGroup.getTerminationPolicies());\n+      deployDescription.setKernelId(launchConfig.getKernelId());\n+      deployDescription.setEbsOptimized(launchConfig.getEbsOptimized());\n+      deployDescription.setBase64UserData(launchConfig.getUserData());\n+      deployDescription.setLoadBalancers(targetLoadBalancers.stream()\n+        .map(MigrateLoadBalancerResult::getTargetName).collect(Collectors.toList()));\n+      deployDescription.setSecurityGroups(targetSecurityGroups.stream()\n+        .map(sg -> sg.getTarget().getTargetName()).collect(Collectors.toList()));\n+      deployDescription.setAvailabilityZones(zones);\n+      deployDescription.setStartDisabled(true);\n+      deployDescription.setCapacity(capacity);\n+      deployDescription.setSubnetType(subnetType);\n+\n+      BasicAmazonDeployDescription description = generateDescription(source, deployDescription);\n+\n+      result = getBasicAmazonDeployHandler().handle(description, new ArrayList());\n+    } else {\n+      result = new DeploymentResult();\n+      String targetName = getRegionScopedProviderFactory().forRegion(target.getCredentials(), target.getRegion())\n+        .getAWSServerGroupNameResolver()\n+        .resolveNextServerGroupName(names.getApp(), names.getStack(), names.getDetail(), false);\n+\n+      result.setServerGroupNames(Collections.singletonList(targetName));\n+    }\n+    migrateResult.setServerGroupName(result.getServerGroupNames().get(0));\n+    migrateResult.setLoadBalancers(targetLoadBalancers);\n+    migrateResult.setSecurityGroups(targetSecurityGroups);\n+    return migrateResult;\n+  }\n+\n+  private BasicAmazonDeployDescription generateDescription(ServerGroupLocation source,\n+                                                           BasicAmazonDeployDescription deployDescription) {\n+    return getBasicAmazonDeployHandler().copySourceAttributes(\n+      getRegionScopedProviderFactory().forRegion(source.getCredentials(), source.getRegion()), source.getName(),\n+      false, deployDescription);\n+  }\n+\n+  private static Source getSource(ServerGroupLocation source) {\n+    Source deploySource = new Source();\n+    deploySource.setAccount(source.getCredentialAccount());\n+    deploySource.setRegion(source.getRegion());\n+    deploySource.setAsgName(source.getName());\n+    return deploySource;\n+  }\n+\n+  private static Capacity getCapacity() {\n+    Capacity capacity = new Capacity();\n+    capacity.setMin(0);\n+    capacity.setMax(0);\n+    capacity.setDesired(0);\n+    return capacity;\n+  }\n+\n+  protected List<MigrateSecurityGroupResult> generateTargetSecurityGroups(LaunchConfiguration sourceLaunchConfig,\n+                                                                          ServerGroupLocation source,\n+                                                                          ServerGroupLocation target,\n+                                                                          MigrateServerGroupResult result,\n+                                                                          boolean dryRun) {\n+\n+    sourceLaunchConfig.getSecurityGroups().stream()\n+      .filter(g -> !sourceLookup.getSecurityGroupById(source.getCredentialAccount(), g, source.getVpcId()).isPresent())\n+      .forEach(m -> result.getWarnings().add(\"Skipping creation of security group: \" + m\n+        + \" (could not be found in source location)\"));\n+\n+    List<String> securityGroupNames = sourceLaunchConfig.getSecurityGroups().stream()\n+      .filter(g -> sourceLookup.getSecurityGroupById(source.getCredentialAccount(), g, source.getVpcId()).isPresent())\n+      .map(g -> sourceLookup.getSecurityGroupById(source.getCredentialAccount(), g, source.getVpcId()).get())\n+      .map(g -> g.getSecurityGroup().getGroupName())\n+      .collect(Collectors.toList());\n+\n+    List<MigrateSecurityGroupResult> targetSecurityGroups = securityGroupNames.stream().map(group ->\n+      getMigrateSecurityGroupResult(source, target, sourceLookup, targetLookup, dryRun, group)\n+    ).collect(Collectors.toList());\n+\n+    if (getDeployDefaults().getAddAppGroupToServerGroup()) {","path":"clouddriver-aws/src/main/groovy/com/netflix/spinnaker/clouddriver/aws/deploy/handlers/MigrateServerGroupStrategy.java","position":211,"original_position":211,"commit_id":"ae5b3e75d098d5e6d49c12bfc42a42ead1891864","original_commit_id":"ae5b3e75d098d5e6d49c12bfc42a42ead1891864","user":{"login":"cfieber","id":301292,"avatar_url":"https://avatars.githubusercontent.com/u/301292?v=3","gravatar_id":"","url":"https://api.github.com/users/cfieber","html_url":"https://github.com/cfieber","followers_url":"https://api.github.com/users/cfieber/followers","following_url":"https://api.github.com/users/cfieber/following{/other_user}","gists_url":"https://api.github.com/users/cfieber/gists{/gist_id}","starred_url":"https://api.github.com/users/cfieber/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cfieber/subscriptions","organizations_url":"https://api.github.com/users/cfieber/orgs","repos_url":"https://api.github.com/users/cfieber/repos","events_url":"https://api.github.com/users/cfieber/events{/privacy}","received_events_url":"https://api.github.com/users/cfieber/received_events","type":"User","site_admin":false},"body":"creation of this group will happen automatically during the deploy\r\n\r\nI guess the case this would handle if the source group exists but hasn't already been attached to the source asg to ensure that the source rules ended up on the target when it was created. Not sure if that is a case we would encounter or not though","created_at":"2016-07-11T17:51:40Z","updated_at":"2016-07-11T17:51:40Z","html_url":"https://github.com/spinnaker/clouddriver/pull/748#discussion_r70304693","pull_request_url":"https://api.github.com/repos/spinnaker/clouddriver/pulls/748","_links":{"self":{"href":"https://api.github.com/repos/spinnaker/clouddriver/pulls/comments/70304693"},"html":{"href":"https://github.com/spinnaker/clouddriver/pull/748#discussion_r70304693"},"pull_request":{"href":"https://api.github.com/repos/spinnaker/clouddriver/pulls/748"}}},"pull_request":{"url":"https://api.github.com/repos/spinnaker/clouddriver/pulls/748","id":76830253,"html_url":"https://github.com/spinnaker/clouddriver/pull/748","diff_url":"https://github.com/spinnaker/clouddriver/pull/748.diff","patch_url":"https://github.com/spinnaker/clouddriver/pull/748.patch","issue_url":"https://api.github.com/repos/spinnaker/clouddriver/issues/748","number":748,"state":"open","locked":false,"title":"(aws) migrate server group support","user":{"login":"anotherchrisberry","id":73450,"avatar_url":"https://avatars.githubusercontent.com/u/73450?v=3","gravatar_id":"","url":"https://api.github.com/users/anotherchrisberry","html_url":"https://github.com/anotherchrisberry","followers_url":"https://api.github.com/users/anotherchrisberry/followers","following_url":"https://api.github.com/users/anotherchrisberry/following{/other_user}","gists_url":"https://api.github.com/users/anotherchrisberry/gists{/gist_id}","starred_url":"https://api.github.com/users/anotherchrisberry/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/anotherchrisberry/subscriptions","organizations_url":"https://api.github.com/users/anotherchrisberry/orgs","repos_url":"https://api.github.com/users/anotherchrisberry/repos","events_url":"https://api.github.com/users/anotherchrisberry/events{/privacy}","received_events_url":"https://api.github.com/users/anotherchrisberry/received_events","type":"User","site_admin":false},"body":"Part 3 of 4 in the AWS migration series","created_at":"2016-07-09T00:04:07Z","updated_at":"2016-07-11T17:51:40Z","closed_at":null,"merged_at":null,"merge_commit_sha":"25b7a91480cda5d1b96e2f61d91dbb439c6867a1","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/spinnaker/clouddriver/pulls/748/commits","review_comments_url":"https://api.github.com/repos/spinnaker/clouddriver/pulls/748/comments","review_comment_url":"https://api.github.com/repos/spinnaker/clouddriver/pulls/comments{/number}","comments_url":"https://api.github.com/repos/spinnaker/clouddriver/issues/748/comments","statuses_url":"https://api.github.com/repos/spinnaker/clouddriver/statuses/ae5b3e75d098d5e6d49c12bfc42a42ead1891864","head":{"label":"anotherchrisberry:migrate-server-group","ref":"migrate-server-group","sha":"ae5b3e75d098d5e6d49c12bfc42a42ead1891864","user":{"login":"anotherchrisberry","id":73450,"avatar_url":"https://avatars.githubusercontent.com/u/73450?v=3","gravatar_id":"","url":"https://api.github.com/users/anotherchrisberry","html_url":"https://github.com/anotherchrisberry","followers_url":"https://api.github.com/users/anotherchrisberry/followers","following_url":"https://api.github.com/users/anotherchrisberry/following{/other_user}","gists_url":"https://api.github.com/users/anotherchrisberry/gists{/gist_id}","starred_url":"https://api.github.com/users/anotherchrisberry/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/anotherchrisberry/subscriptions","organizations_url":"https://api.github.com/users/anotherchrisberry/orgs","repos_url":"https://api.github.com/users/anotherchrisberry/repos","events_url":"https://api.github.com/users/anotherchrisberry/events{/privacy}","received_events_url":"https://api.github.com/users/anotherchrisberry/received_events","type":"User","site_admin":false},"repo":{"id":47797368,"name":"clouddriver","full_name":"anotherchrisberry/clouddriver","owner":{"login":"anotherchrisberry","id":73450,"avatar_url":"https://avatars.githubusercontent.com/u/73450?v=3","gravatar_id":"","url":"https://api.github.com/users/anotherchrisberry","html_url":"https://github.com/anotherchrisberry","followers_url":"https://api.github.com/users/anotherchrisberry/followers","following_url":"https://api.github.com/users/anotherchrisberry/following{/other_user}","gists_url":"https://api.github.com/users/anotherchrisberry/gists{/gist_id}","starred_url":"https://api.github.com/users/anotherchrisberry/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/anotherchrisberry/subscriptions","organizations_url":"https://api.github.com/users/anotherchrisberry/orgs","repos_url":"https://api.github.com/users/anotherchrisberry/repos","events_url":"https://api.github.com/users/anotherchrisberry/events{/privacy}","received_events_url":"https://api.github.com/users/anotherchrisberry/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/anotherchrisberry/clouddriver","description":"read and write operations across cloud providers","fork":true,"url":"https://api.github.com/repos/anotherchrisberry/clouddriver","forks_url":"https://api.github.com/repos/anotherchrisberry/clouddriver/forks","keys_url":"https://api.github.com/repos/anotherchrisberry/clouddriver/keys{/key_id}","collaborators_url":"https://api.github.com/repos/anotherchrisberry/clouddriver/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/anotherchrisberry/clouddriver/teams","hooks_url":"https://api.github.com/repos/anotherchrisberry/clouddriver/hooks","issue_events_url":"https://api.github.com/repos/anotherchrisberry/clouddriver/issues/events{/number}","events_url":"https://api.github.com/repos/anotherchrisberry/clouddriver/events","assignees_url":"https://api.github.com/repos/anotherchrisberry/clouddriver/assignees{/user}","branches_url":"https://api.github.com/repos/anotherchrisberry/clouddriver/branches{/branch}","tags_url":"https://api.github.com/repos/anotherchrisberry/clouddriver/tags","blobs_url":"https://api.github.com/repos/anotherchrisberry/clouddriver/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/anotherchrisberry/clouddriver/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/anotherchrisberry/clouddriver/git/refs{/sha}","trees_url":"https://api.github.com/repos/anotherchrisberry/clouddriver/git/trees{/sha}","statuses_url":"https://api.github.com/repos/anotherchrisberry/clouddriver/statuses/{sha}","languages_url":"https://api.github.com/repos/anotherchrisberry/clouddriver/languages","stargazers_url":"https://api.github.com/repos/anotherchrisberry/clouddriver/stargazers","contributors_url":"https://api.github.com/repos/anotherchrisberry/clouddriver/contributors","subscribers_url":"https://api.github.com/repos/anotherchrisberry/clouddriver/subscribers","subscription_url":"https://api.github.com/repos/anotherchrisberry/clouddriver/subscription","commits_url":"https://api.github.com/repos/anotherchrisberry/clouddriver/commits{/sha}","git_commits_url":"https://api.github.com/repos/anotherchrisberry/clouddriver/git/commits{/sha}","comments_url":"https://api.github.com/repos/anotherchrisberry/clouddriver/comments{/number}","issue_comment_url":"https://api.github.com/repos/anotherchrisberry/clouddriver/issues/comments{/number}","contents_url":"https://api.github.com/repos/anotherchrisberry/clouddriver/contents/{+path}","compare_url":"https://api.github.com/repos/anotherchrisberry/clouddriver/compare/{base}...{head}","merges_url":"https://api.github.com/repos/anotherchrisberry/clouddriver/merges","archive_url":"https://api.github.com/repos/anotherchrisberry/clouddriver/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/anotherchrisberry/clouddriver/downloads","issues_url":"https://api.github.com/repos/anotherchrisberry/clouddriver/issues{/number}","pulls_url":"https://api.github.com/repos/anotherchrisberry/clouddriver/pulls{/number}","milestones_url":"https://api.github.com/repos/anotherchrisberry/clouddriver/milestones{/number}","notifications_url":"https://api.github.com/repos/anotherchrisberry/clouddriver/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/anotherchrisberry/clouddriver/labels{/name}","releases_url":"https://api.github.com/repos/anotherchrisberry/clouddriver/releases{/id}","deployments_url":"https://api.github.com/repos/anotherchrisberry/clouddriver/deployments","created_at":"2015-12-11T01:21:48Z","updated_at":"2016-04-07T04:06:29Z","pushed_at":"2016-07-09T00:02:16Z","git_url":"git://github.com/anotherchrisberry/clouddriver.git","ssh_url":"git@github.com:anotherchrisberry/clouddriver.git","clone_url":"https://github.com/anotherchrisberry/clouddriver.git","svn_url":"https://github.com/anotherchrisberry/clouddriver","homepage":null,"size":27161,"stargazers_count":0,"watchers_count":0,"language":"Groovy","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"spinnaker:master","ref":"master","sha":"48eb169faa588e089da8da2f0aedc6b3238ad2dd","user":{"login":"spinnaker","id":7634182,"avatar_url":"https://avatars.githubusercontent.com/u/7634182?v=3","gravatar_id":"","url":"https://api.github.com/users/spinnaker","html_url":"https://github.com/spinnaker","followers_url":"https://api.github.com/users/spinnaker/followers","following_url":"https://api.github.com/users/spinnaker/following{/other_user}","gists_url":"https://api.github.com/users/spinnaker/gists{/gist_id}","starred_url":"https://api.github.com/users/spinnaker/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/spinnaker/subscriptions","organizations_url":"https://api.github.com/users/spinnaker/orgs","repos_url":"https://api.github.com/users/spinnaker/repos","events_url":"https://api.github.com/users/spinnaker/events{/privacy}","received_events_url":"https://api.github.com/users/spinnaker/received_events","type":"Organization","site_admin":false},"repo":{"id":37556951,"name":"clouddriver","full_name":"spinnaker/clouddriver","owner":{"login":"spinnaker","id":7634182,"avatar_url":"https://avatars.githubusercontent.com/u/7634182?v=3","gravatar_id":"","url":"https://api.github.com/users/spinnaker","html_url":"https://github.com/spinnaker","followers_url":"https://api.github.com/users/spinnaker/followers","following_url":"https://api.github.com/users/spinnaker/following{/other_user}","gists_url":"https://api.github.com/users/spinnaker/gists{/gist_id}","starred_url":"https://api.github.com/users/spinnaker/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/spinnaker/subscriptions","organizations_url":"https://api.github.com/users/spinnaker/orgs","repos_url":"https://api.github.com/users/spinnaker/repos","events_url":"https://api.github.com/users/spinnaker/events{/privacy}","received_events_url":"https://api.github.com/users/spinnaker/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/spinnaker/clouddriver","description":"read and write operations across cloud providers","fork":false,"url":"https://api.github.com/repos/spinnaker/clouddriver","forks_url":"https://api.github.com/repos/spinnaker/clouddriver/forks","keys_url":"https://api.github.com/repos/spinnaker/clouddriver/keys{/key_id}","collaborators_url":"https://api.github.com/repos/spinnaker/clouddriver/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/spinnaker/clouddriver/teams","hooks_url":"https://api.github.com/repos/spinnaker/clouddriver/hooks","issue_events_url":"https://api.github.com/repos/spinnaker/clouddriver/issues/events{/number}","events_url":"https://api.github.com/repos/spinnaker/clouddriver/events","assignees_url":"https://api.github.com/repos/spinnaker/clouddriver/assignees{/user}","branches_url":"https://api.github.com/repos/spinnaker/clouddriver/branches{/branch}","tags_url":"https://api.github.com/repos/spinnaker/clouddriver/tags","blobs_url":"https://api.github.com/repos/spinnaker/clouddriver/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/spinnaker/clouddriver/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/spinnaker/clouddriver/git/refs{/sha}","trees_url":"https://api.github.com/repos/spinnaker/clouddriver/git/trees{/sha}","statuses_url":"https://api.github.com/repos/spinnaker/clouddriver/statuses/{sha}","languages_url":"https://api.github.com/repos/spinnaker/clouddriver/languages","stargazers_url":"https://api.github.com/repos/spinnaker/clouddriver/stargazers","contributors_url":"https://api.github.com/repos/spinnaker/clouddriver/contributors","subscribers_url":"https://api.github.com/repos/spinnaker/clouddriver/subscribers","subscription_url":"https://api.github.com/repos/spinnaker/clouddriver/subscription","commits_url":"https://api.github.com/repos/spinnaker/clouddriver/commits{/sha}","git_commits_url":"https://api.github.com/repos/spinnaker/clouddriver/git/commits{/sha}","comments_url":"https://api.github.com/repos/spinnaker/clouddriver/comments{/number}","issue_comment_url":"https://api.github.com/repos/spinnaker/clouddriver/issues/comments{/number}","contents_url":"https://api.github.com/repos/spinnaker/clouddriver/contents/{+path}","compare_url":"https://api.github.com/repos/spinnaker/clouddriver/compare/{base}...{head}","merges_url":"https://api.github.com/repos/spinnaker/clouddriver/merges","archive_url":"https://api.github.com/repos/spinnaker/clouddriver/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/spinnaker/clouddriver/downloads","issues_url":"https://api.github.com/repos/spinnaker/clouddriver/issues{/number}","pulls_url":"https://api.github.com/repos/spinnaker/clouddriver/pulls{/number}","milestones_url":"https://api.github.com/repos/spinnaker/clouddriver/milestones{/number}","notifications_url":"https://api.github.com/repos/spinnaker/clouddriver/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/spinnaker/clouddriver/labels{/name}","releases_url":"https://api.github.com/repos/spinnaker/clouddriver/releases{/id}","deployments_url":"https://api.github.com/repos/spinnaker/clouddriver/deployments","created_at":"2015-06-16T21:26:02Z","updated_at":"2016-07-08T19:16:29Z","pushed_at":"2016-07-11T17:44:42Z","git_url":"git://github.com/spinnaker/clouddriver.git","ssh_url":"git@github.com:spinnaker/clouddriver.git","clone_url":"https://github.com/spinnaker/clouddriver.git","svn_url":"https://github.com/spinnaker/clouddriver","homepage":null,"size":29375,"stargazers_count":55,"watchers_count":55,"language":"Groovy","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":82,"mirror_url":null,"open_issues_count":10,"forks":82,"open_issues":10,"watchers":55,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/spinnaker/clouddriver/pulls/748"},"html":{"href":"https://github.com/spinnaker/clouddriver/pull/748"},"issue":{"href":"https://api.github.com/repos/spinnaker/clouddriver/issues/748"},"comments":{"href":"https://api.github.com/repos/spinnaker/clouddriver/issues/748/comments"},"review_comments":{"href":"https://api.github.com/repos/spinnaker/clouddriver/pulls/748/comments"},"review_comment":{"href":"https://api.github.com/repos/spinnaker/clouddriver/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/spinnaker/clouddriver/pulls/748/commits"},"statuses":{"href":"https://api.github.com/repos/spinnaker/clouddriver/statuses/ae5b3e75d098d5e6d49c12bfc42a42ead1891864"}}}}
{"actor":{"display_login":"cfieber"}}