Skip to content

client: export config and credential functionalities to 3rd parties#30817

Closed
AkihiroSuda wants to merge 2 commits intomoby:masterfrom
AkihiroSuda:move-config
Closed

client: export config and credential functionalities to 3rd parties#30817
AkihiroSuda wants to merge 2 commits intomoby:masterfrom
AkihiroSuda:move-config

Conversation

@AkihiroSuda
Copy link
Member

@AkihiroSuda AkihiroSuda commented Feb 8, 2017

- What I did

The github.com/docker/docker/client package should provide functions that are enough to "do anything the command-line interface does" for 3rd parties, as the README says.

However, some functions such as client.ImagePull() are not so useful, because the client package lacks functions for loading the client config and credentials configured with it.

So I added functions related to them to the client package.

- How I did it

Moved some packages and functions from the cli package to the client package.

  • Package client/config: moved from cli/config
  • Function client/clientutil.LoadDefaultConfigFile(): moved from cli/command/cli.go
  • Function client/clientutil.GetAllCredentials(): moved from cli/command/cli.go
  • Function client/clientutil.CredentialsStore(): moved from cli/command/cli.go
  • Function client/clientutil.ElectAuthServer(): moved from cli/command/registry.go
  • Function client/clientutil.EncodeAuthToBase64(): moved from cli/command/registry.go
  • Function client/clientutil.ResolveAuthConfig(): moved from cli/command/registry.go

- How to verify it
Prepare main.go like this:

package main

// make sure we don't need to import CLI-related packages here..
import (
        "context"
        "flag"
        "fmt"
        "os"

        "github.com/docker/distribution/reference"
        "github.com/docker/docker/api/types"
        "github.com/docker/docker/client"
        "github.com/docker/docker/client/clientutil"
        "github.com/docker/docker/pkg/jsonmessage"
        "github.com/docker/docker/registry"
)

// pullImageDumb is simple but dumb
func pullImageDumb(s string) error {
        cli, err := client.NewEnvClient()
        if err != nil {
                return err
        }
        responseBody, err := cli.ImagePull(context.TODO(), s, types.ImagePullOptions{})
        if err != nil {
                return err
        }
        defer responseBody.Close()
        return jsonmessage.DisplayJSONMessagesStream(responseBody, os.Stdout, os.Stdout.Fd(), true, nil)
}

// pullImageEx supports credential helpers.
// still too complicated... :-(
func pullImageEx(s string) error {
        distributionRef, err := reference.ParseNormalizedNamed(s)
        if err != nil {
                return err
        }
        repoInfo, err := registry.ParseRepositoryInfo(distributionRef)
        if err != nil {
                return err
        }
        cli, err := client.NewEnvClient()
        if err != nil {
                return err
        }
        cfg, err := clientutil.LoadDefaultConfigFile()
        if err != nil {
                return err
        }
        authConfig, err := clientutil.ResolveAuthConfig(context.TODO(), cli, cfg, repoInfo.Index)
        if err != nil {
                return err
        }
        encodedAuth, err := clientutil.EncodeAuthToBase64(authConfig)
        if err != nil {
                return err
        }
        responseBody, err := cli.ImagePull(context.TODO(), reference.FamiliarString(distributionRef), types.ImagePullOptions{
                RegistryAuth: encodedAuth,
        })
        if err != nil {
                return err
        }
        defer responseBody.Close()
        return jsonmessage.DisplayJSONMessagesStream(responseBody, os.Stdout, os.Stdout.Fd(), true, nil)
}

func main() {
        ex := flag.Bool("ex", false, "enables credential helpers")
        flag.Parse()
        img := flag.Args()[0]

        var err error
        if *ex {
                err = pullImageEx(img)
        } else {
                err = pullImageDumb(img)
        }

        if err != nil {
                fmt.Fprintf(os.Stderr, "%v\n", err)
                os.Exit(1)
        }
}

Without the new functions added in this PR, the program cannot pull an image that requires the credential.

