Commit fda07d69 authored by Matej Velikonja's avatar Matej Velikonja

add project clusters API support

parent e0e1ddfe
......@@ -66,6 +66,7 @@ to add new and/or missing endpoints. Currently the following services are suppor
- [ ] Project import/export
- [x] Project Members
- [x] Project Snippets
- [x] Project Clusters
- [x] Protected Branches
- [x] Protected Tags
- [x] Repositories
......
......@@ -320,6 +320,7 @@ type Client struct {
ProjectBadges *ProjectBadgesService
ProjectSnippets *ProjectSnippetsService
ProjectVariables *ProjectVariablesService
ProjectCluster *ProjectClustersService
ProtectedBranches *ProtectedBranchesService
ProtectedTags *ProtectedTagsService
Repositories *RepositoriesService
......@@ -461,6 +462,7 @@ func newClient(httpClient *http.Client) *Client {
c.ProjectBadges = &ProjectBadgesService{client: c}
c.ProjectSnippets = &ProjectSnippetsService{client: c}
c.ProjectVariables = &ProjectVariablesService{client: c}
c.ProjectCluster = &ProjectClustersService{client: c}
c.ProtectedBranches = &ProtectedBranchesService{client: c}
c.ProtectedTags = &ProtectedTagsService{client: c}
c.Repositories = &RepositoriesService{client: c}
......
//
// Copyright 2019, Matej Velikonja
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package gitlab
import (
"fmt"
"net/url"
"time"
)
// ProjectClustersService handles communication with the
// project clusters related methods of the GitLab API.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_clusters.html
type ProjectClustersService struct {
client *Client
}
// ProjectCluster represents a GitLab Project Cluster.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_clusters.html
type ProjectCluster struct {
ID int `json:"id,omitempty"`
Name string `json:"name,omitempty"`
Enabled *bool `json:"enabled,omitempty"`
CreatedAt *time.Time `json:"created_at,omitempty"`
ProviderType string `json:"provider_type,omitempty"`
PlatformType string `json:"platform_type,omitempty"`
EnvironmentScope string `json:"environment_scope,omitempty"`
ClusterType string `json:"cluster_type,omitempty"`
User *User `json:"user,omitempty"`
PlatformKubernetes PlatformKubernetes `json:"platform_kubernetes,omitempty"`
Project *Project `json:"project,omitempty"`
}
func (v ProjectCluster) String() string {
return Stringify(v)
}
type PlatformKubernetes struct {
ApiUrl string `json:"api_url,omitempty"`
Token string `json:"token,omitempty"`
CaCert string `json:"ca_cert,omitempty"`
Namespace string `json:"namespace,omitempty"`
AuthorizationType string `json:"authorization_type,omitempty"`
}
// ListClusters gets a list of all clusters in a project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_clusters.html#list-project-clusters
func (s *ProjectClustersService) ListClusters(pid interface{}, options ...OptionFunc) ([]*ProjectCluster, *Response, error) {
projectID, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/clusters", url.QueryEscape(projectID))
req, err := s.client.NewRequest("GET", u, nil, options)
if err != nil {
return nil, nil, err
}
var vs []*ProjectCluster
resp, err := s.client.Do(req, &vs)
if err != nil {
return nil, resp, err
}
return vs, resp, err
}
// GetCluster gets a cluster.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_clusters.html#get-a-single-project-cluster
func (s *ProjectClustersService) GetCluster(pid interface{}, clusterID int, options ...OptionFunc) (*ProjectCluster, *Response, error) {
projectID, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/clusters/%d", url.QueryEscape(projectID), clusterID)
req, err := s.client.NewRequest("GET", u, nil, options)
if err != nil {
return nil, nil, err
}
var vs *ProjectCluster
resp, err := s.client.Do(req, &vs)
if err != nil {
return nil, resp, err
}
return vs, resp, err
}
// AddClusterOptions represents the available AddCluster() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_clusters.html#add-existing-cluster-to-project
type AddClusterOptions struct {
Name string `json:"name,omitempty"`
Enabled *bool `json:"enabled,omitempty"`
EnvironmentScope string `json:"environment_scope,omitempty"`
PlatformKubernetes PlatformKubernetes `json:"platform_kubernetes_attributes,omitempty"`
}
// AddCluster adds an existing cluster to the project.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_clusters.html#add-existing-cluster-to-project
func (s *ProjectClustersService) AddCluster(pid interface{}, opt *AddClusterOptions, options ...OptionFunc) (*ProjectCluster, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/clusters/user", url.QueryEscape(project))
req, err := s.client.NewRequest("POST", u, opt, options)
if err != nil {
return nil, nil, err
}
//b, _ := ioutil.ReadAll(req.Body)
//fmt.Println(string(b))
pc := new(ProjectCluster)
resp, err := s.client.Do(req, pc)
if err != nil {
return nil, resp, err
}
return pc, resp, err
}
// EditClusterOptions represents the available EditCluster() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_clusters.html#edit-project-cluster
type EditClusterOptions struct {
Name string `json:"name"`
EnvironmentScope string `json:"environment_scope,omitempty"`
PlatformKubernetes PlatformKubernetes `json:"platform_kubernetes_attributes,omitempty"`
}
// EditCluster updates an existing project cluster.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_clusters.html#edit-project-cluster
func (s *ProjectClustersService) EditCluster(pid interface{}, cid int, opt *EditClusterOptions, options ...OptionFunc) (*ProjectCluster, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/clusters/%d", url.QueryEscape(project), cid)
req, err := s.client.NewRequest("PUT", u, opt, options)
if err != nil {
return nil, nil, err
}
pc := new(ProjectCluster)
resp, err := s.client.Do(req, pc)
if err != nil {
return nil, resp, err
}
return pc, resp, err
}
// DeleteCluster deletes an existing project cluster.
//
// GitLab API docs:
// https://docs.gitlab.com/ee/api/project_clusters.html#delete-project-cluster
func (s *ProjectClustersService) DeleteCluster(pid interface{}, cid int, options ...OptionFunc) (*Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, err
}
u := fmt.Sprintf("projects/%s/clusters/%d", url.QueryEscape(project), cid)
req, err := s.client.NewRequest("DELETE", u, nil, options)
if err != nil {
return nil, err
}
return s.client.Do(req, nil)
}
package gitlab
import (
"fmt"
"net/http"
"testing"
)
func TestListClusters(t *testing.T) {
mux, server, client := setup()
defer teardown(server)
pid := 1234
mux.HandleFunc("/api/v4/projects/1234/clusters", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
response := `[
{
"id":18,
"name":"cluster-1",
"created_at":"2019-01-02T20:18:12.563Z",
"provider_type":"user",
"platform_type":"kubernetes",
"environment_scope":"*",
"cluster_type":"project_type",
"user":
{
"id":1,
"name":"Administrator",
"username":"root",
"state":"active",
"avatar_url":"https://www.gravatar.com/avatar/4249f4df72b..",
"web_url":"https://gitlab.example.com/root"
},
"platform_kubernetes":
{
"api_url":"https://104.197.68.152",
"namespace":"cluster-1-namespace",
"authorization_type":"rbac",
"ca_cert":"-----BEGIN CERTIFICATE-----\r\nhFiK1L61owwDQYJKoZIhvcNAQELBQAw\r\nLzEtMCsGA1UEAxMkZDA1YzQ1YjctNzdiMS00NDY0LThjNmEtMTQ0ZDJkZjM4ZDBj\r\nMB4XDTE4MTIyNzIwMDM1MVoXDTIzMTIyNjIxMDM1MVowLzEtMCsGA1UEAxMkZDA1\r\nYzQ1YjctNzdiMS00NDY0LThjNmEtMTQ0ZDJkZjM.......-----END CERTIFICATE-----"
}
}
]`
fmt.Fprint(w, response)
})
clusters, _, err := client.ProjectCluster.ListClusters(pid)
if err != nil {
t.Errorf("ProjectClusters.ListClusters returned error: %v", err)
}
if len(clusters) != 1 {
t.Errorf("expected 1 cluster; got %d", len(clusters))
}
if clusters[0].ID != 18 {
t.Errorf("expected clusterID 1; got %d", clusters[0].ID)
}
}
func TestGetCluster(t *testing.T) {
mux, server, client := setup()
defer teardown(server)
pid := 1234
mux.HandleFunc("/api/v4/projects/1234/clusters/1", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
response := `{
"id":18,
"name":"cluster-1",
"created_at":"2019-01-02T20:18:12.563Z",
"provider_type":"user",
"platform_type":"kubernetes",
"environment_scope":"*",
"cluster_type":"project_type",
"user":
{
"id":1,
"name":"Administrator",
"username":"root",
"state":"active",
"avatar_url":"https://www.gravatar.com/avatar/4249f4df72b..",
"web_url":"https://gitlab.example.com/root"
},
"platform_kubernetes":
{
"api_url":"https://104.197.68.152",
"namespace":"cluster-1-namespace",
"authorization_type":"rbac",
"ca_cert":"-----BEGIN CERTIFICATE-----\r\nhFiK1L61owwDQYJKoZIhvcNAQELBQAw\r\nLzEtMCsGA1UEAxMkZDA1YzQ1YjctNzdiMS00NDY0LThjNmEtMTQ0ZDJkZjM4ZDBj\r\nMB4XDTE4MTIyNzIwMDM1MVoXDTIzMTIyNjIxMDM1MVowLzEtMCsGA1UEAxMkZDA1\r\nYzQ1YjctNzdiMS00NDY0LThjNmEtMTQ0ZDJkZjM.......-----END CERTIFICATE-----"
},
"project":
{
"id":26,
"description":"",
"name":"project-with-clusters-api",
"name_with_namespace":"Administrator / project-with-clusters-api",
"path":"project-with-clusters-api",
"path_with_namespace":"root/project-with-clusters-api",
"created_at":"2019-01-02T20:13:32.600Z",
"default_branch":null,
"tag_list":[],
"ssh_url_to_repo":"ssh://gitlab.example.com/root/project-with-clusters-api.git",
"http_url_to_repo":"https://gitlab.example.com/root/project-with-clusters-api.git",
"web_url":"https://gitlab.example.com/root/project-with-clusters-api",
"readme_url":null,
"avatar_url":null,
"star_count":0,
"forks_count":0,
"last_activity_at":"2019-01-02T20:13:32.600Z",
"namespace":
{
"id":1,
"name":"root",
"path":"root",
"kind":"user",
"full_path":"root",
"parent_id":null
}
}
}`
fmt.Fprint(w, response)
})
cluster, _, err := client.ProjectCluster.GetCluster(pid, 1)
if err != nil {
t.Errorf("ProjectClusters.ListClusters returned error: %v", err)
}
if cluster.ID != 18 {
t.Errorf("expected clusterID 18; got %d", cluster.ID)
}
}
func TestAddCluster(t *testing.T) {
mux, server, client := setup()
defer teardown(server)
pid := 1234
mux.HandleFunc("/api/v4/projects/1234/clusters/user", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "POST")
response := `{
"id":24,
"name":"cluster-5",
"created_at":"2019-01-03T21:53:40.610Z",
"provider_type":"user",
"platform_type":"kubernetes",
"environment_scope":"*",
"cluster_type":"project_type",
"user":
{
"id":1,
"name":"Administrator",
"username":"root",
"state":"active",
"avatar_url":"https://www.gravatar.com/avatar/4249f4df72b..",
"web_url":"https://gitlab.example.com/root"
},
"platform_kubernetes":
{
"api_url":"https://35.111.51.20",
"namespace":"cluster-5-namespace",
"authorization_type":"rbac",
"ca_cert":"-----BEGIN CERTIFICATE-----\r\nhFiK1L61owwDQYJKoZIhvcNAQELBQAw\r\nLzEtMCsGA1UEAxMkZDA1YzQ1YjctNzdiMS00NDY0LThjNmEtMTQ0ZDJkZjM4ZDBj\r\nMB4XDTE4MTIyNzIwMDM1MVoXDTIzMTIyNjIxMDM1MVowLzEtMCsGA1UEAxMkZDA1\r\nYzQ1YjctNzdiMS00NDY0LThjNmEtMTQ0ZDJkZjM.......-----END CERTIFICATE-----"
},
"project":
{
"id":26,
"description":"",
"name":"project-with-clusters-api",
"name_with_namespace":"Administrator / project-with-clusters-api",
"path":"project-with-clusters-api",
"path_with_namespace":"root/project-with-clusters-api",
"created_at":"2019-01-02T20:13:32.600Z",
"default_branch":null,
"tag_list":[],
"ssh_url_to_repo":"ssh:://gitlab.example.com/root/project-with-clusters-api.git",
"http_url_to_repo":"https://gitlab.example.com/root/project-with-clusters-api.git",
"web_url":"https://gitlab.example.com/root/project-with-clusters-api",
"readme_url":null,
"avatar_url":null,
"star_count":0,
"forks_count":0,
"last_activity_at":"2019-01-02T20:13:32.600Z",
"namespace":
{
"id":1,
"name":"root",
"path":"root",
"kind":"user",
"full_path":"root",
"parent_id":null
}
}
}`
fmt.Fprint(w, response)
})
cluster, _, err := client.ProjectCluster.AddCluster(pid, &AddClusterOptions{})
if err != nil {
t.Errorf("ProjectClusters.AddCluster returned error: %v", err)
}
if cluster.ID != 24 {
t.Errorf("expected ClusterID 24; got %d", cluster.ID)
}
}
func TestEditCluster(t *testing.T) {
mux, server, client := setup()
defer teardown(server)
pid := 1234
mux.HandleFunc("/api/v4/projects/1234/clusters/1", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "PUT")
response := `{
"id":24,
"name":"new-cluster-name",
"created_at":"2019-01-03T21:53:40.610Z",
"provider_type":"user",
"platform_type":"kubernetes",
"environment_scope":"*",
"cluster_type":"project_type",
"user":
{
"id":1,
"name":"Administrator",
"username":"root",
"state":"active",
"avatar_url":"https://www.gravatar.com/avatar/4249f4df72b..",
"web_url":"https://gitlab.example.com/root"
},
"platform_kubernetes":
{
"api_url":"https://new-api-url.com",
"namespace":"cluster-5-namespace",
"authorization_type":"rbac",
"ca_cert":null
},
"project":
{
"id":26,
"description":"",
"name":"project-with-clusters-api",
"name_with_namespace":"Administrator / project-with-clusters-api",
"path":"project-with-clusters-api",
"path_with_namespace":"root/project-with-clusters-api",
"created_at":"2019-01-02T20:13:32.600Z",
"default_branch":null,
"tag_list":[],
"ssh_url_to_repo":"ssh:://gitlab.example.com/root/project-with-clusters-api.git",
"http_url_to_repo":"https://gitlab.example.com/root/project-with-clusters-api.git",
"web_url":"https://gitlab.example.com/root/project-with-clusters-api",
"readme_url":null,
"avatar_url":null,
"star_count":0,
"forks_count":0,
"last_activity_at":"2019-01-02T20:13:32.600Z",
"namespace":
{
"id":1,
"name":"root",
"path":"root",
"kind":"user",
"full_path":"root",
"parent_id":null
}
}
}`
fmt.Fprint(w, response)
})
cluster, _, err := client.ProjectCluster.EditCluster(pid, 1, &EditClusterOptions{})
if err != nil {
t.Errorf("ProjectClusters.EditCluster returned error: %v", err)
}
if cluster.ID != 24 {
t.Errorf("expected ClusterID 24; got %d", cluster.ID)
}
}
func TestDeleteCluster(t *testing.T) {
mux, server, client := setup()
defer teardown(server)
mux.HandleFunc("/api/v4/projects/1234/clusters/1", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "DELETE")
w.WriteHeader(http.StatusAccepted)
})
resp, err := client.ProjectCluster.DeleteCluster(1234, 1)
if err != nil {
t.Errorf("ProjectCluster.DeleteCluster returned error: %v", err)
}
want := http.StatusAccepted
got := resp.StatusCode
if got != want {
t.Errorf("ProjectCluster.DeleteCluster returned %d, want %d", got, want)
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment