mirror of
https://github.com/docker/compose.git
synced 2025-04-08 17:05:13 +02:00
Merge pull request #40 from docker/chore-cleanup
Add comments on exported items, remove example command
This commit is contained in:
commit
f32235b8ba
14
.github/workflows/ci.yml
vendored
14
.github/workflows/ci.yml
vendored
@ -11,23 +11,17 @@ jobs:
|
||||
name: Build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Set up Go 1.13
|
||||
- name: Set up Go 1.14
|
||||
uses: actions/setup-go@v1
|
||||
with:
|
||||
go-version: 1.13
|
||||
go-version: 1.14
|
||||
id: go
|
||||
|
||||
- name: Checkout code into the Go module directory
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Install Protoc
|
||||
uses: arduino/setup-protoc@master
|
||||
|
||||
- name: Get dependencies
|
||||
run: ./scripts/setup/install-go-gen
|
||||
|
||||
- name: Protos
|
||||
run: make protos
|
||||
- name: Lint
|
||||
run: make lint
|
||||
|
||||
- name: Build
|
||||
run: make cli
|
||||
|
35
.golangci.yml
Normal file
35
.golangci.yml
Normal file
@ -0,0 +1,35 @@
|
||||
linters:
|
||||
run:
|
||||
concurrency: 2
|
||||
enable-all: false
|
||||
disable-all: true
|
||||
enable:
|
||||
- deadcode
|
||||
- errcheck
|
||||
- gocyclo
|
||||
- gofmt
|
||||
- goimports
|
||||
- golint
|
||||
- gosimple
|
||||
- govet
|
||||
- ineffassign
|
||||
- interfacer
|
||||
- lll
|
||||
- misspell
|
||||
- nakedret
|
||||
- staticcheck
|
||||
- structcheck
|
||||
- typecheck
|
||||
- unconvert
|
||||
- unparam
|
||||
- unused
|
||||
- varcheck
|
||||
linters-settings:
|
||||
gocyclo:
|
||||
min-complexity: 16
|
||||
lll:
|
||||
line-length: 200
|
||||
issues:
|
||||
# golangci hides some golint warnings (the warning about exported things
|
||||
# withtout documentation for example), this will make it show them anyway.
|
||||
exclude-use-default: false
|
20
Dockerfile
20
Dockerfile
@ -4,15 +4,20 @@ ARG GO_VERSION=1.14.2
|
||||
FROM golang:${GO_VERSION} AS fs
|
||||
ARG TARGET_OS=unknown
|
||||
ARG TARGET_ARCH=unknown
|
||||
ARG PWD=$GOPATH/src/github.com/docker/api
|
||||
ARG PWD=/api
|
||||
ENV GO111MODULE=on
|
||||
|
||||
RUN apt-get update && apt-get install --no-install-recommends -y \
|
||||
make \
|
||||
git \
|
||||
protobuf-compiler \
|
||||
libprotobuf-dev
|
||||
RUN go get github.com/golang/protobuf/protoc-gen-go && \
|
||||
|
||||
RUN go get github.com/golang/protobuf/protoc-gen-go@v1.4.1 && \
|
||||
go get golang.org/x/tools/cmd/goimports && \
|
||||
go get gotest.tools/gotestsum
|
||||
go get gotest.tools/gotestsum@v0.4.2 && \
|
||||
go get github.com/golangci/golangci-lint/cmd/golangci-lint@v1.26.0
|
||||
|
||||
WORKDIR ${PWD}
|
||||
ADD go.* ${PWD}
|
||||
RUN go mod download
|
||||
@ -32,13 +37,16 @@ RUN --mount=type=cache,target=/root/.cache/go-build \
|
||||
make -f builder.Makefile cross
|
||||
|
||||
FROM scratch AS protos
|
||||
COPY --from=make-protos /go/src/github.com/docker/api .
|
||||
COPY --from=make-protos /api .
|
||||
|
||||
FROM scratch AS cli
|
||||
COPY --from=make-cli /go/src/github.com/docker/api/bin/* .
|
||||
COPY --from=make-cli /api/bin/* .
|
||||
|
||||
FROM scratch AS cross
|
||||
COPY --from=make-cross /go/src/github.com/docker/api/bin/* .
|
||||
COPY --from=make-cross /api/bin/* .
|
||||
|
||||
FROM make-protos as test
|
||||
RUN make -f builder.Makefile test
|
||||
|
||||
FROM fs AS lint
|
||||
RUN make -f builder.Makefile lint
|
||||
|
8
Makefile
8
Makefile
@ -53,8 +53,14 @@ test: ## Run unit tests
|
||||
cache-clear: # Clear the builder cache
|
||||
@docker builder prune --force --filter type=exec.cachemount --filter=unused-for=24h
|
||||
|
||||
lint: ## run linter(s)
|
||||
@docker build . \
|
||||
--target lint
|
||||
|
||||
help: ## Show help
|
||||
@echo Please specify a build target. The choices are:
|
||||
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
|
||||
|
||||
.PHONY: all protos cli cross test cache-clear help
|
||||
FORCE:
|
||||
|
||||
.PHONY: all protos cli cross test cache-clear lint help
|
||||
|
12
README.md
12
README.md
@ -4,7 +4,17 @@
|
||||
|
||||
## Dev Setup
|
||||
|
||||
Make sure you have Docker installed and running.
|
||||
The recommended way is to use the main `Makefile` that runs everything inside a container.
|
||||
|
||||
If you don't have or want to use Docker for building you need to make sure you have all the needed tools installed locally:
|
||||
|
||||
* go 1.14
|
||||
* `go get github.com/golang/protobuf/protoc-gen-go@v1.4.1`
|
||||
* `go get golang.org/x/tools/cmd/goimports`
|
||||
* `go get gotest.tools/gotestsum@v0.4.2`
|
||||
* `go get github.com/golangci/golangci-lint/cmd/golangci-lint@v1.26.0`
|
||||
|
||||
And then you can call the same make targets but you need to pass it the `builder.Makefile` (`make -f builder.Makefile`).
|
||||
|
||||
## Building the project
|
||||
|
||||
|
48
azure/aci.go
48
azure/aci.go
@ -32,7 +32,7 @@ func init() {
|
||||
func createACIContainers(ctx context.Context, aciContext store.AciContext, groupDefinition containerinstance.ContainerGroup) (c containerinstance.ContainerGroup, err error) {
|
||||
containerGroupsClient, err := getContainerGroupsClient(aciContext.SubscriptionID)
|
||||
if err != nil {
|
||||
return c, fmt.Errorf("cannot get container group client: %v", err)
|
||||
return c, errors.Wrapf(err, "cannot get container group client")
|
||||
}
|
||||
|
||||
// Check if the container group already exists
|
||||
@ -96,30 +96,11 @@ func createACIContainers(ctx context.Context, aciContext store.AciContext, group
|
||||
return containerGroup, err
|
||||
}
|
||||
|
||||
func listACIContainers(aciContext store.AciContext) (c []containerinstance.ContainerGroup, err error) {
|
||||
ctx := context.TODO()
|
||||
containerGroupsClient, err := getContainerGroupsClient(aciContext.SubscriptionID)
|
||||
if err != nil {
|
||||
return c, fmt.Errorf("cannot get container group client: %v", err)
|
||||
}
|
||||
|
||||
var containers []containerinstance.ContainerGroup
|
||||
result, err := containerGroupsClient.ListByResourceGroup(ctx, aciContext.ResourceGroup)
|
||||
if err != nil {
|
||||
return []containerinstance.ContainerGroup{}, err
|
||||
}
|
||||
for result.NotDone() {
|
||||
containers = append(containers, result.Values()...)
|
||||
if err := result.NextWithContext(ctx); err != nil {
|
||||
return []containerinstance.ContainerGroup{}, err
|
||||
}
|
||||
}
|
||||
|
||||
return containers, err
|
||||
}
|
||||
|
||||
func execACIContainer(ctx context.Context, aciContext store.AciContext, command, containerGroup string, containerName string) (c containerinstance.ContainerExecResponse, err error) {
|
||||
containerClient := getContainerClient(aciContext.SubscriptionID)
|
||||
containerClient, err := getContainerClient(aciContext.SubscriptionID)
|
||||
if err != nil {
|
||||
return c, errors.Wrapf(err, "cannot get container client")
|
||||
}
|
||||
rows, cols := getTermSize()
|
||||
containerExecRequest := containerinstance.ContainerExecRequest{
|
||||
Command: to.StringPtr(command),
|
||||
@ -224,7 +205,10 @@ func exec(ctx context.Context, address string, password string, reader io.Reader
|
||||
}
|
||||
|
||||
func getACIContainerLogs(ctx context.Context, aciContext store.AciContext, containerGroupName, containerName string) (string, error) {
|
||||
containerClient := getContainerClient(aciContext.SubscriptionID)
|
||||
containerClient, err := getContainerClient(aciContext.SubscriptionID)
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "cannot get container client")
|
||||
}
|
||||
|
||||
logs, err := containerClient.ListLogs(ctx, aciContext.ResourceGroup, containerGroupName, containerName, nil)
|
||||
if err != nil {
|
||||
@ -234,15 +218,21 @@ func getACIContainerLogs(ctx context.Context, aciContext store.AciContext, conta
|
||||
}
|
||||
|
||||
func getContainerGroupsClient(subscriptionID string) (containerinstance.ContainerGroupsClient, error) {
|
||||
auth, _ := auth.NewAuthorizerFromCLI()
|
||||
auth, err := auth.NewAuthorizerFromCLI()
|
||||
if err != nil {
|
||||
return containerinstance.ContainerGroupsClient{}, err
|
||||
}
|
||||
containerGroupsClient := containerinstance.NewContainerGroupsClient(subscriptionID)
|
||||
containerGroupsClient.Authorizer = auth
|
||||
return containerGroupsClient, nil
|
||||
}
|
||||
|
||||
func getContainerClient(subscriptionID string) containerinstance.ContainerClient {
|
||||
auth, _ := auth.NewAuthorizerFromCLI()
|
||||
func getContainerClient(subscriptionID string) (containerinstance.ContainerClient, error) {
|
||||
auth, err := auth.NewAuthorizerFromCLI()
|
||||
if err != nil {
|
||||
return containerinstance.ContainerClient{}, err
|
||||
}
|
||||
containerClient := containerinstance.NewContainerClient(subscriptionID)
|
||||
containerClient.Authorizer = auth
|
||||
return containerClient
|
||||
return containerClient, nil
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ func getter() interface{} {
|
||||
return &store.AciContext{}
|
||||
}
|
||||
|
||||
// New creates a backend that can manage containers on ACI
|
||||
func New(ctx context.Context) (containers.ContainerService, error) {
|
||||
currentContext := apicontext.CurrentContext(ctx)
|
||||
contextStore, err := store.New()
|
||||
|
@ -21,8 +21,10 @@ const (
|
||||
volumeDriveroptsAccountNameKey = "storage_account_name"
|
||||
volumeDriveroptsAccountKeyKey = "storage_account_key"
|
||||
singleContainerName = "single--container--aci"
|
||||
secretInlineMark = "inline:"
|
||||
)
|
||||
|
||||
// ToContainerGroup converts a compose project into a ACI container group
|
||||
func ToContainerGroup(aciContext store.AciContext, p compose.Project) (containerinstance.ContainerGroup, error) {
|
||||
project := projectAciHelper(p)
|
||||
containerGroupName := strings.ToLower(project.Name)
|
||||
@ -98,8 +100,8 @@ func (p projectAciHelper) getAciSecretVolumes() ([]containerinstance.Volume, err
|
||||
var secretVolumes []containerinstance.Volume
|
||||
for secretName, filepathToRead := range p.Secrets {
|
||||
var data []byte
|
||||
if strings.HasPrefix(filepathToRead.File, compose.SecretInlineMark) {
|
||||
data = []byte(filepathToRead.File[len(compose.SecretInlineMark):])
|
||||
if strings.HasPrefix(filepathToRead.File, secretInlineMark) {
|
||||
data = []byte(filepathToRead.File[len(secretInlineMark):])
|
||||
} else {
|
||||
var err error
|
||||
data, err = ioutil.ReadFile(filepathToRead.File)
|
||||
|
@ -7,43 +7,46 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
ErrNoType = errors.New("backend: no type")
|
||||
ErrNoName = errors.New("backend: no name")
|
||||
ErrTypeRegistered = errors.New("backend: already registered")
|
||||
errNoType = errors.New("backend: no type")
|
||||
errNoName = errors.New("backend: no name")
|
||||
errTypeRegistered = errors.New("backend: already registered")
|
||||
)
|
||||
|
||||
type InitFunc func(context.Context) (interface{}, error)
|
||||
type initFunc func(context.Context) (interface{}, error)
|
||||
|
||||
type Backend struct {
|
||||
type registeredBackend struct {
|
||||
name string
|
||||
backendType string
|
||||
init InitFunc
|
||||
init initFunc
|
||||
}
|
||||
|
||||
var backends = struct {
|
||||
r []*Backend
|
||||
r []*registeredBackend
|
||||
}{}
|
||||
|
||||
func Register(name string, backendType string, init InitFunc) {
|
||||
// Register adds a typed backend to the registry
|
||||
func Register(name string, backendType string, init initFunc) {
|
||||
if name == "" {
|
||||
panic(ErrNoName)
|
||||
panic(errNoName)
|
||||
}
|
||||
if backendType == "" {
|
||||
panic(ErrNoType)
|
||||
panic(errNoType)
|
||||
}
|
||||
for _, b := range backends.r {
|
||||
if b.backendType == backendType {
|
||||
panic(ErrTypeRegistered)
|
||||
panic(errTypeRegistered)
|
||||
}
|
||||
}
|
||||
|
||||
backends.r = append(backends.r, &Backend{
|
||||
backends.r = append(backends.r, ®isteredBackend{
|
||||
name,
|
||||
backendType,
|
||||
init,
|
||||
})
|
||||
}
|
||||
|
||||
// Get returns the backend registered for a particular type, it returns
|
||||
// an error if there is no registered backends for the given type.
|
||||
func Get(ctx context.Context, backendType string) (interface{}, error) {
|
||||
for _, b := range backends.r {
|
||||
if b.backendType == backendType {
|
||||
|
@ -57,6 +57,10 @@ cross:
|
||||
test:
|
||||
@gotestsum ./...
|
||||
|
||||
lint:
|
||||
golangci-lint run --timeout 10m0s ./...
|
||||
|
||||
|
||||
FORCE:
|
||||
|
||||
.PHONY: all protos cli cross test
|
||||
.PHONY: all protos cli cross test lint
|
||||
|
@ -38,9 +38,7 @@ import (
|
||||
"github.com/docker/api/context/store"
|
||||
)
|
||||
|
||||
type CliContext struct {
|
||||
}
|
||||
|
||||
// ContextCommand manages contexts
|
||||
func ContextCommand() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "context",
|
||||
|
@ -1,71 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2020 Docker Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without
|
||||
restriction, including without limitation the rights to use, copy,
|
||||
modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED,
|
||||
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"os"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
v1 "github.com/docker/api/backend/v1"
|
||||
"github.com/docker/api/client"
|
||||
)
|
||||
|
||||
var ExampleCommand = cobra.Command{
|
||||
Use: "example",
|
||||
Short: "sample command using backend, to be removed later",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
ctx := cmd.Context()
|
||||
|
||||
c, err := client.New(ctx)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "cannot connect to backend")
|
||||
}
|
||||
|
||||
info, err := c.BackendInformation(ctx, &v1.BackendInformationRequest{})
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetch backend information")
|
||||
}
|
||||
enc := json.NewEncoder(os.Stdout)
|
||||
enc.SetIndent("", " ")
|
||||
return enc.Encode(info)
|
||||
},
|
||||
}
|
||||
|
||||
type backendAddressKey struct{}
|
||||
|
||||
func BackendAddress(ctx context.Context) (string, error) {
|
||||
v, ok := ctx.Value(backendAddressKey{}).(string)
|
||||
if !ok {
|
||||
return "", errors.New("no backend address key")
|
||||
}
|
||||
return v, nil
|
||||
}
|
@ -2,6 +2,7 @@ package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
@ -17,6 +18,7 @@ type execOpts struct {
|
||||
Tty bool
|
||||
}
|
||||
|
||||
// ExecCommand runs a command in a running container
|
||||
func ExecCommand() *cobra.Command {
|
||||
var opts execOpts
|
||||
cmd := &cobra.Command{
|
||||
@ -52,7 +54,9 @@ func runExec(ctx context.Context, opts execOpts, name string, command string) er
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
con.Reset()
|
||||
if err := con.Reset(); err != nil {
|
||||
fmt.Println("Unable to close the console")
|
||||
}
|
||||
}()
|
||||
|
||||
stdout = con
|
||||
|
@ -16,6 +16,7 @@ type logsOpts struct {
|
||||
Tail string
|
||||
}
|
||||
|
||||
// LogsCommand fetches and shows logs of a container
|
||||
func LogsCommand() *cobra.Command {
|
||||
var opts logsOpts
|
||||
cmd := &cobra.Command{
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
"github.com/docker/api/client"
|
||||
)
|
||||
|
||||
// PsCommand lists containers
|
||||
var PsCommand = cobra.Command{
|
||||
Use: "ps",
|
||||
Short: "List containers",
|
||||
|
@ -36,6 +36,7 @@ import (
|
||||
"github.com/docker/api/client"
|
||||
)
|
||||
|
||||
// Command runs a container
|
||||
func Command() *cobra.Command {
|
||||
var opts runOpts
|
||||
cmd := &cobra.Command{
|
||||
|
@ -20,6 +20,7 @@ type serveOpts struct {
|
||||
address string
|
||||
}
|
||||
|
||||
// ServeCommand returns the command to serve the API
|
||||
func ServeCommand() *cobra.Command {
|
||||
var opts serveOpts
|
||||
cmd := &cobra.Command{
|
||||
@ -42,9 +43,10 @@ func runServe(ctx context.Context, opts serveOpts) error {
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "listen unix socket")
|
||||
}
|
||||
// nolint errcheck
|
||||
defer listener.Close()
|
||||
|
||||
p := proxy.NewContainerApi()
|
||||
p := proxy.NewContainerAPI()
|
||||
|
||||
containersv1.RegisterContainersServer(s, p)
|
||||
cliv1.RegisterCliServer(s, &cliServer{
|
||||
|
@ -51,7 +51,7 @@ import (
|
||||
)
|
||||
|
||||
type mainOpts struct {
|
||||
apicontext.ContextFlags
|
||||
apicontext.Flags
|
||||
debug bool
|
||||
}
|
||||
|
||||
@ -99,7 +99,6 @@ func main() {
|
||||
cmd.ContextCommand(),
|
||||
&cmd.PsCommand,
|
||||
cmd.ServeCommand(),
|
||||
&cmd.ExampleCommand,
|
||||
run.Command(),
|
||||
cmd.ExecCommand(),
|
||||
cmd.LogsCommand(),
|
||||
|
@ -41,7 +41,7 @@ import (
|
||||
"github.com/docker/api/context/store"
|
||||
)
|
||||
|
||||
// New returns a GRPC client
|
||||
// New returns a backend client
|
||||
func New(ctx context.Context) (*Client, error) {
|
||||
currentContext := apicontext.CurrentContext(ctx)
|
||||
s := store.ContextStore(ctx)
|
||||
@ -68,6 +68,7 @@ func New(ctx context.Context) (*Client, error) {
|
||||
|
||||
}
|
||||
|
||||
// Client is a multi-backend client
|
||||
type Client struct {
|
||||
backendv1.BackendClient
|
||||
cliv1.CliClient
|
||||
@ -78,6 +79,7 @@ type Client struct {
|
||||
cc containers.ContainerService
|
||||
}
|
||||
|
||||
// ContainerService returns the backend service for the current context
|
||||
func (c *Client) ContainerService() containers.ContainerService {
|
||||
return c.cc
|
||||
}
|
||||
|
@ -14,17 +14,14 @@ import (
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
const (
|
||||
SecretInlineMark = "inline:"
|
||||
)
|
||||
|
||||
var SupportedFilenames = []string{
|
||||
var supportedFilenames = []string{
|
||||
"compose.yml",
|
||||
"compose.yaml",
|
||||
"docker-compose.yml",
|
||||
"docker-compose.yaml",
|
||||
}
|
||||
|
||||
// ProjectOptions configures a compose project
|
||||
type ProjectOptions struct {
|
||||
Name string
|
||||
WorkDir string
|
||||
@ -32,6 +29,7 @@ type ProjectOptions struct {
|
||||
Environment []string
|
||||
}
|
||||
|
||||
// Project represents a compose project with a name
|
||||
type Project struct {
|
||||
types.Config
|
||||
projectDir string
|
||||
@ -100,7 +98,7 @@ func getConfigPathFromOptions(options *ProjectOptions) ([]string, error) {
|
||||
|
||||
for {
|
||||
var candidates []string
|
||||
for _, n := range SupportedFilenames {
|
||||
for _, n := range supportedFilenames {
|
||||
f := filepath.Join(pwd, n)
|
||||
if _, err := os.Stat(f); err == nil {
|
||||
candidates = append(candidates, f)
|
||||
@ -116,7 +114,7 @@ func getConfigPathFromOptions(options *ProjectOptions) ([]string, error) {
|
||||
}
|
||||
parent := filepath.Dir(pwd)
|
||||
if parent == pwd {
|
||||
return nil, fmt.Errorf("Can't find a suitable configuration file in this directory or any parent. Is %q the right directory?", pwd)
|
||||
return nil, fmt.Errorf("can't find a suitable configuration file in this directory or any parent. Is %q the right directory?", pwd)
|
||||
}
|
||||
pwd = parent
|
||||
}
|
||||
@ -129,12 +127,11 @@ func parseConfigs(configPaths []string) ([]types.ConfigFile, error) {
|
||||
var err error
|
||||
if f == "-" {
|
||||
return []types.ConfigFile{}, errors.New("reading compose file from stdin is not supported")
|
||||
} else {
|
||||
if _, err := os.Stat(f); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b, err = ioutil.ReadFile(f)
|
||||
}
|
||||
if _, err := os.Stat(f); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b, err = ioutil.ReadFile(f)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
30
consts.go
30
consts.go
@ -1,30 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2019 Docker Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without
|
||||
restriction, including without limitation the rights to use, copy,
|
||||
modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED,
|
||||
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package api
|
||||
|
||||
const DockerContextKey = "DOCKER_CONTEXT_KEY"
|
@ -11,7 +11,7 @@ type Container struct {
|
||||
Status string
|
||||
Image string
|
||||
Command string
|
||||
CpuTime uint64
|
||||
CPUTime uint64
|
||||
MemoryUsage uint64
|
||||
MemoryLimit uint64
|
||||
PidsCurrent uint64
|
||||
@ -37,6 +37,7 @@ type ContainerConfig struct {
|
||||
Ports []Port
|
||||
}
|
||||
|
||||
// LogsRequest contains configuration about a log request
|
||||
type LogsRequest struct {
|
||||
Follow bool
|
||||
Tail string
|
||||
|
@ -34,6 +34,7 @@ import (
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// LoadConfigFile loads the docker configuration
|
||||
func LoadConfigFile(configDir string, configFileName string) (*ConfigFile, error) {
|
||||
filename := filepath.Join(configDir, configFileName)
|
||||
configFile := &ConfigFile{
|
||||
@ -45,6 +46,7 @@ func LoadConfigFile(configDir string, configFileName string) (*ConfigFile, error
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("can't read %s: %w", filename, err)
|
||||
}
|
||||
// nolint errcheck
|
||||
defer file.Close()
|
||||
err = json.NewDecoder(file).Decode(&configFile)
|
||||
if err != nil {
|
||||
@ -59,6 +61,7 @@ func LoadConfigFile(configDir string, configFileName string) (*ConfigFile, error
|
||||
return configFile, nil
|
||||
}
|
||||
|
||||
// ConfigFile contains the current context from the docker configuration file
|
||||
type ConfigFile struct {
|
||||
Filename string `json:"-"` // Note: for internal use only
|
||||
CurrentContext string `json:"currentContext,omitempty"`
|
||||
|
@ -6,10 +6,13 @@ import (
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
const KEY = "context_key"
|
||||
// Key is the key where the current docker context is stored in the metadata
|
||||
// of a gRPC request
|
||||
const Key = "context_key"
|
||||
|
||||
type currentContextKey struct{}
|
||||
|
||||
// WithCurrentContext sets the name of the current docker context
|
||||
func WithCurrentContext(ctx gocontext.Context, contextName string) context.Context {
|
||||
return context.WithValue(ctx, currentContextKey{}, contextName)
|
||||
}
|
||||
|
@ -41,12 +41,14 @@ const (
|
||||
configFileDir = ".docker"
|
||||
)
|
||||
|
||||
type ContextFlags struct {
|
||||
// Flags are the global cli flags
|
||||
type Flags struct {
|
||||
Config string
|
||||
Context string
|
||||
}
|
||||
|
||||
func (c *ContextFlags) AddFlags(flags *pflag.FlagSet) {
|
||||
// AddFlags adds persistent (global) flags
|
||||
func (c *Flags) AddFlags(flags *pflag.FlagSet) {
|
||||
flags.StringVar(&c.Config, "config", filepath.Join(home(), configFileDir), "Location of the client config files `DIRECTORY`")
|
||||
flags.StringVarP(&c.Context, "context", "c", os.Getenv("DOCKER_CONTEXT"), "context")
|
||||
}
|
||||
|
@ -47,16 +47,18 @@ const (
|
||||
|
||||
type contextStoreKey struct{}
|
||||
|
||||
// WithContextStore adds the store to the context
|
||||
func WithContextStore(ctx context.Context, store Store) context.Context {
|
||||
return context.WithValue(ctx, contextStoreKey{}, store)
|
||||
}
|
||||
|
||||
// ContextStore returns the store from the context
|
||||
func ContextStore(ctx context.Context) Store {
|
||||
s, _ := ctx.Value(contextStoreKey{}).(Store)
|
||||
return s
|
||||
}
|
||||
|
||||
// Store
|
||||
// Store is the context store
|
||||
type Store interface {
|
||||
// Get returns the context with name, it returns an error if the context
|
||||
// doesn't exist
|
||||
@ -74,16 +76,18 @@ type store struct {
|
||||
root string
|
||||
}
|
||||
|
||||
type StoreOpt func(*store)
|
||||
// Opt is a functional option for the store
|
||||
type Opt func(*store)
|
||||
|
||||
func WithRoot(root string) StoreOpt {
|
||||
// WithRoot sets a new root to the store
|
||||
func WithRoot(root string) Opt {
|
||||
return func(s *store) {
|
||||
s.root = root
|
||||
}
|
||||
}
|
||||
|
||||
// New returns a configured context store
|
||||
func New(opts ...StoreOpt) (Store, error) {
|
||||
// New returns a configured context store with $HOME/.docker as root
|
||||
func New(opts ...Opt) (Store, error) {
|
||||
home, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -182,7 +186,7 @@ func (s *store) Create(name string, data TypedContext) error {
|
||||
dir := contextdirOf(name)
|
||||
metaDir := filepath.Join(s.root, contextsDir, metadataDir, dir)
|
||||
if _, err := os.Stat(metaDir); !os.IsNotExist(err) {
|
||||
return fmt.Errorf("Context %q already exists", name)
|
||||
return fmt.Errorf("context %q already exists", name)
|
||||
}
|
||||
|
||||
err := os.Mkdir(metaDir, 0755)
|
||||
@ -191,15 +195,15 @@ func (s *store) Create(name string, data TypedContext) error {
|
||||
}
|
||||
|
||||
if data.Data == nil {
|
||||
data.Data = DummyContext{}
|
||||
data.Data = dummyContext{}
|
||||
}
|
||||
|
||||
meta := Metadata{
|
||||
Name: name,
|
||||
Metadata: data,
|
||||
Endpoints: map[string]interface{}{
|
||||
"docker": DummyContext{},
|
||||
(data.Type): DummyContext{},
|
||||
"docker": dummyContext{},
|
||||
(data.Type): dummyContext{},
|
||||
},
|
||||
}
|
||||
|
||||
@ -237,8 +241,9 @@ func contextdirOf(name string) string {
|
||||
return digest.FromString(name).Encoded()
|
||||
}
|
||||
|
||||
type DummyContext struct{}
|
||||
type dummyContext struct{}
|
||||
|
||||
// Metadata represents the docker context metadata
|
||||
type Metadata struct {
|
||||
Name string `json:",omitempty"`
|
||||
Metadata TypedContext `json:",omitempty"`
|
||||
@ -257,12 +262,14 @@ type untypedContext struct {
|
||||
Type string `json:",omitempty"`
|
||||
}
|
||||
|
||||
// TypedContext is a context with a type (moby, aci, etc...)
|
||||
type TypedContext struct {
|
||||
Type string `json:",omitempty"`
|
||||
Description string `json:",omitempty"`
|
||||
Data interface{} `json:",omitempty"`
|
||||
}
|
||||
|
||||
// AciContext is the context for ACI
|
||||
type AciContext struct {
|
||||
SubscriptionID string `json:",omitempty"`
|
||||
Location string `json:",omitempty"`
|
||||
|
@ -55,7 +55,8 @@ func (suite *StoreTestSuite) BeforeTest(suiteName, testName string) {
|
||||
}
|
||||
|
||||
func (suite *StoreTestSuite) AfterTest(suiteName, testName string) {
|
||||
os.RemoveAll(suite.dir)
|
||||
err := os.RemoveAll(suite.dir)
|
||||
require.Nil(suite.T(), err)
|
||||
}
|
||||
|
||||
func (suite *StoreTestSuite) TestCreate() {
|
||||
|
@ -13,14 +13,10 @@ type containerService struct{}
|
||||
|
||||
func init() {
|
||||
backend.Register("example", "example", func(ctx context.Context) (interface{}, error) {
|
||||
return New(), nil
|
||||
return &containerService{}, nil
|
||||
})
|
||||
}
|
||||
|
||||
func New() containers.ContainerService {
|
||||
return &containerService{}
|
||||
}
|
||||
|
||||
func (cs *containerService) List(ctx context.Context) ([]containers.Container, error) {
|
||||
return []containers.Container{
|
||||
{
|
||||
|
2
go.mod
2
go.mod
@ -1,6 +1,6 @@
|
||||
module github.com/docker/api
|
||||
|
||||
go 1.13
|
||||
go 1.14
|
||||
|
||||
require (
|
||||
github.com/Azure/azure-sdk-for-go v42.0.0+incompatible
|
||||
|
@ -1,7 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
go get -u github.com/gogo/protobuf/proto
|
||||
go get -u github.com/gogo/protobuf/jsonpb
|
||||
go get -u github.com/golang/protobuf/protoc-gen-go
|
||||
go get -u github.com/stevvooe/protobuild
|
||||
go get -u gotest.tools/gotestsum
|
@ -1,61 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright The containerd 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.
|
||||
|
||||
#
|
||||
# Downloads and installs protobuf
|
||||
#
|
||||
set -eu -o pipefail
|
||||
|
||||
PROTOBUF_VERSION=3.11.4
|
||||
GOARCH=$(go env GOARCH)
|
||||
GOOS=$(go env GOOS)
|
||||
PROTOBUF_DIR=$(mktemp -d)
|
||||
|
||||
case $GOARCH in
|
||||
|
||||
arm64)
|
||||
wget -O $PROTOBUF_DIR/protobuf "https://github.com/google/protobuf/releases/download/v$PROTOBUF_VERSION/protoc-$PROTOBUF_VERSION-linux-aarch64.zip"
|
||||
unzip $PROTOBUF_DIR/protobuf -d /usr/local
|
||||
;;
|
||||
|
||||
amd64 | 386)
|
||||
if [ "$GOOS" = windows ]; then
|
||||
wget -O $PROTOBUF_DIR/protobuf "https://github.com/google/protobuf/releases/download/v$PROTOBUF_VERSION/protoc-$PROTOBUF_VERSION-win32.zip"
|
||||
elif [ "$GOOS" = linux ]; then
|
||||
wget -O $PROTOBUF_DIR/protobuf "https://github.com/google/protobuf/releases/download/v$PROTOBUF_VERSION/protoc-$PROTOBUF_VERSION-linux-x86_64.zip"
|
||||
elif [ "$GOOS" = darwin ]; then
|
||||
curl -Lo $PROTOBUF_DIR/protobuf "https://github.com/google/protobuf/releases/download/v$PROTOBUF_VERSION/protoc-$PROTOBUF_VERSION-osx-x86_64.zip"
|
||||
fi
|
||||
unzip $PROTOBUF_DIR/protobuf -x readme.txt -d /usr/local
|
||||
;;
|
||||
|
||||
ppc64le)
|
||||
wget -O $PROTOBUF_DIR/protobuf "https://github.com/google/protobuf/releases/download/v$PROTOBUF_VERSION/protoc-$PROTOBUF_VERSION-linux-ppcle_64.zip"
|
||||
unzip $PROTOBUF_DIR/protobuf -d /usr/local
|
||||
;;
|
||||
*)
|
||||
wget -O $PROTOBUF_DIR/protobuf "https://github.com/google/protobuf/releases/download/v$PROTOBUF_VERSION/protobuf-cpp-$PROTOBUF_VERSION.zip"
|
||||
unzip $PROTOBUF_DIR/protobuf -d /usr/src/protobuf
|
||||
cd /usr/src/protobuf/protobuf-$PROTOBUF_VERSION
|
||||
./autogen.sh
|
||||
./configure --disable-shared
|
||||
make
|
||||
make check
|
||||
make install
|
||||
ldconfig
|
||||
;;
|
||||
esac
|
||||
rm -rf $PROTOBUF_DIR
|
@ -10,22 +10,25 @@ import (
|
||||
|
||||
type clientKey struct{}
|
||||
|
||||
// WithClient adds the client to the context
|
||||
func WithClient(ctx context.Context, c *client.Client) (context.Context, error) {
|
||||
return context.WithValue(ctx, clientKey{}, c), nil
|
||||
}
|
||||
|
||||
// Client returns the client from the context
|
||||
func Client(ctx context.Context) *client.Client {
|
||||
c, _ := ctx.Value(clientKey{}).(*client.Client)
|
||||
return c
|
||||
}
|
||||
|
||||
func NewContainerApi() v1.ContainersServer {
|
||||
return &proxyContainerApi{}
|
||||
// NewContainerAPI creates a proxy container server
|
||||
func NewContainerAPI() v1.ContainersServer {
|
||||
return &proxyContainerAPI{}
|
||||
}
|
||||
|
||||
type proxyContainerApi struct{}
|
||||
type proxyContainerAPI struct{}
|
||||
|
||||
func (p *proxyContainerApi) List(ctx context.Context, _ *v1.ListRequest) (*v1.ListResponse, error) {
|
||||
func (p *proxyContainerAPI) List(ctx context.Context, _ *v1.ListRequest) (*v1.ListResponse, error) {
|
||||
client := Client(ctx)
|
||||
|
||||
c, err := client.ContainerService().List(ctx)
|
||||
@ -46,7 +49,7 @@ func (p *proxyContainerApi) List(ctx context.Context, _ *v1.ListRequest) (*v1.Li
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (p *proxyContainerApi) Create(ctx context.Context, request *v1.CreateRequest) (*v1.CreateResponse, error) {
|
||||
func (p *proxyContainerAPI) Create(ctx context.Context, request *v1.CreateRequest) (*v1.CreateResponse, error) {
|
||||
client := Client(ctx)
|
||||
|
||||
err := client.ContainerService().Run(ctx, containers.ContainerConfig{
|
||||
@ -57,26 +60,26 @@ func (p *proxyContainerApi) Create(ctx context.Context, request *v1.CreateReques
|
||||
return &v1.CreateResponse{}, err
|
||||
}
|
||||
|
||||
func (p *proxyContainerApi) Start(_ context.Context, _ *v1.StartRequest) (*v1.StartResponse, error) {
|
||||
func (p *proxyContainerAPI) Start(_ context.Context, _ *v1.StartRequest) (*v1.StartResponse, error) {
|
||||
panic("not implemented") // TODO: Implement
|
||||
}
|
||||
|
||||
func (p *proxyContainerApi) Stop(_ context.Context, _ *v1.StopRequest) (*v1.StopResponse, error) {
|
||||
func (p *proxyContainerAPI) Stop(_ context.Context, _ *v1.StopRequest) (*v1.StopResponse, error) {
|
||||
panic("not implemented") // TODO: Implement
|
||||
}
|
||||
|
||||
func (p *proxyContainerApi) Kill(_ context.Context, _ *v1.KillRequest) (*v1.KillResponse, error) {
|
||||
func (p *proxyContainerAPI) Kill(_ context.Context, _ *v1.KillRequest) (*v1.KillResponse, error) {
|
||||
panic("not implemented") // TODO: Implement
|
||||
}
|
||||
|
||||
func (p *proxyContainerApi) Delete(_ context.Context, _ *v1.DeleteRequest) (*v1.DeleteResponse, error) {
|
||||
func (p *proxyContainerAPI) Delete(_ context.Context, _ *v1.DeleteRequest) (*v1.DeleteResponse, error) {
|
||||
panic("not implemented") // TODO: Implement
|
||||
}
|
||||
|
||||
func (p *proxyContainerApi) Update(_ context.Context, _ *v1.UpdateRequest) (*v1.UpdateResponse, error) {
|
||||
func (p *proxyContainerAPI) Update(_ context.Context, _ *v1.UpdateRequest) (*v1.UpdateResponse, error) {
|
||||
panic("not implemented") // TODO: Implement
|
||||
}
|
||||
|
||||
func (p *proxyContainerApi) Exec(_ context.Context, _ *v1.ExecRequest) (*v1.ExecResponse, error) {
|
||||
func (p *proxyContainerAPI) Exec(_ context.Context, _ *v1.ExecRequest) (*v1.ExecResponse, error) {
|
||||
panic("not implemented") // TODO: Implement
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ func unaryMeta(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo,
|
||||
return nil, errors.New("missing metadata")
|
||||
}
|
||||
|
||||
key := md[apicontext.KEY]
|
||||
key := md[apicontext.Key]
|
||||
|
||||
if len(key) == 1 {
|
||||
s, err := store.New()
|
||||
|
Loading…
x
Reference in New Issue
Block a user