From 88ce84a0d5763dfd1d3dbd2df048a1a0d5915d40 Mon Sep 17 00:00:00 2001 From: ianedwards Date: Thu, 28 Sep 2023 18:04:39 -0400 Subject: [PATCH] POR-1440 use previews config as overrides in validate apply flow (#3670) --- api/client/porter_app.go | 28 +++++++++++++------- api/server/handlers/porter_app/parse_yaml.go | 1 + api/server/handlers/porter_app/validate.go | 22 +++++++++++++++ cli/cmd/v2/apply.go | 27 ++++++++++++++++++- go.mod | 2 +- go.sum | 4 +-- 6 files changed, 70 insertions(+), 14 deletions(-) diff --git a/api/client/porter_app.go b/api/client/porter_app.go index df612ddbf0..4a66966af2 100644 --- a/api/client/porter_app.go +++ b/api/client/porter_app.go @@ -176,29 +176,37 @@ func (c *Client) ParseYAML( return resp, err } +// ValidatePorterAppInput is the input struct to ValidatePorterApp +type ValidatePorterAppInput struct { + ProjectID uint + ClusterID uint + AppName string + Base64AppProto string + Base64AppOverrides string + DeploymentTarget string + CommitSHA string +} + // ValidatePorterApp takes in a base64 encoded app definition that is potentially partial and returns a complete definition // using any previous app revisions and defaults func (c *Client) ValidatePorterApp( ctx context.Context, - projectID, clusterID uint, - appName string, - base64AppProto string, - deploymentTarget string, - commitSHA string, + inp ValidatePorterAppInput, ) (*porter_app.ValidatePorterAppResponse, error) { resp := &porter_app.ValidatePorterAppResponse{} req := &porter_app.ValidatePorterAppRequest{ - AppName: appName, - Base64AppProto: base64AppProto, - DeploymentTargetId: deploymentTarget, - CommitSHA: commitSHA, + AppName: inp.AppName, + Base64AppProto: inp.Base64AppProto, + Base64AppOverrides: inp.Base64AppOverrides, + DeploymentTargetId: inp.DeploymentTarget, + CommitSHA: inp.CommitSHA, } err := c.postRequest( fmt.Sprintf( "/projects/%d/clusters/%d/apps/validate", - projectID, clusterID, + inp.ProjectID, inp.ClusterID, ), req, resp, diff --git a/api/server/handlers/porter_app/parse_yaml.go b/api/server/handlers/porter_app/parse_yaml.go index 136cc856e6..6e87056ac1 100644 --- a/api/server/handlers/porter_app/parse_yaml.go +++ b/api/server/handlers/porter_app/parse_yaml.go @@ -128,6 +128,7 @@ func (c *ParsePorterYAMLToProtoHandler) ServeHTTP(w http.ResponseWriter, r *http B64AppProto: encodedPreviewApp, EnvVariables: appDefinition.PreviewApp.EnvVariables, } + telemetry.WithAttributes(span, telemetry.AttributeKV{Key: "includes-preview-app", Value: true}) } c.WriteResult(w, r, response) diff --git a/api/server/handlers/porter_app/validate.go b/api/server/handlers/porter_app/validate.go index efa09d14e7..bcfac2b1dd 100644 --- a/api/server/handlers/porter_app/validate.go +++ b/api/server/handlers/porter_app/validate.go @@ -47,6 +47,7 @@ type Deletions struct { type ValidatePorterAppRequest struct { AppName string `json:"app_name"` Base64AppProto string `json:"b64_app_proto"` + Base64AppOverrides string `json:"b64_app_overrides"` DeploymentTargetId string `json:"deployment_target_id"` CommitSHA string `json:"commit_sha"` Deletions Deletions `json:"deletions"` @@ -121,11 +122,32 @@ func (c *ValidatePorterAppHandler) ServeHTTP(w http.ResponseWriter, r *http.Requ telemetry.AttributeKV{Key: "commit-sha", Value: request.CommitSHA}, ) + var overrides *porterv1.PorterApp + if request.Base64AppOverrides != "" { + decoded, err := base64.StdEncoding.DecodeString(request.Base64AppOverrides) + if err != nil { + err := telemetry.Error(ctx, span, err, "error decoding base yaml") + c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusBadRequest)) + return + } + + overrides = &porterv1.PorterApp{} + err = helpers.UnmarshalContractObject(decoded, overrides) + if err != nil { + err := telemetry.Error(ctx, span, err, "error unmarshalling app proto") + c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusBadRequest)) + return + } + + telemetry.WithAttributes(span, telemetry.AttributeKV{Key: "validated-with-overrides", Value: true}) + } + validateReq := connect.NewRequest(&porterv1.ValidatePorterAppRequest{ ProjectId: int64(project.ID), DeploymentTargetId: request.DeploymentTargetId, CommitSha: request.CommitSHA, App: appProto, + AppOverrides: overrides, Deletions: &porterv1.Deletions{ ServiceNames: request.Deletions.ServiceNames, EnvVariableNames: request.Deletions.EnvVariableNames, diff --git a/cli/cmd/v2/apply.go b/cli/cmd/v2/apply.go index 3dc70ad609..41e3b25d16 100644 --- a/cli/cmd/v2/apply.go +++ b/cli/cmd/v2/apply.go @@ -66,6 +66,9 @@ func Apply(ctx context.Context, inp ApplyInput) error { } } + // overrides incorporated into the app contract baed on the deployment target + var b64AppOverrides string + appName := inp.AppName if porterYamlExists { porterYaml, err := os.ReadFile(filepath.Clean(inp.PorterYamlPath)) @@ -116,6 +119,20 @@ func Apply(ctx context.Context, inp ApplyInput) error { return fmt.Errorf("error updating app env group in proto: %w", err) } + if inp.PreviewApply && parseResp.PreviewApp != nil { + b64AppOverrides = parseResp.PreviewApp.B64AppProto + + envGroupResp, err := client.CreateOrUpdateAppEnvironment(ctx, cliConf.Project, cliConf.Cluster, appName, deploymentTargetID, parseResp.PreviewApp.EnvVariables, parseResp.PreviewApp.EnvSecrets, parseResp.PreviewApp.B64AppProto) + if err != nil { + return fmt.Errorf("error calling create or update app environment group endpoint: %w", err) + } + + b64AppOverrides, err = updateEnvGroupsInProto(ctx, b64AppOverrides, envGroupResp.EnvGroups) + if err != nil { + return fmt.Errorf("error updating app env group in proto: %w", err) + } + } + color.New(color.FgGreen).Printf("Successfully parsed Porter YAML: applying app \"%s\"\n", appName) // nolint:errcheck,gosec } @@ -125,7 +142,15 @@ func Apply(ctx context.Context, inp ApplyInput) error { commitSHA := commitSHAFromEnv() - validateResp, err := client.ValidatePorterApp(ctx, cliConf.Project, cliConf.Cluster, appName, b64AppProto, deploymentTargetID, commitSHA) + validateResp, err := client.ValidatePorterApp(ctx, api.ValidatePorterAppInput{ + ProjectID: cliConf.Project, + ClusterID: cliConf.Cluster, + AppName: appName, + Base64AppProto: b64AppProto, + Base64AppOverrides: b64AppOverrides, + DeploymentTarget: deploymentTargetID, + CommitSHA: commitSHA, + }) if err != nil { return fmt.Errorf("error calling validate endpoint: %w", err) } diff --git a/go.mod b/go.mod index ffec764854..8f9c51192c 100644 --- a/go.mod +++ b/go.mod @@ -82,7 +82,7 @@ require ( github.com/matryer/is v1.4.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.2.1 + github.com/porter-dev/api-contracts v0.2.4 github.com/riandyrn/otelchi v0.5.1 github.com/santhosh-tekuri/jsonschema/v5 v5.0.1 github.com/stefanmcshane/helm v0.0.0-20221213002717-88a4a2c6e77d diff --git a/go.sum b/go.sum index 43166618a7..265fea1399 100644 --- a/go.sum +++ b/go.sum @@ -1516,8 +1516,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.2.1 h1:Xb1ngCQuLJIa38OY/K+fE6uvCTEiJCSzcSnh7EFLHZ0= -github.com/porter-dev/api-contracts v0.2.1/go.mod h1:fX6JmP5QuzxDLvqP3evFOTXjI4dHxsG0+VKNTjImZU8= +github.com/porter-dev/api-contracts v0.2.4 h1:LmSMP0k2ehvQASS+DnavN8LwRRI5mTBIfhBaA8LoyJs= +github.com/porter-dev/api-contracts v0.2.4/go.mod h1:fX6JmP5QuzxDLvqP3evFOTXjI4dHxsG0+VKNTjImZU8= github.com/porter-dev/switchboard v0.0.3 h1:dBuYkiVLa5Ce7059d6qTe9a1C2XEORFEanhbtV92R+M= github.com/porter-dev/switchboard v0.0.3/go.mod h1:xSPzqSFMQ6OSbp42fhCi4AbGbQbsm6nRvOkrblFeXU4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=