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

Filter teams by name, org members by email #393

Merged
merged 5 commits into from May 5, 2022
Merged
Show file tree
Hide file tree
Changes from 4 commits
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
7 changes: 5 additions & 2 deletions CHANGELOG.md
@@ -1,10 +1,13 @@
# v1.2.0 (Unreleased)

## Enhancements
* Adds support for reading current state version outputs to StateVersionOutputs, which can be useful for reading outputs when users don't have the necessary permissions to read the entire state.
* Adds Variable Set methods for `ApplyToWorkspaces` and `RemoveFromWorkspaces` [#375](https://github.com/hashicorp/go-tfe/pull/375)
* Adds support for reading current state version outputs to StateVersionOutputs, which can be useful for reading outputs when users don't have the necessary permissions to read the entire state by @brandonc [#370](https://github.com/hashicorp/go-tfe/pull/370)
* Adds Variable Set methods for `ApplyToWorkspaces` and `RemoveFromWorkspaces` by @byronwolfman [#375](https://github.com/hashicorp/go-tfe/pull/375)
* Adds `Names` query param field to `TeamListOptions` by @sebasslash [#393](https://github.com/hashicorp/go-tfe/pull/393)
* Adds `Emails` query param field to `OrganizationMembershipListOptions` by @sebasslash [#393](https://github.com/hashicorp/go-tfe/pull/393)
* Adds Run Tasks API support by @glennsarti [#381](https://github.com/hashicorp/go-tfe/pull/381), [#382](https://github.com/hashicorp/go-tfe/pull/382) and [#383](https://github.com/hashicorp/go-tfe/pull/383)


## Bug fixes
* Fixes ignored comment when performing apply, discard, cancel, and force-cancel run actions [#388](https://github.com/hashicorp/go-tfe/pull/388)

Expand Down
4 changes: 4 additions & 0 deletions errors.go
Expand Up @@ -262,4 +262,8 @@ var (
ErrRequiredWorkspacesList = errors.New("no workspaces list provided")

ErrCommentBody = errors.New("comment body is required")

ErrEmptyTeamName = errors.New("team name can not be empty")
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
ErrEmptyTeamName = errors.New("team name can not be empty")
ErrEmptyTeamName = errors.New("team name cannot be empty")

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm asking @laurapacilio about this because ... after doing a quick search I realized that this suggestion may not be consistent with what we do as a company.


ErrInvalidEmail = errors.New("email is invalid")
)
17 changes: 17 additions & 0 deletions organization_membership.go
Expand Up @@ -77,6 +77,9 @@ type OrganizationMembershipListOptions struct {
// Optional: A list of relations to include. See available resources
// https://www.terraform.io/cloud-docs/api-docs/organization-memberships#available-related-resources
Include []OrgMembershipIncludeOpt `url:"include,omitempty"`

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

Choose a reason for hiding this comment

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

should this be,

Suggested change
Emails []string `url:"filter[email],omitempty"`
Emails []string `url:"filter[emails],omitempty"`

Copy link
Contributor Author

Choose a reason for hiding this comment

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

}

// OrganizationMembershipCreateOptions represents the options for creating an organization membership.
Expand Down Expand Up @@ -206,6 +209,10 @@ func (o *OrganizationMembershipListOptions) valid() error {
return err
}

if err := validateOrgMembershipEmailParams(o.Emails); err != nil {
return err
}

return nil
}

Expand All @@ -229,3 +236,13 @@ func validateOrgMembershipIncludeParams(params []OrgMembershipIncludeOpt) error

return nil
}

func validateOrgMembershipEmailParams(emails []string) error {
for _, email := range emails {
if !validEmail(email) {
return ErrInvalidEmail
}
}

return nil
}
22 changes: 22 additions & 0 deletions organization_membership_integration_test.go
Expand Up @@ -72,6 +72,28 @@ func TestOrganizationMembershipsList(t *testing.T) {
assert.Contains(t, ml.Items, memTest2)
})

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

ml, err := client.OrganizationMemberships.List(ctx, orgTest.Name, &OrganizationMembershipListOptions{
Emails: []string{memTest2.Email},
})
require.NoError(t, err)

assert.Len(t, ml.Items, 1)
assert.Equal(t, ml.Items[0].ID, memTest2.ID)

t.Run("with invalid email", func(t *testing.T) {
ml, err = client.OrganizationMemberships.List(ctx, orgTest.Name, &OrganizationMembershipListOptions{
Emails: []string{"foobar"},
})
assert.Equal(t, err, ErrInvalidEmail)
})
})

t.Run("without a valid organization", func(t *testing.T) {
ml, err := client.OrganizationMemberships.List(ctx, badIdentifier, nil)
assert.Nil(t, ml)
Expand Down
17 changes: 17 additions & 0 deletions team.go
Expand Up @@ -88,6 +88,9 @@ type TeamListOptions struct {
// Optional: A list of relations to include.
// https://www.terraform.io/docs/cloud/api/teams.html#available-related-resources
Include []TeamIncludeOpt `url:"include,omitempty"`

// Optional: A list of team names to filter by.
Names []string `url:"filter[names],omitempty"`
}

// TeamCreateOptions represents the options for creating a team.
Expand Down Expand Up @@ -263,6 +266,10 @@ func (o *TeamListOptions) valid() error {
return err
}

if err := validateTeamNames(o.Names); err != nil {
return err
}

return nil
}

Expand All @@ -278,3 +285,13 @@ func validateTeamIncludeParams(params []TeamIncludeOpt) error {

return nil
}

func validateTeamNames(names []string) error {
for _, name := range names {
Copy link
Collaborator

Choose a reason for hiding this comment

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

This works when names is nil, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yessir!

if name == "" {
return ErrEmptyTeamName
}
}

return nil
}
15 changes: 15 additions & 0 deletions team_integration_test.go
Expand Up @@ -54,6 +54,21 @@ func TestTeamsList(t *testing.T) {
assert.Empty(t, tl.Items)
assert.Equal(t, 999, tl.CurrentPage)
assert.Equal(t, 2, tl.TotalCount)

tl, err = client.Teams.List(ctx, orgTest.Name, &TeamListOptions{
Names: []string{tmTest2.Name},
})

assert.Equal(t, tl.Items, 1)
assert.Contains(t, tl.Items, tmTest2)

t.Run("with invalid names query param", func(t *testing.T) {
// should return an error because we've included an empty string
tl, err = client.Teams.List(ctx, orgTest.Name, &TeamListOptions{
Names: []string{tmTest2.Name, ""},
})
assert.Equal(t, err, ErrEmptyTeamName)
})
})

t.Run("without a valid organization", func(t *testing.T) {
Expand Down
7 changes: 7 additions & 0 deletions validations.go
@@ -1,6 +1,7 @@
package tfe

import (
"net/mail"
"regexp"
)

Expand All @@ -20,3 +21,9 @@ func validString(v *string) bool {
func validStringID(v *string) bool {
return v != nil && reStringID.MatchString(*v)
}

// validEmail checks if the given input is a correct email
func validEmail(v string) bool {
_, err := mail.ParseAddress(v)
Copy link
Contributor

Choose a reason for hiding this comment

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

nice 🎉

return err == nil
}