Skip to content

Commit 35e7f3e

Browse files
committed
feat(subscriptions): add catalog health conditions
- Add Subscription status catalog health conditions - Add list of catalog health references to Subscription status - Reorganize internal types and add new fields
1 parent 496b877 commit 35e7f3e

File tree

6 files changed

+350
-4
lines changed

6 files changed

+350
-4
lines changed

pkg/api/apis/operators/clusterserviceversion_types.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import (
1111
)
1212

1313
// ClusterServiceVersionKind is the PascalCase name of a CSV's kind.
14-
const ClusterServiceVersionKind = "ClusterServiceVersionKind"
14+
const ClusterServiceVersionKind = "ClusterServiceVersion"
1515

1616
// InstallModeType is a supported type of install mode for CSV installation
1717
type InstallModeType string

pkg/api/apis/operators/install/install.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,4 @@ func Install(scheme *runtime.Scheme) {
1515
utilruntime.Must(v1alpha1.AddToScheme(scheme))
1616
utilruntime.Must(v1.AddToScheme(scheme))
1717
utilruntime.Must(scheme.SetVersionPriority(v1.SchemeGroupVersion, v1alpha1.SchemeGroupVersion))
18-
}
18+
}

pkg/api/apis/operators/reference/reference_test.go

Lines changed: 117 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ import (
1111
"k8s.io/apimachinery/pkg/runtime"
1212
"k8s.io/apimachinery/pkg/types"
1313

14-
"github.com/operator-framework/operator-lifecycle-manager/pkg/api/apis/operators/v1"
14+
"github.com/operator-framework/operator-lifecycle-manager/pkg/api/apis/operators"
15+
v1 "github.com/operator-framework/operator-lifecycle-manager/pkg/api/apis/operators/v1"
1516
"github.com/operator-framework/operator-lifecycle-manager/pkg/api/apis/operators/v1alpha1"
1617
)
1718

@@ -159,6 +160,121 @@ func TestGetReference(t *testing.T) {
159160
err: nil,
160161
},
161162
},
163+
{
164+
name: "internalversion/ClusterServiceVersion",
165+
args: args{
166+
&operators.ClusterServiceVersion{
167+
ObjectMeta: metav1.ObjectMeta{
168+
Namespace: "ns",
169+
Name: "csv",
170+
UID: types.UID("uid"),
171+
SelfLink: buildSelfLink(operators.SchemeGroupVersion.String(), "clusterserviceversions", "ns", "csv"),
172+
},
173+
},
174+
},
175+
want: want{
176+
ref: &corev1.ObjectReference{
177+
Namespace: "ns",
178+
Name: "csv",
179+
UID: types.UID("uid"),
180+
Kind: operators.ClusterServiceVersionKind,
181+
APIVersion: operators.SchemeGroupVersion.String(),
182+
},
183+
err: nil,
184+
},
185+
},
186+
{
187+
name: "internalversion/InstallPlan",
188+
args: args{
189+
&v1alpha1.InstallPlan{
190+
ObjectMeta: metav1.ObjectMeta{
191+
Namespace: "ns",
192+
Name: "ip",
193+
UID: types.UID("uid"),
194+
SelfLink: buildSelfLink(operators.SchemeGroupVersion.String(), "installplans", "ns", "ip"),
195+
},
196+
},
197+
},
198+
want: want{
199+
ref: &corev1.ObjectReference{
200+
Namespace: "ns",
201+
Name: "ip",
202+
UID: types.UID("uid"),
203+
Kind: operators.InstallPlanKind,
204+
APIVersion: operators.SchemeGroupVersion.String(),
205+
},
206+
err: nil,
207+
},
208+
},
209+
{
210+
name: "internalversion/Subscription",
211+
args: args{
212+
&v1alpha1.Subscription{
213+
ObjectMeta: metav1.ObjectMeta{
214+
Namespace: "ns",
215+
Name: "sub",
216+
UID: types.UID("uid"),
217+
SelfLink: buildSelfLink(operators.SchemeGroupVersion.String(), "subscriptions", "ns", "sub"),
218+
},
219+
},
220+
},
221+
want: want{
222+
ref: &corev1.ObjectReference{
223+
Namespace: "ns",
224+
Name: "sub",
225+
UID: types.UID("uid"),
226+
Kind: operators.SubscriptionKind,
227+
APIVersion: operators.SchemeGroupVersion.String(),
228+
},
229+
err: nil,
230+
},
231+
},
232+
{
233+
name: "internalversion/CatalogSource",
234+
args: args{
235+
&v1alpha1.CatalogSource{
236+
ObjectMeta: metav1.ObjectMeta{
237+
Namespace: "ns",
238+
Name: "catsrc",
239+
UID: types.UID("uid"),
240+
SelfLink: buildSelfLink(operators.SchemeGroupVersion.String(), "catalogsources", "ns", "catsrc"),
241+
},
242+
},
243+
},
244+
want: want{
245+
ref: &corev1.ObjectReference{
246+
Namespace: "ns",
247+
Name: "catsrc",
248+
UID: types.UID("uid"),
249+
Kind: operators.CatalogSourceKind,
250+
APIVersion: operators.SchemeGroupVersion.String(),
251+
},
252+
err: nil,
253+
},
254+
},
255+
{
256+
name: "internalversion/OperatorGroup",
257+
args: args{
258+
&v1.OperatorGroup{
259+
ObjectMeta: metav1.ObjectMeta{
260+
Namespace: "ns",
261+
Name: "og",
262+
UID: types.UID("uid"),
263+
SelfLink: buildSelfLink(operators.SchemeGroupVersion.String(), "operatorgroups", "ns", "og"),
264+
},
265+
},
266+
},
267+
want: want{
268+
ref: &corev1.ObjectReference{
269+
Namespace: "ns",
270+
Name: "og",
271+
UID: types.UID("uid"),
272+
Kind: operators.OperatorGroupKind,
273+
APIVersion: operators.SchemeGroupVersion.String(),
274+
},
275+
err: nil,
276+
},
277+
},
162278
}
163279

