Skip to content

Commit

Permalink
Add swarmkit fields to stack service.
Browse files Browse the repository at this point in the history
Needs compose-file re-vendor.

Signed-off-by: Daniel Nephin <dnephin@docker.com>
  • Loading branch information
dnephin committed Oct 31, 2016
1 parent 2a5843b commit 83e90fa
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 32 deletions.
26 changes: 16 additions & 10 deletions cli/command/service/opts.go
Expand Up @@ -48,16 +48,9 @@ func (c *nanoCPUs) String() 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
}

func (c *nanoCPUs) Type() string {
Expand All @@ -68,6 +61,19 @@ 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
}

// DurationOpt is an option type for time.Duration that uses a pointer. This
// allows us to get nil values outside, instead of defaulting to 0
type DurationOpt struct {
Expand Down
105 changes: 88 additions & 17 deletions cli/command/stack/deploy.go
Expand Up @@ -7,7 +7,6 @@ import (
"io/ioutil"
"os"
"strings"
"time"

"github.com/spf13/cobra"
"golang.org/x/net/context"
Expand All @@ -21,6 +20,7 @@ import (
"github.com/docker/docker/cli"
"github.com/docker/docker/cli/command"
servicecmd "github.com/docker/docker/cli/command/service"
"github.com/docker/docker/runconfig/opts"
"github.com/docker/go-connections/nat"
)

Expand Down Expand Up @@ -344,42 +344,113 @@ 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,
},
},
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)
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 := opts.ParseRestartPolicy(restart)
if err != nil {
return swarm.ServiceSpec{}, err
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
}
serviceSpec.TaskTemplate.ContainerSpec.StopGracePeriod = &stopGrace
}
return &swarm.RestartPolicy{
Condition: swarm.RestartPolicyCondition(source.Condition),
Delay: source.Delay,
MaxAttempts: source.MaxAttempts,
Window: source.Window,
}, nil
}

// TODO: convert mounts
return serviceSpec, 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 := servicecmd.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 := servicecmd.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) {
Expand Down
10 changes: 5 additions & 5 deletions vendor/src/github.com/aanand/compose-file/types/types.go
Expand Up @@ -88,11 +88,11 @@ type DeployConfig struct {
}

type UpdateConfig struct {
Parallelism int64
Parallelism uint64
Delay time.Duration
FailureAction string `mapstructure:"failure_action"`
Monitor time.Duration
MaxFailureRatio float64 `mapstructure:"max_failure_ratio"`
MaxFailureRatio float32 `mapstructure:"max_failure_ratio"`
}

type Resources struct {
Expand All @@ -110,9 +110,9 @@ type UnitBytes int64

type RestartPolicy struct {
Condition string
Delay time.Duration
MaxAttempts int64 `mapstructure:"max_attempts"`
Window time.Duration
Delay *time.Duration
MaxAttempts *uint64 `mapstructure:"max_attempts"`
Window *time.Duration
}

type Placement struct {
Expand Down

0 comments on commit 83e90fa

Please sign in to comment.