Terraform-provider-aws: aws_spot_instance_request tags won't apply to instance

Created on 13 Jun 2017  路  21Comments  路  Source: hashicorp/terraform-provider-aws

_This issue was originally opened by @caarlos0 as hashicorp/terraform#3263. It was migrated here as part of the provider split. The original body of the issue is below._


I have an aws_spot_instance_request like this:

resource "aws_spot_instance_request" "seleniumgrid" {
    ami = "${var.amiPuppet}"
    key_name = "${var.key}"
    instance_type = "c3.4xlarge"
    subnet_id = "${var.subnet}"
    vpc_security_group_ids = [ "${var.securityGroup}" ]
    user_data = "${template_file.userdata.rendered}"
    wait_for_fulfillment = true
    spot_price = "${var.price}"
    availability_zone = "${var.zone}"
    instance_initiated_shutdown_behavior = "terminate"
    root_block_device {
      volume_size = 100
      volume_type = "gp2"
    }
    tags {
      Name = "${var.name}.${var.domain}"
      Provider = "Terraform"
      CA_TEAM = "${var.team}"
      CA_ROLE = "${var.role}"
      CA_SERVICE = "${var.service}"
    }
}

The tags are being applied only to the spot request itself, not to the underlying instance. Is this an expected behavior? How can I change this?

Thanks!

enhancement servicec2

Most helpful comment

This is a nice workaround I just implemented with local-exec

resource "aws_spot_instance_request" "platform" {
  ami           = "${var.ami_id}"
  instance_type = "${var.instance_type}"
  key_name      = "${var.key_name}"
  subnet_id     = "${lookup(var.subnet, var.region)}"

  associate_public_ip_address = true
  vpc_security_group_ids      = ["${lookup(var.security_groups, var.region)}"]

  tags = "${var.tags}"

  spot_price    = "0.03"
  wait_for_fulfillment = true

  provisioner "local-exec" {
    command = "./update_spotinstance_tags.sh ${var.region} ${aws_spot_instance_request.platform.id} ${aws_spot_instance_request.platform.spot_instance_id}"
  }
}

update_spotinstance_tags.sh

#!/usr/bin/env bash

#$1 = ${var.region} 
#$2 = ${aws_spot_instance_request.platform.id} 
#$3 = ${aws_spot_instance_request.platform.spot_instance_id}

aws --region $1 ec2 describe-spot-instance-requests --spot-instance-request-ids $2 --query 'SpotInstanceRequests[0].Tags' > tags.json
aws ec2 create-tags --resources $3 --tags file://tags.json
rm -f tags.json

All 21 comments

_This comment was originally opened by @jmreicha as https://github.com/hashicorp/terraform/issues/3263#issuecomment-156028640. It was migrated here as part of the provider split. The original comment is below._


I just ran in to this issue as well.

_This comment was originally opened by @sean-brandt as https://github.com/hashicorp/terraform/issues/3263#issuecomment-161453999. It was migrated here as part of the provider split. The original comment is below._


Definitely an issue, also in 0.6.8. Need a way to apply those tags to the new instance, or allow for an aws_instance_tag resource that will allow arbitrary tags to be set on ec2 instances.

_This comment was originally opened by @caarlos0 as https://github.com/hashicorp/terraform/issues/3263#issuecomment-161464036. It was migrated here as part of the provider split. The original comment is below._


Agreed!

_This comment was originally opened by @stolinzeev as https://github.com/hashicorp/terraform/issues/3263#issuecomment-162320876. It was migrated here as part of the provider split. The original comment is below._


Present in 0.6.8 as well

_This comment was originally opened by @catsby as https://github.com/hashicorp/terraform/issues/3263#issuecomment-162662829. It was migrated here as part of the provider split. The original comment is below._


There is no AWS API that will do this via the Spot Instance request itself. We would need to trap the InstanceId (which we do) and then call out to set the tags on that. I don't see a straightforward easy way to do this, but it shouldn't be too hard. I don't know that I'll get to this anytime soon however, but maybe someone in the community will pick it up.

_This comment was originally opened by @cbarbour as https://github.com/hashicorp/terraform/issues/3263#issuecomment-239058907. It was migrated here as part of the provider split. The original comment is below._


This is the expected behavior as per AWS documentation, unfortunately.

http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-requests.html#concepts-spot-instances-request-tags

I did find a solution. I created an IAM role with a policy that grants CreateTag permissions. I added an instance_profile to the role, and a ruleset allowing it to be assigned to the instances.

Using cloud init, I have a script that looks up the instances metadata, and using the result, tags itself based on arguments passed to the script.

There are a few moving parts, unfortunately. It helps if you're already familiar with cloud-init.

_This comment was originally opened by @cbarbour as https://github.com/hashicorp/terraform/issues/3263#issuecomment-241910882. It was migrated here as part of the provider split. The original comment is below._


Another option: Use autoscaling groups. Tags applied to the launch_configuration will be passed on to the resulting spot instance.

_This comment was originally opened by @rehmanzile as https://github.com/hashicorp/terraform/issues/3263#issuecomment-247736606. It was migrated here as part of the provider split. The original comment is below._


