@Override
 public ResourceAction perform(ResourceAction resourceAction) throws Exception {
   AWSEC2VolumeResourceAction action = (AWSEC2VolumeResourceAction) resourceAction;
   ServiceConfiguration configuration = Topology.lookup(Compute.class);
   // Create 'system' tags as admin user
   String effectiveAdminUserId =
       Accounts.lookupPrincipalByAccountNumber(
               Accounts.lookupPrincipalByUserId(action.info.getEffectiveUserId())
                   .getAccountNumber())
           .getUserId();
   CreateTagsType createSystemTagsType =
       MessageHelper.createPrivilegedMessage(CreateTagsType.class, effectiveAdminUserId);
   createSystemTagsType.setResourcesSet(
       Lists.newArrayList(action.info.getPhysicalResourceId()));
   createSystemTagsType.setTagSet(
       EC2Helper.createTagSet(
           TagHelper.getEC2SystemTags(action.info, action.getStackEntity())));
   AsyncRequests.<CreateTagsType, CreateTagsResponseType>sendSync(
       configuration, createSystemTagsType);
   // Create non-system tags as regular user
   List<EC2Tag> tags = TagHelper.getEC2StackTags(action.getStackEntity());
   if (action.properties.getTags() != null && !action.properties.getTags().isEmpty()) {
     TagHelper.checkReservedEC2TemplateTags(action.properties.getTags());
     tags.addAll(action.properties.getTags());
   }
   if (!tags.isEmpty()) {
     CreateTagsType createTagsType =
         MessageHelper.createMessage(CreateTagsType.class, action.info.getEffectiveUserId());
     createTagsType.setResourcesSet(Lists.newArrayList(action.info.getPhysicalResourceId()));
     createTagsType.setTagSet(EC2Helper.createTagSet(tags));
     AsyncRequests.<CreateTagsType, CreateTagsResponseType>sendSync(
         configuration, createTagsType);
   }
   return action;
 }
      @Override
      public ResourceAction perform(
          ResourceAction oldResourceAction, ResourceAction newResourceAction) throws Exception {
        AWSEC2VolumeResourceAction oldAction = (AWSEC2VolumeResourceAction) oldResourceAction;
        AWSEC2VolumeResourceAction newAction = (AWSEC2VolumeResourceAction) newResourceAction;
        ServiceConfiguration configuration = Topology.lookup(Compute.class);
        DescribeTagsType describeTagsType =
            MessageHelper.createMessage(
                DescribeTagsType.class, newAction.info.getEffectiveUserId());
        describeTagsType.setFilterSet(
            Lists.newArrayList(
                Filter.filter("resource-id", newAction.info.getPhysicalResourceId())));
        DescribeTagsResponseType describeTagsResponseType =
            AsyncRequests.sendSync(configuration, describeTagsType);
        Set<EC2Tag> existingTags = Sets.newLinkedHashSet();
        if (describeTagsResponseType != null && describeTagsResponseType.getTagSet() != null) {
          for (TagInfo tagInfo : describeTagsResponseType.getTagSet()) {
            EC2Tag tag = new EC2Tag();
            tag.setKey(tagInfo.getKey());
            tag.setValue(tagInfo.getValue());
            existingTags.add(tag);
          }
        }
        Set<EC2Tag> newTags = Sets.newLinkedHashSet();
        if (newAction.properties.getTags() != null) {
          newTags.addAll(newAction.properties.getTags());
        }
        List<EC2Tag> newStackTags = TagHelper.getEC2StackTags(newAction.getStackEntity());
        if (newStackTags != null) {
          newTags.addAll(newStackTags);
        }
        TagHelper.checkReservedEC2TemplateTags(newTags);
        // add only 'new' tags
        Set<EC2Tag> onlyNewTags = Sets.difference(newTags, existingTags);
        if (!onlyNewTags.isEmpty()) {
          CreateTagsType createTagsType =
              MessageHelper.createMessage(
                  CreateTagsType.class, newAction.info.getEffectiveUserId());
          createTagsType.setResourcesSet(
              Lists.newArrayList(newAction.info.getPhysicalResourceId()));
          createTagsType.setTagSet(EC2Helper.createTagSet(onlyNewTags));
          AsyncRequests.<CreateTagsType, CreateTagsResponseType>sendSync(
              configuration, createTagsType);
        }
        //  Get old tags...
        Set<EC2Tag> oldTags = Sets.newLinkedHashSet();
        if (oldAction.properties.getTags() != null) {
          oldTags.addAll(oldAction.properties.getTags());
        }
        List<EC2Tag> oldStackTags = TagHelper.getEC2StackTags(oldAction.getStackEntity());
        if (oldStackTags != null) {
          oldTags.addAll(oldStackTags);
        }

        // remove only the old tags that are not new and that exist
        Set<EC2Tag> tagsToRemove =
            Sets.intersection(oldTags, Sets.difference(existingTags, newTags));
        if (!tagsToRemove.isEmpty()) {
          DeleteTagsType deleteTagsType =
              MessageHelper.createMessage(
                  DeleteTagsType.class, newAction.info.getEffectiveUserId());
          deleteTagsType.setResourcesSet(
              Lists.newArrayList(newAction.info.getPhysicalResourceId()));
          deleteTagsType.setTagSet(EC2Helper.deleteTagSet(tagsToRemove));
          AsyncRequests.<DeleteTagsType, DeleteTagsResponseType>sendSync(
              configuration, deleteTagsType);
        }
        return newAction;
      }