164280
for _, tt := range tests {

pkg/api/apis/operators/register.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,7 @@ func addKnownTypes(scheme *runtime.Scheme) error {
4848
)
4949
return nil
5050
}
51+
52+
func init() {
53+
54+
}

pkg/api/apis/operators/subscription_types.go

Lines changed: 114 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import (
77
)
88

99
// SubscriptionKind is the PascalCase name of a Subscription's kind.
10-
const SubscriptionKind = "SubscriptionKind"
10+
const SubscriptionKind = "Subscription"
1111

1212
// SubscriptionState tracks when updates are available, installing, or service is up to date
1313
type SubscriptionState string
@@ -35,6 +35,65 @@ type SubscriptionSpec struct {
3535
InstallPlanApproval Approval
3636
}
3737

38+
// SubscriptionConditionType indicates an explicit state condition about a Subscription in "abnormal-true"
39+
// polarity form (see https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties).
40+
type SubscriptionConditionType string
41+
42+
const (
43+
// SubscriptionCatalogSourcesUnhealthy indicates that some or all of the CatalogSources to be used in resolution are unhealthy.
44+
SubscriptionCatalogSourcesUnhealthy SubscriptionConditionType = "CatalogSourcesUnhealthy"
45+
)
46+
47+
const (
48+
// NoCatalogSourcesFound is a reason string for Subscriptions with unhealthy CatalogSources due to none being available.
49+
NoCatalogSourcesFound = "NoCatalogSourcesFound"
50+
51+
// AllCatalogSourcesHealthy is a reason string for Subscriptions whose CatalogSources are all healthy.
52+
AllCatalogSourcesHealthy = "AllCatalogSourcesHealthy"
53+
54+
// CatalogSourcesAdded is a reason string for Subscriptions that transitioned due to CatalogSources being added.
55+
CatalogSourcesAdded = "CatalogSourcesAdded"
56+
57+
// CatalogSourcesUpdated is a reason string for Subscriptions that transitioned due to CatalogSource being updated..
58+
CatalogSourcesUpdated = "CatalogSourcesUpdated"
59+
60+
// CatalogSourcesDeleted is a reason string for Subscriptions that transitioned due to CatalogSources being removed.
61+
CatalogSourcesDeleted = "CatalogSourcesDeleted"
62+
63+
// UnhealthyCatalogSourceFound is a reason string for Subscriptions that transitioned because an unhealthy CatalogSource was found.
64+
UnhealthyCatalogSourceFound = "UnhealthyCatalogSourceFound"
65+
)
66+
67+
type SubscriptionCondition struct {
68+
// Type is the type of Subscription condition.
69+
Type SubscriptionConditionType
70+
71+
// Status is the status of the condition, one of True, False, Unknown.
72+
Status corev1.ConditionStatus
73+
74+
// Reason is a one-word CamelCase reason for the condition's last transition.
75+
// +optional
76+
Reason string
77+
78+
// Message is a human-readable message indicating details about last transition.
79+
// +optional
80+
Message string
81+
82+
// LastHeartbeatTime is the last time we got an update on a given condition
83+
// +optional
84+
LastHeartbeatTime *metav1.Time
85+
86+
// LastTransitionTime is the last time the condition transit from one status to another
87+
// +optional
88+
LastTransitionTime *metav1.Time
89+
}
90+
91+
// Equals returns true if a SubscriptionCondition equals the one given, false otherwise.
92+
// Equality is determined by the equality of the type, status, reason, and message fields ONLY.
93+
func (s SubscriptionCondition) Equals(condition SubscriptionCondition) bool {
94+
return s.Type == condition.Type && s.Status == condition.Status && s.Reason == condition.Reason && s.Message == condition.Message
95+
}
96+
3897
type SubscriptionStatus struct {
3998
// CurrentCSV is the CSV the Subscription is progressing to.
4099
// +optional
@@ -61,17 +120,71 @@ type SubscriptionStatus struct {
61120
// +optional
62121
InstallPlanRef *corev1.ObjectReference
63122

123+
// CatalogHealth contains the Subscription's view of its relevant CatalogSources' status.
124+
// It is used to determine SubscriptionStatusConditions related to CatalogSources.
125+
// +optional
126+
CatalogHealth []SubscriptionCatalogHealth
127+
128+
// Conditions is a list of the latest available observations about a Subscription's current state.
129+
// +optional
130+
Conditions []SubscriptionCondition
131+
64132
// LastUpdated represents the last time that the Subscription status was updated.
65133
LastUpdated metav1.Time
66134
}
67135

136+
// GetCondition returns the SubscriptionCondition of the given type if it exists in the SubscriptionStatus' Conditions.
137+
// Returns a condition of the given type with a ConditionStatus of "Unknown" if not found.
138+
func (status SubscriptionStatus) GetCondition(conditionType SubscriptionConditionType) SubscriptionCondition {
139+
for _, cond := range status.Conditions {
140+
if cond.Type == conditionType {
141+
return cond
142+
}
143+
}
144+
145+
return SubscriptionCondition{
146+
Type: conditionType,
147+
Status: corev1.ConditionUnknown,
148+
}
149+
}
150+
151+
// SetCondition sets the given SubscriptionCondition in the SubscriptionStatus' Conditions.
152+
func (status *SubscriptionStatus) SetCondition(condition SubscriptionCondition) {
153+
for i, cond := range status.Conditions {
154+
if cond.Type == condition.Type {
155+
status.Conditions[i] = condition
156+
return
157+
}
158+
}
159+
160+
status.Conditions = append(status.Conditions, condition)
161+
}
162+
68163
type InstallPlanReference struct {
69164
APIVersion string
70165
Kind string
71166
Name string
72167
UID types.UID
73168
}
74169

170+
// SubscriptionCatalogHealth describes the health of a CatalogSource the Subscription knows about.
171+
type SubscriptionCatalogHealth struct {
172+
// CatalogSourceRef is a reference to a CatalogSource.
173+
CatalogSourceRef *corev1.ObjectReference
174+
175+
// LastUpdated represents the last time that the CatalogSourceHealth changed
176+
LastUpdated *metav1.Time
177+
178+
// Healthy is true if the CatalogSource is healthy; false otherwise.
179+
Healthy bool
180+
}
181+
182+
// Equals returns true if a SubscriptionCatalogHealth equals the one given, false otherwise.
183+
// Equality is based SOLEY on health and UID.
184+
func (s SubscriptionCatalogHealth) Equals(health SubscriptionCatalogHealth) bool {
185+
return s.Healthy == health.Healthy && s.CatalogSourceRef.UID == health.CatalogSourceRef.UID
186+
}
187+
75188
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
76189
// +genclient
77190

0 commit comments

Comments
 (0)