1
0
Эх сурвалжийг харах

Remove example backend.

Signed-off-by: Guillaume Tardif <[email protected]>
Guillaume Tardif 4 жил өмнө
parent
commit
aca816d5d6

+ 59 - 0
.github/stale.yml

@@ -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

+ 1 - 2
.github/workflows/ci.yml

@@ -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

+ 1 - 3
.github/workflows/windows-ci.yml

@@ -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

+ 0 - 16
BUILDING.md

@@ -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

+ 2 - 3
Makefile

@@ -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
 
 

+ 0 - 3
api/context/store/contextmetadata.go

@@ -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{}{}

+ 0 - 6
api/context/store/store.go

@@ -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{}
-		},
 	}
 	}
 }
 }

+ 2 - 2
api/context/store/store_test.go

@@ -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
-	err = s.GetEndpoint("aci", &exampleCtx)
+	var localCtx LocalContext
+	err = s.GetEndpoint("aci", &localCtx)
 	assert.Error(t, err, "wrong context type")
 	assert.Error(t, err, "wrong context type")
 }
 }
 
 

+ 1 - 18
cli/cmd/context/create.go

@@ -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(

+ 0 - 1
cli/main.go

@@ -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"
 )
 )
 
 

+ 0 - 1
docs/architecture.md

@@ -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)

+ 0 - 187
example/backend.go

@@ -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
-}

+ 0 - 17
example/doc.go

@@ -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

+ 0 - 9
import-restrictions.yaml

@@ -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

+ 19 - 65
tests/e2e/e2e_test.go

@@ -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":"stop","context":"example","source":"cli","status":"failure"}`,
-			`{"command":"context use","context":"example","source":"cli","status":"success"}`,
-			`{"command":"ps","context":"example","source":"cli","status":"success"}`,
+			`{"command":"ps","context":"local","source":"cli","status":"success"}`,
+			`{"command":"stop","context":"local","source":"cli","status":"failure"}`,
+			`{"command":"context use","context":"local","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", "use", "test-example")
+		c.RunDockerCmd("context", "create", "local", "test-local")
+		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")
-		// Example backend's ps output includes these strings
-		assert.Assert(t, !strings.Contains(res.Stdout(), "id"), "%q does not contains %q", res.Stdout(), "id")
-		assert.Assert(t, !strings.Contains(res.Stdout(), "1234"), "%q does not contains %q", res.Stdout(), "1234")
+		res := c.RunDockerCmd("-H", endpoint, "images")
+		// Local backend does not have images command
+		assert.Assert(t, strings.Contains(res.Stdout(), "IMAGE ID"), res.Stdout())
 	})
 	})
 }
 }
 
 
@@ -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")
-	res := c.RunDockerOrExitError("--context", "test-example", "images")
+	c.RunDockerCmd("context", "create", "local", "test-local")
+	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", "use", "test-example")
+		c.RunDockerCmd("context", "create", "local", "test-local")
+		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")

+ 0 - 14
tests/e2e/testdata/inspect-id.golden

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

+ 0 - 3
tests/e2e/testdata/ls-out-test-example-windows.golden

@@ -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                                                                                                              

+ 0 - 1
tests/e2e/testdata/ps-out-example-json.golden

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

+ 0 - 3
tests/e2e/testdata/ps-out-example.golden

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

+ 0 - 3
tests/e2e/testdata/ps-quiet-all-out-example.golden

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

+ 0 - 2
tests/e2e/testdata/ps-quiet-out-example.golden

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

+ 56 - 0
tests/skip-win-ci-e2e/skip_win_ci_test.go

@@ -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)

+ 1 - 1
tests/e2e/testdata/ls-out-test-example.golden → tests/skip-win-ci-e2e/testdata/ls-out-test-local.golden

@@ -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