diff --git a/cli/cli.go b/cli/cli.go index 8fa866133a..b0346cbbc8 100644 --- a/cli/cli.go +++ b/cli/cli.go @@ -7,6 +7,7 @@ import ( log "github.com/Sirupsen/logrus" "github.com/codegangsta/cli" + "github.com/docker/swarm/experimental" "github.com/docker/swarm/version" ) @@ -32,6 +33,11 @@ func Run() { Value: "info", Usage: fmt.Sprintf("Log level (options: debug, info, warn, error, fatal, panic)"), }, + + cli.BoolFlag{ + Name: "experimental", + Usage: "enable experimental features", + }, } // logs @@ -49,6 +55,8 @@ func Run() { log.SetLevel(log.DebugLevel) } + experimental.ENABLED = c.Bool("experimental") + return nil } diff --git a/cli/manage.go b/cli/manage.go index baca69b45d..b8a3bd83de 100644 --- a/cli/manage.go +++ b/cli/manage.go @@ -17,6 +17,7 @@ import ( "github.com/docker/swarm/cluster" "github.com/docker/swarm/cluster/mesos" "github.com/docker/swarm/cluster/swarm" + "github.com/docker/swarm/experimental" "github.com/docker/swarm/leadership" "github.com/docker/swarm/scheduler" "github.com/docker/swarm/scheduler/filter" @@ -324,6 +325,9 @@ func manage(c *cli.Context) { server.SetHandler(api.NewPrimary(cl, tlsConfig, &statusHandler{cl, nil, nil}, c.GlobalBool("debug"), c.Bool("cors"))) } - cluster.NewWatchdog(cl) + if experimental.ENABLED { + log.Warn("WARNING: rescheduling is currently experimental, use at your own risks") + cluster.NewWatchdog(cl) + } log.Fatal(server.ListenAndServe()) } diff --git a/cluster/config.go b/cluster/config.go index d74c408153..57822f99d9 100644 --- a/cluster/config.go +++ b/cluster/config.go @@ -6,6 +6,7 @@ import ( "fmt" "strings" + "github.com/docker/swarm/experimental" "github.com/samalba/dockerclient" ) @@ -86,25 +87,26 @@ func BuildContainerConfig(c dockerclient.ContainerConfig) *ContainerConfig { json.Unmarshal([]byte(labels), &constraints) } - // parse reschedule policy from labels (ex. docker run --label 'com.docker.swarm.reschedule-policies=on-node-failure') - if labels, ok := c.Labels[SwarmLabelNamespace+".reschedule-policies"]; ok { - json.Unmarshal([]byte(labels), &reschedulePolicies) + if experimental.ENABLED { + // parse reschedule policy from labels (ex. docker run --label 'com.docker.swarm.reschedule-policies=on-node-failure') + if labels, ok := c.Labels[SwarmLabelNamespace+".reschedule-policies"]; ok { + json.Unmarshal([]byte(labels), &reschedulePolicies) + } } - // parse affinities/constraints/reschedule policies from env (ex. docker run -e affinity:container==redis -e affinity:image==nginx -e constraint:region==us-east -e constraint:storage==ssd -e reschedule:off) for _, e := range c.Env { if ok, key, value := parseEnv(e); ok && key == "affinity" { affinities = append(affinities, value) } else if ok && key == "constraint" { constraints = append(constraints, value) - } else if ok && key == "reschedule" { + } else if experimental.ENABLED && ok && key == "reschedule" { reschedulePolicies = append(reschedulePolicies, value) } else { env = append(env, e) } } - // remove affinities/constraints from env + // remove affinities/constraints/reschedule policies from env c.Env = env // store affinities in labels @@ -121,10 +123,12 @@ func BuildContainerConfig(c dockerclient.ContainerConfig) *ContainerConfig { } } - // store reschedule policies in labels - if len(reschedulePolicies) > 0 { - if labels, err := json.Marshal(reschedulePolicies); err == nil { - c.Labels[SwarmLabelNamespace+".reschedule-policies"] = string(labels) + if experimental.ENABLED { + // store reschedule policies in labels + if len(reschedulePolicies) > 0 { + if labels, err := json.Marshal(reschedulePolicies); err == nil { + c.Labels[SwarmLabelNamespace+".reschedule-policies"] = string(labels) + } } } @@ -217,19 +221,23 @@ func (c *ContainerConfig) HasReschedulePolicy(p string) bool { // Validate returns an error if the config isn't valid func (c *ContainerConfig) Validate() error { //TODO: add validation for affinities and constraints - reschedulePolicies := c.extractExprs("reschedule-policies") - if len(reschedulePolicies) > 1 { - return errors.New("too many reschedule policies") - } else if len(reschedulePolicies) == 1 { - valid := false - for _, validReschedulePolicy := range []string{"off", "on-node-failure"} { - if reschedulePolicies[0] == validReschedulePolicy { - valid = true + + if experimental.ENABLED { + reschedulePolicies := c.extractExprs("reschedule-policies") + if len(reschedulePolicies) > 1 { + return errors.New("too many reschedule policies") + } else if len(reschedulePolicies) == 1 { + valid := false + for _, validReschedulePolicy := range []string{"off", "on-node-failure"} { + if reschedulePolicies[0] == validReschedulePolicy { + valid = true + } + } + if !valid { + return fmt.Errorf("invalid reschedule policy: %s", reschedulePolicies[0]) } } - if !valid { - return fmt.Errorf("invalid reschedule policy: %s", reschedulePolicies[0]) - } } + return nil } diff --git a/experimental/README.md b/experimental/README.md index 78a0c1c048..6e7824fc4b 100644 --- a/experimental/README.md +++ b/experimental/README.md @@ -8,7 +8,15 @@ The information below describes each feature and the GitHub pull requests and issues associated with it. If necessary, links are provided to additional documentation on an issue. As an active Docker user and community member, please feel free to provide any feedback on these features you wish. +## Enable experimental features +To enable experimental feature, use the flag `-experimental` on swarm, for example: + +``` +$ swarm -experimental manage ... +# or +$ swarm -experimental join ... +``` ## Current experimental features diff --git a/experimental/experimental.go b/experimental/experimental.go new file mode 100644 index 0000000000..7d735a49b3 --- /dev/null +++ b/experimental/experimental.go @@ -0,0 +1,4 @@ +package experimental + +// ENABLED is set to true when the -experimental flag is set. +var ENABLED = false diff --git a/test/integration/helpers.bash b/test/integration/helpers.bash index 7a0bb781d0..82d0acdf13 100644 --- a/test/integration/helpers.bash +++ b/test/integration/helpers.bash @@ -117,7 +117,7 @@ function swarm_manage_no_wait() { local port=$(($SWARM_BASE_PORT + $i)) local host=127.0.0.1:$port - "$SWARM_BINARY" -l debug manage -H "$host" --heartbeat=1s $discovery & + "$SWARM_BINARY" -l debug -experimental manage -H "$host" --heartbeat=1s $discovery & SWARM_MANAGE_PID[$i]=$! SWARM_HOSTS[$i]=$host