diff --git a/control/api/v1alpha1/module_types.go b/control/api/v1alpha1/module_types.go index a68df98..5179036 100644 --- a/control/api/v1alpha1/module_types.go +++ b/control/api/v1alpha1/module_types.go @@ -20,11 +20,38 @@ type ModuleSpec struct { // +optional Selector *metav1.LabelSelector `json:"selector,omitempty"` + // Rollout gives the strategy for updating the module + // +optional + // +kubebuilder:default={"strategy": "all-at-once"} + Rollout *RolloutSpec `json:"rollout,omitempty"` + // Sync gives the configuration to sync on assigned clusters. // +required Sync asmv1.Sync `json:"sync"` } +// RolloutSpec defines how the module rolls out changes when it is +// updated itself. +type RolloutSpec struct { + // Strategy names the rollout strategy to use when updating + // assigned clusters. + // +required + // +kubebuilder:validation:Enum=all-at-once;gradual + Strategy RolloutStrategyName `json:"strategy"` +} + +type RolloutStrategyName string + +const ( + // RolloutReplace names the strategy in which all module uses are + // replaced with the new definition. + RolloutReplace RolloutStrategyName = "all-at-once" + // RolloutGradual names the strategy in which module uses are + // updated gradually, making sure there are a limited number of + // clusters updating at any point. + RolloutGradual RolloutStrategyName = "gradual" +) + // ModuleStatus defines the observed state of Module type ModuleStatus struct { // ObservedSync gives the spec of the Sync as most recently acted diff --git a/control/api/v1alpha1/zz_generated.deepcopy.go b/control/api/v1alpha1/zz_generated.deepcopy.go index b236cf7..85dead2 100644 --- a/control/api/v1alpha1/zz_generated.deepcopy.go +++ b/control/api/v1alpha1/zz_generated.deepcopy.go @@ -96,6 +96,11 @@ func (in *ModuleSpec) DeepCopyInto(out *ModuleSpec) { *out = new(v1.LabelSelector) (*in).DeepCopyInto(*out) } + if in.Rollout != nil { + in, out := &in.Rollout, &out.Rollout + *out = new(RolloutSpec) + **out = **in + } in.Sync.DeepCopyInto(&out.Sync) } @@ -232,6 +237,21 @@ func (in *RemoteAssemblageStatus) DeepCopy() *RemoteAssemblageStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RolloutSpec) DeepCopyInto(out *RolloutSpec) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RolloutSpec. +func (in *RolloutSpec) DeepCopy() *RolloutSpec { + if in == nil { + return nil + } + out := new(RolloutSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SyncSummary) DeepCopyInto(out *SyncSummary) { *out = *in diff --git a/control/config/crd/bases/fleet.squaremo.dev_modules.yaml b/control/config/crd/bases/fleet.squaremo.dev_modules.yaml index 749f512..34b2022 100644 --- a/control/config/crd/bases/fleet.squaremo.dev_modules.yaml +++ b/control/config/crd/bases/fleet.squaremo.dev_modules.yaml @@ -52,6 +52,21 @@ spec: spec: description: ModuleSpec defines the desired state of Module properties: + rollout: + default: + strategy: all-at-once + description: Rollout gives the strategy for updating the module + properties: + strategy: + description: Strategy names the rollout strategy to use when updating + assigned clusters. + enum: + - all-at-once + - gradual + type: string + required: + - strategy + type: object selector: description: Selector gives the criteria for assigning this module to an cluster. If missing, no clusters are selected. If present diff --git a/docs/design/modules.md b/docs/design/modules.md index 0f1464e..4fa8b52 100644 --- a/docs/design/modules.md +++ b/docs/design/modules.md @@ -22,3 +22,6 @@ simplest is to update one cluster at a time, and wait until it is ready before u The trickier questions come when you consider what to do if the assigned clusters are still in a rollout when you begin another, i.e., there is already at least one cluster in updating state. Naively, you might simply wait until there are no clusters in updating state. + +What about if new clusters are assigned? There is nothing to do but give them the new configuration, +but does this count against the budget for clusters in updating state?