Skip to content

Commit

Permalink
fix(helm): login OCI Helm dependencies correctly (#8563) (#11327)
Browse files Browse the repository at this point in the history
Signed-off-by: Alex Eftimie <alex.eftimie@getyourguide.com>

Signed-off-by: Alex Eftimie <alex.eftimie@getyourguide.com>
  • Loading branch information
alexef authored and crenshaw-dev committed Dec 7, 2022
1 parent fca6271 commit ecdea74
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 34 deletions.
46 changes: 28 additions & 18 deletions reposerver/repository/repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -697,6 +697,32 @@ func runHelmBuild(appPath string, h helm.Helm) error {
return ioutil.WriteFile(markerFile, []byte("marker"), 0644)
}

func populateRequestRepos(appPath string, q *apiclient.ManifestRequest) error {
repos, err := getHelmDependencyRepos(appPath)
if err != nil {
return err
}

for _, r := range repos {
if !repoExists(r.Repo, q.Repos) {
repositoryCredential := getRepoCredential(q.HelmRepoCreds, r.Repo)
if repositoryCredential != nil {
if repositoryCredential.EnableOCI {
r.Repo = strings.TrimPrefix(r.Repo, ociPrefix)
}
r.EnableOCI = repositoryCredential.EnableOCI
r.Password = repositoryCredential.Password
r.Username = repositoryCredential.Username
r.SSHPrivateKey = repositoryCredential.SSHPrivateKey
r.TLSClientCertData = repositoryCredential.TLSClientCertData
r.TLSClientCertKey = repositoryCredential.TLSClientCertKey
}
q.Repos = append(q.Repos, r)
}
}
return nil
}

func helmTemplate(appPath string, repoRoot string, env *v1alpha1.Env, q *apiclient.ManifestRequest, isLocal bool) ([]*unstructured.Unstructured, error) {
concurrencyAllowed := isConcurrencyAllowed(appPath)
if !concurrencyAllowed {
Expand Down Expand Up @@ -787,24 +813,8 @@ func helmTemplate(appPath string, repoRoot string, env *v1alpha1.Env, q *apiclie
templateOpts.SetString[i] = env.Envsubst(j)
}

repos, err := getHelmDependencyRepos(appPath)
if err != nil {
return nil, err
}

for _, r := range repos {
if !repoExists(r.Repo, q.Repos) {
repositoryCredential := getRepoCredential(q.HelmRepoCreds, r.Repo)
if repositoryCredential != nil {
r.EnableOCI = repositoryCredential.EnableOCI
r.Password = repositoryCredential.Password
r.Username = repositoryCredential.Username
r.SSHPrivateKey = repositoryCredential.SSHPrivateKey
r.TLSClientCertData = repositoryCredential.TLSClientCertData
r.TLSClientCertKey = repositoryCredential.TLSClientCertKey
}
q.Repos = append(q.Repos, r)
}
if err := populateRequestRepos(appPath, q); err != nil {
return nil, fmt.Errorf("failed parsing dependencies: %v", err)
}

var proxy string
Expand Down
54 changes: 38 additions & 16 deletions reposerver/repository/repository_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,14 @@ gpg: using RSA key 4AEE18F83AFDEB23
gpg: Good signature from "GitHub (web-flow commit signing) <noreply@github.com>" [ultimate]
`

type clientFunc func(*gitmocks.Client)
type clientFunc func(*gitmocks.Client, *helmmocks.Client)

func newServiceWithMocks(root string, signed bool) (*Service, *gitmocks.Client) {
root, err := filepath.Abs(root)
if err != nil {
panic(err)
}
return newServiceWithOpt(func(gitClient *gitmocks.Client) {
return newServiceWithOpt(func(gitClient *gitmocks.Client, helmClient *helmmocks.Client) {
gitClient.On("Init").Return(nil)
gitClient.On("Fetch", mock.Anything).Return(nil)
gitClient.On("Checkout", mock.Anything, mock.Anything).Return(nil)
Expand All @@ -66,26 +66,27 @@ func newServiceWithMocks(root string, signed bool) (*Service, *gitmocks.Client)
} else {
gitClient.On("VerifyCommitSignature", mock.Anything).Return("", nil)
}
})

chart := "my-chart"
version := "1.1.0"
helmClient.On("GetIndex", true).Return(&helm.Index{Entries: map[string]helm.Entries{
chart: {{Version: "1.0.0"}, {Version: version}},
}}, nil)
helmClient.On("ExtractChart", chart, version).Return("./testdata/my-chart", io.NopCloser, nil)
helmClient.On("CleanChartCache", chart, version).Return(nil)
helmClient.On("DependencyBuild").Return(nil)
}, root)
}

func newServiceWithOpt(cf clientFunc) (*Service, *gitmocks.Client) {
func newServiceWithOpt(cf clientFunc, root string) (*Service, *gitmocks.Client) {
helmClient := &helmmocks.Client{}
gitClient := &gitmocks.Client{}
cf(gitClient)
cf(gitClient, helmClient)
service := NewService(metrics.NewMetricsServer(), cache.NewCache(
cacheutil.NewCache(cacheutil.NewInMemoryCache(1*time.Minute)),
1*time.Minute,
1*time.Minute,
), RepoServerInitConstants{ParallelismLimit: 1}, argo.NewResourceTracking(), &git.NoopCredsStore{}, os.TempDir())

chart := "my-chart"
version := "1.1.0"
helmClient.On("GetIndex", true).Return(&helm.Index{Entries: map[string]helm.Entries{
chart: {{Version: "1.0.0"}, {Version: version}},
}}, nil)
helmClient.On("ExtractChart", chart, version).Return("./testdata/my-chart", io.NopCloser, nil)
helmClient.On("CleanChartCache", chart, version).Return(nil)
), RepoServerInitConstants{ParallelismLimit: 1}, argo.NewResourceTracking(), &git.NoopCredsStore{}, root)

service.newGitClient = func(rawRepoURL string, root string, creds git.Creds, insecure bool, enableLfs bool, prosy string, opts ...git.ClientOpts) (client git.Client, e error) {
return gitClient, nil
Expand All @@ -110,21 +111,26 @@ func newServiceWithSignature(root string) *Service {
}

func newServiceWithCommitSHA(root, revision string) *Service {
root, err := filepath.Abs(root)
if err != nil {
panic(err)
}

var revisionErr error

commitSHARegex := regexp.MustCompile("^[0-9A-Fa-f]{40}$")
if !commitSHARegex.MatchString(revision) {
revisionErr = errors.New("not a commit SHA")
}

service, gitClient := newServiceWithOpt(func(gitClient *gitmocks.Client) {
service, gitClient := newServiceWithOpt(func(gitClient *gitmocks.Client, helmClient *helmmocks.Client) {
gitClient.On("Init").Return(nil)
gitClient.On("Fetch", mock.Anything).Return(nil)
gitClient.On("Checkout", mock.Anything, mock.Anything).Return(nil)
gitClient.On("LsRemote", revision).Return(revision, revisionErr)
gitClient.On("CommitSHA").Return("632039659e542ed7de0c170a4fcc1c571b288fc0", nil)
gitClient.On("Root").Return(root)
})
}, root)

service.newGitClient = func(rawRepoURL string, root string, creds git.Creds, insecure bool, enableLfs bool, proxy string, opts ...git.ClientOpts) (client git.Client, e error) {
return gitClient, nil
Expand Down Expand Up @@ -1180,6 +1186,7 @@ func TestListApps(t *testing.T) {
"kustomization_yml": "Kustomize",
"my-chart": "Helm",
"my-chart-2": "Helm",
"oci-dependencies": "Helm",
"out-of-bounds-values-file-link": "Helm",
"values-files": "Helm",
}
Expand Down Expand Up @@ -2499,3 +2506,18 @@ func Test_populateHelmAppDetails_values_symlinks(t *testing.T) {
assert.Empty(t, res.Helm.Parameters)
})
}

func TestOCIDependencies(t *testing.T) {
src := argoappv1.ApplicationSource{Path: "."}
q := apiclient.ManifestRequest{Repo: &argoappv1.Repository{}, ApplicationSource: &src, HelmRepoCreds: []*argoappv1.RepoCreds{
{URL: "example.com", Username: "test", Password: "test", EnableOCI: true},
}}

err := populateRequestRepos("./testdata/oci-dependencies", &q)
assert.Nil(t, err)

assert.Equal(t, len(q.Repos), 1)
assert.Equal(t, q.Repos[0].Username, "test")
assert.Equal(t, q.Repos[0].EnableOCI, true)
assert.Equal(t, q.Repos[0].Repo, "example.com")
}
6 changes: 6 additions & 0 deletions reposerver/repository/testdata/oci-dependencies/Chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
name: my-chart
version: 1.1.0
dependencies:
- name: my-dependency
repository: oci://example.com
version: '*'

0 comments on commit ecdea74

Please sign in to comment.