Skip to content

Commit a6536ef

Browse files
authored
Merge pull request #102 from SomtochiAma/update-event-status
Adds Version Check
2 parents 10baa89 + b8ba229 commit a6536ef

File tree

5 files changed

+135
-12
lines changed

5 files changed

+135
-12
lines changed

go.sum

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,6 @@ github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34
124124
github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg=
125125
github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
126126
github.com/go-openapi/jsonreference v0.18.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
127-
github.com/go-openapi/jsonreference v0.19.2 h1:o20suLFB4Ri0tuzpWtyHlh7E7HnkqTNLq6aR6WVNS1w=
128127
github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
129128
github.com/go-openapi/jsonreference v0.19.3 h1:5cxNfTy0UVC3X8JL5ymxzyoUZmo8iZb+jeTWn7tUa8o=
130129
github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8=
@@ -214,7 +213,6 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a
214213
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
215214
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
216215
github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
217-
github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
218216
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
219217
github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=
220218
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@@ -289,7 +287,6 @@ github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN
289287
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
290288
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
291289
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
292-
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e h1:hB2xlXdHp/pmPZq0y3QnmWAArdw9PqbmotexnWx/FU8=
293290
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
294291
github.com/mailru/easyjson v0.7.0 h1:aizVhC/NAAcKWb+5QsU1iNOZb4Yws5UO2I+aIprQITM=
295292
github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
@@ -324,12 +321,10 @@ github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn
324321
github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
325322
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
326323
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
327-
github.com/onsi/ginkgo v1.10.1 h1:q/mM8GF/n0shIN8SaAZ0V+jnLPzen6WIVZdiwrRlMlo=
328324
github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
329325
github.com/onsi/ginkgo v1.11.0 h1:JAKSXpt1YjtLA7YpPiqO9ss6sNXEsPfSGdwN0UHqzrw=
330326
github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
331327
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
332-
github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME=
333328
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
334329
github.com/onsi/gomega v1.8.1 h1:C5Dqfs/LeauYDX0jJXIe2SWmwCbGzx9yF8C8xy3Lh34=
335330
github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
@@ -346,23 +341,19 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
346341
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
347342
github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
348343
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
349-
github.com/prometheus/client_golang v0.9.3 h1:9iH4JKXLzFbOAdtqv/a+j8aewx2Y8lAjAydhbaScPF8=
350344
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
351345
github.com/prometheus/client_golang v1.0.0 h1:vrDKnkGzuGvhNAL56c7DBz29ZL+KxnoR0x7enabFceM=
352346
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
353347
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
354-
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 h1:S/YWwWx/RA8rT8tKFRuGUZhuA90OyIBpPCXkcbwU8DE=
355348
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
356349
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
357350
github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
358351
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
359352
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
360-
github.com/prometheus/common v0.4.0 h1:7etb9YClo3a6HjLzfl6rIQaU+FDfi0VSX39io3aQ+DM=
361353
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
362354
github.com/prometheus/common v0.4.1 h1:K0MGApIoQvMw27RTdJkPbr3JZ7DNbtxQNyi5STVM6Kw=
363355
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
364356
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
365-
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084 h1:sofwID9zm4tzrgykg80hfFph1mryUeLRsUfoocVVmRY=
366357
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
367358
github.com/prometheus/procfs v0.0.2 h1:6LJUbpNm42llc4HRCuvApCSWB/WfhuNo9K98Q9sNGfs=
368359
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,18 @@ func NewBasic(client client.Client) declarative.Status {
2929
// no preflight checks
3030
}
3131
}
32+
33+
// NewBasicVersionCheck provides an implementation of declarative.Status that
34+
// performs version checks for the version of the operator that the manifest requires.
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+
41+
return &declarative.StatusBuilder{
42+
ReconciledImpl: NewAggregator(client),
43+
VersionCheckImpl: v,
44+
// no preflight checks
45+
}, nil
46+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package status
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"github.com/blang/semver"
8+
"sigs.k8s.io/controller-runtime/pkg/client"
9+
"sigs.k8s.io/controller-runtime/pkg/log"
10+
addonsv1alpha1 "sigs.k8s.io/kubebuilder-declarative-pattern/pkg/patterns/addon/pkg/apis/v1alpha1"
11+
12+
"sigs.k8s.io/kubebuilder-declarative-pattern/pkg/patterns/declarative"
13+
"sigs.k8s.io/kubebuilder-declarative-pattern/pkg/patterns/declarative/pkg/manifest"
14+
)
15+
16+
// NewVersionCheck provides an implementation of declarative.Reconciled that
17+
// checks the version of the operator if it is up to the version required by the manifest
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
24+
}
25+
26+
type versionCheck struct {
27+
client client.Client
28+
operatorVersion semver.Version
29+
}
30+
31+
func (p *versionCheck) VersionCheck(
32+
ctx context.Context,
33+
src declarative.DeclarativeObject,
34+
objs *manifest.Objects,
35+
) (bool, error) {
36+
log := log.Log
37+
var minOperatorVersion semver.Version
38+
39+
// Look for annotation from any resource with the max version
40+
for _, obj := range objs.Items {
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")
44+
45+
versionNeeded, err := semver.Parse(versionNeededStr)
46+
if err != nil {
47+
log.WithValues("version", versionNeededStr).Error(err, "Unable to parse version restriction")
48+
return false, err
49+
}
50+
51+
if versionNeeded.GT(minOperatorVersion) {
52+
minOperatorVersion = versionNeeded
53+
}
54+
}
55+
}
56+
57+
if p.operatorVersion.GTE(minOperatorVersion) {
58+
return true, nil
59+
}
60+
61+
addonObject, ok := src.(addonsv1alpha1.CommonObject)
62+
if !ok {
63+
return false, fmt.Errorf("object %T was not an addonsv1alpha1.CommonObject", src)
64+
}
65+
66+
status := addonsv1alpha1.CommonStatus{
67+
Healthy: false,
68+
Errors: []string{
69+
fmt.Sprintf("manifest needs operator version >= %v, this operator is version %v", minOperatorVersion.String(), p.operatorVersion.String()),
70+
},
71+
}
72+
log.WithValues("name", addonObject.GetName()).WithValues("status", status).Info("updating status")
73+
addonObject.SetCommonStatus(status)
74+
75+
return false, fmt.Errorf("operator not qualified, manifest needs operator version >= %v", minOperatorVersion.String())
76+
}

