Jelajahi Sumber

configured postrenderer and cred helper with do registry

Alexander Belanger 5 tahun lalu
induk
melakukan
ece33b99f6

+ 40 - 0
cli/cmd/api/registry.go

@@ -243,6 +243,46 @@ func (c *Client) GetGCRAuthorizationToken(
 	return bodyResp, nil
 }
 
+type GetDOCRTokenRequest struct {
+	ServerURL string `json:"server_url"`
+}
+
+// GetDOCRAuthorizationToken gets a DOCR authorization token
+func (c *Client) GetDOCRAuthorizationToken(
+	ctx context.Context,
+	projectID uint,
+	docrRequest *GetDOCRTokenRequest,
+) (*GetTokenResponse, error) {
+	data, err := json.Marshal(docrRequest)
+
+	if err != nil {
+		return nil, err
+	}
+
+	req, err := http.NewRequest(
+		"GET",
+		fmt.Sprintf("%s/projects/%d/registries/docr/token", c.BaseURL, projectID),
+		strings.NewReader(string(data)),
+	)
+
+	if err != nil {
+		return nil, err
+	}
+
+	bodyResp := &GetTokenResponse{}
+	req = req.WithContext(ctx)
+
+	if httpErr, err := c.sendRequest(req, bodyResp, true); httpErr != nil || err != nil {
+		if httpErr != nil {
+			return nil, fmt.Errorf("code %d, errors %v", httpErr.Code, httpErr.Errors)
+		}
+
+		return nil, err
+	}
+
+	return bodyResp, nil
+}
+
 // ListRegistryRepositoryResponse is the list of repositories in a registry
 type ListRegistryRepositoryResponse []registry.Repository
 

+ 45 - 0
cmd/docker-credential-porter/helper/helper.go

