Skip to content
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
4 changes: 4 additions & 0 deletions lib/resourcebuilder/apiext.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ func newCRDBuilder(config *rest.Config, m lib.Manifest) Interface {
}
}

func (b *crdBuilder) WithMode(m Mode) Interface {
return b
}

func (b *crdBuilder) WithModifier(f MetaV1ObjectModifierFunc) Interface {
b.modifier = f
return b
Expand Down
4 changes: 4 additions & 0 deletions lib/resourcebuilder/apireg.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ func newAPIServiceBuilder(config *rest.Config, m lib.Manifest) Interface {
}
}

func (b *apiServiceBuilder) WithMode(m Mode) Interface {
return b
}

func (b *apiServiceBuilder) WithModifier(f MetaV1ObjectModifierFunc) Interface {
b.modifier = f
return b
Expand Down
8 changes: 8 additions & 0 deletions lib/resourcebuilder/apps.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ func newDeploymentBuilder(config *rest.Config, m lib.Manifest) Interface {
}
}

func (b *deploymentBuilder) WithMode(m Mode) Interface {
return b
}

func (b *deploymentBuilder) WithModifier(f MetaV1ObjectModifierFunc) Interface {
b.modifier = f
return b
Expand Down Expand Up @@ -91,6 +95,10 @@ func newDaemonsetBuilder(config *rest.Config, m lib.Manifest) Interface {
}
}

func (b *daemonsetBuilder) WithMode(m Mode) Interface {
return b
}

func (b *daemonsetBuilder) WithModifier(f MetaV1ObjectModifierFunc) Interface {
b.modifier = f
return b
Expand Down
4 changes: 4 additions & 0 deletions lib/resourcebuilder/batch.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ func newJobBuilder(config *rest.Config, m lib.Manifest) Interface {
}
}

func (b *jobBuilder) WithMode(m Mode) Interface {
return b
}

func (b *jobBuilder) WithModifier(f MetaV1ObjectModifierFunc) Interface {
b.modifier = f
return b
Expand Down
16 changes: 16 additions & 0 deletions lib/resourcebuilder/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ func newServiceAccountBuilder(config *rest.Config, m lib.Manifest) Interface {
}
}

func (b *serviceAccountBuilder) WithMode(m Mode) Interface {
return b
}

func (b *serviceAccountBuilder) WithModifier(f MetaV1ObjectModifierFunc) Interface {
b.modifier = f
return b
Expand Down Expand Up @@ -50,6 +54,10 @@ func newConfigMapBuilder(config *rest.Config, m lib.Manifest) Interface {
}
}

func (b *configMapBuilder) WithMode(m Mode) Interface {
return b
}

func (b *configMapBuilder) WithModifier(f MetaV1ObjectModifierFunc) Interface {
b.modifier = f
return b
Expand Down Expand Up @@ -77,6 +85,10 @@ func newNamespaceBuilder(config *rest.Config, m lib.Manifest) Interface {
}
}

func (b *namespaceBuilder) WithMode(m Mode) Interface {
return b
}

func (b *namespaceBuilder) WithModifier(f MetaV1ObjectModifierFunc) Interface {
b.modifier = f
return b
Expand Down Expand Up @@ -104,6 +116,10 @@ func newServiceBuilder(config *rest.Config, m lib.Manifest) Interface {
}
}

func (b *serviceBuilder) WithMode(m Mode) Interface {
return b
}

func (b *serviceBuilder) WithModifier(f MetaV1ObjectModifierFunc) Interface {
b.modifier = f
return b
Expand Down
10 changes: 10 additions & 0 deletions lib/resourcebuilder/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,18 @@ type MetaV1ObjectModifierFunc func(metav1.Object)
// and the Manifest.
type NewInteraceFunc func(rest *rest.Config, m lib.Manifest) Interface

// Mode is how this builder is being used.
type Mode int

const (
UpdatingMode Mode = iota
ReconcilingMode
InitializingMode
)

type Interface interface {
WithModifier(MetaV1ObjectModifierFunc) Interface
WithMode(Mode) Interface
Do(context.Context) error
}

Expand Down
16 changes: 16 additions & 0 deletions lib/resourcebuilder/rbac.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ func newClusterRoleBuilder(config *rest.Config, m lib.Manifest) Interface {
}
}

func (b *clusterRoleBuilder) WithMode(m Mode) Interface {
return b
}

func (b *clusterRoleBuilder) WithModifier(f MetaV1ObjectModifierFunc) Interface {
b.modifier = f
return b
Expand Down Expand Up @@ -50,6 +54,10 @@ func newClusterRoleBindingBuilder(config *rest.Config, m lib.Manifest) Interface
}
}

func (b *clusterRoleBindingBuilder) WithMode(m Mode) Interface {
return b
}

func (b *clusterRoleBindingBuilder) WithModifier(f MetaV1ObjectModifierFunc) Interface {
b.modifier = f
return b
Expand Down Expand Up @@ -77,6 +85,10 @@ func newRoleBuilder(config *rest.Config, m lib.Manifest) Interface {
}
}

