Skip to content

Commit fc07c90

Browse files
vdemeestersilvin-lubecki
authored andcommitted
Add support for kubernetes in docker cli
- Add support for kubernetes for docker stack command - Update to go 1.9 - Add kubernetes to vendors - Print orchestrator in docker version command Signed-off-by: Vincent Demeester <vincent@sbr.pm> Signed-off-by: Silvin Lubecki <silvin.lubecki@docker.com>
1 parent b45a49c commit fc07c90

File tree

985 files changed

+319794
-3423
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

985 files changed

+319794
-3423
lines changed

circle.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ jobs:
3737
docker build -f $dockerfile --tag cli-builder:$CIRCLE_BUILD_NUM .
3838
name=cross-$CIRCLE_BUILD_NUM-$CIRCLE_NODE_INDEX
3939
docker run \
40+
-e VERSION=$VERSION \
4041
-e CROSS_GROUP=$CIRCLE_NODE_INDEX \
4142
--name $name cli-builder:$CIRCLE_BUILD_NUM \
4243
make cross
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package orchestrator
2+
3+
import (
4+
"os"
5+
"strings"
6+
7+
"github.com/docker/cli/cli/command"
8+
cliconfig "github.com/docker/cli/cli/config"
9+
)
10+
11+
// Orchestrator type acts as an enum describing supported orchestrators.
12+
type Orchestrator string
13+
14+
const (
15+
// Kubernetes orchestrator
16+
Kubernetes = Orchestrator("kubernetes")
17+
// Swarm orchestrator
18+
Swarm = Orchestrator("swarm")
19+
unset = Orchestrator("unset")
20+
21+
defaultOrchestrator = Swarm
22+
dockerOrchestrator = "DOCKER_ORCHESTRATOR"
23+
)
24+
25+
func normalize(flag string) Orchestrator {
26+
switch strings.ToLower(flag) {
27+
case "kubernetes", "k8s":
28+
return Kubernetes
29+
case "swarm", "swarmkit":
30+
return Swarm
31+
default:
32+
return unset
33+
}
34+
}
35+
36+
// GetOrchestrator checks DOCKER_ORCHESTRATOR environment variable and configuration file
37+
// orchestrator value and returns user defined Orchestrator.
38+
func GetOrchestrator(dockerCli command.Cli) Orchestrator {
39+
// Check environment variable
40+
env := os.Getenv(dockerOrchestrator)
41+
if o := normalize(env); o != unset {
42+
return o
43+
}
44+
// Check config file
45+
if configFile := cliconfig.LoadDefaultConfigFile(dockerCli.Err()); configFile != nil {
46+
if o := normalize(configFile.Orchestrator); o != unset {
47+
return o
48+
}
49+
}
50+
51+
// Nothing set, use default orchestrator
52+
return defaultOrchestrator
53+
}

cli/command/stack/cmd.go

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ package stack
33
import (
44
"github.com/docker/cli/cli"
55
"github.com/docker/cli/cli/command"
6+
"github.com/docker/cli/cli/command/orchestrator"
7+
"github.com/docker/cli/cli/command/stack/kubernetes"
8+
"github.com/docker/cli/cli/command/stack/swarm"
69
"github.com/spf13/cobra"
710
)
811

@@ -15,19 +18,24 @@ func NewStackCommand(dockerCli command.Cli) *cobra.Command {
1518
RunE: command.ShowHelp(dockerCli.Err()),
1619
Annotations: map[string]string{"version": "1.25"},
1720
}
18-
cmd.AddCommand(
19-
newDeployCommand(dockerCli),
20-
newListCommand(dockerCli),
21-
newRemoveCommand(dockerCli),
22-
newServicesCommand(dockerCli),
23-
newPsCommand(dockerCli),
24-
)
21+
switch orchestrator.GetOrchestrator(dockerCli) {
22+
case orchestrator.Kubernetes:
23+
kubernetes.AddStackCommands(cmd, dockerCli)
24+
case orchestrator.Swarm:
25+
swarm.AddStackCommands(cmd, dockerCli)
26+
}
2527
return cmd
2628
}
2729

