Remove example backend.

Signed-off-by: Guillaume Tardif <guillaume.tardif@gmail.com>
This commit is contained in:
Guillaume Tardif 2021-01-18 18:35:03 +01:00
parent 268b3f65b0
commit aca816d5d6
23 changed files with 142 additions and 360 deletions

59
.github/stale.yml vendored Normal file
View File

@ -0,0 +1,59 @@
# Configuration for probot-stale - https://github.com/probot/stale
# Number of days of inactivity before an Issue or Pull Request becomes stale
daysUntilStale: 180
# Number of days of inactivity before an Issue or Pull Request with the stale label is closed.
# Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale.
daysUntilClose: 7
# Only issues or pull requests with all of these labels are check if stale. Defaults to `[]` (disabled)
onlyLabels: []
# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable
exemptLabels:
- "enhancement ✨"
# Set to true to ignore issues in a project (defaults to false)
exemptProjects: false
# Set to true to ignore issues in a milestone (defaults to false)
exemptMilestones: false
# Set to true to ignore issues with an assignee (defaults to false)
exemptAssignees: true
# Label to use when marking as stale
staleLabel: stale
# Comment to post when marking as stale. Set to `false` to disable
markComment: >
This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions.
# Comment to post when removing the stale label.
unmarkComment: >
This issue has been automatically marked as not stale anymore due to the recent activity.
# Comment to post when closing a stale Issue or Pull Request.
closeComment: >
This issue has been automatically closed because it had not recent activity during the stale period.
# Limit the number of actions per hour, from 1-30. Default is 30
limitPerRun: 30
# Limit to only `issues` or `pulls`
only: issues
# Optionally, specify configuration settings that are specific to just 'issues' or 'pulls':
# pulls:
# daysUntilStale: 30
# markComment: >
# This pull request has been automatically marked as stale because it has not had
# recent activity. It will be closed if no further activity occurs. Thank you
# for your contributions.
# issues:
# exemptLabels:
# - confirmed

View File

@ -65,12 +65,11 @@ jobs:
- name: Test - name: Test
env: env:
BUILD_TAGS: example
run: make -f builder.Makefile test run: make -f builder.Makefile test
- name: Build for local E2E - name: Build for local E2E
env: env:
BUILD_TAGS: example,e2e BUILD_TAGS: e2e
run: make -f builder.Makefile cli run: make -f builder.Makefile cli
- name: E2E Test - name: E2E Test

View File

@ -48,13 +48,11 @@ jobs:
key: go-${{ hashFiles('**/go.sum') }} key: go-${{ hashFiles('**/go.sum') }}
- name: Test - name: Test
env:
BUILD_TAGS: example,local
run: make -f builder.Makefile test run: make -f builder.Makefile test
- name: Build - name: Build
env: env:
BUILD_TAGS: example,local,e2e BUILD_TAGS: e2e
run: make -f builder.Makefile cli run: make -f builder.Makefile cli
- name: E2E Test - name: E2E Test

View File

