From 3c97747edda060b535f79671210af8fe143c31db Mon Sep 17 00:00:00 2001 From: d-g-town <66391417+d-g-town@users.noreply.github.com> Date: Wed, 13 Sep 2023 11:42:06 -0400 Subject: [PATCH] allow missing porter yaml in CLI (#3558) Co-authored-by: David Townley --- api/client/porter_app.go | 2 + api/server/handlers/porter_app/validate.go | 44 ++++++++++-------- cli/cmd/v2/apply.go | 52 +++++++++++++--------- 3 files changed, 58 insertions(+), 40 deletions(-) diff --git a/api/client/porter_app.go b/api/client/porter_app.go index db2ee77ce2..68913a822c 100644 --- a/api/client/porter_app.go +++ b/api/client/porter_app.go @@ -180,6 +180,7 @@ func (c *Client) ParseYAML( func (c *Client) ValidatePorterApp( ctx context.Context, projectID, clusterID uint, + appName string, base64AppProto string, deploymentTarget string, commitSHA string, @@ -187,6 +188,7 @@ func (c *Client) ValidatePorterApp( resp := &porter_app.ValidatePorterAppResponse{} req := &porter_app.ValidatePorterAppRequest{ + AppName: appName, Base64AppProto: base64AppProto, DeploymentTargetId: deploymentTarget, CommitSHA: commitSHA, diff --git a/api/server/handlers/porter_app/validate.go b/api/server/handlers/porter_app/validate.go index c40241c84f..e49f77598b 100644 --- a/api/server/handlers/porter_app/validate.go +++ b/api/server/handlers/porter_app/validate.go @@ -44,6 +44,7 @@ type Deletions struct { // ValidatePorterAppRequest is the request object for the /apps/validate endpoint type ValidatePorterAppRequest struct { + AppName string `json:"app_name"` Base64AppProto string `json:"b64_app_proto"` DeploymentTargetId string `json:"deployment_target_id"` CommitSHA string `json:"commit_sha"` @@ -81,29 +82,34 @@ func (c *ValidatePorterAppHandler) ServeHTTP(w http.ResponseWriter, r *http.Requ return } - if request.Base64AppProto == "" { - err := telemetry.Error(ctx, span, nil, "b64 yaml is empty") - c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusBadRequest)) - return - } - - decoded, err := base64.StdEncoding.DecodeString(request.Base64AppProto) - if err != nil { - err := telemetry.Error(ctx, span, err, "error decoding base yaml") - c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusBadRequest)) - return - } - appProto := &porterv1.PorterApp{} - err = helpers.UnmarshalContractObject(decoded, appProto) - if err != nil { - err := telemetry.Error(ctx, span, err, "error unmarshalling app proto") - c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusBadRequest)) - return + + if request.Base64AppProto == "" { + if request.AppName == "" { + err := telemetry.Error(ctx, span, nil, "app name is empty and no base64 proto provided") + c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusBadRequest)) + return + } + + appProto.Name = request.AppName + } else { + decoded, err := base64.StdEncoding.DecodeString(request.Base64AppProto) + if err != nil { + err := telemetry.Error(ctx, span, err, "error decoding base yaml") + c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusBadRequest)) + return + } + + err = helpers.UnmarshalContractObject(decoded, appProto) + if err != nil { + err := telemetry.Error(ctx, span, err, "error unmarshalling app proto") + c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusBadRequest)) + return + } } if appProto.Name == "" { - err := telemetry.Error(ctx, span, err, "app proto name is empty") + err := telemetry.Error(ctx, span, nil, "app proto name is empty") c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusBadRequest)) return } diff --git a/cli/cmd/v2/apply.go b/cli/cmd/v2/apply.go index 41b860289e..4e26df222a 100644 --- a/cli/cmd/v2/apply.go +++ b/cli/cmd/v2/apply.go @@ -24,33 +24,41 @@ import ( // Apply implements the functionality of the `porter apply` command for validate apply v2 projects func Apply(ctx context.Context, cliConf config.CLIConfig, client api.Client, porterYamlPath string) error { - if len(porterYamlPath) == 0 { - return fmt.Errorf("porter yaml is empty") + var appName string + if os.Getenv("PORTER_APP_NAME") != "" { + appName = os.Getenv("PORTER_APP_NAME") + } else if os.Getenv("PORTER_STACK_NAME") != "" { + appName = os.Getenv("PORTER_STACK_NAME") } - porterYaml, err := os.ReadFile(filepath.Clean(porterYamlPath)) - if err != nil { - return fmt.Errorf("could not read porter yaml file: %w", err) - } + var yamlB64 string + if len(porterYamlPath) != 0 { + porterYaml, err := os.ReadFile(filepath.Clean(porterYamlPath)) + if err != nil { + return fmt.Errorf("could not read porter yaml file: %w", err) + } - b64YAML := base64.StdEncoding.EncodeToString(porterYaml) + b64YAML := base64.StdEncoding.EncodeToString(porterYaml) - // last argument is passed to accommodate users with v1 porter yamls - parseResp, err := client.ParseYAML(ctx, cliConf.Project, cliConf.Cluster, b64YAML, os.Getenv("PORTER_STACK_NAME")) - if err != nil { - return fmt.Errorf("error calling parse yaml endpoint: %w", err) - } + // last argument is passed to accommodate users with v1 porter yamls + parseResp, err := client.ParseYAML(ctx, cliConf.Project, cliConf.Cluster, b64YAML, os.Getenv("PORTER_STACK_NAME")) + if err != nil { + return fmt.Errorf("error calling parse yaml endpoint: %w", err) + } - if parseResp.B64AppProto == "" { - return errors.New("b64 app proto is empty") - } + if parseResp.B64AppProto == "" { + return errors.New("b64 app proto is empty") + } + yamlB64 = parseResp.B64AppProto - appName, err := appNameFromB64AppProto(parseResp.B64AppProto) - if err != nil { - return fmt.Errorf("error getting app name from b64 app proto: %w", err) - } + // override app name if provided + appName, err = appNameFromB64AppProto(parseResp.B64AppProto) + if err != nil { + return fmt.Errorf("error getting app name from b64 app proto: %w", err) + } - color.New(color.FgGreen).Printf("Successfully parsed Porter YAML: applying app \"%s\"\n", appName) // nolint:errcheck,gosec + color.New(color.FgGreen).Printf("Successfully parsed Porter YAML: applying app \"%s\"\n", appName) // nolint:errcheck,gosec + } targetResp, err := client.DefaultDeploymentTarget(ctx, cliConf.Project, cliConf.Cluster) if err != nil { @@ -70,7 +78,7 @@ func Apply(ctx context.Context, cliConf config.CLIConfig, client api.Client, por commitSHA = commit.Sha } - validateResp, err := client.ValidatePorterApp(ctx, cliConf.Project, cliConf.Cluster, parseResp.B64AppProto, targetResp.DeploymentTargetID, commitSHA) + validateResp, err := client.ValidatePorterApp(ctx, cliConf.Project, cliConf.Cluster, appName, yamlB64, targetResp.DeploymentTargetID, commitSHA) if err != nil { return fmt.Errorf("error calling validate endpoint: %w", err) } @@ -154,6 +162,8 @@ func Apply(ctx context.Context, cliConf config.CLIConfig, client api.Client, por } } + color.New(color.FgGreen).Printf("Image tag exists in repository") // nolint:errcheck,gosec + if applyResp.CLIAction == porterv1.EnumCLIAction_ENUM_CLI_ACTION_TRACK_PREDEPLOY { color.New(color.FgGreen).Printf("Waiting for predeploy to complete...\n") // nolint:errcheck,gosec