Add e2e tests for plugin behavior and commands

Signed-off-by: Guillaume Lours <guillaume.lours@docker.com>
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
This commit is contained in:
Guillaume Lours 2020-05-05 23:33:54 +02:00 committed by Nicolas De Loof
parent aa8587095f
commit 6febf68748
No known key found for this signature in database
GPG Key ID: 9858809D6F8F6E7E
10 changed files with 264 additions and 6 deletions

View File

@ -4,7 +4,7 @@ clean:
build:
go build -v -o dist/docker-ecs cmd/main/main.go
test: ## Run tests
test: build ## Run tests
go test ./... -v
dev: build

View File

@ -43,6 +43,12 @@ func NewRootCmd(name string, dockerCli command.Cli) *cobra.Command {
opts, err = docker.CheckAwsContextExists(contextName)
return err
},
RunE: func(cmd *cobra.Command, args []string) error {
if len(args) != 0 {
return fmt.Errorf("%q is not a docker ecs command\nSee 'docker ecs --help'", args[0])
}
return nil
},
}
cmd.AddCommand(
VersionCommand(),

View File

@ -50,6 +50,7 @@ require (
gopkg.in/dancannon/gorethink.v3 v3.0.5 // indirect
gopkg.in/fatih/pool.v2 v2.0.0 // indirect
gopkg.in/gorethink/gorethink.v3 v3.0.5 // indirect
gotest.tools v2.2.0+incompatible
gotest.tools/v3 v3.0.2
vbom.ml/util v0.0.0-20180919145318-efcd4e0f9787 // indirect
)

View File

@ -3,6 +3,7 @@ package docker
import (
"fmt"
"github.com/docker/cli/cli/command"
cliconfig "github.com/docker/cli/cli/config"
"github.com/docker/cli/cli/context/store"
"github.com/mitchellh/mapstructure"
@ -25,7 +26,12 @@ type AwsContext struct {
}
func NewContext(name string, awsContext *AwsContext) error {
contextStore := initContextStore()
_, err := NewContextWithStore(name, awsContext, cliconfig.ContextStoreDir())
return err
}
func NewContextWithStore(name string, awsContext *AwsContext, contextDirectory string) (store.Store, error) {
contextStore := initContextStore(contextDirectory)
endpoints := map[string]interface{}{
"aws": awsContext,
"docker": awsContext,
@ -36,16 +42,19 @@ func NewContext(name string, awsContext *AwsContext) error {
Endpoints: endpoints,
Metadata: TypeContext{Type: contextType},
}
return contextStore.CreateOrUpdate(metadata)
return contextStore, contextStore.CreateOrUpdate(metadata)
}
func initContextStore() store.Store {
func initContextStore(contextDir string) store.Store {
config := store.NewConfig(getter)
return store.New(cliconfig.ContextStoreDir(), config)
return store.New(contextDir, config)
}
func CheckAwsContextExists(contextName string) (*AwsContext, error) {
contextStore := initContextStore()
if contextName == command.DefaultContextName {
return nil, fmt.Errorf("can't use \"%s\" with ECS command because it is not an AWS context", contextName)
}
contextStore := initContextStore(cliconfig.ContextStoreDir())
metadata, err := contextStore.GetMetadata(contextName)
if err != nil {
return nil, err

18
ecs/tests/command_test.go Normal file
View File

@ -0,0 +1,18 @@
package tests
import (
"testing"
"gotest.tools/v3/icmd"
)
func TestExitErrorCode(t *testing.T) {
cmd, cleanup := dockerCli.createTestCmd()
defer cleanup()
cmd.Command = dockerCli.Command("ecs", "unknown_command")
icmd.RunCmd(cmd).Assert(t, icmd.Expected{
ExitCode: 1,
Err: "\"unknown_command\" is not a docker ecs command\nSee 'docker ecs --help'",
})
}

127
ecs/tests/main_test.go Normal file
View File

@ -0,0 +1,127 @@
package tests
import (
"encoding/json"
"flag"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"runtime"
"testing"
dockerConfigFile "github.com/docker/cli/cli/config/configfile"
"github.com/docker/ecs-plugin/pkg/docker"
"gotest.tools/v3/icmd"
)
var (
e2ePath = flag.String("e2e-path", ".", "Set path to the e2e directory")
dockerCliPath = os.Getenv("DOCKERCLI_BINARY")
dockerCli dockerCliCommand
testContextName = "testAwsContextToBeRemoved"
)
type dockerCliCommand struct {
path string
cliPluginDir string
}
type ConfigFileOperator func(configFile *dockerConfigFile.ConfigFile)
func (d dockerCliCommand) createTestCmd(ops ...ConfigFileOperator) (icmd.Cmd, func()) {
configDir, err := ioutil.TempDir("", "config")
if err != nil {
panic(err)
}
configFilePath := filepath.Join(configDir, "config.json")
config := dockerConfigFile.ConfigFile{
CLIPluginsExtraDirs: []string{
d.cliPluginDir,
},
Filename: configFilePath,
}
for _, op := range ops {
op(&config)
}
configFile, err := os.Create(configFilePath)
if err != nil {
panic(err)
}
defer configFile.Close()
err = json.NewEncoder(configFile).Encode(config)
if err != nil {
panic(err)
}
awsContext := docker.AwsContext{
Profile: "TestProfile",
Cluster: "TestCluster",
Region: "TestRegion",
}
testStore, err := docker.NewContextWithStore(testContextName, &awsContext, filepath.Join(configDir, "contexts"))
if err != nil {
panic(err)
}
cleanup := func() {
fmt.Println("cleanup")
testStore.Remove(testContextName)
os.RemoveAll(configDir)
}
env := append(os.Environ(),
"DOCKER_CONFIG="+configDir,
"DOCKER_CLI_EXPERIMENTAL=enabled") // TODO: Remove this once docker ecs plugin is no more experimental
return icmd.Cmd{Env: env}, cleanup
}
func (d dockerCliCommand) Command(args ...string) []string {
return append([]string{d.path, "--context", testContextName}, args...)
}
func TestMain(m *testing.M) {
flag.Parse()
if err := os.Chdir(*e2ePath); err != nil {
panic(err)
}
cwd, err := os.Getwd()
if err != nil {
panic(err)
}
dockerEcs := os.Getenv("DOCKERECS_BINARY")
if dockerEcs == "" {
dockerEcs = filepath.Join(cwd, "../dist/docker-ecs")
}
dockerEcs, err = filepath.Abs(dockerEcs)
if err != nil {
panic(err)
}
if dockerCliPath == "" {
dockerCliPath = "docker"
} else {
dockerCliPath, err = filepath.Abs(dockerCliPath)
if err != nil {
panic(err)
}
}
// Prepare docker cli to call the docker-ecs plugin binary:
// - Create a symbolic link with the dockerEcs binary to the plugin directory
cliPluginDir, err := ioutil.TempDir("", "configContent")
if err != nil {
panic(err)
}
defer os.RemoveAll(cliPluginDir)
createDockerECSSymLink(dockerEcs, cliPluginDir)
dockerCli = dockerCliCommand{path: dockerCliPath, cliPluginDir: cliPluginDir}
os.Exit(m.Run())
}
func createDockerECSSymLink(dockerEcs, configDir string) {
dockerEcsExecName := "docker-ecs"
if runtime.GOOS == "windows" {
dockerEcsExecName += ".exe"
}
if err := os.Symlink(dockerEcs, filepath.Join(configDir, dockerEcsExecName)); err != nil {
panic(err)
}
}

33
ecs/tests/plugin_test.go Normal file
View File

@ -0,0 +1,33 @@
package tests
import (
"regexp"
"testing"
"gotest.tools/assert"
"gotest.tools/v3/golden"
"gotest.tools/v3/icmd"
)
func TestInvokePluginFromCLI(t *testing.T) {
cmd, cleanup := dockerCli.createTestCmd()
defer cleanup()
// docker --help should list app as a top command
cmd.Command = dockerCli.Command("--help")
icmd.RunCmd(cmd).Assert(t, icmd.Expected{
Out: "ecs* Docker ECS (Docker Inc.,",
})
// docker app --help prints docker-app help
cmd.Command = dockerCli.Command("ecs", "--help")
usage := icmd.RunCmd(cmd).Assert(t, icmd.Success).Combined()
goldenFile := "plugin-usage.golden"
golden.Assert(t, usage, goldenFile)
// docker info should print app version and short description
cmd.Command = dockerCli.Command("info")
re := regexp.MustCompile(`ecs: Docker ECS \(Docker Inc\., .*\)`)
output := icmd.RunCmd(cmd).Assert(t, icmd.Success).Combined()
assert.Assert(t, re.MatchString(output))
}

View File

@ -0,0 +1,34 @@
package tests
import (
"strings"
"testing"
"gotest.tools/assert"
"gotest.tools/v3/golden"
"gotest.tools/v3/icmd"
)
func TestSetupMandatoryArguments(t *testing.T) {
cmd, cleanup := dockerCli.createTestCmd()
defer cleanup()
cmd.Command = dockerCli.Command("ecs", "setup")
icmd.RunCmd(cmd).Assert(t, icmd.Expected{
ExitCode: 1,
Err: "required flag(s) \"cluster\", \"profile\", \"region\" not set",
})
}
func TestDefaultAwsContextName(t *testing.T) {
cmd, cleanup := dockerCli.createTestCmd()
defer cleanup()
cmd.Command = dockerCli.Command("ecs", "setup", "--cluster", "clusterName", "--profile", "profileName",
"--region", "regionName")
icmd.RunCmd(cmd).Assert(t, icmd.Success)
cmd.Command = dockerCli.Command("context", "inspect", "aws")
output := icmd.RunCmd(cmd).Assert(t, icmd.Success).Combined()
expected := golden.Get(t, "context-inspect.golden")
assert.Assert(t, strings.HasPrefix(output, string(expected)))
}

View File

@ -0,0 +1,16 @@
[
{
"Name": "aws",
"Metadata": {},
"Endpoints": {
"aws": {
"Cluster": "clusterName",
"Profile": "profileName",
"Region": "regionName"
},
"docker": {
"SkipTLSVerify": false
}
},
"TLSMaterial": {},
"Storage":

14
ecs/tests/testdata/plugin-usage.golden vendored Normal file
View File

@ -0,0 +1,14 @@
Usage: docker ecs COMMAND
run multi-container applications on Amazon ECS.
Management Commands:
compose
secret Manages secrets
Commands:
setup
version Show version.
Run 'docker ecs COMMAND --help' for more information on a command.