mirror of https://github.com/docker/cli.git
Merge pull request #562 from dnephin/update-gometalinter
Update gometalinter
This commit is contained in:
commit
feb4d79935
|
@ -185,6 +185,7 @@ func setRawTerminal(streams command.Streams) error {
|
||||||
return streams.Out().SetRawTerminal()
|
return streams.Out().SetRawTerminal()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// nolint: unparam
|
||||||
func restoreTerminal(streams command.Streams, in io.Closer) error {
|
func restoreTerminal(streams command.Streams, in io.Closer) error {
|
||||||
streams.In().RestoreTerminal()
|
streams.In().RestoreTerminal()
|
||||||
streams.Out().RestoreTerminal()
|
streams.Out().RestoreTerminal()
|
||||||
|
|
|
@ -43,6 +43,7 @@ func TestValidateAttach(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// nolint: unparam
|
||||||
func parseRun(args []string) (*container.Config, *container.HostConfig, *networktypes.NetworkingConfig, error) {
|
func parseRun(args []string) (*container.Config, *container.HostConfig, *networktypes.NetworkingConfig, error) {
|
||||||
flags := pflag.NewFlagSet("run", pflag.ContinueOnError)
|
flags := pflag.NewFlagSet("run", pflag.ContinueOnError)
|
||||||
flags.SetOutput(ioutil.Discard)
|
flags.SetOutput(ioutil.Discard)
|
||||||
|
|
|
@ -6,8 +6,8 @@ import (
|
||||||
|
|
||||||
"github.com/docker/cli/cli"
|
"github.com/docker/cli/cli"
|
||||||
"github.com/docker/cli/cli/command"
|
"github.com/docker/cli/cli/command"
|
||||||
|
"github.com/docker/cli/cli/trust"
|
||||||
"github.com/docker/distribution/reference"
|
"github.com/docker/distribution/reference"
|
||||||
"github.com/docker/docker/registry"
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
|
@ -40,11 +40,14 @@ func NewPullCommand(dockerCli command.Cli) *cobra.Command {
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func runPull(dockerCli command.Cli, opts pullOptions) error {
|
func runPull(cli command.Cli, opts pullOptions) error {
|
||||||
distributionRef, err := reference.ParseNormalizedNamed(opts.remote)
|
ctx := context.Background()
|
||||||
|
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, AuthResolver(cli), opts.remote)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
distributionRef := imgRefAndAuth.Reference()
|
||||||
if opts.all && !reference.IsNameOnly(distributionRef) {
|
if opts.all && !reference.IsNameOnly(distributionRef) {
|
||||||
return errors.New("tag can't be used with --all-tags/-a")
|
return errors.New("tag can't be used with --all-tags/-a")
|
||||||
}
|
}
|
||||||
|
@ -52,27 +55,16 @@ func runPull(dockerCli command.Cli, opts pullOptions) error {
|
||||||
if !opts.all && reference.IsNameOnly(distributionRef) {
|
if !opts.all && reference.IsNameOnly(distributionRef) {
|
||||||
distributionRef = reference.TagNameOnly(distributionRef)
|
distributionRef = reference.TagNameOnly(distributionRef)
|
||||||
if tagged, ok := distributionRef.(reference.Tagged); ok {
|
if tagged, ok := distributionRef.(reference.Tagged); ok {
|
||||||
fmt.Fprintf(dockerCli.Out(), "Using default tag: %s\n", tagged.Tag())
|
fmt.Fprintf(cli.Out(), "Using default tag: %s\n", tagged.Tag())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resolve the Repository name from fqn to RepositoryInfo
|
|
||||||
repoInfo, err := registry.ParseRepositoryInfo(distributionRef)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx := context.Background()
|
|
||||||
|
|
||||||
authConfig := command.ResolveAuthConfig(ctx, dockerCli, repoInfo.Index)
|
|
||||||
requestPrivilege := command.RegistryAuthenticationPrivilegedFunc(dockerCli, repoInfo.Index, "pull")
|
|
||||||
|
|
||||||
// Check if reference has a digest
|
// Check if reference has a digest
|
||||||
_, isCanonical := distributionRef.(reference.Canonical)
|
_, isCanonical := distributionRef.(reference.Canonical)
|
||||||
if command.IsTrusted() && !isCanonical {
|
if command.IsTrusted() && !isCanonical {
|
||||||
err = trustedPull(ctx, dockerCli, repoInfo, distributionRef, authConfig, requestPrivilege)
|
err = trustedPull(ctx, cli, imgRefAndAuth)
|
||||||
} else {
|
} else {
|
||||||
err = imagePullPrivileged(ctx, dockerCli, authConfig, reference.FamiliarString(distributionRef), requestPrivilege, opts.all)
|
err = imagePullPrivileged(ctx, cli, imgRefAndAuth, opts.all)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if strings.Contains(err.Error(), "when fetching 'plugin'") {
|
if strings.Contains(err.Error(), "when fetching 'plugin'") {
|
||||||
|
@ -80,6 +72,5 @@ func runPull(dockerCli command.Cli, opts pullOptions) error {
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,11 +32,6 @@ func TestNewPullCommandErrors(t *testing.T) {
|
||||||
expectedError: "tag can't be used with --all-tags/-a",
|
expectedError: "tag can't be used with --all-tags/-a",
|
||||||
args: []string{"--all-tags", "image:tag"},
|
args: []string{"--all-tags", "image:tag"},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: "pull-error",
|
|
||||||
args: []string{"--disable-content-trust=false", "image:tag"},
|
|
||||||
expectedError: "you are not authorized to perform this operation: server returned 401.",
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
cli := test.NewFakeCli(&fakeClient{})
|
cli := test.NewFakeCli(&fakeClient{})
|
||||||
|
|
|
@ -11,11 +11,12 @@ import (
|
||||||
"github.com/docker/cli/cli/trust"
|
"github.com/docker/cli/cli/trust"
|
||||||
"github.com/docker/distribution/reference"
|
"github.com/docker/distribution/reference"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
|
registrytypes "github.com/docker/docker/api/types/registry"
|
||||||
"github.com/docker/docker/pkg/jsonmessage"
|
"github.com/docker/docker/pkg/jsonmessage"
|
||||||
"github.com/docker/docker/registry"
|
"github.com/docker/docker/registry"
|
||||||
"github.com/docker/notary/client"
|
"github.com/docker/notary/client"
|
||||||
"github.com/docker/notary/tuf/data"
|
"github.com/docker/notary/tuf/data"
|
||||||
"github.com/opencontainers/go-digest"
|
digest "github.com/opencontainers/go-digest"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
|
@ -181,57 +182,13 @@ func imagePushPrivileged(ctx context.Context, cli command.Cli, authConfig types.
|
||||||
}
|
}
|
||||||
|
|
||||||
// trustedPull handles content trust pulling of an image
|
// trustedPull handles content trust pulling of an image
|
||||||
func trustedPull(ctx context.Context, cli command.Cli, repoInfo *registry.RepositoryInfo, ref reference.Named, authConfig types.AuthConfig, requestPrivilege types.RequestPrivilegeFunc) error {
|
func trustedPull(ctx context.Context, cli command.Cli, imgRefAndAuth trust.ImageRefAndAuth) error {
|
||||||
var refs []target
|
refs, err := getTrustedPullTargets(cli, imgRefAndAuth)
|
||||||
|
|
||||||
notaryRepo, err := trust.GetNotaryRepository(cli.In(), cli.Out(), command.UserAgent(), repoInfo, &authConfig, "pull")
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(cli.Out(), "Error establishing connection to trust repository: %s\n", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if tagged, isTagged := ref.(reference.NamedTagged); !isTagged {
|
|
||||||
// List all targets
|
|
||||||
targets, err := notaryRepo.ListTargets(trust.ReleasesRole, data.CanonicalTargetsRole)
|
|
||||||
if err != nil {
|
|
||||||
return trust.NotaryError(ref.Name(), err)
|
|
||||||
}
|
|
||||||
for _, tgt := range targets {
|
|
||||||
t, err := convertTarget(tgt.Target)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(cli.Out(), "Skipping target for %q\n", reference.FamiliarName(ref))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// Only list tags in the top level targets role or the releases delegation role - ignore
|
|
||||||
// all other delegation roles
|
|
||||||
if tgt.Role != trust.ReleasesRole && tgt.Role != data.CanonicalTargetsRole {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
refs = append(refs, t)
|
|
||||||
}
|
|
||||||
if len(refs) == 0 {
|
|
||||||
return trust.NotaryError(ref.Name(), errors.Errorf("No trusted tags for %s", ref.Name()))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
t, err := notaryRepo.GetTargetByName(tagged.Tag(), trust.ReleasesRole, data.CanonicalTargetsRole)
|
|
||||||
if err != nil {
|
|
||||||
return trust.NotaryError(ref.Name(), err)
|
|
||||||
}
|
|
||||||
// Only get the tag if it's in the top level targets role or the releases delegation role
|
|
||||||
// ignore it if it's in any other delegation roles
|
|
||||||
if t.Role != trust.ReleasesRole && t.Role != data.CanonicalTargetsRole {
|
|
||||||
return trust.NotaryError(ref.Name(), errors.Errorf("No trust data for %s", tagged.Tag()))
|
|
||||||
}
|
|
||||||
|
|
||||||
logrus.Debugf("retrieving target for %s role\n", t.Role)
|
|
||||||
r, err := convertTarget(t.Target)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
||||||
}
|
|
||||||
refs = append(refs, r)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ref := imgRefAndAuth.Reference()
|
||||||
for i, r := range refs {
|
for i, r := range refs {
|
||||||
displayTag := r.name
|
displayTag := r.name
|
||||||
if displayTag != "" {
|
if displayTag != "" {
|
||||||
|
@ -243,7 +200,7 @@ func trustedPull(ctx context.Context, cli command.Cli, repoInfo *registry.Reposi
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := imagePullPrivileged(ctx, cli, authConfig, reference.FamiliarString(trustedRef), requestPrivilege, false); err != nil {
|
if err := imagePullPrivileged(ctx, cli, imgRefAndAuth, false); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,13 +216,65 @@ func trustedPull(ctx context.Context, cli command.Cli, repoInfo *registry.Reposi
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// imagePullPrivileged pulls the image and displays it to the output
|
func getTrustedPullTargets(cli command.Cli, imgRefAndAuth trust.ImageRefAndAuth) ([]target, error) {
|
||||||
func imagePullPrivileged(ctx context.Context, cli command.Cli, authConfig types.AuthConfig, ref string, requestPrivilege types.RequestPrivilegeFunc, all bool) error {
|
notaryRepo, err := cli.NotaryClient(imgRefAndAuth, trust.ActionsPullOnly)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(cli.Out(), "Error establishing connection to trust repository: %s\n", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
encodedAuth, err := command.EncodeAuthToBase64(authConfig)
|
ref := imgRefAndAuth.Reference()
|
||||||
|
tagged, isTagged := ref.(reference.NamedTagged)
|
||||||
|
if !isTagged {
|
||||||
|
// List all targets
|
||||||
|
targets, err := notaryRepo.ListTargets(trust.ReleasesRole, data.CanonicalTargetsRole)
|
||||||
|
if err != nil {
|
||||||
|
return nil, trust.NotaryError(ref.Name(), err)
|
||||||
|
}
|
||||||
|
var refs []target
|
||||||
|
for _, tgt := range targets {
|
||||||
|
t, err := convertTarget(tgt.Target)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(cli.Out(), "Skipping target for %q\n", reference.FamiliarName(ref))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Only list tags in the top level targets role or the releases delegation role - ignore
|
||||||
|
// all other delegation roles
|
||||||
|
if tgt.Role != trust.ReleasesRole && tgt.Role != data.CanonicalTargetsRole {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
refs = append(refs, t)
|
||||||
|
}
|
||||||
|
if len(refs) == 0 {
|
||||||
|
return nil, trust.NotaryError(ref.Name(), errors.Errorf("No trusted tags for %s", ref.Name()))
|
||||||
|
}
|
||||||
|
return refs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
t, err := notaryRepo.GetTargetByName(tagged.Tag(), trust.ReleasesRole, data.CanonicalTargetsRole)
|
||||||
|
if err != nil {
|
||||||
|
return nil, trust.NotaryError(ref.Name(), err)
|
||||||
|
}
|
||||||
|
// Only get the tag if it's in the top level targets role or the releases delegation role
|
||||||
|
// ignore it if it's in any other delegation roles
|
||||||
|
if t.Role != trust.ReleasesRole && t.Role != data.CanonicalTargetsRole {
|
||||||
|
return nil, trust.NotaryError(ref.Name(), errors.Errorf("No trust data for %s", tagged.Tag()))
|
||||||
|
}
|
||||||
|
|
||||||
|
logrus.Debugf("retrieving target for %s role\n", t.Role)
|
||||||
|
r, err := convertTarget(t.Target)
|
||||||
|
return []target{r}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// imagePullPrivileged pulls the image and displays it to the output
|
||||||
|
func imagePullPrivileged(ctx context.Context, cli command.Cli, imgRefAndAuth trust.ImageRefAndAuth, all bool) error {
|
||||||
|
ref := reference.FamiliarString(imgRefAndAuth.Reference())
|
||||||
|
|
||||||
|
encodedAuth, err := command.EncodeAuthToBase64(*imgRefAndAuth.AuthConfig())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
requestPrivilege := command.RegistryAuthenticationPrivilegedFunc(cli, imgRefAndAuth.RepoInfo().Index, "pull")
|
||||||
options := types.ImagePullOptions{
|
options := types.ImagePullOptions{
|
||||||
RegistryAuth: encodedAuth,
|
RegistryAuth: encodedAuth,
|
||||||
PrivilegeFunc: requestPrivilege,
|
PrivilegeFunc: requestPrivilege,
|
||||||
|
@ -346,3 +355,10 @@ func TagTrusted(ctx context.Context, cli command.Cli, trustedRef reference.Canon
|
||||||
|
|
||||||
return cli.Client().ImageTag(ctx, trustedFamiliarRef, familiarRef)
|
return cli.Client().ImageTag(ctx, trustedFamiliarRef, familiarRef)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AuthResolver returns an auth resolver function from a command.Cli
|
||||||
|
func AuthResolver(cli command.Cli) func(ctx context.Context, index *registrytypes.IndexInfo) types.AuthConfig {
|
||||||
|
return func(ctx context.Context, index *registrytypes.IndexInfo) types.AuthConfig {
|
||||||
|
return command.ResolveAuthConfig(ctx, cli, index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
"github.com/docker/notary/passphrase"
|
"github.com/docker/notary/passphrase"
|
||||||
"github.com/docker/notary/trustpinning"
|
"github.com/docker/notary/trustpinning"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func unsetENV() {
|
func unsetENV() {
|
||||||
|
@ -67,6 +68,7 @@ func TestAddTargetToAllSignableRolesError(t *testing.T) {
|
||||||
defer os.RemoveAll(tmpDir)
|
defer os.RemoveAll(tmpDir)
|
||||||
|
|
||||||
notaryRepo, err := client.NewFileCachedRepository(tmpDir, "gun", "https://localhost", nil, passphrase.ConstantRetriever("password"), trustpinning.TrustPinConfig{})
|
notaryRepo, err := client.NewFileCachedRepository(tmpDir, "gun", "https://localhost", nil, passphrase.ConstantRetriever("password"), trustpinning.TrustPinConfig{})
|
||||||
|
require.NoError(t, err)
|
||||||
target := client.Target{}
|
target := client.Target{}
|
||||||
err = AddTargetToAllSignableRoles(notaryRepo, &target)
|
err = AddTargetToAllSignableRoles(notaryRepo, &target)
|
||||||
assert.EqualError(t, err, "client is offline")
|
assert.EqualError(t, err, "client is offline")
|
||||||
|
|
|
@ -104,13 +104,12 @@ func checkDaemonIsSwarmManager(ctx context.Context, dockerCli command.Cli) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// pruneServices removes services that are no longer referenced in the source
|
// pruneServices removes services that are no longer referenced in the source
|
||||||
func pruneServices(ctx context.Context, dockerCli command.Cli, namespace convert.Namespace, services map[string]struct{}) bool {
|
func pruneServices(ctx context.Context, dockerCli command.Cli, namespace convert.Namespace, services map[string]struct{}) {
|
||||||
client := dockerCli.Client()
|
client := dockerCli.Client()
|
||||||
|
|
||||||
oldServices, err := getServices(ctx, client, namespace.Name())
|
oldServices, err := getServices(ctx, client, namespace.Name())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(dockerCli.Err(), "Failed to list services: %s", err)
|
fmt.Fprintf(dockerCli.Err(), "Failed to list services: %s", err)
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pruneServices := []swarm.Service{}
|
pruneServices := []swarm.Service{}
|
||||||
|
@ -119,5 +118,5 @@ func pruneServices(ctx context.Context, dockerCli command.Cli, namespace convert
|
||||||
pruneServices = append(pruneServices, service)
|
pruneServices = append(pruneServices, service)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return removeServices(ctx, dockerCli, pruneServices)
|
removeServices(ctx, dockerCli, pruneServices)
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,6 +59,7 @@ func TestStackPsEmptyStack(t *testing.T) {
|
||||||
})
|
})
|
||||||
cmd := newPsCommand(fakeCli)
|
cmd := newPsCommand(fakeCli)
|
||||||
cmd.SetArgs([]string{"foo"})
|
cmd.SetArgs([]string{"foo"})
|
||||||
|
cmd.SetOutput(ioutil.Discard)
|
||||||
|
|
||||||
assert.Error(t, cmd.Execute())
|
assert.Error(t, cmd.Execute())
|
||||||
assert.EqualError(t, cmd.Execute(), "nothing found in stack: foo")
|
assert.EqualError(t, cmd.Execute(), "nothing found in stack: foo")
|
||||||
|
|
|
@ -15,24 +15,20 @@ import (
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
)
|
)
|
||||||
|
|
||||||
type unlockOptions struct{}
|
|
||||||
|
|
||||||
func newUnlockCommand(dockerCli command.Cli) *cobra.Command {
|
func newUnlockCommand(dockerCli command.Cli) *cobra.Command {
|
||||||
opts := unlockOptions{}
|
|
||||||
|
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "unlock",
|
Use: "unlock",
|
||||||
Short: "Unlock swarm",
|
Short: "Unlock swarm",
|
||||||
Args: cli.NoArgs,
|
Args: cli.NoArgs,
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
return runUnlock(dockerCli, opts)
|
return runUnlock(dockerCli)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func runUnlock(dockerCli command.Cli, opts unlockOptions) error {
|
func runUnlock(dockerCli command.Cli) error {
|
||||||
client := dockerCli.Client()
|
client := dockerCli.Client()
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
|
|
|
@ -5,15 +5,13 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/cli/cli"
|
||||||
registrytypes "github.com/docker/docker/api/types/registry"
|
"github.com/docker/cli/cli/command"
|
||||||
|
"github.com/docker/cli/cli/command/image"
|
||||||
|
"github.com/docker/cli/cli/trust"
|
||||||
"github.com/docker/notary/client"
|
"github.com/docker/notary/client"
|
||||||
"github.com/docker/notary/tuf/data"
|
"github.com/docker/notary/tuf/data"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
"github.com/docker/cli/cli"
|
|
||||||
"github.com/docker/cli/cli/command"
|
|
||||||
"github.com/docker/cli/cli/trust"
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -38,10 +36,7 @@ func newRevokeCommand(dockerCli command.Cli) *cobra.Command {
|
||||||
|
|
||||||
func revokeTrust(cli command.Cli, remote string, options revokeOptions) error {
|
func revokeTrust(cli command.Cli, remote string, options revokeOptions) error {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
authResolver := func(ctx context.Context, index *registrytypes.IndexInfo) types.AuthConfig {
|
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, image.AuthResolver(cli), remote)
|
||||||
return command.ResolveAuthConfig(ctx, cli, index)
|
|
||||||
}
|
|
||||||
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, authResolver, remote)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -57,7 +52,7 @@ func revokeTrust(cli command.Cli, remote string, options revokeOptions) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
notaryRepo, err := cli.NotaryClient(*imgRefAndAuth, trust.ActionsPushAndPull)
|
notaryRepo, err := cli.NotaryClient(imgRefAndAuth, trust.ActionsPushAndPull)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"github.com/docker/notary/passphrase"
|
"github.com/docker/notary/passphrase"
|
||||||
"github.com/docker/notary/trustpinning"
|
"github.com/docker/notary/trustpinning"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestTrustRevokeCommandErrors(t *testing.T) {
|
func TestTrustRevokeCommandErrors(t *testing.T) {
|
||||||
|
@ -140,6 +141,7 @@ func TestGetSignableRolesForTargetAndRemoveError(t *testing.T) {
|
||||||
defer os.RemoveAll(tmpDir)
|
defer os.RemoveAll(tmpDir)
|
||||||
|
|
||||||
notaryRepo, err := client.NewFileCachedRepository(tmpDir, "gun", "https://localhost", nil, passphrase.ConstantRetriever("password"), trustpinning.TrustPinConfig{})
|
notaryRepo, err := client.NewFileCachedRepository(tmpDir, "gun", "https://localhost", nil, passphrase.ConstantRetriever("password"), trustpinning.TrustPinConfig{})
|
||||||
|
require.NoError(t, err)
|
||||||
target := client.Target{}
|
target := client.Target{}
|
||||||
err = getSignableRolesForTargetAndRemove(target, notaryRepo)
|
err = getSignableRolesForTargetAndRemove(target, notaryRepo)
|
||||||
assert.EqualError(t, err, "client is offline")
|
assert.EqualError(t, err, "client is offline")
|
||||||
|
|
|
@ -3,6 +3,7 @@ package trust
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"path"
|
"path"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -11,8 +12,6 @@ import (
|
||||||
"github.com/docker/cli/cli/command"
|
"github.com/docker/cli/cli/command"
|
||||||
"github.com/docker/cli/cli/command/image"
|
"github.com/docker/cli/cli/command/image"
|
||||||
"github.com/docker/cli/cli/trust"
|
"github.com/docker/cli/cli/trust"
|
||||||
"github.com/docker/docker/api/types"
|
|
||||||
registrytypes "github.com/docker/docker/api/types/registry"
|
|
||||||
"github.com/docker/notary/client"
|
"github.com/docker/notary/client"
|
||||||
"github.com/docker/notary/tuf/data"
|
"github.com/docker/notary/tuf/data"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
@ -25,30 +24,23 @@ func newSignCommand(dockerCli command.Cli) *cobra.Command {
|
||||||
Short: "Sign an image",
|
Short: "Sign an image",
|
||||||
Args: cli.ExactArgs(1),
|
Args: cli.ExactArgs(1),
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
return signImage(dockerCli, args[0])
|
return runSignImage(dockerCli, args[0])
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func signImage(cli command.Cli, imageName string) error {
|
func runSignImage(cli command.Cli, imageName string) error {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
authResolver := func(ctx context.Context, index *registrytypes.IndexInfo) types.AuthConfig {
|
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, image.AuthResolver(cli), imageName)
|
||||||
return command.ResolveAuthConfig(ctx, cli, index)
|
|
||||||
}
|
|
||||||
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, authResolver, imageName)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
tag := imgRefAndAuth.Tag()
|
if err := validateTag(imgRefAndAuth); err != nil {
|
||||||
if tag == "" {
|
return err
|
||||||
if imgRefAndAuth.Digest() != "" {
|
|
||||||
return fmt.Errorf("cannot use a digest reference for IMAGE:TAG")
|
|
||||||
}
|
|
||||||
return fmt.Errorf("No tag specified for %s", imageName)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
notaryRepo, err := cli.NotaryClient(*imgRefAndAuth, trust.ActionsPushAndPull)
|
notaryRepo, err := cli.NotaryClient(imgRefAndAuth, trust.ActionsPushAndPull)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return trust.NotaryError(imgRefAndAuth.Reference().Name(), err)
|
return trust.NotaryError(imgRefAndAuth.Reference().Name(), err)
|
||||||
}
|
}
|
||||||
|
@ -78,7 +70,7 @@ func signImage(cli command.Cli, imageName string) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
requestPrivilege := command.RegistryAuthenticationPrivilegedFunc(cli, imgRefAndAuth.RepoInfo().Index, "push")
|
requestPrivilege := command.RegistryAuthenticationPrivilegedFunc(cli, imgRefAndAuth.RepoInfo().Index, "push")
|
||||||
target, err := createTarget(notaryRepo, tag)
|
target, err := createTarget(notaryRepo, imgRefAndAuth.Tag())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
switch err := err.(type) {
|
switch err := err.(type) {
|
||||||
case client.ErrNoSuchTarget, client.ErrRepositoryNotExist:
|
case client.ErrNoSuchTarget, client.ErrRepositoryNotExist:
|
||||||
|
@ -91,21 +83,36 @@ func signImage(cli command.Cli, imageName string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return signAndPublishToTarget(cli.Out(), imgRefAndAuth, notaryRepo, target)
|
||||||
|
}
|
||||||
|
|
||||||
fmt.Fprintf(cli.Out(), "Signing and pushing trust metadata for %s\n", imageName)
|
func signAndPublishToTarget(out io.Writer, imgRefAndAuth trust.ImageRefAndAuth, notaryRepo client.Repository, target client.Target) error {
|
||||||
|
tag := imgRefAndAuth.Tag()
|
||||||
|
fmt.Fprintf(out, "Signing and pushing trust metadata for %s\n", imgRefAndAuth.Name())
|
||||||
existingSigInfo, err := getExistingSignatureInfoForReleasedTag(notaryRepo, tag)
|
existingSigInfo, err := getExistingSignatureInfoForReleasedTag(notaryRepo, tag)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = image.AddTargetToAllSignableRoles(notaryRepo, &target)
|
err = image.AddTargetToAllSignableRoles(notaryRepo, &target)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
prettyPrintExistingSignatureInfo(cli, existingSigInfo)
|
prettyPrintExistingSignatureInfo(out, existingSigInfo)
|
||||||
err = notaryRepo.Publish()
|
err = notaryRepo.Publish()
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "failed to sign %q:%s", imgRefAndAuth.RepoInfo().Name.Name(), tag)
|
return errors.Wrapf(err, "failed to sign %q:%s", imgRefAndAuth.RepoInfo().Name.Name(), tag)
|
||||||
}
|
}
|
||||||
fmt.Fprintf(cli.Out(), "Successfully signed %q:%s\n", imgRefAndAuth.RepoInfo().Name.Name(), tag)
|
fmt.Fprintf(out, "Successfully signed %q:%s\n", imgRefAndAuth.RepoInfo().Name.Name(), tag)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func validateTag(imgRefAndAuth trust.ImageRefAndAuth) error {
|
||||||
|
tag := imgRefAndAuth.Tag()
|
||||||
|
if tag == "" {
|
||||||
|
if imgRefAndAuth.Digest() != "" {
|
||||||
|
return fmt.Errorf("cannot use a digest reference for IMAGE:TAG")
|
||||||
|
}
|
||||||
|
return fmt.Errorf("No tag specified for %s", imgRefAndAuth.Name())
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,10 +161,10 @@ func getExistingSignatureInfoForReleasedTag(notaryRepo client.Repository, tag st
|
||||||
return releasedTargetInfoList[0], nil
|
return releasedTargetInfoList[0], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func prettyPrintExistingSignatureInfo(cli command.Cli, existingSigInfo trustTagRow) {
|
func prettyPrintExistingSignatureInfo(out io.Writer, existingSigInfo trustTagRow) {
|
||||||
sort.Strings(existingSigInfo.Signers)
|
sort.Strings(existingSigInfo.Signers)
|
||||||
joinedSigners := strings.Join(existingSigInfo.Signers, ", ")
|
joinedSigners := strings.Join(existingSigInfo.Signers, ", ")
|
||||||
fmt.Fprintf(cli.Out(), "Existing signatures for tag %s digest %s from:\n%s\n", existingSigInfo.TagName, existingSigInfo.HashHex, joinedSigners)
|
fmt.Fprintf(out, "Existing signatures for tag %s digest %s from:\n%s\n", existingSigInfo.TagName, existingSigInfo.HashHex, joinedSigners)
|
||||||
}
|
}
|
||||||
|
|
||||||
func initNotaryRepoWithSigners(notaryRepo client.Repository, newSigner data.RoleName) error {
|
func initNotaryRepoWithSigners(notaryRepo client.Repository, newSigner data.RoleName) error {
|
||||||
|
|
|
@ -6,6 +6,8 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"bytes"
|
||||||
|
|
||||||
"github.com/docker/cli/cli/config"
|
"github.com/docker/cli/cli/config"
|
||||||
"github.com/docker/cli/cli/trust"
|
"github.com/docker/cli/cli/trust"
|
||||||
"github.com/docker/cli/internal/test"
|
"github.com/docker/cli/internal/test"
|
||||||
|
@ -17,6 +19,7 @@ import (
|
||||||
"github.com/docker/notary/trustpinning"
|
"github.com/docker/notary/trustpinning"
|
||||||
"github.com/docker/notary/tuf/data"
|
"github.com/docker/notary/tuf/data"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
const passwd = "password"
|
const passwd = "password"
|
||||||
|
@ -151,6 +154,7 @@ func TestAddStageSigners(t *testing.T) {
|
||||||
NewThreshold: notary.MinThreshold,
|
NewThreshold: notary.MinThreshold,
|
||||||
AddKeys: data.KeyList([]data.PublicKey{userKey}),
|
AddKeys: data.KeyList([]data.PublicKey{userKey}),
|
||||||
})
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
expectedChange := changelist.NewTUFChange(
|
expectedChange := changelist.NewTUFChange(
|
||||||
changelist.ActionCreate,
|
changelist.ActionCreate,
|
||||||
userRole,
|
userRole,
|
||||||
|
@ -165,6 +169,7 @@ func TestAddStageSigners(t *testing.T) {
|
||||||
expectedJSON, err = json.Marshal(&changelist.TUFDelegation{
|
expectedJSON, err = json.Marshal(&changelist.TUFDelegation{
|
||||||
AddPaths: []string{""},
|
AddPaths: []string{""},
|
||||||
})
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
expectedChange = changelist.NewTUFChange(
|
expectedChange = changelist.NewTUFChange(
|
||||||
changelist.ActionCreate,
|
changelist.ActionCreate,
|
||||||
userRole,
|
userRole,
|
||||||
|
@ -182,6 +187,7 @@ func TestAddStageSigners(t *testing.T) {
|
||||||
NewThreshold: notary.MinThreshold,
|
NewThreshold: notary.MinThreshold,
|
||||||
AddKeys: data.KeyList([]data.PublicKey{userKey}),
|
AddKeys: data.KeyList([]data.PublicKey{userKey}),
|
||||||
})
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
expectedChange = changelist.NewTUFChange(
|
expectedChange = changelist.NewTUFChange(
|
||||||
changelist.ActionCreate,
|
changelist.ActionCreate,
|
||||||
releasesRole,
|
releasesRole,
|
||||||
|
@ -196,6 +202,7 @@ func TestAddStageSigners(t *testing.T) {
|
||||||
expectedJSON, err = json.Marshal(&changelist.TUFDelegation{
|
expectedJSON, err = json.Marshal(&changelist.TUFDelegation{
|
||||||
AddPaths: []string{""},
|
AddPaths: []string{""},
|
||||||
})
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
expectedChange = changelist.NewTUFChange(
|
expectedChange = changelist.NewTUFChange(
|
||||||
changelist.ActionCreate,
|
changelist.ActionCreate,
|
||||||
releasesRole,
|
releasesRole,
|
||||||
|
@ -259,27 +266,32 @@ func TestGetExistingSignatureInfoForReleasedTag(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPrettyPrintExistingSignatureInfo(t *testing.T) {
|
func TestPrettyPrintExistingSignatureInfo(t *testing.T) {
|
||||||
fakeCli := test.NewFakeCli(&fakeClient{})
|
buf := bytes.NewBuffer(nil)
|
||||||
|
|
||||||
signers := []string{"Bob", "Alice", "Carol"}
|
signers := []string{"Bob", "Alice", "Carol"}
|
||||||
existingSig := trustTagRow{trustTagKey{"tagName", "abc123"}, signers}
|
existingSig := trustTagRow{trustTagKey{"tagName", "abc123"}, signers}
|
||||||
prettyPrintExistingSignatureInfo(fakeCli, existingSig)
|
prettyPrintExistingSignatureInfo(buf, existingSig)
|
||||||
|
|
||||||
assert.Contains(t, fakeCli.OutBuffer().String(), "Existing signatures for tag tagName digest abc123 from:\nAlice, Bob, Carol")
|
assert.Contains(t, buf.String(), "Existing signatures for tag tagName digest abc123 from:\nAlice, Bob, Carol")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestChangeList(t *testing.T) {
|
func TestSignCommandChangeListIsCleanedOnError(t *testing.T) {
|
||||||
tmpDir, err := ioutil.TempDir("", "docker-sign-test-")
|
tmpDir, err := ioutil.TempDir("", "docker-sign-test-")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
defer os.RemoveAll(tmpDir)
|
defer os.RemoveAll(tmpDir)
|
||||||
|
|
||||||
config.SetDir(tmpDir)
|
config.SetDir(tmpDir)
|
||||||
cmd := newSignCommand(
|
cli := test.NewFakeCli(&fakeClient{})
|
||||||
test.NewFakeCli(&fakeClient{}))
|
cli.SetNotaryClient(getLoadedNotaryRepository)
|
||||||
|
cmd := newSignCommand(cli)
|
||||||
cmd.SetArgs([]string{"ubuntu:latest"})
|
cmd.SetArgs([]string{"ubuntu:latest"})
|
||||||
cmd.SetOutput(ioutil.Discard)
|
cmd.SetOutput(ioutil.Discard)
|
||||||
|
|
||||||
err = cmd.Execute()
|
err = cmd.Execute()
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
notaryRepo, err := client.NewFileCachedRepository(tmpDir, "docker.io/library/ubuntu", "https://localhost", nil, passphrase.ConstantRetriever(passwd), trustpinning.TrustPinConfig{})
|
notaryRepo, err := client.NewFileCachedRepository(tmpDir, "docker.io/library/ubuntu", "https://localhost", nil, passphrase.ConstantRetriever(passwd), trustpinning.TrustPinConfig{})
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
cl, err := notaryRepo.GetChangelist()
|
cl, err := notaryRepo.GetChangelist()
|
||||||
|
require.NoError(t, err)
|
||||||
assert.Equal(t, len(cl.List()), 0)
|
assert.Equal(t, len(cl.List()), 0)
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,9 +11,8 @@ import (
|
||||||
"github.com/docker/cli/cli"
|
"github.com/docker/cli/cli"
|
||||||
"github.com/docker/cli/cli/command"
|
"github.com/docker/cli/cli/command"
|
||||||
"github.com/docker/cli/cli/command/formatter"
|
"github.com/docker/cli/cli/command/formatter"
|
||||||
|
"github.com/docker/cli/cli/command/image"
|
||||||
"github.com/docker/cli/cli/trust"
|
"github.com/docker/cli/cli/trust"
|
||||||
"github.com/docker/docker/api/types"
|
|
||||||
registrytypes "github.com/docker/docker/api/types/registry"
|
|
||||||
"github.com/docker/notary"
|
"github.com/docker/notary"
|
||||||
"github.com/docker/notary/client"
|
"github.com/docker/notary/client"
|
||||||
"github.com/docker/notary/tuf/data"
|
"github.com/docker/notary/tuf/data"
|
||||||
|
@ -61,15 +60,12 @@ func newViewCommand(dockerCli command.Cli) *cobra.Command {
|
||||||
|
|
||||||
func lookupTrustInfo(cli command.Cli, remote string) error {
|
func lookupTrustInfo(cli command.Cli, remote string) error {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
authResolver := func(ctx context.Context, index *registrytypes.IndexInfo) types.AuthConfig {
|
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, image.AuthResolver(cli), remote)
|
||||||
return command.ResolveAuthConfig(ctx, cli, index)
|
|
||||||
}
|
|
||||||
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, authResolver, remote)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
tag := imgRefAndAuth.Tag()
|
tag := imgRefAndAuth.Tag()
|
||||||
notaryRepo, err := cli.NotaryClient(*imgRefAndAuth, trust.ActionsPullOnly)
|
notaryRepo, err := cli.NotaryClient(imgRefAndAuth, trust.ActionsPullOnly)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return trust.NotaryError(imgRefAndAuth.Reference().Name(), err)
|
return trust.NotaryError(imgRefAndAuth.Reference().Name(), err)
|
||||||
}
|
}
|
||||||
|
@ -113,7 +109,9 @@ func lookupTrustInfo(cli command.Cli, remote string) error {
|
||||||
// If we do not have additional signers, do not display
|
// If we do not have additional signers, do not display
|
||||||
if len(signerRoleToKeyIDs) > 0 {
|
if len(signerRoleToKeyIDs) > 0 {
|
||||||
fmt.Fprintf(cli.Out(), "\nList of signers and their keys for %s:\n\n", strings.Split(remote, ":")[0])
|
fmt.Fprintf(cli.Out(), "\nList of signers and their keys for %s:\n\n", strings.Split(remote, ":")[0])
|
||||||
printSignerInfo(cli.Out(), signerRoleToKeyIDs)
|
if err := printSignerInfo(cli.Out(), signerRoleToKeyIDs); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This will always have the root and targets information
|
// This will always have the root and targets information
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package trust
|
package trust
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
|
@ -32,6 +31,7 @@ import (
|
||||||
digest "github.com/opencontainers/go-digest"
|
digest "github.com/opencontainers/go-digest"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
"golang.org/x/net/context"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -288,6 +288,7 @@ func GetSignableRoles(repo client.Repository, target *client.Target) ([]data.Rol
|
||||||
|
|
||||||
// ImageRefAndAuth contains all reference information and the auth config for an image request
|
// ImageRefAndAuth contains all reference information and the auth config for an image request
|
||||||
type ImageRefAndAuth struct {
|
type ImageRefAndAuth struct {
|
||||||
|
original string
|
||||||
authConfig *types.AuthConfig
|
authConfig *types.AuthConfig
|
||||||
reference reference.Named
|
reference reference.Named
|
||||||
repoInfo *registry.RepositoryInfo
|
repoInfo *registry.RepositoryInfo
|
||||||
|
@ -295,27 +296,29 @@ type ImageRefAndAuth struct {
|
||||||
digest digest.Digest
|
digest digest.Digest
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewImageRefAndAuth creates a new ImageRefAndAuth struct
|
|
||||||
func NewImageRefAndAuth(authConfig *types.AuthConfig, reference reference.Named, repoInfo *registry.RepositoryInfo, tag string, digest digest.Digest) *ImageRefAndAuth {
|
|
||||||
return &ImageRefAndAuth{authConfig, reference, repoInfo, tag, digest}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetImageReferencesAndAuth retrieves the necessary reference and auth information for an image name
|
// GetImageReferencesAndAuth retrieves the necessary reference and auth information for an image name
|
||||||
// as a ImageRefAndAuth struct
|
// as a ImageRefAndAuth struct
|
||||||
func GetImageReferencesAndAuth(ctx context.Context, authResolver func(ctx context.Context, index *registrytypes.IndexInfo) types.AuthConfig, imgName string) (*ImageRefAndAuth, error) {
|
func GetImageReferencesAndAuth(ctx context.Context, authResolver func(ctx context.Context, index *registrytypes.IndexInfo) types.AuthConfig, imgName string) (ImageRefAndAuth, error) {
|
||||||
ref, err := reference.ParseNormalizedNamed(imgName)
|
ref, err := reference.ParseNormalizedNamed(imgName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return ImageRefAndAuth{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resolve the Repository name from fqn to RepositoryInfo
|
// Resolve the Repository name from fqn to RepositoryInfo
|
||||||
repoInfo, err := registry.ParseRepositoryInfo(ref)
|
repoInfo, err := registry.ParseRepositoryInfo(ref)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return ImageRefAndAuth{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
authConfig := authResolver(ctx, repoInfo.Index)
|
authConfig := authResolver(ctx, repoInfo.Index)
|
||||||
return NewImageRefAndAuth(&authConfig, ref, repoInfo, getTag(ref), getDigest(ref)), nil
|
return ImageRefAndAuth{
|
||||||
|
original: imgName,
|
||||||
|
authConfig: &authConfig,
|
||||||
|
reference: ref,
|
||||||
|
repoInfo: repoInfo,
|
||||||
|
tag: getTag(ref),
|
||||||
|
digest: getDigest(ref),
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getTag(ref reference.Named) string {
|
func getTag(ref reference.Named) string {
|
||||||
|
@ -364,3 +367,9 @@ func (imgRefAuth *ImageRefAndAuth) Tag() string {
|
||||||
func (imgRefAuth *ImageRefAndAuth) Digest() digest.Digest {
|
func (imgRefAuth *ImageRefAndAuth) Digest() digest.Digest {
|
||||||
return imgRefAuth.digest
|
return imgRefAuth.digest
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Name returns the image name used to initialize the ImageRefAndAuth
|
||||||
|
func (imgRefAuth *ImageRefAndAuth) Name() string {
|
||||||
|
return imgRefAuth.original
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"github.com/docker/notary/trustpinning"
|
"github.com/docker/notary/trustpinning"
|
||||||
digest "github.com/opencontainers/go-digest"
|
digest "github.com/opencontainers/go-digest"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGetTag(t *testing.T) {
|
func TestGetTag(t *testing.T) {
|
||||||
|
@ -53,6 +54,7 @@ func TestGetSignableRolesError(t *testing.T) {
|
||||||
defer os.RemoveAll(tmpDir)
|
defer os.RemoveAll(tmpDir)
|
||||||
|
|
||||||
notaryRepo, err := client.NewFileCachedRepository(tmpDir, "gun", "https://localhost", nil, passphrase.ConstantRetriever("password"), trustpinning.TrustPinConfig{})
|
notaryRepo, err := client.NewFileCachedRepository(tmpDir, "gun", "https://localhost", nil, passphrase.ConstantRetriever("password"), trustpinning.TrustPinConfig{})
|
||||||
|
require.NoError(t, err)
|
||||||
target := client.Target{}
|
target := client.Target{}
|
||||||
_, err = GetSignableRoles(notaryRepo, &target)
|
_, err = GetSignableRoles(notaryRepo, &target)
|
||||||
assert.EqualError(t, err, "client is offline")
|
assert.EqualError(t, err, "client is offline")
|
||||||
|
|
|
@ -2,7 +2,7 @@ FROM golang:1.8.3-alpine
|
||||||
|
|
||||||
RUN apk add -U git
|
RUN apk add -U git
|
||||||
|
|
||||||
ARG GOMETALINTER_SHA=4306381615a2ba2a207f8fcea02c08c6b2b0803f
|
ARG GOMETALINTER_SHA=8eca55135021737bbc65ed68b548b3336853274c
|
||||||
RUN go get -d github.com/alecthomas/gometalinter && \
|
RUN go get -d github.com/alecthomas/gometalinter && \
|
||||||
cd /go/src/github.com/alecthomas/gometalinter && \
|
cd /go/src/github.com/alecthomas/gometalinter && \
|
||||||
git checkout -q "$GOMETALINTER_SHA" && \
|
git checkout -q "$GOMETALINTER_SHA" && \
|
||||||
|
|
|
@ -10,7 +10,7 @@ import (
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
"gopkg.in/yaml.v2"
|
yaml "gopkg.in/yaml.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
type cmdOption struct {
|
type cmdOption struct {
|
||||||
|
@ -46,18 +46,17 @@ type cmdDoc struct {
|
||||||
|
|
||||||
// GenYamlTree creates yaml structured ref files
|
// GenYamlTree creates yaml structured ref files
|
||||||
func GenYamlTree(cmd *cobra.Command, dir string) error {
|
func GenYamlTree(cmd *cobra.Command, dir string) error {
|
||||||
identity := func(s string) string { return s }
|
|
||||||
emptyStr := func(s string) string { return "" }
|
emptyStr := func(s string) string { return "" }
|
||||||
return GenYamlTreeCustom(cmd, dir, emptyStr, identity)
|
return GenYamlTreeCustom(cmd, dir, emptyStr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenYamlTreeCustom creates yaml structured ref files
|
// GenYamlTreeCustom creates yaml structured ref files
|
||||||
func GenYamlTreeCustom(cmd *cobra.Command, dir string, filePrepender, linkHandler func(string) string) error {
|
func GenYamlTreeCustom(cmd *cobra.Command, dir string, filePrepender func(string) string) error {
|
||||||
for _, c := range cmd.Commands() {
|
for _, c := range cmd.Commands() {
|
||||||
if !c.IsAvailableCommand() || c.IsHelpCommand() {
|
if !c.IsAvailableCommand() || c.IsHelpCommand() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if err := GenYamlTreeCustom(c, dir, filePrepender, linkHandler); err != nil {
|
if err := GenYamlTreeCustom(c, dir, filePrepender); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
{
|
{
|
||||||
"Vendor": true,
|
"Vendor": true,
|
||||||
"Deadline": "2m",
|
"Deadline": "2m",
|
||||||
"Sort": ["linter", "severity", "path"],
|
"Sort": ["linter", "severity", "path", "line"],
|
||||||
"Exclude": ["cli/compose/schema/bindata.go"],
|
"Exclude": [
|
||||||
|
"cli/compose/schema/bindata.go",
|
||||||
|
"parameter .* always receives"
|
||||||
|
],
|
||||||
|
"EnableGC": true,
|
||||||
|
|
||||||
"DisableAll": true,
|
"DisableAll": true,
|
||||||
"Enable": [
|
"Enable": [
|
||||||
|
@ -22,6 +26,6 @@
|
||||||
"vet"
|
"vet"
|
||||||
],
|
],
|
||||||
|
|
||||||
"Cyclo": 19,
|
"Cyclo": 16,
|
||||||
"LineLength": 200
|
"LineLength": 200
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue