Skip to content

Commit 9e17933

Browse files
committed
Base preflight check function
1 parent 1b07d87 commit 9e17933

File tree

4 files changed

+49
-48
lines changed

4 files changed

+49
-48
lines changed

pkg/patterns/addon/pkg/status/basic.go

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,15 @@ func NewBasic(client client.Client) declarative.Status {
3232

3333
// NewBasicVersionCheck provides an implementation of declarative.Status that
3434
// performs version checks for the version of the operator that the manifest requires.
35-
func NewBasicVersionChecks(client client.Client, version string) declarative.Status {
35+
func NewBasicVersionChecks(client client.Client, version string) (declarative.Status, error) {
36+
v, err := NewVersionCheck(client, version)
37+
if err != nil {
38+
return nil, err
39+
}
40+
3641
return &declarative.StatusBuilder{
37-
ReconciledImpl: NewAggregator(client),
38-
VersionCheckImpl: NewVersionCheck(client, version),
42+
ReconciledImpl: NewAggregator(client),
43+
VersionCheckImpl: v,
3944
// no preflight checks
40-
}
45+
}, nil
4146
}

pkg/patterns/addon/pkg/status/version.go

Lines changed: 21 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,26 +3,29 @@ package status
33
import (
44
"context"
55
"fmt"
6+
67
"github.com/blang/semver"
78
"sigs.k8s.io/controller-runtime/pkg/client"
89
"sigs.k8s.io/controller-runtime/pkg/log"
910
addonsv1alpha1 "sigs.k8s.io/kubebuilder-declarative-pattern/pkg/patterns/addon/pkg/apis/v1alpha1"
1011

11-
//"sigs.k8s.io/controller-runtime/pkg/log"
12-
1312
"sigs.k8s.io/kubebuilder-declarative-pattern/pkg/patterns/declarative"
1413
"sigs.k8s.io/kubebuilder-declarative-pattern/pkg/patterns/declarative/pkg/manifest"
1514
)
1615

1716
// NewVersionCheck provides an implementation of declarative.Reconciled that
1817
// checks the version of the operator if it is up to the version required by the manifest
19-
func NewVersionCheck(client client.Client, version string) *versionCheck {
20-
return &versionCheck{client, version}
18+
func NewVersionCheck(client client.Client, operatorVersionString string) (*versionCheck, error) {
19+
operatorVersion, err := semver.Parse(operatorVersionString)
20+
if err != nil {
21+
return nil, fmt.Errorf("unable to parse operator version %q: %v", operatorVersionString, err)
22+
}
23+
return &versionCheck{client: client, operatorVersion: operatorVersion}, nil
2124
}
2225

2326
type versionCheck struct {
24-
client client.Client
25-
version string
27+
client client.Client
28+
operatorVersion semver.Version
2629
}
2730

2831
func (p *versionCheck) VersionCheck(
@@ -31,39 +34,27 @@ func (p *versionCheck) VersionCheck(
3134
objs *manifest.Objects,
3235
) (bool, error) {
3336
log := log.Log
34-
zeroVersion := semver.Version{}
35-
var versionNeededStr string
36-
maxVersion := zeroVersion
37+
var minOperatorVersion semver.Version
3738

3839
// Look for annotation from any resource with the max version
3940
for _, obj := range objs.Items {
40-
unstruct := obj.UnstructuredObject().Object
41-
metadata := unstruct["metadata"].(map[string]interface{})
42-
annotations, ok := metadata["annotations"].(map[string]interface{})
43-
if ok {
44-
versionNeededStr, _ = annotations["addons.k8s.io/operator-version"].(string)
45-
log.WithValues("version", versionNeededStr).Info("Got version, %v")
41+
annotations := obj.UnstructuredObject().GetAnnotations()
42+
if versionNeededStr, ok := annotations["addons.k8s.io/min-operator-version"]; ok {
43+
log.WithValues("min-operator-version", versionNeededStr).Info("Got version requirement addons.k8s.io/operator-version")
4644

47-
versionActual, err := semver.Make(versionNeededStr)
45+
versionNeeded, err := semver.Parse(versionNeededStr)
4846
if err != nil {
49-
log.WithValues("version", versionNeededStr).Info("Unable to convert string to version, skipping this object")
50-
continue
47+
log.WithValues("version", versionNeededStr).Error(err, "Unable to parse version restriction")
48+
return false, err
5149
}
5250

53-
if versionActual.GT(maxVersion) {
54-
maxVersion = versionActual
51+
if versionNeeded.GT(minOperatorVersion) {
52+
minOperatorVersion = versionNeeded
5553
}
5654
}
5755
}
5856

59-
// TODO(somtochi): Do we want to return an error when the version is invalid or just skip and use the operator?
60-
operatorVersion, err := semver.Make(p.version)
61-
if err != nil {
62-
log.WithValues("version", p.version).Info("Unable to convert string to version, skipping check")
63-
return true, nil
64-
}
65-
66-
if maxVersion.Equals(zeroVersion) || !maxVersion.GT(operatorVersion) {
57+
if p.operatorVersion.GTE(minOperatorVersion) {
6758
return true, nil
6859
}
6960

@@ -75,11 +66,11 @@ func (p *versionCheck) VersionCheck(
7566
status := addonsv1alpha1.CommonStatus{
7667
Healthy: false,
7768
Errors: []string{
78-
fmt.Sprintf("Addons needs version %v, this operator is version %v", maxVersion.String(), operatorVersion.String()),
69+
fmt.Sprintf("manifest needs operator version >= %v, this operator is version %v", minOperatorVersion.String(), p.operatorVersion.String()),
7970
},
8071
}
8172
log.WithValues("name", addonObject.GetName()).WithValues("status", status).Info("updating status")
8273
addonObject.SetCommonStatus(status)
8374

84-
return false, fmt.Errorf("operator not qualified, manifest needs operator >= %v", maxVersion.String())
75+
return false, fmt.Errorf("operator not qualified, manifest needs operator version >= %v", minOperatorVersion.String())
8576
}

pkg/patterns/declarative/reconciler.go

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import (
2929
"k8s.io/apimachinery/pkg/runtime"
3030
"k8s.io/apimachinery/pkg/types"
3131
"k8s.io/client-go/rest"
32+
"k8s.io/client-go/tools/record"
3233
"sigs.k8s.io/controller-runtime/pkg/client"
3334
"sigs.k8s.io/controller-runtime/pkg/client/apiutil"
3435
"sigs.k8s.io/controller-runtime/pkg/log"
@@ -52,6 +53,9 @@ type Reconciler struct {
5253

5354
mgr manager.Manager
5455

56+
// recorder is the EventRecorder for creating k8s events
57+
recorder record.EventRecorder
58+
5559
options reconcilerParams
5660
}
5761

@@ -71,6 +75,10 @@ func (r *Reconciler) Init(mgr manager.Manager, prototype DeclarativeObject, opts
7175
r.prototype = prototype
7276
r.kubectl = kubectl
7377

78+
// TODO: Can we derive the name from prototype?
79+
controllerName := "addon-controller"
80+
r.recorder = mgr.GetEventRecorderFor(controllerName)
81+
7482
r.client = mgr.GetClient()
7583
r.config = mgr.GetConfig()
7684
r.mgr = mgr
@@ -115,11 +123,7 @@ func (r *Reconciler) Reconcile(request reconcile.Request) (result reconcile.Resu
115123
}
116124

117125
if r.options.status != nil {
118-
<<<<<<< HEAD
119-
if err = r.options.status.Preflight(ctx, instance); err != nil {
120-
=======
121126
if err := r.options.status.Preflight(ctx, instance); err != nil {
122-
>>>>>>> 3128f67... Changes preflight to version checks
123127
log.Error(err, "preflight check failed, not reconciling")
124128
return reconcile.Result{}, err
125129
}
@@ -145,13 +149,14 @@ func (r *Reconciler) reconcileExists(ctx context.Context, name types.NamespacedN
145149
log.WithValues("objects", fmt.Sprintf("%d", len(objects.Items))).Info("built deployment objects")
146150

147151
if r.options.status != nil {
148-
bool, err := r.options.status.VersionCheck(ctx, instance, objects)
149-
if err != nil {
150-
if !bool {
152+
isValidVersion, err := r.options.status.VersionCheck(ctx, instance, objects)
153+
if err != nil {
154+
if !isValidVersion {
151155
// r.client isn't exported so can't be updated in version check function
152-
r.client.Status().Update(ctx, instance)
153-
recorder := r.mgr.GetEventRecorderFor(fmt.Sprintf("%v", instance.GetName()))
154-
recorder.Event(instance, "Warning", "Failed version check", err.Error())
156+
if err := r.client.Status().Update(ctx, instance); err != nil {
157+
return reconcile.Result{}, err
158+
}
159+
r.recorder.Event(instance, "Warning", "Failed version check", err.Error())
155160
log.Error(err, "Version check failed, not reconciling")
156161
return reconcile.Result{}, nil
157162
}

pkg/patterns/declarative/status.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,15 @@ type Preflight interface {
4545

4646
type VersionCheck interface {
4747
// VersionCheck checks if the version of the operator is greater than or equal to the
48-
//version requested by objects in the manifest, if it isn't it updates the status and
48+
// version requested by objects in the manifest, if it isn't it updates the status and
4949
// events and stops reconciling
5050
VersionCheck(context.Context, DeclarativeObject, *manifest.Objects) (bool, error)
5151
}
5252

5353
// StatusBuilder provides a pluggable implementation of Status
5454
type StatusBuilder struct {
55-
ReconciledImpl Reconciled
56-
PreflightImpl Preflight
55+
ReconciledImpl Reconciled
56+
PreflightImpl Preflight
5757
VersionCheckImpl VersionCheck
5858
}
5959

@@ -71,7 +71,7 @@ func (s *StatusBuilder) Preflight(ctx context.Context, src DeclarativeObject) er
7171
return nil
7272
}
7373

74-
func (s *StatusBuilder) VersionCheck(ctx context.Context, src DeclarativeObject,objs *manifest.Objects) (bool, error) {
74+
func (s *StatusBuilder) VersionCheck(ctx context.Context, src DeclarativeObject, objs *manifest.Objects) (bool, error) {
7575
if s.VersionCheckImpl != nil {
7676
return s.VersionCheckImpl.VersionCheck(ctx, src, objs)
7777
}

0 commit comments

Comments
 (0)