diff --git a/docs/basics/update-methods.md b/docs/basics/update-methods.md
index 2a368ea4..ba27ce4f 100644
--- a/docs/basics/update-methods.md
+++ b/docs/basics/update-methods.md
@@ -144,6 +144,22 @@ kubectl -n argocd-image-updater create secret generic git-creds \
--from-file=sshPrivateKey=~/.ssh/id_rsa
```
+### Specifying a repository when using a Helm repository in repoURL
+
+By default, Argo CD Image Updater will use the value found in the Application
+spec at `.spec.source.repoURL` as Git repository to checkout. But when using
+a Helm repository as `.spec.source.repoURL` GIT will simply fail. To manually
+specify the repository to push the changes, specify the
+annotation `argocd-image-updater.argoproj.io/git-repository` on the Application
+manifest.
+
+The value of this annotation will define the Git repository to use, for example the
+following would use a GitHub's repository:
+
+```yaml
+argocd-image-updater.argoproj.io/git-repository: git@github.com:example/example.git
+```
+
### Specifying a branch to commit to
By default, Argo CD Image Updater will use the value found in the Application
diff --git a/pkg/argocd/git.go b/pkg/argocd/git.go
index 6aa4b421..ef26fbe3 100644
--- a/pkg/argocd/git.go
+++ b/pkg/argocd/git.go
@@ -131,7 +131,7 @@ func commitChangesGit(app *v1alpha1.Application, wbc *WriteBackConfig, changeLis
logCtx := log.WithContext().AddField("application", app.GetName())
creds, err := wbc.GetCreds(app)
if err != nil {
- return fmt.Errorf("could not get creds for repo '%s': %v", app.Spec.Source.RepoURL, err)
+ return fmt.Errorf("could not get creds for repo '%s': %v", wbc.GitRepo, err)
}
var gitC git.Client
if wbc.GitClient == nil {
@@ -145,7 +145,7 @@ func commitChangesGit(app *v1alpha1.Application, wbc *WriteBackConfig, changeLis
logCtx.Errorf("could not remove temp dir: %v", err)
}
}()
- gitC, err = git.NewClientExt(app.Spec.Source.RepoURL, tempRoot, creds, false, false, "")
+ gitC, err = git.NewClientExt(wbc.GitRepo, tempRoot, creds, false, false, "")
if err != nil {
return err
}
diff --git a/pkg/argocd/gitcreds.go b/pkg/argocd/gitcreds.go
index 4d42e837..85988212 100644
--- a/pkg/argocd/gitcreds.go
+++ b/pkg/argocd/gitcreds.go
@@ -14,39 +14,39 @@ import (
)
// getGitCredsSource returns git credentials source that loads credentials from the secret or from Argo CD settings
-func getGitCredsSource(creds string, kubeClient *kube.KubernetesClient) (GitCredsSource, error) {
+func getGitCredsSource(creds string, kubeClient *kube.KubernetesClient, wbc *WriteBackConfig) (GitCredsSource, error) {
switch {
case creds == "repocreds":
return func(app *v1alpha1.Application) (git.Creds, error) {
- return getCredsFromArgoCD(app, kubeClient)
+ return getCredsFromArgoCD(wbc, kubeClient)
}, nil
case strings.HasPrefix(creds, "secret:"):
return func(app *v1alpha1.Application) (git.Creds, error) {
- return getCredsFromSecret(app, creds[len("secret:"):], kubeClient)
+ return getCredsFromSecret(wbc, creds[len("secret:"):], kubeClient)
}, nil
}
return nil, fmt.Errorf("unexpected credentials format. Expected 'repocreds' or 'secret:/' but got '%s'", creds)
}
// getCredsFromArgoCD loads repository credentials from Argo CD settings
-func getCredsFromArgoCD(app *v1alpha1.Application, kubeClient *kube.KubernetesClient) (git.Creds, error) {
+func getCredsFromArgoCD(wbc *WriteBackConfig, kubeClient *kube.KubernetesClient) (git.Creds, error) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
settingsMgr := settings.NewSettingsManager(ctx, kubeClient.Clientset, kubeClient.Namespace)
argocdDB := db.NewDB(kubeClient.Namespace, settingsMgr, kubeClient.Clientset)
- repo, err := argocdDB.GetRepository(ctx, app.Spec.Source.RepoURL)
+ repo, err := argocdDB.GetRepository(ctx, wbc.GitRepo)
if err != nil {
return nil, err
}
if !repo.HasCredentials() {
- return nil, fmt.Errorf("credentials for '%s' are not configured in Argo CD settings", app.Spec.Source.RepoURL)
+ return nil, fmt.Errorf("credentials for '%s' are not configured in Argo CD settings", wbc.GitRepo)
}
return repo.GetGitCreds(), nil
}
// getCredsFromSecret loads repository credentials from secret
-func getCredsFromSecret(app *v1alpha1.Application, credentialsSecret string, kubeClient *kube.KubernetesClient) (git.Creds, error) {
+func getCredsFromSecret(wbc *WriteBackConfig, credentialsSecret string, kubeClient *kube.KubernetesClient) (git.Creds, error) {
var credentials map[string][]byte
var err error
s := strings.SplitN(credentialsSecret, "/", 2)
@@ -59,13 +59,13 @@ func getCredsFromSecret(app *v1alpha1.Application, credentialsSecret string, kub
return nil, fmt.Errorf("secret ref must be in format 'namespace/name', but is '%s'", credentialsSecret)
}
- if ok, _ := git.IsSSHURL(app.Spec.Source.RepoURL); ok {
+ if ok, _ := git.IsSSHURL(wbc.GitRepo); ok {
var sshPrivateKey []byte
if sshPrivateKey, ok = credentials["sshPrivateKey"]; !ok {
return nil, fmt.Errorf("invalid secret %s: does not contain field sshPrivateKey", credentialsSecret)
}
return git.NewSSHCreds(string(sshPrivateKey), "", true), nil
- } else if git.IsHTTPSURL(app.Spec.Source.RepoURL) {
+ } else if git.IsHTTPSURL(wbc.GitRepo) {
var username, password []byte
if username, ok = credentials["username"]; !ok {
return nil, fmt.Errorf("invalid secret %s: does not contain field username", credentialsSecret)
diff --git a/pkg/argocd/update.go b/pkg/argocd/update.go
index c92730dc..c7f6cdd6 100644
--- a/pkg/argocd/update.go
+++ b/pkg/argocd/update.go
@@ -68,6 +68,7 @@ type WriteBackConfig struct {
GitCommitMessage string
KustomizeBase string
Target string
+ GitRepo string
}
// The following are helper structs to only marshal the fields we require
@@ -476,7 +477,12 @@ func parseGitConfig(app *v1alpha1.Application, kubeClient *kube.KubernetesClient
wbc.GitWriteBranch = branches[1]
}
}
- credsSource, err := getGitCredsSource(creds, kubeClient)
+ wbc.GitRepo = app.Spec.Source.RepoURL
+ repo, ok := app.Annotations[common.GitRepositoryAnnotation]
+ if ok {
+ wbc.GitRepo = repo
+ }
+ credsSource, err := getGitCredsSource(creds, kubeClient, wbc)
if err != nil {
return fmt.Errorf("invalid git credentials source: %v", err)
}
@@ -486,7 +492,7 @@ func parseGitConfig(app *v1alpha1.Application, kubeClient *kube.KubernetesClient
func commitChangesLocked(app *v1alpha1.Application, wbc *WriteBackConfig, state *SyncIterationState, changeList []ChangeEntry) error {
if wbc.RequiresLocking() {
- lock := state.GetRepositoryLock(app.Spec.Source.RepoURL)
+ lock := state.GetRepositoryLock(wbc.GitRepo)
lock.Lock()
defer lock.Unlock()
}
diff --git a/pkg/argocd/update_test.go b/pkg/argocd/update_test.go
index ea5cdccf..c9110e18 100644
--- a/pkg/argocd/update_test.go
+++ b/pkg/argocd/update_test.go
@@ -1691,6 +1691,48 @@ func Test_GetGitCreds(t *testing.T) {
require.Error(t, err)
require.Nil(t, creds)
})
+
+ t.Run("SSH creds from Argo CD settings with Helm Chart repoURL", func(t *testing.T) {
+ argoClient := argomock.ArgoCD{}
+ argoClient.On("UpdateSpec", mock.Anything, mock.Anything).Return(nil, nil)
+ secret := fixture.NewSecret("argocd-image-updater", "git-creds", map[string][]byte{
+ "sshPrivateKey": []byte("foo"),
+ })
+ kubeClient := kube.KubernetesClient{
+ Clientset: fake.NewFakeClientsetWithResources(secret),
+ }
+
+ app := v1alpha1.Application{
+ ObjectMeta: v1.ObjectMeta{
+ Name: "testapp",
+ Annotations: map[string]string{
+ "argocd-image-updater.argoproj.io/image-list": "nginx",
+ "argocd-image-updater.argoproj.io/write-back-method": "git:secret:argocd-image-updater/git-creds",
+ "argocd-image-updater.argoproj.io/git-repository": "git@github.com:example/example.git",
+ },
+ },
+ Spec: v1alpha1.ApplicationSpec{
+ Source: v1alpha1.ApplicationSource{
+ RepoURL: "https://example-helm-repo.com/example",
+ TargetRevision: "main",
+ },
+ },
+ Status: v1alpha1.ApplicationStatus{
+ SourceType: v1alpha1.ApplicationSourceTypeKustomize,
+ },
+ }
+
+ wbc, err := getWriteBackConfig(&app, &kubeClient, &argoClient)
+ require.NoError(t, err)
+ require.Equal(t, wbc.GitRepo, "git@github.com:example/example.git")
+
+ creds, err := wbc.GetCreds(&app)
+ require.NoError(t, err)
+ require.NotNil(t, creds)
+ // Must have SSH creds
+ _, ok := creds.(git.SSHCreds)
+ require.True(t, ok)
+ })
}
func Test_CommitUpdates(t *testing.T) {
diff --git a/pkg/common/constants.go b/pkg/common/constants.go
index 527b2009..5abf6da6 100644
--- a/pkg/common/constants.go
+++ b/pkg/common/constants.go
@@ -50,6 +50,7 @@ const (
const (
WriteBackMethodAnnotation = ImageUpdaterAnnotationPrefix + "/write-back-method"
GitBranchAnnotation = ImageUpdaterAnnotationPrefix + "/git-branch"
+ GitRepositoryAnnotation = ImageUpdaterAnnotationPrefix + "/git-repository"
WriteBackTargetAnnotation = ImageUpdaterAnnotationPrefix + "/write-back-target"
KustomizationPrefix = "kustomization"
)