@ -35,22 +35,6 @@ This will create a symbolic link from the existing Docker CLI to
You can statically cross compile the CLI for Windows, macOS, and Linux using the You can statically cross compile the CLI for Windows, macOS, and Linux using the
`cross` target. `cross` target.
### Building with specific backends
You can specify which backends are build using the `BUILD_TAGS` variable.
The available backends are:
* `aci`: For ACI support (always built)
* `ecs`: For ECS support (always built)
* `example`: Testing backend (off by default)
* `local`: Beginnings of a [moby](https://github.com/moby/moby) backend
(off by default)
If you want the ACI, ECS and example backends, then you can build as follows:
```console
make BUILD_TAGS=example cli
```
### Updating the API code ### Updating the API code
The API provided by the CLI is defined using protobuf. If you make changes to The API provided by the CLI is defined using protobuf. If you make changes to

View File

@ -39,7 +39,7 @@ protos: ## Generate go code from .proto files
cli: ## Compile the cli cli: ## Compile the cli
@docker build . --target cli \ @docker build . --target cli \
--platform local \ --platform local \
--build-arg BUILD_TAGS=example,e2e \ --build-arg BUILD_TAGS=e2e \
--build-arg GIT_TAG=$(GIT_TAG) \ --build-arg GIT_TAG=$(GIT_TAG) \
--output ./bin --output ./bin
@ -63,7 +63,6 @@ cross: ## Compile the CLI for linux, darwin and windows
test: ## Run unit tests test: ## Run unit tests
@docker build . \ @docker build . \
--build-arg BUILD_TAGS=example \
--build-arg GIT_TAG=$(GIT_TAG) \ --build-arg GIT_TAG=$(GIT_TAG) \
--target test --target test
@ -72,7 +71,7 @@ cache-clear: ## Clear the builder cache
lint: ## run linter(s) lint: ## run linter(s)
@docker build . \ @docker build . \
--build-arg BUILD_TAGS=example,e2e \ --build-arg BUILD_TAGS=e2e \
--build-arg GIT_TAG=$(GIT_TAG) \ --build-arg GIT_TAG=$(GIT_TAG) \
--target lint --target lint

View File

@ -61,9 +61,6 @@ type AwsContext EcsContext
// LocalContext is the context for the local backend // LocalContext is the context for the local backend
type LocalContext struct{} type LocalContext struct{}
// ExampleContext is the context for the example backend
type ExampleContext struct{}
// MarshalJSON implements custom JSON marshalling // MarshalJSON implements custom JSON marshalling
func (dc ContextMetadata) MarshalJSON() ([]byte, error) { func (dc ContextMetadata) MarshalJSON() ([]byte, error) {
s := map[string]interface{}{} s := map[string]interface{}{}

View File

@ -55,9 +55,6 @@ const (
// LocalContextType is the endpoint key in the context endpoints for a new // LocalContextType is the endpoint key in the context endpoints for a new
// local backend // local backend
LocalContextType = "local" LocalContextType = "local"
// ExampleContextType is the endpoint key in the context endpoints for an
// example backend
ExampleContextType = "example"
) )
const ( const (
@ -331,8 +328,5 @@ func getters() map[string]func() interface{} {
LocalContextType: func() interface{} { LocalContextType: func() interface{} {
return &LocalContext{} return &LocalContext{}
}, },
ExampleContextType: func() interface{} {
return &ExampleContext{}
},
} }
} }

View File

@ -64,8 +64,8 @@ func TestGetEndpoint(t *testing.T) {
assert.NilError(t, err) assert.NilError(t, err)
assert.Equal(t, ctx.Location, "eu") assert.Equal(t, ctx.Location, "eu")
var exampleCtx ExampleContext var localCtx LocalContext
err = s.GetEndpoint("aci", &exampleCtx) err = s.GetEndpoint("aci", &localCtx)
assert.Error(t, err, "wrong context type") assert.Error(t, err, "wrong context type")
} }

View File