This issue seems to be open for a year now. Any luck with the fix.

_This comment was originally opened by @jalkjaer as https://github.com/hashicorp/terraform/issues/3263#issuecomment-284387578. It was migrated here as part of the provider split. The original comment is below._


Until there is explicit support, we are getting by with the following user-data snippet to clone the spot-request tags to the instance.
Its somewhat simplistic and lacks error handling, but it does the job for us. It requires that aws cli / curl is available and that the instance has the proper IAM permission of course

#!/bin/bash

REGION=us-east-1
INSTANCE_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id)
SPOT_REQ_ID=$(aws --region $REGION ec2 describe-instances --instance-ids "$INSTANCE_ID"  --query 'Reservations[0].Instances[0].SpotInstanceRequestId' --output text)
if [ "$SPOT_REQ_ID" != "None" ] ; then
  TAGS=$(aws --region $REGION ec2 describe-spot-instance-requests --spot-instance-request-ids "$SPOT_REQ_ID" --query 'SpotInstanceRequests[0].Tags')
  aws --region $REGION ec2 create-tags --resources "$INSTANCE_ID" --tags "$TAGS"
fi

_This comment was originally opened by @alextbrandwatch as https://github.com/hashicorp/terraform/issues/3263#issuecomment-299899528. It was migrated here as part of the provider split. The original comment is below._


Issue still seems to be present in 0.9.4. Causing problems - will attempt the workaround solutions posted here

_This comment was originally opened by @kostyrev as https://github.com/hashicorp/terraform/issues/3263#issuecomment-308077893. It was migrated here as part of the provider split. The original comment is below._


Workarounds are good but not always applicable.
Please consider adding explicit support.

This is a nice workaround I just implemented with local-exec

resource "aws_spot_instance_request" "platform" {
  ami           = "${var.ami_id}"
  instance_type = "${var.instance_type}"
  key_name      = "${var.key_name}"
  subnet_id     = "${lookup(var.subnet, var.region)}"

  associate_public_ip_address = true
  vpc_security_group_ids      = ["${lookup(var.security_groups, var.region)}"]

  tags = "${var.tags}"

  spot_price    = "0.03"
  wait_for_fulfillment = true

  provisioner "local-exec" {
    command = "./update_spotinstance_tags.sh ${var.region} ${aws_spot_instance_request.platform.id} ${aws_spot_instance_request.platform.spot_instance_id}"
  }
}

update_spotinstance_tags.sh

#!/usr/bin/env bash

#$1 = ${var.region} 
#$2 = ${aws_spot_instance_request.platform.id} 
#$3 = ${aws_spot_instance_request.platform.spot_instance_id}

aws --region $1 ec2 describe-spot-instance-requests --spot-instance-request-ids $2 --query 'SpotInstanceRequests[0].Tags' > tags.json
aws ec2 create-tags --resources $3 --tags file://tags.json
rm -f tags.json

I would expect that this can be implemented via something similar to aws_instance's volume_tags. Call it instance_tags.

And I just realized that volume_tags are also not being passed from the Spot request to the instance's volumes.

Are you guys planning on fixing this?

Any news on this? Thanks

+1

Please fix this. Currently implementing ugly workarounds in order to resolve this issue.

+1 to some implementation here

@birkoff Saved my life. I had to modify a bit to avoid file creation. Tks!

#!/usr/bin/env bash

#$1 = ${var.region} 
#$2 = ${aws_spot_instance_request.platform.id} 
#$3 = ${aws_spot_instance_request.platform.spot_instance_id}

TAGS=$(aws ec2 describe-spot-instance-requests \
--region $1 \
--spot-instance-request-ids $2 \
--query 'SpotInstanceRequests[0].Tags')

aws ec2 create-tags --region $1 --resources $3 --tags "$TAGS"

The new(ish) aws_ec2_tag resource can be used to tag the created EC2 instance, for example:

data "aws_ami" "amzn-ami-minimal-hvm-ebs" {
  most_recent = true
  owners      = ["amazon"]

  filter {
    name   = "name"
    values = ["amzn-ami-minimal-hvm-*"]
  }

  filter {
    name   = "root-device-type"
    values = ["ebs"]
  }
}

data "aws_ec2_instance_type_offering" "available" {
  filter {
    name   = "instance-type"
    values = ["t3.micro", "t2.micro"]
  }

  preferred_instance_types = ["t3.micro", "t2.micro"]
}

resource "aws_spot_instance_request" "example" {
  ami           = data.aws_ami.amzn-ami-minimal-hvm-ebs.id
  instance_type = data.aws_ec2_instance_type_offering.available.instance_type

  spot_price = "0.05"

  wait_for_fulfillment = true
}

locals {
  tags = {
    Environment = "Test"
    Name        = "Example"
  }
}

resource "aws_ec2_tag" "example" {
  resource_id = aws_spot_instance_request.example.spot_instance_id

  for_each = local.tags
  key      = each.key
  value    = each.value
}
Was this page helpful?
0 / 5 - 0 ratings