$ ./a.out example.com/foo/bar:latest
Pulling repository example.com/foo/bar
Error: Status 403 trying to pull repository foo/bar: "Unable to access the repository: foo/bar; please verify that it exists and you have permission to access it (no valid credential was supplied)."

With the new functions (-ex), the program should be able to pull the image.

$ ./a.out -ex example.com/foo/bar:latest
Pulling repository example.com/foo/bar
...
aa2e67ada86f: Pull complete 
fa37c75ff5f0: Pull complete 
Digest: sha256:fce33cbd4e79c6b69c01445c2dd556016ae2e2a7926a6d60c395f86ef0aee765
Status: Downloaded newer image for example.com/foo/bar:latest

- Description for the changelog
client: export config and credential functionalities to 3rd parties

- A picture of a cute animal (not mandatory but encouraged)

2590009476
Signed-off-by: Akihiro Suda suda.akihiro@lab.ntt.co.jp

Signed-off-by: Akihiro Suda <suda.akihiro@lab.ntt.co.jp>
…y 3rd parties

Signed-off-by: Akihiro Suda <suda.akihiro@lab.ntt.co.jp>
@AkihiroSuda
Copy link
Member Author

@vdemeester PTAL?

@vdemeester
Copy link
Member

@AkihiroSuda @dnephin I wonder if this should go int docker/cli or ? 👼

@AkihiroSuda
Copy link
Member Author

yes closing

@AkihiroSuda AkihiroSuda closed this May 7, 2017
@AkihiroSuda
Copy link
Member Author

Reopening this PR, because client is no longer being moved to docker/cli.

Related: https://forums.mobyproject.org/t/go-client-and-pushing-to-a-restricted-registry/61.

@AkihiroSuda AkihiroSuda reopened this Jun 12, 2017
@AkihiroSuda
Copy link
Member Author

I'll rebase this PR if I can get SGTMs

@vdemeester @dnephin @dmcgowan

@vdemeester
Copy link
Member

@AkihiroSuda isn't this all in docker/cli now ? 👼

@AkihiroSuda
Copy link
Member Author

@vdemeester

client continues to exist under this repo, IIUC

@dnephin
Copy link
Member

dnephin commented Jun 12, 2017

Refactoring this code to make it easier for other consumers sounds great to me. However I don't think it belongs in the client/ package (and I'm generally not a fan of the name util for anything).

How about we keep this in the docker/cli repo? The code from registry.go could move to cli/registry/ and the other code could move to cli/config/ (or cli/config/configfile) with some small cleanup of the existing imports (dnephin/cli@f3e8309). Feel free to grab that commit if you want to fix the tangled imports in cli/config.

As long as everything is exported and isn't a method on the DockerCli struct, then it should be just as easy to use as the client/ package. The dependencies of cli/registry/ and cli/config should be pretty small. By keeping them separate anyone who doesn't need those pieces isn't forced to pull in a bunch more dependencies.

@vieux
Copy link
Contributor

vieux commented Jun 13, 2017

@AkihiroSuda should we open those changes to github.com/docker/cli

@AkihiroSuda
Copy link
Member Author

ok

@AkihiroSuda
Copy link
Member Author

WIP: https://github.com/docker/cli/compare/master...AkihiroSuda:config?expand=1
I'll open PR to docker/cli (probably) tomorrow

AkihiroSuda added a commit to AkihiroSuda/docker-cli that referenced this pull request Jun 15, 2017
Example: contrib/client-with-cli-config (but without whole cli)
See also moby/moby#30817

Signed-off-by: Akihiro Suda <suda.akihiro@lab.ntt.co.jp>
@AkihiroSuda
Copy link
Member Author

opened docker/cli#197

AkihiroSuda added a commit to AkihiroSuda/docker-cli that referenced this pull request Jun 15, 2017
Example: contrib/client-with-cli-config (but without whole cli)
See also moby/moby#30817

Signed-off-by: Akihiro Suda <suda.akihiro@lab.ntt.co.jp>
@AkihiroSuda
Copy link
Member Author

Note: this seems settled as docker/cli#227 (thank you @dnephin )

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants