From e97900aef28a4d3b2f3df30ee9558dfc8f730503 Mon Sep 17 00:00:00 2001 From: Jake Champlin Date: Mon, 27 Mar 2017 09:32:31 -0400 Subject: [PATCH 1/9] provider/aws: Update calling_identity Updates `aws_caller_identity` data source to actually include the correct attributes from the `GetCallerIdentity` API function. ``` $ make testacc TEST=./builtin/providers/aws TESTARGS='-run=TestAccAWSCallerIdentity_basic' ==> Checking that code complies with gofmt requirements... go generate $(go list ./... | grep -v /terraform/vendor/) 2017/03/27 09:26:13 Generated command/internal_plugin_list.go TF_ACC=1 go test ./builtin/providers/aws -v -run=TestAccAWSCallerIdentity_basic -timeout 120m === RUN TestAccAWSCallerIdentity_basic --- PASS: TestAccAWSCallerIdentity_basic (12.74s) PASS ok github.com/hashicorp/terraform/builtin/providers/aws 12.767s ``` --- .../aws/data_source_aws_caller_identity.go | 27 +++++++++++++++---- .../data_source_aws_caller_identity_test.go | 8 ++++++ .../aws/d/caller_identity.html.markdown | 16 ++++++++--- 3 files changed, 43 insertions(+), 8 deletions(-) diff --git a/builtin/providers/aws/data_source_aws_caller_identity.go b/builtin/providers/aws/data_source_aws_caller_identity.go index 05c03864df0e..95313cea88da 100644 --- a/builtin/providers/aws/data_source_aws_caller_identity.go +++ b/builtin/providers/aws/data_source_aws_caller_identity.go @@ -5,6 +5,7 @@ import ( "log" "time" + "github.com/aws/aws-sdk-go/service/sts" "github.com/hashicorp/terraform/helper/schema" ) @@ -17,24 +18,40 @@ func dataSourceAwsCallerIdentity() *schema.Resource { Type: schema.TypeString, Computed: true, }, + + "arn": { + Type: schema.TypeString, + Computed: true, + }, + + "user_id": { + Type: schema.TypeString, + Computed: true, + }, }, } } func dataSourceAwsCallerIdentityRead(d *schema.ResourceData, meta interface{}) error { - client := meta.(*AWSClient) + client := meta.(*AWSClient).stsconn + + res, err := client.GetCallerIdentity(&sts.GetCallerIdentityInput{}) + if err != nil { + return fmt.Errorf("Error getting Caller Identity: %v", err) + } log.Printf("[DEBUG] Reading Caller Identity.") d.SetId(time.Now().UTC().String()) - if client.accountid == "" { + if *res.Account == "" { log.Println("[DEBUG] No Account ID available, failing") return fmt.Errorf("No AWS Account ID is available to the provider. Please ensure that\n" + "skip_requesting_account_id is not set on the AWS provider.") } - log.Printf("[DEBUG] Setting AWS Account ID to %s.", client.accountid) - d.Set("account_id", meta.(*AWSClient).accountid) - + log.Printf("[DEBUG] Setting AWS Account ID to %s.", *res.Account) + d.Set("account_id", *res.Account) + d.Set("arn", *res.Arn) + d.Set("user_id", *res.UserId) return nil } diff --git a/builtin/providers/aws/data_source_aws_caller_identity_test.go b/builtin/providers/aws/data_source_aws_caller_identity_test.go index f874d7da94de..100bb4db8364 100644 --- a/builtin/providers/aws/data_source_aws_caller_identity_test.go +++ b/builtin/providers/aws/data_source_aws_caller_identity_test.go @@ -39,6 +39,14 @@ func testAccCheckAwsCallerIdentityAccountId(n string) resource.TestCheckFunc { return fmt.Errorf("Incorrect Account ID: expected %q, got %q", expected, rs.Primary.Attributes["account_id"]) } + if rs.Primary.Attributes["user_id"] == "" { + return fmt.Errorf("UserID expected to not be nil") + } + + if rs.Primary.Attributes["arn"] == "" { + return fmt.Errorf("ARN expected to not be nil") + } + return nil } } diff --git a/website/source/docs/providers/aws/d/caller_identity.html.markdown b/website/source/docs/providers/aws/d/caller_identity.html.markdown index ea0b1afccc04..8f4b9974a977 100644 --- a/website/source/docs/providers/aws/d/caller_identity.html.markdown +++ b/website/source/docs/providers/aws/d/caller_identity.html.markdown @@ -9,8 +9,8 @@ description: |- # aws\_caller\_identity -Use this data source to get the access to the effective Account ID in -which Terraform is working. +Use this data source to get the access to the effective Account ID, User ID, and ARN in +which Terraform is authorized. ~> **NOTE on `aws_caller_identity`:** - an Account ID is only available if `skip_requesting_account_id` is not set on the AWS provider. In such @@ -24,6 +24,14 @@ data "aws_caller_identity" "current" {} output "account_id" { value = "${data.aws_caller_identity.current.account_id}" } + +output "caller_arn" { + value = "${data.aws_caller_identity.current.arn}" +} + +output "caller_user" { + value = "${data.aws_caller_identity.current.user_id}" +} ``` ## Argument Reference @@ -32,4 +40,6 @@ There are no arguments available for this data source. ## Attributes Reference -`account_id` is set to the ID of the AWS account. +`account_id` - The AWS Account ID number of the account that owns or contains the calling entity. +`arn` - The AWS ARN associated with the calling entity. +`user_id` - The unique identifier of the calling entity. From f24087ee5437ebf93833dc4c9fbe99978021b52f Mon Sep 17 00:00:00 2001 From: Jake Champlin Date: Thu, 30 Mar 2017 18:11:10 -0400 Subject: [PATCH 2/9] core: Add ImportStateIdPrefix field for testing Adds the `ImportStateIdPrefix` field for import acceptance tests. There are (albeit fairly rare) import cases where a resource needs to be imported with a combination of the resource's ID and a known string prefix. This allows the developer to specify the known prefix, and omit the `ImportStateId` field. ``` $ make test TEST=./helper/resource TESTARGS="-run=TestTest_importStateIdPrefix" ==> Checking that code complies with gofmt requirements... ==> Checking AWS provider for unchecked errors... ==> NOTE: at this time we only look for uncheck errors in the AWS package go generate $(go list ./... | grep -v /terraform/vendor/) 2017/03/30 18:08:36 Generated command/internal_plugin_list.go go test -i ./helper/resource || exit 1 echo ./helper/resource | \ xargs -t -n4 go test -run=TestTest_importStateIdPrefix -timeout=60s -parallel=4 go test -run=TestTest_importStateIdPrefix -timeout=60s -parallel=4 ./helper/resource ok github.com/hashicorp/terraform/helper/resource 0.025s ``` --- helper/resource/testing.go | 7 ++ helper/resource/testing_import_state.go | 4 ++ helper/resource/testing_import_state_test.go | 74 ++++++++++++++++++++ 3 files changed, 85 insertions(+) diff --git a/helper/resource/testing.go b/helper/resource/testing.go index 9557207c3e1d..23af8109600d 100644 --- a/helper/resource/testing.go +++ b/helper/resource/testing.go @@ -174,6 +174,13 @@ type TestStep struct { // determined by inspecting the state for ResourceName's ID. ImportStateId string + // ImportStateIdPrefix is the prefix added in front of ImportStateId. + // This can be useful in complex import cases, where more than one + // attribute needs to be passed on as the Import ID. Mainly in cases + // where the ID is not known, and a known prefix needs to be added to + // the unset ImportStateId field. + ImportStateIdPrefix string + // ImportStateCheck checks the results of ImportState. It should be // used to verify that the resulting value of ImportState has the // proper resources, IDs, and attributes. diff --git a/helper/resource/testing_import_state.go b/helper/resource/testing_import_state.go index d5c579629b09..28ad105267d4 100644 --- a/helper/resource/testing_import_state.go +++ b/helper/resource/testing_import_state.go @@ -25,6 +25,10 @@ func testStepImportState( importId = resource.Primary.ID } + importPrefix := step.ImportStateIdPrefix + if importPrefix != "" { + importId = fmt.Sprintf("%s%s", importPrefix, importId) + } // Setup the context. We initialize with an empty state. We use the // full config for provider configurations. diff --git a/helper/resource/testing_import_state_test.go b/helper/resource/testing_import_state_test.go index 56e6a48450e2..96b1edc3d188 100644 --- a/helper/resource/testing_import_state_test.go +++ b/helper/resource/testing_import_state_test.go @@ -178,6 +178,80 @@ func TestTest_importStateDetectId(t *testing.T) { } } +func TestTest_importStateIdPrefix(t *testing.T) { + mp := testProvider() + mp.DiffReturn = nil + mp.ApplyFn = func( + info *terraform.InstanceInfo, + state *terraform.InstanceState, + diff *terraform.InstanceDiff) (*terraform.InstanceState, error) { + if !diff.Destroy { + return &terraform.InstanceState{ + ID: "foo", + }, nil + } + + return nil, nil + } + + mp.RefreshFn = func( + i *terraform.InstanceInfo, + s *terraform.InstanceState) (*terraform.InstanceState, error) { + return s, nil + } + + mp.ImportStateFn = func( + info *terraform.InstanceInfo, id string) ([]*terraform.InstanceState, error) { + if id != "bazfoo" { + return nil, fmt.Errorf("bad import ID: %s", id) + } + + return []*terraform.InstanceState{ + { + ID: "bar", + Ephemeral: terraform.EphemeralState{Type: "test_instance"}, + }, + }, nil + } + + checked := false + checkFn := func(s []*terraform.InstanceState) error { + checked = true + + if s[0].ID != "bar" { + return fmt.Errorf("bad: %#v", s) + } + + return nil + } + + mt := new(mockT) + Test(mt, TestCase{ + Providers: map[string]terraform.ResourceProvider{ + "test": mp, + }, + + Steps: []TestStep{ + { + Config: testConfigStr, + }, + { + ResourceName: "test_instance.foo", + ImportState: true, + ImportStateCheck: checkFn, + ImportStateIdPrefix: "baz", + }, + }, + }) + + if mt.failed() { + t.Fatalf("test failed: %s", mt.failMessage()) + } + if !checked { + t.Fatal("didn't call check") + } +} + func TestTest_importStateVerify(t *testing.T) { mp := testProvider() mp.DiffReturn = nil From 8050eda52dddf7a62fba602725ca6afdf637fdaf Mon Sep 17 00:00:00 2001 From: James Bardin Date: Fri, 31 Mar 2017 15:21:32 -0400 Subject: [PATCH 3/9] don't delete local state on a local backend Don't erase local state during backend migration if the new and old paths are the same. Skipping the confirmation and copy are handled in another patch, but the local state was always erased by default, even when it was our new state. --- command/meta_backend.go | 28 +++++++++++++++++----- command/meta_backend_test.go | 45 ++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 6 deletions(-) diff --git a/command/meta_backend.go b/command/meta_backend.go index c50214116bc6..afcfe533a0da 100644 --- a/command/meta_backend.go +++ b/command/meta_backend.go @@ -1002,7 +1002,8 @@ func (m *Meta) backend_C_r_s( } // If the local state is not empty, we need to potentially do a - // state migration to the new backend (with user permission). + // state migration to the new backend (with user permission), unless the + // destination is also "local" if localS := localState.State(); !localS.Empty() { // Perform the migration err = m.backendMigrateState(&backendMigrateOpts{ @@ -1015,12 +1016,27 @@ func (m *Meta) backend_C_r_s( return nil, err } - // We always delete the local state - if err := localState.WriteState(nil); err != nil { - return nil, fmt.Errorf(errBackendMigrateLocalDelete, err) + // we usually remove the local state after migration to prevent + // confusion, but adding a default local backend block to the config + // can get us here too. Don't delete our state if the old and new paths + // are the same. + erase := true + if newLocalB, ok := b.(*backendlocal.Local); ok { + if localB, ok := localB.(*backendlocal.Local); ok { + if newLocalB.StatePath == localB.StatePath { + erase = false + } + } } - if err := localState.PersistState(); err != nil { - return nil, fmt.Errorf(errBackendMigrateLocalDelete, err) + + if erase { + // We always delete the local state, unless that was our new state too. + if err := localState.WriteState(nil); err != nil { + return nil, fmt.Errorf(errBackendMigrateLocalDelete, err) + } + if err := localState.PersistState(); err != nil { + return nil, fmt.Errorf(errBackendMigrateLocalDelete, err) + } } } diff --git a/command/meta_backend_test.go b/command/meta_backend_test.go index 143759f98545..ea0085dbaa85 100644 --- a/command/meta_backend_test.go +++ b/command/meta_backend_test.go @@ -3275,6 +3275,51 @@ func TestMetaBackend_configureWithExtra(t *testing.T) { } } +// when confniguring a default local state, don't delete local state +func TestMetaBackend_localDoesNotDeleteLocal(t *testing.T) { + // Create a temporary working directory that is empty + td := tempDir(t) + copy.CopyDir(testFixturePath("init-backend-empty"), td) + defer os.RemoveAll(td) + defer testChdir(t, td)() + + // create our local state + orig := &terraform.State{ + Modules: []*terraform.ModuleState{ + { + Path: []string{"root"}, + Outputs: map[string]*terraform.OutputState{ + "foo": { + Value: "bar", + Type: "string", + }, + }, + }, + }, + } + + err := (&state.LocalState{Path: DefaultStateFilename}).WriteState(orig) + if err != nil { + t.Fatal(err) + } + + m := testMetaBackend(t, nil) + m.forceInitCopy = true + // init the backend + _, err = m.Backend(&BackendOpts{ + Init: true, + }) + if err != nil { + t.Fatalf("bad: %s", err) + } + + // check that we can read the state + s := testStateRead(t, DefaultStateFilename) + if s.Empty() { + t.Fatal("our state was deleted") + } +} + // move options from config to -backend-config func TestMetaBackend_configToExtra(t *testing.T) { // Create a temporary working directory that is empty From efab9e325e7f4510da7cb7735ed43074a4beb355 Mon Sep 17 00:00:00 2001 From: pradeepbhadani Date: Mon, 3 Apr 2017 17:51:20 +0100 Subject: [PATCH 4/9] Fix typo --- .../docs/providers/bitbucket/r/default_reviewers.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/source/docs/providers/bitbucket/r/default_reviewers.html.markdown b/website/source/docs/providers/bitbucket/r/default_reviewers.html.markdown index 29f4f0dc287f..be2333dd773f 100644 --- a/website/source/docs/providers/bitbucket/r/default_reviewers.html.markdown +++ b/website/source/docs/providers/bitbucket/r/default_reviewers.html.markdown @@ -13,7 +13,7 @@ Provides support for setting up default reviewers for your repository. ## Example Usage ``` -# Manage your respository +# Manage your repository resource "bitbucket_default_reviewers" "infrastructure" { owner = "myteam" repository = "terraform-code" From bf8497ed40463204254f4cb9c9c0f24f3803eeba Mon Sep 17 00:00:00 2001 From: pradeepbhadani Date: Mon, 3 Apr 2017 17:52:35 +0100 Subject: [PATCH 5/9] Fix typo --- website/source/docs/providers/bitbucket/r/hook.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/source/docs/providers/bitbucket/r/hook.html.markdown b/website/source/docs/providers/bitbucket/r/hook.html.markdown index 49e991c582f9..404759e188fc 100644 --- a/website/source/docs/providers/bitbucket/r/hook.html.markdown +++ b/website/source/docs/providers/bitbucket/r/hook.html.markdown @@ -15,7 +15,7 @@ This allows you to manage your webhooks on a repository. ## Example Usage ``` -# Manage your respositories hooks +# Manage your repositories hooks resource "bitbucket_hook" "deploy_on_push" { owner = "myteam" repository = "terraform-code" From 40d430ed6670df59544229a9aee3fb7ffdd99758 Mon Sep 17 00:00:00 2001 From: pradeepbhadani Date: Mon, 3 Apr 2017 17:52:50 +0100 Subject: [PATCH 6/9] Fix typo --- .../source/docs/providers/bitbucket/r/repository.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/source/docs/providers/bitbucket/r/repository.html.markdown b/website/source/docs/providers/bitbucket/r/repository.html.markdown index 7d1572a1a701..cc584d9b1fa7 100644 --- a/website/source/docs/providers/bitbucket/r/repository.html.markdown +++ b/website/source/docs/providers/bitbucket/r/repository.html.markdown @@ -16,7 +16,7 @@ private, how to fork the repository and other options. ## Example Usage ``` -# Manage your respository +# Manage your repository resource "bitbucket_repository" "infrastructure" { owner = "myteam" name = "terraform-code" From 75e61606bb74d40667d43292d60baaf30b366aa9 Mon Sep 17 00:00:00 2001 From: Jake Champlin Date: Mon, 3 Apr 2017 14:10:57 -0400 Subject: [PATCH 7/9] dont dereference pointers on Set --- builtin/providers/aws/data_source_aws_caller_identity.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/builtin/providers/aws/data_source_aws_caller_identity.go b/builtin/providers/aws/data_source_aws_caller_identity.go index 95313cea88da..756bc9b525c4 100644 --- a/builtin/providers/aws/data_source_aws_caller_identity.go +++ b/builtin/providers/aws/data_source_aws_caller_identity.go @@ -50,8 +50,8 @@ func dataSourceAwsCallerIdentityRead(d *schema.ResourceData, meta interface{}) e } log.Printf("[DEBUG] Setting AWS Account ID to %s.", *res.Account) - d.Set("account_id", *res.Account) - d.Set("arn", *res.Arn) - d.Set("user_id", *res.UserId) + d.Set("account_id", res.Account) + d.Set("arn", res.Arn) + d.Set("user_id", res.UserId) return nil } From 83afa7bf88c808d0a34686524a4dbc70d07d6cfa Mon Sep 17 00:00:00 2001 From: Jake Champlin Date: Mon, 3 Apr 2017 14:15:01 -0400 Subject: [PATCH 8/9] add bullets to website docs --- .../docs/providers/aws/d/caller_identity.html.markdown | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/website/source/docs/providers/aws/d/caller_identity.html.markdown b/website/source/docs/providers/aws/d/caller_identity.html.markdown index 8f4b9974a977..fdcd41c65f7e 100644 --- a/website/source/docs/providers/aws/d/caller_identity.html.markdown +++ b/website/source/docs/providers/aws/d/caller_identity.html.markdown @@ -40,6 +40,6 @@ There are no arguments available for this data source. ## Attributes Reference -`account_id` - The AWS Account ID number of the account that owns or contains the calling entity. -`arn` - The AWS ARN associated with the calling entity. -`user_id` - The unique identifier of the calling entity. +* `account_id` - The AWS Account ID number of the account that owns or contains the calling entity. +* `arn` - The AWS ARN associated with the calling entity. +* `user_id` - The unique identifier of the calling entity. From c68675bc4fc4424a6ce9f963a246dd509f6183d2 Mon Sep 17 00:00:00 2001 From: Jake Champlin Date: Mon, 3 Apr 2017 14:30:11 -0400 Subject: [PATCH 9/9] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 74e0105820a4..bcfdf2ad2f65 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ IMPROVEMENTS: * provider/aws: Added API Gateway integration update [GH-13249] * provider/aws: Add `identifier` | `name_prefix` to RDS resources [GH-13232] * provider/aws: Validate `aws_ecs_task_definition.container_definitions` [GH-12161] + * provider/aws: Update caller_identity data source [GH-13092] * provider/github: Handle the case when issue labels already exist [GH-13182] * provider/google: Mark `google_container_cluster`'s `client_key` & `password` inside `master_auth` as sensitive [GH-13148] * provider/triton: Move to joyent/triton-go [GH-13225]