|
|
@@ -50,26 +50,31 @@ func (c *CreatePorterAppHandler) ServeHTTP(w http.ResponseWriter, r *http.Reques
|
|
|
|
|
|
request := &types.CreatePorterAppRequest{}
|
|
|
if ok := c.DecodeAndValidate(w, r, request); !ok {
|
|
|
- c.HandleAPIError(w, r, apierrors.NewErrInternal(fmt.Errorf("error decoding request")))
|
|
|
+ err := telemetry.Error(ctx, span, nil, "error decoding request")
|
|
|
+ c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusBadRequest))
|
|
|
return
|
|
|
}
|
|
|
|
|
|
stackName, reqErr := requestutils.GetURLParamString(r, types.URLParamStackName)
|
|
|
if reqErr != nil {
|
|
|
- c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(reqErr, http.StatusBadRequest))
|
|
|
+ err := telemetry.Error(ctx, span, reqErr, "error getting stack name from url")
|
|
|
+ c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusBadRequest))
|
|
|
return
|
|
|
}
|
|
|
namespace := fmt.Sprintf("porter-stack-%s", stackName)
|
|
|
+ telemetry.WithAttributes(span, telemetry.AttributeKV{Key: "application-name", Value: stackName})
|
|
|
|
|
|
helmAgent, err := c.GetHelmAgent(ctx, r, cluster, namespace)
|
|
|
if err != nil {
|
|
|
- c.HandleAPIError(w, r, apierrors.NewErrInternal(fmt.Errorf("error getting helm agent: %w", err)))
|
|
|
+ err = telemetry.Error(ctx, span, err, "error getting helm agent")
|
|
|
+ c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusInternalServerError))
|
|
|
return
|
|
|
}
|
|
|
|
|
|
k8sAgent, err := c.GetAgent(r, cluster, namespace)
|
|
|
if err != nil {
|
|
|
- c.HandleAPIError(w, r, apierrors.NewErrInternal(fmt.Errorf("error getting k8s agent: %w", err)))
|
|
|
+ err = telemetry.Error(ctx, span, err, "error getting k8s agent")
|
|
|
+ c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusInternalServerError))
|
|
|
return
|
|
|
}
|
|
|
|
|
|
@@ -79,13 +84,15 @@ func (c *CreatePorterAppHandler) ServeHTTP(w http.ResponseWriter, r *http.Reques
|
|
|
porterYamlBase64 := request.PorterYAMLBase64
|
|
|
porterYaml, err := base64.StdEncoding.DecodeString(porterYamlBase64)
|
|
|
if err != nil {
|
|
|
- c.HandleAPIError(w, r, apierrors.NewErrInternal(fmt.Errorf("error decoding porter.yaml: %w", err)))
|
|
|
+ err = telemetry.Error(ctx, span, err, "error decoding porter yaml")
|
|
|
+ c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusBadRequest))
|
|
|
return
|
|
|
}
|
|
|
imageInfo := request.ImageInfo
|
|
|
registries, err := c.Repo().Registry().ListRegistriesByProjectID(cluster.ProjectID)
|
|
|
if err != nil {
|
|
|
- c.HandleAPIError(w, r, apierrors.NewErrInternal(fmt.Errorf("error listing registries: %w", err)))
|
|
|
+ err = telemetry.Error(ctx, span, err, "error listing registries")
|
|
|
+ c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusInternalServerError))
|
|
|
return
|
|
|
}
|
|
|
|
|
|
@@ -105,6 +112,7 @@ func (c *CreatePorterAppHandler) ServeHTTP(w http.ResponseWriter, r *http.Reques
|
|
|
releaseValues = helmRelease.Config
|
|
|
releaseDependencies = helmRelease.Chart.Metadata.Dependencies
|
|
|
}
|
|
|
+ telemetry.WithAttributes(span, telemetry.AttributeKV{Key: "image-repo", Value: imageInfo.Repository}, telemetry.AttributeKV{Key: "image-tag", Value: imageInfo.Tag})
|
|
|
|
|
|
if request.Builder == "" {
|
|
|
// attempt to get builder from db
|
|
|
@@ -115,6 +123,7 @@ func (c *CreatePorterAppHandler) ServeHTTP(w http.ResponseWriter, r *http.Reques
|
|
|
}
|
|
|
injectLauncher := strings.Contains(request.Builder, "heroku") ||
|
|
|
strings.Contains(request.Builder, "paketo")
|
|
|
+ telemetry.WithAttributes(span, telemetry.AttributeKV{Key: "builder", Value: request.Builder})
|
|
|
|
|
|
chart, values, releaseJobValues, err := parse(
|
|
|
porterYaml,
|
|
|
@@ -133,20 +142,25 @@ func (c *CreatePorterAppHandler) ServeHTTP(w http.ResponseWriter, r *http.Reques
|
|
|
injectLauncher,
|
|
|
)
|
|
|
if err != nil {
|
|
|
- c.HandleAPIError(w, r, apierrors.NewErrInternal(fmt.Errorf("error parsing porter.yaml into chart and values: %w", err)))
|
|
|
+ err = telemetry.Error(ctx, span, err, "error parsing porter yaml into chart and values")
|
|
|
+ c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusInternalServerError))
|
|
|
return
|
|
|
}
|
|
|
|
|
|
if shouldCreate {
|
|
|
+ telemetry.WithAttributes(span, telemetry.AttributeKV{Key: "installing-application", Value: true})
|
|
|
+
|
|
|
// create the namespace if it does not exist already
|
|
|
_, err = k8sAgent.CreateNamespace(namespace, nil)
|
|
|
if err != nil {
|
|
|
- c.HandleAPIError(w, r, apierrors.NewErrInternal(fmt.Errorf("error creating namespace: %w", err)))
|
|
|
+ err = telemetry.Error(ctx, span, err, "error creating namespace")
|
|
|
+ c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusInternalServerError))
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// create the release job chart if it does not exist (only done by front-end currently, where we set overrideRelease=true)
|
|
|
if request.OverrideRelease && releaseJobValues != nil {
|
|
|
+ telemetry.WithAttributes(span, telemetry.AttributeKV{Key: "installing-pre-deploy-job", Value: true})
|
|
|
conf, err := createReleaseJobChart(
|
|
|
ctx,
|
|
|
stackName,
|
|
|
@@ -157,15 +171,19 @@ func (c *CreatePorterAppHandler) ServeHTTP(w http.ResponseWriter, r *http.Reques
|
|
|
c.Repo(),
|
|
|
)
|
|
|
if err != nil {
|
|
|
- c.HandleAPIError(w, r, apierrors.NewErrInternal(fmt.Errorf("error making config for release job chart: %w", err)))
|
|
|
+ err = telemetry.Error(ctx, span, err, "error making config for pre-deploy job chart")
|
|
|
+ c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusInternalServerError))
|
|
|
return
|
|
|
}
|
|
|
_, err = helmAgent.InstallChart(ctx, conf, c.Config().DOConf, c.Config().ServerConf.DisablePullSecretsInjection)
|
|
|
if err != nil {
|
|
|
- c.HandleAPIError(w, r, apierrors.NewErrInternal(fmt.Errorf("error creating release job chart: %w", err)))
|
|
|
- _, err = helmAgent.UninstallChart(ctx, fmt.Sprintf("%s-r", stackName))
|
|
|
- if err != nil {
|
|
|
- c.HandleAPIError(w, r, apierrors.NewErrInternal(fmt.Errorf("error uninstalling release job chart: %w", err)))
|
|
|
+ err = telemetry.Error(ctx, span, err, "error installing pre-deploy job chart")
|
|
|
+ telemetry.WithAttributes(span, telemetry.AttributeKV{Key: "install-pre-deploy-job-error", Value: err})
|
|
|
+ c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusInternalServerError))
|
|
|
+ _, uninstallChartErr := helmAgent.UninstallChart(ctx, fmt.Sprintf("%s-r", stackName))
|
|
|
+ if uninstallChartErr != nil {
|
|
|
+ uninstallChartErr = telemetry.Error(ctx, span, err, "error uninstalling pre-deploy job chart after failed install")
|
|
|
+ c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(uninstallChartErr, http.StatusInternalServerError))
|
|
|
}
|
|
|
return
|
|
|
}
|
|
|
@@ -184,11 +202,13 @@ func (c *CreatePorterAppHandler) ServeHTTP(w http.ResponseWriter, r *http.Reques
|
|
|
// create the app chart
|
|
|
_, err = helmAgent.InstallChart(ctx, conf, c.Config().DOConf, c.Config().ServerConf.DisablePullSecretsInjection)
|
|
|
if err != nil {
|
|
|
- c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(fmt.Errorf("error deploying app: %s", err.Error()), http.StatusBadRequest))
|
|
|
+ err = telemetry.Error(ctx, span, err, "error installing app chart")
|
|
|
+ c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusBadRequest))
|
|
|
|
|
|
_, err = helmAgent.UninstallChart(ctx, stackName)
|
|
|
if err != nil {
|
|
|
- c.HandleAPIError(w, r, apierrors.NewErrInternal(fmt.Errorf("error uninstalling chart: %w", err)))
|
|
|
+ err = telemetry.Error(ctx, span, err, "error uninstalling app chart after failed install")
|
|
|
+ c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusInternalServerError))
|
|
|
}
|
|
|
|
|
|
return
|
|
|
@@ -196,11 +216,12 @@ func (c *CreatePorterAppHandler) ServeHTTP(w http.ResponseWriter, r *http.Reques
|
|
|
|
|
|
existing, err := c.Repo().PorterApp().ReadPorterAppByName(cluster.ID, stackName)
|
|
|
if err != nil {
|
|
|
- c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
|
|
|
+ err = telemetry.Error(ctx, span, err, "error reading app from DB")
|
|
|
+ c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusInternalServerError))
|
|
|
return
|
|
|
} else if existing.Name != "" {
|
|
|
- c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(
|
|
|
- fmt.Errorf("app with name %s already exists in your project", existing.Name), http.StatusForbidden))
|
|
|
+ err = telemetry.Error(ctx, span, err, "app with name already exists in project")
|
|
|
+ c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusForbidden))
|
|
|
return
|
|
|
}
|
|
|
|
|
|
@@ -224,28 +245,34 @@ func (c *CreatePorterAppHandler) ServeHTTP(w http.ResponseWriter, r *http.Reques
|
|
|
// create the db entry
|
|
|
porterApp, err := c.Repo().PorterApp().UpdatePorterApp(app)
|
|
|
if err != nil {
|
|
|
- c.HandleAPIError(w, r, apierrors.NewErrInternal(fmt.Errorf("error writing app to DB: %s", err.Error())))
|
|
|
+ err = telemetry.Error(ctx, span, err, "error writing app to DB")
|
|
|
+ c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusInternalServerError))
|
|
|
return
|
|
|
}
|
|
|
|
|
|
_, err = createPorterAppEvent(ctx, "SUCCESS", porterApp.ID, 1, imageInfo.Tag, c.Repo().PorterAppEvent())
|
|
|
if err != nil {
|
|
|
- c.HandleAPIError(w, r, apierrors.NewErrInternal(fmt.Errorf("error creating porter app event: %s", err.Error())))
|
|
|
+ err = telemetry.Error(ctx, span, err, "error creating porter app event")
|
|
|
+ c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusInternalServerError))
|
|
|
return
|
|
|
}
|
|
|
|
|
|
c.WriteResult(w, r, porterApp.ToPorterAppType())
|
|
|
} else {
|
|
|
+ telemetry.WithAttributes(span, telemetry.AttributeKV{Key: "upgrading-application", Value: true})
|
|
|
+
|
|
|
// create/update the release job chart
|
|
|
if request.OverrideRelease {
|
|
|
if releaseJobValues == nil {
|
|
|
- // handle exception where the user has chosen to delete the release job
|
|
|
releaseJobName := fmt.Sprintf("%s-r", stackName)
|
|
|
_, err := helmAgent.GetRelease(ctx, releaseJobName, 0, false)
|
|
|
if err == nil {
|
|
|
+ // handle exception where the user has chosen to delete the release job
|
|
|
+ telemetry.WithAttributes(span, telemetry.AttributeKV{Key: "deleting-pre-deploy-job", Value: true})
|
|
|
_, err = helmAgent.UninstallChart(ctx, releaseJobName)
|
|
|
if err != nil {
|
|
|
- c.HandleAPIError(w, r, apierrors.NewErrInternal(fmt.Errorf("error uninstalling release job chart: %w", err)))
|
|
|
+ err = telemetry.Error(ctx, span, err, "error uninstalling pre-deploy job chart")
|
|
|
+ c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusInternalServerError))
|
|
|
return
|
|
|
}
|
|
|
}
|
|
|
@@ -253,6 +280,7 @@ func (c *CreatePorterAppHandler) ServeHTTP(w http.ResponseWriter, r *http.Reques
|
|
|
releaseJobName := fmt.Sprintf("%s-r", stackName)
|
|
|
helmRelease, err := helmAgent.GetRelease(ctx, releaseJobName, 0, false)
|
|
|
if err != nil {
|
|
|
+ telemetry.WithAttributes(span, telemetry.AttributeKV{Key: "creating-pre-deploy-job", Value: true})
|
|
|
conf, err := createReleaseJobChart(
|
|
|
ctx,
|
|
|
stackName,
|
|
|
@@ -263,23 +291,29 @@ func (c *CreatePorterAppHandler) ServeHTTP(w http.ResponseWriter, r *http.Reques
|
|
|
c.Repo(),
|
|
|
)
|
|
|
if err != nil {
|
|
|
- c.HandleAPIError(w, r, apierrors.NewErrInternal(fmt.Errorf("error making config for release job chart: %w", err)))
|
|
|
+ err = telemetry.Error(ctx, span, err, "error making config for pre-deploy job chart")
|
|
|
+ c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusInternalServerError))
|
|
|
return
|
|
|
}
|
|
|
|
|
|
_, err = helmAgent.InstallChart(ctx, conf, c.Config().DOConf, c.Config().ServerConf.DisablePullSecretsInjection)
|
|
|
if err != nil {
|
|
|
- c.HandleAPIError(w, r, apierrors.NewErrInternal(fmt.Errorf("error creating release job chart: %w", err)))
|
|
|
- _, err = helmAgent.UninstallChart(ctx, fmt.Sprintf("%s-r", stackName))
|
|
|
- if err != nil {
|
|
|
- c.HandleAPIError(w, r, apierrors.NewErrInternal(fmt.Errorf("error uninstalling release job chart: %w", err)))
|
|
|
+ err = telemetry.Error(ctx, span, err, "error installing pre-deploy job chart")
|
|
|
+ telemetry.WithAttributes(span, telemetry.AttributeKV{Key: "install-pre-deploy-job-error", Value: err})
|
|
|
+ c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusInternalServerError))
|
|
|
+ _, uninstallChartErr := helmAgent.UninstallChart(ctx, fmt.Sprintf("%s-r", stackName))
|
|
|
+ if uninstallChartErr != nil {
|
|
|
+ uninstallChartErr = telemetry.Error(ctx, span, err, "error uninstalling pre-deploy job chart after failed install")
|
|
|
+ c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(uninstallChartErr, http.StatusInternalServerError))
|
|
|
}
|
|
|
return
|
|
|
}
|
|
|
} else {
|
|
|
+ telemetry.WithAttributes(span, telemetry.AttributeKV{Key: "updating-pre-deploy-job", Value: true})
|
|
|
chart, err := loader.LoadChartPublic(ctx, c.Config().Metadata.DefaultAppHelmRepoURL, "job", "")
|
|
|
if err != nil {
|
|
|
- c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(fmt.Errorf("error loading release job chart: %w", err), http.StatusBadRequest))
|
|
|
+ err = telemetry.Error(ctx, span, err, "error loading latest job chart")
|
|
|
+ c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusInternalServerError))
|
|
|
return
|
|
|
}
|
|
|
|
|
|
@@ -293,7 +327,8 @@ func (c *CreatePorterAppHandler) ServeHTTP(w http.ResponseWriter, r *http.Reques
|
|
|
}
|
|
|
_, err = helmAgent.UpgradeReleaseByValues(ctx, conf, c.Config().DOConf, c.Config().ServerConf.DisablePullSecretsInjection, false)
|
|
|
if err != nil {
|
|
|
- c.HandleAPIError(w, r, apierrors.NewErrInternal(fmt.Errorf("error upgrading release job chart: %w", err)))
|
|
|
+ err = telemetry.Error(ctx, span, err, "error upgrading pre-deploy job chart")
|
|
|
+ c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusInternalServerError))
|
|
|
return
|
|
|
}
|
|
|
}
|
|
|
@@ -314,14 +349,16 @@ func (c *CreatePorterAppHandler) ServeHTTP(w http.ResponseWriter, r *http.Reques
|
|
|
// update the chart
|
|
|
_, err = helmAgent.UpgradeInstallChart(ctx, conf, c.Config().DOConf, c.Config().ServerConf.DisablePullSecretsInjection)
|
|
|
if err != nil {
|
|
|
- c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(fmt.Errorf("error deploying app: %s", err.Error()), http.StatusBadRequest))
|
|
|
+ err = telemetry.Error(ctx, span, err, "error upgrading application")
|
|
|
+ c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusBadRequest))
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// update the DB entry
|
|
|
app, err := c.Repo().PorterApp().ReadPorterAppByName(cluster.ID, stackName)
|
|
|
if err != nil {
|
|
|
- c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
|
|
|
+ err = telemetry.Error(ctx, span, err, "error reading app from DB")
|
|
|
+ c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusInternalServerError))
|
|
|
return
|
|
|
}
|
|
|
|
|
|
@@ -362,15 +399,29 @@ func (c *CreatePorterAppHandler) ServeHTTP(w http.ResponseWriter, r *http.Reques
|
|
|
app.PullRequestURL = request.PullRequestURL
|
|
|
}
|
|
|
|
|
|
+ telemetry.WithAttributes(
|
|
|
+ span,
|
|
|
+ telemetry.AttributeKV{Key: "updated-repo-name", Value: app.RepoName},
|
|
|
+ telemetry.AttributeKV{Key: "updated-git-branch", Value: app.GitBranch},
|
|
|
+ telemetry.AttributeKV{Key: "updated-build-context", Value: app.BuildContext},
|
|
|
+ telemetry.AttributeKV{Key: "updated-builder", Value: app.Builder},
|
|
|
+ telemetry.AttributeKV{Key: "updated-buildpacks", Value: app.Buildpacks},
|
|
|
+ telemetry.AttributeKV{Key: "updated-dockerfile", Value: app.Dockerfile},
|
|
|
+ telemetry.AttributeKV{Key: "updated-image-repo-uri", Value: app.ImageRepoURI},
|
|
|
+ telemetry.AttributeKV{Key: "updated-pull-request-url", Value: app.PullRequestURL},
|
|
|
+ )
|
|
|
+
|
|
|
updatedPorterApp, err := c.Repo().PorterApp().UpdatePorterApp(app)
|
|
|
if err != nil {
|
|
|
- c.HandleAPIError(w, r, apierrors.NewErrInternal(fmt.Errorf("error writing updated app to DB: %s", err.Error())))
|
|
|
+ err = telemetry.Error(ctx, span, err, "error writing updated app to DB")
|
|
|
+ c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusInternalServerError))
|
|
|
return
|
|
|
}
|
|
|
|
|
|
_, err = createPorterAppEvent(ctx, "SUCCESS", updatedPorterApp.ID, helmRelease.Version+1, imageInfo.Tag, c.Repo().PorterAppEvent())
|
|
|
if err != nil {
|
|
|
- c.HandleAPIError(w, r, apierrors.NewErrInternal(fmt.Errorf("error creating porter app event: %s", err.Error())))
|
|
|
+ err = telemetry.Error(ctx, span, err, "error creating porter app event")
|
|
|
+ c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusInternalServerError))
|
|
|
return
|
|
|
}
|
|
|
|