Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New Resource: aws_launch_template #2927

Merged
merged 7 commits into from
Apr 13, 2018

Conversation

kl4w
Copy link
Contributor

@kl4w kl4w commented Jan 10, 2018

To address #2505

I've created an initial LaunchTemplate resource but unsure how to handle versions and would like input/help.

Creating a new launch template is also conceptually creating the first LaunchTemplateVersion.
If a new LaunchTemplateVersion resource is to be created, it seems weird that it may/should also update the defaultVersion and latestVersion attributes of the LaunchTemplate. Deleting a launch template also deletes all existing versions.

I was thinking about combining the concept of LaunchTemplate and LaunchTemplateVersion such that an update of the LaunchTemplate creates a LaunchTemplateVersion. This results in a single LaunchTemplate in the resulting state. The question is how to handle the versioning of the launch template and how to handle the sourceVersion parameter when creating a new LaunchTemplateVersion.

Combining LaunchTemplate and LaunchTemplateVersion also means that it does not allow as much freedom managing versions, and may mean that creating any resource using the LaunchTemplate may have to use the latestVersion.

Another idea that I was throwing around was create both the LaunchTemplate and LaunchTemplateVersion resources but remove the launchTemplateData attribute from the LaunchTemplate. This would mean that the LaunchTemplate is used more as a versioning reference, and the data is always held in the LaunchTemplateVersion resource. However this would also mean that both resources would be required in order to create a useful launch template.

Thoughts/ideas?

@bflad bflad added new-resource Introduces a new resource. service/ec2 Issues and PRs that pertain to the ec2 service. labels Jan 11, 2018
@danieladams456
Copy link
Contributor

I don't think having to configure two resources (LaunchTemplate and LaunchTemplateVersion) would be too bad. The main thing I would want to do is be able to use Lambda or some other automated process to make a new version of the Launch Template and update the default version to the new without making a re-run of Terraform think it needs to change something. This would let me do initial infrastructure creation through Terraform and automated maintenance through Lambda.

Having a boolean manageVersions or some other similar method would seem to achieve that. I don't know if Terraform can store attributes in state that are for informational purposes only but not engage on a feedback loop for changing resources based on them? If not, then maybe that boolean would cause version not to be stored in state so Terraform wouldn't see any changes.

@bflad
Copy link
Contributor

bflad commented Jan 11, 2018

Terraform core provides a lifecycle configuration block for all resources that allows you to ignore certain attributes you don't want to track: https://www.terraform.io/docs/configuration/resources.html#ignore_changes

e.g. this will create an ECS service with a desired count of 1 (or import with whatever value) and ignore any changes

resource "aws_ecs_service" "example" {
  # other configuration
  desired_count = 1

  lifecycle {
    ignore_changes = ["desired_count"]
  }
}

@danieladams456
Copy link
Contributor

@bflad Is that only for explicitly defined fields or computed values as well?

As long as this feature is implemented in a way that the default version attribute can be ignored with this methodology, that sounds great to me.

@radeksimko radeksimko changed the title [WIP] create launch template resource [WIP] New Resource: aws_launch_template Jan 16, 2018
@kl4w kl4w force-pushed the add_launch_template_resource branch from 06830e6 to 8675237 Compare January 24, 2018 03:12
@kl4w
Copy link
Contributor Author

kl4w commented Jan 24, 2018

Would appreciate some eyes on this PR so far.

make testacc TEST=./aws TESTARGS='-run=TestAccAWSLaunchTemplate_'
==> Checking that code complies with gofmt requirements...
TF_ACC=1 go test ./aws -v -run=TestAccAWSLaunchTemplate_ -timeout 120m
=== RUN   TestAccAWSLaunchTemplate_basic
--- PASS: TestAccAWSLaunchTemplate_basic (21.18s)
=== RUN   TestAccAWSLaunchTemplate_data
--- PASS: TestAccAWSLaunchTemplate_data (21.27s)
PASS
ok  	github.com/terraform-providers/terraform-provider-aws/aws	42.490s

@kl4w kl4w force-pushed the add_launch_template_resource branch from 95af11a to 4b30fd6 Compare January 24, 2018 03:19
@kl4w kl4w force-pushed the add_launch_template_resource branch from 4b30fd6 to f99fe1b Compare February 26, 2018 14:15
@ghost ghost added the size/XXL Managed by automation to categorize the size of a PR. label Feb 26, 2018
@bflad bflad added this to the v1.12.0 milestone Feb 28, 2018
@bflad bflad self-requested a review February 28, 2018 18:38
@ghost ghost added the size/XXL Managed by automation to categorize the size of a PR. label Mar 1, 2018
@kl4w
Copy link
Contributor Author

kl4w commented Mar 1, 2018

I think this is ready to remove to the WIP from this PR

