Skip to content

Commit a518f8f

Browse files
committed
Prevent endpoint update if service operator changes condition
Previously to apply service overrides to service CRs there were checks that services have reached a specific condition state. E.g. for glance that glancev1.GlanceAPIReadyCondition is true. This conditon resulted in the behavior that when after a successful deployment glance flipped to glancev1.GlanceAPIReadyCondition == False e.g. seen when ceph is not healty and glance api pods manually restarted, that the service overrides got removed (with route hostname information) and the keystoneendpoint updated to be the k8s service instead of the route. With this change there is no wait for a condition, instead checking the endpoint k8s services matching the label selector applied by the openstack-operator. If no services are found, the user provided overrides + the label selector get set. If the expected number of k8s services are identified, endpointdetails get evaluated and e.g. the routes hostname applied. Initially the conditions were used to prevent rerunning bootstrap jobs while there is still one in progress. With the changes to the DoJob [1] this should no longer be required since the job handling will wait for a running job to complete before rerunning it with a new config. [1] https://github.com/openstack-k8s-operators/lib-common/blob/main/modules/common/job/job.go#L115
1 parent 5ca45db commit a518f8f

File tree

15 files changed

+336
-334
lines changed

15 files changed

+336
-334
lines changed

pkg/openstack/barbican.go

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"context"
55
"fmt"
66

