diff --git a/api/server/handlers/release/update_image_batch.go b/api/server/handlers/release/update_image_batch.go index 06c5b848c4..c51c8fe0bc 100644 --- a/api/server/handlers/release/update_image_batch.go +++ b/api/server/handlers/release/update_image_batch.go @@ -1,12 +1,13 @@ package release import ( - "context" "fmt" "net/http" "strings" "sync" + "github.com/porter-dev/porter/internal/telemetry" + "github.com/porter-dev/porter/api/server/authz" "github.com/porter-dev/porter/api/server/handlers" "github.com/porter-dev/porter/api/server/shared" @@ -34,22 +35,33 @@ func NewUpdateImageBatchHandler( } func (c *UpdateImageBatchHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + ctx, span := telemetry.NewSpan(r.Context(), "serve-update-image-batch") + defer span.End() + + r = r.Clone(ctx) + cluster, _ := r.Context().Value(types.ClusterScope).(*models.Cluster) - helmAgent, err := c.GetHelmAgent(r.Context(), r, cluster, "") + // helmAgent has namespace set from the request + helmAgent, err := c.GetHelmAgent(ctx, r, cluster, "") if err != nil { + err = telemetry.Error(ctx, span, err, "error getting helm agent") c.HandleAPIError(w, r, apierrors.NewErrInternal(err)) return } + telemetry.WithAttributes(span, telemetry.AttributeKV{Key: "namespace", Value: helmAgent.Namespace()}) + request := &types.UpdateImageBatchRequest{} if ok := c.DecodeAndValidate(w, r, request); !ok { + _ = telemetry.Error(ctx, span, nil, "error decoding and validating request") return } releases, err := c.Repo().Release().ListReleasesByImageRepoURI(cluster.ID, request.ImageRepoURI) if err != nil { + _ = telemetry.Error(ctx, span, err, "error listing releases by image repo uri") c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient( fmt.Errorf("releases not found with given image repo uri"), http.StatusBadRequest, @@ -58,8 +70,16 @@ func (c *UpdateImageBatchHandler) ServeHTTP(w http.ResponseWriter, r *http.Reque return } + var namespaceScopedReleases []*models.Release + for _, release := range releases { + if release.Namespace == helmAgent.Namespace() { + namespaceScopedReleases = append(namespaceScopedReleases, release) + } + } + registries, err := c.Repo().Registry().ListRegistriesByProjectID(cluster.ProjectID) if err != nil { + err = telemetry.Error(ctx, span, err, "error listing registries by project id") c.HandleAPIError(w, r, apierrors.NewErrInternal(err)) return } @@ -67,17 +87,20 @@ func (c *UpdateImageBatchHandler) ServeHTTP(w http.ResponseWriter, r *http.Reque // asynchronously update releases with that image repo uri var wg sync.WaitGroup mu := &sync.Mutex{} - errors := make([]string, 0) + errs := make([]string, 0) - for i := range releases { + for i := range namespaceScopedReleases { index := i wg.Add(1) go func() { + ctx, span := telemetry.NewSpan(ctx, "update-image-batch") + defer span.End() defer wg.Done() // read release via agent - rel, err := helmAgent.GetRelease(context.Background(), releases[index].Name, 0, false) + rel, err := helmAgent.GetRelease(ctx, namespaceScopedReleases[index].Name, 0, false) if err != nil { + err = telemetry.Error(ctx, span, err, "error getting release") // if this is a release not found error, just return - the release has likely been deleted from the underlying // cluster but has not been deleted from the Porter database yet if strings.Contains(err.Error(), "release: not found") { @@ -85,29 +108,29 @@ func (c *UpdateImageBatchHandler) ServeHTTP(w http.ResponseWriter, r *http.Reque } mu.Lock() - errors = append(errors, fmt.Sprintf("Error for %s, index %d: %s", releases[index].Name, index, err.Error())) + errs = append(errs, fmt.Sprintf("Error for %s, index %d: %s", namespaceScopedReleases[index].Name, index, err.Error())) mu.Unlock() return } if rel.Chart.Name() == "job" { image := map[string]interface{}{} - image["repository"] = releases[index].ImageRepoURI + image["repository"] = namespaceScopedReleases[index].ImageRepoURI image["tag"] = request.Tag rel.Config["image"] = image rel.Config["paused"] = true conf := &helm.UpgradeReleaseConfig{ - Name: releases[index].Name, + Name: namespaceScopedReleases[index].Name, Cluster: cluster, Repo: c.Repo(), Registries: registries, Values: rel.Config, } - _, err = helmAgent.UpgradeReleaseByValues(context.Background(), conf, c.Config().DOConf, c.Config().ServerConf.DisablePullSecretsInjection, false) - + _, err = helmAgent.UpgradeReleaseByValues(ctx, conf, c.Config().DOConf, c.Config().ServerConf.DisablePullSecretsInjection, false) if err != nil { + err = telemetry.Error(ctx, span, err, "error upgrading release by values") // if this is a release not found error, just return - the release has likely been deleted from the underlying // cluster in the time since we've read the release, but has not been deleted from the Porter database yet if strings.Contains(err.Error(), "release: not found") { @@ -115,7 +138,7 @@ func (c *UpdateImageBatchHandler) ServeHTTP(w http.ResponseWriter, r *http.Reque } mu.Lock() - errors = append(errors, fmt.Sprintf("Error for %s, index %d: %s", releases[index].Name, index, err.Error())) + errs = append(errs, fmt.Sprintf("Error for %s, index %d: %s", namespaceScopedReleases[index].Name, index, err.Error())) mu.Unlock() } } @@ -124,12 +147,10 @@ func (c *UpdateImageBatchHandler) ServeHTTP(w http.ResponseWriter, r *http.Reque wg.Wait() - if len(errors) > 0 { - c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient( - fmt.Errorf("errors while deploying: %s", strings.Join(errors, ",")), - http.StatusBadRequest, - )) - + if len(errs) > 0 { + err = fmt.Errorf("errors while deploying: %s", strings.Join(errs, ",")) + err = telemetry.Error(ctx, span, err, "errors while deploying") + c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusInternalServerError)) return } } diff --git a/api/server/shared/config/env/envconfs.go b/api/server/shared/config/env/envconfs.go index 89b812a363..ddaf56f359 100644 --- a/api/server/shared/config/env/envconfs.go +++ b/api/server/shared/config/env/envconfs.go @@ -29,8 +29,8 @@ type ServerConf struct { IsTesting bool `env:"IS_TESTING,default=false"` AppRootDomain string `env:"APP_ROOT_DOMAIN,default=porter.run"` - DefaultApplicationHelmRepoURL string `env:"HELM_APP_REPO_URL,default=https://charts.dev.getporter.dev"` - DefaultAddonHelmRepoURL string `env:"HELM_ADD_ON_REPO_URL,default=https://chart-addons.dev.getporter.dev"` + DefaultApplicationHelmRepoURL string `env:"HELM_APP_REPO_URL,default=https://charts.getporter.dev"` + DefaultAddonHelmRepoURL string `env:"HELM_ADD_ON_REPO_URL,default=https://chart-addons.getporter.dev"` BasicLoginEnabled bool `env:"BASIC_LOGIN_ENABLED,default=true"`