Skip to content

Commit

Permalink
properly scope job charts to namespace (#4334)
Browse files Browse the repository at this point in the history
  • Loading branch information
d-g-town authored Feb 27, 2024
1 parent 0f5f5a3 commit ab4b91d
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 19 deletions.
55 changes: 38 additions & 17 deletions api/server/handlers/release/update_image_batch.go
Original file line number Diff line number Diff line change
@@ -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"
Expand Down Expand Up @@ -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,
Expand All @@ -58,64 +70,75 @@ 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
}

// 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") {
return
}

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") {
return
}

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()
}
}
Expand All @@ -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
}
}
4 changes: 2 additions & 2 deletions api/server/shared/config/env/envconfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"`

Expand Down

0 comments on commit ab4b91d

Please sign in to comment.