diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ac6a8db..026227f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Change Log +## Unreleased + +- #259 Add Kubernetes GetCredentials method - @snormore + ## [v1.21.1] - 2019-09-19 - #257 Upgrade to Go 1.13 - @bentranter diff --git a/kubernetes.go b/kubernetes.go index 6271be6d..35fcd19a 100644 --- a/kubernetes.go +++ b/kubernetes.go @@ -8,6 +8,7 @@ import ( "fmt" "net/http" "net/url" + "strconv" "strings" "time" ) @@ -27,6 +28,7 @@ type KubernetesService interface { GetUser(context.Context, string) (*KubernetesClusterUser, *Response, error) GetUpgrades(context.Context, string) ([]*KubernetesVersion, *Response, error) GetKubeConfig(context.Context, string) (*KubernetesClusterConfig, *Response, error) + GetCredentials(context.Context, string, *KubernetesClusterCredentialsGetRequest) (*KubernetesClusterCredentials, *Response, error) List(context.Context, *ListOptions) ([]*KubernetesCluster, *Response, error) Update(context.Context, string, *KubernetesClusterUpdateRequest) (*KubernetesCluster, *Response, error) Upgrade(context.Context, string, *KubernetesClusterUpgradeRequest) (*Response, error) @@ -117,6 +119,11 @@ type KubernetesNodeDeleteRequest struct { SkipDrain bool `json:"skip_drain,omitempty"` } +// KubernetesClusterCredentialsGetRequest is a request to get cluster credentials. +type KubernetesClusterCredentialsGetRequest struct { + ExpirySeconds *int `json:"expiry_seconds,omitempty"` +} + // KubernetesCluster represents a Kubernetes cluster. type KubernetesCluster struct { ID string `json:"id,omitempty"` @@ -146,6 +153,16 @@ type KubernetesClusterUser struct { Groups []string `json:"groups,omitempty"` } +// KubernetesClusterCredentials represents Kubernetes cluster credentials. +type KubernetesClusterCredentials struct { + Server string `json:"server"` + CertificateAuthorityData []byte `json:"certificate_authority_data"` + ClientCertificateData []byte `json:"client_certificate_data"` + ClientKeyData []byte `json:"client_key_data"` + Token string `json:"token"` + ExpiresAt time.Time `json:"expires_at"` +} + // KubernetesMaintenancePolicy is a configuration to set the maintenance window // of a cluster type KubernetesMaintenancePolicy struct { @@ -480,6 +497,25 @@ func (svc *KubernetesServiceOp) GetKubeConfig(ctx context.Context, clusterID str return res, resp, nil } +// GetCredentials returns a Kubernetes API server credentials for the specified cluster. +func (svc *KubernetesServiceOp) GetCredentials(ctx context.Context, clusterID string, get *KubernetesClusterCredentialsGetRequest) (*KubernetesClusterCredentials, *Response, error) { + path := fmt.Sprintf("%s/%s/credentials", kubernetesClustersPath, clusterID) + req, err := svc.client.NewRequest(ctx, http.MethodGet, path, nil) + if err != nil { + return nil, nil, err + } + q := req.URL.Query() + if get.ExpirySeconds != nil { + q.Add("expiry_seconds", strconv.Itoa(*get.ExpirySeconds)) + } + credentials := new(KubernetesClusterCredentials) + resp, err := svc.client.Do(ctx, req, credentials) + if err != nil { + return nil, nil, err + } + return credentials, resp, nil +} + // Update updates a Kubernetes cluster's properties. func (svc *KubernetesServiceOp) Update(ctx context.Context, clusterID string, update *KubernetesClusterUpdateRequest) (*KubernetesCluster, *Response, error) { path := fmt.Sprintf("%s/%s", kubernetesClustersPath, clusterID) diff --git a/kubernetes_test.go b/kubernetes_test.go index 1e6c100b..1d9471c5 100644 --- a/kubernetes_test.go +++ b/kubernetes_test.go @@ -373,6 +373,33 @@ func TestKubernetesClusters_GetKubeConfig(t *testing.T) { require.Equal(t, blob, got.KubeconfigYAML) } +func TestKubernetesClusters_GetCredentials(t *testing.T) { + setup() + defer teardown() + + kubeSvc := client.Kubernetes + timestamp, err := time.Parse(time.RFC3339, "2014-11-12T11:45:26.371Z") + require.NoError(t, err) + want := &KubernetesClusterCredentials{ + Token: "secret", + ExpiresAt: timestamp, + } + jBlob := ` +{ + "token": "secret", + "expires_at": "2014-11-12T11:45:26.371Z" +}` + mux.HandleFunc("/v2/kubernetes/clusters/deadbeef-dead-4aa5-beef-deadbeef347d/credentials", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, http.MethodGet) + fmt.Fprint(w, jBlob) + }) + got, _, err := kubeSvc.GetCredentials(ctx, "deadbeef-dead-4aa5-beef-deadbeef347d", &KubernetesClusterCredentialsGetRequest{ + ExpirySeconds: intPtr(60 * 60), + }) + require.NoError(t, err) + require.Equal(t, want, got) +} + func TestKubernetesClusters_GetUpgrades(t *testing.T) { setup() defer teardown()