provider/aws: Support refresh of EC2 instance user_data.

Make sure to hash base64 decoded value since user_data might be given
either raw bytes or base64 value.

This helps https://github.com/hashicorp/terraform/issues/1887 somewhat
as now you can:

1) Update user_data in AWS console.
2) Respectively update user_data in terraform code.
3) Just refresh terraform state and it should not report any changes.
This commit is contained in:
Modestas Vainius 2016-05-17 17:15:15 +03:00 committed by Clint
parent 961c8f9d97
commit 7385fa9eac
2 changed files with 30 additions and 6 deletions

View File

@ -98,8 +98,7 @@ func resourceAwsInstance() *schema.Resource {
StateFunc: func(v interface{}) string {
switch v.(type) {
case string:
hash := sha1.Sum([]byte(v.(string)))
return hex.EncodeToString(hash[:])
return userDataHashSum(v.(string))
default:
return ""
}
@ -583,6 +582,18 @@ func resourceAwsInstanceRead(d *schema.ResourceData, meta interface{}) error {
}
d.Set("disable_api_termination", attr.DisableApiTermination.Value)
}
{
attr, err := conn.DescribeInstanceAttribute(&ec2.DescribeInstanceAttributeInput{
Attribute: aws.String(ec2.InstanceAttributeNameUserData),
InstanceId: aws.String(d.Id()),
})
if err != nil {
return err
}
if attr.UserData.Value != nil {
d.Set("user_data", userDataHashSum(*attr.UserData.Value))
}
}
return nil
}
@ -1166,3 +1177,16 @@ func iamInstanceProfileArnToName(ip *ec2.IamInstanceProfile) string {
parts := strings.Split(*ip.Arn, "/")
return parts[len(parts)-1]
}
func userDataHashSum(user_data string) string {
// Check whether the user_data is not Base64 encoded.
// Always calculate hash of base64 decoded value since we
// check against double-encoding when setting it
v, base64DecodeError := base64.StdEncoding.DecodeString(user_data)
if base64DecodeError != nil {
v = []byte(user_data)
}
hash := sha1.Sum(v)
return hex.EncodeToString(hash[:])
}

View File

@ -39,7 +39,7 @@ func TestAccAWSInstance_basic(t *testing.T) {
// we'll import as VPC security groups, which is fine. We verify
// VPC security group import in other tests
IDRefreshName: "aws_instance.foo",
IDRefreshIgnore: []string{"user_data", "security_groups", "vpc_security_group_ids"},
IDRefreshIgnore: []string{"security_groups", "vpc_security_group_ids"},
Providers: testAccProviders,
CheckDestroy: testAccCheckInstanceDestroy,
@ -195,7 +195,7 @@ func TestAccAWSInstance_blockDevices(t *testing.T) {
PreCheck: func() { testAccPreCheck(t) },
IDRefreshName: "aws_instance.foo",
IDRefreshIgnore: []string{
"ephemeral_block_device", "user_data", "security_groups", "vpc_security_groups"},
"ephemeral_block_device", "security_groups", "vpc_security_groups"},
Providers: testAccProviders,
CheckDestroy: testAccCheckInstanceDestroy,
Steps: []resource.TestStep{
@ -346,7 +346,7 @@ func TestAccAWSInstance_vpc(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
IDRefreshName: "aws_instance.foo",
IDRefreshIgnore: []string{"associate_public_ip_address", "user_data"},
IDRefreshIgnore: []string{"associate_public_ip_address"},
Providers: testAccProviders,
CheckDestroy: testAccCheckInstanceDestroy,
Steps: []resource.TestStep{
@ -358,7 +358,7 @@ func TestAccAWSInstance_vpc(t *testing.T) {
resource.TestCheckResourceAttr(
"aws_instance.foo",
"user_data",
"2fad308761514d9d73c3c7fdc877607e06cf950d"),
"562a3e32810edf6ff09994f050f12e799452379d"),
),
},
},