Skip to content

Commit 6a901a5

Browse files
iuri-slywitch-hashicorphelenjwJarrettSpiker
authored
[TF-27661] Add support for HYOK related attributes (#1192)
* initial attribute changes, wip * Add support for HYOK Configurations and OIDC Configurations (#1162) Co-authored-by: Helen Jiang <[email protected]> * Update workspace.go Co-authored-by: Jarrett Spiker <[email protected]> * Add support for HYOK Configurations and OIDC Configurations (#1162) Co-authored-by: Helen Jiang <[email protected]> * Add support for Customer Key Version and Encrypted Data Keys (#1203) Co-authored-by: Jarrett Spiker <[email protected]> * Updating attributes. * Add support for HYOK Configurations and OIDC Configurations (#1162) Co-authored-by: Helen Jiang <[email protected]> * Add support for Customer Key Version and Encrypted Data Keys (#1203) Co-authored-by: Jarrett Spiker <[email protected]> * Updating agent_pool. Added test case. * Updated agent pool integration test file. * Revert commented section. * Updating organization. WIP organization_integration_test. * Updated organization integration test. * Updating attributes. Updating test cases. * Added workspace integration test cases * Updated test cases. * Updated state_version. Updated Read test cases. * Updated hyok tests. Added environment variables. * Updated errors.go * WIP StateVersion * Updated skipHYOKIntegrationTests if-statement. * Added hyok-testing.sh to scripts folder. Finished state_version testing and new functions. * Updated uploading test. * Added comments to UploadSanitizedState. * Updated hyok test cases. * Updating state_version_mocks.go. --------- Co-authored-by: Helen Jiang <[email protected]> Co-authored-by: Jarrett Spiker <[email protected]> Co-authored-by: Helen Jiang <[email protected]>
1 parent eaf7215 commit 6a901a5

22 files changed

+799
-88
lines changed

.github/actions/test-go-tfe/action.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,14 @@ runs:
9797
GITHUB_REGISTRY_MODULE_IDENTIFIER: "hashicorp/terraform-random-module"
9898
GITHUB_REGISTRY_NO_CODE_MODULE_IDENTIFIER: "hashicorp/terraform-random-no-code-module"
9999
OAUTH_CLIENT_GITHUB_TOKEN: "${{ inputs.oauth-client-github-token }}"
100+
SKIP_HYOK_INTEGRATION_TESTS: "${{ inputs.skip-hyok-integration-tests }}"
101+
HYOK_ORGANIZATION_NAME: "${{ inputs.hyok-organization-name }}"
102+
HYOK_WORKSPACE_NAME: "${{ inputs.hyok-workspace-name }}"
103+
HYOK_POOL_ID: "${{ inputs.hyok-pool-id }}"
104+
HYOK_PLAN_ID: "${{ inputs.hyok-plan-id }}"
105+
HYOK_STATE_VERSION_ID: "${{ inputs.hyok-state-version-id }}"
106+
HYOK_CUSTOMER_KEY_VERSION_ID: "${{ inputs.hyok-customer-key-version-id }}"
107+
HYOK_ENCRYPTED_DATA_KEY_ID: "${{ inputs.hyok-encrypted-data-key-id }}"
100108
GO111MODULE: "on"
101109
ENABLE_TFE: ${{ inputs.enterprise }}
102110
run: |

agent_pool.go

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,18 +66,20 @@ type AgentPool struct {
6666
CreatedAt time.Time `jsonapi:"attr,created-at,iso8601"`
6767

6868
// Relations
69-
Organization *Organization `jsonapi:"relation,organization"`
70-
Workspaces []*Workspace `jsonapi:"relation,workspaces"`
71-
AllowedWorkspaces []*Workspace `jsonapi:"relation,allowed-workspaces"`
72-
AllowedProjects []*Project `jsonapi:"relation,allowed-projects"`
73-
ExcludedWorkspaces []*Workspace `jsonapi:"relation,excluded-workspaces"`
69+
Organization *Organization `jsonapi:"relation,organization"`
70+
HYOKConfigurations []*HYOKConfiguration `jsonapi:"relation,hyok-configurations"`
71+
Workspaces []*Workspace `jsonapi:"relation,workspaces"`
72+
AllowedWorkspaces []*Workspace `jsonapi:"relation,allowed-workspaces"`
73+
AllowedProjects []*Project `jsonapi:"relation,allowed-projects"`
74+
ExcludedWorkspaces []*Workspace `jsonapi:"relation,excluded-workspaces"`
7475
}
7576

7677
// A list of relations to include
7778
// https://developer.hashicorp.com/terraform/cloud-docs/api-docs/agents#available-related-resources
7879
type AgentPoolIncludeOpt string
7980

8081
const AgentPoolWorkspaces AgentPoolIncludeOpt = "workspaces"
82+
const AgentPoolHYOKConfigurations AgentPoolIncludeOpt = "hyok-configurations"
8183

8284
type AgentPoolReadOptions struct {
8385
Include []AgentPoolIncludeOpt `url:"include,omitempty"`
@@ -188,7 +190,7 @@ func (s *agentPools) ReadWithOptions(ctx context.Context, agentpoolID string, op
188190
}
189191

190192
u := fmt.Sprintf("agent-pools/%s", url.PathEscape(agentpoolID))
191-
req, err := s.client.NewRequest("GET", u, nil)
193+
req, err := s.client.NewRequest("GET", u, &options)
192194
if err != nil {
193195
return nil, err
194196
}

agent_pool_integration_test.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package tfe
55

66
import (
77
"context"
8+
"os"
89
"testing"
910

1011
"github.com/stretchr/testify/assert"
@@ -343,6 +344,22 @@ func TestAgentPoolsRead(t *testing.T) {
343344
require.NoError(t, err)
344345
assert.NotEmpty(t, k.Workspaces[0])
345346
})
347+
348+
t.Run("read hyok configurations of an agent pool", func(t *testing.T) {
349+
skipHYOKIntegrationTests(t)
350+
351+
// replace the environment variable with a valid agent pool ID that has HYOK configurations
352+
hyokPoolID := os.Getenv("HYOK_POOL_ID")
353+
if hyokPoolID == "" {
354+
t.Fatal("Export a valid HYOK_POOL_ID before running this test!")
355+
}
356+
357+
k, err := client.AgentPools.ReadWithOptions(ctx, hyokPoolID, &AgentPoolReadOptions{
358+
Include: []AgentPoolIncludeOpt{AgentPoolHYOKConfigurations},
359+
})
360+
require.NoError(t, err)
361+
assert.NotEmpty(t, k.HYOKConfigurations)
362+
})
346363
}
347364

348365
func TestAgentPoolsReadCreatedAt(t *testing.T) {

aws_oidc_configuration_integration_test.go

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package tfe
22

33
import (
44
"context"
5+
"os"
56
"testing"
67

78
"github.com/stretchr/testify/assert"
@@ -12,13 +13,17 @@ import (
1213
// To run them locally, follow the instructions outlined in hyok_configuration_integration_test.go
1314

1415
func TestAWSOIDCConfigurationCreateDelete(t *testing.T) {
15-
if skipHYOKIntegrationTests {
16-
t.Skip()
17-
}
16+
skipHYOKIntegrationTests(t)
1817

1918
client := testClient(t)
2019
ctx := context.Background()
2120

21+
// replace the environment variable with a valid organization name that has AWS OIDC HYOK configurations
22+
hyokOrganizationName := os.Getenv("HYOK_ORGANIZATION_NAME")
23+
if hyokOrganizationName == "" {
24+
t.Fatal("Export a valid HYOK_ORGANIZATION_NAME before running this test!")
25+
}
26+
2227
orgTest, err := client.Organizations.Read(ctx, hyokOrganizationName)
2328
if err != nil {
2429
t.Fatal(err)
@@ -48,13 +53,17 @@ func TestAWSOIDCConfigurationCreateDelete(t *testing.T) {
4853
}
4954

5055
func TestAWSOIDCConfigurationRead(t *testing.T) {
51-
if skipHYOKIntegrationTests {
52-
t.Skip()
53-
}
56+
skipHYOKIntegrationTests(t)
5457

5558
client := testClient(t)
5659
ctx := context.Background()
5760

61+
// replace the environment variable with a valid organization name that has AWS OIDC HYOK configurations
62+
hyokOrganizationName := os.Getenv("HYOK_ORGANIZATION_NAME")
63+
if hyokOrganizationName == "" {
64+
t.Fatal("Export a valid HYOK_ORGANIZATION_NAME before running this test!")
65+
}
66+
5867
orgTest, err := client.Organizations.Read(ctx, hyokOrganizationName)
5968
if err != nil {
6069
t.Fatal(err)
@@ -76,13 +85,17 @@ func TestAWSOIDCConfigurationRead(t *testing.T) {
7685
}
7786

7887
func TestAWSOIDCConfigurationsUpdate(t *testing.T) {
79-
if skipHYOKIntegrationTests {
80-
t.Skip()
81-
}
88+
skipHYOKIntegrationTests(t)
8289

8390
client := testClient(t)
8491
ctx := context.Background()
8592

93+
// replace the environment variable with a valid organization name that has AWS OIDC HYOK configurations
94+
hyokOrganizationName := os.Getenv("HYOK_ORGANIZATION_NAME")
95+
if hyokOrganizationName == "" {
96+
t.Fatal("Export a valid HYOK_ORGANIZATION_NAME before running this test!")
97+
}
98+
8699
orgTest, err := client.Organizations.Read(ctx, hyokOrganizationName)
87100
if err != nil {
88101
t.Fatal(err)

azure_oidc_configuration_integration_test.go

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package tfe
22

33
import (
44
"context"
5+
"os"
56
"testing"
67

78
"github.com/stretchr/testify/assert"
@@ -12,13 +13,17 @@ import (
1213
// To run them locally, follow the instructions outlined in hyok_configuration_integration_test.go
1314

1415
func TestAzureOIDCConfigurationCreateDelete(t *testing.T) {
15-
if skipHYOKIntegrationTests {
16-
t.Skip()
17-
}
16+
skipHYOKIntegrationTests(t)
1817

1918
client := testClient(t)
2019
ctx := context.Background()
2120

21+
// replace the environment variable with a valid organization name that has Azure OIDC HYOK configurations
22+
hyokOrganizationName := os.Getenv("HYOK_ORGANIZATION_NAME")
23+
if hyokOrganizationName == "" {
24+
t.Fatal("Export a valid HYOK_ORGANIZATION_NAME before running this test!")
25+
}
26+
2227
orgTest, err := client.Organizations.Read(ctx, hyokOrganizationName)
2328
if err != nil {
2429
t.Fatal(err)
@@ -75,13 +80,17 @@ func TestAzureOIDCConfigurationCreateDelete(t *testing.T) {
7580
}
7681

7782
func TestAzureOIDCConfigurationRead(t *testing.T) {
78-
if skipHYOKIntegrationTests {
79-
t.Skip()
80-
}
83+
skipHYOKIntegrationTests(t)
8184

8285
client := testClient(t)
8386
ctx := context.Background()
8487

88+
// replace the environment variable with a valid organization name that has Azure OIDC HYOK configurations
89+
hyokOrganizationName := os.Getenv("HYOK_ORGANIZATION_NAME")
90+
if hyokOrganizationName == "" {
91+
t.Fatal("Export a valid HYOK_ORGANIZATION_NAME before running this test!")
92+
}
93+
8594
orgTest, err := client.Organizations.Read(ctx, hyokOrganizationName)
8695
if err != nil {
8796
t.Fatal(err)
@@ -103,13 +112,17 @@ func TestAzureOIDCConfigurationRead(t *testing.T) {
103112
}
104113

105114
func TestAzureOIDCConfigurationUpdate(t *testing.T) {
106-
if skipHYOKIntegrationTests {
107-
t.Skip()
108-
}
115+
skipHYOKIntegrationTests(t)
109116

110117
client := testClient(t)
111118
ctx := context.Background()
112119

120+
// replace the environment variable with a valid organization name that has Azure OIDC HYOK configurations
121+
hyokOrganizationName := os.Getenv("HYOK_ORGANIZATION_NAME")
122+
if hyokOrganizationName == "" {
123+
t.Fatal("Export a valid HYOK_ORGANIZATION_NAME before running this test!")
124+
}
125+
113126
orgTest, err := client.Organizations.Read(ctx, hyokOrganizationName)
114127
if err != nil {
115128
t.Fatal(err)

errors.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,9 @@ var (
8989
// it is locked. "conflict" followed by newline is used to preserve go-tfe version
9090
// compatibility with the error constructed at runtime before it was defined here.
9191
ErrWorkspaceLockedCannotDelete = errors.New("conflict\nWorkspace is currently locked. Workspace must be unlocked before it can be safely deleted")
92+
93+
// ErrHYOKCannotBeDisabled is returned when attempting to disable HYOK on a workspace that already has it enabled.
94+
ErrHYOKCannotBeDisabled = errors.New("bad request\n\nhyok may not be disabled once it has been turned on for a workspace")
9295
)
9396

9497
// Invalid values for resources/struct fields
@@ -410,6 +413,8 @@ var (
410413

411414
ErrStateVersionUploadNotSupported = errors.New("upload not supported by this version of Terraform Enterprise")
412415

416+
ErrSanitizedStateUploadURLMissing = errors.New("sanitized state upload URL is missing")
417+
413418
ErrRequiredRoleARN = errors.New("role-arn is required for AWS OIDC configuration")
414419

415420
ErrRequiredServiceAccountEmail = errors.New("service-account-email is required for GCP OIDC configuration")

gcp_oidc_configuration_integration_test.go

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package tfe
22

33
import (
44
"context"
5+
"os"
56
"testing"
67

78
"github.com/stretchr/testify/assert"
@@ -12,13 +13,17 @@ import (
1213
// To run them locally, follow the instructions outlined in hyok_configuration_integration_test.go
1314

1415
func TestGCPOIDCConfigurationCreateDelete(t *testing.T) {
15-
if skipHYOKIntegrationTests {
16-
t.Skip()
17-
}
16+
skipHYOKIntegrationTests(t)
1817

1918
client := testClient(t)
2019
ctx := context.Background()
2120

21+
// replace the environment variable with a valid organization name that has GCP OIDC HYOK configurations
22+
hyokOrganizationName := os.Getenv("HYOK_ORGANIZATION_NAME")
23+
if hyokOrganizationName == "" {
24+
t.Fatal("Export a valid HYOK_ORGANIZATION_NAME before running this test!")
25+
}
26+
2227
orgTest, err := client.Organizations.Read(ctx, hyokOrganizationName)
2328
if err != nil {
2429
t.Fatal(err)
@@ -75,13 +80,17 @@ func TestGCPOIDCConfigurationCreateDelete(t *testing.T) {
7580
}
7681

7782
func TestGCPOIDCConfigurationRead(t *testing.T) {
78-
if skipHYOKIntegrationTests {
79-
t.Skip()
80-
}
83+
skipHYOKIntegrationTests(t)
8184

8285
client := testClient(t)
8386
ctx := context.Background()
8487

88+
// replace the environment variable with a valid organization name that has GCP OIDC HYOK configurations
89+
hyokOrganizationName := os.Getenv("HYOK_ORGANIZATION_NAME")
90+
if hyokOrganizationName == "" {
91+
t.Fatal("Export a valid HYOK_ORGANIZATION_NAME before running this test!")
92+
}
93+
8594
orgTest, err := client.Organizations.Read(ctx, hyokOrganizationName)
8695
if err != nil {
8796
t.Fatal(err)
@@ -103,13 +112,17 @@ func TestGCPOIDCConfigurationRead(t *testing.T) {
103112
}
104113

105114
func TestGCPOIDCConfigurationUpdate(t *testing.T) {
106-
if skipHYOKIntegrationTests {
107-
t.Skip()
108-
}
115+
skipHYOKIntegrationTests(t)
109116

110117
client := testClient(t)
111118
ctx := context.Background()
112119

120+
// replace the environment variable with a valid organization name that has GCP OIDC HYOK configurations
121+
hyokOrganizationName := os.Getenv("HYOK_ORGANIZATION_NAME")
122+
if hyokOrganizationName == "" {
123+
t.Fatal("Export a valid HYOK_ORGANIZATION_NAME before running this test!")
124+
}
125+
113126
orgTest, err := client.Organizations.Read(ctx, hyokOrganizationName)
114127
if err != nil {
115128
t.Fatal(err)

helper_test.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3221,6 +3221,13 @@ func skipIfEnterprise(t *testing.T) {
32213221
}
32223222
}
32233223

3224+
func skipHYOKIntegrationTests(t *testing.T) {
3225+
t.Helper()
3226+
if !hyokIntegrationTestsEnabled() {
3227+
t.Skip("Skipping test related to HYOK features. Set ENABLE_HYOK_INTEGRATION_TESTS=1 to run.")
3228+
}
3229+
}
3230+
32243231
// skips a test if the underlying beta feature is not available.
32253232
// **Note: ENABLE_BETA is always disabled in CI, so ensure you:
32263233
//
@@ -3269,6 +3276,11 @@ func betaFeaturesEnabled() bool {
32693276
return os.Getenv("ENABLE_BETA") == "1"
32703277
}
32713278

3279+
// Checks to see if HYOK_INTEGRATION_TESTS is set to 1, thereby enabling tests for HYOK features.
3280+
func hyokIntegrationTestsEnabled() bool {
3281+
return os.Getenv("ENABLE_HYOK_INTEGRATION_TESTS") == "1"
3282+
}
3283+
32723284
// isEmpty gets whether the specified object is considered empty or not.
32733285
func isEmpty(object interface{}) bool {
32743286
// get nil case out of the way

0 commit comments

Comments
 (0)