Skip to content

Commit

Permalink
Merge branch 'main' into support_cv_notifications
Browse files Browse the repository at this point in the history
  • Loading branch information
rexredinger committed Oct 20, 2022
2 parents 3af18f4 + 94a36e6 commit 21047a2
Show file tree
Hide file tree
Showing 9 changed files with 188 additions and 5 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/nightly-tfe-ci.yml
Expand Up @@ -20,7 +20,7 @@ jobs:
TFE_TOKEN: ${{ secrets.TF_WORKFLOW_TFLOCAL_CLOUD_TFC_TOKEN }}
TF_CLOUD_ORGANIZATION: "hashicorp-v2"
TF_CLOUD_HOSTNAME: "app.terraform.io"
TF_CLOUD_WORKSPACE: "tflocal-go-tfe-nightly"
TF_WORKSPACE: "tflocal-go-tfe-nightly"
run: |
cd tflocal/
terraform init
Expand Down
12 changes: 11 additions & 1 deletion CHANGELOG.md
@@ -1,3 +1,14 @@
# (Unreleased)

## Enhancements

* Add `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 by @tstapler [#552](https://github.com/hashicorp/go-tfe/pull/552)
* Add `NotificationTriggerAssessmentDrifted` and `NotificationTriggerAssessmentFailed` notification trigger types by @lawliet89 [#542](https://github.com/hashicorp/go-tfe/pull/542)

## Bug Fixes
* Fix marshalling of run variables in `RunCreateOptions`. The `Variables` field type in `Run` struct has changed from `[]*RunVariable` to `[]*RunVariableAttr` by @Uk1288 [#531](https://github.com/hashicorp/go-tfe/pull/531)

# v1.10.0

## Enhancements
Expand All @@ -7,7 +18,6 @@

## Bug Fixes
* Fixes null value returned in variable set relationship in `VariableSetVariable` by @sebasslash [#521](https://github.com/hashicorp/go-tfe/pull/521)
* Fix marshalling of run variables in `RunCreateOptions`. The `Variables` field type in `Run` struct has changed from `[]*RunVariable` to `[]*RunVariableAttr` by @Uk1288 [#531](https://github.com/hashicorp/go-tfe/pull/531)

# v1.9.0

Expand Down
4 changes: 2 additions & 2 deletions README.md
Expand Up @@ -88,11 +88,11 @@ This API client covers most of the existing Terraform Cloud API calls and is upd
- [x] Policy Checks
- [x] Policy Sets
- [x] Policy Set Parameters
- [ ] Private Registry
- [x] Private Registry
- [x] Modules
- [x] Providers
- [x] Provider Provider Versions and Platforms
- [ ] GPG Keys
- [x] GPG Keys
- [x] Runs
- [x] Run Tasks
- [ ] Run Tasks Integration
Expand Down
28 changes: 28 additions & 0 deletions helper_test.go
Expand Up @@ -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()

Expand Down
15 changes: 15 additions & 0 deletions mocks/variable_set_mocks.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions organization_membership.go
Expand Up @@ -80,6 +80,13 @@ type OrganizationMembershipListOptions struct {

// Optional: A list of organization member emails to filter by.
Emails []string `url:"filter[email],omitempty"`

// Optional: If specified, restricts results to those matching status value.
Status OrganizationMembershipStatus `url:"filter[status],omitempty"`

// Optional: A query string to search organization memberships by user name
// and email.
Query string `url:"q,omitempty"`
}

// OrganizationMembershipCreateOptions represents the options for creating an organization membership.
Expand Down
40 changes: 40 additions & 0 deletions organization_membership_integration_test.go
Expand Up @@ -103,6 +103,46 @@ func TestOrganizationMembershipsList(t *testing.T) {
})
})

t.Run("with status filter option", func(t *testing.T) {
_, memTest1Cleanup := createOrganizationMembership(t, client, orgTest)
t.Cleanup(memTest1Cleanup)
_, memTest2Cleanup := createOrganizationMembership(t, client, orgTest)
t.Cleanup(memTest2Cleanup)

ml, err := client.OrganizationMemberships.List(ctx, orgTest.Name, &OrganizationMembershipListOptions{
Status: OrganizationMembershipInvited,
})
require.NoError(t, err)

require.Len(t, ml.Items, 2)
for _, member := range ml.Items {
assert.Equal(t, member.Status, OrganizationMembershipInvited)
}
})

t.Run("with search query string", func(t *testing.T) {
memTest1, memTest1Cleanup := createOrganizationMembership(t, client, orgTest)
t.Cleanup(memTest1Cleanup)
_, memTest2Cleanup := createOrganizationMembership(t, client, orgTest)
t.Cleanup(memTest2Cleanup)
_, memTest3Cleanup := createOrganizationMembership(t, client, orgTest)
t.Cleanup(memTest3Cleanup)

t.Run("using an email", func(t *testing.T) {
ml, err := client.OrganizationMemberships.List(ctx, orgTest.Name, &OrganizationMembershipListOptions{
Query: memTest1.Email,
})
require.NoError(t, err)

require.Len(t, ml.Items, 1)
assert.Equal(t, ml.Items[0].Email, memTest1.Email)
})

t.Run("using a user name", func(t *testing.T) {
t.Skip("Skipping, missing Account API support in order to set usernames")
})
})

t.Run("without a valid organization", func(t *testing.T) {
ml, err := client.OrganizationMemberships.List(ctx, badIdentifier, nil)
assert.Nil(t, ml)
Expand Down
29 changes: 29 additions & 0 deletions variable_set.go
Expand Up @@ -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)

Expand Down Expand Up @@ -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) {
Expand Down
56 changes: 55 additions & 1 deletion variable_set_test.go
Expand Up @@ -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)

Expand Down

0 comments on commit 21047a2

Please sign in to comment.