func (b *roleBuilder) WithMode(m Mode) Interface {
return b
}

func (b *roleBuilder) WithModifier(f MetaV1ObjectModifierFunc) Interface {
b.modifier = f
return b
Expand Down Expand Up @@ -104,6 +116,10 @@ func newRoleBindingBuilder(config *rest.Config, m lib.Manifest) Interface {
}
}

func (b *roleBindingBuilder) WithMode(m Mode) Interface {
return b
}

func (b *roleBindingBuilder) WithModifier(f MetaV1ObjectModifierFunc) Interface {
b.modifier = f
return b
Expand Down
4 changes: 4 additions & 0 deletions lib/resourcebuilder/security.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ func newSecurityBuilder(config *rest.Config, m lib.Manifest) Interface {
}
}

func (b *securityBuilder) WithMode(m Mode) Interface {
return b
}

func (b *securityBuilder) WithModifier(f MetaV1ObjectModifierFunc) Interface {
b.modifier = f
return b
Expand Down
55 changes: 48 additions & 7 deletions pkg/cvo/cvo.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ import (
"github.com/openshift/cluster-version-operator/lib"
"github.com/openshift/cluster-version-operator/lib/resourceapply"
"github.com/openshift/cluster-version-operator/lib/resourcebuilder"
"github.com/openshift/cluster-version-operator/lib/resourcemerge"
"github.com/openshift/cluster-version-operator/lib/validation"
"github.com/openshift/cluster-version-operator/pkg/cvo/internal"
"github.com/openshift/cluster-version-operator/pkg/cvo/internal/dynamicclient"
Expand Down Expand Up @@ -157,7 +156,7 @@ func New(
kubeClient: kubeClient,
eventRecorder: eventBroadcaster.NewRecorder(scheme.Scheme, corev1.EventSource{Component: namespace}),

queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "clusterversion"),
queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "clusterversion"),
availableUpdatesQueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "availableupdates"),
}

Expand Down Expand Up @@ -334,10 +333,19 @@ func (optr *Operator) sync(key string) error {
}, errs)
}

// identify an initial state to inform the sync loop of
var state payload.State
switch {
case hasNeverReachedLevel(config):
state = payload.InitializingPayload
case hasReachedLevel(config, desired):
state = payload.ReconcilingPayload
default:
state = payload.UpdatingPayload
}

// inform the config sync loop about our desired state
reconciling := resourcemerge.IsOperatorStatusConditionTrue(config.Status.Conditions, configv1.OperatorAvailable) &&
resourcemerge.IsOperatorStatusConditionFalse(config.Status.Conditions, configv1.OperatorProgressing)
status := optr.configSync.Update(config.Generation, desired, config.Spec.Overrides, reconciling)
status := optr.configSync.Update(config.Generation, desired, config.Spec.Overrides, state)

// write cluster version status
return optr.syncStatus(original, config, status, errs)
Expand Down Expand Up @@ -485,13 +493,46 @@ func (b *resourceBuilder) BuilderFor(m *lib.Manifest) (resourcebuilder.Interface
return internal.NewGenericBuilder(client, *m)
}

func (b *resourceBuilder) Apply(ctx context.Context, m *lib.Manifest) error {
func (b *resourceBuilder) Apply(ctx context.Context, m *lib.Manifest, state payload.State) error {
builder, err := b.BuilderFor(m)
if err != nil {
return err
}
if b.modifier != nil {
builder = builder.WithModifier(b.modifier)
}
return builder.Do(ctx)
return builder.WithMode(stateToMode(state)).Do(ctx)
}

func stateToMode(state payload.State) resourcebuilder.Mode {
switch state {
case payload.InitializingPayload:
return resourcebuilder.InitializingMode
case payload.UpdatingPayload:
return resourcebuilder.UpdatingMode
case payload.ReconcilingPayload:
return resourcebuilder.ReconcilingMode
default:
panic(fmt.Sprintf("unexpected payload state %d", int(state)))
}
}

func hasNeverReachedLevel(cv *configv1.ClusterVersion) bool {
Copy link
Contributor

Choose a reason for hiding this comment

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

This is a stretch :P (sorry my brain just went there)
but, what if somebody overrides the desired more than 10 times, so there will be all partial and we will truncate to all partial because

if len(config.Status.History) > 10 {
config.Status.History = config.Status.History[:10]
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hrm, we should leave the last completed. We should never prune to no completed. Good catch, will change

for _, version := range cv.Status.History {
if version.State == configv1.CompletedUpdate {
return false
}
}
// TODO: check the payload, just in case
return true
}

func hasReachedLevel(cv *configv1.ClusterVersion, desired configv1.Update) bool {
if len(cv.Status.History) == 0 {
return false
}
if cv.Status.History[0].State != configv1.CompletedUpdate {
return false
}
return desired.Image == cv.Status.History[0].Image
}
Loading