Skip to content

Commit b22e79c

Browse files
New patch (#80)
* some initial design Signed-off-by: raffaelespazzoli <[email protected]> * new patch Signed-off-by: raffaelespazzoli <[email protected]> * fixed manifest generation Signed-off-by: raffaelespazzoli <[email protected]> * Update README.md Co-authored-by: Andrew Block <[email protected]> * Update README.md Co-authored-by: Andrew Block <[email protected]> * Update README.md Co-authored-by: Andrew Block <[email protected]> * Update README.md Co-authored-by: Andrew Block <[email protected]> * fixes from andy's comments Signed-off-by: raffaelespazzoli <[email protected]> Co-authored-by: Andrew Block <[email protected]>
1 parent db103cf commit b22e79c

36 files changed

+2094
-2031
lines changed

README.md

Lines changed: 62 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,23 @@ This library layers on top of the Operator SDK and with the objective of helping
1313

1414
This library covers three main areas:
1515

16-
1. [Idempotent methods](#Idempotent-Methods-to-Manipulate-Resources) to manipulate resources and arrays of resources
17-
2. [Basic operator lifecycle](#Basic-Operator-Lifecycle-Management) needs (validation, initialization, status and error management, finalization)
18-
3. [Enforcing resources operator support](#Enforcing-Resource-Operator-Support). For those operators which calculate a set of resources that need to exist and then enforce them, generalized support for the enforcing phase is provided.
16+
1. [Utility Methods](#Utility-Methods) Utility methods that are callable by any operator.
17+
2. [Idempotent methods](#Idempotent-Methods-to-Manipulate-Resources) to manipulate resources and arrays of resources
18+
3. [Basic operator lifecycle](#Basic-Operator-Lifecycle-Management) needs (validation, initialization, status and error management, finalization)
19+
4. [Enforcing resources operator support](#Enforcing-Resource-Operator-Support). For those operators which calculate a set of resources that need to exist and then enforce them, generalized support for the enforcing phase is provided.
20+
21+
## Utility Methods
22+
23+
Prior to version v2.x the general philosophy of this library was that new operator would inherit from `ReconcilerBase` and in doing so they would have access to a bunch of utility methods.
24+
With release v2.0.0 a new approach is available. Utility methods are callable by any operator having to inherit. This makes it easier to use this library and does not conflict with autogenerate code from `kube-builder` and `operator-sdk`.
25+
Most of the Utility methods receive a context.Context parameter. Normally this context must be initialized with a `logr.Logger` and a `rest.Config`. Some utility methods may require more, see each individual documentation.
26+
27+
Utility methods are currently organized in the following folders:
28+
29+
1. crud: idempotent create/update/delete functions.
30+
2. discoveryclient: methods related to the discovery client, typically used to load `apiResource` objects.
31+
3. dynamicclient: methods related to building client based on object whose type is not known at compile time.
32+
4. templates: utility methods for dealing with templates whose output is an object or a list of objects.
1933

2034
## Idempotent Methods to Manipulate Resources
2135

@@ -29,6 +43,15 @@ Also there are utility methods to manage finalizers, test ownership and process
2943

3044
## Basic Operator Lifecycle Management
3145

46+
---
47+
48+
Note
49+
50+
This part of the library is largely deprecated. For initialization and defaulting a MutatingWebHook should be used. For validation a Validating WebHook should be used.
51+
The part regarding the finalization is still relevant.
52+
53+
---
54+
3255
To get started with this library do the following:
3356

3457
Change your reconciler initialization as exemplified below to add a set of utility methods to it
@@ -172,9 +195,11 @@ return r.ManageSuccessWithRequeue(ctx, instance, 3*time.Second)
172195
```
173196

174197
or simply using the convenience function:
198+
175199
```go
176200
return r.ManageOutcomeWithRequeue(ctx, instance, err, 3*time.Second)
177201
```
202+
178203
which will delegate to the error or success variant depending on `err` being `nil` or not.
179204

180205
### Managing CR Finalization
@@ -287,17 +312,33 @@ In some situations, a patch must be parametric on some state of the cluster. For
287312
A patch is defined as follows:
288313

289314
```golang
290-
type LockedPatch struct {
291-
ID string `json:"id,omitempty"`
292-
SourceObjectRefs []corev1.ObjectReference `json:"sourceObjectRefs,omitempty"`
293-
TargetObjectRef corev1.ObjectReference `json:"targetObjectRef,omitempty"`
294-
PatchType types.PatchType `json:"patchType,omitempty"`
295-
PatchTemplate string `json:"patchTemplate,omitempty"`
296-
Template template.Template `json:"-"`
315+
type LockedPatch struct {
316+
Name string `json:"name,omitempty"`
317+
SourceObjectRefs []utilsapi.SourceObjectReference `json:"sourceObjectRefs,omitempty"`
318+
TargetObjectRef utilsapi.TargetObjectReference `json:"targetObjectRef,omitempty"`
319+
PatchType types.PatchType `json:"patchType,omitempty"`
320+
PatchTemplate string `json:"patchTemplate,omitempty"`
321+
Template template.Template `json:"-"`
297322
}
298323
```
299324

300325
the targetObjectRef and sourceObjectRefs are watched for changes by the reconciler.
326+
327+
targetObjectRef can select multiple objects, this is the logic
328+
329+
| Namespaced Type | Namespace | Name | Selection type |
330+
| --- | --- | --- | --- |
331+
| yes | null | null | multiple selection across namespaces |
332+
| yes | null | not null | multiple selection across namespaces where the name corresponds to the passed name |
333+
| yes | not null | null | multiple selection within a namespace |
334+
| yes | not null | not nul | single selection |
335+
| no | N/A | null | multiple selection |
336+
| no | N/A | not null | single selection |
337+
338+
Selection can be further narrowed down by filtering by labels and/or annotations. The patch will be applied to all of the selected instances.
339+
340+
Name and Namespace of sourceRefObjects are interpreted as golang templates with the current target instance and the only parameter. This allows to select different source object for each target object.
341+
301342
The relevant part of the operator code would look like this:
302343

303344
```golang
@@ -411,6 +452,17 @@ oc login --token ${token}
411452
make run ENABLE_WEBHOOKS=false
412453
```
413454

455+
### testing
456+
457+
Patches
458+
459+
```shell
460+
oc new-project patch-test
461+
oc create sa test -n patch-test
462+
oc adm policy add-cluster-role-to-user cluster-reader -z default -n patch-test
463+
oc apply -f ./test/enforcing-patch.yaml -n patch-test
464+
```
465+
414466
## Building/Pushing the operator image
415467

416468
```shell

api/v1alpha1/enforcingcrd_types.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ limitations under the License.
1717
package v1alpha1
1818

1919
import (
20-
"github.com/redhat-cop/operator-utils/pkg/util/apis"
2120
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2221
)
2322

@@ -32,7 +31,7 @@ type EnforcingCRDSpec struct {
3231
// Resources is a list of resource manifests that should be locked into the specified configuration
3332
// +kubebuilder:validation:Optional
3433
// +listType=atomic
35-
Resources []apis.LockedResource `json:"resources,omitempty"`
34+
Resources []LockedResource `json:"resources,omitempty"`
3635
}
3736

3837
// EnforcingCRDStatus defines the observed state of EnforcingCRD
@@ -41,14 +40,14 @@ type EnforcingCRDStatus struct {
4140
// Important: Run "operator-sdk generate k8s" to regenerate code after modifying this file
4241
// Add custom validation using kubebuilder tags: https://book-v1.book.kubebuilder.io/beyond_basics/generating_crd.html
4342
// +kubebuilder:validation:Optional
44-
apis.EnforcingReconcileStatus `json:",inline,omitempty"`
43+
EnforcingReconcileStatus `json:",inline,omitempty"`
4544
}
4645

47-
func (m *EnforcingCRD) GetEnforcingReconcileStatus() apis.EnforcingReconcileStatus {
46+
func (m *EnforcingCRD) GetEnforcingReconcileStatus() EnforcingReconcileStatus {
4847
return m.Status.EnforcingReconcileStatus
4948
}
5049

51-
func (m *EnforcingCRD) SetEnforcingReconcileStatus(reconcileStatus apis.EnforcingReconcileStatus) {
50+
func (m *EnforcingCRD) SetEnforcingReconcileStatus(reconcileStatus EnforcingReconcileStatus) {
5251
m.Status.EnforcingReconcileStatus = reconcileStatus
5352
}
5453

api/v1alpha1/enforcingpatch_types.go

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ limitations under the License.
1717
package v1alpha1
1818

1919
import (
20-
"github.com/redhat-cop/operator-utils/pkg/util/apis"
2120
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2221
)
2322

@@ -32,23 +31,22 @@ type EnforcingPatchSpec struct {
3231

3332
// Patches is a list of pacthes that should be encforced at runtime.
3433
// +kubebuilder:validation:Optional
35-
// +listType=atomic
36-
Patches []apis.Patch `json:"patches,omitempty"`
34+
Patches map[string]Patch `json:"patches,omitempty"`
3735
}
3836

3937
// EnforcingPatchStatus defines the observed state of EnforcingPatch
4038
type EnforcingPatchStatus struct {
4139
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
4240
// Important: Run "operator-sdk generate k8s" to regenerate code after modifying this file
4341
// Add custom validation using kubebuilder tags: https://book-v1.book.kubebuilder.io/beyond_basics/generating_crd.html
44-
apis.EnforcingReconcileStatus `json:",inline,omitempty"`
42+
EnforcingReconcileStatus `json:",inline,omitempty"`
4543
}
4644

47-
func (m *EnforcingPatch) GetEnforcingReconcileStatus() apis.EnforcingReconcileStatus {
45+
func (m *EnforcingPatch) GetEnforcingReconcileStatus() EnforcingReconcileStatus {
4846
return m.Status.EnforcingReconcileStatus
4947
}
5048

51-
func (m *EnforcingPatch) SetEnforcingReconcileStatus(reconcileStatus apis.EnforcingReconcileStatus) {
49+
func (m *EnforcingPatch) SetEnforcingReconcileStatus(reconcileStatus EnforcingReconcileStatus) {
5250
m.Status.EnforcingReconcileStatus = reconcileStatus
5351
}
5452

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package v1alpha1
2+
3+
import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
4+
5+
// +patchMergeKey=type
6+
// +patchStrategy=merge
7+
// +listType=map
8+
// +listMapKey=type
9+
type Conditions []metav1.Condition
10+
11+
// +mapType=granular
12+
type ConditionMap map[string]Conditions
13+
14+
// EnforcingReconcileStatus represents the status of the last reconcile cycle. It's used to communicate success or failure and the error message
15+
type EnforcingReconcileStatus struct {
16+
17+
// ReconcileStatus this is the general status of the main reconciler
18+
// +kubebuilder:validation:Optional
19+
// +patchMergeKey=type
20+
// +patchStrategy=merge
21+
// +listType=map
22+
// +listMapKey=type
23+
Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
24+
25+
//LockedResourceStatuses contains the reconcile status for each of the managed resources
26+
// +kubebuilder:validation:Optional
27+
LockedResourceStatuses map[string]Conditions `json:"lockedResourceStatuses,omitempty"`
28+
29+
//LockedResourceStatuses contains the reconcile status for each of the managed resources
30+
// +kubebuilder:validation:Optional
31+
LockedPatchStatuses map[string]ConditionMap `json:"lockedPatchStatuses,omitempty"`
32+
}
33+
34+
// EnforcingReconcileStatusAware is an interfce that must be implemented by a CRD type that has been enabled with ReconcileStatus, it can then benefit of a series of utility methods.
35+
// +kubebuilder:object:generate:=false
36+
type EnforcingReconcileStatusAware interface {
37+
GetEnforcingReconcileStatus() EnforcingReconcileStatus
38+
SetEnforcingReconcileStatus(enforcingReconcileStatus EnforcingReconcileStatus)
39+
}

0 commit comments

Comments
 (0)