Skip to content

Commit 2402ef3

Browse files
Merge pull request #1794 from deads2k/apply-02-more-loops
API-1835: Apply 02 more loops
2 parents 3c41fd1 + a86ed62 commit 2402ef3

File tree

47 files changed

+425
-159
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+425
-159
lines changed

pkg/controller/factory/interfaces.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,7 @@ type SyncFunc func(ctx context.Context, controllerContext SyncContext) error
5050
func ControllerFieldManager(controllerName, usageName string) string {
5151
return fmt.Sprintf("%s-%s", controllerName, usageName)
5252
}
53+
54+
func ControllerInstanceName(instanceName, controllerName string) string {
55+
return fmt.Sprintf("%s-%s", instanceName, controllerName)
56+
}

pkg/operator/README.md

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,43 @@
44

55
Creates and maintains an `apiservices.apiregistration.k8s.io`.
66

7-
### ResourceSyncController
7+
### AuditPolicy
8+
**Location** [apiserver/controller/audit](https://github.com/openshift/library-go/tree/master/pkg/operator/apiserver/controller/audit)
9+
10+
Reads the `apiserver.config.openshift.io#.spec.audit` and creates a ConfigMap with the desired audit configuration.
11+
12+
### ConfigObserver
13+
**Location** [configobserver](https://github.com/openshift/library-go/tree/master/pkg/operator/configobserver)
14+
15+
Runs a series of configured observers to produce a RawExtension to set at `.spec.observedConfiguration`.
16+
This allows independently watching many different inputs to produce a single configuration with a `.metadata.generation`.
17+
Every field in the RawExtension must be set by a single observer.
18+
A single observer may set many fields.
19+
20+
### LatencyProfile
21+
**Location** [latencyprofile](https://github.com/openshift/library-go/tree/master/pkg/operator/latencyprofile)
22+
23+
Reads the `node.config.openshift.io` resource to determine a latency profile for deciding about node lifecycle
24+
controller and related timing.
25+
This controller appears to be trying to indicate whether a level has been reached, but to be honest I cannot
26+
figure out how it's actually driving the change, which probably means that there is a configobserver somewhere.
27+
28+
### ResourceSync
829
**Location** [resourcesynccontroller](https://github.com/openshift/library-go/tree/master/pkg/operator/resourcesynccontroller)
930

1031
Copies a ConfigMap or Secret from one location to another.
1132
Can copy partial ConfigMaps or Secrets.
1233

13-
### StaticResourceController
34+
### StaleConditions
35+
**Location** [staleconditions](https://github.com/openshift/library-go/tree/master/pkg/operator/staleconditions)
36+
37+
Takes a list of conditions and their corresponding fieldManagers so that the condition can be removed on the
38+
`<foo>.operator.openshift.io` resource.
39+
This is useful when old control loops are no longer needed.
40+
If you forget to do this and just delete the control loop, then on upgrade there is a "stuck" condition that
41+
cannot be cleared and can impact the summary of status on `clusteroperator.config.openshift.io`.
42+
43+
### StaticResources
1444
**Location** [staticresourcecontroller](https://github.com/openshift/library-go/tree/master/pkg/operator/staticresourcecontroller)
1545

1646
Creates, maintains, and deletes resources that need little to no customization.

pkg/operator/apiserver/controller/apiservice/apiservice_controller.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ type GetAPIServicesToMangeFunc func() (enabled []*apiregistrationv1.APIService,
3434
type apiServicesPreconditionFuncType func([]*apiregistrationv1.APIService) (bool, error)
3535

3636
type APIServiceController struct {
37-
name string
37+
controllerInstanceName string
3838
getAPIServicesToManageFn GetAPIServicesToMangeFunc
3939
// preconditionsForEnabledAPIServices must return true before the apiservices will be created
4040
preconditionsForEnabledAPIServices apiServicesPreconditionFuncType
@@ -46,7 +46,7 @@ type APIServiceController struct {
4646
}
4747

4848
func NewAPIServiceController(
49-
name, targetNamespace string,
49+
instanceName, targetNamespace string,
5050
getAPIServicesToManageFunc GetAPIServicesToMangeFunc,
5151
operatorClient v1helpers.OperatorClient,
5252
apiregistrationInformers apiregistrationinformers.SharedInformerFactory,
@@ -57,7 +57,7 @@ func NewAPIServiceController(
5757
informers ...factory.Informer,
5858
) factory.Controller {
5959
c := &APIServiceController{
60-
name: "APIServiceController_" + name,
60+
controllerInstanceName: factory.ControllerInstanceName(instanceName, "APIService"),
6161
preconditionsForEnabledAPIServices: preconditionsForEnabledAPIServices(
6262
kubeInformersForNamespaces.InformersFor(targetNamespace).Core().V1().Endpoints().Lister(),
6363
kubeInformersForNamespaces.InformersFor(metav1.NamespaceSystem).Core().V1().ConfigMaps().Lister(),
@@ -77,7 +77,7 @@ func NewAPIServiceController(
7777
kubeInformersForNamespaces.InformersFor(metav1.NamespaceSystem).Core().V1().ConfigMaps().Informer(),
7878
apiregistrationInformers.Apiregistration().V1().APIServices().Informer(),
7979
)...,
80-
).ToController(c.name, eventRecorder.WithComponentSuffix("apiservice-"+name+"-controller"))
80+
).ToController(c.controllerInstanceName, eventRecorder.WithComponentSuffix("apiservice-"+instanceName+"-controller"))
8181
}
8282

8383
func (c *APIServiceController) updateOperatorStatus(
@@ -121,7 +121,7 @@ func (c *APIServiceController) updateOperatorStatus(
121121
defer func() {
122122
status := applyoperatorv1.OperatorStatus().
123123
WithConditions(conditionAPIServicesDegraded, conditionAPIServicesAvailable)
124-
updateError := c.operatorClient.ApplyOperatorStatus(ctx, factory.ControllerFieldManager(c.name, "updateOperatorStatus"), status)
124+
updateError := c.operatorClient.ApplyOperatorStatus(ctx, c.controllerInstanceName, status)
125125
if updateError != nil {
126126
// overrides error returned through 'return <ERROR>' statement
127127
err = updateError

pkg/operator/apiserver/controller/auditpolicy/auditpolicy_controller.go

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import (
44
"context"
55
"time"
66

7+
applyoperatorv1 "github.com/openshift/client-go/operator/applyconfigurations/operator/v1"
8+
79
configv1 "github.com/openshift/api/config/v1"
810
operatorsv1 "github.com/openshift/api/operator/v1"
911
operatorv1 "github.com/openshift/api/operator/v1"
@@ -23,6 +25,7 @@ import (
2325
)
2426

2527
type auditPolicyController struct {
28+
controllerInstanceName string
2629
apiserverConfigLister configv1listers.APIServerLister
2730
kubeClient kubernetes.Interface
2831
operatorClient v1helpers.OperatorClient
@@ -32,6 +35,7 @@ type auditPolicyController struct {
3235
// NewAuditPolicyController create a controller that watches the config.openshift.io/v1 APIServer object
3336
// and reconciles a ConfigMap in the target namespace with the audit.k8s.io/v1 policy.yaml file.
3437
func NewAuditPolicyController(
38+
name string,
3539
targetNamespace string,
3640
targetConfigMapName string,
3741
apiserverConfigLister configv1listers.APIServerLister,
@@ -42,18 +46,22 @@ func NewAuditPolicyController(
4246
eventRecorder events.Recorder,
4347
) factory.Controller {
4448
c := &auditPolicyController{
45-
operatorClient: operatorClient,
46-
apiserverConfigLister: apiserverConfigLister,
47-
kubeClient: kubeClient,
48-
targetNamespace: targetNamespace,
49-
targetConfigMapName: targetConfigMapName,
49+
controllerInstanceName: factory.ControllerInstanceName(name, "AuditPolicy"),
50+
operatorClient: operatorClient,
51+
apiserverConfigLister: apiserverConfigLister,
52+
kubeClient: kubeClient,
53+
targetNamespace: targetNamespace,
54+
targetConfigMapName: targetConfigMapName,
5055
}
5156

5257
return factory.New().WithSync(c.sync).ResyncEvery(10*time.Second).WithInformers(
5358
configInformers.Config().V1().APIServers().Informer(),
5459
kubeInformersForTargetNamesace.Core().V1().ConfigMaps().Informer(),
5560
operatorClient.Informer(),
56-
).ToController("auditPolicyController", eventRecorder.WithComponentSuffix("audit-policy-controller"))
61+
).ToController(
62+
"auditPolicyController", // don't change what is passed here unless you also remove the old FooDegraded condition
63+
eventRecorder.WithComponentSuffix("audit-policy-controller"),
64+
)
5765
}
5866

5967
func (c *auditPolicyController) sync(ctx context.Context, syncCtx factory.SyncContext) error {
@@ -81,19 +89,19 @@ func (c *auditPolicyController) sync(ctx context.Context, syncCtx factory.SyncCo
8189
err = c.syncAuditPolicy(ctx, config.Spec.Audit, syncCtx.Recorder())
8290

8391
// update failing condition
84-
cond := operatorv1.OperatorCondition{
85-
Type: "AuditPolicyDegraded",
86-
Status: operatorv1.ConditionFalse,
87-
}
92+
condition := applyoperatorv1.OperatorCondition().
93+
WithType("AuditPolicyDegraded").
94+
WithStatus(operatorv1.ConditionFalse)
8895
if err != nil {
89-
cond.Status = operatorv1.ConditionTrue
90-
cond.Reason = "Error"
91-
cond.Message = err.Error()
96+
condition = condition.
97+
WithStatus(operatorv1.ConditionTrue).
98+
WithReason("Error").
99+
WithMessage(err.Error())
92100
}
93-
if _, _, updateError := v1helpers.UpdateStatus(ctx, c.operatorClient, v1helpers.UpdateConditionFn(cond)); updateError != nil {
94-
if err == nil {
95-
return updateError
96-
}
101+
status := applyoperatorv1.OperatorStatus().WithConditions(condition)
102+
updateError := c.operatorClient.ApplyOperatorStatus(ctx, c.controllerInstanceName, status)
103+
if updateError != nil {
104+
return updateError
97105
}
98106

99107
return err

pkg/operator/apiserver/controller/nsfinalizer/finalizer_controller.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,10 @@ func NewFinalizerController(
5353
return factory.New().ResyncEvery(time.Minute).WithSync(c.sync).WithInformers(
5454
kubeInformersForTargetNamespace.Core().V1().Pods().Informer(),
5555
kubeInformersForTargetNamespace.Apps().V1().DaemonSets().Informer(),
56-
).ToController(fullname, eventRecorder.WithComponentSuffix("finalizer-controller"))
56+
).ToController(
57+
fullname, // don't change what is passed here unless you also remove the old FooDegraded condition
58+
eventRecorder.WithComponentSuffix("finalizer-controller"),
59+
)
5760
}
5861

5962
func (c finalizerController) sync(ctx context.Context, syncCtx factory.SyncContext) error {

pkg/operator/apiserver/controller/workload/workload.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,10 @@ func NewController(name, operatorNamespace, targetNamespace, targetOperandVersio
110110

111111
return c.WithSync(controllerRef.sync).
112112
WithInformers(informers...).
113-
ToController(fmt.Sprintf("%sWorkloadController", name), eventRecorder)
113+
ToController(
114+
fmt.Sprintf("%sWorkloadController", name), // don't change what is passed here unless you also remove the old FooDegraded condition
115+
eventRecorder,
116+
)
114117
}
115118

116119
func (c *Controller) sync(ctx context.Context, controllerContext factory.SyncContext) error {

pkg/operator/apiserver/controllerset/apiservercontrollerset.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ func (cw *controllerWrapper) prepare() (controller, error) {
7171

7272
// APIServerControllerSet is a set of controllers that maintain a deployment of an API server and the namespace it's running in
7373
type APIServerControllerSet struct {
74+
name string
7475
operatorClient v1helpers.OperatorClient
7576
eventRecorder events.Recorder
7677

@@ -88,10 +89,12 @@ type APIServerControllerSet struct {
8889
}
8990

9091
func NewAPIServerControllerSet(
92+
name string,
9193
operatorClient v1helpers.OperatorClient,
9294
eventRecorder events.Recorder,
9395
) *APIServerControllerSet {
9496
apiServerControllerSet := &APIServerControllerSet{
97+
name: name,
9598
operatorClient: operatorClient,
9699
eventRecorder: eventRecorder,
97100
}
@@ -405,6 +408,7 @@ func (cs *APIServerControllerSet) WithAuditPolicyController(
405408
kubeClient kubernetes.Interface,
406409
) *APIServerControllerSet {
407410
cs.auditPolicyController.controller = auditpolicy.NewAuditPolicyController(
411+
cs.name,
408412
targetNamespace,
409413
targetConfigMapName,
410414
apiserverConfigLister,

pkg/operator/certrotation/client_cert_rotation_controller.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,10 @@ func NewCertRotationController(
9898
WithPostStartHooks(
9999
c.targetCertRecheckerPostRunHook,
100100
).
101-
ToController("CertRotationController", recorder.WithComponentSuffix("cert-rotation-controller").WithComponentSuffix(name))
101+
ToController(
102+
"CertRotationController", // don't change what is passed here unless you also remove the old FooDegraded condition
103+
recorder.WithComponentSuffix("cert-rotation-controller").WithComponentSuffix(name),
104+
)
102105
}
103106

104107
func (c CertRotationController) Sync(ctx context.Context, syncCtx factory.SyncContext) error {

pkg/operator/configobserver/config_observer_controller.go

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import (
99
"strings"
1010
"time"
1111

12+
applyoperatorv1 "github.com/openshift/client-go/operator/applyconfigurations/operator/v1"
13+
1214
"github.com/imdario/mergo"
1315
"k8s.io/klog/v2"
1416

@@ -44,6 +46,8 @@ type Listers interface {
4446
type ObserveConfigFunc func(listers Listers, recorder events.Recorder, existingConfig map[string]interface{}) (observedConfig map[string]interface{}, errs []error)
4547

4648
type ConfigObserver struct {
49+
controllerInstanceName string
50+
4751
// observers are called in an undefined order and their results are merged to
4852
// determine the observed configuration.
4953
observers []ObserveConfigFunc
@@ -58,13 +62,15 @@ type ConfigObserver struct {
5862
}
5963

6064
func NewConfigObserver(
65+
name string,
6166
operatorClient v1helpers.OperatorClient,
6267
eventRecorder events.Recorder,
6368
listers Listers,
6469
informers []factory.Informer,
6570
observers ...ObserveConfigFunc,
6671
) factory.Controller {
6772
return NewNestedConfigObserver(
73+
name,
6874
operatorClient,
6975
eventRecorder,
7076
listers,
@@ -95,6 +101,7 @@ func NewConfigObserver(
95101
// oauthAPIController := NewNestedConfigObserver(..., []string{"oauthAPIServer"}
96102
// oauthServerController := NewNestedConfigObserver(..., []string{"oauthServer"}
97103
func NewNestedConfigObserver(
104+
name string,
98105
operatorClient v1helpers.OperatorClient,
99106
eventRecorder events.Recorder,
100107
listers Listers,
@@ -104,14 +111,22 @@ func NewNestedConfigObserver(
104111
observers ...ObserveConfigFunc,
105112
) factory.Controller {
106113
c := &ConfigObserver{
107-
operatorClient: operatorClient,
108-
observers: observers,
109-
listers: listers,
110-
nestedConfigPath: nestedConfigPath,
111-
degradedConditionType: degradedConditionPrefix + condition.ConfigObservationDegradedConditionType,
114+
controllerInstanceName: factory.ControllerInstanceName(name, "ConfigObserver"),
115+
operatorClient: operatorClient,
116+
observers: observers,
117+
listers: listers,
118+
nestedConfigPath: nestedConfigPath,
119+
degradedConditionType: degradedConditionPrefix + condition.ConfigObservationDegradedConditionType,
112120
}
113121

114-
return factory.New().ResyncEvery(time.Minute).WithSync(c.sync).WithInformers(append(informers, listersToInformer(listers)...)...).ToController("ConfigObserver", eventRecorder.WithComponentSuffix("config-observer"))
122+
return factory.New().
123+
ResyncEvery(time.Minute).
124+
WithSync(c.sync).
125+
WithInformers(append(informers, listersToInformer(listers)...)...).
126+
ToController(
127+
"ConfigObserver", // don't change what is passed here unless you also remove the old FooDegraded condition
128+
eventRecorder.WithComponentSuffix("config-observer"),
129+
)
115130
}
116131

117132
// sync reacts to a change in prereqs by finding information that is required to match another value in the cluster. This
@@ -165,16 +180,18 @@ func (c ConfigObserver) sync(ctx context.Context, syncCtx factory.SyncContext) e
165180
configError := v1helpers.NewMultiLineAggregate(errs)
166181

167182
// update failing condition
168-
cond := operatorv1.OperatorCondition{
169-
Type: c.degradedConditionType,
170-
Status: operatorv1.ConditionFalse,
171-
}
183+
condition := applyoperatorv1.OperatorCondition().
184+
WithType(c.degradedConditionType).
185+
WithStatus(operatorv1.ConditionFalse)
172186
if configError != nil {
173-
cond.Status = operatorv1.ConditionTrue
174-
cond.Reason = "Error"
175-
cond.Message = configError.Error()
187+
condition = condition.
188+
WithStatus(operatorv1.ConditionTrue).
189+
WithReason("Error").
190+
WithMessage(configError.Error())
176191
}
177-
if _, _, updateError := v1helpers.UpdateStatus(ctx, c.operatorClient, v1helpers.UpdateConditionFn(cond)); updateError != nil {
192+
status := applyoperatorv1.OperatorStatus().WithConditions(condition)
193+
updateError := c.operatorClient.ApplyOperatorStatus(ctx, c.controllerInstanceName, status)
194+
if updateError != nil {
178195
return updateError
179196
}
180197

pkg/operator/configobserver/config_observer_controller_test.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package configobserver
33
import (
44
"context"
55
"fmt"
6+
"k8s.io/apimachinery/pkg/util/json"
67
"reflect"
78
"strings"
89
"testing"
@@ -70,6 +71,16 @@ func (c *fakeOperatorClient) ApplyOperatorSpec(ctx context.Context, fieldManager
7071
}
7172

7273
func (c *fakeOperatorClient) ApplyOperatorStatus(ctx context.Context, fieldManager string, applyConfiguration *applyoperatorv1.OperatorStatusApplyConfiguration) (err error) {
74+
applyJSON, err := json.Marshal(applyConfiguration)
75+
if err != nil {
76+
return fmt.Errorf("marshal failure: %w", err)
77+
}
78+
status := &operatorv1.OperatorStatus{}
79+
if err := json.Unmarshal(applyJSON, status); err != nil {
80+
return fmt.Errorf("unmarshal failure: %w", err)
81+
}
82+
c.status = status
83+
7384
return nil
7485
}
7586

0 commit comments

Comments
 (0)