-
Notifications
You must be signed in to change notification settings - Fork 19
/
util.go
160 lines (143 loc) · 5.32 KB
/
util.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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
package util
import (
"context"
"fmt"
"os"
configv1 "github.com/openshift/api/config/v1"
rukpakv1alpha2 "github.com/operator-framework/rukpak/api/v1alpha2"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
utilerror "k8s.io/apimachinery/pkg/util/errors"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/handler"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
platformv1alpha1 "github.com/openshift/api/platform/v1alpha1"
platformtypes "github.com/openshift/platform-operators/api/v1alpha1"
)
// GetPodNamespace checks whether the controller is running in a Pod vs.
// being run locally by inspecting the namespace file that gets mounted
// automatically for Pods at runtime. If that file doesn't exist, then
// return the value of the defaultNamespace parameter.
func PodNamespace(defaultNamespace string) string {
namespace, err := os.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/namespace")
if err != nil {
return defaultNamespace
}
return string(namespace)
}
func RequeuePlatformOperators(cl client.Client) handler.MapFunc {
return func(ctx context.Context, object client.Object) []reconcile.Request {
poList := &platformv1alpha1.PlatformOperatorList{}
if err := cl.List(context.Background(), poList); err != nil {
return nil
}
var requests []reconcile.Request
for _, po := range poList.Items {
requests = append(requests, reconcile.Request{
NamespacedName: types.NamespacedName{
Name: po.GetName(),
},
})
}
return requests
}
}
func RequeueBundleDeployment(c client.Client) handler.MapFunc {
return func(ctx context.Context, obj client.Object) []reconcile.Request {
bi := obj.(*rukpakv1alpha2.BundleDeployment)
poList := &platformv1alpha1.PlatformOperatorList{}
if err := c.List(context.Background(), poList); err != nil {
return nil
}
var requests []reconcile.Request
for _, po := range poList.Items {
po := po
for _, ref := range bi.GetOwnerReferences() {
if ref.Name == po.GetName() {
requests = append(requests, reconcile.Request{NamespacedName: client.ObjectKeyFromObject(&po)})
}
}
}
return requests
}
}
func RequeueClusterOperator(c client.Client, name string) handler.MapFunc {
return func(ctx context.Context, obj client.Object) []reconcile.Request {
co := &configv1.ClusterOperator{}
if err := c.Get(context.Background(), types.NamespacedName{Name: name}, co); err != nil {
return nil
}
return []reconcile.Request{{NamespacedName: client.ObjectKeyFromObject(co)}}
}
}
// InspectPlatformOperators iterates over all the POs in the list
// and determines whether a PO is in a failing state by inspecting its status.
// A nil return value indicates no errors were found with the POs provided.
func InspectPlatformOperators(poList *platformv1alpha1.PlatformOperatorList) error {
var poErrors []error
for _, po := range poList.Items {
if err := inspectPlatformOperator(po); err != nil {
poErrors = append(poErrors, err)
}
}
return utilerror.NewAggregate(poErrors)
}
// inspectPlatformOperator is responsible for inspecting an individual platform
// operator resource, and determining whether it's reporting any failing conditions.
// In the case that the PO resource is expressing failing states, then an error
// will be returned to reflect that.
func inspectPlatformOperator(po platformv1alpha1.PlatformOperator) error {
installed := meta.FindStatusCondition(po.Status.Conditions, platformtypes.TypeInstalled)
if installed == nil {
return buildPOFailureMessage(po.GetName(), platformtypes.ReasonInstallPending)
}
if installed.Status != metav1.ConditionTrue {
return buildPOFailureMessage(po.GetName(), installed.Reason)
}
return nil
}
func buildPOFailureMessage(name, reason string) error {
return fmt.Errorf("encountered the failing %s platform operator with reason %q", name, reason)
}
// InspectBundleDeployment is responsible for inspecting an individual BD
// resource, and verifying whether the referenced Bundle contents has been
// successfully unpacked and persisted to the cluster. In the case that the
// BD is reporting a successful status, a nil metav1.Condition will be returned.
func InspectBundleDeployment(_ context.Context, conditions []metav1.Condition) *metav1.Condition {
unpacked := meta.FindStatusCondition(conditions, rukpakv1alpha2.TypeHasValidBundle)
if unpacked == nil {
return &metav1.Condition{
Type: platformtypes.TypeInstalled,
Status: metav1.ConditionFalse,
Reason: platformtypes.ReasonUnpackPending,
Message: "Waiting for the bundle to be unpacked",
}
}
if unpacked.Status != metav1.ConditionTrue {
return &metav1.Condition{
Type: platformtypes.TypeInstalled,
Status: metav1.ConditionFalse,
Reason: unpacked.Reason,
Message: unpacked.Message,
}
}
installed := meta.FindStatusCondition(conditions, rukpakv1alpha2.TypeInstalled)
if installed == nil {
return &metav1.Condition{
Type: platformtypes.TypeInstalled,
Status: metav1.ConditionFalse,
Reason: platformtypes.ReasonInstallPending,
Message: "Waiting for the bundle to be installed",
}
}
if installed.Status != metav1.ConditionTrue {
return &metav1.Condition{
Type: platformtypes.TypeInstalled,
Status: metav1.ConditionFalse,
Reason: installed.Reason,
Message: installed.Message,
}
}
return nil
}