package test import ( "bytes" "fmt" "io" "io/ioutil" "strings" "github.com/docker/cli/cli/command" "github.com/docker/cli/cli/config/configfile" "github.com/docker/cli/cli/context/docker" "github.com/docker/cli/cli/context/store" manifeststore "github.com/docker/cli/cli/manifest/store" registryclient "github.com/docker/cli/cli/registry/client" "github.com/docker/cli/cli/streams" "github.com/docker/cli/cli/trust" clitypes "github.com/docker/cli/types" "github.com/docker/docker/client" notaryclient "github.com/theupdateframework/notary/client" ) // NotaryClientFuncType defines a function that returns a fake notary client type NotaryClientFuncType func(imgRefAndAuth trust.ImageRefAndAuth, actions []string) (notaryclient.Repository, error) type clientInfoFuncType func() command.ClientInfo type containerizedEngineFuncType func(string) (clitypes.ContainerizedClient, error) // FakeCli emulates the default DockerCli type FakeCli struct { command.DockerCli client client.APIClient configfile *configfile.ConfigFile out *streams.Out outBuffer *bytes.Buffer err *bytes.Buffer in *streams.In server command.ServerInfo clientInfoFunc clientInfoFuncType notaryClientFunc NotaryClientFuncType manifestStore manifeststore.Store registryClient registryclient.RegistryClient contentTrust bool containerizedEngineClientFunc containerizedEngineFuncType contextStore store.Store currentContext string dockerEndpoint docker.Endpoint } // NewFakeCli returns a fake for the command.Cli interface func NewFakeCli(client client.APIClient, opts ...func(*FakeCli)) *FakeCli { outBuffer := new(bytes.Buffer) errBuffer := new(bytes.Buffer) c := &FakeCli{ client: client, out: streams.NewOut(outBuffer), outBuffer: outBuffer, err: errBuffer, in: streams.NewIn(ioutil.NopCloser(strings.NewReader(""))), // Use an empty string for filename so that tests don't create configfiles // Set cli.ConfigFile().Filename to a tempfile to support Save. configfile: configfile.New(""), } for _, opt := range opts { opt(c) } return c } // SetIn sets the input of the cli to the specified ReadCloser func (c *FakeCli) SetIn(in *streams.In) { c.in = in } // SetErr sets the stderr stream for the cli to the specified io.Writer func (c *FakeCli) SetErr(err *bytes.Buffer) { c.err = err } // SetOut sets the stdout stream for the cli to the specified io.Writer func (c *FakeCli) SetOut(out *streams.Out) { c.out = out } // SetConfigFile sets the "fake" config file func (c *FakeCli) SetConfigFile(configfile *configfile.ConfigFile) { c.configfile = configfile } // SetContextStore sets the "fake" context store func (c *FakeCli) SetContextStore(store store.Store) { c.contextStore = store } // SetCurrentContext sets the "fake" current context func (c *FakeCli) SetCurrentContext(name string) { c.currentContext = name } // SetDockerEndpoint sets the "fake" docker endpoint func (c *FakeCli) SetDockerEndpoint(ep docker.Endpoint) { c.dockerEndpoint = ep } // Client returns a docker API client func (c *FakeCli) Client() client.APIClient { return c.client } // Out returns the output stream (stdout) the cli should write on func (c *FakeCli) Out() *streams.Out { return c.out } // Err returns the output stream (stderr) the cli should write on func (c *FakeCli) Err() io.Writer { return c.err } // In returns the input stream the cli will use func (c *FakeCli) In() *streams.In { return c.in } // ConfigFile returns the cli configfile object (to get client configuration) func (c *FakeCli) ConfigFile() *configfile.ConfigFile { return c.configfile } // ContextStore returns the cli context store func (c *FakeCli) ContextStore() store.Store { return c.contextStore } // CurrentContext returns the cli context func (c *FakeCli) CurrentContext() string { return c.currentContext } // DockerEndpoint returns the current DockerEndpoint func (c *FakeCli) DockerEndpoint() docker.Endpoint { return c.dockerEndpoint } // ServerInfo returns API server information for the server used by this client func (c *FakeCli) ServerInfo() command.ServerInfo { return c.server } // ClientInfo returns client information func (c *FakeCli) ClientInfo() command.ClientInfo { if c.clientInfoFunc != nil { return c.clientInfoFunc() } return c.DockerCli.ClientInfo() } // SetClientInfo sets the internal getter for retrieving a ClientInfo func (c *FakeCli) SetClientInfo(clientInfoFunc clientInfoFuncType) { c.clientInfoFunc = clientInfoFunc } // OutBuffer returns the stdout buffer func (c *FakeCli) OutBuffer() *bytes.Buffer { return c.outBuffer } // ErrBuffer Buffer returns the stderr buffer func (c *FakeCli) ErrBuffer() *bytes.Buffer { return c.err } // ResetOutputBuffers resets the .OutBuffer() and.ErrBuffer() back to empty func (c *FakeCli) ResetOutputBuffers() { c.outBuffer.Reset() c.err.Reset() } // SetNotaryClient sets the internal getter for retrieving a NotaryClient func (c *FakeCli) SetNotaryClient(notaryClientFunc NotaryClientFuncType) { c.notaryClientFunc = notaryClientFunc } // NotaryClient returns an err for testing unless defined func (c *FakeCli) NotaryClient(imgRefAndAuth trust.ImageRefAndAuth, actions []string) (notaryclient.Repository, error) { if c.notaryClientFunc != nil { return c.notaryClientFunc(imgRefAndAuth, actions) } return nil, fmt.Errorf("no notary client available unless defined") } // ManifestStore returns a fake store used for testing func (c *FakeCli) ManifestStore() manifeststore.Store { return c.manifestStore } // RegistryClient returns a fake client for testing func (c *FakeCli) RegistryClient(insecure bool) registryclient.RegistryClient { return c.registryClient } // SetManifestStore on the fake cli func (c *FakeCli) SetManifestStore(store manifeststore.Store) { c.manifestStore = store } // SetRegistryClient on the fake cli func (c *FakeCli) SetRegistryClient(client registryclient.RegistryClient) { c.registryClient = client } // ContentTrustEnabled on the fake cli func (c *FakeCli) ContentTrustEnabled() bool { return c.contentTrust } // EnableContentTrust on the fake cli func EnableContentTrust(c *FakeCli) { c.contentTrust = true } // NewContainerizedEngineClient returns a containerized engine client func (c *FakeCli) NewContainerizedEngineClient(sockPath string) (clitypes.ContainerizedClient, error) { if c.containerizedEngineClientFunc != nil { return c.containerizedEngineClientFunc(sockPath) } return nil, fmt.Errorf("no containerized engine client available unless defined") } // SetContainerizedEngineClient on the fake cli func (c *FakeCli) SetContainerizedEngineClient(containerizedEngineClientFunc containerizedEngineFuncType) { c.containerizedEngineClientFunc = containerizedEngineClientFunc } // StackOrchestrator return the selected stack orchestrator func (c *FakeCli) StackOrchestrator(flagValue string) (command.Orchestrator, error) { configOrchestrator := "" if c.configfile != nil { configOrchestrator = c.configfile.StackOrchestrator } ctxOrchestrator := "" if c.currentContext != "" && c.contextStore != nil { meta, err := c.contextStore.GetMetadata(c.currentContext) if err != nil { return "", err } context, err := command.GetDockerContext(meta) if err != nil { return "", err } ctxOrchestrator = string(context.StackOrchestrator) } return command.GetStackOrchestrator(flagValue, ctxOrchestrator, configOrchestrator, c.err) }