@@ -48,6 +48,8 @@ func (p *PorterHelper) Get(serverURL string) (user string, secret string, err er
 
 	if strings.Contains(serverURL, "gcr.io") {
 		return p.getGCR(serverURL)
+	} else if strings.Contains(serverURL, "registry.digitalocean.com") {
+		return p.getDOCR(serverURL)
 	}
 
 	return p.getECR(serverURL)
@@ -96,6 +98,49 @@ func (p *PorterHelper) getGCR(serverURL string) (user string, secret string, err
 	return "oauth2accesstoken", token, nil
 }
 
+func (p *PorterHelper) getDOCR(serverURL string) (user string, secret string, err error) {
+	urlP, err := url.Parse(serverURL)
+
+	if err != nil {
+		return "", "", err
+	}
+
+	credCache := BuildCredentialsCache(urlP.Host)
+	cachedEntry := credCache.Get(serverURL)
+
+	var token string
+
+	if cachedEntry != nil && cachedEntry.IsValid(time.Now()) {
+		token = cachedEntry.AuthorizationToken
+	} else {
+		host := viper.GetString("host")
+		projID := viper.GetUint("project")
+
+		client := api.NewClient(host+"/api", "cookie.json")
+
+		// get a token from the server
+		tokenResp, err := client.GetDOCRAuthorizationToken(context.Background(), projID, &api.GetDOCRTokenRequest{
+			ServerURL: serverURL,
+		})
+
+		if err != nil {
+			return "", "", err
+		}
+
+		token = tokenResp.Token
+
+		// set the token in cache
+		credCache.Set(serverURL, &AuthEntry{
+			AuthorizationToken: token,
+			RequestedAt:        time.Now(),
+			ExpiresAt:          *tokenResp.ExpiresAt,
+			ProxyEndpoint:      serverURL,
+		})
+	}
+
+	return token, token, nil
+}
+
 func (p *PorterHelper) getECR(serverURL string) (user string, secret string, err error) {
 	// parse the server url for region
 	matches := ecrPattern.FindStringSubmatch(serverURL)

+ 1 - 0
go.mod

@@ -13,6 +13,7 @@ require (
 	github.com/containerd/containerd v1.4.1 // indirect
 	github.com/coreos/rkt v1.30.0
 	github.com/creack/pty v1.1.11 // indirect
+	github.com/digitalocean/godo v1.56.0
 	github.com/docker/cli v0.0.0-20200130152716-5d0cf8839492
 	github.com/docker/distribution v2.7.1+incompatible
 	github.com/docker/docker v1.4.2-0.20200203170920-46ec8731fbce

+ 2 - 0
go.sum

@@ -230,6 +230,8 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm
 github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
 github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
 github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
+github.com/digitalocean/godo v1.56.0 h1:wXqWJyywrDO3YO2T4Kh8TwbCPOa+OI2vC8qh0/Ngmjk=
+github.com/digitalocean/godo v1.56.0/go.mod h1:p7dOjjtSBqCTUksqtA5Fd3uaKs9kyTq2xcz76ulEJRU=
 github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
 github.com/docker/cli v0.0.0-20200130152716-5d0cf8839492 h1:FwssHbCDJD025h+BchanCwE1Q8fyMgqDr2mOQAWOLGw=
 github.com/docker/cli v0.0.0-20200130152716-5d0cf8839492/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=

+ 9 - 2
internal/helm/agent.go

@@ -7,6 +7,7 @@ import (
 	"github.com/porter-dev/porter/internal/kubernetes"
 	"github.com/porter-dev/porter/internal/models"
 	"github.com/porter-dev/porter/internal/repository"
+	"golang.org/x/oauth2"
 	"helm.sh/helm/v3/pkg/action"
 	"helm.sh/helm/v3/pkg/chart"
 	"helm.sh/helm/v3/pkg/release"
@@ -65,6 +66,7 @@ type UpgradeReleaseConfig struct {
 func (a *Agent) UpgradeRelease(
 	conf *UpgradeReleaseConfig,
 	values string,
+	doAuth *oauth2.Config,
 ) (*release.Release, error) {
 	valuesYaml, err := chartutil.ReadValues([]byte(values))
 
@@ -74,12 +76,13 @@ func (a *Agent) UpgradeRelease(
 
 	conf.Values = valuesYaml
 
-	return a.UpgradeReleaseByValues(conf)
+	return a.UpgradeReleaseByValues(conf, doAuth)
 }
 
 // UpgradeReleaseByValues upgrades a release by unmarshaled yaml values
 func (a *Agent) UpgradeReleaseByValues(
 	conf *UpgradeReleaseConfig,
+	doAuth *oauth2.Config,
 ) (*release.Release, error) {
 	// grab the latest release
 	rel, err := a.GetRelease(conf.Name, 0)
@@ -99,6 +102,7 @@ func (a *Agent) UpgradeReleaseByValues(
 			a.K8sAgent,
 			rel.Namespace,
 			conf.Registries,
+			doAuth,
 		)
 
 		if err != nil {
@@ -130,6 +134,7 @@ type InstallChartConfig struct {
 func (a *Agent) InstallChartFromValuesBytes(
 	conf *InstallChartConfig,
 	values []byte,
+	doAuth *oauth2.Config,
 ) (*release.Release, error) {
 	valuesYaml, err := chartutil.ReadValues(values)
 
@@ -139,12 +144,13 @@ func (a *Agent) InstallChartFromValuesBytes(
 
 	conf.Values = valuesYaml
 
-	return a.InstallChart(conf)
+	return a.InstallChart(conf, doAuth)
 }
 
 // InstallChart installs a new chart
 func (a *Agent) InstallChart(
 	conf *InstallChartConfig,
+	doAuth *oauth2.Config,
 ) (*release.Release, error) {
 	cmd := action.NewInstall(a.ActionConfig)
 
@@ -169,6 +175,7 @@ func (a *Agent) InstallChart(
 			a.K8sAgent,
 			conf.Namespace,
 			conf.Registries,
+			doAuth,
 		)
 
 		if err != nil {

+ 5 - 5
internal/helm/postrenderer.go

@@ -2,7 +2,6 @@ package helm
 
 import (
 	"bytes"
-	"fmt"
 	"io"
 	"net/url"
 	"regexp"
@@ -13,6 +12,7 @@ import (
 	"github.com/porter-dev/porter/internal/models"
 	"github.com/porter-dev/porter/internal/models/integrations"
 	"github.com/porter-dev/porter/internal/repository"
+	"golang.org/x/oauth2"
 	"gopkg.in/yaml.v2"
 	"helm.sh/helm/v3/pkg/postrender"
 
@@ -31,6 +31,7 @@ type DockerSecretsPostRenderer struct {
 	Repo      repository.Repository
 	Agent     *kubernetes.Agent
 	Namespace string
+	DOAuth    *oauth2.Config
 
 	registries map[string]*models.Registry
 
@@ -48,6 +49,7 @@ func NewDockerSecretsPostRenderer(
 	agent *kubernetes.Agent,
 	namespace string,
 	regs []*models.Registry,
+	doAuth *oauth2.Config,
 ) (postrender.PostRenderer, error) {
 	// Registries is a map of registry URLs to registry ids
 	registries := make(map[string]*models.Registry)
@@ -72,8 +74,6 @@ func NewDockerSecretsPostRenderer(
 		}
 
 		registries[addReg] = reg
-
-		fmt.Println("ADDED REGISTRIES", addReg)
 	}
 
 	return &DockerSecretsPostRenderer{
@@ -81,6 +81,7 @@ func NewDockerSecretsPostRenderer(
 		Repo:       repo,
 		Agent:      agent,
 		Namespace:  namespace,
+		DOAuth:     doAuth,
 		registries: registries,
 		podSpecs:   make([]resource, 0),
 		resources:  make([]resource, 0),
@@ -105,6 +106,7 @@ func (d *DockerSecretsPostRenderer) Run(
 		d.Repo,
 		d.Namespace,
 		linkedRegs,
+		d.DOAuth,
 	)
 
 	if err != nil {
@@ -252,8 +254,6 @@ func (d *DockerSecretsPostRenderer) getPodSpecs(resources []resource) {
 
 func (d *DockerSecretsPostRenderer) updatePodSpecs(secrets map[string]string) {
 	for _, podSpec := range d.podSpecs {
-		fmt.Println("PARSING POD SPEC", podSpec)
-
 		containersVal, hasContainers := podSpec["containers"]
 
 		if !hasContainers {

+ 3 - 1
internal/kubernetes/agent.go

@@ -16,6 +16,7 @@ import (
 	"github.com/porter-dev/porter/internal/models/integrations"
 	"github.com/porter-dev/porter/internal/registry"
 	"github.com/porter-dev/porter/internal/repository"
+	"golang.org/x/oauth2"
 
 	"github.com/gorilla/websocket"
 	"github.com/porter-dev/porter/internal/helm/grapher"
@@ -343,13 +344,14 @@ func (a *Agent) CreateImagePullSecrets(
 	repo repository.Repository,
 	namespace string,
 	linkedRegs map[string]*models.Registry,
+	doAuth *oauth2.Config,
 ) (map[string]string, error) {
 	res := make(map[string]string)
 
 	for key, val := range linkedRegs {
 		_reg := registry.Registry(*val)
 
-		data, err := _reg.GetDockerConfigJSON(repo)
+		data, err := _reg.GetDockerConfigJSON(repo, doAuth)
 
 		if err != nil {
 			return nil, err

+ 1 - 1
internal/kubernetes/config.go

@@ -307,7 +307,7 @@ func (conf *OutOfClusterConfig) createRawConfigFromCluster() (*api.Config, error
 			return nil, err
 		}
 
-		tok, err := oauth.GetAccessToken(oauthInt, conf.DigitalOceanOAuth, *conf.Repo)
+		tok, _, err := oauth.GetAccessToken(oauthInt, conf.DigitalOceanOAuth, *conf.Repo)
 
 		if err != nil {
 			return nil, err

+ 5 - 4
internal/oauth/config.go

@@ -4,6 +4,7 @@ import (
 	"context"
 	"crypto/rand"
 	"encoding/base64"
+	"time"
 
 	"github.com/porter-dev/porter/internal/models/integrations"
 	"github.com/porter-dev/porter/internal/repository"
@@ -58,7 +59,7 @@ func GetAccessToken(
 	o *integrations.OAuthIntegration,
 	conf *oauth2.Config,
 	repo repository.Repository,
-) (string, error) {
+) (string, *time.Time, error) {
 	tokSource := conf.TokenSource(context.TODO(), &oauth2.Token{
 		AccessToken:  string(o.AccessToken),
 		RefreshToken: string(o.RefreshToken),
@@ -68,7 +69,7 @@ func GetAccessToken(
 	token, err := tokSource.Token()
 
 	if err != nil {
-		return "", err
+		return "", nil, err
 	}
 
 	if token.AccessToken != string(o.AccessToken) {
@@ -78,9 +79,9 @@ func GetAccessToken(
 		o, err = repo.OAuthIntegration.UpdateOAuthIntegration(o)
 
 		if err != nil {
-			return "", err
+			return "", nil, err
 		}
 	}
 
-	return token.AccessToken, nil
+	return token.AccessToken, &token.Expiry, nil
 }

+ 153 - 2
internal/registry/registry.go

@@ -1,6 +1,7 @@
 package registry
 
 import (
+	"context"
 	"encoding/base64"
 	"encoding/json"
 	"fmt"
@@ -10,10 +11,13 @@ import (
 
 	"github.com/aws/aws-sdk-go/service/ecr"
 	"github.com/porter-dev/porter/internal/models"
+	"github.com/porter-dev/porter/internal/oauth"
 	"github.com/porter-dev/porter/internal/repository"
+	"golang.org/x/oauth2"
 
 	ints "github.com/porter-dev/porter/internal/models/integrations"
 
+	"github.com/digitalocean/godo"
 	"github.com/docker/cli/cli/config/configfile"
 	"github.com/docker/cli/cli/config/types"
 )
@@ -49,7 +53,10 @@ type Image struct {
 }
 
 // ListRepositories lists the repositories for a registry
-func (r *Registry) ListRepositories(repo repository.Repository) ([]*Repository, error) {
+func (r *Registry) ListRepositories(
+	repo repository.Repository,
+	doAuth *oauth2.Config, // only required if using DOCR
+) ([]*Repository, error) {
 	// switch on the auth mechanism to get a token
 	if r.AWSIntegrationID != 0 {
 		return r.listECRRepositories(repo)
@@ -59,6 +66,10 @@ func (r *Registry) ListRepositories(repo repository.Repository) ([]*Repository,
 		return r.listGCRRepositories(repo)
 	}
 
+	if r.DOIntegrationID != 0 {
+		return r.listDOCRRepositories(repo, doAuth)
+	}
+
 	return nil, fmt.Errorf("error listing repositories")
 }
 
@@ -183,6 +194,52 @@ func (r *Registry) listECRRepositories(repo repository.Repository) ([]*Repositor
 	return res, nil
 }
 
+func (r *Registry) listDOCRRepositories(
+	repo repository.Repository,
+	doAuth *oauth2.Config,
+) ([]*Repository, error) {
+	oauthInt, err := repo.OAuthIntegration.ReadOAuthIntegration(
+		r.DOIntegrationID,
+	)
+
+	if err != nil {
+		return nil, err
+	}
+
+	tok, _, err := oauth.GetAccessToken(oauthInt, doAuth, repo)
+
+	if err != nil {
+		return nil, err
+	}
+
+	client := godo.NewFromToken(tok)
+
+	urlArr := strings.Split(r.URL, "/")
+
+	if len(urlArr) != 2 {
+		return nil, fmt.Errorf("invalid digital ocean registry url")
+	}
+
+	name := urlArr[1]
+
+	repos, _, err := client.Registry.ListRepositories(context.TODO(), name, &godo.ListOptions{})
+
+	if err != nil {
+		return nil, err
+	}
+
+	res := make([]*Repository, 0)
+
+	for _, repo := range repos {
+		res = append(res, &Repository{
+			Name: repo.Name,
+			URI:  r.URL + "/" + repo.Name,
+		})
+	}
+
+	return res, nil
+}
+
 func (r *Registry) getTokenCache() (tok *ints.TokenCache, err error) {
 	return &ints.TokenCache{
 		Token:  r.TokenCache.Token,
@@ -212,6 +269,7 @@ func (r *Registry) setTokenCacheFunc(
 func (r *Registry) ListImages(
 	repoName string,
 	repo repository.Repository,
+	doAuth *oauth2.Config, // only required if using DOCR
 ) ([]*Image, error) {
 	// switch on the auth mechanism to get a token
 	if r.AWSIntegrationID != 0 {
@@ -222,6 +280,10 @@ func (r *Registry) ListImages(
 		return r.listGCRImages(repoName, repo)
 	}
 
+	if r.DOIntegrationID != 0 {
+		return r.listDOCRImages(repoName, repo, doAuth)
+	}
+
 	return nil, fmt.Errorf("error listing images")
 }
 
@@ -315,9 +377,59 @@ func (r *Registry) listGCRImages(repoName string, repo repository.Repository) ([
 	return res, nil
 }
 
+func (r *Registry) listDOCRImages(
+	repoName string,
+	repo repository.Repository,
+	doAuth *oauth2.Config,
+) ([]*Image, error) {
+	oauthInt, err := repo.OAuthIntegration.ReadOAuthIntegration(
+		r.DOIntegrationID,
+	)
+
+	if err != nil {
+		return nil, err
+	}
+
+	tok, _, err := oauth.GetAccessToken(oauthInt, doAuth, repo)
+
+	if err != nil {
+		return nil, err
+	}
+
+	client := godo.NewFromToken(tok)
+
+	urlArr := strings.Split(r.URL, "/")
+
+	if len(urlArr) != 2 {
+		return nil, fmt.Errorf("invalid digital ocean registry url")
+	}
+
+	name := urlArr[1]
+
+	tags, _, err := client.Registry.ListRepositoryTags(context.TODO(), name, repoName, &godo.ListOptions{})
+
+	if err != nil {
+		return nil, err
+	}
+
+	res := make([]*Image, 0)
+
+	for _, tag := range tags {
+		res = append(res, &Image{
+			RepositoryName: repoName,
+			Tag:            tag.Tag,
+		})
+	}
+
+	return res, nil
+}
+
 // GetDockerConfigJSON returns a dockerconfigjson file contents with "auths"
 // populated.
-func (r *Registry) GetDockerConfigJSON(repo repository.Repository) ([]byte, error) {
+func (r *Registry) GetDockerConfigJSON(
+	repo repository.Repository,
+	doAuth *oauth2.Config, // only required if using DOCR
+) ([]byte, error) {
 	var conf *configfile.ConfigFile
 	var err error
 
@@ -330,6 +442,10 @@ func (r *Registry) GetDockerConfigJSON(repo repository.Repository) ([]byte, erro
 		conf, err = r.getGCRDockerConfigFile(repo)
 	}
 
+	if r.DOIntegrationID != 0 {
+		conf, err = r.getDOCRDockerConfigFile(repo, doAuth)
+	}
+
 	if err != nil {
 		return nil, err
 	}
@@ -418,3 +534,38 @@ func (r *Registry) getGCRDockerConfigFile(
 		},
 	}, nil
 }
+
+func (r *Registry) getDOCRDockerConfigFile(
+	repo repository.Repository,
+	doAuth *oauth2.Config,
+) (*configfile.ConfigFile, error) {
+	oauthInt, err := repo.OAuthIntegration.ReadOAuthIntegration(
+		r.DOIntegrationID,
+	)
+
+	if err != nil {
+		return nil, err
+	}
+
+	tok, _, err := oauth.GetAccessToken(oauthInt, doAuth, repo)
+
+	if err != nil {
+		return nil, err
+	}
+
+	key := r.URL
+
+	if !strings.Contains(key, "http") {
+		key = "https://" + key
+	}
+
+	return &configfile.ConfigFile{
+		AuthConfigs: map[string]types.AuthConfig{
+			key: types.AuthConfig{
+				Username: tok,
+				Password: tok,
+				Auth:     tok,
+			},
+		},
+	}, nil
+}

+ 2 - 2
internal/templater/helm/values/writer.go

@@ -42,7 +42,7 @@ func (w *TemplateWriter) Create(
 		Values:    vals,
 	}
 
-	_, err := w.Agent.InstallChart(conf)
+	_, err := w.Agent.InstallChart(conf, nil)
 
 	if err != nil {
 		return nil, err
@@ -64,7 +64,7 @@ func (w *TemplateWriter) Update(
 		Values: vals,
 	}
 
-	_, err := w.Agent.UpgradeReleaseByValues(conf)
+	_, err := w.Agent.UpgradeReleaseByValues(conf, nil)
 
 	if err != nil {
 		return nil, err

+ 1 - 1
server/api/deploy_handler.go

@@ -102,7 +102,7 @@ func (app *App) HandleDeployTemplate(w http.ResponseWriter, r *http.Request) {
 		Registries: registries,
 	}
 
-	_, err = agent.InstallChart(conf)
+	_, err = agent.InstallChart(conf, app.DOConf)
 
 	if err != nil {
 		app.sendExternalError(err, http.StatusInternalServerError, HTTPError{

+ 62 - 2
server/api/registry_handler.go

@@ -7,6 +7,8 @@ import (
 	"strings"
 	"time"
 
+	"github.com/porter-dev/porter/internal/oauth"
+
 	"github.com/porter-dev/porter/internal/registry"
 
 	"github.com/go-chi/chi"
@@ -211,6 +213,64 @@ func (app *App) HandleGetProjectRegistryGCRToken(w http.ResponseWriter, r *http.
 
 			token = string(tokenCache.Token)
 			expiresAt = &tokenCache.Expiry
+			break
+		}
+	}
+
+	resp := &RegTokenResponse{
+		Token:     token,
+		ExpiresAt: expiresAt,
+	}
+
+	w.WriteHeader(http.StatusOK)
+
+	if err := json.NewEncoder(w).Encode(resp); err != nil {
+		app.handleErrorFormDecoding(err, ErrProjectDecode, w)
+		return
+	}
+}
+
+// HandleGetProjectRegistryDOCRToken gets a DOCR token for a registry
+func (app *App) HandleGetProjectRegistryDOCRToken(w http.ResponseWriter, r *http.Request) {
+	projID, err := strconv.ParseUint(chi.URLParam(r, "project_id"), 0, 64)
+
+	if err != nil || projID == 0 {
+		app.handleErrorFormDecoding(err, ErrProjectDecode, w)
+		return
+	}
+
+	reqBody := &GCRTokenRequestBody{}
+
+	// decode from JSON to form value
+	if err := json.NewDecoder(r.Body).Decode(reqBody); err != nil {
+		app.handleErrorFormDecoding(err, ErrProjectDecode, w)
+		return
+	}
+
+	// list registries and find one that matches the region
+	regs, err := app.Repo.Registry.ListRegistriesByProjectID(uint(projID))
+	var token string
+	var expiresAt *time.Time
+
+	for _, reg := range regs {
+		if reg.DOIntegrationID != 0 && strings.Contains(reg.URL, reqBody.ServerURL) {
+			oauthInt, err := app.Repo.OAuthIntegration.ReadOAuthIntegration(reg.DOIntegrationID)
+
+			if err != nil {
+				app.handleErrorDataRead(err, w)
+				return
+			}
+
+			tok, expiry, err := oauth.GetAccessToken(oauthInt, app.DOConf, *app.Repo)
+
+			if err != nil {
+				app.handleErrorDataRead(err, w)
+				return
+			}
+
+			token = tok
+			expiresAt = expiry
+			break
 		}
 	}
 
@@ -331,7 +391,7 @@ func (app *App) HandleListRepositories(w http.ResponseWriter, r *http.Request) {
 	_reg := registry.Registry(*reg)
 	regAPI := &_reg
 
-	repos, err := regAPI.ListRepositories(*app.Repo)
+	repos, err := regAPI.ListRepositories(*app.Repo, app.DOConf)
 
 	if err != nil {
 		app.handleErrorRead(err, ErrProjectDataRead, w)
@@ -368,7 +428,7 @@ func (app *App) HandleListImages(w http.ResponseWriter, r *http.Request) {
 	_reg := registry.Registry(*reg)
 	regAPI := &_reg
 
-	imgs, err := regAPI.ListImages(repoName, *app.Repo)
+	imgs, err := regAPI.ListImages(repoName, *app.Repo, app.DOConf)
 
 	if err != nil {
 		app.handleErrorRead(err, ErrProjectDataRead, w)

+ 3 - 3
server/api/release_handler.go

@@ -498,7 +498,7 @@ func (app *App) HandleUpgradeRelease(w http.ResponseWriter, r *http.Request) {
 		Registries: registries,
 	}
 
-	_, err = agent.UpgradeRelease(conf, form.Values)
+	_, err = agent.UpgradeRelease(conf, form.Values, app.DOConf)
 
 	if err != nil {
 		app.sendExternalError(err, http.StatusInternalServerError, HTTPError{
@@ -578,7 +578,7 @@ func (app *App) HandleReleaseDeployHook(w http.ResponseWriter, r *http.Request)
 		Values:     newval,
 	}
 
-	_, err = agent.UpgradeReleaseByValues(conf)
+	_, err = agent.UpgradeReleaseByValues(conf, app.DOConf)
 
 	if err != nil {
 		app.sendExternalError(err, http.StatusInternalServerError, HTTPError{
@@ -671,7 +671,7 @@ func (app *App) HandleReleaseDeployWebhook(w http.ResponseWriter, r *http.Reques
 		Values:     newval,
 	}
 
-	_, err = agent.UpgradeReleaseByValues(conf)
+	_, err = agent.UpgradeReleaseByValues(conf, app.DOConf)
 
 	if err != nil {
 		app.sendExternalError(err, http.StatusInternalServerError, HTTPError{