Browse Source

add get kubeconfig endpoint

Anukul Sangwan 4 years ago
parent
commit
8d7f4a1c92

+ 1 - 5
api/client/k8s.go

@@ -60,13 +60,9 @@ func (c *Client) GetKubeconfig(
 	projectID uint,
 	clusterID uint,
 ) (*GetKubeconfigResponse, error) {
-	cl := fmt.Sprintf("%d", clusterID)
-
 	req, err := http.NewRequest(
 		"GET",
-		fmt.Sprintf("%s/projects/%d/k8s/kubeconfig?"+url.Values{
-			"cluster_id": []string{cl},
-		}.Encode(), c.BaseURL, projectID),
+		fmt.Sprintf("%s/projects/%d/clusters/%d/kubeconfig", c.BaseURL, projectID, clusterID),
 		nil,
 	)
 

+ 7 - 2
api/server/handlers/cluster/agent.go

@@ -7,6 +7,7 @@ import (
 )
 
 type KubernetesAgentGetter interface {
+	GetOutOfClusterConfig(cluster *models.Cluster) *kubernetes.OutOfClusterConfig
 	GetAgent(cluster *models.Cluster) (*kubernetes.Agent, error)
 }
 
@@ -18,12 +19,16 @@ func NewDefaultKubernetesAgentGetter(config *shared.Config) KubernetesAgentGette
 	return &DefaultKubernetesAgentGetter{config}
 }
 
-func (d *DefaultKubernetesAgentGetter) GetAgent(cluster *models.Cluster) (*kubernetes.Agent, error) {
-	ooc := &kubernetes.OutOfClusterConfig{
+func (d *DefaultKubernetesAgentGetter) GetOutOfClusterConfig(cluster *models.Cluster) *kubernetes.OutOfClusterConfig {
+	return &kubernetes.OutOfClusterConfig{
 		Repo:              d.config.Repo,
 		DigitalOceanOAuth: d.config.DOConf,
 		Cluster:           cluster,
 	}
+}
+
+func (d *DefaultKubernetesAgentGetter) GetAgent(cluster *models.Cluster) (*kubernetes.Agent, error) {
+	ooc := d.GetOutOfClusterConfig(cluster)
 
 	return kubernetes.GetAgentOutOfClusterConfig(ooc)
 }

+ 53 - 0
api/server/handlers/cluster/get_kubeconfig.go

@@ -0,0 +1,53 @@
+package cluster
+
+import (
+	"net/http"
+
+	"github.com/porter-dev/porter/api/server/handlers"
+	"github.com/porter-dev/porter/api/server/shared"
+	"github.com/porter-dev/porter/api/server/shared/apierrors"
+	"github.com/porter-dev/porter/api/types"
+	"github.com/porter-dev/porter/internal/models"
+	"k8s.io/client-go/tools/clientcmd"
+)
+
+type GetTemporaryKubeconfigHandler struct {
+	handlers.PorterHandlerWriter
+	KubernetesAgentGetter
+}
+
+func NewGetTemporaryKubeconfigHandler(
+	config *shared.Config,
+	writer shared.ResultWriter,
+) *GetTemporaryKubeconfigHandler {
+	return &GetTemporaryKubeconfigHandler{
+		PorterHandlerWriter:   handlers.NewDefaultPorterHandler(config, nil, writer),
+		KubernetesAgentGetter: NewDefaultKubernetesAgentGetter(config),
+	}
+}
+
+func (c *GetTemporaryKubeconfigHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+	cluster, _ := r.Context().Value(types.ClusterScope).(*models.Cluster)
+
+	outOfClusterConfig := c.GetOutOfClusterConfig(cluster)
+
+	kubeconfig, err := outOfClusterConfig.CreateRawConfigFromCluster()
+
+	if err != nil {
+		c.HandleAPIError(w, apierrors.NewErrInternal(err))
+		return
+	}
+
+	kubeconfigBytes, err := clientcmd.Write(*kubeconfig)
+
+	if err != nil {
+		c.HandleAPIError(w, apierrors.NewErrInternal(err))
+		return
+	}
+
+	res := &types.GetTemporaryKubeconfigResponse{
+		Kubeconfig: kubeconfigBytes,
+	}
+
+	c.WriteResult(w, res)
+}

+ 28 - 0
api/server/router/cluster.go

@@ -164,5 +164,33 @@ func getClusterRoutes(
 		Router:   r,
 	})
 
+	// GET /api/projects/{project_id}/clusters/{cluster_id}/kubeconfig -> cluster.NewGetTemporaryKubeconfigHandler
+	getTemporaryKubeconfigEndpoint := factory.NewAPIEndpoint(
+		&types.APIRequestMetadata{
+			Verb:   types.APIVerbGet,
+			Method: types.HTTPVerbGet,
+			Path: &types.Path{
+				Parent:       basePath,
+				RelativePath: relPath + "/kubeconfig",
+			},
+			Scopes: []types.PermissionScope{
+				types.UserScope,
+				types.ProjectScope,
+				types.ClusterScope,
+			},
+		},
+	)
+
+	getTemporaryKubeconfigHandler := cluster.NewGetTemporaryKubeconfigHandler(
+		config,
+		factory.GetResultWriter(),
+	)
+
+	routes = append(routes, &Route{
+		Endpoint: getTemporaryKubeconfigEndpoint,
+		Handler:  getTemporaryKubeconfigHandler,
+		Router:   r,
+	})
+
 	return routes, newPath
 }

+ 4 - 0
api/types/cluster.go

@@ -58,3 +58,7 @@ type CreateNamespaceResponse struct {
 type DeleteNamespaceRequest struct {
 	Name string `json:"name" form:"required"`
 }
+
+type GetTemporaryKubeconfigResponse struct {
+	Kubeconfig []byte `json:"kubeconfig"`
+}