Procházet zdrojové kódy

cleanups and error handling

Feroze Mohideen před 3 roky
rodič
revize
d58f5283ad

+ 2 - 0
api/server/handlers/project_integration/create_aws.go

@@ -57,6 +57,8 @@ func (p *CreateAWSHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 			SourceArn:       "arn:aws:iam::108458755588:role/CAPIManagement", // hard coded as this is the final hop for a CAPI cluster
 			TargetAccessId:  request.AWSAccessKeyID,
 			TargetSecretKey: request.AWSSecretAccessKey,
+			TargetArn:       request.TargetArn,
+			ExternalId:      request.ExternalID,
 		}
 		credResp, err := p.Config().ClusterControlPlaneClient.CreateAssumeRoleChain(ctx, connect.NewRequest(&credReq))
 		if err != nil {

+ 0 - 65
api/server/handlers/project_integration/preflight_check_aws_role.go

@@ -1,65 +0,0 @@
-package project_integration
-
-import (
-	"fmt"
-	"net/http"
-
-	"github.com/bufbuild/connect-go"
-	porterv1 "github.com/porter-dev/api-contracts/generated/go/porter/v1"
-	"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/server/shared/config"
-	"github.com/porter-dev/porter/api/types"
-	"github.com/porter-dev/porter/internal/models"
-)
-
-type CreatePreflightCheckAWSRoleHandler struct {
-	handlers.PorterHandlerReadWriter
-}
-
-func NewCreatePreflightCheckAWSRoleHandler(
-	config *config.Config,
-	decoderValidator shared.RequestDecoderValidator,
-	writer shared.ResultWriter,
-) *CreatePreflightCheckAWSRoleHandler {
-	return &CreatePreflightCheckAWSRoleHandler{
-		PorterHandlerReadWriter: handlers.NewDefaultPorterHandler(config, decoderValidator, writer),
-	}
-}
-
-func (p *CreatePreflightCheckAWSRoleHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
-	project, _ := r.Context().Value(types.ProjectScope).(*models.Project)
-	ctx := r.Context()
-
-	request := &types.RolePreflightCheckRequest{}
-	if ok := p.DecodeAndValidate(w, r, request); !ok {
-		return
-	}
-
-	res := types.RolePreflightCheckResponse{
-		TargetARN: request.TargetARN,
-	}
-
-	checkReq := porterv1.RolePreflightCheckRequest{
-		ProjectId:  int64(project.ID),
-		TargetArn:  request.TargetARN,
-		ExternalId: request.ExternalID,
-	}
-
-	checkResp, err := p.Config().ClusterControlPlaneClient.RolePreflightCheck(ctx, connect.NewRequest(&checkReq))
-
-	if err != nil {
-		e := fmt.Errorf("preflight check failed: %w", err)
-		p.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(
-			e,
-			http.StatusNotFound,
-		))
-
-		return
-	}
-
-	res.TargetARN = checkResp.Msg.TargetArn
-
-	p.WriteResult(w, r, checkResp)
-}

+ 2 - 2
api/server/handlers/project_integration/preflight_check_aws_usage.go

@@ -46,8 +46,8 @@ func (p *CreatePreflightCheckAWSUsageHandler) ServeHTTP(w http.ResponseWriter, r
 	checkResp, err := p.Config().ClusterControlPlaneClient.QuotaPreflightCheck(ctx, connect.NewRequest(&checkReq))
 
 	if err != nil {
-		e := fmt.Errorf("preflight check failed: %w", err)
-		p.HandleAPIError(w, r, apierrors.NewErrInternal(e))
+		e := fmt.Errorf("Pre-provision check failed: %w", err)
+		p.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(e, http.StatusPreconditionFailed, err.Error()))
 		return
 	}
 

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

@@ -220,34 +220,6 @@ func getProjectIntegrationRoutes(
 		Router:   r,
 	})
 
