Parcourir la source

provision eks endpoint + dashboard

Alexander Belanger il y a 5 ans
Parent
commit
120ae5208c

+ 4 - 2
dashboard/src/main/home/new-project/NewProject.tsx

@@ -214,18 +214,20 @@ export default class NewProject extends Component<PropsType, StateType> {
               this.context.setCurrentProject(proj);
 
               if (this.state.selectedProvider === 'aws') {
+                let clusterName = `${proj.name}-cluster`
 
                 api.createAWSIntegration('<token>', {
                   aws_region: awsRegion,
+                  aws_cluster_id: clusterName,
                   aws_access_key_id: awsAccessId,
                   aws_secret_access_key: awsSecretKey,
                 }, { id: proj.id }, (err2: any, res2: any) => {
                   if (err2) {
                     console.log(err2);
                   } else {
-                    api.provisionECR('<token>', {
+                    api.provisionEKS('<token>', {
                       aws_integration_id: res2.data.id,
-                      ecr_name: `${proj.name}-registry`
+                      eks_name: clusterName,
                     }, {id: proj.id}, (err3: any, res3:any) => {
                       if (err3) {
                         console.log(err3)

+ 8 - 0
dashboard/src/shared/api.tsx

@@ -210,6 +210,7 @@ const getProjectRepos = baseApi<{}, { id: number }>('GET', pathParams => {
 
 const createAWSIntegration = baseApi<{
   aws_region: string,
+  aws_cluster_id: string,
   aws_access_key_id: string,
   aws_secret_access_key: string,
 }, { id: number }>('POST', pathParams => {
@@ -223,6 +224,12 @@ const provisionECR = baseApi<{
   return `/api/projects/${pathParams.id}/provision/ecr`;
 });
 
+const provisionEKS = baseApi<{
+  eks_name: string,
+  aws_integration_id: string,
+}, { id: number }>('POST', pathParams => {
+  return `/api/projects/${pathParams.id}/provision/eks`;
+});
 
 const createECR = baseApi<{
   name: string,
@@ -301,6 +308,7 @@ export default {
   getProjectRepos,
   createAWSIntegration,
   provisionECR,
+  provisionEKS,
   createECR,
   getImageRepos,
   getImageTags,

+ 18 - 0
internal/forms/infra.go

@@ -21,3 +21,21 @@ func (ce *CreateECRInfra) ToAWSInfra() (*models.AWSInfra, error) {
 		AWSIntegrationID: ce.AWSIntegrationID,
 	}, nil
 }
+
+// CreateEKSInfra represents the accepted values for creating an
+// EKS infra via the provisioning container
+type CreateEKSInfra struct {
+	EKSName          string `json:"eks_name" form:"required"`
+	ProjectID        uint   `json:"project_id" form:"required"`
+	AWSIntegrationID uint   `json:"aws_integration_id" form:"required"`
+}
+
+// ToAWSInfra converts the form to a gorm aws infra model
+func (ce *CreateEKSInfra) ToAWSInfra() (*models.AWSInfra, error) {
+	return &models.AWSInfra{
+		Kind:             models.AWSInfraEKS,
+		ProjectID:        ce.ProjectID,
+		Status:           models.StatusCreating,
+		AWSIntegrationID: ce.AWSIntegrationID,
+	}, nil
+}

+ 26 - 0
internal/kubernetes/agent.go

@@ -11,6 +11,7 @@ import (
 	"github.com/porter-dev/porter/internal/kubernetes/provisioner"
 	"github.com/porter-dev/porter/internal/kubernetes/provisioner/aws"
 	"github.com/porter-dev/porter/internal/kubernetes/provisioner/aws/ecr"
+	"github.com/porter-dev/porter/internal/kubernetes/provisioner/aws/eks"
 	"github.com/porter-dev/porter/internal/models"
 	"github.com/porter-dev/porter/internal/models/integrations"
 
@@ -257,6 +258,31 @@ func (a *Agent) ProvisionECR(
 	return a.provision(prov)
 }
 
+// ProvisionEKS spawns a new provisioning pod that creates an EKS instance
+func (a *Agent) ProvisionEKS(
+	projectID uint,
+	awsConf *integrations.AWSIntegration,
+	eksName string,
+	awsInfra *models.AWSInfra,
+) (*batchv1.Job, error) {
+	id := awsInfra.GetID()
+	prov := &provisioner.Conf{
+		ID:   id,
+		Name: fmt.Sprintf("prov-%s", id),
+		Kind: provisioner.EKS,
+		AWS: &aws.Conf{
+			AWSRegion:          awsConf.AWSRegion,
+			AWSAccessKeyID:     string(awsConf.AWSAccessKeyID),
+			AWSSecretAccessKey: string(awsConf.AWSSecretAccessKey),
+		},
+		EKS: &eks.Conf{
+			ClusterName: eksName,
+		},
+	}
+
+	return a.provision(prov)
+}
+
 // ProvisionTest spawns a new provisioning pod that tests provisioning
 func (a *Agent) ProvisionTest(
 	projectID uint,

+ 3 - 3
internal/kubernetes/provisioner/global_stream.go

@@ -2,6 +2,7 @@ package provisioner
 
 import (
 	"context"
+	"encoding/json"
 	"fmt"
 
 	"github.com/porter-dev/porter/internal/repository"
@@ -134,11 +135,10 @@ func GlobalStreamListener(
 					}
 
 					// parse raw data into ECR type
-					dataMap, ok := msg.Values["data"].(map[string]interface{})
+					dataString, ok := msg.Values["data"].(string)
 
 					if ok {
-						name, _ := dataMap["name"].(string)
-						reg.Name = name
+						json.Unmarshal([]byte(dataString), reg)
 					}
 
 					reg, err := repo.Registry.CreateRegistry(reg)

+ 80 - 0
server/api/provision_handler.go

@@ -123,6 +123,86 @@ func (app *App) HandleProvisionAWSECRInfra(w http.ResponseWriter, r *http.Reques
 	}
 }
 
+// HandleProvisionAWSEKSInfra provisions a new aws EKS instance for a project
+func (app *App) HandleProvisionAWSEKSInfra(w http.ResponseWriter, r *http.Request) {
+	projID, err := strconv.ParseUint(chi.URLParam(r, "project_id"), 0, 64)
+
+	if err != nil || projID == 0 {
+		app.handleErrorFormDecoding(err, ErrProjectDecode, w)
+		return
+	}
+
+	form := &forms.CreateEKSInfra{
+		ProjectID: uint(projID),
+	}
+
+	// decode from JSON to form value
+	if err := json.NewDecoder(r.Body).Decode(form); err != nil {
+		app.handleErrorFormDecoding(err, ErrProjectDecode, w)
+		return
+	}
+
+	// validate the form
+	if err := app.validator.Struct(form); err != nil {
+		app.handleErrorFormValidation(err, ErrProjectValidateFields, w)
+		return
+	}
+
+	// convert the form to an aws infra instance
+	infra, err := form.ToAWSInfra()
+
+	if err != nil {
+		app.handleErrorFormDecoding(err, ErrProjectDecode, w)
+		return
+	}
+
+	// handle write to the database
+	infra, err = app.Repo.AWSInfra.CreateAWSInfra(infra)
+
+	if err != nil {
+		app.handleErrorDataWrite(err, w)
+		return
+	}
+
+	awsInt, err := app.Repo.AWSIntegration.ReadAWSIntegration(infra.AWSIntegrationID)
+
+	if err != nil {
+		app.handleErrorDataRead(err, w)
+		return
+	}
+
+	// launch provisioning pod
+	agent, err := kubernetes.GetAgentInClusterConfig()
+
+	if err != nil {
+		app.handleErrorDataRead(err, w)
+		return
+	}
+
+	_, err = agent.ProvisionEKS(
+		uint(projID),
+		awsInt,
+		form.EKSName,
+		infra,
+	)
+
+	if err != nil {
+		app.handleErrorInternal(err, w)
+		return
+	}
+
+	app.Logger.Info().Msgf("New aws eks infra created: %d", infra.ID)
+
+	w.WriteHeader(http.StatusCreated)
+
+	infraExt := infra.Externalize()
+
+	if err := json.NewEncoder(w).Encode(infraExt); err != nil {
+		app.handleErrorFormDecoding(err, ErrProjectDecode, w)
+		return
+	}
+}
+
 // HandleGetProvisioningLogs returns real-time logs of the provisioning process via websockets
 func (app *App) HandleGetProvisioningLogs(w http.ResponseWriter, r *http.Request) {
 	// get path parameters

+ 10 - 0
server/router/router.go

@@ -198,6 +198,16 @@ func New(a *api.App) *chi.Mux {
 			),
 		)
 
+		r.Method(
+			"POST",
+			"/projects/{project_id}/provision/eks",
+			auth.DoesUserHaveProjectAccess(
+				requestlog.NewHandler(a.HandleProvisionAWSEKSInfra, l),
+				mw.URLParam,
+				mw.ReadAccess,
+			),
+		)
+
 		r.Method(
 			"GET",
 			"/projects/{project_id}/provision/{kind}/{infra_id}/logs",