From 877d99f6c6feb469b39503e1222b2115b65f413c Mon Sep 17 00:00:00 2001 From: Ralph Schmieder Date: Wed, 29 Mar 2023 14:25:04 +0200 Subject: [PATCH] version 0.0.16, see CHANGELOG --- CHANGELOG.md | 8 +++++++ apiclient.go | 2 +- go.mod | 2 +- go.sum | 4 ++-- group.go | 21 +++++++++-------- lab.go | 21 +++++++++-------- lab_test.go | 16 +++++++++++++ user.go | 57 ++++++++++++++++++++++++++++++++++++---------- users_test.go | 15 +++++------- vendor/modules.txt | 4 ++-- 10 files changed, 105 insertions(+), 45 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1be2689..64d05f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,14 @@ Lists the changes in the gocmlclient package. +## Version 0.0.16 + +- added new API endpoints for groups and users +- tried to apply some consistency to func names +- add 201 return code to the list of "OK" codes +- allow to set "groups" when creating/updating a lab +- updated dependencies + ## Version 0.0.15 - made node configuration a pointer to differentiate between diff --git a/apiclient.go b/apiclient.go index bae94a6..70a6094 100644 --- a/apiclient.go +++ b/apiclient.go @@ -99,7 +99,7 @@ retry: c.state.set(stateAuthenticated) goto retry } - if res.StatusCode == http.StatusOK || res.StatusCode == http.StatusNoContent { + if res.StatusCode == http.StatusOK || res.StatusCode == http.StatusNoContent || res.StatusCode == http.StatusCreated { return body, err } else { return nil, fmt.Errorf("status: %d, %s", res.StatusCode, body) diff --git a/go.mod b/go.mod index bdade7f..e0741a7 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.19 require ( github.com/Masterminds/semver/v3 v3.2.0 - github.com/rschmied/mockresponder v1.0.3 + github.com/rschmied/mockresponder v1.0.4 github.com/stretchr/testify v1.8.2 golang.org/x/sync v0.1.0 ) diff --git a/go.sum b/go.sum index 2fe1305..c69f1ce 100644 --- a/go.sum +++ b/go.sum @@ -5,8 +5,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rschmied/mockresponder v1.0.3 h1:HvYHzzVEzW4HmzFR5y3BiYTg2RTuFBKztFQCaYLX5dw= -github.com/rschmied/mockresponder v1.0.3/go.mod h1:pwohppdT8/A4hR2r7LzRspvbOk9jdLpO83zm4SDMNpc= +github.com/rschmied/mockresponder v1.0.4 h1:VFXa9Y9QJ/5oZFhKoqh9u3HQlbjcBfE9pxI+BanMlEs= +github.com/rschmied/mockresponder v1.0.4/go.mod h1:+EEq2xxKOQNbJTTvfqmjYh1zPPCKnZBthHzaZAJSExg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= diff --git a/group.go b/group.go index 4a1804a..0d02e0c 100644 --- a/group.go +++ b/group.go @@ -28,15 +28,16 @@ import ( // } // ] +type GroupLab struct { + ID string `json:"id"` + Permission string `json:"permission"` +} type Group struct { - ID string `json:"id"` - Description string `json:"description"` - Members []string `json:"members"` - Name string `json:"name"` - Labs []struct { - ID string `json:"id"` - Permission string `json:"permission"` - } + ID string `json:"id,omitempty"` + Description string `json:"description"` + Members []string `json:"members"` + Name string `json:"name"` + Labs []GroupLab `json:"labs"` } type GroupList []*Group @@ -98,13 +99,15 @@ func (c *Client) GroupCreate(ctx context.Context, group *Group) (*Group, error) // GroupUpdate updates the given group which must exist. func (c *Client) GroupUpdate(ctx context.Context, group *Group) (*Group, error) { + groupID := group.ID + group.ID = "" buf := &bytes.Buffer{} err := json.NewEncoder(buf).Encode(group) if err != nil { return nil, err } result := Group{} - err = c.jsonPatch(ctx, fmt.Sprintf("groups/%s", group.ID), buf, &result, 0) + err = c.jsonPatch(ctx, fmt.Sprintf("groups/%s", groupID), buf, &result, 0) if err != nil { return nil, err } diff --git a/lab.go b/lab.go index cd775a2..1aed008 100644 --- a/lab.go +++ b/lab.go @@ -41,7 +41,7 @@ const ( type LabGroup struct { ID string `json:"id"` - Name string `json:"name"` + Name string `json:"name,omitempty"` Permission string `json:"permission"` } @@ -50,7 +50,7 @@ type NodeMap map[string]*Node type InterfaceList []*Interface type nodeList []*Node type linkList []*Link -type labGroupList []*LabGroup +type LabGroupList []*LabGroup type labAlias struct { Lab @@ -58,9 +58,10 @@ type labAlias struct { } type labPatchPostAlias struct { - Title string `json:"title,omitempty"` - Description string `json:"description,omitempty"` - Notes string `json:"notes,omitempty"` + Title string `json:"title,omitempty"` + Description string `json:"description,omitempty"` + Notes string `json:"notes,omitempty"` + Groups LabGroupList `json:"groups,omitempty"` } type Lab struct { @@ -76,7 +77,7 @@ type Lab struct { LinkCount int `json:"link_count"` Nodes NodeMap `json:"nodes"` Links linkList `json:"links"` - Groups labGroupList `json:"groups"` + Groups LabGroupList `json:"groups"` // private // filled bool @@ -190,6 +191,7 @@ func (c *Client) LabCreate(ctx context.Context, lab Lab) (*Lab, error) { Title: lab.Title, Description: lab.Description, Notes: lab.Notes, + // Groups: lab.Groups, // can't set at create } buf := &bytes.Buffer{} @@ -204,9 +206,8 @@ func (c *Client) LabCreate(ctx context.Context, lab Lab) (*Lab, error) { return nil, err } - la.Owner = &User{ID: la.OwnerID} - la.Nodes = make(NodeMap) - return c.cacheLab(&la.Lab, nil) + lab.ID = la.ID + return c.LabUpdate(ctx, lab) } // LabUpdate updates specific fields of a lab (title, description and notes). @@ -217,6 +218,7 @@ func (c *Client) LabUpdate(ctx context.Context, lab Lab) (*Lab, error) { Title: lab.Title, Description: lab.Description, Notes: lab.Notes, + Groups: lab.Groups, } buf := &bytes.Buffer{} @@ -233,6 +235,7 @@ func (c *Client) LabUpdate(ctx context.Context, lab Lab) (*Lab, error) { } la.Owner = &User{ID: la.OwnerID} + la.Nodes = make(NodeMap) return c.cacheLab(&la.Lab, nil) } diff --git a/lab_test.go b/lab_test.go index dcb6b76..ccea24b 100644 --- a/lab_test.go +++ b/lab_test.go @@ -599,6 +599,22 @@ func TestClient_LabCreate(t *testing.T) { "groups": [] }`), }, + mr.MockResp{ + Data: []byte(`{ + "state": "DEFINED_ON_CORE", + "created": "2022-10-14T10:05:07+00:00", + "modified": "2022-10-14T10:05:07+00:00", + "lab_title": "Lab at Mon 17:27 PM", + "lab_description": "string", + "lab_notes": "string", + "owner": "00000000-0000-4000-a000-000000000000", + "owner_username": "admin", + "node_count": 0, + "link_count": 0, + "id": "375b41ae-dd90-41a2-858d-98948abbbd38", + "groups": [] + }`), + }, } tests := []struct { diff --git a/user.go b/user.go index 2a39c0d..e199eb1 100644 --- a/user.go +++ b/user.go @@ -28,23 +28,54 @@ import ( // } type User struct { - ID string `json:"id"` - Created string `json:"created"` - Modified string `json:"modified"` + ID string `json:"id,omitempty"` + Created string `json:"created,omitempty"` + Modified string `json:"modified,omitempty"` Username string `json:"username"` + Password string `json:"password"` Fullname string `json:"fullname"` Email string `json:"email"` - Description string `json:"lab_description"` + Description string `json:"description"` IsAdmin bool `json:"admin"` - DirectoryDN string `json:"directory_dn"` - Groups []string `json:"groups"` - Labs []string `json:"labs"` - OptIn bool `json:"opt_in"` // with 2.5.0 - ResourcePool *string `json:"resource_pool"` // with 2.5.0 + DirectoryDN string `json:"directory_dn,omitempty"` + Groups []string `json:"groups,omitempty"` + Labs []string `json:"labs,omitempty"` + OptIn bool `json:"opt_in"` // with 2.5.0 + ResourcePool *string `json:"resource_pool,omitempty"` // with 2.5.0 } type UserList []*User +type userPatchPostAlias struct { + Username string `json:"username"` + Password string `json:"password,omitempty"` + Fullname string `json:"fullname"` + Email string `json:"email"` + Description string `json:"description"` + IsAdmin bool `json:"admin"` + Groups []string `json:"groups"` + Labs []string `json:"labs,omitempty"` // can't be set + OptIn bool `json:"opt_in"` // with 2.5.0 + ResourcePool *string `json:"resource_pool,omitempty"` // with 2.5.0 +} + +func newUserAlias(user *User) userPatchPostAlias { + upp := userPatchPostAlias{} + + upp.Username = user.Username + upp.Password = user.Password + upp.Fullname = user.Fullname + upp.Email = user.Email + upp.Description = user.Description + upp.IsAdmin = user.IsAdmin + upp.OptIn = user.OptIn + upp.Groups = user.Groups + upp.Labs = user.Labs + upp.ResourcePool = user.ResourcePool + + return upp +} + // UserGet returns the user with the given `id`. func (c *Client) UserGet(ctx context.Context, id string) (*User, error) { api := fmt.Sprintf("users/%s", id) @@ -99,13 +130,14 @@ func (c *Client) UserCreate(ctx context.Context, user *User) (*User, error) { if err != nil { return nil, err } - return &result, err + return c.UserGet(ctx, result.ID) } // UserUpdate updates the given user which must exist. func (c *Client) UserUpdate(ctx context.Context, user *User) (*User, error) { + patchAlias := newUserAlias(user) buf := &bytes.Buffer{} - err := json.NewEncoder(buf).Encode(user) + err := json.NewEncoder(buf).Encode(patchAlias) if err != nil { return nil, err } @@ -114,7 +146,7 @@ func (c *Client) UserUpdate(ctx context.Context, user *User) (*User, error) { if err != nil { return nil, err } - return &result, err + return c.UserGet(ctx, result.ID) } // UserGroups retrieves the list of all groups the user belongs to. @@ -136,6 +168,7 @@ func (c *Client) UserGroups(ctx context.Context, id string) (GroupList, error) { } // sort the user list by their ID + // (groups are a set so sorting is only done for test stability) sort.Slice(groups, func(i, j int) bool { return groups[i].ID > groups[j].ID }) diff --git a/users_test.go b/users_test.go index eecfd55..8c2bbc6 100644 --- a/users_test.go +++ b/users_test.go @@ -257,9 +257,8 @@ func TestClient_UserCreate(t *testing.T) { { "good", mr.MockRespList{ - mr.MockResp{ - Data: []byte(user1), - }, + mr.MockResp{Data: []byte(user1)}, + mr.MockResp{Data: []byte(user1)}, }, false, }, @@ -316,6 +315,9 @@ func TestClient_UserUpdate(t *testing.T) { mr.MockResp{ Data: []byte(user1), }, + mr.MockResp{ + Data: []byte(user1), + }, }, false, }, @@ -372,7 +374,7 @@ func TestClient_UserGroups(t *testing.T) { mr.MockRespList{ mr.MockResp{ Data: []byte(`[ - "85401911-851f-4e6a-b5c3-4aa1d91fa21d", + "85401911-851f-4e6a-b5c3-4aa1d91fa21d", "90f84e38-a71c-4d57-8d90-00fa8a197385" ]`), }, @@ -424,9 +426,4 @@ func TestClient_UserGroups(t *testing.T) { t.Error("not all data in mock client consumed") } } - - // "id": "85401911-851f-4e6a-b5c3-4aa1d91fa21d", - // "id": "90f84e38-a71c-4d57-8d90-00fa8a197385", - - // "id": "cc42bd56-1dc6-445c-b7e7-569b0a8b0c94", } diff --git a/vendor/modules.txt b/vendor/modules.txt index 1e3ac2d..e8b1453 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -7,8 +7,8 @@ github.com/davecgh/go-spew/spew # github.com/pmezard/go-difflib v1.0.0 ## explicit github.com/pmezard/go-difflib/difflib -# github.com/rschmied/mockresponder v1.0.3 -## explicit; go 1.18 +# github.com/rschmied/mockresponder v1.0.4 +## explicit; go 1.19 github.com/rschmied/mockresponder # github.com/stretchr/testify v1.8.2 ## explicit; go 1.13