-	// POST /api/projects/{project_id}/integrations/aws/preflightcheck/role -> project_integration.NewCreatePreflightCheckAWSHandler
-	preflightCheckAWSRoleEndpoint := factory.NewAPIEndpoint(
-		&types.APIRequestMetadata{
-			Verb:   types.APIVerbCreate,
-			Method: types.HTTPVerbPost,
-			Path: &types.Path{
-				Parent:       basePath,
-				RelativePath: relPath + "/aws/preflight/role",
-			},
-			Scopes: []types.PermissionScope{
-				types.UserScope,
-				types.ProjectScope,
-			},
-		},
-	)
-
-	preflightCheckAWSRoleHandler := project_integration.NewCreatePreflightCheckAWSRoleHandler(
-		config,
-		factory.GetDecoderValidator(),
-		factory.GetResultWriter(),
-	)
-
-	routes = append(routes, &router.Route{
-		Endpoint: preflightCheckAWSRoleEndpoint,
-		Handler:  preflightCheckAWSRoleHandler,
-		Router:   r,
-	})
-
 	// POST /api/projects/{project_id}/integrations/aws/preflightcheck/usage -> project_integration.NewCreatePreflightCheckAWSHandler
 	preflightCheckAWSUsageEndpoint := factory.NewAPIEndpoint(
 		&types.APIRequestMetadata{

+ 2 - 10
api/types/project_integration.go

@@ -75,16 +75,6 @@ type AWSIntegration struct {
 
 type ListAWSResponse []*AWSIntegration
 
-type RolePreflightCheckRequest struct {
-	ProjectID  uint   `json:"project_id"`
-	TargetARN  string `json:"target_arn"`
-	ExternalID string `json:"external_id"`
-}
-
-type RolePreflightCheckResponse struct {
-	TargetARN string `json:"target_arn"`
-}
-
 type QuotaPreflightCheckRequest struct {
 	ProjectID  uint   `json:"project_id"`
 	TargetARN  string `json:"target_arn"`
@@ -100,6 +90,8 @@ type CreateAWSRequest struct {
 	AWSAccessKeyID     string `json:"aws_access_key_id"`
 	AWSSecretAccessKey string `json:"aws_secret_access_key"`
 	AWSAssumeRoleArn   string `json:"aws_assume_role_arn"`
+	TargetArn          string `json:"aws_target_arn"`
+	ExternalID         string `json:"aws_external_id"`
 }
 
 type CreateAWSResponse struct {

+ 3 - 3
dashboard/src/components/CloudFormationForm.tsx

@@ -49,11 +49,11 @@ const CloudFormationForm: React.FC<Props> = ({
     let targetARN = `arn:aws:iam::${AWSAccountID}:role/porter-role`
     setRoleStatus("loading");
     api
-      .preflightCheckAWSRole(
+      .createAWSIntegration(
         "<token>",
         {
-          target_arn: targetARN,
-          external_id: externalId,
+          aws_target_arn: targetARN,
+          aws_external_id: externalId,
         },
         {
           id: currentProject.id,

+ 29 - 22
dashboard/src/components/ProvisionerSettings.tsx

@@ -76,6 +76,7 @@ const ProvisionerSettings: React.FC<Props> = props => {
   const [cidrRange, setCidrRange] = useState("172.0.0.0/16");
   const [clusterVersion, setClusterVersion] = useState("v1.24.0");
   const [isReadOnly, setIsReadOnly] = useState(false);
+  const [errorMessage, setErrorMessage] = useState<string>(undefined);
 
   const createCluster = async () => {
     var data = new Contract({
@@ -123,27 +124,19 @@ const ProvisionerSettings: React.FC<Props> = props => {
       data["cluster"]["clusterId"] = props.clusterId;
     }
 
-    // api
-    //   .preflightCheckAWSUsage(
-    //     "<token>",
-    //     {
-    //       // TODO: change this back
-    //       // target_arn: `arn:aws:iam::${props.AWSAccountID}:role/porter-role`,
-    //       target_arn: "arn:aws:iam::844966915049:role/PorterRole-RootRole-1S8V1TYOMOXTK",
-    //       region: awsRegion
-    //     },
-    //     {
-    //       id: currentProject.id,
-    //     }
-    //   )
-    //   .then(({ data }) => {
-    //     console.log(data)
-    //   })
-    //   .catch((err) => {
-    //     console.error(err);
-    //   });
-
     try {
+      await api
+        .preflightCheckAWSUsage(
+          "<token>",
+          {
+            target_arn: `arn:aws:iam::${props.AWSAccountID}:role/porter-role`,
+            region: awsRegion
+          },
+          {
+            id: currentProject.id,
+          }
+        );
+
       const res = await api.createContract(
         "<token>",
         data,
@@ -174,8 +167,9 @@ const ProvisionerSettings: React.FC<Props> = props => {
             console.error(err);
           });
       }
+      setErrorMessage(undefined);
     } catch (err) {
-      console.log(err);
+      setErrorMessage(err.response.data.error.replace('unknown: ', ''));
     }
   }
 
@@ -338,6 +332,7 @@ const ProvisionerSettings: React.FC<Props> = props => {
         statusPosition="right"
         status={isReadOnly && "Provisioning is still in progress"}
       />
+      {errorMessage && <ErrorContainer>{errorMessage} Please correct the issue and try to provision again.</ErrorContainer>}
     </>
   );
 };
@@ -363,4 +358,16 @@ const StyledForm = styled.div`
   border: 1px solid #494b4f;
   font-size: 13px;
   margin-bottom: 30px;
-`;
+`;
+
+const ErrorContainer = styled.div`
+  position: relative;
+  margin-top: 20px;
+  padding: 30px 30px 25px;
+  border-radius: 5px;
+  background: #26292e;
+  border: 1px solid #494b4f;
+  font-size: 13px;
+  margin-bottom: 30px;
+  color: red;
+`

+ 5 - 14
dashboard/src/shared/api.tsx

@@ -71,16 +71,6 @@ const getGitlabIntegration = baseApi<{}, { project_id: number }>(
   ({ project_id }) => `/api/projects/${project_id}/integrations/gitlab`
 );
 
-const preflightCheckAWSRole = baseApi<
-  {
-    target_arn: string;
-    external_id: string;
-  },
-  { id: number }
->("POST", (pathParams) => {
-  return `/api/projects/${pathParams.id}/integrations/aws/preflight/role`;
-});
-
 const preflightCheckAWSUsage = baseApi<
   {
     target_arn: string;
@@ -93,11 +83,13 @@ const preflightCheckAWSUsage = baseApi<
 
 const createAWSIntegration = baseApi<
   {
-    aws_region: string;
+    aws_region?: string;
     aws_cluster_id?: string;
-    aws_access_key_id: string;
-    aws_secret_access_key: string;
+    aws_access_key_id?: string;
+    aws_secret_access_key?: string;
     aws_assume_role_arn?: string;
+    aws_target_arn?: string;
+    aws_external_id?: string;
   },
   { id: number }
 >("POST", (pathParams) => {
@@ -2575,7 +2567,6 @@ export default {
   addApplicationToEnvGroup,
   removeApplicationFromEnvGroup,
   provisionDatabase,
-  preflightCheckAWSRole,
   preflightCheckAWSUsage,
   getDatabases,
   getPreviousLogsForContainer,

+ 1 - 1
go.mod

@@ -74,7 +74,7 @@ require (
 	github.com/glebarez/sqlite v1.6.0
 	github.com/nats-io/nats.go v1.24.0
 	github.com/open-policy-agent/opa v0.44.0
-	github.com/porter-dev/api-contracts v0.0.51
+	github.com/porter-dev/api-contracts v0.0.58
 	github.com/santhosh-tekuri/jsonschema/v5 v5.0.1
 	github.com/stefanmcshane/helm v0.0.0-20221213002717-88a4a2c6e77d
 	github.com/xanzy/go-gitlab v0.68.0

+ 2 - 4
go.sum

@@ -1466,10 +1466,8 @@ github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/polyfloyd/go-errorlint v0.0.0-20210722154253-910bb7978349/go.mod h1:wi9BfjxjF/bwiZ701TzmfKu6UKC357IOAtNr0Td0Lvw=
-github.com/porter-dev/api-contracts v0.0.48 h1:i6B6H26+am/H61YC1u9u7gAah+opnWS7qfUxZQrkWjo=
-github.com/porter-dev/api-contracts v0.0.48/go.mod h1:qr2L58mJLr5DUGV5OPw3REiSrQvJq6TgkKyEWP95dyU=
-github.com/porter-dev/api-contracts v0.0.51 h1:gQIHqG78DuvjxQ44epFwwO69+nO3/LaZDqhl//60xNg=
-github.com/porter-dev/api-contracts v0.0.51/go.mod h1:qr2L58mJLr5DUGV5OPw3REiSrQvJq6TgkKyEWP95dyU=
+github.com/porter-dev/api-contracts v0.0.58 h1:J587ZrAts6WLt717ud3EuD8GEF14YDygKaLCSRbh634=
+github.com/porter-dev/api-contracts v0.0.58/go.mod h1:qr2L58mJLr5DUGV5OPw3REiSrQvJq6TgkKyEWP95dyU=
 github.com/porter-dev/switchboard v0.0.0-20221019155755-67ff2bf04935 h1:hfb3nt3AJXIBbevu6ARTg9SdOkMP6WLbKBiG5hT5rcc=
 github.com/porter-dev/switchboard v0.0.0-20221019155755-67ff2bf04935/go.mod h1:xSPzqSFMQ6OSbp42fhCi4AbGbQbsm6nRvOkrblFeXU4=
 github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=