mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Add swarmkit fields to stack service.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
This commit is contained in:
parent
0884e3c868
commit
13384ba34b
2 changed files with 111 additions and 33 deletions
|
@ -5,7 +5,6 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
|
@ -19,6 +18,8 @@ import (
|
||||||
"github.com/docker/docker/cli"
|
"github.com/docker/docker/cli"
|
||||||
"github.com/docker/docker/cli/command"
|
"github.com/docker/docker/cli/command"
|
||||||
servicecmd "github.com/docker/docker/cli/command/service"
|
servicecmd "github.com/docker/docker/cli/command/service"
|
||||||
|
runconfigopts "github.com/docker/docker/runconfig/opts"
|
||||||
|
"github.com/docker/docker/opts"
|
||||||
"github.com/docker/go-connections/nat"
|
"github.com/docker/go-connections/nat"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -343,23 +344,37 @@ func convertService(
|
||||||
return swarm.ServiceSpec{}, err
|
return swarm.ServiceSpec{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resources, err := convertResources(service.Deploy.Resources)
|
||||||
|
if err != nil {
|
||||||
|
return swarm.ServiceSpec{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
restartPolicy, err := convertRestartPolicy(
|
||||||
|
service.Restart, service.Deploy.RestartPolicy)
|
||||||
|
if err != nil {
|
||||||
|
return swarm.ServiceSpec{}, err
|
||||||
|
}
|
||||||
|
|
||||||
serviceSpec := swarm.ServiceSpec{
|
serviceSpec := swarm.ServiceSpec{
|
||||||
Annotations: swarm.Annotations{
|
Annotations: swarm.Annotations{
|
||||||
Name: name,
|
Name: name,
|
||||||
Labels: getStackLabels(namespace, service.Labels),
|
Labels: getStackLabels(namespace, service.Deploy.Labels),
|
||||||
},
|
},
|
||||||
TaskTemplate: swarm.TaskSpec{
|
TaskTemplate: swarm.TaskSpec{
|
||||||
ContainerSpec: swarm.ContainerSpec{
|
ContainerSpec: swarm.ContainerSpec{
|
||||||
Image: service.Image,
|
Image: service.Image,
|
||||||
Command: service.Entrypoint,
|
Command: service.Entrypoint,
|
||||||
Args: service.Command,
|
Args: service.Command,
|
||||||
Hostname: service.Hostname,
|
Hostname: service.Hostname,
|
||||||
Env: convertEnvironment(service.Environment),
|
Env: convertEnvironment(service.Environment),
|
||||||
Labels: getStackLabels(namespace, service.Deploy.Labels),
|
Labels: getStackLabels(namespace, service.Labels),
|
||||||
Dir: service.WorkingDir,
|
Dir: service.WorkingDir,
|
||||||
User: service.User,
|
User: service.User,
|
||||||
Mounts: mounts,
|
Mounts: mounts,
|
||||||
|
StopGracePeriod: service.StopGracePeriod,
|
||||||
},
|
},
|
||||||
|
Resources: resources,
|
||||||
|
RestartPolicy: restartPolicy,
|
||||||
Placement: &swarm.Placement{
|
Placement: &swarm.Placement{
|
||||||
Constraints: service.Deploy.Placement.Constraints,
|
Constraints: service.Deploy.Placement.Constraints,
|
||||||
},
|
},
|
||||||
|
@ -367,20 +382,77 @@ func convertService(
|
||||||
EndpointSpec: endpoint,
|
EndpointSpec: endpoint,
|
||||||
Mode: mode,
|
Mode: mode,
|
||||||
Networks: convertNetworks(service.Networks, namespace, service.Name),
|
Networks: convertNetworks(service.Networks, namespace, service.Name),
|
||||||
|
UpdateConfig: convertUpdateConfig(service.Deploy.UpdateConfig),
|
||||||
}
|
}
|
||||||
|
|
||||||
if service.StopGracePeriod != nil {
|
|
||||||
stopGrace, err := time.ParseDuration(*service.StopGracePeriod)
|
|
||||||
if err != nil {
|
|
||||||
return swarm.ServiceSpec{}, err
|
|
||||||
}
|
|
||||||
serviceSpec.TaskTemplate.ContainerSpec.StopGracePeriod = &stopGrace
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: convert mounts
|
|
||||||
return serviceSpec, nil
|
return serviceSpec, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func convertRestartPolicy(restart string, source *composetypes.RestartPolicy) (*swarm.RestartPolicy, error) {
|
||||||
|
// TODO: log if restart is being ignored
|
||||||
|
if source == nil {
|
||||||
|
policy, err := runconfigopts.ParseRestartPolicy(restart)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// TODO: is this an accurate convertion?
|
||||||
|
switch {
|
||||||
|
case policy.IsNone(), policy.IsAlways(), policy.IsUnlessStopped():
|
||||||
|
return nil, nil
|
||||||
|
case policy.IsOnFailure():
|
||||||
|
attempts := uint64(policy.MaximumRetryCount)
|
||||||
|
return &swarm.RestartPolicy{
|
||||||
|
Condition: swarm.RestartPolicyConditionOnFailure,
|
||||||
|
MaxAttempts: &attempts,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &swarm.RestartPolicy{
|
||||||
|
Condition: swarm.RestartPolicyCondition(source.Condition),
|
||||||
|
Delay: source.Delay,
|
||||||
|
MaxAttempts: source.MaxAttempts,
|
||||||
|
Window: source.Window,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func convertUpdateConfig(source *composetypes.UpdateConfig) *swarm.UpdateConfig {
|
||||||
|
if source == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &swarm.UpdateConfig{
|
||||||
|
Parallelism: source.Parallelism,
|
||||||
|
Delay: source.Delay,
|
||||||
|
FailureAction: source.FailureAction,
|
||||||
|
Monitor: source.Monitor,
|
||||||
|
MaxFailureRatio: source.MaxFailureRatio,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func convertResources(source composetypes.Resources) (*swarm.ResourceRequirements, error) {
|
||||||
|
resources := &swarm.ResourceRequirements{}
|
||||||
|
if source.Limits != nil {
|
||||||
|
cpus, err := opts.ParseCPUs(source.Limits.NanoCPUs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
resources.Limits = &swarm.Resources{
|
||||||
|
NanoCPUs: cpus,
|
||||||
|
MemoryBytes: int64(source.Limits.MemoryBytes),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if source.Reservations != nil {
|
||||||
|
cpus, err := opts.ParseCPUs(source.Reservations.NanoCPUs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
resources.Reservations = &swarm.Resources{
|
||||||
|
NanoCPUs: cpus,
|
||||||
|
MemoryBytes: int64(source.Reservations.MemoryBytes),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return resources, nil
|
||||||
|
}
|
||||||
|
|
||||||
func convertEndpointSpec(source []string) (*swarm.EndpointSpec, error) {
|
func convertEndpointSpec(source []string) (*swarm.EndpointSpec, error) {
|
||||||
portConfigs := []swarm.PortConfig{}
|
portConfigs := []swarm.PortConfig{}
|
||||||
ports, portBindings, err := nat.ParsePortSpecs(source)
|
ports, portBindings, err := nat.ParsePortSpecs(source)
|
||||||
|
@ -407,17 +479,17 @@ func convertEnvironment(source map[string]string) []string {
|
||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
|
|
||||||
func convertDeployMode(mode string, replicas uint64) (swarm.ServiceMode, error) {
|
func convertDeployMode(mode string, replicas *uint64) (swarm.ServiceMode, error) {
|
||||||
serviceMode := swarm.ServiceMode{}
|
serviceMode := swarm.ServiceMode{}
|
||||||
|
|
||||||
switch mode {
|
switch mode {
|
||||||
case "global":
|
case "global":
|
||||||
if replicas != 0 {
|
if replicas != nil {
|
||||||
return serviceMode, fmt.Errorf("replicas can only be used with replicated mode")
|
return serviceMode, fmt.Errorf("replicas can only be used with replicated mode")
|
||||||
}
|
}
|
||||||
serviceMode.Global = &swarm.GlobalService{}
|
serviceMode.Global = &swarm.GlobalService{}
|
||||||
case "replicated":
|
case "replicated":
|
||||||
serviceMode.Replicated = &swarm.ReplicatedService{Replicas: &replicas}
|
serviceMode.Replicated = &swarm.ReplicatedService{Replicas: replicas}
|
||||||
default:
|
default:
|
||||||
return serviceMode, fmt.Errorf("Unknown mode: %s", mode)
|
return serviceMode, fmt.Errorf("Unknown mode: %s", mode)
|
||||||
}
|
}
|
||||||
|
|
26
opts/opts.go
26
opts/opts.go
|
@ -331,16 +331,9 @@ func (c *NanoCPUs) String() string {
|
||||||
|
|
||||||
// Set sets the value of the NanoCPU by passing a string
|
// Set sets the value of the NanoCPU by passing a string
|
||||||
func (c *NanoCPUs) Set(value string) error {
|
func (c *NanoCPUs) Set(value string) error {
|
||||||
cpu, ok := new(big.Rat).SetString(value)
|
cpus, err := ParseCPUs(value)
|
||||||
if !ok {
|
*c = NanoCPUs(cpus)
|
||||||
return fmt.Errorf("Failed to parse %v as a rational number", value)
|
return err
|
||||||
}
|
|
||||||
nano := cpu.Mul(cpu, big.NewRat(1e9, 1))
|
|
||||||
if !nano.IsInt() {
|
|
||||||
return fmt.Errorf("value is too precise")
|
|
||||||
}
|
|
||||||
*c = NanoCPUs(nano.Num().Int64())
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Type returns the type
|
// Type returns the type
|
||||||
|
@ -352,3 +345,16 @@ func (c *NanoCPUs) Type() string {
|
||||||
func (c *NanoCPUs) Value() int64 {
|
func (c *NanoCPUs) Value() int64 {
|
||||||
return int64(*c)
|
return int64(*c)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ParseCPUs takes a string ratio and returns an integer value of nano cpus
|
||||||
|
func ParseCPUs(value string) (int64, error) {
|
||||||
|
cpu, ok := new(big.Rat).SetString(value)
|
||||||
|
if !ok {
|
||||||
|
return 0, fmt.Errorf("failed to parse %v as a rational number", value)
|
||||||
|
}
|
||||||
|
nano := cpu.Mul(cpu, big.NewRat(1e9, 1))
|
||||||
|
if !nano.IsInt() {
|
||||||
|
return 0, fmt.Errorf("value is too precise")
|
||||||
|
}
|
||||||
|
return nano.Num().Int64(), nil
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue