From 508a96324af8cf3473ba5e8f7420f935b025259a Mon Sep 17 00:00:00 2001 From: Igor Ovsyannikov Date: Wed, 8 Sep 2021 02:34:28 +0300 Subject: [PATCH 1/2] docker: support for encoded_auth in deploy closes #2243 --- builtin/docker/platform.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/builtin/docker/platform.go b/builtin/docker/platform.go index c8aee1071fe..93e39d53782 100644 --- a/builtin/docker/platform.go +++ b/builtin/docker/platform.go @@ -718,6 +718,10 @@ func (p *Platform) pullImage(cli *client.Client, log hclog.Logger, ui terminal.U ipo := types.ImagePullOptions{} + if p.config.EncodedAuth != "" { + ipo.RegistryAuth = p.config.EncodedAuth + } + // if the username and password is not null make an authenticated // image pull /* @@ -812,6 +816,9 @@ type PlatformConfig struct { // TODO Evaluate if this should remain as a default 3000, should be a required field, // or default to another port. ServicePort uint `hcl:"service_port,optional"` + + // Same as encoded_auth for registry config + EncodedAuth string `hcl:"encoded_auth,optional"` } type ClientConfig struct { @@ -951,6 +958,15 @@ deploy { ), ) + doc.SetField( + "encoded_auth", + "authentication information for pulling images", + docs.Summary( + "Similar to `encoded_auth` field for registry -", + "base64-encoded JSON with fields `username` and `password`.", + ), + ) + return doc, nil } From e9e44bb65c2b582751bace8baa1864be12060ec5 Mon Sep 17 00:00:00 2001 From: Igor Ovsyannikov Date: Wed, 8 Sep 2021 23:25:35 +0300 Subject: [PATCH 2/2] docker: replace encoded_auth by normal registry block --- builtin/docker/platform.go | 28 +++++------- builtin/docker/registry_docker.go | 72 ++++++++++++++++++------------- 2 files changed, 53 insertions(+), 47 deletions(-) diff --git a/builtin/docker/platform.go b/builtin/docker/platform.go index 93e39d53782..dd306d75a68 100644 --- a/builtin/docker/platform.go +++ b/builtin/docker/platform.go @@ -406,7 +406,7 @@ func (p *Platform) resourceContainerCreate( netState *Resource_Network, ) error { // Pull the image - err := p.pullImage(cli, log, ui, img, p.config.ForcePull) + err := p.pullImage(cli, ctx, log, ui, img, p.config.ForcePull) if err != nil { return status.Errorf(codes.FailedPrecondition, "unable to pull image from Docker registry: %s", err) @@ -687,7 +687,7 @@ func (p *Platform) getDockerClient(ctx context.Context) (*client.Client, error) return cli, nil } -func (p *Platform) pullImage(cli *client.Client, log hclog.Logger, ui terminal.UI, img *Image, force bool) error { +func (p *Platform) pullImage(cli *client.Client, ctx context.Context, log hclog.Logger, ui terminal.UI, img *Image, force bool) error { in := fmt.Sprintf("%s:%s", img.Image, img.Tag) args := filters.NewArgs() args.Add("reference", in) @@ -718,10 +718,6 @@ func (p *Platform) pullImage(cli *client.Client, log hclog.Logger, ui terminal.U ipo := types.ImagePullOptions{} - if p.config.EncodedAuth != "" { - ipo.RegistryAuth = p.config.EncodedAuth - } - // if the username and password is not null make an authenticated // image pull /* @@ -737,6 +733,14 @@ func (p *Platform) pullImage(cli *client.Client, log hclog.Logger, ui terminal.U in = named.Name() + dockerReg := &Registry{} + creds, err := dockerReg.findAuth(named, cli, ctx, log) + if err != nil { + return status.Errorf(codes.Internal, "failed to get docker auth: %s", err) + } + + ipo.RegistryAuth = creds + log.Debug("pulling image", "image", in) out, err := cli.ImagePull(context.Background(), in, ipo) @@ -816,9 +820,6 @@ type PlatformConfig struct { // TODO Evaluate if this should remain as a default 3000, should be a required field, // or default to another port. ServicePort uint `hcl:"service_port,optional"` - - // Same as encoded_auth for registry config - EncodedAuth string `hcl:"encoded_auth,optional"` } type ClientConfig struct { @@ -958,15 +959,6 @@ deploy { ), ) - doc.SetField( - "encoded_auth", - "authentication information for pulling images", - docs.Summary( - "Similar to `encoded_auth` field for registry -", - "base64-encoded JSON with fields `username` and `password`.", - ), - ) - return doc, nil } diff --git a/builtin/docker/registry_docker.go b/builtin/docker/registry_docker.go index e3afd2d77c0..6c9eedb05d8 100644 --- a/builtin/docker/registry_docker.go +++ b/builtin/docker/registry_docker.go @@ -61,6 +61,45 @@ func (r *Registry) pushWithDocker( return status.Errorf(codes.Internal, "unable to parse image name: %s", err) } + encodedAuth, err := r.findAuth(ref, cli, ctx, log) + if err != nil { + return status.Errorf(codes.Internal, "unable to extract registry credentials: %s", err) + } + + + step = sg.Add("Pushing Docker image...") + + options := types.ImagePushOptions{ + RegistryAuth: encodedAuth, + } + + responseBody, err := cli.ImagePush(ctx, reference.FamiliarString(ref), options) + if err != nil { + return status.Errorf(codes.Internal, "unable to push image to registry: %s", err) + } + + defer responseBody.Close() + + var termFd uintptr + if f, ok := stdout.(*os.File); ok { + termFd = f.Fd() + } + + err = jsonmessage.DisplayJSONMessagesStream(responseBody, step.TermOutput(), termFd, true, nil) + if err != nil { + return status.Errorf(codes.Internal, "unable to stream Docker logs to terminal: %s", err) + } + + step.Done() + return nil +} + +func (r *Registry) findAuth( + ref reference.Named, + cli *client.Client, + ctx context.Context, + log hclog.Logger, +) (string, error) { encodedAuth := r.config.EncodedAuth // If there was no explicit encoded auth but there is a password, make the username+password @@ -73,7 +112,7 @@ func (r *Registry) pushWithDocker( buf, err := json.Marshal(authConfig) if err != nil { - return status.Errorf(codes.Internal, "unable to generate authentication info for registry: %s", err) + return "", status.Errorf(codes.Internal, "unable to generate authentication info for registry: %s", err) } encodedAuth = base64.URLEncoding.EncodeToString(buf) } @@ -83,7 +122,7 @@ func (r *Registry) pushWithDocker( // Resolve the Repository name from fqn to RepositoryInfo repoInfo, err := registry.ParseRepositoryInfo(ref) if err != nil { - return status.Errorf(codes.Internal, "unable to parse repository info from image name: %s", err) + return "", status.Errorf(codes.Internal, "unable to parse repository info from image name: %s", err) } var server string @@ -109,34 +148,9 @@ func (r *Registry) pushWithDocker( authConfig, _ := cf.GetAuthConfig(server) buf, err := json.Marshal(authConfig) if err != nil { - return status.Errorf(codes.Internal, "unable to generate authentication info for registry: %s", err) + return "", status.Errorf(codes.Internal, "unable to generate authentication info for registry: %s", err) } encodedAuth = base64.URLEncoding.EncodeToString(buf) } - - step = sg.Add("Pushing Docker image...") - - options := types.ImagePushOptions{ - RegistryAuth: encodedAuth, - } - - responseBody, err := cli.ImagePush(ctx, reference.FamiliarString(ref), options) - if err != nil { - return status.Errorf(codes.Internal, "unable to push image to registry: %s", err) - } - - defer responseBody.Close() - - var termFd uintptr - if f, ok := stdout.(*os.File); ok { - termFd = f.Fd() - } - - err = jsonmessage.DisplayJSONMessagesStream(responseBody, step.TermOutput(), termFd, true, nil) - if err != nil { - return status.Errorf(codes.Internal, "unable to stream Docker logs to terminal: %s", err) - } - - step.Done() - return nil + return encodedAuth, nil }