{"action":"created","comment":{"url":"https://api.github.com/repos/spinnaker/orca/pulls/comments/72653903","id":72653903,"diff_hunk":"@@ -0,0 +1,150 @@\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.orca.clouddriver.tasks.providers.aws;\n+\n+import com.fasterxml.jackson.databind.ObjectMapper;\n+import com.google.common.collect.ImmutableMap;\n+import com.netflix.spinnaker.orca.clouddriver.OortService;\n+import com.netflix.spinnaker.orca.clouddriver.tasks.image.MachineImageTagger;\n+import com.netflix.spinnaker.orca.clouddriver.utils.CloudProviderAware;\n+import com.netflix.spinnaker.orca.pipeline.model.Stage;\n+import org.springframework.beans.factory.annotation.Autowired;\n+import org.springframework.beans.factory.annotation.Value;\n+import org.springframework.stereotype.Component;\n+\n+import java.util.*;\n+import java.util.concurrent.atomic.AtomicBoolean;\n+\n+import static java.lang.String.format;\n+\n+@Component\n+public class AmazonMachineImageTagger implements MachineImageTagger, CloudProviderAware {\n+  private static final String ALLOW_LAUNCH_OPERATION = \"allowLaunchDescription\";\n+\n+  @Autowired\n+  OortService oortService;\n+\n+  @Autowired\n+  ObjectMapper objectMapper;\n+\n+  @Value(\"${default.bake.account:default}\")\n+  String defaultBakeAccount;\n+\n+  @Override\n+  public MachineImageTagger.OperationContext getOperationContext(Stage stage) {\n+    StageData stageData = (StageData) stage.mapTo(StageData.class);\n+\n+    MatchedImage matchedImage = findImage(stageData.amiName);\n+    if (stageData.regions == null || stageData.regions.isEmpty()) {\n+      stageData.regions = matchedImage.amis.keySet();\n+    }\n+\n+    MachineImage targetMachineImage = new MachineImage(\n+      stageData.amiName,\n+      defaultBakeAccount,\n+      stageData.regions,\n+      stageData.tags\n+    );\n+\n+    List<Map<String, Map>> operations = new ArrayList<>();\n+\n+    // Update the tags on the image in the `defaultBakeAccount`\n+    operations.add(\n+      ImmutableMap.<String, Map>builder()\n+        .put(OPERATION, ImmutableMap.builder()\n+          .put(\"amiName\", targetMachineImage.imageName)\n+          .put(\"tags\", targetMachineImage.tags)\n+          .put(\"regions\", targetMachineImage.regions)\n+          .put(\"credentials\", targetMachineImage.account)\n+          .build()\n+        ).build()\n+    );\n+\n+    // Re-share the image in all other accounts (will result in tags being updated)\n+    matchedImage.accounts.stream()\n+      .filter(account -> !account.equalsIgnoreCase(defaultBakeAccount))\n+      .forEach(account -> {\n+        stageData.regions.forEach(region ->\n+          operations.add(\n+            ImmutableMap.<String, Map>builder()\n+              .put(ALLOW_LAUNCH_OPERATION, ImmutableMap.builder()\n+                .put(\"account\", account)\n+                .put(\"credentials\", defaultBakeAccount)\n+                .put(\"region\", region)\n+                .put(\"amiName\", stageData.amiName)\n+                .build()\n+              ).build()\n+          )\n+        );\n+      });\n+\n+    Map<String, Object> extraOutput = objectMapper.convertValue(stageData, Map.class);\n+    extraOutput.put(\"target\", targetMachineImage);\n+    return new MachineImageTagger.OperationContext(operations, extraOutput);\n+  }\n+\n+  /**\n+   * Return true iff the tags on the current machine image match the desired.\n+   */\n+  @Override\n+  public boolean isMachineImageTagged(MachineImageTagger.MachineImage targetMachineImage, Stage stage) {\n+    MatchedImage matchedImage = findImage(targetMachineImage.imageName);\n+\n+    AtomicBoolean isUpserted = new AtomicBoolean(true);\n+    targetMachineImage.regions.forEach(region -> {\n+        List<String> imagesForRegion = matchedImage.amis.get(region);\n+        imagesForRegion.forEach(image -> {\n+          Map<String, String> allImageTags = matchedImage.tagsByImageId.get(image);\n+          targetMachineImage.tags.entrySet().forEach(entry -> {\n+            // assert tag equality\n+            isUpserted.set(isUpserted.get() && allImageTags.get(entry.getKey()).equals(entry.getValue()));","path":"orca-clouddriver/src/main/groovy/com/netflix/spinnaker/orca/clouddriver/tasks/providers/aws/AmazonMachineImageTagger.java","position":114,"original_position":114,"commit_id":"a4ee2e5e845167585381d4c1923c86203c07ba33","original_commit_id":"a4ee2e5e845167585381d4c1923c86203c07ba33","user":{"login":"tomaslin","id":74310,"avatar_url":"https://avatars.githubusercontent.com/u/74310?v=3","gravatar_id":"","url":"https://api.github.com/users/tomaslin","html_url":"https://github.com/tomaslin","followers_url":"https://api.github.com/users/tomaslin/followers","following_url":"https://api.github.com/users/tomaslin/following{/other_user}","gists_url":"https://api.github.com/users/tomaslin/gists{/gist_id}","starred_url":"https://api.github.com/users/tomaslin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tomaslin/subscriptions","organizations_url":"https://api.github.com/users/tomaslin/orgs","repos_url":"https://api.github.com/users/tomaslin/repos","events_url":"https://api.github.com/users/tomaslin/events{/privacy}","received_events_url":"https://api.github.com/users/tomaslin/received_events","type":"User","site_admin":false},"body":"would it make sense to have a set of tags that we won't update such as 'appversion' and 'buildhost'?  ","created_at":"2016-07-28T16:20:33Z","updated_at":"2016-07-28T16:20:33Z","html_url":"https://github.com/spinnaker/orca/pull/906#discussion_r72653903","pull_request_url":"https://api.github.com/repos/spinnaker/orca/pulls/906","_links":{"self":{"href":"https://api.github.com/repos/spinnaker/orca/pulls/comments/72653903"},"html":{"href":"https://github.com/spinnaker/orca/pull/906#discussion_r72653903"},"pull_request":{"href":"https://api.github.com/repos/spinnaker/orca/pulls/906"}}},"pull_request":{"url":"https://api.github.com/repos/spinnaker/orca/pulls/906","id":79122687,"html_url":"https://github.com/spinnaker/orca/pull/906","diff_url":"https://github.com/spinnaker/orca/pull/906.diff","patch_url":"https://github.com/spinnaker/orca/pull/906.patch","issue_url":"https://api.github.com/repos/spinnaker/orca/issues/906","number":906,"state":"open","locked":false,"title":"Support for tagging of machine images (AWS-only implementation right …","user":{"login":"ajordens","id":388652,"avatar_url":"https://avatars.githubusercontent.com/u/388652?v=3","gravatar_id":"","url":"https://api.github.com/users/ajordens","html_url":"https://github.com/ajordens","followers_url":"https://api.github.com/users/ajordens/followers","following_url":"https://api.github.com/users/ajordens/following{/other_user}","gists_url":"https://api.github.com/users/ajordens/gists{/gist_id}","starred_url":"https://api.github.com/users/ajordens/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ajordens/subscriptions","organizations_url":"https://api.github.com/users/ajordens/orgs","repos_url":"https://api.github.com/users/ajordens/repos","events_url":"https://api.github.com/users/ajordens/events{/privacy}","received_events_url":"https://api.github.com/users/ajordens/received_events","type":"User","site_admin":false},"body":"…now)","created_at":"2016-07-28T01:00:34Z","updated_at":"2016-07-28T16:20:33Z","closed_at":null,"merged_at":null,"merge_commit_sha":"ae9c37535cad153a0eb9bcc485449db2cde0898e","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/spinnaker/orca/pulls/906/commits","review_comments_url":"https://api.github.com/repos/spinnaker/orca/pulls/906/comments","review_comment_url":"https://api.github.com/repos/spinnaker/orca/pulls/comments{/number}","comments_url":"https://api.github.com/repos/spinnaker/orca/issues/906/comments","statuses_url":"https://api.github.com/repos/spinnaker/orca/statuses/a4ee2e5e845167585381d4c1923c86203c07ba33","head":{"label":"ajordens:upsert-machine-images","ref":"upsert-machine-images","sha":"a4ee2e5e845167585381d4c1923c86203c07ba33","user":{"login":"ajordens","id":388652,"avatar_url":"https://avatars.githubusercontent.com/u/388652?v=3","gravatar_id":"","url":"https://api.github.com/users/ajordens","html_url":"https://github.com/ajordens","followers_url":"https://api.github.com/users/ajordens/followers","following_url":"https://api.github.com/users/ajordens/following{/other_user}","gists_url":"https://api.github.com/users/ajordens/gists{/gist_id}","starred_url":"https://api.github.com/users/ajordens/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ajordens/subscriptions","organizations_url":"https://api.github.com/users/ajordens/orgs","repos_url":"https://api.github.com/users/ajordens/repos","events_url":"https://api.github.com/users/ajordens/events{/privacy}","received_events_url":"https://api.github.com/users/ajordens/received_events","type":"User","site_admin":false},"repo":{"id":63391290,"name":"orca","full_name":"ajordens/orca","owner":{"login":"ajordens","id":388652,"avatar_url":"https://avatars.githubusercontent.com/u/388652?v=3","gravatar_id":"","url":"https://api.github.com/users/ajordens","html_url":"https://github.com/ajordens","followers_url":"https://api.github.com/users/ajordens/followers","following_url":"https://api.github.com/users/ajordens/following{/other_user}","gists_url":"https://api.github.com/users/ajordens/gists{/gist_id}","starred_url":"https://api.github.com/users/ajordens/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ajordens/subscriptions","organizations_url":"https://api.github.com/users/ajordens/orgs","repos_url":"https://api.github.com/users/ajordens/repos","events_url":"https://api.github.com/users/ajordens/events{/privacy}","received_events_url":"https://api.github.com/users/ajordens/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/ajordens/orca","description":"orchestration engine","fork":true,"url":"https://api.github.com/repos/ajordens/orca","forks_url":"https://api.github.com/repos/ajordens/orca/forks","keys_url":"https://api.github.com/repos/ajordens/orca/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ajordens/orca/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ajordens/orca/teams","hooks_url":"https://api.github.com/repos/ajordens/orca/hooks","issue_events_url":"https://api.github.com/repos/ajordens/orca/issues/events{/number}","events_url":"https://api.github.com/repos/ajordens/orca/events","assignees_url":"https://api.github.com/repos/ajordens/orca/assignees{/user}","branches_url":"https://api.github.com/repos/ajordens/orca/branches{/branch}","tags_url":"https://api.github.com/repos/ajordens/orca/tags","blobs_url":"https://api.github.com/repos/ajordens/orca/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ajordens/orca/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ajordens/orca/git/refs{/sha}","trees_url":"https://api.github.com/repos/ajordens/orca/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ajordens/orca/statuses/{sha}","languages_url":"https://api.github.com/repos/ajordens/orca/languages","stargazers_url":"https://api.github.com/repos/ajordens/orca/stargazers","contributors_url":"https://api.github.com/repos/ajordens/orca/contributors","subscribers_url":"https://api.github.com/repos/ajordens/orca/subscribers","subscription_url":"https://api.github.com/repos/ajordens/orca/subscription","commits_url":"https://api.github.com/repos/ajordens/orca/commits{/sha}","git_commits_url":"https://api.github.com/repos/ajordens/orca/git/commits{/sha}","comments_url":"https://api.github.com/repos/ajordens/orca/comments{/number}","issue_comment_url":"https://api.github.com/repos/ajordens/orca/issues/comments{/number}","contents_url":"https://api.github.com/repos/ajordens/orca/contents/{+path}","compare_url":"https://api.github.com/repos/ajordens/orca/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ajordens/orca/merges","archive_url":"https://api.github.com/repos/ajordens/orca/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ajordens/orca/downloads","issues_url":"https://api.github.com/repos/ajordens/orca/issues{/number}","pulls_url":"https://api.github.com/repos/ajordens/orca/pulls{/number}","milestones_url":"https://api.github.com/repos/ajordens/orca/milestones{/number}","notifications_url":"https://api.github.com/repos/ajordens/orca/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ajordens/orca/labels{/name}","releases_url":"https://api.github.com/repos/ajordens/orca/releases{/id}","deployments_url":"https://api.github.com/repos/ajordens/orca/deployments","created_at":"2016-07-15T04:19:37Z","updated_at":"2016-07-15T04:19:43Z","pushed_at":"2016-07-28T01:03:37Z","git_url":"git://github.com/ajordens/orca.git","ssh_url":"git@github.com:ajordens/orca.git","clone_url":"https://github.com/ajordens/orca.git","svn_url":"https://github.com/ajordens/orca","homepage":"","size":6579,"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":"f30d719dcde9b104d05e37c910de795d1cbc7779","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":19834314,"name":"orca","full_name":"spinnaker/orca","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/orca","description":"orchestration engine","fork":false,"url":"https://api.github.com/repos/spinnaker/orca","forks_url":"https://api.github.com/repos/spinnaker/orca/forks","keys_url":"https://api.github.com/repos/spinnaker/orca/keys{/key_id}","collaborators_url":"https://api.github.com/repos/spinnaker/orca/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/spinnaker/orca/teams","hooks_url":"https://api.github.com/repos/spinnaker/orca/hooks","issue_events_url":"https://api.github.com/repos/spinnaker/orca/issues/events{/number}","events_url":"https://api.github.com/repos/spinnaker/orca/events","assignees_url":"https://api.github.com/repos/spinnaker/orca/assignees{/user}","branches_url":"https://api.github.com/repos/spinnaker/orca/branches{/branch}","tags_url":"https://api.github.com/repos/spinnaker/orca/tags","blobs_url":"https://api.github.com/repos/spinnaker/orca/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/spinnaker/orca/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/spinnaker/orca/git/refs{/sha}","trees_url":"https://api.github.com/repos/spinnaker/orca/git/trees{/sha}","statuses_url":"https://api.github.com/repos/spinnaker/orca/statuses/{sha}","languages_url":"https://api.github.com/repos/spinnaker/orca/languages","stargazers_url":"https://api.github.com/repos/spinnaker/orca/stargazers","contributors_url":"https://api.github.com/repos/spinnaker/orca/contributors","subscribers_url":"https://api.github.com/repos/spinnaker/orca/subscribers","subscription_url":"https://api.github.com/repos/spinnaker/orca/subscription","commits_url":"https://api.github.com/repos/spinnaker/orca/commits{/sha}","git_commits_url":"https://api.github.com/repos/spinnaker/orca/git/commits{/sha}","comments_url":"https://api.github.com/repos/spinnaker/orca/comments{/number}","issue_comment_url":"https://api.github.com/repos/spinnaker/orca/issues/comments{/number}","contents_url":"https://api.github.com/repos/spinnaker/orca/contents/{+path}","compare_url":"https://api.github.com/repos/spinnaker/orca/compare/{base}...{head}","merges_url":"https://api.github.com/repos/spinnaker/orca/merges","archive_url":"https://api.github.com/repos/spinnaker/orca/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/spinnaker/orca/downloads","issues_url":"https://api.github.com/repos/spinnaker/orca/issues{/number}","pulls_url":"https://api.github.com/repos/spinnaker/orca/pulls{/number}","milestones_url":"https://api.github.com/repos/spinnaker/orca/milestones{/number}","notifications_url":"https://api.github.com/repos/spinnaker/orca/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/spinnaker/orca/labels{/name}","releases_url":"https://api.github.com/repos/spinnaker/orca/releases{/id}","deployments_url":"https://api.github.com/repos/spinnaker/orca/deployments","created_at":"2014-05-15T20:33:00Z","updated_at":"2016-07-27T09:42:32Z","pushed_at":"2016-07-28T01:03:38Z","git_url":"git://github.com/spinnaker/orca.git","ssh_url":"git@github.com:spinnaker/orca.git","clone_url":"https://github.com/spinnaker/orca.git","svn_url":"https://github.com/spinnaker/orca","homepage":"","size":9653,"stargazers_count":33,"watchers_count":33,"language":"Groovy","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":57,"mirror_url":null,"open_issues_count":49,"forks":57,"open_issues":49,"watchers":33,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/spinnaker/orca/pulls/906"},"html":{"href":"https://github.com/spinnaker/orca/pull/906"},"issue":{"href":"https://api.github.com/repos/spinnaker/orca/issues/906"},"comments":{"href":"https://api.github.com/repos/spinnaker/orca/issues/906/comments"},"review_comments":{"href":"https://api.github.com/repos/spinnaker/orca/pulls/906/comments"},"review_comment":{"href":"https://api.github.com/repos/spinnaker/orca/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/spinnaker/orca/pulls/906/commits"},"statuses":{"href":"https://api.github.com/repos/spinnaker/orca/statuses/a4ee2e5e845167585381d4c1923c86203c07ba33"}}}}
{"actor":{"display_login":"tomaslin"}}