@kl4w kl4w changed the title [WIP] New Resource: aws_launch_template New Resource: aws_launch_template Mar 1, 2018
@kl4w
Copy link
Contributor Author

kl4w commented Mar 2, 2018

after rebase and added documentation:

==> Checking that code complies with gofmt requirements...
TF_ACC=1 go test ./aws -v -run=TestAccAWSLaunchTemplate_ -timeout 120m
=== RUN   TestAccAWSLaunchTemplate_basic
--- PASS: TestAccAWSLaunchTemplate_basic (12.32s)
=== RUN   TestAccAWSLaunchTemplate_data
--- PASS: TestAccAWSLaunchTemplate_data (10.72s)
=== RUN   TestAccAWSLaunchTemplate_update
--- PASS: TestAccAWSLaunchTemplate_update (19.42s)
PASS
ok  	github.com/terraform-providers/terraform-provider-aws/aws	42.505s```

@bflad bflad modified the milestones: v1.12.0, v1.13.0 Mar 23, 2018
@kl4w kl4w force-pushed the add_launch_template_resource branch from ac7bc33 to 4a26f38 Compare March 26, 2018 14:02
@ghost ghost added the size/XXL Managed by automation to categorize the size of a PR. label Mar 26, 2018
@kl4w
Copy link
Contributor Author

kl4w commented Mar 26, 2018

rebase again

make testacc TEST=./aws TESTARGS='-run=TestAccAWSLaunchTemplate_'
==> Checking that code complies with gofmt requirements...
TF_ACC=1 go test ./aws -v -run=TestAccAWSLaunchTemplate_ -timeout 120m
=== RUN   TestAccAWSLaunchTemplate_basic
--- PASS: TestAccAWSLaunchTemplate_basic (10.54s)
=== RUN   TestAccAWSLaunchTemplate_data
--- PASS: TestAccAWSLaunchTemplate_data (10.51s)
=== RUN   TestAccAWSLaunchTemplate_update
--- PASS: TestAccAWSLaunchTemplate_update (18.99s)
PASS
ok  	github.com/terraform-providers/terraform-provider-aws/aws	40.084s

george-angel added a commit to utilitywarehouse/tf_kube_aws that referenced this pull request Mar 26, 2018
Currently occasional cpu spike cause the t2 instance to go down and new
instances are unable to bootstrap (upgrades)

Until
hashicorp/terraform-provider-aws#2927
becomes available, move all critical instances on non-metered cpu
instances types
@bflad bflad modified the milestones: v1.13.0, v1.14.0 Mar 29, 2018
@bflad bflad self-assigned this Apr 5, 2018
Copy link
Contributor

@bflad bflad left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @kl4w! 👋 Thank you very much for this contribution! Overall this pull request is in great shape (don't let the number of comments distract from that 😄 ). You did a fantastic job implementing the crazy nested schema here.

Please check out the feedback and let me know if you have any questions or do not have time to implement any of them.

Aside: For this resource especially, I would also suggest running the acceptance testing with TF_SCHEMA_PANIC_ON_ERROR=1 just in case you missed setting any of the API attributes properly (types, etc.) back into the Terraform state, but it looks like you did a really good job returning errors for d.Set().

"github.com/hashicorp/terraform/helper/schema"
)

const awsSpotInstanceTimeLayout = "2006-01-02T15:04:05Z"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should use RFC3339 instead of our own custom time layout. 👍

"description": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be simplified with:

ValidateFunc: validation.StringLenBetween(0, 255),

},
},

"client_token": {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This attribute is not necessary (nor would I recommend) exposing. 👍

Optional: true,
},
"ebs": {
Type: schema.TypeSet,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To simplify the implementation and future maintenance, we can use schema.TypeList here 👍

},

"instance_market_options": {
Type: schema.TypeSet,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To simply the implementation and future maintenance, this can be schema.TypeList 👍

s := []interface{}{}
for _, v := range m {
mapping := map[string]interface{}{
"device_name": *v.DeviceName,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than risk panics on nil dereferencing, we should switch anything using *thing to the appropriate SDK method that will set it to the zero value for the type: e.g. aws.StringValue(v.DeviceName) This should repeated everywhere below.

resource.TestCheckResourceAttr(resName, "default_version", "1"),
resource.TestCheckResourceAttr(resName, "latest_version", "1"),
),
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add a TestStep here that imports the resource and ensures the Terraform state matches what is expected 👍

{
  ResourceName: resName,
  ImportState: true,
  ImportStateVerify: true,
},

resource.TestCheckResourceAttr(resName, "vpc_security_group_ids.#", "1"),
resource.TestCheckResourceAttr(resName, "tag_specifications.#", "1"),
),
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add a TestStep here that imports the resource and ensures the Terraform state matches what is expected 👍

{
  ResourceName: resName,
  ImportState: true,
  ImportStateVerify: true,
},

resource.TestCheckResourceAttr(resName, "latest_version", "2"),
resource.TestCheckResourceAttrSet(resName, "image_id"),
),
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add a TestStep here that imports the resource and ensures the Terraform state matches what is expected 👍

{
  ResourceName: resName,
  ImportState: true,
  ImportStateVerify: true,
},

}
}

ae, ok := err.(awserr.Error)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be simplified with if isAWSErr(err, "InvalidLaunchTemplateId.NotFound", "") { 👍 (replacing the middle with an SDK constant if available)

@bflad bflad added the waiting-response Maintainers are waiting on response from community or contributor. label Apr 5, 2018
@danieladams456
Copy link
Contributor

To echo @bflad, thank-you very much! This will definitely be useful.

@bflad bflad modified the milestones: v1.14.0, v1.15.0 Apr 6, 2018
@ghost ghost added the size/XXL Managed by automation to categorize the size of a PR. label Apr 13, 2018
@@ -277,34 +279,31 @@ func resourceAwsLaunchTemplate() *schema.Resource {
Optional: true,
},
"security_groups": {
Type: schema.TypeSet,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These (security_groups, ipv6_addresses, and ipv4_addresses) will likely need to remain Type: TypeSet (just needed the Set: schema.HashString removed) as the API likely does not return them in a consistent order. We'll find out!

@@ -358,21 +362,19 @@ func resourceAwsLaunchTemplate() *schema.Resource {
},

"security_group_names": {
Type: schema.TypeSet,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar note here about security_group_names and vpc_security_group_ids -- we shall see!

"volume_type": *v.Ebs.VolumeType,
"delete_on_termination": aws.BoolValue(v.Ebs.DeleteOnTermination),
"encrypted": aws.BoolValue(v.Ebs.Encrypted),
"volume_size": aws.Int64Value(v.Ebs.VolumeSize),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any of these aws.Int64Value() calls will need to be wrapped in int(aws.Int64Value()) since Terraform's TypeInt is a regular int

@kl4w
Copy link
Contributor Author

kl4w commented Apr 13, 2018

Made modifications based off of the review. Can someone please advise on the import? I'm having test failures after adding the import step verification

Without import

make testacc TEST=./aws TESTARGS='-run=TestAccAWSLaunchTemplate_'
gofmt -w $(find . -name '*.go' |grep -v vendor)
==> Checking that code complies with gofmt requirements...
TF_ACC=1 go test ./aws -v -run=TestAccAWSLaunchTemplate_ -timeout 120m
=== RUN   TestAccAWSLaunchTemplate_basic
--- PASS: TestAccAWSLaunchTemplate_basic (13.15s)
=== RUN   TestAccAWSLaunchTemplate_data
--- PASS: TestAccAWSLaunchTemplate_data (11.08s)
=== RUN   TestAccAWSLaunchTemplate_update
--- PASS: TestAccAWSLaunchTemplate_update (21.39s)
PASS
ok  	github.com/terraform-providers/terraform-provider-aws/aws

With import:

make testacc TEST=./aws TESTARGS='-run=TestAccAWSLaunchTemplate_'
gofmt -w $(find . -name '*.go' |grep -v vendor)
==> Checking that code complies with gofmt requirements...
TF_ACC=1 go test ./aws -v -run=TestAccAWSLaunchTemplate_ -timeout 120m
=== RUN   TestAccAWSLaunchTemplate_basic
--- PASS: TestAccAWSLaunchTemplate_basic (14.27s)
=== RUN   TestAccAWSLaunchTemplate_data
--- FAIL: TestAccAWSLaunchTemplate_data (12.74s)
	testing.go:518: Step 1 error: ImportStateVerify attributes not equivalent. Difference is shown below. Top is actual, bottom is expected.

		(map[string]string) {
		}


		(map[string]string) (len=5) {
		 (string) (len=12) "monitoring.#": (string) (len=1) "1",
		 (string) (len=20) "monitoring.0.enabled": (string) (len=4) "true",
		 (string) (len=11) "ram_disk_id": (string) (len=12) "ari-a12bc3de",
		 (string) (len=24) "vpc_security_group_ids.#": (string) (len=1) "1",
		 (string) (len=24) "vpc_security_group_ids.0": (string) (len=4) "test"
		}

=== RUN   TestAccAWSLaunchTemplate_update
--- FAIL: TestAccAWSLaunchTemplate_update (23.05s)
	testing.go:518: Step 2 error: ImportStateVerify attributes not equivalent. Difference is shown below. Top is actual, bottom is expected.

		(map[string]string) {
		}


		(map[string]string) (len=5) {
		 (string) (len=12) "monitoring.#": (string) (len=1) "1",
		 (string) (len=20) "monitoring.0.enabled": (string) (len=4) "true",
		 (string) (len=11) "ram_disk_id": (string) (len=12) "ari-a12bc3de",
		 (string) (len=24) "vpc_security_group_ids.#": (string) (len=1) "1",
		 (string) (len=24) "vpc_security_group_ids.0": (string) (len=4) "test"
		}

FAIL
FAIL	github.com/terraform-providers/terraform-provider-aws/aws	50.102s

@bflad
Copy link
Contributor

bflad commented Apr 13, 2018

@kl4w generally that means d.Set() is not being called correctly for those attributes during read. 😄

d.Set("instance_type", ltData.InstanceType)
d.Set("kernel_id", ltData.KernelId)
d.Set("key_name", ltData.KeyName)
d.Set("monitoring", ltData.Monitoring)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to be updated to err check (since its non-scalar now) as well as correctly handle the new nested structure:

if err := d.Set("monitoring", getMonitoring(ltData.Monitoring)); err != nil {
  return err
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ahhh makes sense. Thank you. I'll make those changes now.

d.Set("kernel_id", ltData.KernelId)
d.Set("key_name", ltData.KeyName)
d.Set("monitoring", ltData.Monitoring)
d.Set("ram_dist_id", ltData.RamDiskId)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: 😅 d.Set("ram_disk_id", ltData.RamDiskId) (FYI you can find these by running the acceptance testing with TF_SCHEMA_PANIC_ON_ERROR=1 as well as the import testing that noticed it)

@ghost ghost added the size/XXL Managed by automation to categorize the size of a PR. label Apr 13, 2018
@kl4w
Copy link
Contributor Author

kl4w commented Apr 13, 2018

TF_SCHEMA_PANIC_ON_ERROR=1 make testacc TEST=./aws TESTARGS='-run=TestAccAWSLaunchTemplate_'
gofmt -w $(find . -name '*.go' |grep -v vendor)
==> Checking that code complies with gofmt requirements...
TF_ACC=1 go test ./aws -v -run=TestAccAWSLaunchTemplate_ -timeout 120m
=== RUN   TestAccAWSLaunchTemplate_importBasic
--- PASS: TestAccAWSLaunchTemplate_importBasic (14.62s)
=== RUN   TestAccAWSLaunchTemplate_importData
--- PASS: TestAccAWSLaunchTemplate_importData (15.01s)
=== RUN   TestAccAWSLaunchTemplate_basic
--- PASS: TestAccAWSLaunchTemplate_basic (12.00s)
=== RUN   TestAccAWSLaunchTemplate_data
--- PASS: TestAccAWSLaunchTemplate_data (13.97s)
=== RUN   TestAccAWSLaunchTemplate_update
--- PASS: TestAccAWSLaunchTemplate_update (21.29s)
PASS
ok  	github.com/terraform-providers/terraform-provider-aws/aws

@bflad
Copy link
Contributor

bflad commented Apr 13, 2018

Do you have a second to update the monitoring documentation as well? Running testing now


key_name = "test"

monitoring = true
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll fix this up post merge 👍

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ahh thanks. I was going to update the documentation as well on this branch. Do you want me to hold off?

Copy link
Contributor

@bflad bflad left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kl4w you are about to make a large amount of people happy! Great work on this and thanks for sticking through the crazy schema issues! 🚀 💯 🥇

5 tests passed (all tests)
=== RUN   TestAccAWSLaunchTemplate_data
--- PASS: TestAccAWSLaunchTemplate_data (6.54s)
=== RUN   TestAccAWSLaunchTemplate_basic
--- PASS: TestAccAWSLaunchTemplate_basic (6.60s)
=== RUN   TestAccAWSLaunchTemplate_importBasic
--- PASS: TestAccAWSLaunchTemplate_importBasic (7.32s)
=== RUN   TestAccAWSLaunchTemplate_importData
--- PASS: TestAccAWSLaunchTemplate_importData (7.35s)
=== RUN   TestAccAWSLaunchTemplate_update
--- PASS: TestAccAWSLaunchTemplate_update (11.30s)

@bflad bflad removed the waiting-response Maintainers are waiting on response from community or contributor. label Apr 13, 2018
@bflad bflad merged commit 621189d into hashicorp:master Apr 13, 2018
bflad added a commit that referenced this pull request Apr 13, 2018
@bflad
Copy link
Contributor

bflad commented Apr 18, 2018

This has been released in version 1.15.0 of the AWS provider. Please see the Terraform documentation on provider versioning or reach out if you need any assistance upgrading.

@ghost
Copy link

ghost commented Apr 6, 2020

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues.

If you feel this issue should be reopened, we encourage creating a new issue linking back to this one for added context. Thanks!

@ghost ghost locked and limited conversation to collaborators Apr 6, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
new-resource Introduces a new resource. service/ec2 Issues and PRs that pertain to the ec2 service. size/XXL Managed by automation to categorize the size of a PR.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants