Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: add support for applying/removing variable set against workspaces #375

Merged
merged 16 commits into from May 2, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
75 changes: 74 additions & 1 deletion variable_set.go
Expand Up @@ -29,7 +29,13 @@ type VariableSets interface {
// Delete a variable set by ID.
Delete(ctx context.Context, variableSetID string) error

// Update list of workspaces to which the variable set is applied to match the supplied list
// Apply variable set to workspaces in the supplied list.
ApplyToWorkspaces(ctx context.Context, variableSetID string, options *VariableSetApplyToWorkspacesOptions) error

// Remove variable set from workspaces in the supplied list.
RemoveFromWorkspaces(ctx context.Context, variableSetID string, options *VariableSetRemoveFromWorkspacesOptions) error

// Update list of workspaces to which the variable set is applied to match the supplied list.
UpdateWorkspaces(ctx context.Context, variableSetID string, options *VariableSetUpdateWorkspacesOptions) (*VariableSet, error)
}

Expand Down Expand Up @@ -200,6 +206,7 @@ type VariableSetUpdateOptions struct {
Global *bool `jsonapi:"attr,global,omitempty"`
}

// Update an existing variable set.
func (s *variableSets) Update(ctx context.Context, variableSetID string, options *VariableSetUpdateOptions) (*VariableSet, error) {
if !validStringID(&variableSetID) {
return nil, ErrInvalidVariableSetID
Expand Down Expand Up @@ -235,6 +242,72 @@ func (s *variableSets) Delete(ctx context.Context, variableSetID string) error {
return s.client.do(ctx, req, nil)
}

// VariableSetApplyToWorkspacesOptions represents the options for applying variable sets to workspaces.
type VariableSetApplyToWorkspacesOptions struct {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We've established a convention for v1.0 that lays out the structure for any given file: 1) Interface/Struct definitions, 2) Receiver methods and 3) validate/helper methods.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to be clear, it should be all structs at the top of the file, followed by receiver methods and so on...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cheers, happy to move these. To be clear: would you like me to move just these newly-added structs, or all previously-existing ones too? It looks like workspace.tf follows the convention you're describing as a matter of prior art.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes if you would not mind reorganizing the file that would be great! 🚀

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed, but this may make the diff somewhat more difficult to read. I've split the re-arrangement into its own commit, here: ba9fb5d

// The workspaces to apply the variable set to (additive).
Workspaces []*Workspace
}

func (o *VariableSetApplyToWorkspacesOptions) valid() error {
for _, s := range o.Workspaces {
if !validStringID(&s.ID) {
return ErrRequiredWorkspaceID
}
}
return nil
}

// Apply variable set to workspaces in the supplied list.
func (s *variableSets) ApplyToWorkspaces(ctx context.Context, variableSetID string, options *VariableSetApplyToWorkspacesOptions) error {
if !validStringID(&variableSetID) {
return ErrInvalidVariableSetID
}
if err := options.valid(); err != nil {
return err
}

u := fmt.Sprintf("varsets/%s/relationships/workspaces", url.QueryEscape(variableSetID))
req, err := s.client.newRequest("POST", u, options.Workspaces)
if err != nil {
return err
}

return s.client.do(ctx, req, nil)
}

// VariableSetRemoveFromWorkspacesOptions represents the options for removing variable sets from workspaces.
type VariableSetRemoveFromWorkspacesOptions struct {
// The workspaces to remove the variable set from.
Workspaces []*Workspace
}

func (o *VariableSetRemoveFromWorkspacesOptions) valid() error {
for _, s := range o.Workspaces {
if !validStringID(&s.ID) {
return ErrRequiredWorkspaceID
}
}
return nil
}

// Remove variable set from workspaces in the supplied list.
func (s *variableSets) RemoveFromWorkspaces(ctx context.Context, variableSetID string, options *VariableSetRemoveFromWorkspacesOptions) error {
if !validStringID(&variableSetID) {
return ErrInvalidVariableSetID
}
if err := options.valid(); err != nil {
return err
}

u := fmt.Sprintf("varsets/%s/relationships/workspaces", url.QueryEscape(variableSetID))
req, err := s.client.newRequest("DELETE", u, options.Workspaces)
if err != nil {
return err
}

return s.client.do(ctx, req, nil)
}

// VariableSetUpdateWorkspacesOptions represents a subset of update options specifically for applying variable sets to workspaces
type VariableSetUpdateWorkspacesOptions struct {
// Type is a public field utilized by JSON:API to
Expand Down
61 changes: 61 additions & 0 deletions variable_set_test.go
Expand Up @@ -190,6 +190,67 @@ func TestVariableSetsDelete(t *testing.T) {
})
}

func TestVariableSetsApplyToAndRemoveFromWorkspaces(t *testing.T) {
client := testClient(t)
ctx := context.Background()

orgTest, orgTestCleanup := createOrganization(t, client)
defer orgTestCleanup()

vsTest, _ := createVariableSet(t, client, orgTest, VariableSetCreateOptions{})
byronwolfman marked this conversation as resolved.
Show resolved Hide resolved

wTest1, _ := createWorkspace(t, client, orgTest)
wTest2, _ := createWorkspace(t, client, orgTest)

t.Run("with first workspace added", func(t *testing.T) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would love to see some test cases for invalid options

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cheers, will add some more test cases!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, some test cases added for invalid options in bd4f215 (and hilariously corrected via 0fac7ae).

options := VariableSetApplyToWorkspacesOptions{
Workspaces: []*Workspace{wTest1},
}

err := client.VariableSets.ApplyToWorkspaces(ctx, vsTest.ID, &options)
require.NoError(t, err)

vsAfter, err := client.VariableSets.Read(ctx, vsTest.ID, nil)
require.NoError(t, err)

// Variable set should be applied to [wTest1]
assert.Equal(t, len(options.Workspaces), len(vsAfter.Workspaces))
assert.Equal(t, options.Workspaces[0].ID, vsAfter.Workspaces[0].ID)
})

t.Run("with second workspace added", func(t *testing.T) {
options := VariableSetApplyToWorkspacesOptions{
Workspaces: []*Workspace{wTest2},
}

err := client.VariableSets.ApplyToWorkspaces(ctx, vsTest.ID, &options)
require.NoError(t, err)

vsAfter, err := client.VariableSets.Read(ctx, vsTest.ID, nil)
require.NoError(t, err)

// Variable set should be applied to [wTest1, wTest2]
assert.Equal(t, len(options.Workspaces), len(vsAfter.Workspaces))
assert.Equal(t, options.Workspaces[1].ID, vsAfter.Workspaces[1].ID)
})

t.Run("with first workspace removed", func(t *testing.T) {
options := VariableSetRemoveFromWorkspacesOptions{
Workspaces: []*Workspace{wTest1},
}

err := client.VariableSets.RemoveFromWorkspaces(ctx, vsTest.ID, &options)
require.NoError(t, err)

vsAfter, err := client.VariableSets.Read(ctx, vsTest.ID, nil)
require.NoError(t, err)

// Variable set should be applied to [wTest2]
assert.Equal(t, 1, len(vsAfter.Workspaces))
assert.Equal(t, wTest2.ID, vsAfter.Workspaces[0].ID)
})
}

func TestVariableSetsUpdateWorkspaces(t *testing.T) {
client := testClient(t)
ctx := context.Background()
Expand Down