From 6dbb1b33b2c6e5c95c90fbd7205e17701387f407 Mon Sep 17 00:00:00 2001 From: Tyler Stapler Date: Tue, 30 Aug 2022 13:00:38 -0700 Subject: [PATCH 1/3] Add method to list variable sets by workspace --- helper_test.go | 28 ++++++++++++++++++++++ variable_set.go | 29 +++++++++++++++++++++++ variable_set_test.go | 56 +++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 112 insertions(+), 1 deletion(-) diff --git a/helper_test.go b/helper_test.go index 7e8b25f6e..1a3f6b194 100644 --- a/helper_test.go +++ b/helper_test.go @@ -1742,6 +1742,34 @@ func createVariableSet(t *testing.T, client *Client, org *Organization, options } } +func applyVariableSetToWorkspace(t *testing.T, client *Client, vsID string, wsID string) { + if vsID == "" { + t.Fatal("variable set ID must not be empty") + } + + if wsID == "" { + t.Fatal("workspace ID must not be empty") + } + + opts := &VariableSetApplyToWorkspacesOptions{} + opts.Workspaces = append(opts.Workspaces, &Workspace{ID: wsID}) + + ctx := context.Background() + if err := client.VariableSets.ApplyToWorkspaces(ctx, vsID, opts); err != nil { + t.Fatalf("Error applying variable set %s to workspace %s: %v", vsID, wsID, err) + } + + t.Cleanup(func() { + removeOpts := &VariableSetRemoveFromWorkspacesOptions{} + removeOpts.Workspaces = append(removeOpts.Workspaces, &Workspace{ID: wsID}) + if err := client.VariableSets.RemoveFromWorkspaces(ctx, vsID, removeOpts); err != nil { + t.Errorf("Error removing variable set from workspace! WARNING: Dangling resources\n"+ + "may exist! The full error is shown below.\n\n"+ + "VariableSet ID: %s\nError: %s", vsID, err) + } + }) +} + func createVariableSetVariable(t *testing.T, client *Client, vs *VariableSet, options VariableSetVariableCreateOptions) (*VariableSetVariable, func()) { var vsCleanup func() diff --git a/variable_set.go b/variable_set.go index 3a9a1f9ec..6bc37c6a5 100644 --- a/variable_set.go +++ b/variable_set.go @@ -17,6 +17,9 @@ type VariableSets interface { // List all the variable sets within an organization. List(ctx context.Context, organization string, options *VariableSetListOptions) (*VariableSetList, error) + // ListForWorkspace gets the associated variable sets for a workspace. + ListForWorkspace(ctx context.Context, workspaceID string, options *VariableSetListOptions) (*VariableSetList, error) + // Create is used to create a new variable set. Create(ctx context.Context, organization string, options *VariableSetCreateOptions) (*VariableSet, error) @@ -179,6 +182,32 @@ func (s *variableSets) List(ctx context.Context, organization string, options *V return vl, nil } +// ListForWorkspace gets the associated variable sets for a workspace. +func (s *variableSets) ListForWorkspace(ctx context.Context, workspaceID string, options *VariableSetListOptions) (*VariableSetList, error) { + if !validStringID(&workspaceID) { + return nil, ErrInvalidWorkspaceID + } + if options != nil { + if err := options.valid(); err != nil { + return nil, err + } + } + + u := fmt.Sprintf("workspaces/%s/varsets", url.QueryEscape(workspaceID)) + req, err := s.client.NewRequest("GET", u, options) + if err != nil { + return nil, err + } + + vl := &VariableSetList{} + err = req.Do(ctx, vl) + if err != nil { + return nil, err + } + + return vl, nil +} + // Create is used to create a new variable set. func (s *variableSets) Create(ctx context.Context, organization string, options *VariableSetCreateOptions) (*VariableSet, error) { if !validStringID(&organization) { diff --git a/variable_set_test.go b/variable_set_test.go index 8af5b7652..c3fcd7d98 100644 --- a/variable_set_test.go +++ b/variable_set_test.go @@ -51,13 +51,67 @@ func TestVariableSetsList(t *testing.T) { assert.Equal(t, 2, vsl.TotalCount) }) - t.Run("when Organization name is invalid ID", func(t *testing.T) { + t.Run("when Organization name is an invalid ID", func(t *testing.T) { vsl, err := client.VariableSets.List(ctx, badIdentifier, nil) assert.Nil(t, vsl) assert.EqualError(t, err, ErrInvalidOrg.Error()) }) } +func TestVariableSetsListForWorkspace(t *testing.T) { + skipIfNotCINode(t) + + client := testClient(t) + ctx := context.Background() + + orgTest, orgTestCleanup := createOrganization(t, client) + t.Cleanup(orgTestCleanup) + workspaceTest, workspaceTestCleanup := createWorkspace(t, client, orgTest) + t.Cleanup(workspaceTestCleanup) + + vsTest1, vsTestCleanup1 := createVariableSet(t, client, orgTest, VariableSetCreateOptions{}) + t.Cleanup(vsTestCleanup1) + vsTest2, vsTestCleanup2 := createVariableSet(t, client, orgTest, VariableSetCreateOptions{}) + t.Cleanup(vsTestCleanup2) + + applyVariableSetToWorkspace(t, client, vsTest1.ID, workspaceTest.ID) + applyVariableSetToWorkspace(t, client, vsTest2.ID, workspaceTest.ID) + + t.Run("without list options", func(t *testing.T) { + vsl, err := client.VariableSets.ListForWorkspace(ctx, workspaceTest.ID, nil) + require.NoError(t, err) + require.Len(t, vsl.Items, 2) + + ids := []string{vsTest1.ID, vsTest2.ID} + for _, varset := range vsl.Items { + assert.Contains(t, ids, varset.ID) + } + }) + + t.Run("with list options", func(t *testing.T) { + t.Skip("paging not supported yet in API") + // Request a page number which is out of range. The result should + // be successful, but return no results if the paging options are + // properly passed along. + vsl, err := client.VariableSets.ListForWorkspace(ctx, workspaceTest.ID, &VariableSetListOptions{ + ListOptions: ListOptions{ + PageNumber: 999, + PageSize: 100, + }, + }) + require.NoError(t, err) + assert.Empty(t, vsl.Items) + assert.Equal(t, 999, vsl.CurrentPage) + assert.Equal(t, 2, vsl.TotalCount) + }) + + t.Run("when Workspace ID is an invalid ID", func(t *testing.T) { + vsl, err := client.VariableSets.ListForWorkspace(ctx, badIdentifier, nil) + assert.Nil(t, vsl) + assert.EqualError(t, err, ErrInvalidWorkspaceID.Error()) + }) +} + func TestVariableSetsCreate(t *testing.T) { skipIfNotCINode(t) From 092d1b7327414e5131402c9339de168febd9cd90 Mon Sep 17 00:00:00 2001 From: Sebastian Rivera Date: Mon, 17 Oct 2022 13:31:44 -0400 Subject: [PATCH 2/3] Update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5954d9db6..ab4b2d6f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,9 @@ # (Unreleased) ## Enhancements + * Adds `Query` and `Status` fields to `OrganizationMembershipListOptions` to allow filtering memberships by status or username by @sebasslash [#550](https://github.com/hashicorp/go-tfe/pull/550) +* Add `ListForWorkspace` method to `VariableSets` interface to enable fetching variable sets associated with a workspace. [#551](https://github.com/hashicorp/go-tfe/pull/551) # v1.10.0 From 5d4da4e3864517d759c57acd31d2381112fba463 Mon Sep 17 00:00:00 2001 From: Sebastian Rivera Date: Mon, 17 Oct 2022 13:34:28 -0400 Subject: [PATCH 3/3] Regenerate mocks --- mocks/variable_set_mocks.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/mocks/variable_set_mocks.go b/mocks/variable_set_mocks.go index 56d02c9ab..5ac9aa699 100644 --- a/mocks/variable_set_mocks.go +++ b/mocks/variable_set_mocks.go @@ -93,6 +93,21 @@ func (mr *MockVariableSetsMockRecorder) List(ctx, organization, options interfac return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "List", reflect.TypeOf((*MockVariableSets)(nil).List), ctx, organization, options) } +// ListForWorkspace mocks base method. +func (m *MockVariableSets) ListForWorkspace(ctx context.Context, workspaceID string, options *tfe.VariableSetListOptions) (*tfe.VariableSetList, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ListForWorkspace", ctx, workspaceID, options) + ret0, _ := ret[0].(*tfe.VariableSetList) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ListForWorkspace indicates an expected call of ListForWorkspace. +func (mr *MockVariableSetsMockRecorder) ListForWorkspace(ctx, workspaceID, options interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListForWorkspace", reflect.TypeOf((*MockVariableSets)(nil).ListForWorkspace), ctx, workspaceID, options) +} + // Read mocks base method. func (m *MockVariableSets) Read(ctx context.Context, variableSetID string, options *tfe.VariableSetReadOptions) (*tfe.VariableSet, error) { m.ctrl.T.Helper()