7-
"github.com/openstack-k8s-operators/lib-common/modules/common"
87
"github.com/openstack-k8s-operators/lib-common/modules/common/condition"
98
"github.com/openstack-k8s-operators/lib-common/modules/common/helper"
109
"github.com/openstack-k8s-operators/lib-common/modules/common/service"
@@ -42,7 +41,7 @@ func ReconcileBarbican(ctx context.Context, instance *corev1beta1.OpenStackContr
4241
if instance.Spec.Barbican.Template.BarbicanAPI.Override.Service == nil {
4342
instance.Spec.Barbican.Template.BarbicanAPI.Override.Service = map[service.Endpoint]service.RoutedOverrideSpec{}
4443
}
45-
instance.Spec.Barbican.Template.BarbicanAPI.Override.Service[endpointType] = AddServiceComponentLabel(
44+
instance.Spec.Barbican.Template.BarbicanAPI.Override.Service[endpointType] = AddServiceOpenStackOperatorLabel(
4645
instance.Spec.Barbican.Template.BarbicanAPI.Override.Service[endpointType],
4746
barbican.Name)
4847
}
@@ -60,17 +59,18 @@ func ReconcileBarbican(ctx context.Context, instance *corev1beta1.OpenStackContr
6059
}
6160
instance.Spec.Barbican.Template.BarbicanAPI.TLS.CaBundleSecretName = instance.Status.TLS.CaBundleSecretName
6261

63-
if barbican.Status.Conditions.IsTrue(barbicanv1.BarbicanAPIReadyCondition) {
64-
svcs, err := service.GetServicesListWithLabel(
65-
ctx,
66-
helper,
67-
instance.Namespace,
68-
map[string]string{common.AppSelector: barbican.Name},
69-
)
70-
if err != nil {
71-
return ctrl.Result{}, err
72-
}
62+
svcs, err := service.GetServicesListWithLabel(
63+
ctx,
64+
helper,
65+
instance.Namespace,
66+
GetServiceOpenStackOperatorLabel(barbican.Name),
67+
)
68+
if err != nil {
69+
return ctrl.Result{}, err
70+
}
7371

72+
// make sure to get to EndpointConfig when all service got created
73+
if len(svcs.Items) == len(instance.Spec.Barbican.Template.BarbicanAPI.Override.Service) {
7474
endpointDetails, ctrlResult, err := EnsureEndpointConfig(
7575
ctx,
7676
instance,
@@ -87,9 +87,8 @@ func ReconcileBarbican(ctx context.Context, instance *corev1beta1.OpenStackContr
8787
} else if (ctrlResult != ctrl.Result{}) {
8888
return ctrlResult, nil
8989
}
90-
90+
// set service overrides
9191
instance.Spec.Barbican.Template.BarbicanAPI.Override.Service = endpointDetails.GetEndpointServiceOverrides()
92-
9392
// update TLS settings with cert secret
9493
instance.Spec.Barbican.Template.BarbicanAPI.TLS.API.Public.SecretName = endpointDetails.GetEndptCertSecret(service.EndpointPublic)
9594
instance.Spec.Barbican.Template.BarbicanAPI.TLS.API.Internal.SecretName = endpointDetails.GetEndptCertSecret(service.EndpointInternal)

pkg/openstack/cinder.go

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"context"
55
"fmt"
66

7-
"github.com/openstack-k8s-operators/lib-common/modules/common"
87
"github.com/openstack-k8s-operators/lib-common/modules/common/condition"
98
"github.com/openstack-k8s-operators/lib-common/modules/common/helper"
109
"github.com/openstack-k8s-operators/lib-common/modules/common/service"
@@ -44,7 +43,7 @@ func ReconcileCinder(ctx context.Context, instance *corev1beta1.OpenStackControl
4443
instance.Spec.Cinder.Template.CinderAPI.Override.Service = map[service.Endpoint]service.RoutedOverrideSpec{}
4544
}
4645
instance.Spec.Cinder.Template.CinderAPI.Override.Service[endpointType] =
47-
AddServiceComponentLabel(
46+
AddServiceOpenStackOperatorLabel(
4847
instance.Spec.Cinder.Template.CinderAPI.Override.Service[endpointType],
4948
cinder.Name)
5049
}
@@ -62,17 +61,18 @@ func ReconcileCinder(ctx context.Context, instance *corev1beta1.OpenStackControl
6261
}
6362
instance.Spec.Cinder.Template.CinderAPI.TLS.CaBundleSecretName = instance.Status.TLS.CaBundleSecretName
6463

65-
if cinder.Status.Conditions.IsTrue(cinderv1.CinderAPIReadyCondition) {
66-
svcs, err := service.GetServicesListWithLabel(
67-
ctx,
68-
helper,
69-
instance.Namespace,
70-
map[string]string{common.AppSelector: cinder.Name},
71-
)
72-
if err != nil {
73-
return ctrl.Result{}, err
74-
}
64+
svcs, err := service.GetServicesListWithLabel(
65+
ctx,
66+
helper,
67+
instance.Namespace,
68+
GetServiceOpenStackOperatorLabel(cinder.Name),
69+
)
70+
if err != nil {
71+
return ctrl.Result{}, err
72+
}
7573

74+
// make sure to get to EndpointConfig when all service got created
75+
if len(svcs.Items) == len(instance.Spec.Cinder.Template.CinderAPI.Override.Service) {
7676
endpointDetails, ctrlResult, err := EnsureEndpointConfig(
7777
ctx,
7878
instance,
@@ -89,9 +89,8 @@ func ReconcileCinder(ctx context.Context, instance *corev1beta1.OpenStackControl
8989
} else if (ctrlResult != ctrl.Result{}) {
9090
return ctrlResult, nil
9191
}
92-
92+
// set service overrides
9393
instance.Spec.Cinder.Template.CinderAPI.Override.Service = endpointDetails.GetEndpointServiceOverrides()
94-
9594
// update TLS settings with cert secret
9695
instance.Spec.Cinder.Template.CinderAPI.TLS.API.Public.SecretName = endpointDetails.GetEndptCertSecret(service.EndpointPublic)
9796
instance.Spec.Cinder.Template.CinderAPI.TLS.API.Internal.SecretName = endpointDetails.GetEndptCertSecret(service.EndpointInternal)

pkg/openstack/common.go

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import (
1818
ironicv1 "github.com/openstack-k8s-operators/ironic-operator/api/v1beta1"
1919
keystonev1 "github.com/openstack-k8s-operators/keystone-operator/api/v1beta1"
2020
"github.com/openstack-k8s-operators/lib-common/modules/certmanager"
21-
"github.com/openstack-k8s-operators/lib-common/modules/common"
2221
"github.com/openstack-k8s-operators/lib-common/modules/common/condition"
2322
"github.com/openstack-k8s-operators/lib-common/modules/common/helper"
2423
"github.com/openstack-k8s-operators/lib-common/modules/common/route"
@@ -47,6 +46,17 @@ import (
4746
"sigs.k8s.io/controller-runtime/pkg/reconcile"
4847
)
4948

49+
const (
50+
// ooSelector is used as a selector to the labels to differentiate from
51+
// any other possible labels added to services, because e.g. the common.AppSelector
52+
// is also used by service operators.
53+
ooSelector = "osctlplane"
54+
55+
// ooAppSelector service selector label added by the openstack-operator to service
56+
// overrides
57+
ooAppSelector = "osctlplane-service"
58+
)
59+
5060
// GetLog returns a logger object with a prefix of "controller.name" and aditional controller context fields
5161
func GetLogger(ctx context.Context) logr.Logger {
5262
return log.FromContext(ctx).WithName("Controllers").WithName("OpenstackControlPlane")
@@ -71,10 +81,20 @@ func EnsureDeleted(ctx context.Context, helper *helper.Helper, obj client.Object
7181

7282
}
7383

74-
// AddServiceComponentLabel - adds component label to the service override to be able to query
84+
// GetServiceOpenStackOperatorLabel - returns the labels to be added to service override
85+
func GetServiceOpenStackOperatorLabel(value string) map[string]string {
86+
return map[string]string{
87+
ooAppSelector: value,
88+
ooSelector: "",
89+
}
90+
}
91+
92+
// AddServiceOpenStackOperatorLabel - adds labels to the service override to be able to query
7593
// the service labels to check for any route creation
76-
func AddServiceComponentLabel(svcOverride service.RoutedOverrideSpec, value string) service.RoutedOverrideSpec {
77-
svcOverride.AddLabel(map[string]string{common.AppSelector: value})
94+
func AddServiceOpenStackOperatorLabel(svcOverride service.RoutedOverrideSpec, value string) service.RoutedOverrideSpec {
95+
for s, v := range GetServiceOpenStackOperatorLabel(value) {
96+
svcOverride.AddLabel(map[string]string{s: v})
97+
}
7898

7999
return svcOverride
80100
}
@@ -315,13 +335,13 @@ func (ed *EndpointDetail) ensureRoute(
315335
owner metav1.Object,
316336
condType condition.Type,
317337
) (ctrl.Result, error) {
318-
// check if there is already a route with common.AppSelector from the service
319-
if svcLabelVal, ok := svc.Labels[common.AppSelector]; ok {
338+
// check if there is already a route with ooAppSelector from the service
339+
if svcLabelVal, ok := svc.Labels[ooAppSelector]; ok {
320340
routes, err := GetRoutesListWithLabel(
321341
ctx,
322342
helper,
323343
instance.Namespace,
324-
map[string]string{common.AppSelector: svcLabelVal},
344+
map[string]string{ooAppSelector: svcLabelVal},
325345
)
326346
if err != nil {
327347
return ctrl.Result{}, err
@@ -376,8 +396,8 @@ func (ed *EndpointDetail) ensureRoute(
376396
ed.Service.OverrideSpec.EmbeddedLabelsAnnotations = &service.EmbeddedLabelsAnnotations{}
377397
}
378398

379-
if labelVal, ok := ed.Service.OverrideSpec.EmbeddedLabelsAnnotations.Labels[common.AppSelector]; ok {
380-
ed.Labels = map[string]string{common.AppSelector: labelVal}
399+
if labelVal, ok := ed.Service.OverrideSpec.EmbeddedLabelsAnnotations.Labels[ooAppSelector]; ok {
400+
ed.Labels = map[string]string{ooAppSelector: labelVal}
381401
}
382402

383403
ctrlResult, err := ed.CreateRoute(ctx, helper, owner)

pkg/openstack/designate.go

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"context"
55
"fmt"
66

7-
"github.com/openstack-k8s-operators/lib-common/modules/common"
87
"github.com/openstack-k8s-operators/lib-common/modules/common/condition"
98
"github.com/openstack-k8s-operators/lib-common/modules/common/helper"
109
"github.com/openstack-k8s-operators/lib-common/modules/common/service"
@@ -43,7 +42,7 @@ func ReconcileDesignate(ctx context.Context, instance *corev1beta1.OpenStackCont
4342
instance.Spec.Designate.Template.DesignateAPI.Override.Service = map[service.Endpoint]service.RoutedOverrideSpec{}
4443
}
4544
instance.Spec.Designate.Template.DesignateAPI.Override.Service[endpointType] =
46-
AddServiceComponentLabel(
45+
AddServiceOpenStackOperatorLabel(
4746
instance.Spec.Designate.Template.DesignateAPI.Override.Service[endpointType],
4847
designate.Name)
4948
}
@@ -55,17 +54,18 @@ func ReconcileDesignate(ctx context.Context, instance *corev1beta1.OpenStackCont
5554
}
5655
}
5756

58-
if designate.Status.Conditions.IsTrue(designatev1.DesignateAPIReadyCondition) {
59-
svcs, err := service.GetServicesListWithLabel(
60-
ctx,
61-
helper,
62-
instance.Namespace,
63-
map[string]string{common.AppSelector: designate.Name},
64-
)
65-
if err != nil {
66-
return ctrl.Result{}, err
67-
}
57+
svcs, err := service.GetServicesListWithLabel(
58+
ctx,
59+
helper,
60+
instance.Namespace,
61+
GetServiceOpenStackOperatorLabel(designate.Name),
62+
)
63+
if err != nil {
64+
return ctrl.Result{}, err
65+
}
6866

67+
// make sure to get to EndpointConfig when all service got created
68+
if len(svcs.Items) == len(instance.Spec.Designate.Template.DesignateAPI.Override.Service) {
6969
endpointDetails, ctrlResult, err := EnsureEndpointConfig(
7070
ctx,
7171
instance,
@@ -82,7 +82,7 @@ func ReconcileDesignate(ctx context.Context, instance *corev1beta1.OpenStackCont
8282
} else if (ctrlResult != ctrl.Result{}) {
8383
return ctrlResult, nil
8484
}
85-
85+
// set service overrides
8686
instance.Spec.Designate.Template.DesignateAPI.Override.Service = endpointDetails.GetEndpointServiceOverrides()
8787
}
8888

pkg/openstack/glance.go

Lines changed: 40 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"github.com/openstack-k8s-operators/lib-common/modules/common/condition"
99
"github.com/openstack-k8s-operators/lib-common/modules/common/helper"
1010
"github.com/openstack-k8s-operators/lib-common/modules/common/service"
11+
"github.com/openstack-k8s-operators/lib-common/modules/common/util"
1112
corev1beta1 "github.com/openstack-k8s-operators/openstack-operator/apis/core/v1beta1"
1213
k8s_errors "k8s.io/apimachinery/pkg/api/errors"
1314
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -18,8 +19,11 @@ import (
1819

1920
const (
2021
// svcSelector is used as selector to get the list of "Services" associated
21-
// to a specific glanceAPI instance
22-
svcSelector = "glanceAPI"
22+
// to a specific glanceAPI instance. It must be different from glanceAPI
23+
// label set by the service operator as in case of split glanceAPI type the
24+
// the label on public svc gets set to -external and internal instance svc
25+
// to -internal instead of the glance top level glanceType split
26+
svcSelector = "tlGlanceAPI"
2327
)
2428

2529
// ReconcileGlance -
@@ -55,7 +59,7 @@ func ReconcileGlance(ctx context.Context, instance *corev1beta1.OpenStackControl
5559
if glanceAPI.Override.Service == nil {
5660
glanceAPI.Override.Service = map[service.Endpoint]service.RoutedOverrideSpec{}
5761
}
58-
glanceAPI.Override.Service[endpointType] = AddServiceComponentLabel(
62+
glanceAPI.Override.Service[endpointType] = AddServiceOpenStackOperatorLabel(
5963
glanceAPI.Override.Service[endpointType], glance.Name)
6064

6165
svcOverride := glanceAPI.Override.Service[endpointType]
@@ -71,32 +75,36 @@ func ReconcileGlance(ctx context.Context, instance *corev1beta1.OpenStackControl
7175
instance.Spec.Glance.Template.GlanceAPIs[name] = glanceAPI
7276
}
7377

74-
if glance.Status.Conditions.IsTrue(glancev1.GlanceAPIReadyCondition) {
75-
// initialize the main APIOverride struct
76-
if instance.Spec.Glance.APIOverride == nil {
77-
instance.Spec.Glance.APIOverride = map[string]corev1beta1.Override{}
78-
}
78+
// initialize the main APIOverride struct
79+
if instance.Spec.Glance.APIOverride == nil {
80+
instance.Spec.Glance.APIOverride = map[string]corev1beta1.Override{}
81+
}
7982

80-
var changed bool = false
81-
for name, glanceAPI := range instance.Spec.Glance.Template.GlanceAPIs {
82-
if _, ok := instance.Spec.Glance.APIOverride[name]; !ok {
83-
instance.Spec.Glance.APIOverride[name] = corev1beta1.Override{}
84-
}
85-
// Retrieve the services by Label and filter on glanceAPI: for
86-
// each instance we should get **only** the associated `SVCs`
87-
// and not the whole list. As per the Glance design doc we know
88-
// that a given instance name is made in the form: "<service>
89-
// <apiName> <apiType>", so we build the filter accordingly
90-
// to resolve the label as <service>-<apiName>
91-
svcs, err := service.GetServicesListWithLabel(
92-
ctx,
93-
helper,
94-
instance.Namespace,
83+
var changed = false
84+
for name, glanceAPI := range instance.Spec.Glance.Template.GlanceAPIs {
85+
if _, ok := instance.Spec.Glance.APIOverride[name]; !ok {
86+
instance.Spec.Glance.APIOverride[name] = corev1beta1.Override{}
87+
}
88+
// Retrieve the services by Label and filter on glanceAPI: for
89+
// each instance we should get **only** the associated `SVCs`
90+
// and not the whole list. As per the Glance design doc we know
91+
// that a given instance name is made in the form: "<service>
92+
// <apiName> <apiType>", so we build the filter accordingly
93+
// to resolve the label as <service>-<apiName>
94+
svcs, err := service.GetServicesListWithLabel(
95+
ctx,
96+
helper,
97+
instance.Namespace,
98+
util.MergeMaps(
99+
GetServiceOpenStackOperatorLabel(glance.Name),
95100
getGlanceAPILabelMap(glance.Name, name, glanceAPI.Type),
96-
)
97-
if err != nil {
98-
return ctrl.Result{}, err
99-
}
101+
),
102+
)
103+
if err != nil {
104+
return ctrl.Result{}, err
105+
}
106+
// make sure to get to EndpointConfig when all service got created
107+
if len(svcs.Items) == len(glanceAPI.Override.Service) {
100108
endpointDetails, ctrlResult, err := EnsureEndpointConfig(
101109
ctx,
102110
instance,
@@ -111,23 +119,22 @@ func ReconcileGlance(ctx context.Context, instance *corev1beta1.OpenStackControl
111119
if err != nil {
112120
return ctrlResult, err
113121
}
122+
// set service overrides
114123
glanceAPI.Override.Service = endpointDetails.GetEndpointServiceOverrides()
115-
116124
// update TLS cert secret
117125
glanceAPI.TLS.API.Public.SecretName = endpointDetails.GetEndptCertSecret(service.EndpointPublic)
118126
glanceAPI.TLS.API.Internal.SecretName = endpointDetails.GetEndptCertSecret(service.EndpointInternal)
119-
instance.Spec.Glance.Template.GlanceAPIs[name] = glanceAPI
120127

121128
// let's keep track of changes for any instance, but return
122129
// only when the iteration on the whole APIList is over
123130
if (ctrlResult != ctrl.Result{}) {
124131
changed = true
125132
}
126133
}
127-
// if one of the API changed, return
128-
if changed {
129-
return ctrl.Result{}, nil
130-
}
134+
instance.Spec.Glance.Template.GlanceAPIs[name] = glanceAPI
135+
}
136+
if changed {
137+
return ctrl.Result{}, nil
131138
}
132139

133140
Log.Info("Reconciling Glance", "Glance.Namespace", instance.Namespace, "Glance.Name", "glance")

0 commit comments

Comments
 (0)