-
Notifications
You must be signed in to change notification settings - Fork 190
/
subscription.go
117 lines (101 loc) · 4.02 KB
/
subscription.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package gatewayclass
import (
"context"
"fmt"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
operatorsv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1"
operatorcontroller "github.com/openshift/cluster-ingress-operator/pkg/operator/controller"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
)
// ensureServiceMeshOperatorSubscription attempts to ensure that a subscription
// for servicemeshoperator is present and returns a Boolean indicating whether
// it exists, the subscription if it exists, and an error value.
func (r *reconciler) ensureServiceMeshOperatorSubscription(ctx context.Context) (bool, *operatorsv1alpha1.Subscription, error) {
name := operatorcontroller.ServiceMeshSubscriptionName()
have, current, err := r.currentSubscription(ctx, name)
if err != nil {
return false, nil, err
}
desired, err := desiredSubscription(name)
if err != nil {
return have, current, err
}
switch {
case !have:
if err := r.createSubscription(ctx, desired); err != nil {
return false, nil, err
}
return r.currentSubscription(ctx, name)
case have:
if updated, err := r.updateSubscription(ctx, current, desired); err != nil {
return have, current, err
} else if updated {
return r.currentSubscription(ctx, name)
}
}
return true, current, nil
}
// desiredSubscription returns the desired subscription.
func desiredSubscription(name types.NamespacedName) (*operatorsv1alpha1.Subscription, error) {
subscription := operatorsv1alpha1.Subscription{
ObjectMeta: metav1.ObjectMeta{
Namespace: name.Namespace,
Name: name.Name,
},
Spec: &operatorsv1alpha1.SubscriptionSpec{
Channel: "stable",
InstallPlanApproval: operatorsv1alpha1.ApprovalAutomatic,
Package: "servicemeshoperator",
CatalogSource: "redhat-operators",
CatalogSourceNamespace: "openshift-marketplace",
},
}
return &subscription, nil
}
// currentSubscription returns the current subscription.
func (r *reconciler) currentSubscription(ctx context.Context, name types.NamespacedName) (bool, *operatorsv1alpha1.Subscription, error) {
var subscription operatorsv1alpha1.Subscription
if err := r.client.Get(ctx, name, &subscription); err != nil {
if errors.IsNotFound(err) {
return false, nil, nil
}
return false, nil, fmt.Errorf("failed to get subscription %s: %w", name, err)
}
return true, &subscription, nil
}
// createSubscription creates a subscription.
func (r *reconciler) createSubscription(ctx context.Context, subscription *operatorsv1alpha1.Subscription) error {
if err := r.client.Create(ctx, subscription); err != nil {
return fmt.Errorf("failed to create subscription %s/%s: %w", subscription.Namespace, subscription.Name, err)
}
log.Info("created subscription", "namespace", subscription.Namespace, "name", subscription.Name)
return nil
}
// updateSubscription updates a subscription.
func (r *reconciler) updateSubscription(ctx context.Context, current, desired *operatorsv1alpha1.Subscription) (bool, error) {
changed, updated := subscriptionChanged(current, desired)
if !changed {
return false, nil
}
// Diff before updating because the client may mutate the object.
diff := cmp.Diff(current, updated, cmpopts.EquateEmpty())
if err := r.client.Update(ctx, updated); err != nil {
return false, fmt.Errorf("failed to update subscription %s/%s: %w", updated.Namespace, updated.Name, err)
}
log.Info("updated subscription", "namespace", updated.Namespace, "name", updated.Name, "diff", diff)
return true, nil
}
// subscriptionChanged returns a Boolean indicating whether the current
// subscription matches the expected subscription and the updated subscription
// if they do not match.
func subscriptionChanged(current, expected *operatorsv1alpha1.Subscription) (bool, *operatorsv1alpha1.Subscription) {
if cmp.Equal(current.Spec, expected.Spec, cmpopts.EquateEmpty()) {
return false, nil
}
updated := current.DeepCopy()
updated.Spec = expected.Spec
return true, updated
}