Преглед изворни кода

Merge pull request #2681 from porter-dev/staging

KMS in existing clusters
jusrhee пре 3 година
родитељ
комит
346f1bf956

+ 2 - 1
.github/workflows/build-dev-cli.yaml

@@ -24,7 +24,8 @@ jobs:
         run: |
           DOCKER_BUILDKIT=1 docker build . \
             -t public.ecr.aws/o1j4x7p4/porter-cli:dev \
-            -f ./services/porter_cli_container/dev.Dockerfile
+            -f ./services/porter_cli_container/dev.Dockerfile \
+            --build-arg SENTRY_DSN=${{ secrets.SENTRY_DSN }}
       - name: Push
         run: |
           docker push public.ecr.aws/o1j4x7p4/porter-cli:dev

+ 4 - 3
.github/workflows/prerelease.yaml

@@ -142,7 +142,7 @@ jobs:
           NODE_ENV: production
       - name: Build Linux binaries
         run: |
-          go build -ldflags="-w -s -X 'github.com/porter-dev/porter/cli/cmd/config.Version=${{steps.tag_name.outputs.tag}}'" -a -tags cli -o ./porter ./cli &
+          go build -ldflags="-w -s -X 'github.com/porter-dev/porter/cli/cmd/config.Version=${{steps.tag_name.outputs.tag}}' -X 'github.com/porter-dev/porter/cli/cmd/errors.SentryDSN=${{secrets.SENTRY_DSN}}'" -a -tags cli -o ./porter ./cli &
           go build -ldflags="-w -s -X 'main.Version=${{steps.tag_name.outputs.tag}}'" -a -o ./docker-credential-porter ./cmd/docker-credential-porter/ &
           go build -ldflags="-w -s -X 'main.Version=${{steps.tag_name.outputs.tag}}'" -a -tags ee -o ./portersvr ./cmd/app/ &
           wait
@@ -199,7 +199,7 @@ jobs:
           EOL
       - name: Build and Zip MacOS amd64 binaries
         run: |
-          go build -ldflags="-w -s -X 'github.com/porter-dev/porter/cli/cmd/config.Version=${{steps.tag_name.outputs.tag}}'" -a -tags cli -o ./amd64/porter ./cli &
+          go build -ldflags="-w -s -X 'github.com/porter-dev/porter/cli/cmd/config.Version=${{steps.tag_name.outputs.tag}}' -X 'github.com/porter-dev/porter/cli/cmd/errors.SentryDSN=${{secrets.SENTRY_DSN}}'" -a -tags cli -o ./amd64/porter ./cli &
           go build -ldflags="-w -s -X 'main.Version=${{steps.tag_name.outputs.tag}}'" -a -o ./amd64/docker-credential-porter ./cmd/docker-credential-porter/ &
           go build -ldflags="-w -s -X 'main.Version=${{steps.tag_name.outputs.tag}}'" -a -tags ee -o ./amd64/portersvr ./cmd/app/ &
           wait
@@ -462,7 +462,8 @@ jobs:
           docker build ./services/porter_cli_container \
             -t public.ecr.aws/o1j4x7p4/porter-cli:${{steps.tag_name.outputs.tag}} \
             -f ./services/porter_cli_container/Dockerfile \
-            --build-arg VERSION=${{steps.tag_name.outputs.tag}}
+            --build-arg VERSION=${{steps.tag_name.outputs.tag}} \
+            --build-arg SENTRY_DSN=${{secrets.SENTRY_DSN}}
       - name: Push
         run: |
           docker push public.ecr.aws/o1j4x7p4/porter-cli:${{steps.tag_name.outputs.tag}}

+ 5 - 4
Makefile

@@ -1,5 +1,6 @@
-BINDIR      := $(CURDIR)/bin
-VERSION ?= dev
+BINDIR     := $(CURDIR)/bin
+VERSION    ?= dev
+SENTRY_DSN ?= 
 
 start-dev: install setup-env-files
 	bash ./scripts/dev-environment/StartDevServer.sh
@@ -14,10 +15,10 @@ setup-env-files:
 	bash ./scripts/dev-environment/CreateDefaultEnvFiles.sh
 
 build-cli:
