Support for azure acr helm repositories (#1526)
Adds a basic support for Helm repositories hosted on Azure Container Registry (not OCI but classic ones). Add a new field to RepositorySpec to state that is externally managed and runs the `az-cli` command instead of the helm one to manage the repository.
This commit is contained in:
parent
563fce4adf
commit
8f8669778c
|
|
@ -2418,7 +2418,7 @@ func (helm *mockHelmExec) SetExtraArgs(args ...string) {
|
|||
func (helm *mockHelmExec) SetHelmBinary(bin string) {
|
||||
return
|
||||
}
|
||||
func (helm *mockHelmExec) AddRepo(name, repository, cafile, certfile, keyfile, username, password string) error {
|
||||
func (helm *mockHelmExec) AddRepo(name, repository, cafile, certfile, keyfile, username, password string, managed string) error {
|
||||
helm.repos = append(helm.repos, mockRepo{Name: name})
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ func (helm *noCallHelmExec) SetHelmBinary(bin string) {
|
|||
helm.doPanic()
|
||||
return
|
||||
}
|
||||
func (helm *noCallHelmExec) AddRepo(name, repository, cafile, certfile, keyfile, username, password string) error {
|
||||
func (helm *noCallHelmExec) AddRepo(name, repository, cafile, certfile, keyfile, username, password string, managed string) error {
|
||||
helm.doPanic()
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,8 +82,8 @@ func (helm *Helm) SetExtraArgs(args ...string) {
|
|||
func (helm *Helm) SetHelmBinary(bin string) {
|
||||
return
|
||||
}
|
||||
func (helm *Helm) AddRepo(name, repository, cafile, certfile, keyfile, username, password string) error {
|
||||
helm.Repo = []string{name, repository, cafile, certfile, keyfile, username, password}
|
||||
func (helm *Helm) AddRepo(name, repository, cafile, certfile, keyfile, username, password string, managed string) error {
|
||||
helm.Repo = []string{name, repository, cafile, certfile, keyfile, username, password, managed}
|
||||
return nil
|
||||
}
|
||||
func (helm *Helm) UpdateRepo() error {
|
||||
|
|
|
|||
|
|
@ -105,34 +105,46 @@ func (helm *execer) SetHelmBinary(bin string) {
|
|||
helm.helmBinary = bin
|
||||
}
|
||||
|
||||
func (helm *execer) AddRepo(name, repository, cafile, certfile, keyfile, username, password string) error {
|
||||
func (helm *execer) AddRepo(name, repository, cafile, certfile, keyfile, username, password string, managed string) error {
|
||||
var args []string
|
||||
var out []byte
|
||||
var err error
|
||||
if name == "" && repository != "" {
|
||||
helm.logger.Infof("empty field name\n")
|
||||
return fmt.Errorf("empty field name")
|
||||
}
|
||||
args = append(args, "repo", "add", name, repository)
|
||||
switch managed {
|
||||
case "acr":
|
||||
helm.logger.Infof("Adding repo %v (acr)", name)
|
||||
out, err = helm.azcli(name)
|
||||
case "":
|
||||
args = append(args, "repo", "add", name, repository)
|
||||
|
||||
// See https://github.com/helm/helm/pull/8777
|
||||
if cons, err := semver.NewConstraint(">= 3.3.2, < 3.3.4"); err == nil {
|
||||
if cons.Check(&helm.version) {
|
||||
args = append(args, "--force-update")
|
||||
// See https://github.com/helm/helm/pull/8777
|
||||
if cons, err := semver.NewConstraint(">= 3.3.2, < 3.3.4"); err == nil {
|
||||
if cons.Check(&helm.version) {
|
||||
args = append(args, "--force-update")
|
||||
}
|
||||
} else {
|
||||
panic(err)
|
||||
}
|
||||
} else {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if certfile != "" && keyfile != "" {
|
||||
args = append(args, "--cert-file", certfile, "--key-file", keyfile)
|
||||
if certfile != "" && keyfile != "" {
|
||||
args = append(args, "--cert-file", certfile, "--key-file", keyfile)
|
||||
}
|
||||
if cafile != "" {
|
||||
args = append(args, "--ca-file", cafile)
|
||||
}
|
||||
if username != "" && password != "" {
|
||||
args = append(args, "--username", username, "--password", password)
|
||||
}
|
||||
helm.logger.Infof("Adding repo %v %v", name, repository)
|
||||
out, err = helm.exec(args, map[string]string{})
|
||||
default:
|
||||
helm.logger.Errorf("ERROR: unknown type '%v' for repository %v", managed, name)
|
||||
out = nil
|
||||
err = nil
|
||||
}
|
||||
if cafile != "" {
|
||||
args = append(args, "--ca-file", cafile)
|
||||
}
|
||||
if username != "" && password != "" {
|
||||
args = append(args, "--username", username, "--password", password)
|
||||
}
|
||||
helm.logger.Infof("Adding repo %v %v", name, repository)
|
||||
out, err := helm.exec(args, map[string]string{})
|
||||
helm.info(out)
|
||||
return err
|
||||
}
|
||||
|
|
@ -370,6 +382,15 @@ func (helm *execer) exec(args []string, env map[string]string) ([]byte, error) {
|
|||
return bytes, err
|
||||
}
|
||||
|
||||
func (helm *execer) azcli(name string) ([]byte, error) {
|
||||
cmdargs := append(strings.Split("acr helm repo add --name", " "), name)
|
||||
cmd := fmt.Sprintf("exec: az %s", strings.Join(cmdargs, " "))
|
||||
helm.logger.Debug(cmd)
|
||||
bytes, err := helm.runner.Execute("az", cmdargs, map[string]string{})
|
||||
helm.logger.Debugf("%s: %s", cmd, bytes)
|
||||
return bytes, err
|
||||
}
|
||||
|
||||
func (helm *execer) info(out []byte) {
|
||||
if len(out) > 0 {
|
||||
helm.logger.Infof("%s", out)
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ func Test_AddRepo_Helm_3_3_2(t *testing.T) {
|
|||
kubeContext: "dev",
|
||||
runner: &mockRunner{},
|
||||
}
|
||||
helm.AddRepo("myRepo", "https://repo.example.com/", "", "cert.pem", "key.pem", "", "")
|
||||
helm.AddRepo("myRepo", "https://repo.example.com/", "", "cert.pem", "key.pem", "", "", "")
|
||||
expected := `Adding repo myRepo https://repo.example.com/
|
||||
exec: helm --kube-context dev repo add myRepo https://repo.example.com/ --force-update --cert-file cert.pem --key-file key.pem
|
||||
exec: helm --kube-context dev repo add myRepo https://repo.example.com/ --force-update --cert-file cert.pem --key-file key.pem:
|
||||
|
|
@ -96,7 +96,7 @@ func Test_AddRepo(t *testing.T) {
|
|||
var buffer bytes.Buffer
|
||||
logger := NewLogger(&buffer, "debug")
|
||||
helm := MockExecer(logger, "dev")
|
||||
helm.AddRepo("myRepo", "https://repo.example.com/", "", "cert.pem", "key.pem", "", "")
|
||||
helm.AddRepo("myRepo", "https://repo.example.com/", "", "cert.pem", "key.pem", "", "", "")
|
||||
expected := `Adding repo myRepo https://repo.example.com/
|
||||
exec: helm --kube-context dev repo add myRepo https://repo.example.com/ --cert-file cert.pem --key-file key.pem
|
||||
exec: helm --kube-context dev repo add myRepo https://repo.example.com/ --cert-file cert.pem --key-file key.pem:
|
||||
|
|
@ -106,7 +106,7 @@ exec: helm --kube-context dev repo add myRepo https://repo.example.com/ --cert-f
|
|||
}
|
||||
|
||||
buffer.Reset()
|
||||
helm.AddRepo("myRepo", "https://repo.example.com/", "ca.crt", "", "", "", "")
|
||||
helm.AddRepo("myRepo", "https://repo.example.com/", "ca.crt", "", "", "", "", "")
|
||||
expected = `Adding repo myRepo https://repo.example.com/
|
||||
exec: helm --kube-context dev repo add myRepo https://repo.example.com/ --ca-file ca.crt
|
||||
exec: helm --kube-context dev repo add myRepo https://repo.example.com/ --ca-file ca.crt:
|
||||
|
|
@ -116,7 +116,7 @@ exec: helm --kube-context dev repo add myRepo https://repo.example.com/ --ca-fil
|
|||
}
|
||||
|
||||
buffer.Reset()
|
||||
helm.AddRepo("myRepo", "https://repo.example.com/", "", "", "", "", "")
|
||||
helm.AddRepo("myRepo", "https://repo.example.com/", "", "", "", "", "", "")
|
||||
expected = `Adding repo myRepo https://repo.example.com/
|
||||
exec: helm --kube-context dev repo add myRepo https://repo.example.com/
|
||||
exec: helm --kube-context dev repo add myRepo https://repo.example.com/:
|
||||
|
|
@ -126,7 +126,25 @@ exec: helm --kube-context dev repo add myRepo https://repo.example.com/:
|
|||
}
|
||||
|
||||
buffer.Reset()
|
||||
helm.AddRepo("myRepo", "https://repo.example.com/", "", "", "", "example_user", "example_password")
|
||||
helm.AddRepo("acrRepo", "", "", "", "", "", "", "acr")
|
||||
expected = `Adding repo acrRepo (acr)
|
||||
exec: az acr helm repo add --name acrRepo
|
||||
exec: az acr helm repo add --name acrRepo:
|
||||
`
|
||||
if buffer.String() != expected {
|
||||
t.Errorf("helmexec.AddRepo()\nactual = %v\nexpect = %v", buffer.String(), expected)
|
||||
}
|
||||
|
||||
buffer.Reset()
|
||||
helm.AddRepo("otherRepo", "", "", "", "", "", "", "unknown")
|
||||
expected = `ERROR: unknown type 'unknown' for repository otherRepo
|
||||
`
|
||||
if buffer.String() != expected {
|
||||
t.Errorf("helmexec.AddRepo()\nactual = %v\nexpect = %v", buffer.String(), expected)
|
||||
}
|
||||
|
||||
buffer.Reset()
|
||||
helm.AddRepo("myRepo", "https://repo.example.com/", "", "", "", "example_user", "example_password", "")
|
||||
expected = `Adding repo myRepo https://repo.example.com/
|
||||
exec: helm --kube-context dev repo add myRepo https://repo.example.com/ --username example_user --password example_password
|
||||
exec: helm --kube-context dev repo add myRepo https://repo.example.com/ --username example_user --password example_password:
|
||||
|
|
@ -136,7 +154,7 @@ exec: helm --kube-context dev repo add myRepo https://repo.example.com/ --userna
|
|||
}
|
||||
|
||||
buffer.Reset()
|
||||
helm.AddRepo("", "https://repo.example.com/", "", "", "", "", "")
|
||||
helm.AddRepo("", "https://repo.example.com/", "", "", "", "", "", "")
|
||||
expected = `empty field name
|
||||
|
||||
`
|
||||
|
|
@ -482,7 +500,7 @@ func Test_LogLevels(t *testing.T) {
|
|||
buffer.Reset()
|
||||
logger := NewLogger(&buffer, logLevel)
|
||||
helm := MockExecer(logger, "")
|
||||
helm.AddRepo("myRepo", "https://repo.example.com/", "", "", "", "example_user", "example_password")
|
||||
helm.AddRepo("myRepo", "https://repo.example.com/", "", "", "", "example_user", "example_password", "")
|
||||
if buffer.String() != expected {
|
||||
t.Errorf("helmexec.AddRepo()\nactual = %v\nexpect = %v", buffer.String(), expected)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ type Interface interface {
|
|||
SetExtraArgs(args ...string)
|
||||
SetHelmBinary(bin string)
|
||||
|
||||
AddRepo(name, repository, cafile, certfile, keyfile, username, password string) error
|
||||
AddRepo(name, repository, cafile, certfile, keyfile, username, password string, managed string) error
|
||||
UpdateRepo() error
|
||||
BuildDeps(name, chart string) error
|
||||
UpdateDeps(chart string) error
|
||||
|
|
|
|||
|
|
@ -157,6 +157,7 @@ type RepositorySpec struct {
|
|||
KeyFile string `yaml:"keyFile,omitempty"`
|
||||
Username string `yaml:"username,omitempty"`
|
||||
Password string `yaml:"password,omitempty"`
|
||||
Managed string `yaml:"managed,omitempty"`
|
||||
}
|
||||
|
||||
// ReleaseSpec defines the structure of a helm release
|
||||
|
|
@ -313,7 +314,7 @@ func (st *HelmState) ApplyOverrides(spec *ReleaseSpec) {
|
|||
}
|
||||
|
||||
type RepoUpdater interface {
|
||||
AddRepo(name, repository, cafile, certfile, keyfile, username, password string) error
|
||||
AddRepo(name, repository, cafile, certfile, keyfile, username, password string, managed string) error
|
||||
UpdateRepo() error
|
||||
}
|
||||
|
||||
|
|
@ -355,7 +356,7 @@ func (st *HelmState) SyncRepos(helm RepoUpdater, shouldSkip map[string]bool) ([]
|
|||
continue
|
||||
}
|
||||
|
||||
if err := helm.AddRepo(repo.Name, repo.URL, repo.CaFile, repo.CertFile, repo.KeyFile, repo.Username, repo.Password); err != nil {
|
||||
if err := helm.AddRepo(repo.Name, repo.URL, repo.CaFile, repo.CertFile, repo.KeyFile, repo.Username, repo.Password, repo.Managed); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -857,7 +857,18 @@ func TestHelmState_SyncRepos(t *testing.T) {
|
|||
},
|
||||
},
|
||||
helm: &exectest.Helm{},
|
||||
want: []string{"name", "http://example.com/", "", "", "", "", ""},
|
||||
want: []string{"name", "http://example.com/", "", "", "", "", "", ""},
|
||||
},
|
||||
{
|
||||
name: "ACR hosted repository",
|
||||
repos: []RepositorySpec{
|
||||
{
|
||||
Name: "name",
|
||||
Managed: "acr",
|
||||
},
|
||||
},
|
||||
helm: &exectest.Helm{},
|
||||
want: []string{"name", "", "", "", "", "", "", "acr"},
|
||||
},
|
||||
{
|
||||
name: "repository with cert and key",
|
||||
|
|
@ -872,7 +883,7 @@ func TestHelmState_SyncRepos(t *testing.T) {
|
|||
},
|
||||
},
|
||||
helm: &exectest.Helm{},
|
||||
want: []string{"name", "http://example.com/", "", "certfile", "keyfile", "", ""},
|
||||
want: []string{"name", "http://example.com/", "", "certfile", "keyfile", "", "", ""},
|
||||
},
|
||||
{
|
||||
name: "repository with ca file",
|
||||
|
|
@ -886,7 +897,7 @@ func TestHelmState_SyncRepos(t *testing.T) {
|
|||
},
|
||||
},
|
||||
helm: &exectest.Helm{},
|
||||
want: []string{"name", "http://example.com/", "cafile", "", "", "", ""},
|
||||
want: []string{"name", "http://example.com/", "cafile", "", "", "", "", ""},
|
||||
},
|
||||
{
|
||||
name: "repository with username and password",
|
||||
|
|
@ -901,7 +912,7 @@ func TestHelmState_SyncRepos(t *testing.T) {
|
|||
},
|
||||
},
|
||||
helm: &exectest.Helm{},
|
||||
want: []string{"name", "http://example.com/", "", "", "", "example_user", "example_password"},
|
||||
want: []string{"name", "http://example.com/", "", "", "", "example_user", "example_password", ""},
|
||||
},
|
||||
}
|
||||
for i := range tests {
|
||||
|
|
|
|||
Loading…
Reference in New Issue