Merge pull request #40 from docker/chore-cleanup

Add comments on exported items, remove example command
This commit is contained in:
Djordje Lukic 2020-05-05 12:06:55 +02:00 committed by GitHub
commit f32235b8ba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
33 changed files with 189 additions and 284 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View 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, &registeredBackend{
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 {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -11,6 +11,7 @@ import (
"github.com/docker/api/client"
)
// PsCommand lists containers
var PsCommand = cobra.Command{
Use: "ps",
Short: "List containers",

View File

@ -36,6 +36,7 @@ import (
"github.com/docker/api/client"
)
// Command runs a container
func Command() *cobra.Command {
var opts runOpts
cmd := &cobra.Command{

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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