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

resource/aws_ssm_activation: Prevent crash with expiration_date #3597

Merged
merged 2 commits into from
Mar 2, 2018
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions aws/resource_aws_ssm_activation.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@ func resourceAwsSsmActivation() *schema.Resource {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
// When released, replace with upstream validation function:
// https://github.com/hashicorp/terraform/pull/17484
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.

What do you think of extracting it to its own function in order to be able to test it at some point?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I submitted an upstream PR hashicorp/terraform#17484 with tests to get it included where it ideally belongs. I'll move this to its own function in this repository with the same testing for now.

if _, err := time.Parse(time.RFC3339, v.(string)); err != nil {
errors = append(errors, fmt.Errorf("%q: %s", k, err))
}
return
},
},
"iam_role": {
Type: schema.TypeString,
Expand Down Expand Up @@ -77,8 +85,9 @@ func resourceAwsSsmActivationCreate(d *schema.ResourceData, meta interface{}) er
activationInput.Description = aws.String(d.Get("description").(string))
}

if _, ok := d.GetOk("expiration_date"); ok {
activationInput.ExpirationDate = aws.Time(d.Get("expiration_date").(time.Time))
if v, ok := d.GetOk("expiration_date"); ok {
t, _ := time.Parse(time.RFC3339, v.(string))
activationInput.ExpirationDate = aws.Time(t)
}

if _, ok := d.GetOk("iam_role"); ok {
Expand Down
64 changes: 64 additions & 0 deletions aws/resource_aws_ssm_activation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package aws

import (
"fmt"
"regexp"
"testing"
"time"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ssm"
Expand All @@ -29,6 +31,32 @@ func TestAccAWSSSMActivation_basic(t *testing.T) {
})
}

func TestAccAWSSSMActivation_expirationDate(t *testing.T) {
rName := acctest.RandString(10)
expirationTime := time.Now().Add(48 * time.Hour)
expirationDateS := expirationTime.Format(time.RFC3339)
resourceName := "aws_ssm_activation.foo"

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSSSMActivationDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSSSMActivationConfig_expirationDate(rName, "2018-03-01"),
ExpectError: regexp.MustCompile(`cannot parse`),
},
{
Config: testAccAWSSSMActivationConfig_expirationDate(rName, expirationDateS),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSSSMActivationExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "expiration_date", expirationDateS),
),
},
},
})
}

func testAccCheckAWSSSMActivationExists(n string) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n]
Expand Down Expand Up @@ -130,3 +158,39 @@ resource "aws_ssm_activation" "foo" {
}
`, rName, rName)
}

func testAccAWSSSMActivationConfig_expirationDate(rName, expirationDate string) string {
return fmt.Sprintf(`
resource "aws_iam_role" "test_role" {
name = "test_role-%[1]s"
Copy link
Contributor

Choose a reason for hiding this comment

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

❤️ the use of %[1]s, 👍

assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ssm.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
EOF
}

resource "aws_iam_role_policy_attachment" "test_attach" {
role = "${aws_iam_role.test_role.name}"
policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM"
}

resource "aws_ssm_activation" "foo" {
name = "test_ssm_activation-%[1]s",
description = "Test"
expiration_date = "%[2]s"
iam_role = "${aws_iam_role.test_role.name}"
registration_limit = "5"
depends_on = ["aws_iam_role_policy_attachment.test_attach"]
}
`, rName, expirationDate)
}
2 changes: 1 addition & 1 deletion website/docs/r/ssm_activation.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ The following arguments are supported:

* `name` - (Optional) The default name of the registerd managed instance.
* `description` - (Optional) The description of the resource that you want to register.
* `expiration_date` - (Optional) The date by which this activation request should expire. The default value is 24 hours.
* `expiration_date` - (Optional) A timestamp in [RFC3339 format](https://tools.ietf.org/html/rfc3339#section-5.8) by which this activation request should expire. The default value is 24 hours from resource creation time.
* `iam_role` - (Required) The IAM Role to attach to the managed instance.
* `registration_limit` - (Optional) The maximum number of managed instances you want to register. The default value is 1 instance.

Expand Down