Reform update strategy types
It's convenient to be able to leave out the update strategy, since there is only one possible value at present; and if there were alternatives, the present choice would still be a reasonable default. However, with the format as it is, this doesn't work with OpenAPIv3 schema, so you have to supply a value, even though there are no parameters: ```yaml spec: update: setters: {} ``` A more self-explanatory format which _does_ work with defaulting is to name the strategy rather than relying on the presence of a field: ```yaml spec: update: strategy: Setters ``` The whole `update` field can be elided and left to default. This doesn't preclude having other strategies later, even those with parameters, e.g., ```yaml spec: update: strategy: Foo fooParam: 5 ``` This commit changes the API types and code that uses them, and the CRD manifest, and adds a test that checks the defaulting actually works. Signed-off-by: Michael Bridgen <michael@weave.works>
This commit is contained in:
parent
a804fcdfc8
commit
bd76267be5
|
@ -36,9 +36,10 @@ type ImageUpdateAutomationSpec struct {
|
|||
// +required
|
||||
Interval metav1.Duration `json:"interval"`
|
||||
// Update gives the specification for how to update the files in
|
||||
// the repository
|
||||
// +required
|
||||
Update UpdateStrategy `json:"update"`
|
||||
// the repository. This can be left empty, to use the default
|
||||
// value.
|
||||
// +kubebuilder:default={"strategy":"Setters"}
|
||||
Update *UpdateStrategy `json:"update,omitempty"`
|
||||
// Commit specifies how to commit to the git repo
|
||||
// +required
|
||||
Commit CommitSpec `json:"commit"`
|
||||
|
@ -59,18 +60,25 @@ type GitCheckoutSpec struct {
|
|||
Branch string `json:"branch"`
|
||||
}
|
||||
|
||||
// UpdateStrategy is a union of the various strategies for updating
|
||||
// the git repository.
|
||||
type UpdateStrategy struct {
|
||||
// Setters if present means update workloads using setters, via
|
||||
// fields marked in the files themselves.
|
||||
// +optional
|
||||
Setters *SettersStrategy `json:"setters,omitempty"`
|
||||
}
|
||||
// UpdateStrategyName is the type for names that go in
|
||||
// .update.strategy. NB the value in the const immediately below.
|
||||
// +kubebuilder:validation:Enum=Setters
|
||||
type UpdateStrategyName string
|
||||
|
||||
// SettersStrategy specifies how to use kyaml setters to update the
|
||||
// git repository.
|
||||
type SettersStrategy struct {
|
||||
const (
|
||||
// UpdateStrategySetters is the name of the update strategy that
|
||||
// uses kyaml setters. NB the value in the enum annotation for the
|
||||
// type, above.
|
||||
UpdateStrategySetters UpdateStrategyName = "Setters"
|
||||
)
|
||||
|
||||
// UpdateStrategy is a union of the various strategies for updating
|
||||
// the Git repository. Parameters for each strategy (if any) can be
|
||||
// inlined here.
|
||||
type UpdateStrategy struct {
|
||||
// Strategy names the strategy to be used.
|
||||
// +required
|
||||
Strategy UpdateStrategyName `json:"strategy"`
|
||||
}
|
||||
|
||||
// CommitSpec specifies how to commit changes to the git repository
|
||||
|
|
|
@ -120,7 +120,11 @@ func (in *ImageUpdateAutomationSpec) DeepCopyInto(out *ImageUpdateAutomationSpec
|
|||
*out = *in
|
||||
out.Checkout = in.Checkout
|
||||
out.Interval = in.Interval
|
||||
in.Update.DeepCopyInto(&out.Update)
|
||||
if in.Update != nil {
|
||||
in, out := &in.Update, &out.Update
|
||||
*out = new(UpdateStrategy)
|
||||
**out = **in
|
||||
}
|
||||
out.Commit = in.Commit
|
||||
}
|
||||
|
||||
|
@ -165,29 +169,9 @@ func (in *ImageUpdateAutomationStatus) DeepCopy() *ImageUpdateAutomationStatus {
|
|||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *SettersStrategy) DeepCopyInto(out *SettersStrategy) {
|
||||
*out = *in
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SettersStrategy.
|
||||
func (in *SettersStrategy) DeepCopy() *SettersStrategy {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(SettersStrategy)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *UpdateStrategy) DeepCopyInto(out *UpdateStrategy) {
|
||||
*out = *in
|
||||
if in.Setters != nil {
|
||||
in, out := &in.Setters, &out.Setters
|
||||
*out = new(SettersStrategy)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UpdateStrategy.
|
||||
|
|
|
@ -90,19 +90,24 @@ spec:
|
|||
until it is unset (or set to false). Defaults to false.
|
||||
type: boolean
|
||||
update:
|
||||
default:
|
||||
strategy: Setters
|
||||
description: Update gives the specification for how to update the
|
||||
files in the repository
|
||||
files in the repository. This can be left empty, to use the default
|
||||
value.
|
||||
properties:
|
||||
setters:
|
||||
description: Setters if present means update workloads using setters,
|
||||
via fields marked in the files themselves.
|
||||
type: object
|
||||
strategy:
|
||||
description: Strategy names the strategy to be used.
|
||||
enum:
|
||||
- Setters
|
||||
type: string
|
||||
required:
|
||||
- strategy
|
||||
type: object
|
||||
required:
|
||||
- checkout
|
||||
- commit
|
||||
- interval
|
||||
- update
|
||||
type: object
|
||||
status:
|
||||
description: ImageUpdateAutomationStatus defines the observed state of
|
||||
|
|
|
@ -3,5 +3,12 @@ kind: ImageUpdateAutomation
|
|||
metadata:
|
||||
name: imageupdateautomation-sample
|
||||
spec:
|
||||
# Add fields here
|
||||
foo: bar
|
||||
checkout:
|
||||
gitRepositoryRef:
|
||||
name: app-repo
|
||||
branch: main
|
||||
interval: 5m
|
||||
# update strategy is left to default to "Setters"
|
||||
commit:
|
||||
authorName: Fluxbot
|
||||
authorEmail: fluxbot@example.com
|
||||
|
|
|
@ -168,9 +168,8 @@ func (r *ImageUpdateAutomationReconciler) Reconcile(ctx context.Context, req ctr
|
|||
|
||||
log.V(debug).Info("cloned git repository", "gitrepository", originName, "branch", auto.Spec.Checkout.Branch, "working", tmp)
|
||||
|
||||
updateStrat := auto.Spec.Update
|
||||
switch {
|
||||
case updateStrat.Setters != nil:
|
||||
case auto.Spec.Update != nil && auto.Spec.Update.Strategy == imagev1.UpdateStrategySetters:
|
||||
// For setters we first want to compile a list of _all_ the
|
||||
// policies in the same namespace (maybe in the future this
|
||||
// could be filtered by the automation object).
|
||||
|
@ -185,8 +184,8 @@ func (r *ImageUpdateAutomationReconciler) Reconcile(ctx context.Context, req ctr
|
|||
default:
|
||||
log.Info("no update strategy given in the spec")
|
||||
// no sense rescheduling until this resource changes
|
||||
r.event(ctx, auto, events.EventSeverityInfo, "no update strategy in spec, failing trivially")
|
||||
imagev1.SetImageUpdateAutomationReadiness(&auto, metav1.ConditionFalse, imagev1.NoStrategyReason, "no update strategy is given for object")
|
||||
r.event(ctx, auto, events.EventSeverityInfo, "no known update strategy in spec, failing trivially")
|
||||
imagev1.SetImageUpdateAutomationReadiness(&auto, metav1.ConditionFalse, imagev1.NoStrategyReason, "no known update strategy is given for object")
|
||||
err := r.Status().Update(ctx, &auto)
|
||||
return ctrl.Result{}, err
|
||||
}
|
||||
|
|
|
@ -182,6 +182,48 @@ var _ = Describe("ImageUpdateAutomation", func() {
|
|||
Expect(k8sClient.Delete(context.Background(), policy)).To(Succeed())
|
||||
})
|
||||
|
||||
Context("defaulting", func() {
|
||||
var key types.NamespacedName
|
||||
var auto *imagev1.ImageUpdateAutomation
|
||||
|
||||
BeforeEach(func() {
|
||||
key = types.NamespacedName{
|
||||
Namespace: gitRepoKey.Namespace,
|
||||
Name: "update-" + randStringRunes(5),
|
||||
}
|
||||
auto = &imagev1.ImageUpdateAutomation{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: key.Name,
|
||||
Namespace: key.Namespace,
|
||||
},
|
||||
Spec: imagev1.ImageUpdateAutomationSpec{
|
||||
Interval: metav1.Duration{Duration: 2 * time.Hour}, // this is to ensure any subsequent run should be outside the scope of the testing
|
||||
Checkout: imagev1.GitCheckoutSpec{
|
||||
GitRepositoryRef: corev1.LocalObjectReference{
|
||||
Name: "garbage",
|
||||
},
|
||||
Branch: branch,
|
||||
},
|
||||
// leave Update field out
|
||||
Commit: imagev1.CommitSpec{
|
||||
MessageTemplate: commitMessage,
|
||||
},
|
||||
},
|
||||
}
|
||||
Expect(k8sClient.Create(context.Background(), auto)).To(Succeed())
|
||||
})
|
||||
|
||||
AfterEach(func() {
|
||||
Expect(k8sClient.Delete(context.Background(), auto)).To(Succeed())
|
||||
})
|
||||
|
||||
It("defaults .spec.update to {strategy: Setters}", func() {
|
||||
var fetchedAuto imagev1.ImageUpdateAutomation
|
||||
Expect(k8sClient.Get(context.Background(), key, &fetchedAuto)).To(Succeed())
|
||||
Expect(fetchedAuto.Spec.Update).To(Equal(&imagev1.UpdateStrategy{Strategy: imagev1.UpdateStrategySetters}))
|
||||
})
|
||||
})
|
||||
|
||||
Context("with Setters", func() {
|
||||
|
||||
var (
|
||||
|
@ -220,8 +262,8 @@ var _ = Describe("ImageUpdateAutomation", func() {
|
|||
},
|
||||
Branch: branch,
|
||||
},
|
||||
Update: imagev1.UpdateStrategy{
|
||||
Setters: &imagev1.SettersStrategy{},
|
||||
Update: &imagev1.UpdateStrategy{
|
||||
Strategy: imagev1.UpdateStrategySetters,
|
||||
},
|
||||
Commit: imagev1.CommitSpec{
|
||||
MessageTemplate: commitMessage,
|
||||
|
|
Loading…
Reference in New Issue