From 7339879231b07bdd5c72f0982aa251de203570d3 Mon Sep 17 00:00:00 2001 From: Andrei Ozerov Date: Fri, 20 Apr 2018 14:10:44 +0300 Subject: [PATCH] Resell V2 - add roles with project list method Add roles package with basic structure and ListProject method. Add tests and doc example. --- selvpcclient/resell/v2/roles/doc.go | 15 ++ selvpcclient/resell/v2/roles/requests.go | 33 +++++ selvpcclient/resell/v2/roles/schemas.go | 10 ++ .../resell/v2/roles/testing/fixtures.go | 54 +++++++ .../resell/v2/roles/testing/requests_test.go | 135 ++++++++++++++++++ 5 files changed, 247 insertions(+) create mode 100644 selvpcclient/resell/v2/roles/doc.go create mode 100644 selvpcclient/resell/v2/roles/requests.go create mode 100644 selvpcclient/resell/v2/roles/schemas.go create mode 100644 selvpcclient/resell/v2/roles/testing/fixtures.go create mode 100644 selvpcclient/resell/v2/roles/testing/requests_test.go diff --git a/selvpcclient/resell/v2/roles/doc.go b/selvpcclient/resell/v2/roles/doc.go new file mode 100644 index 0000000..e591735 --- /dev/null +++ b/selvpcclient/resell/v2/roles/doc.go @@ -0,0 +1,15 @@ +/* +Package roles provides the ability to retrieve and manage roles through the +Resell v2 API. + +Example of getting roles in the specified project + + allRoles, _, err := roles.ListProject(context, resellClient, projectID) + if err != nil { + log.Fatal(err) + } + for _, myRole := range allRoles { + fmt.Println(myRole) + } +*/ +package roles diff --git a/selvpcclient/resell/v2/roles/requests.go b/selvpcclient/resell/v2/roles/requests.go new file mode 100644 index 0000000..2111350 --- /dev/null +++ b/selvpcclient/resell/v2/roles/requests.go @@ -0,0 +1,33 @@ +package roles + +import ( + "context" + "strings" + + "github.com/selectel/go-selvpcclient/selvpcclient" +) + +const resourceURL = "roles" + +// ListProject returns all roles in the specified project. +func ListProject(ctx context.Context, client *selvpcclient.ServiceClient, id string) ([]*Role, *selvpcclient.ResponseResult, error) { + url := strings.Join([]string{client.Endpoint, resourceURL, "projects", id}, "/") + responseResult, err := client.DoRequest(ctx, "GET", url, nil) + if err != nil { + return nil, nil, err + } + if responseResult.Err != nil { + return nil, responseResult, responseResult.Err + } + + // Extract roles from the response body. + var result struct { + Roles []*Role `json:"roles"` + } + err = responseResult.ExtractResult(&result) + if err != nil { + return nil, responseResult, err + } + + return result.Roles, responseResult, nil +} diff --git a/selvpcclient/resell/v2/roles/schemas.go b/selvpcclient/resell/v2/roles/schemas.go new file mode 100644 index 0000000..75140f6 --- /dev/null +++ b/selvpcclient/resell/v2/roles/schemas.go @@ -0,0 +1,10 @@ +package roles + +// Role represents a single Resell subnet. +type Role struct { + // ProjectID represents an associated Resell project. + ProjectID string `json:"project_id"` + + // UserID represents an associated Resell user. + UserID string `json:"user_id"` +} diff --git a/selvpcclient/resell/v2/roles/testing/fixtures.go b/selvpcclient/resell/v2/roles/testing/fixtures.go new file mode 100644 index 0000000..e7c248c --- /dev/null +++ b/selvpcclient/resell/v2/roles/testing/fixtures.go @@ -0,0 +1,54 @@ +package testing + +import "github.com/selectel/go-selvpcclient/selvpcclient/resell/v2/roles" + +// TestListResponseRaw represents a raw response from List requests. +const TestListResponseRaw = ` +{ + "roles": [ + { + "project_id": "49338ac045f448e294b25d013f890317", + "user_id": "b006a55e3a904472824061d64d61be75" + }, + { + "project_id": "49338ac045f448e294b25d013f890317", + "user_id": "a699c05690ec44ad8cb2a6fe80b29e70" + }, + { + "project_id": "49338ac045f448e294b25d013f890317", + "user_id": "763eecfaeb0c8e9b76ab12a82eb4c11" + } + ] +} +` + +// TestListResponseSingleRaw represents a raw response with a single role from List requests. +const TestListResponseSingleRaw = ` +{ + "roles": [ + { + "project_id": "49338ac045f448e294b25d013f890317", + "user_id": "763eecfaeb0c8e9b76ab12a82eb4c11" + } + ] +} +` + +// TestListResponseSingle represents the unmarshalled TestListResponseSingleRaw response. +var TestListResponseSingle = []*roles.Role{ + { + ProjectID: "49338ac045f448e294b25d013f890317", + UserID: "763eecfaeb0c8e9b76ab12a82eb4c11", + }, +} + +// TestManyRolesInvalidResponseRaw represents a raw invalid response with several roles. +const TestManyRolesInvalidResponseRaw = ` +{ + "roles": [ + { + "project_id": 123 + } + ] +} +` diff --git a/selvpcclient/resell/v2/roles/testing/requests_test.go b/selvpcclient/resell/v2/roles/testing/requests_test.go new file mode 100644 index 0000000..4e0e40e --- /dev/null +++ b/selvpcclient/resell/v2/roles/testing/requests_test.go @@ -0,0 +1,135 @@ +package testing + +import ( + "context" + "net/http" + "reflect" + "testing" + + "github.com/selectel/go-selvpcclient/selvpcclient/resell/v2/roles" + "github.com/selectel/go-selvpcclient/selvpcclient/testutils" +) + +func TestListRolesProjectLicenses(t *testing.T) { + endpointCalled := false + + testEnv := testutils.SetupTestEnv() + defer testEnv.TearDownTestEnv() + testEnv.NewTestResellV2Client() + testutils.HandleReqWithoutBody(testEnv.Mux, "/resell/v2/roles/projects/49338ac045f448e294b25d013f890317", + TestListResponseRaw, http.MethodGet, http.StatusOK, &endpointCalled, t) + + ctx := context.Background() + actual, _, err := roles.ListProject(ctx, testEnv.Client, "49338ac045f448e294b25d013f890317") + if err != nil { + t.Fatal(err) + } + + if !endpointCalled { + t.Fatal("endpoint wasn't called") + } + if actual == nil { + t.Fatal("didn't get roles") + } + actualKind := reflect.TypeOf(actual).Kind() + if actualKind != reflect.Slice { + t.Errorf("expected slice of pointers to roles, but got %v", actualKind) + } + if len(actual) != 3 { + t.Errorf("expected 3 roles, but got %d", len(actual)) + } +} + +func TestListRolesProjectSingle(t *testing.T) { + endpointCalled := false + + testEnv := testutils.SetupTestEnv() + defer testEnv.TearDownTestEnv() + testEnv.NewTestResellV2Client() + testutils.HandleReqWithoutBody(testEnv.Mux, "/resell/v2/roles/projects/49338ac045f448e294b25d013f890317", + TestListResponseSingleRaw, http.MethodGet, http.StatusOK, &endpointCalled, t) + + ctx := context.Background() + actual, _, err := roles.ListProject(ctx, testEnv.Client, "49338ac045f448e294b25d013f890317") + if err != nil { + t.Fatal(err) + } + + expected := TestListResponseSingle + + if !endpointCalled { + t.Fatal("endpoint wasn't called") + } + if !reflect.DeepEqual(actual, expected) { + t.Fatalf("expected %#v, but got %#v", expected, actual) + } +} + +func TestListRolesProjectHTTPError(t *testing.T) { + endpointCalled := false + + testEnv := testutils.SetupTestEnv() + defer testEnv.TearDownTestEnv() + testEnv.NewTestResellV2Client() + testutils.HandleReqWithoutBody(testEnv.Mux, "/resell/v2/roles/projects/49338ac045f448e294b25d013f890317", + TestListResponseRaw, http.MethodGet, http.StatusBadGateway, + &endpointCalled, t) + + ctx := context.Background() + allRoles, httpResponse, err := roles.ListProject(ctx, testEnv.Client, "49338ac045f448e294b25d013f890317") + + if !endpointCalled { + t.Fatal("endpoint wasn't called") + } + if allRoles != nil { + t.Fatal("expected no roles from the Get method") + } + if err == nil { + t.Fatal("expected error from the Get method") + } + if httpResponse.StatusCode != http.StatusBadGateway { + t.Fatalf("expected %d status in the HTTP response, but got %d", + http.StatusBadGateway, httpResponse.StatusCode) + } +} + +func TestListRolesProjectTimeoutError(t *testing.T) { + testEnv := testutils.SetupTestEnv() + testEnv.Server.Close() + defer testEnv.TearDownTestEnv() + testEnv.NewTestResellV2Client() + + ctx := context.Background() + allRoles, _, err := roles.ListProject(ctx, testEnv.Client, "49338ac045f448e294b25d013f890317") + + if allRoles != nil { + t.Fatal("expected no roles from the List method") + } + if err == nil { + t.Fatal("expected error from the List method") + } +} + +func TestListRolesProjectUnmarshalError(t *testing.T) { + endpointCalled := false + + testEnv := testutils.SetupTestEnv() + defer testEnv.TearDownTestEnv() + testEnv.NewTestResellV2Client() + testutils.HandleReqWithoutBody(testEnv.Mux, "/resell/v2/roles/projects/49338ac045f448e294b25d013f890317", + TestManyRolesInvalidResponseRaw, http.MethodGet, http.StatusOK, + &endpointCalled, t) + + ctx := context.Background() + allRoles, _, err := roles.ListProject(ctx, testEnv.Client, "49338ac045f448e294b25d013f890317") + + if !endpointCalled { + t.Fatal("endpoint wasn't called") + } + if allRoles != nil { + t.Fatal("expected no roles from the List method") + } + if err == nil { + t.Fatal("expected error from the List method") + } +}