diff --git a/builtin/providers/aws/import_aws_iam_account_alias_test.go b/builtin/providers/aws/import_aws_iam_account_alias_test.go new file mode 100644 index 000000000..e2d00b68c --- /dev/null +++ b/builtin/providers/aws/import_aws_iam_account_alias_test.go @@ -0,0 +1,31 @@ +package aws + +import ( + "testing" + + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" +) + +func TestAccAWSIAMAccountAlias_importBasic(t *testing.T) { + resourceName := "aws_iam_account_alias.test" + + rstring := acctest.RandString(5) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSIAMAccountAliasDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccAWSIAMAccountAliasConfig(rstring), + }, + + resource.TestStep{ + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} diff --git a/builtin/providers/aws/provider.go b/builtin/providers/aws/provider.go index d6b156bb0..30c56fa30 100644 --- a/builtin/providers/aws/provider.go +++ b/builtin/providers/aws/provider.go @@ -298,6 +298,7 @@ func Provider() terraform.ResourceProvider { "aws_flow_log": resourceAwsFlowLog(), "aws_glacier_vault": resourceAwsGlacierVault(), "aws_iam_access_key": resourceAwsIamAccessKey(), + "aws_iam_account_alias": resourceAwsIamAccountAlias(), "aws_iam_account_password_policy": resourceAwsIamAccountPasswordPolicy(), "aws_iam_group_policy": resourceAwsIamGroupPolicy(), "aws_iam_group": resourceAwsIamGroup(), diff --git a/builtin/providers/aws/resource_aws_iam_account_alias.go b/builtin/providers/aws/resource_aws_iam_account_alias.go new file mode 100644 index 000000000..3b1b86f1e --- /dev/null +++ b/builtin/providers/aws/resource_aws_iam_account_alias.go @@ -0,0 +1,94 @@ +package aws + +import ( + "fmt" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/iam" + "github.com/hashicorp/terraform/helper/schema" +) + +func resourceAwsIamAccountAlias() *schema.Resource { + return &schema.Resource{ + Create: resourceAwsIamAccountAliasCreate, + Read: resourceAwsIamAccountAliasRead, + Delete: resourceAwsIamAccountAliasDelete, + + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Schema: map[string]*schema.Schema{ + "account_alias": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validateAccountAlias, + }, + }, + } +} + +func resourceAwsIamAccountAliasCreate(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).iamconn + + account_alias := d.Get("account_alias").(string) + + params := &iam.CreateAccountAliasInput{ + AccountAlias: aws.String(account_alias), + } + + _, err := conn.CreateAccountAlias(params) + + if err != nil { + return fmt.Errorf("Error creating account alias with name %s", account_alias) + } + + d.SetId(account_alias) + + return nil +} + +func resourceAwsIamAccountAliasRead(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).iamconn + + params := &iam.ListAccountAliasesInput{} + + resp, err := conn.ListAccountAliases(params) + + if err != nil { + return err + } + + if resp == nil || len(resp.AccountAliases) == 0 { + d.SetId("") + return nil + } + + account_alias := aws.StringValue(resp.AccountAliases[0]) + + d.SetId(account_alias) + d.Set("account_alias", account_alias) + + return nil +} + +func resourceAwsIamAccountAliasDelete(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).iamconn + + account_alias := d.Get("account_alias").(string) + + params := &iam.DeleteAccountAliasInput{ + AccountAlias: aws.String(account_alias), + } + + _, err := conn.DeleteAccountAlias(params) + + if err != nil { + return fmt.Errorf("Error deleting account alias with name %s", account_alias) + } + + d.SetId("") + + return nil +} diff --git a/builtin/providers/aws/resource_aws_iam_account_alias_test.go b/builtin/providers/aws/resource_aws_iam_account_alias_test.go new file mode 100644 index 000000000..7106566a2 --- /dev/null +++ b/builtin/providers/aws/resource_aws_iam_account_alias_test.go @@ -0,0 +1,91 @@ +package aws + +import ( + "fmt" + "testing" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/iam" + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" +) + +func TestAccAWSIAMAccountAlias_basic(t *testing.T) { + var account_alias string + + rstring := acctest.RandString(5) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSIAMAccountAliasDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSIAMAccountAliasConfig(rstring), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSIAMAccountAliasExists("aws_iam_account_alias.test", &account_alias), + ), + }, + }, + }) +} + +func testAccCheckAWSIAMAccountAliasDestroy(s *terraform.State) error { + conn := testAccProvider.Meta().(*AWSClient).iamconn + + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_iam_account_alias" { + continue + } + + params := &iam.ListAccountAliasesInput{} + + resp, err := conn.ListAccountAliases(params) + + if err != nil || resp == nil { + return nil + } + + if len(resp.AccountAliases) > 0 { + return fmt.Errorf("Bad: Account alias still exists: %q", rs.Primary.ID) + } + } + + return nil + +} + +func testAccCheckAWSIAMAccountAliasExists(n string, a *string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + conn := testAccProvider.Meta().(*AWSClient).iamconn + params := &iam.ListAccountAliasesInput{} + + resp, err := conn.ListAccountAliases(params) + + if err != nil || resp == nil { + return nil + } + + if len(resp.AccountAliases) == 0 { + return fmt.Errorf("Bad: Account alias %q does not exist", rs.Primary.ID) + } + + *a = aws.StringValue(resp.AccountAliases[0]) + + return nil + } +} + +func testAccAWSIAMAccountAliasConfig(rstring string) string { + return fmt.Sprintf(` +resource "aws_iam_account_alias" "test" { + account_alias = "terraform-%s-alias" +} +`, rstring) +} diff --git a/builtin/providers/aws/validators.go b/builtin/providers/aws/validators.go index e6c6962a0..f7a600c2c 100644 --- a/builtin/providers/aws/validators.go +++ b/builtin/providers/aws/validators.go @@ -930,3 +930,22 @@ func validateConfigExecutionFrequency(v interface{}, k string) (ws []string, err k, frequency, validFrequencies)) return } + +func validateAccountAlias(v interface{}, k string) (ws []string, es []error) { + val := v.(string) + + if (len(val) < 3) || (len(val) > 63) { + es = append(es, fmt.Errorf("%q must contain from 3 to 63 alphanumeric characters or hyphens", k)) + } + if !regexp.MustCompile("^[a-z0-9][a-z0-9-]+$").MatchString(val) { + es = append(es, fmt.Errorf("%q must start with an alphanumeric character and only contain lowercase alphanumeric characters and hyphens", k)) + } + if strings.Contains(val, "--") { + es = append(es, fmt.Errorf("%q must not contain consecutive hyphens", k)) + } + if strings.HasSuffix(val, "-") { + es = append(es, fmt.Errorf("%q must not end in a hyphen", k)) + } + + return +} diff --git a/builtin/providers/aws/validators_test.go b/builtin/providers/aws/validators_test.go index 8920ae764..21136d3bb 100644 --- a/builtin/providers/aws/validators_test.go +++ b/builtin/providers/aws/validators_test.go @@ -1550,3 +1550,32 @@ func TestValidateDmsReplicationTaskId(t *testing.T) { } } } + +func TestValidateAccountAlias(t *testing.T) { + validAliases := []string{ + "tf-alias", + "0tf-alias1", + } + + for _, s := range validAliases { + _, errors := validateAccountAlias(s, "account_alias") + if len(errors) > 0 { + t.Fatalf("%q should be a valid account alias: %v", s, errors) + } + } + + invalidAliases := []string{ + "tf", + "-tf", + "tf-", + "TF-Alias", + "tf-alias-tf-alias-tf-alias-tf-alias-tf-alias-tf-alias-tf-alias-tf-alias", + } + + for _, s := range invalidAliases { + _, errors := validateAccountAlias(s, "account_alias") + if len(errors) == 0 { + t.Fatalf("%q should not be a valid account alias: %v", s, errors) + } + } +} diff --git a/website/source/docs/providers/aws/r/iam_account_alias.html.markdown b/website/source/docs/providers/aws/r/iam_account_alias.html.markdown new file mode 100644 index 000000000..7acd08834 --- /dev/null +++ b/website/source/docs/providers/aws/r/iam_account_alias.html.markdown @@ -0,0 +1,35 @@ +--- +layout: "aws" +page_title: "AWS: aws_iam_account_alias" +sidebar_current: "docs-aws-resource-iam-account-alias" +description: |- + Manages the account alias for the AWS Account. +--- + +# aws\_iam\_account\_alias + +-> **Note:** There is only a single account alias per AWS account. + +Manages the account alias for the AWS Account. + +## Example Usage + +``` +resource "aws_iam_account_alias" "alias" { + account_alias = "my-account-alias" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `account_alias` - (Required) The account alias + +## Import + +The current Account Alias can be imported using the `account_alias`, e.g. + +``` +$ terraform import aws_iam_account_alias.alias my-account-alias +``` diff --git a/website/source/layouts/aws.erb b/website/source/layouts/aws.erb index 1b868743c..fa7caad7a 100644 --- a/website/source/layouts/aws.erb +++ b/website/source/layouts/aws.erb @@ -702,6 +702,10 @@ aws_iam_access_key + > + aws_iam_account_alias + + > aws_iam_account_password_policy