Skip to content

Commit

Permalink
Fix registry auth phasing and image retagging (#88)
Browse files Browse the repository at this point in the history
  • Loading branch information
jnummelin authored May 26, 2020
1 parent b6d4144 commit 752dc3a
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 10 deletions.
20 changes: 20 additions & 0 deletions examples/footloose/cluster_custom_imagerepo.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
apiVersion: "launchpad.mirantis.com/v1beta1"
kind: UCP
spec:
hosts:
- address: "127.0.0.1"
sshPort: 9022
user: "root"
role: "manager"
- address: "127.0.0.1"
sshPort: 9023
user: "root"
role: "worker"
ucp:
version: 3.3.0-rc4
# Use custom image repo, remember to set the REGISTRY_USERNAME & REGISTRY_PASSWORD envs
imageRepo: docker.io/dockereng
installFlags:
- --admin-username=admin
- --admin-password=orcaorcaorca
- --default-node-orchestrator=kubernetes
2 changes: 2 additions & 0 deletions examples/footloose/footloose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ machines:
hostPort: 9022
- containerPort: 443
hostPort: 443
- containerPort: 6443
hostPort: 6443
- count: 1
backend: docker
spec:
Expand Down
7 changes: 4 additions & 3 deletions pkg/apis/v1beta1/hosts.go
Original file line number Diff line number Diff line change
Expand Up @@ -221,16 +221,17 @@ func trimOutput(output []byte) string {

// AuthenticateDocker performs a docker login on the host using local REGISTRY_USERNAME
// and REGISTRY_PASSWORD when set
func (h *Host) AuthenticateDocker(server string) error {
func (h *Host) AuthenticateDocker(imageRepo string) error {
if user := os.Getenv("REGISTRY_USERNAME"); user != "" {
pass := os.Getenv("REGISTRY_PASSWORD")
if pass == "" {
return fmt.Errorf("%s: REGISTRY_PASSWORD not set", h.Address)
}
log.Infof("%s: authenticating docker", h.Address)

log.Infof("%s: authenticating docker for image repo %s", h.Address, imageRepo)
old := log.GetLevel()
log.SetLevel(log.ErrorLevel)
err := h.ExecCmd(h.Configurer.DockerCommandf("login -u %s --password-stdin %s", user, server), pass, false, true)
err := h.ExecCmd(h.Configurer.DockerCommandf("login -u %s --password-stdin %s", user, imageRepo), pass, false, true)
log.SetLevel(old)

if err != nil {
Expand Down
5 changes: 5 additions & 0 deletions pkg/apis/v1beta1/ucp_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,8 @@ func NewUcpConfig() UcpConfig {
func (c *UcpConfig) GetBootstrapperImage() string {
return fmt.Sprintf("%s/ucp:%s", c.ImageRepo, c.Version)
}

// IsCustomImageRepo checks if the config is using a custom image repo
func (c *UcpConfig) IsCustomImageRepo() bool {
return c.ImageRepo != constant.ImageRepo
}
6 changes: 6 additions & 0 deletions pkg/phase/install_ucp.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@ func (p *InstallUCP) Run(config *api.ClusterConfig) error {
}
installFlags = append(installFlags, fmt.Sprintf("--license '%s'", string(license)))
}

if config.Spec.Ucp.IsCustomImageRepo() {
// In case of custom repo, don't let UCP to check the images
installFlags = append(installFlags, "--pull never")
}

flags := strings.Join(installFlags, " ")
installCmd := swarmLeader.Configurer.DockerCommandf("run --rm -i -v /var/run/docker.sock:/var/run/docker.sock %s install %s", image, flags)
err := swarmLeader.ExecCmd(installCmd, "", true, true)
Expand Down
46 changes: 39 additions & 7 deletions pkg/phase/pull_images.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,23 +20,41 @@ func (p *PullImages) Title() string {
// Run pulls all the needed images on managers in parallel.
// Parallel on each host and pulls 5 images at a time on each host.
func (p *PullImages) Run(c *api.ClusterConfig) error {
images, err := p.listImages(c)
if err != nil {
return NewError(err.Error())
}
log.Debugf("loaded images list: %v", images)

err = runParallelOnHosts(c.Spec.Hosts, c, func(h *api.Host, c *api.ClusterConfig) error {
err := runParallelOnHosts(c.Spec.Hosts, c, func(h *api.Host, c *api.ClusterConfig) error {
return h.AuthenticateDocker(c.Spec.Ucp.ImageRepo)
})

if err != nil {
return err
}
images, err := p.listImages(c)
if err != nil {
return NewError(err.Error())
}
log.Debugf("loaded images list: %v", images)

if c.Spec.Ucp.IsCustomImageRepo() {
// Store map of original --> custom repo images
imageMap := make(map[string]string, len(images))
for index, i := range images {
newImage := strings.Replace(i, "docker/", fmt.Sprintf("%s/", c.Spec.Ucp.ImageRepo), 1)
imageMap[i] = newImage
images[index] = newImage
}
// In case of custom image repo, we need to pull and retag all the images on all hosts
return runParallelOnHosts(c.Spec.Hosts, c, func(h *api.Host, c *api.ClusterConfig) error {
err := p.pullImages(h, images)
if err != nil {
return err
}
return p.retagImages(h, imageMap)
})
}
// Normally we pull only on managers, let workers pull needed stuff on-demand
return runParallelOnHosts(c.Spec.Managers(), c, func(h *api.Host, c *api.ClusterConfig) error {
return p.pullImages(h, images)
})

}

func (p *PullImages) listImages(config *api.ClusterConfig) ([]string, error) {
Expand Down Expand Up @@ -72,3 +90,17 @@ func (p *PullImages) pullImages(host *api.Host, images []string) error {
}
return nil
}

func (p *PullImages) retagImages(host *api.Host, imageMap map[string]string) error {

for dockerImage, realImage := range imageMap {
retagCmd := host.Configurer.DockerCommandf("tag %s %s", realImage, dockerImage)
log.Debugf("%s: retag %s --> %s", host.Address, realImage, dockerImage)
_, err := host.ExecWithOutput(retagCmd)
if err != nil {
return err
}
}

return nil
}

0 comments on commit 752dc3a

Please sign in to comment.