Skip to content

Commit

Permalink
SCALRCORE-17735 Add teams service
Browse files Browse the repository at this point in the history
[API_BRANCH]
  • Loading branch information
petroprotsakh committed Oct 28, 2021
1 parent 3fff1f6 commit 215f4a1
Show file tree
Hide file tree
Showing 9 changed files with 582 additions and 8 deletions.
4 changes: 2 additions & 2 deletions examples/account-users/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func main() {
log.Fatal(err)
}

if len(aul.Items) == 0 {
if aul.TotalCount == 0 {
log.Printf("No users found in account %s", accID)
} else {
var active []string
Expand All @@ -55,7 +55,7 @@ func main() {
log.Fatal(err)
}

if len(aul.Items) == 0 {
if aul.TotalCount == 0 {
log.Printf("No accounts found for user %s", userID)
} else {
var active []string
Expand Down
65 changes: 65 additions & 0 deletions examples/teams/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package main

import (
"context"
"log"
"strings"

scalr "github.com/scalr/go-scalr"
)

func main() {
accID := "acc-svrcncgh453bi8g"

config := scalr.DefaultConfig()
client, err := scalr.NewClient(config)
if err != nil {
log.Fatal(err)
}

// Create a context
ctx := context.Background()

// List all teams in account
tl, err := client.Teams.List(ctx, scalr.TeamListOptions{
Account: scalr.String(accID),
})
if err != nil {
log.Fatal(err)
}

if tl.TotalCount == 0 {
log.Printf("No teams found in account %s", accID)
} else {
var teams []string
for _, t := range tl.Items {
teams = append(teams, t.Name)
}
log.Printf("Teams in account %s: %s", accID, strings.Join(teams, ", "))
}

// Create a new team
t, err := client.Teams.Create(ctx, scalr.TeamCreateOptions{
Name: scalr.String("dev"),
Description: scalr.String("Developers"),
Account: &scalr.Account{ID: accID},
Users: []*scalr.User{
{ID: "user-suh84u6vuvidtbg"},
{ID: "user-suh84u72gfrbd30"},
},
})
if err != nil {
log.Fatal(err)
}

// Update a team
t, err = client.Teams.Update(ctx, t.ID, scalr.TeamUpdateOptions{
Name: scalr.String("dev-new"),
Users: []*scalr.User{
{ID: "user-svrcmmpcrkmit1g"},
},
})
if err != nil {
log.Fatal(err)
}
}
23 changes: 23 additions & 0 deletions helper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,29 @@ func createVcsProvider(t *testing.T, client *Client, envs []*Environment) (*VcsP
}
}

func createTeam(t *testing.T, client *Client, users []*User) (*Team, func()) {
ctx := context.Background()
team, err := client.Teams.Create(
ctx,
TeamCreateOptions{
Name: String("tst-" + randomString(t)),
Account: &Account{ID: defaultAccountID},
Users: users,
},
)
if err != nil {
t.Fatal(err)
}

return team, func() {
if err := client.Teams.Delete(ctx, team.ID); err != nil {
t.Errorf("Error deleting team! WARNING: Dangling resources\n"+
"may exist! The full error is shown below.\n\n"+
"VCS Providder: %s\nError: %s", team.ID, err)
}
}
}

func randomString(t *testing.T) string {
v, err := uuid.GenerateUUID()
if err != nil {
Expand Down
5 changes: 4 additions & 1 deletion identity_provider.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package scalr

const defaultIdentityProviderLdapID = "idp-sojhv9e8mc2k808"
const (
defaultIdentityProviderScalrID = "idp-sohkb0o1phrdmr8"
defaultIdentityProviderLdapID = "idp-sojhv9e8mc2k808"
)

// IdentityProvider represents a Scalr identity provider.
type IdentityProvider struct {
Expand Down
2 changes: 2 additions & 0 deletions scalr.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ type Client struct {
Modules Modules
Roles Roles
Runs Runs
Teams Teams
Users Users
Variables Variables
VcsProviders VcsProviders
Expand Down Expand Up @@ -206,6 +207,7 @@ func NewClient(cfg *Config) (*Client, error) {
client.Modules = &modules{client: client}
client.Roles = &roles{client: client}
client.Runs = &runs{client: client}
client.Teams = &teams{client: client}
client.Users = &users{client: client}
client.Variables = &variables{client: client}
client.VcsProviders = &vcsProviders{client: client}
Expand Down
187 changes: 185 additions & 2 deletions team.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,189 @@
package scalr

import (
"context"
"errors"
"fmt"
"net/url"
)

// Compile-time proof of interface implementation.
var _ Teams = (*teams)(nil)

// Teams describes all the team related methods that the
// Scalr API supports.
type Teams interface {
List(ctx context.Context, options TeamListOptions) (*TeamList, error)
Create(ctx context.Context, options TeamCreateOptions) (*Team, error)
Read(ctx context.Context, teamID string) (*Team, error)
Update(ctx context.Context, teamID string, options TeamUpdateOptions) (*Team, error)
Delete(ctx context.Context, teamID string) error
}

// teams implements Teams.
type teams struct {
client *Client
}

type Team struct {
ID string `jsonapi:"primary,teams"`
Name string `jsonapi:"attr,name,omitempty"`
ID string `jsonapi:"primary,teams"`
Name string `jsonapi:"attr,name,omitempty"`
Description string `jsonapi:"attr,description,omitempty"`

// Relations
Account *Account `jsonapi:"relation,account"`
IdentityProvider *IdentityProvider `jsonapi:"relation,identity-provider"`
Users []*User `jsonapi:"relation,users"`
}

// TeamList represents a list of teams.
type TeamList struct {
*Pagination
Items []*Team
}

// TeamListOptions represents the options for listing teams.
type TeamListOptions struct {
ListOptions

Team *string `url:"filter[team],omitempty"`
Name *string `url:"filter[name],omitempty"`
Account *string `url:"filter[account],omitempty"`
IdentityProvider *string `url:"filter[identity-provider],omitempty"`
Query *string `url:"query,omitempty"`
Sort *string `url:"sort,omitempty"`
Include *string `url:"include,omitempty"`
}

// TeamCreateOptions represents the options for creating a new team.
type TeamCreateOptions struct {
ID string `jsonapi:"primary,teams"`
Name *string `jsonapi:"attr,name"`
Description *string `jsonapi:"attr,description"`

// Relations
Account *Account `jsonapi:"relation,account,omitempty"`
IdentityProvider *IdentityProvider `jsonapi:"relation,identity-provider,omitempty"`
Users []*User `jsonapi:"relation,users,omitempty"`
}

func (o TeamCreateOptions) valid() error {
if !validString(o.Name) {
return errors.New("name is required")
}
if o.Account != nil && !validStringID(&o.Account.ID) {
return errors.New("invalid value for account ID")
}
if o.IdentityProvider != nil && !validStringID(&o.IdentityProvider.ID) {
return errors.New("invalid value for identity provider ID")
}

return nil
}

// TeamUpdateOptions represents the options for updating a team.
type TeamUpdateOptions struct {
ID string `jsonapi:"primary,teams"`
Name *string `jsonapi:"attr,name,omitempty"`
Description *string `jsonapi:"attr,description,omitempty"`

// Relations
Users []*User `jsonapi:"relation,users"`
}

// List all the teams.
func (s *teams) List(ctx context.Context, options TeamListOptions) (*TeamList, error) {
req, err := s.client.newRequest("GET", "teams", &options)
if err != nil {
return nil, err
}

tl := &TeamList{}
err = s.client.do(ctx, req, tl)
if err != nil {
return nil, err
}

return tl, nil
}

// Create a new team.
func (s *teams) Create(ctx context.Context, options TeamCreateOptions) (*Team, error) {
if err := options.valid(); err != nil {
return nil, err
}
// Make sure we don't send a user provided ID.
options.ID = ""
req, err := s.client.newRequest("POST", "teams", &options)
if err != nil {
return nil, err
}

t := &Team{}
err = s.client.do(ctx, req, t)
if err != nil {
return nil, err
}

return t, nil
}

// Read team by its ID.
func (s *teams) Read(ctx context.Context, teamID string) (*Team, error) {
if !validStringID(&teamID) {
return nil, errors.New("invalid value for team ID")
}

u := fmt.Sprintf("teams/%s", url.QueryEscape(teamID))
req, err := s.client.newRequest("GET", u, nil)
if err != nil {
return nil, err
}

t := &Team{}
err = s.client.do(ctx, req, t)
if err != nil {
return nil, err
}

return t, nil
}

// Update settings of an existing team.
func (s *teams) Update(ctx context.Context, teamID string, options TeamUpdateOptions) (*Team, error) {
if !validStringID(&teamID) {
return nil, errors.New("invalid value for team ID")
}

// Make sure we don't send a user provided ID.
options.ID = ""

u := fmt.Sprintf("teams/%s", url.QueryEscape(teamID))
req, err := s.client.newRequest("PATCH", u, &options)
if err != nil {
return nil, err
}

t := &Team{}
err = s.client.do(ctx, req, t)
if err != nil {
return nil, err
}

return t, nil
}

// Delete team by its ID.
func (s *teams) Delete(ctx context.Context, teamID string) error {
if !validStringID(&teamID) {
return errors.New("invalid value for team ID")
}

u := fmt.Sprintf("teams/%s", url.QueryEscape(teamID))
req, err := s.client.newRequest("DELETE", u, nil)
if err != nil {
return err
}

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

0 comments on commit 215f4a1

Please sign in to comment.