@Override
  public void execute(Context context) throws Exception {
    RunInstancesRequest request =
        new RunInstancesRequest()
            .withKeyName(resource.keyPair.remoteKeyPair.getKeyName())
            .withInstanceType(resource.instanceType)
            .withImageId(resource.ami.imageId())
            .withMinCount(addedCount)
            .withMaxCount(addedCount)
            .withUserData(Base64.encodeBase64String(Strings.bytes(userData(context.env))));

    if (resource.instanceProfile != null)
      request.withIamInstanceProfile(
          new IamInstanceProfileSpecification()
              .withName(resource.instanceProfile.remoteInstanceProfile.getInstanceProfileName()));

    String sgId = resource.securityGroup.remoteSecurityGroup.getGroupId();

    request
        .getNetworkInterfaces()
        .add(
            new InstanceNetworkInterfaceSpecification()
                .withDeviceIndex(0)
                .withSubnetId(resource.subnet.firstRemoteSubnet().getSubnetId())
                .withGroups(sgId)
                .withAssociatePublicIpAddress(resource.subnet.type == SubnetType.PUBLIC));

    if (resource.ebs.rootVolumeSize != null) {
      request
          .getBlockDeviceMappings()
          .add(
              new BlockDeviceMapping()
                  .withDeviceName("/dev/sda1")
                  .withEbs(new EbsBlockDevice().withVolumeSize(resource.ebs.rootVolumeSize)));
    }

    List<com.amazonaws.services.ec2.model.Instance> remoteInstances =
        AWS.ec2.runInstances(request, tags(context.env));
    resource.remoteInstances.addAll(remoteInstances);

    for (com.amazonaws.services.ec2.model.Instance remoteInstance : remoteInstances) {
      String key = String.format("instance/%s/%s", resource.id, remoteInstance.getInstanceId());
      StringBuilder builder = new StringBuilder();
      builder.append("privateIP=").append(remoteInstance.getPrivateIpAddress());
      if (resource.subnet == null || resource.subnet.type == SubnetType.PUBLIC) {
        builder.append(", publicDNS=").append(remoteInstance.getPublicDnsName());
      }
      context.output(key, builder.toString());
    }

    if (resource.elb != null) {
      List<String> instanceIds =
          remoteInstances
              .stream()
              .map(com.amazonaws.services.ec2.model.Instance::getInstanceId)
              .collect(Collectors.toList());
      AWS.elb.attachInstances(
          resource.elb.remoteELB.getLoadBalancerName(), instanceIds, waitUntilInService);
    }
  }