diff --git a/CHANGELOG.md b/CHANGELOG.md index 1db49b805..a845e5740 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,8 +3,8 @@ ## Enhancements * Adds `RetryServerErrors` field to the `Config` object by @sebasslash [#439](https://github.com/hashicorp/go-tfe/pull/439) * Adds support for the GPG Keys API by @sebasslash [#429](https://github.com/hashicorp/go-tfe/pull/429) -* [beta] Renames the optional StateVersion field `ExtState` to `JSONState` and changes to string for base64 encoding by @annawinkler [#444](https://github.com/hashicorp/go-tfe/pull/444) * Add support for new `WorkspaceLimit` Admin setting for organizations [#425](https://github.com/hashicorp/go-tfe/pull/425) +* [beta] Renames the optional StateVersion field `ExtState` to `JSONStateOutputs` and changes the purpose and type by @annawinkler [#444](https://github.com/hashicorp/go-tfe/pull/444) and @brandoncroft [#452](https://github.com/hashicorp/go-tfe/pull/452) # v1.3.0 diff --git a/configuration_version_integration_test.go b/configuration_version_integration_test.go index fe028698e..b85e6790e 100644 --- a/configuration_version_integration_test.go +++ b/configuration_version_integration_test.go @@ -7,10 +7,12 @@ import ( "bytes" "context" "encoding/json" - "github.com/hashicorp/go-slug" + "errors" "testing" "time" + "github.com/hashicorp/go-slug" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -155,22 +157,25 @@ func TestConfigurationVersionsReadWithOptions(t *testing.T) { wTest, wTestCleanup := createWorkspaceWithVCS(t, client, orgTest, WorkspaceCreateOptions{QueueAllRuns: Bool(true)}) defer wTestCleanup() - // Hack: Wait for TFC to ingress the configuration and queue a run - time.Sleep(3 * time.Second) + w, err := retry(func() (interface{}, error) { + w, err := client.Workspaces.ReadByIDWithOptions(ctx, wTest.ID, &WorkspaceReadOptions{ + Include: []WSIncludeOpt{WSCurrentRunConfigVer}, + }) - w, err := client.Workspaces.ReadByIDWithOptions(ctx, wTest.ID, &WorkspaceReadOptions{ - Include: []WSIncludeOpt{WSCurrentRunConfigVer}, - }) + if err != nil { + return nil, err + } - if err != nil { - require.NoError(t, err) - } + if w.CurrentRun == nil { + return nil, errors.New("A run was expected to be found on this workspace as a test pre-condition") + } - if w.CurrentRun == nil { - t.Fatal("A run was expected to be found on this workspace as a test pre-condition") - } + return w, nil + }) + + require.NoError(t, err) - cv := w.CurrentRun.ConfigurationVersion + cv := w.(*Workspace).CurrentRun.ConfigurationVersion t.Run("when the configuration version exists", func(t *testing.T) { options := &ConfigurationVersionReadOptions{ diff --git a/oauth_client_integration_test.go b/oauth_client_integration_test.go index b9b0817d1..2927097b1 100644 --- a/oauth_client_integration_test.go +++ b/oauth_client_integration_test.go @@ -5,6 +5,7 @@ package tfe import ( "context" + "fmt" "os" "testing" @@ -247,8 +248,14 @@ func TestOAuthClientsDelete(t *testing.T) { err := client.OAuthClients.Delete(ctx, ocTest.ID) require.NoError(t, err) - // Try loading the OAuth client - it should fail. - _, err = client.OAuthClients.Read(ctx, ocTest.ID) + _, err = retry(func() (interface{}, error) { + c, err := client.OAuthClients.Read(ctx, ocTest.ID) + if err != ErrResourceNotFound { + return nil, fmt.Errorf("expected %s, but err was %s", ErrResourceNotFound, err) + } + return c, err + }) + assert.Equal(t, err, ErrResourceNotFound) }) diff --git a/state_version.go b/state_version.go index 078d3e177..39173aafb 100644 --- a/state_version.go +++ b/state_version.go @@ -139,13 +139,13 @@ type StateVersionCreateOptions struct { // Optional: Specifies the run to associate the state with. Run *Run `jsonapi:"relation,run,omitempty"` - // Optional: The external, json representation of state data, base64 encoded. - // https://www.terraform.io/internals/json-format#state-representation - // Supplying this state representation can provide more details to the platform + // Optional: The external, json representation of state outputs, base64 encoded. Supplying this field + // will provide more detailed output type information to TFE. + // For more information on the contents of this field: https://www.terraform.io/internals/json-format#values-representation // about the current terraform state. // // **Note**: This field is in BETA, subject to change and not widely available yet. - JSONState *string `jsonapi:"attr,json-state,omitempty"` + JSONStateOutputs *string `jsonapi:"attr,json-state-outputs,omitempty"` } // List all the state versions for a given workspace. diff --git a/state_version_integration_test.go b/state_version_integration_test.go index de4166999..35e086e04 100644 --- a/state_version_integration_test.go +++ b/state_version_integration_test.go @@ -121,7 +121,7 @@ func TestStateVersionsCreate(t *testing.T) { t.Fatal(err) } - jsonState, err := ioutil.ReadFile("test-fixtures/ext-state-version/state.json") + jsonStateOutputs, err := ioutil.ReadFile("test-fixtures/json-state-outputs/everything.json") if err != nil { t.Fatal(err) } @@ -169,11 +169,11 @@ func TestStateVersionsCreate(t *testing.T) { } sv, err := client.StateVersions.Create(ctx, wTest.ID, StateVersionCreateOptions{ - Lineage: String("741c4949-60b9-5bb1-5bf8-b14f4bb14af3"), - MD5: String(fmt.Sprintf("%x", md5.Sum(state))), - Serial: Int64(1), - State: String(base64.StdEncoding.EncodeToString(state)), - JSONState: String(base64.StdEncoding.EncodeToString(jsonState)), + Lineage: String("741c4949-60b9-5bb1-5bf8-b14f4bb14af3"), + MD5: String(fmt.Sprintf("%x", md5.Sum(state))), + Serial: Int64(1), + State: String(base64.StdEncoding.EncodeToString(state)), + JSONStateOutputs: String(base64.StdEncoding.EncodeToString(jsonStateOutputs)), }) require.NoError(t, err) @@ -186,6 +186,8 @@ func TestStateVersionsCreate(t *testing.T) { t.Fatal(err) } + // TODO: check state outputs for the ones we sent in JSONStateOutputs + for _, item := range []*StateVersion{ sv, refreshed, diff --git a/test-fixtures/ext-state-version/state.json b/test-fixtures/ext-state-version/state.json deleted file mode 100644 index 5acced8cc..000000000 --- a/test-fixtures/ext-state-version/state.json +++ /dev/null @@ -1,163 +0,0 @@ -{ - "format_version": "1.0", - "terraform_version": "1.2.0", - "values": { - "outputs": { - "a-decimal": { - "sensitive": false, - "value": 1000.1, - "type": "number" - }, - "a-false-bool": { - "sensitive": false, - "value": false, - "type": "bool" - }, - "a-list": { - "sensitive": false, - "value": [ - "example", - "1001", - "1000.1" - ], - "type": [ - "list", - "string" - ] - }, - "a-long-string": { - "sensitive": false, - "value": "The private integer of the main server instance is where you want to go when you have the most fun in every Terraform instance you can see in the world that you live in except for dogs because they don't run servers in the same place that humans do.", - "type": "string" - }, - "a-object": { - "sensitive": false, - "value": { - "bar": 1000.1, - "example": 1001 - }, - "type": [ - "object", - { - "bar": "number", - "example": "number" - } - ] - }, - "a-sensitive-value": { - "sensitive": true, - "value": "hopefully you cannot see me", - "type": "string" - }, - "a-string": { - "sensitive": false, - "value": "example string", - "type": "string" - }, - "a-true-bool": { - "sensitive": false, - "value": true, - "type": "bool" - }, - "a-tuple": { - "sensitive": false, - "value": [ - 1, - "example" - ], - "type": [ - "tuple", - [ - "number", - "string" - ] - ] - }, - "an-int": { - "sensitive": false, - "value": 1001, - "type": "number" - }, - "escapes": { - "sensitive": false, - "value": "line 1\nline 2\n\\\\\\\\\n", - "type": "string" - }, - "myoutput": { - "sensitive": false, - "value": { - "nesting1": { - "nesting2": { - "nesting3": "4263891374290101092" - } - } - }, - "type": [ - "object", - { - "nesting1": [ - "object", - { - "nesting2": [ - "object", - { - "nesting3": "string" - } - ] - } - ] - } - ] - }, - "random": { - "sensitive": false, - "value": "8b3086889a9ef7a5", - "type": "string" - } - }, - "root_module": { - "resources": [ - { - "address": "null_resource.test", - "mode": "managed", - "type": "null_resource", - "name": "test", - "provider_name": "registry.terraform.io/hashicorp/null", - "schema_version": 0, - "values": { - "id": "4263891374290101092", - "triggers": { - "hello": "wat3" - } - }, - "sensitive_values": { - "triggers": {} - } - }, - { - "address": "random_id.random", - "mode": "managed", - "type": "random_id", - "name": "random", - "provider_name": "registry.terraform.io/hashicorp/random", - "schema_version": 0, - "values": { - "b64_std": "izCGiJqe96U=", - "b64_url": "izCGiJqe96U", - "byte_length": 8, - "dec": "10029664291421878181", - "hex": "8b3086889a9ef7a5", - "id": "izCGiJqe96U", - "keepers": { - "uuid": "437a1415-932b-9f74-c214-184d88215353" - }, - "prefix": null - }, - "sensitive_values": { - "keepers": {} - } - } - ] - } - } -} diff --git a/test-fixtures/json-state-outputs/everything.json b/test-fixtures/json-state-outputs/everything.json new file mode 100644 index 000000000..66c5b45b6 --- /dev/null +++ b/test-fixtures/json-state-outputs/everything.json @@ -0,0 +1,113 @@ +{ + "a-decimal": { + "sensitive": false, + "value": 1000.1, + "type": "number" + }, + "a-false-bool": { + "sensitive": false, + "value": false, + "type": "bool" + }, + "a-list": { + "sensitive": false, + "value": [ + "example", + "1001", + "1000.1" + ], + "type": [ + "list", + "string" + ] + }, + "a-long-string": { + "sensitive": false, + "value": "The private integer of the main server instance is where you want to go when you have the most fun in every Terraform instance you can see in the world that you live in except for dogs because they don't run servers in the same place that humans do.", + "type": "string" + }, + "a-object": { + "sensitive": false, + "value": { + "bar": 1000.1, + "example": 1001 + }, + "type": [ + "object", + { + "bar": "number", + "example": "number" + } + ] + }, + "a-sensitive-value": { + "sensitive": true, + "value": "hopefully you cannot see me", + "type": "string" + }, + "a-string": { + "sensitive": false, + "value": "example string", + "type": "string" + }, + "a-true-bool": { + "sensitive": false, + "value": true, + "type": "bool" + }, + "a-tuple": { + "sensitive": false, + "value": [ + 1, + "example" + ], + "type": [ + "tuple", + [ + "number", + "string" + ] + ] + }, + "an-int": { + "sensitive": false, + "value": 1001, + "type": "number" + }, + "escapes": { + "sensitive": false, + "value": "line 1\nline 2\n\\\\\\\\\n", + "type": "string" + }, + "myoutput": { + "sensitive": false, + "value": { + "nesting1": { + "nesting2": { + "nesting3": "4263891374290101092" + } + } + }, + "type": [ + "object", + { + "nesting1": [ + "object", + { + "nesting2": [ + "object", + { + "nesting3": "string" + } + ] + } + ] + } + ] + }, + "random": { + "sensitive": false, + "value": "8b3086889a9ef7a5", + "type": "string" + } +} diff --git a/workspace_integration_test.go b/workspace_integration_test.go index d5264d912..2604f1a47 100644 --- a/workspace_integration_test.go +++ b/workspace_integration_test.go @@ -472,11 +472,24 @@ func TestWorkspacesReadWithHistory(t *testing.T) { _, rCleanup := createRunApply(t, client, wTest) defer rCleanup() - w, err := client.Workspaces.Read(context.Background(), orgTest.Name, wTest.Name) - require.NoError(t, err) + _, err := retry(func() (interface{}, error) { + w, err := client.Workspaces.Read(context.Background(), orgTest.Name, wTest.Name) + require.NoError(t, err) + + if w.RunsCount != 1 { + return nil, fmt.Errorf("expected %d runs but found %d", 1, w.RunsCount) + } + + if w.ResourceCount != 1 { + return nil, fmt.Errorf("expected %d resources but found %d", 1, w.ResourceCount) + } + + return w, nil + }) - assert.Equal(t, 1, w.RunsCount) - assert.Equal(t, 1, w.ResourceCount) + if err != nil { + t.Error(err) + } } func TestWorkspacesReadReadme(t *testing.T) {