@ -39,7 +39,7 @@ func createCommand() *cobra.Command {
longHelp := fmt.Sprintf(`Create a new context longHelp := fmt.Sprintf(`Create a new context
Create docker engine context: Create docker engine context:
$ docker context create CONTEXT [flags] $ docker context create CONTEXT [flags]
%s %s
@ -78,7 +78,6 @@ $ docker context create my-context --description "some description" --docker "ho
cmd.AddCommand( cmd.AddCommand(
createLocalCommand(), createLocalCommand(),
createExampleCommand(),
) )
for _, command := range extraCommands { for _, command := range extraCommands {
cmd.AddCommand(command()) cmd.AddCommand(command())
@ -111,22 +110,6 @@ func createLocalCommand() *cobra.Command {
return cmd return cmd
} }
func createExampleCommand() *cobra.Command {
var opts descriptionCreateOpts
cmd := &cobra.Command{
Use: "example CONTEXT",
Short: "Create a test context returning fixed output",
Args: cobra.ExactArgs(1),
Hidden: true,
RunE: func(cmd *cobra.Command, args []string) error {
return createDockerContext(cmd.Context(), args[0], store.ExampleContextType, opts.description, store.ExampleContext{})
},
}
addDescriptionFlag(cmd, &opts.description)
return cmd
}
func createDockerContext(ctx context.Context, name string, contextType string, description string, data interface{}) error { func createDockerContext(ctx context.Context, name string, contextType string, description string, data interface{}) error {
s := store.ContextStore(ctx) s := store.ContextStore(ctx)
result := s.Create( result := s.Create(

View File

@ -51,7 +51,6 @@ import (
_ "github.com/docker/compose-cli/aci" _ "github.com/docker/compose-cli/aci"
_ "github.com/docker/compose-cli/ecs" _ "github.com/docker/compose-cli/ecs"
_ "github.com/docker/compose-cli/ecs/local" _ "github.com/docker/compose-cli/ecs/local"
_ "github.com/docker/compose-cli/example"
_ "github.com/docker/compose-cli/local" _ "github.com/docker/compose-cli/local"
) )

View File

@ -20,7 +20,6 @@ These constraints resulted in the following architecture:
What follows is a list of useful links to help navigate the code: What follows is a list of useful links to help navigate the code:
* The CLI UX code is in [`cli/`](../cli) * The CLI UX code is in [`cli/`](../cli)
* The backend interface is defined in [`backend/`](../backend) * The backend interface is defined in [`backend/`](../backend)
* An example backend can be found in [`example/`](../example)
* The API is defined by protobufs that can be found in [`protos/`](../protos) * The API is defined by protobufs that can be found in [`protos/`](../protos)
* The API server is in [`server/`](../server) * The API server is in [`server/`](../server)
* The context management and interface can be found in [`context/`](../api/context) * The context management and interface can be found in [`context/`](../api/context)

View File

@ -1,187 +0,0 @@
// +build example
/*
Copyright 2020 Docker Compose CLI authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package example
import (
"context"
"errors"
"fmt"
"github.com/docker/compose-cli/api/backend"
"github.com/docker/compose-cli/api/cloud"
"github.com/docker/compose-cli/api/compose"
"github.com/docker/compose-cli/api/containers"
"github.com/docker/compose-cli/api/errdefs"
"github.com/docker/compose-cli/api/resources"
"github.com/docker/compose-cli/api/secrets"
"github.com/docker/compose-cli/api/volumes"
"github.com/compose-spec/compose-go/types"
)
type apiService struct {
containerService
composeService
}
func (a *apiService) ContainerService() containers.Service {
return &a.containerService
}
func (a *apiService) ComposeService() compose.Service {
return &a.composeService
}
func (a *apiService) SecretsService() secrets.Service {
return nil
}
func (a *apiService) VolumeService() volumes.Service {
return nil
}
func (a *apiService) ResourceService() resources.Service {
return nil
}
func init() {
backend.Register("example", "example", service, cloud.NotImplementedCloudService)
}
func service(ctx context.Context) (backend.Service, error) {
return &apiService{}, nil
}
type containerService struct{}
func (cs *containerService) Inspect(ctx context.Context, id string) (containers.Container, error) {
return containers.Container{
ID: "id",
Image: "nginx",
Platform: "Linux",
HostConfig: &containers.HostConfig{
RestartPolicy: "none",
},
}, nil
}
func (cs *containerService) List(ctx context.Context, all bool) ([]containers.Container, error) {
result := []containers.Container{
{
ID: "id",
Image: "nginx",
},
{
ID: "1234",
Image: "alpine",
},
}
if all {
result = append(result, containers.Container{
ID: "stopped",
Image: "nginx",
})
}
return result, nil
}
func (cs *containerService) Run(ctx context.Context, r containers.ContainerConfig) error {
fmt.Printf("Running container %q with name %q\n", r.Image, r.ID)
return nil
}
func (cs *containerService) Start(ctx context.Context, containerID string) error {
return errors.New("not implemented")
}
func (cs *containerService) Stop(ctx context.Context, containerName string, timeout *uint32) error {
return errors.New("not implemented")
}
func (cs *containerService) Kill(ctx context.Context, containerName string, signal string) error {
return errors.New("not implemented")
}
func (cs *containerService) Exec(ctx context.Context, name string, request containers.ExecRequest) error {
fmt.Printf("Executing command %q on container %q", request.Command, name)
return nil
}
func (cs *containerService) Logs(ctx context.Context, containerName string, request containers.LogsRequest) error {
fmt.Fprintf(request.Writer, "Following logs for container %q", containerName)
return nil
}
func (cs *containerService) Delete(ctx context.Context, id string, request containers.DeleteRequest) error {
fmt.Printf("Deleting container %q with force = %t\n", id, request.Force)
return nil
}
type composeService struct{}
func (cs *composeService) Build(ctx context.Context, project *types.Project) error {
fmt.Printf("Build command on project %q", project.Name)
return nil
}
func (cs *composeService) Push(ctx context.Context, project *types.Project) error {
return errdefs.ErrNotImplemented
}
func (cs *composeService) Pull(ctx context.Context, project *types.Project) error {
return errdefs.ErrNotImplemented
}
func (cs *composeService) Create(ctx context.Context, project *types.Project, opts compose.CreateOptions) error {
return errdefs.ErrNotImplemented
}
func (cs *composeService) Start(ctx context.Context, project *types.Project, consumer compose.LogConsumer) error {
return errdefs.ErrNotImplemented
}
func (cs *composeService) Up(ctx context.Context, project *types.Project, options compose.UpOptions) error {
fmt.Printf("Up command on project %q", project.Name)
return nil
}
func (cs *composeService) Down(ctx context.Context, projectName string, options compose.DownOptions) error {
fmt.Printf("Down command on project %q", projectName)
return nil
}
func (cs *composeService) Ps(ctx context.Context, projectName string) ([]compose.ContainerSummary, error) {
return nil, errdefs.ErrNotImplemented
}
func (cs *composeService) List(ctx context.Context, project string) ([]compose.Stack, error) {
return nil, errdefs.ErrNotImplemented
}
func (cs *composeService) Logs(ctx context.Context, projectName string, consumer compose.LogConsumer, options compose.LogOptions) error {
return errdefs.ErrNotImplemented
}
func (cs *composeService) Convert(ctx context.Context, project *types.Project, options compose.ConvertOptions) ([]byte, error) {
return nil, errdefs.ErrNotImplemented
}
func (cs *composeService) RunOneOffContainer(ctx context.Context, project *types.Project, opts compose.RunOptions) error {
return errdefs.ErrNotImplemented
}

View File

@ -1,17 +0,0 @@
/*
Copyright 2020 Docker Compose CLI authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package example

View File

@ -3,23 +3,14 @@
forbiddenImports: forbiddenImports:
- github.com/docker/compose-cli/cli - github.com/docker/compose-cli/cli
- github.com/docker/compose-cli/ecs - github.com/docker/compose-cli/ecs
- github.com/docker/compose-cli/example
- github.com/docker/compose-cli/local - github.com/docker/compose-cli/local
- path: ./ecs - path: ./ecs
forbiddenImports: forbiddenImports:
- github.com/docker/compose-cli/aci - github.com/docker/compose-cli/aci
- github.com/docker/compose-cli/cli - github.com/docker/compose-cli/cli
- github.com/docker/compose-cli/example
- github.com/docker/compose-cli/local
- path: ./example
forbiddenImports:
- github.com/docker/compose-cli/aci
- github.com/docker/compose-cli/cli
- github.com/docker/compose-cli/ecs
- github.com/docker/compose-cli/local - github.com/docker/compose-cli/local
- path: ./local - path: ./local
forbiddenImports: forbiddenImports:
- github.com/docker/compose-cli/aci - github.com/docker/compose-cli/aci
- github.com/docker/compose-cli/cli - github.com/docker/compose-cli/cli
- github.com/docker/compose-cli/ecs - github.com/docker/compose-cli/ecs
- github.com/docker/compose-cli/example

View File

@ -189,23 +189,25 @@ func TestContextMetrics(t *testing.T) {
t.Run("metrics on other context type", func(t *testing.T) { t.Run("metrics on other context type", func(t *testing.T) {
s.ResetUsage() s.ResetUsage()
c.RunDockerCmd("context", "create", "example", "test-example") c.RunDockerCmd("context", "create", "local", "test-local")
c.RunDockerCmd("ps") c.RunDockerCmd("ps")
c.RunDockerCmd("context", "use", "test-example") c.RunDockerCmd("context", "use", "test-local")
c.RunDockerCmd("ps") c.RunDockerCmd("ps")
c.RunDockerOrExitError("stop", "unknown") c.RunDockerOrExitError("stop", "unknown")
c.RunDockerCmd("context", "use", "default") c.RunDockerCmd("context", "use", "default")
c.RunDockerCmd("--context", "test-example", "ps") c.RunDockerCmd("--context", "test-local", "ps")
c.RunDockerCmd("context", "ls")
usage := s.GetUsage() usage := s.GetUsage()
assert.DeepEqual(t, []string{ assert.DeepEqual(t, []string{
`{"command":"context create","context":"moby","source":"cli","status":"success"}`, `{"command":"context create","context":"moby","source":"cli","status":"success"}`,
`{"command":"ps","context":"moby","source":"cli","status":"success"}`, `{"command":"ps","context":"moby","source":"cli","status":"success"}`,
`{"command":"context use","context":"moby","source":"cli","status":"success"}`, `{"command":"context use","context":"moby","source":"cli","status":"success"}`,
`{"command":"ps","context":"example","source":"cli","status":"success"}`, `{"command":"ps","context":"local","source":"cli","status":"success"}`,
`{"command":"stop","context":"example","source":"cli","status":"failure"}`, `{"command":"stop","context":"local","source":"cli","status":"failure"}`,
`{"command":"context use","context":"example","source":"cli","status":"success"}`, `{"command":"context use","context":"local","source":"cli","status":"success"}`,
`{"command":"ps","context":"example","source":"cli","status":"success"}`, `{"command":"ps","context":"local","source":"cli","status":"success"}`,
`{"command":"context ls","context":"moby","source":"cli","status":"success"}`,
}, usage) }, usage)
}) })
} }
@ -418,16 +420,15 @@ func TestLegacy(t *testing.T) {
}) })
t.Run("host flag overrides context", func(t *testing.T) { t.Run("host flag overrides context", func(t *testing.T) {
c.RunDockerCmd("context", "create", "example", "test-example") c.RunDockerCmd("context", "create", "local", "test-local")
c.RunDockerCmd("context", "use", "test-example") c.RunDockerCmd("context", "use", "test-local")
endpoint := "unix:///var/run/docker.sock" endpoint := "unix:///var/run/docker.sock"
if runtime.GOOS == "windows" { if runtime.GOOS == "windows" {
endpoint = "npipe:////./pipe/docker_engine" endpoint = "npipe:////./pipe/docker_engine"
} }
res := c.RunDockerCmd("-H", endpoint, "ps") res := c.RunDockerCmd("-H", endpoint, "images")
// Example backend's ps output includes these strings // Local backend does not have images command
assert.Assert(t, !strings.Contains(res.Stdout(), "id"), "%q does not contains %q", res.Stdout(), "id") assert.Assert(t, strings.Contains(res.Stdout(), "IMAGE ID"), res.Stdout())
assert.Assert(t, !strings.Contains(res.Stdout(), "1234"), "%q does not contains %q", res.Stdout(), "1234")
}) })
} }
@ -459,11 +460,11 @@ func TestLegacyLogin(t *testing.T) {
func TestUnsupportedCommand(t *testing.T) { func TestUnsupportedCommand(t *testing.T) {
c := NewParallelE2eCLI(t, binDir) c := NewParallelE2eCLI(t, binDir)
c.RunDockerCmd("context", "create", "example", "test-example") c.RunDockerCmd("context", "create", "local", "test-local")
res := c.RunDockerOrExitError("--context", "test-example", "images") res := c.RunDockerOrExitError("--context", "test-local", "images")
res.Assert(t, icmd.Expected{ res.Assert(t, icmd.Expected{
ExitCode: 1, ExitCode: 1,
Err: `Command "images" not available in current context (test-example), you can use the "default" context to run this command`, Err: `Command "images" not available in current context (test-local), you can use the "default" context to run this command`,
}) })
} }
@ -519,60 +520,13 @@ func TestVersion(t *testing.T) {
}) })
t.Run("delegate version flag", func(t *testing.T) { t.Run("delegate version flag", func(t *testing.T) {
c.RunDockerCmd("context", "create", "example", "test-example") c.RunDockerCmd("context", "create", "local", "test-local")
c.RunDockerCmd("context", "use", "test-example") c.RunDockerCmd("context", "use", "test-local")
res := c.RunDockerCmd("-v") res := c.RunDockerCmd("-v")
res.Assert(t, icmd.Expected{Out: "Docker version"}) res.Assert(t, icmd.Expected{Out: "Docker version"})
}) })
} }
func TestMockBackend(t *testing.T) {
c := NewParallelE2eCLI(t, binDir)
c.RunDockerCmd("context", "create", "example", "test-example")
res := c.RunDockerCmd("context", "use", "test-example")
res.Assert(t, icmd.Expected{Out: "test-example"})
t.Run("use", func(t *testing.T) {
res := c.RunDockerCmd("context", "show")
res.Assert(t, icmd.Expected{Out: "test-example"})
res = c.RunDockerCmd("context", "ls")
golden.Assert(t, res.Stdout(), GoldenFile("ls-out-test-example"))
})
t.Run("ps", func(t *testing.T) {
res := c.RunDockerCmd("ps")
golden.Assert(t, res.Stdout(), "ps-out-example.golden")
res = c.RunDockerCmd("ps", "--format", "pretty")
golden.Assert(t, res.Stdout(), "ps-out-example.golden")
res = c.RunDockerCmd("ps", "--format", "json")
golden.Assert(t, res.Stdout(), "ps-out-example-json.golden")
})
t.Run("ps quiet", func(t *testing.T) {
res := c.RunDockerCmd("ps", "-q")
golden.Assert(t, res.Stdout(), "ps-quiet-out-example.golden")
})
t.Run("ps quiet all", func(t *testing.T) {
res := c.RunDockerCmd("ps", "-q", "--all")
golden.Assert(t, res.Stdout(), "ps-quiet-all-out-example.golden")
})
t.Run("inspect", func(t *testing.T) {
res := c.RunDockerCmd("inspect", "id")
golden.Assert(t, res.Stdout(), "inspect-id.golden")
})
t.Run("run", func(t *testing.T) {
res := c.RunDockerCmd("run", "-d", "nginx", "-p", "80:80")
res.Assert(t, icmd.Expected{
Out: `Running container "nginx" with name`,
})
})
}
func TestFailOnEcsUsageAsPlugin(t *testing.T) { func TestFailOnEcsUsageAsPlugin(t *testing.T) {
c := NewParallelE2eCLI(t, binDir) c := NewParallelE2eCLI(t, binDir)
res := c.RunDockerCmd("context", "create", "local", "local") res := c.RunDockerCmd("context", "create", "local", "local")

View File

@ -1,14 +0,0 @@
{
"ID": "id",
"Status": "",
"Image": "nginx",
"HostConfig": {
"RestartPolicy": "none",
"CPUReservation": 0,
"CPULimit": 0,
"MemoryReservation": 0,
"MemoryLimit": 0,
"AutoRemove": false
},
"Platform": "Linux"
}

View File

@ -1,3 +0,0 @@
NAME TYPE DESCRIPTION DOCKER ENDPOINT KUBERNETES ENDPOINT ORCHESTRATOR
default moby Current DOCKER_HOST based configuration npipe:////./pipe/docker_engine swarm
test-example * example

View File

@ -1 +0,0 @@
[{"ID":"id","Image":"nginx","Status":"","Command":"","Ports":[]},{"ID":"1234","Image":"alpine","Status":"","Command":"","Ports":[]}]

View File

@ -1,3 +0,0 @@
CONTAINER ID IMAGE COMMAND STATUS PORTS
id nginx
1234 alpine

View File

@ -1,3 +0,0 @@
id
1234
stopped

View File

@ -1,2 +0,0 @@
id
1234

View File

@ -17,6 +17,7 @@
package main package main
import ( import (
"encoding/json"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"os" "os"
@ -27,10 +28,12 @@ import (
"testing" "testing"
"time" "time"
"gotest.tools/golden"
"gotest.tools/v3/assert" "gotest.tools/v3/assert"
"gotest.tools/v3/icmd" "gotest.tools/v3/icmd"
"gotest.tools/v3/poll" "gotest.tools/v3/poll"
"github.com/docker/compose-cli/cli/cmd"
. "github.com/docker/compose-cli/tests/framework" . "github.com/docker/compose-cli/tests/framework"
) )
@ -92,6 +95,59 @@ func TestKillChildProcess(t *testing.T) {
poll.WaitOn(t, buildStopped, poll.WithDelay(1*time.Second), poll.WithTimeout(60*time.Second)) poll.WaitOn(t, buildStopped, poll.WithDelay(1*time.Second), poll.WithTimeout(60*time.Second))
} }
// no linux containers on GHA Windows CI nodes (windows server)
func TestLocalContainers(t *testing.T) {
c := NewParallelE2eCLI(t, binDir)
c.RunDockerCmd("context", "create", "local", "test-local")
res := c.RunDockerCmd("context", "use", "test-local")
res.Assert(t, icmd.Expected{Out: "test-local"})
t.Run("use", func(t *testing.T) {
res := c.RunDockerCmd("context", "show")
res.Assert(t, icmd.Expected{Out: "test-local"})
res = c.RunDockerCmd("context", "ls")
golden.Assert(t, res.Stdout(), GoldenFile("ls-out-test-local"))
})
var nginxContainerName string
t.Run("run", func(t *testing.T) {
res := c.RunDockerCmd("run", "-d", "-p", "85:80", "nginx")
nginxContainerName = strings.TrimSpace(res.Stdout())
})
defer c.RunDockerOrExitError("rm", "-f", nginxContainerName)
var nginxID string
t.Run("inspect", func(t *testing.T) {
res = c.RunDockerCmd("inspect", nginxContainerName)
inspect := &cmd.ContainerInspectView{}
err := json.Unmarshal([]byte(res.Stdout()), inspect)
assert.NilError(t, err)
nginxID = inspect.ID
})
t.Run("ps", func(t *testing.T) {
res = c.RunDockerCmd("ps")
lines := Lines(res.Stdout())
nginxFound := false
for _, line := range lines {
fields := strings.Fields(line)
if fields[0] == nginxID {
nginxFound = true
assert.Equal(t, fields[1], "nginx")
assert.Equal(t, fields[2], "/docker-entrypoint.sh")
}
}
assert.Assert(t, nginxFound, res.Stdout())
res = c.RunDockerCmd("ps", "--format", "json")
res.Assert(t, icmd.Expected{Out: `"Image":"nginx","Status":"Up Less than a second","Command":"/docker-entrypoint.sh nginx -g 'daemon off;'","Ports":["0.0.0.0:85->80/tcp"`})
res = c.RunDockerCmd("ps", "--quiet")
res.Assert(t, icmd.Expected{Out: nginxID + "\n"})
})
}
func writeDockerfile(t *testing.T) string { func writeDockerfile(t *testing.T) string {
d, err := ioutil.TempDir("", "") d, err := ioutil.TempDir("", "")
assert.NilError(t, err) assert.NilError(t, err)

View File

@ -1,3 +1,3 @@
NAME TYPE DESCRIPTION DOCKER ENDPOINT KUBERNETES ENDPOINT ORCHESTRATOR NAME TYPE DESCRIPTION DOCKER ENDPOINT KUBERNETES ENDPOINT ORCHESTRATOR
default moby Current DOCKER_HOST based configuration unix:///var/run/docker.sock swarm default moby Current DOCKER_HOST based configuration unix:///var/run/docker.sock swarm
test-example * example test-local * local