-	go build -ldflags="-w -s -X 'github.com/porter-dev/porter/cli/cmd/config.Version=${VERSION}'" -a -tags cli -o $(BINDIR)/porter ./cli
+	go build -ldflags="-w -s -X 'github.com/porter-dev/porter/cli/cmd/config.Version=${VERSION}' -X 'github.com/porter-dev/porter/cli/cmd/errors.SentryDSN=${SENTRY_DSN}'" -a -tags cli -o $(BINDIR)/porter ./cli
 
 build-cli-dev:
-	go build -ldflags="-X 'github.com/porter-dev/porter/cli/cmd/config.Version=${VERSION}'" -tags cli -o $(BINDIR)/porter ./cli
+	go build -ldflags="-X 'github.com/porter-dev/porter/cli/cmd/config.Version=${VERSION}' -X 'github.com/porter-dev/porter/cli/cmd/errors.SentryDSN=${SENTRY_DSN}'" -tags cli -o $(BINDIR)/porter ./cli
 
 start-provisioner-dev: install setup-env-files
 	bash ./scripts/dev-environment/StartProvisionerServer.sh

+ 1 - 1
api/client/registry.go

@@ -31,7 +31,7 @@ func (c *Client) CreateRegistry(
 func (c *Client) CreateHelmRepo(
 	ctx context.Context,
 	projectID uint,
-	req *types.CreateHelmRepoRequest,
+	req *types.CreateUpdateHelmRepoRequest,
 ) (*types.HelmRepo, error) {
 	resp := &types.HelmRepo{}
 

+ 1 - 1
api/server/handlers/helmrepo/create.go

@@ -31,7 +31,7 @@ func NewHelmRepoCreateHandler(
 func (p *HelmRepoCreateHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 	proj, _ := r.Context().Value(types.ProjectScope).(*models.Project)
 
-	request := &types.CreateHelmRepoRequest{}
+	request := &types.CreateUpdateHelmRepoRequest{}
 
 	ok := p.DecodeAndValidate(w, r, request)
 

+ 92 - 0
api/server/handlers/helmrepo/update.go

@@ -0,0 +1,92 @@
+package helmrepo
+
+import (
+	"errors"
+	"fmt"
+	"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/server/shared/config"
+	"github.com/porter-dev/porter/api/server/shared/requestutils"
+	"github.com/porter-dev/porter/api/types"
+	"github.com/porter-dev/porter/internal/models"
+	"gorm.io/gorm"
+)
+
+type HelmRepoUpdateHandler struct {
+	handlers.PorterHandlerReadWriter
+}
+
+func NewHelmRepoUpdateHandler(
+	config *config.Config,
+	decoderValidator shared.RequestDecoderValidator,
+	writer shared.ResultWriter,
+) *HelmRepoUpdateHandler {
+	return &HelmRepoUpdateHandler{
+		PorterHandlerReadWriter: handlers.NewDefaultPorterHandler(config, decoderValidator, writer),
+	}
+}
+
+func (p *HelmRepoUpdateHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+	proj, _ := r.Context().Value(types.ProjectScope).(*models.Project)
+
+	helmRepoID, reqErr := requestutils.GetURLParamUint(r, "helm_repo_id")
+
+	if reqErr != nil {
+		p.HandleAPIError(w, r, reqErr)
+		return
+	}
+
+	helmRepo, err := p.Repo().HelmRepo().ReadHelmRepo(proj.ID, helmRepoID)
+
+	if err != nil {
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			p.HandleAPIError(w, r, apierrors.NewErrNotFound(fmt.Errorf("no such helm repo")))
+			return
+		}
+
+		p.HandleAPIError(w, r, apierrors.NewErrInternal(err))
+		return
+	}
+
+	request := &types.CreateUpdateHelmRepoRequest{}
+
+	ok := p.DecodeAndValidate(w, r, request)
+
+	if !ok {
+		return
+	}
+
+	// if a basic integration is specified, verify that it exists in the project
+	if request.BasicIntegrationID != 0 {
+		_, err := p.Repo().BasicIntegration().ReadBasicIntegration(proj.ID, request.BasicIntegrationID)
+
+		if err != nil {
+			if errors.Is(err, gorm.ErrRecordNotFound) {
+				p.HandleAPIError(w, r, apierrors.NewErrForbidden(
+					fmt.Errorf("basic integration with id %d not found in project %d", request.BasicIntegrationID, proj.ID),
+				))
+
+				return
+			}
+
+			p.HandleAPIError(w, r, apierrors.NewErrInternal(err))
+			return
+		}
+	}
+
+	helmRepo.Name = request.Name
+	helmRepo.RepoURL = request.URL
+	helmRepo.BasicAuthIntegrationID = request.BasicIntegrationID
+
+	helmRepo, err = p.Repo().HelmRepo().UpdateHelmRepo(helmRepo)
+
+	if err != nil {
+		p.HandleAPIError(w, r, apierrors.NewErrInternal(err))
+		return
+	}
+
+	p.WriteResult(w, r, helmRepo.ToHelmRepoType())
+}

+ 10 - 1
api/server/handlers/infra/forms.go

@@ -471,7 +471,7 @@ tabs:
           value: m6i.4xlarge
         - label: r5.large
           value: r5.large
-        - value: r5.xlarge
+        - label: r5.xlarge
           value: r5.xlarge
     - type: string-input
       label: 👤 Issuer Email
@@ -758,6 +758,15 @@ tabs:
           value: t3.large
         - label: t3.xlarge
           value: t3.xlarge
+  - name: kms_secret_encryption
+    contents:
+    - type: heading
+      label: KMS Encryption
+    - type: checkbox
+      variable: is_kms_enabled
+      label: Encrypt all Kubernetes secrets with AWS Key Management Service (KMS)
+      settings:
+        default: false
 `
 
 const gcrForm = `name: GCR

+ 29 - 0
api/server/router/helm_repo.go

@@ -81,6 +81,35 @@ func getHelmRepoRoutes(
 		Router:   r,
 	})
 
+	// PATCH /api/projects/{project_id}/helmrepos/{helm_repo_id} -> registry.NewHelmRepoUpdateHandler
+	updateEndpoint := factory.NewAPIEndpoint(
+		&types.APIRequestMetadata{
+			Verb:   types.APIVerbUpdate,
+			Method: types.HTTPVerbPatch,
+			Path: &types.Path{
+				Parent:       basePath,
+				RelativePath: relPath,
+			},
+			Scopes: []types.PermissionScope{
+				types.UserScope,
+				types.ProjectScope,
+				types.HelmRepoScope,
+			},
+		},
+	)
+
+	updateHandler := helmrepo.NewHelmRepoUpdateHandler(
+		config,
+		factory.GetDecoderValidator(),
+		factory.GetResultWriter(),
+	)
+
+	routes = append(routes, &router.Route{
+		Endpoint: updateEndpoint,
+		Handler:  updateHandler,
+		Router:   r,
+	})
+
 	// DELETE /api/projects/{project_id}/helmrepos/{helm_repo_id} -> registry.NewHelmRepoDeleteHandler
 	deleteEndpoint := factory.NewAPIEndpoint(
 		&types.APIRequestMetadata{

+ 2 - 2
api/types/helm_repo.go

@@ -14,8 +14,8 @@ type HelmRepo struct {
 
 type GetHelmRepoResponse HelmRepo
 
-type CreateHelmRepoRequest struct {
-	URL                string `json:"url"`
+type CreateUpdateHelmRepoRequest struct {
+	URL                string `json:"url" form:"required"`
 	Name               string `json:"name" form:"required"`
 	BasicIntegrationID uint   `json:"basic_integration_id"`
 }

+ 1 - 1
cli/cmd/connect/helmrepo.go

@@ -77,7 +77,7 @@ Password:`)
 	reg, err := client.CreateHelmRepo(
 		context.Background(),
 		projectID,
-		&types.CreateHelmRepoRequest{
+		&types.CreateUpdateHelmRepoRequest{
 			URL:                repoURL,
 			Name:               repoName,
 			BasicIntegrationID: basicIntegrationID,

+ 3 - 1
cli/cmd/errors.go

@@ -10,6 +10,7 @@ import (
 	api "github.com/porter-dev/porter/api/client"
 	"github.com/porter-dev/porter/api/types"
 	"github.com/porter-dev/porter/cli/cmd/config"
+	cliErrors "github.com/porter-dev/porter/cli/cmd/errors"
 )
 
 var ErrNotLoggedIn error = errors.New("You are not logged in.")
@@ -52,7 +53,8 @@ func checkLoginAndRun(args []string, runner func(user *types.GetAuthenticatedUse
 			return nil
 		}
 
-		red.Fprintf(os.Stderr, "Error: %v\n", err.Error())
+		cliErrors.GetErrorHandler().HandleError(err)
+
 		return err
 	}
 

+ 52 - 0
cli/cmd/errors/error_handler.go

@@ -0,0 +1,52 @@
+package errors
+
+import (
+	"fmt"
+	"os"
+
+	"github.com/fatih/color"
+	"github.com/getsentry/sentry-go"
+	"github.com/porter-dev/porter/cli/cmd/config"
+)
+
+var SentryDSN string = ""
+
+type errorHandler interface {
+	HandleError(error)
+}
+
+type standardErrorHandler struct{}
+
+func (h *standardErrorHandler) HandleError(err error) {
+	color.New(color.FgRed).Fprintf(os.Stderr, "error: %s\n", err.Error())
+}
+
+type sentryErrorHandler struct{}
+
+func (h *sentryErrorHandler) HandleError(err error) {
+	if SentryDSN != "" {
+		localHub := sentry.CurrentHub().Clone()
+
+		localHub.ConfigureScope(func(scope *sentry.Scope) {
+			scope.SetTags(map[string]string{
+				"host":    config.GetCLIConfig().Host,
+				"project": fmt.Sprintf("%d", config.GetCLIConfig().Project),
+				"cluster": fmt.Sprintf("%d", config.GetCLIConfig().Cluster),
+			})
+		})
+
+		if eventID := localHub.CaptureException(err); eventID == nil {
+			color.New(color.FgRed).Fprintf(os.Stderr, "error in sending exception to sentry\n")
+		}
+	}
+
+	color.New(color.FgRed).Fprintf(os.Stderr, "error: %s\n", err.Error())
+}
+
+func GetErrorHandler() errorHandler {
+	if SentryDSN != "" {
+		return &sentryErrorHandler{}
+	}
+
+	return &standardErrorHandler{}
+}

+ 27 - 0
cli/main.go

@@ -1,11 +1,38 @@
+//go:build cli
 // +build cli
 
 package main
 
 import (
+	"os"
+	"time"
+
+	"github.com/fatih/color"
+	"github.com/getsentry/sentry-go"
 	"github.com/porter-dev/porter/cli/cmd"
+	"github.com/porter-dev/porter/cli/cmd/config"
+	"github.com/porter-dev/porter/cli/cmd/errors"
 )
 
 func main() {
+	if errors.SentryDSN != "" {
+		err := sentry.Init(sentry.ClientOptions{
+			Dsn:         errors.SentryDSN,
+			Environment: "cli",
+			Debug:       config.Version == "dev",
+			Release:     config.Version,
+			IgnoreErrors: []string{
+				"Forbidden",
+			},
+		})
+
+		if err != nil {
+			color.New(color.FgRed).Fprintf(os.Stderr, "error initialising sentry: %s\n", err)
+			os.Exit(1)
+		}
+
+		defer sentry.Flush(2 * time.Second)
+	}
+
 	cmd.Execute()
 }

+ 1 - 1
dashboard/src/components/porter-form/FormDebugger.tsx

@@ -61,7 +61,7 @@ export default class FormDebugger extends Component<PropsType, StateType> {
     try {
       formData = yaml.load(this.state.rawYaml);
     } catch (err: any) {
-      console.log("YAML parsing error.");
+      console.log("YAML parsing error.", err);
     }
     return (
       <StyledFormDebugger>

+ 3 - 1
dashboard/src/components/repo-selector/ActionDetails.tsx

@@ -137,10 +137,12 @@ const ActionDetails: React.FC<PropsType> = (props) => {
         />
       )}
       <InputRow
-        disabled={true}
+        // Currently there is a bug which is failing to detect the correct application folder root path. As a hotfix, we are enabling the user to manually set the application folder path.
+        disabled={false}
         label={dockerfilePath ? "Docker build context" : "Application folder"}
         type="text"
         width="100%"
+        setValue={(value) => typeof value === "string" && setFolderPath(value)}
         value={folderPath}
       />
       {renderRegistrySection()}