2830
// NewTopLevelDeployCommand returns a command for `docker deploy`
2931
func NewTopLevelDeployCommand(dockerCli command.Cli) *cobra.Command {
30-
cmd := newDeployCommand(dockerCli)
32+
var cmd *cobra.Command
33+
switch orchestrator.GetOrchestrator(dockerCli) {
34+
case orchestrator.Kubernetes:
35+
cmd = kubernetes.NewTopLevelDeployCommand(dockerCli)
36+
case orchestrator.Swarm:
37+
cmd = swarm.NewTopLevelDeployCommand(dockerCli)
38+
}
3139
// Remove the aliases at the top level
3240
cmd.Aliases = []string{}
3341
cmd.Annotations = map[string]string{"experimental": "", "version": "1.25"}
Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package stack
1+
package common
22

33
import (
44
"fmt"
@@ -10,21 +10,25 @@ import (
1010
"github.com/spf13/pflag"
1111
)
1212

13-
func addComposefileFlag(opt *string, flags *pflag.FlagSet) {
13+
// AddComposefileFlag adds compose-file file to the specified flagset
14+
func AddComposefileFlag(opt *string, flags *pflag.FlagSet) {
1415
flags.StringVarP(opt, "compose-file", "c", "", "Path to a Compose file")
1516
flags.SetAnnotation("compose-file", "version", []string{"1.25"})
1617
}
1718

18-
func addBundlefileFlag(opt *string, flags *pflag.FlagSet) {
19+
// AddBundlefileFlag adds bundle-file file to the specified flagset
20+
func AddBundlefileFlag(opt *string, flags *pflag.FlagSet) {
1921
flags.StringVar(opt, "bundle-file", "", "Path to a Distributed Application Bundle file")
2022
flags.SetAnnotation("bundle-file", "experimental", nil)
2123
}
2224

23-
func addRegistryAuthFlag(opt *bool, flags *pflag.FlagSet) {
25+
// AddRegistryAuthFlag adds with-registry-auth file to the specified flagset
26+
func AddRegistryAuthFlag(opt *bool, flags *pflag.FlagSet) {
2427
flags.BoolVar(opt, "with-registry-auth", false, "Send registry authentication details to Swarm agents")
2528
}
2629

27-
func loadBundlefile(stderr io.Writer, namespace string, path string) (*bundlefile.Bundlefile, error) {
30+
// LoadBundlefile loads a bundle-file from the specified path
31+
func LoadBundlefile(stderr io.Writer, namespace string, path string) (*bundlefile.Bundlefile, error) {
2832
defaultPath := fmt.Sprintf("%s.dab", namespace)
2933

3034
if path == "" {
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package stack
1+
package common
22

33
import (
44
"bytes"
@@ -32,7 +32,7 @@ func TestLoadBundlefileErrors(t *testing.T) {
3232
}
3333

3434
for _, tc := range testCases {
35-
_, err := loadBundlefile(&bytes.Buffer{}, tc.namespace, tc.path)
35+
_, err := LoadBundlefile(&bytes.Buffer{}, tc.namespace, tc.path)
3636
assert.Error(t, err, tc.expectedError)
3737
}
3838
}
@@ -42,7 +42,7 @@ func TestLoadBundlefile(t *testing.T) {
4242

4343
namespace := ""
4444
path := filepath.Join("testdata", "bundlefile_with_two_services.dab")
45-
bundleFile, err := loadBundlefile(buf, namespace, path)
45+
bundleFile, err := LoadBundlefile(buf, namespace, path)
4646

4747
assert.NoError(t, err)
4848
assert.Equal(t, len(bundleFile.Services), 2)

cli/command/stack/testdata/bundlefile_with_two_services.dab renamed to cli/command/stack/common/testdata/bundlefile_with_two_services.dab

File renamed without changes.
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package clientset
2+
3+
import (
4+
composev1beta1 "github.com/docker/cli/cli/command/stack/kubernetes/api/client/clientset_generated/clientset/typed/compose/v1beta1"
5+
glog "github.com/golang/glog"
6+
discovery "k8s.io/client-go/discovery"
7+
rest "k8s.io/client-go/rest"
8+
flowcontrol "k8s.io/client-go/util/flowcontrol"
9+
)
10+
11+
type Interface interface {
12+
Discovery() discovery.DiscoveryInterface
13+
ComposeV1beta1() composev1beta1.ComposeV1beta1Interface
14+
// Deprecated: please explicitly pick a version if possible.
15+
Compose() composev1beta1.ComposeV1beta1Interface
16+
}
17+
18+
// Clientset contains the clients for groups. Each group has exactly one
19+
// version included in a Clientset.
20+
type Clientset struct {
21+
*discovery.DiscoveryClient
22+
*composev1beta1.ComposeV1beta1Client
23+
}
24+
25+
// ComposeV1beta1 retrieves the ComposeV1beta1Client
26+
func (c *Clientset) ComposeV1beta1() composev1beta1.ComposeV1beta1Interface {
27+
if c == nil {
28+
return nil
29+
}
30+
return c.ComposeV1beta1Client
31+
}
32+
33+
// Deprecated: Compose retrieves the default version of ComposeClient.
34+
// Please explicitly pick a version.
35+
func (c *Clientset) Compose() composev1beta1.ComposeV1beta1Interface {
36+
if c == nil {
37+
return nil
38+
}
39+
return c.ComposeV1beta1Client
40+
}
41+
42+
// Discovery retrieves the DiscoveryClient
43+
func (c *Clientset) Discovery() discovery.DiscoveryInterface {
44+
if c == nil {
45+
return nil
46+
}
47+
return c.DiscoveryClient
48+
}
49+
50+
// NewForConfig creates a new Clientset for the given config.
51+
func NewForConfig(c *rest.Config) (*Clientset, error) {
52+
configShallowCopy := *c
53+
if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 {
54+
configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst)
55+
}
56+
var cs Clientset
57+
var err error
58+
cs.ComposeV1beta1Client, err = composev1beta1.NewForConfig(&configShallowCopy)
59+
if err != nil {
60+
return nil, err
61+
}
62+
63+
cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy)
64+
if err != nil {
65+
glog.Errorf("failed to create the DiscoveryClient: %v", err)
66+
return nil, err
67+
}
68+
return &cs, nil
69+
}
70+
71+
// NewForConfigOrDie creates a new Clientset for the given config and
72+
// panics if there is an error in the config.
73+
func NewForConfigOrDie(c *rest.Config) *Clientset {
74+
var cs Clientset
75+
cs.ComposeV1beta1Client = composev1beta1.NewForConfigOrDie(c)
76+
77+
cs.DiscoveryClient = discovery.NewDiscoveryClientForConfigOrDie(c)
78+
return &cs
79+
}
80+
81+
// New creates a new Clientset for the given RESTClient.
82+
func New(c rest.Interface) *Clientset {
83+
var cs Clientset
84+
cs.ComposeV1beta1Client = composev1beta1.New(c)
85+
86+
cs.DiscoveryClient = discovery.NewDiscoveryClient(c)
87+
return &cs
88+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// This package is generated by client-gen with custom arguments.
2+
3+
// This package has the automatically generated clientset.
4+
package clientset
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// This package is generated by client-gen with custom arguments.
2+
3+
// This package contains the scheme of the automatically generated clientset.
4+
package scheme
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package scheme
2+
3+
import (
4+
composev1beta1 "github.com/docker/cli/cli/command/stack/kubernetes/api/compose/v1beta1"
5+
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
6+
runtime "k8s.io/apimachinery/pkg/runtime"
7+
schema "k8s.io/apimachinery/pkg/runtime/schema"
8+
serializer "k8s.io/apimachinery/pkg/runtime/serializer"
9+
)
10+
11+
var Scheme = runtime.NewScheme()
12+
var Codecs = serializer.NewCodecFactory(Scheme)
13+
var ParameterCodec = runtime.NewParameterCodec(Scheme)
14+
15+
func init() {
16+
v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"})
17+
AddToScheme(Scheme)
18+
}
19+
20+
// AddToScheme adds all types of this clientset into the given scheme. This allows composition
21+
// of clientsets, like in:
22+
//
23+
// import (
24+
// "k8s.io/client-go/kubernetes"
25+
// clientsetscheme "k8s.io/client-go/kuberentes/scheme"
26+
// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme"
27+
// )
28+
//
29+
// kclientset, _ := kubernetes.NewForConfig(c)
30+
// aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)
31+
//
32+
// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types
33+
// correctly.
34+
func AddToScheme(scheme *runtime.Scheme) {
35+
composev1beta1.AddToScheme(scheme)
36+
37+
}

0 commit comments

Comments
 (0)