Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

api: Centralize defaults and add InsertDefaults flag #1744

Merged
merged 1 commit into from
Mar 30, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
278 changes: 157 additions & 121 deletions api/control.pb.go

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions api/control.proto
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ message CreateServiceResponse {

message GetServiceRequest {
string service_id = 1;
bool insert_defaults = 2;
}

message GetServiceResponse {
Expand Down
83 changes: 83 additions & 0 deletions api/defaults/service.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package defaults

import (
"time"

"github.com/docker/swarmkit/api"
"github.com/docker/swarmkit/api/deepcopy"
gogotypes "github.com/gogo/protobuf/types"
)

// Service is a ServiceSpec object with all fields filled in using default
// values.
var Service = api.ServiceSpec{
Task: api.TaskSpec{
Runtime: &api.TaskSpec_Container{
Container: &api.ContainerSpec{
StopGracePeriod: gogotypes.DurationProto(10 * time.Second),
PullOptions: &api.ContainerSpec_PullOptions{},
DNSConfig: &api.ContainerSpec_DNSConfig{},
},
},
Resources: &api.ResourceRequirements{},
Restart: &api.RestartPolicy{
Delay: gogotypes.DurationProto(5 * time.Second),
},
Placement: &api.Placement{},
},
Update: &api.UpdateConfig{
FailureAction: api.UpdateConfig_PAUSE,
Monitor: gogotypes.DurationProto(5 * time.Second),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are more parameters like parallelism, update-delay, etc.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The default value of UpdateDelay is 0, so it's not necessary to include it here. You're right that Parallelism should be included. It used to default to 0, but now defaults to 1. Fixing.

Parallelism: 1,
Order: api.UpdateConfig_STOP_FIRST,
},
}

// InterpolateService returns a ServiceSpec based on the provided spec, which
// has all unspecified values filled in with default values.
func InterpolateService(origSpec *api.ServiceSpec) *api.ServiceSpec {
spec := origSpec.Copy()

container := spec.Task.GetContainer()
defaultContainer := Service.Task.GetContainer()
if container != nil {
if container.StopGracePeriod == nil {
container.StopGracePeriod = &gogotypes.Duration{}
deepcopy.Copy(container.StopGracePeriod, defaultContainer.StopGracePeriod)
}
if container.PullOptions == nil {
container.PullOptions = defaultContainer.PullOptions.Copy()
}
if container.DNSConfig == nil {
container.DNSConfig = defaultContainer.DNSConfig.Copy()
}
}

if spec.Task.Resources == nil {
spec.Task.Resources = Service.Task.Resources.Copy()
}

if spec.Task.Restart == nil {
spec.Task.Restart = Service.Task.Restart.Copy()
} else {
if spec.Task.Restart.Delay == nil {
spec.Task.Restart.Delay = &gogotypes.Duration{}
deepcopy.Copy(spec.Task.Restart.Delay, Service.Task.Restart.Delay)
}
}

if spec.Task.Placement == nil {
spec.Task.Placement = Service.Task.Placement.Copy()
}

if spec.Update == nil {
spec.Update = Service.Update.Copy()
} else {
if spec.Update.Monitor == nil {
spec.Update.Monitor = &gogotypes.Duration{}
deepcopy.Copy(spec.Update.Monitor, Service.Update.Monitor)
}
}

return spec
}
5 changes: 5 additions & 0 deletions manager/controlapi/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (

"github.com/docker/distribution/reference"
"github.com/docker/swarmkit/api"
"github.com/docker/swarmkit/api/defaults"
"github.com/docker/swarmkit/api/naming"
"github.com/docker/swarmkit/identity"
"github.com/docker/swarmkit/manager/allocator"
Expand Down Expand Up @@ -525,6 +526,10 @@ func (s *Server) GetService(ctx context.Context, request *api.GetServiceRequest)
return nil, grpc.Errorf(codes.NotFound, "service %s not found", request.ServiceID)
}

if request.InsertDefaults {
service.Spec = *defaults.InterpolateService(&service.Spec)
}

return &api.GetServiceResponse{
Service: service,
}, nil
Expand Down
5 changes: 3 additions & 2 deletions manager/orchestrator/restart/restart.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (

"github.com/docker/go-events"
"github.com/docker/swarmkit/api"
"github.com/docker/swarmkit/api/defaults"
"github.com/docker/swarmkit/log"
"github.com/docker/swarmkit/manager/orchestrator"
"github.com/docker/swarmkit/manager/state"
Expand Down Expand Up @@ -159,10 +160,10 @@ func (r *Supervisor) Restart(ctx context.Context, tx store.Tx, cluster *api.Clus
restartDelay, err = gogotypes.DurationFromProto(t.Spec.Restart.Delay)
if err != nil {
log.G(ctx).WithError(err).Error("invalid restart delay; using default")
restartDelay = orchestrator.DefaultRestartDelay
restartDelay, _ = gogotypes.DurationFromProto(defaults.Service.Task.Restart.Delay)
}
} else {
restartDelay = orchestrator.DefaultRestartDelay
restartDelay, _ = gogotypes.DurationFromProto(defaults.Service.Task.Restart.Delay)
}
}

Expand Down
4 changes: 0 additions & 4 deletions manager/orchestrator/task.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,6 @@ import (
"github.com/docker/swarmkit/protobuf/ptypes"
)

// DefaultRestartDelay is the restart delay value to use when none is
// specified.
const DefaultRestartDelay = 5 * time.Second

// NewTask creates a new task.
func NewTask(cluster *api.Cluster, service *api.Service, slot uint64, nodeID string) *api.Task {
var logDriver *api.Driver
Expand Down
6 changes: 3 additions & 3 deletions manager/orchestrator/taskinit/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import (
"time"

"github.com/docker/swarmkit/api"
"github.com/docker/swarmkit/api/defaults"
"github.com/docker/swarmkit/log"
"github.com/docker/swarmkit/manager/orchestrator"
"github.com/docker/swarmkit/manager/orchestrator/restart"
"github.com/docker/swarmkit/manager/state/store"
gogotypes "github.com/gogo/protobuf/types"
Expand Down Expand Up @@ -55,13 +55,13 @@ func CheckTasks(ctx context.Context, s *store.MemoryStore, readTx store.ReadTx,
if t.DesiredState != api.TaskStateReady || t.Status.State > api.TaskStateRunning {
continue
}
restartDelay := orchestrator.DefaultRestartDelay
restartDelay, _ := gogotypes.DurationFromProto(defaults.Service.Task.Restart.Delay)
if t.Spec.Restart != nil && t.Spec.Restart.Delay != nil {
var err error
restartDelay, err = gogotypes.DurationFromProto(t.Spec.Restart.Delay)
if err != nil {
log.G(ctx).WithError(err).Error("invalid restart delay")
restartDelay = orchestrator.DefaultRestartDelay
restartDelay, _ = gogotypes.DurationFromProto(defaults.Service.Task.Restart.Delay)
}
}
if restartDelay != 0 {
Expand Down
19 changes: 8 additions & 11 deletions manager/orchestrator/update/updater.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (

"github.com/docker/go-events"
"github.com/docker/swarmkit/api"
"github.com/docker/swarmkit/api/defaults"
"github.com/docker/swarmkit/log"
"github.com/docker/swarmkit/manager/orchestrator"
"github.com/docker/swarmkit/manager/orchestrator/restart"
Expand All @@ -21,8 +22,6 @@ import (
gogotypes "github.com/gogo/protobuf/types"
)

const defaultMonitor = 5 * time.Second

// Supervisor supervises a set of updates. It's responsible for keeping track of updates,
// shutting them down and replacing them.
type Supervisor struct {
Expand Down Expand Up @@ -156,14 +155,12 @@ func (u *Updater) Run(ctx context.Context, slots []orchestrator.Slot) {
u.startUpdate(ctx, service.ID)
}

var (
parallelism = 1
delay time.Duration
failureAction = api.UpdateConfig_PAUSE
allowedFailureFraction = float32(0)
monitoringPeriod = defaultMonitor
order = api.UpdateConfig_STOP_FIRST
)
delay := defaults.Service.Update.Delay
parallelism := int(defaults.Service.Update.Parallelism)
failureAction := defaults.Service.Update.FailureAction
allowedFailureFraction := defaults.Service.Update.MaxFailureRatio
monitoringPeriod, _ := gogotypes.DurationFromProto(defaults.Service.Update.Monitor)
order := defaults.Service.Update.Order

updateConfig := service.Spec.Update
if service.UpdateStatus != nil && service.UpdateStatus.State == api.UpdateStatus_ROLLBACK_STARTED {
Expand All @@ -181,7 +178,7 @@ func (u *Updater) Run(ctx context.Context, slots []orchestrator.Slot) {
if updateConfig.Monitor != nil {
monitoringPeriod, err = gogotypes.DurationFromProto(updateConfig.Monitor)
if err != nil {
monitoringPeriod = defaultMonitor
monitoringPeriod, _ = gogotypes.DurationFromProto(defaults.Service.Update.Monitor)
}
}
}
Expand Down