pkg/patterns/declarative/reconciler.go

Lines changed: 26 additions & 1 deletion
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+
recorder "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 recorder.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,7 +123,7 @@ func (r *Reconciler) Reconcile(request reconcile.Request) (result reconcile.Resu
115123
}
116124

117125
if r.options.status != nil {
118-
if err = r.options.status.Preflight(ctx, instance); err != nil {
126+
if err := r.options.status.Preflight(ctx, instance); err != nil {
119127
log.Error(err, "preflight check failed, not reconciling")
120128
return reconcile.Result{}, err
121129
}
@@ -140,6 +148,23 @@ func (r *Reconciler) reconcileExists(ctx context.Context, name types.NamespacedN
140148
}
141149
log.WithValues("objects", fmt.Sprintf("%d", len(objects.Items))).Info("built deployment objects")
142150

151+
if r.options.status != nil {
152+
isValidVersion, err := r.options.status.VersionCheck(ctx, instance, objects)
153+
if err != nil {
154+
if !isValidVersion {
155+
// r.client isn't exported so can't be updated in version check function
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())
160+
log.Error(err, "Version check failed, not reconciling")
161+
return reconcile.Result{}, nil
162+
}
163+
log.Error(err, "Version check failed, trying to reconcile")
164+
return reconcile.Result{}, err
165+
}
166+
}
167+
143168
defer func() {
144169
if r.options.status != nil {
145170
if err := r.options.status.Reconciled(ctx, instance, objects); err != nil {

pkg/patterns/declarative/status.go

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
type Status interface {
2727
Reconciled
2828
Preflight
29+
VersionCheck
2930
}
3031

3132
type Reconciled interface {
@@ -42,10 +43,18 @@ type Preflight interface {
4243
Preflight(context.Context, DeclarativeObject) error
4344
}
4445

46+
type VersionCheck interface {
47+
// 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
49+
// events and stops reconciling
50+
VersionCheck(context.Context, DeclarativeObject, *manifest.Objects) (bool, error)
51+
}
52+
4553
// StatusBuilder provides a pluggable implementation of Status
4654
type StatusBuilder struct {
47-
ReconciledImpl Reconciled
48-
PreflightImpl Preflight
55+
ReconciledImpl Reconciled
56+
PreflightImpl Preflight
57+
VersionCheckImpl VersionCheck
4958
}
5059

5160
func (s *StatusBuilder) Reconciled(ctx context.Context, src DeclarativeObject, objs *manifest.Objects) error {
@@ -62,4 +71,11 @@ func (s *StatusBuilder) Preflight(ctx context.Context, src DeclarativeObject) er
6271
return nil
6372
}
6473

74+
func (s *StatusBuilder) VersionCheck(ctx context.Context, src DeclarativeObject, objs *manifest.Objects) (bool, error) {
75+
if s.VersionCheckImpl != nil {
76+
return s.VersionCheckImpl.VersionCheck(ctx, src, objs)
77+
}
78+
return true, nil
79+
}
80+
6581
var _ Status = &StatusBuilder{}

0 commit comments

Comments
 (0)