Add swarmkit fields to stack service.

Signed-off-by: Daniel Nephin <dnephin@docker.com>
This commit is contained in:
Daniel Nephin 2016-10-28 17:30:20 -04:00
Родитель 0884e3c868
Коммит 13384ba34b
2 изменённых файлов: 111 добавлений и 33 удалений

Просмотреть файл

@ -5,7 +5,6 @@ import (
"io/ioutil"
"os"
"strings"
"time"
"github.com/spf13/cobra"
"golang.org/x/net/context"
@ -19,6 +18,8 @@ import (
"github.com/docker/docker/cli"
"github.com/docker/docker/cli/command"
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"
)
@ -343,23 +344,37 @@ func convertService(
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{
Annotations: swarm.Annotations{
Name: name,
Labels: getStackLabels(namespace, service.Labels),
Labels: getStackLabels(namespace, service.Deploy.Labels),
},
TaskTemplate: swarm.TaskSpec{
ContainerSpec: swarm.ContainerSpec{
Image: service.Image,
Command: service.Entrypoint,
Args: service.Command,
Hostname: service.Hostname,
Env: convertEnvironment(service.Environment),
Labels: getStackLabels(namespace, service.Deploy.Labels),
Dir: service.WorkingDir,
User: service.User,
Mounts: mounts,
Image: service.Image,
Command: service.Entrypoint,
Args: service.Command,
Hostname: service.Hostname,
Env: convertEnvironment(service.Environment),
Labels: getStackLabels(namespace, service.Labels),
Dir: service.WorkingDir,
User: service.User,
Mounts: mounts,
StopGracePeriod: service.StopGracePeriod,
},
Resources: resources,
RestartPolicy: restartPolicy,
Placement: &swarm.Placement{
Constraints: service.Deploy.Placement.Constraints,
},
@ -367,20 +382,77 @@ func convertService(
EndpointSpec: endpoint,
Mode: mode,
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
}
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) {
portConfigs := []swarm.PortConfig{}
ports, portBindings, err := nat.ParsePortSpecs(source)
@ -407,17 +479,17 @@ func convertEnvironment(source map[string]string) []string {
return output
}
func convertDeployMode(mode string, replicas uint64) (swarm.ServiceMode, error) {
func convertDeployMode(mode string, replicas *uint64) (swarm.ServiceMode, error) {
serviceMode := swarm.ServiceMode{}
switch mode {
case "global":
if replicas != 0 {
if replicas != nil {
return serviceMode, fmt.Errorf("replicas can only be used with replicated mode")
}
serviceMode.Global = &swarm.GlobalService{}
case "replicated":
serviceMode.Replicated = &swarm.ReplicatedService{Replicas: &replicas}
serviceMode.Replicated = &swarm.ReplicatedService{Replicas: replicas}
default:
return serviceMode, fmt.Errorf("Unknown mode: %s", mode)
}

Просмотреть файл

@ -331,16 +331,9 @@ func (c *NanoCPUs) String() string {
// Set sets the value of the NanoCPU by passing a string
func (c *NanoCPUs) Set(value string) error {
cpu, ok := new(big.Rat).SetString(value)
if !ok {
return fmt.Errorf("Failed to parse %v as a rational number", value)
}
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
cpus, err := ParseCPUs(value)
*c = NanoCPUs(cpus)
return err
}
// Type returns the type
@ -352,3 +345,16 @@ func (c *NanoCPUs) Type() string {
func (c *NanoCPUs) Value() int64 {
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
}