Skip to content

Commit d192def

Browse files
committed
operator: add admin_ack handling
1 parent 752a5a2 commit d192def

File tree

4 files changed

+165
-27
lines changed

4 files changed

+165
-27
lines changed

cmd/machine-config-operator/start.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ func runStartCmd(_ *cobra.Command, _ []string) {
9797
ctrlctx.KubeNamespacedInformerFactory.Core().V1().Secrets(),
9898
ctrlctx.OpenShiftConfigKubeNamespacedInformerFactory.Core().V1().Secrets(),
9999
ctrlctx.OpenShiftConfigManagedKubeNamespacedInformerFactory.Core().V1().Secrets(),
100+
ctrlctx.OpenShiftConfigManagedKubeNamespacedInformerFactory.Core().V1().ConfigMaps(),
100101
ctrlctx.ConfigInformerFactory.Config().V1().ClusterOperators(),
101102
ctrlctx.ClientBuilder.OperatorClientOrDie(componentName),
102103
ctrlctx.OperatorInformerFactory.Operator().V1().MachineConfigurations(),

pkg/operator/admin_ack.go

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
package operator
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"reflect"
7+
8+
configv1 "github.com/openshift/api/config/v1"
9+
ctrlcommon "github.com/openshift/machine-config-operator/pkg/controller/common"
10+
11+
corev1 "k8s.io/api/core/v1"
12+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
13+
"k8s.io/apimachinery/pkg/labels"
14+
"k8s.io/apimachinery/pkg/util/sets"
15+
"k8s.io/klog/v2"
16+
)
17+
18+
const (
19+
BootImageAWSGCPKey = "ack-4.18-boot-image-opt-out-in-4.19"
20+
BootImageAWSGCPMsg = "GCP or AWS platform with no boot image configuration detected. OCP will automatically opt-in all GCP and AWS clusters that currently do not a boot image configuration in 4.19. Please add a configuration to disable boot image updates if this is not desired. See [insert-doc-link] "
21+
22+
AArch64BootImageKey = "ack-4.18-aarch64-bootloader-4.19"
23+
AArch64BootImageMsg = "aarch64 nodes detected. Please ensure boot image are updated by following the KCS:(insertlink) prior to upgrading to 4.19."
24+
25+
AdminAckGatesConfigMapName = "admin-gates"
26+
)
27+
28+
// Syncs the admin-ack configmap in the openshift-config-managed namespace, and adds MCO specific keys if needed.
29+
func (optr *Operator) syncAdminAckConfigMap() error {
30+
cm, err := optr.ocManagedConfigMapLister.ConfigMaps(ctrlcommon.OpenshiftConfigManagedNamespace).Get(AdminAckGatesConfigMapName)
31+
if err != nil {
32+
return fmt.Errorf("error fetching configmap %s during sync: %w", AdminAckGatesConfigMapName, err)
33+
}
34+
35+
newCM := cm.DeepCopy()
36+
37+
// Evaluate AWS/GCP boot image guards
38+
_, bootImageAWSGCPKeyExists := newCM.Data[BootImageAWSGCPKey]
39+
bootImageAWSGCPAdminGuardNeeded, err := optr.checkAWSGCPBootImageGuard()
40+
if err != nil {
41+
return fmt.Errorf("error determining aws/gcp boot image guard during configmap %s sync: %w", AdminAckGatesConfigMapName, err)
42+
}
43+
updateGuardKeyIfNeeded(bootImageAWSGCPAdminGuardNeeded, bootImageAWSGCPKeyExists, BootImageAWSGCPKey, BootImageAWSGCPMsg, newCM)
44+
45+
// Evaluate aarch64 guards
46+
_, aarch64BootImageKeyExists := newCM.Data[AArch64BootImageKey]
47+
aarch64BootImageAdminGuardNeeded, err := optr.checkAArch64BootImageGuard()
48+
if err != nil {
49+
return fmt.Errorf("error determining aarch64 boot image guard during configmap %s sync: %w", AdminAckGatesConfigMapName, err)
50+
}
51+
updateGuardKeyIfNeeded(aarch64BootImageAdminGuardNeeded, aarch64BootImageKeyExists, AArch64BootImageKey, AArch64BootImageMsg, newCM)
52+
53+
// Only send an API request if an update is needed
54+
if !reflect.DeepEqual(cm.Data, newCM.Data) {
55+
_, err = optr.kubeClient.CoreV1().ConfigMaps(ctrlcommon.OpenshiftConfigManagedNamespace).Update(context.TODO(), newCM, metav1.UpdateOptions{})
56+
if err != nil {
57+
return fmt.Errorf("error updating configmap %s during sync: %w", AdminAckGatesConfigMapName, err)
58+
}
59+
klog.Infof("%s configmap update successful", newCM.Name)
60+
}
61+
62+
return nil
63+
}
64+
65+
// checkAWSGCPBootImageGuard checks if AWS & GCP Boot Image admin guard is needed
66+
func (optr *Operator) checkAWSGCPBootImageGuard() (bool, error) {
67+
68+
// First, check if the cluster is on AWS or GCP platform.
69+
infra, err := optr.infraLister.Get("cluster")
70+
if err != nil {
71+
klog.Errorf("Could not get infra: %v", err)
72+
return false, err
73+
}
74+
platforms := sets.New(configv1.GCPPlatformType, configv1.AWSPlatformType)
75+
if !platforms.Has(infra.Status.PlatformStatus.Type) {
76+
return false, nil
77+
}
78+
79+
// Next, check if there is any boot image configuration.
80+
mcop, err := optr.mcopLister.Get(ctrlcommon.MCOOperatorKnobsObjectName)
81+
if err != nil {
82+
klog.Errorf("Could not get MachineConfiguration object: %v", err)
83+
return false, err
84+
}
85+
86+
// If no machine managers exist, no configuration has been defined
87+
return mcop.Spec.ManagedBootImages.MachineManagers == nil, nil
88+
}
89+
90+
// checkAArch64BootImageGuard checks if aarch64 Boot Image admin guard is needed
91+
func (optr *Operator) checkAArch64BootImageGuard() (bool, error) {
92+
93+
// Grab all current nodes
94+
nodes, err := optr.nodeLister.List(labels.Everything())
95+
if err != nil {
96+
klog.Errorf("Could not get nodes: %v", err)
97+
return false, err
98+
}
99+
100+
// Check if any node is of the arm64 type (translates to aarch64 in RPM world)
101+
for _, node := range nodes {
102+
if node.Status.NodeInfo.Architecture == "arm64" {
103+
return true, nil
104+
}
105+
}
106+
107+
return false, nil
108+
}
109+
110+
// updateGuardKeyIfNeeded adds a key with a message depending on:
111+
// If guard is needed and key doesn't exist => create it
112+
// If guard is needed and key exists => nothing to do
113+
// If guard is not needed and key exists => delete it
114+
// If guard is not needed and key doesn't exist => nothing to do
115+
func updateGuardKeyIfNeeded(guardNeeded, keyExists bool, key, msg string, cm *corev1.ConfigMap) {
116+
if guardNeeded && !keyExists {
117+
if cm.Data == nil {
118+
cm.Data = map[string]string{}
119+
}
120+
cm.Data[key] = msg
121+
klog.Infof("Adding key %s to configmap %s", key, cm.Name)
122+
} else if !guardNeeded && keyExists {
123+
delete(cm.Data, key)
124+
klog.Infof("Deleting key %s from configmap %s", key, cm.Name)
125+
}
126+
}

pkg/operator/operator.go

Lines changed: 34 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -81,33 +81,34 @@ type Operator struct {
8181

8282
syncHandler func(ic string) error
8383

84-
imgLister configlistersv1.ImageLister
85-
crdLister apiextlistersv1.CustomResourceDefinitionLister
86-
mcpLister mcfglistersv1.MachineConfigPoolLister
87-
msLister mcfglistersalphav1.MachineConfigNodeLister
88-
ccLister mcfglistersv1.ControllerConfigLister
89-
mcLister mcfglistersv1.MachineConfigLister
90-
deployLister appslisterv1.DeploymentLister
91-
daemonsetLister appslisterv1.DaemonSetLister
92-
infraLister configlistersv1.InfrastructureLister
93-
networkLister configlistersv1.NetworkLister
94-
mcoCmLister corelisterv1.ConfigMapLister
95-
clusterCmLister corelisterv1.ConfigMapLister
96-
proxyLister configlistersv1.ProxyLister
97-
oseKubeAPILister corelisterv1.ConfigMapLister
98-
nodeLister corelisterv1.NodeLister
99-
dnsLister configlistersv1.DNSLister
100-
mcoSALister corelisterv1.ServiceAccountLister
101-
mcoSecretLister corelisterv1.SecretLister
102-
ocSecretLister corelisterv1.SecretLister
103-
ocManagedSecretLister corelisterv1.SecretLister
104-
clusterOperatorLister configlistersv1.ClusterOperatorLister
105-
mcopLister mcoplistersv1.MachineConfigurationLister
106-
mckLister mcfglistersv1.KubeletConfigLister
107-
crcLister mcfglistersv1.ContainerRuntimeConfigLister
108-
nodeClusterLister configlistersv1.NodeLister
109-
moscLister mcfglistersalphav1.MachineOSConfigLister
110-
apiserverLister configlistersv1.APIServerLister
84+
imgLister configlistersv1.ImageLister
85+
crdLister apiextlistersv1.CustomResourceDefinitionLister
86+
mcpLister mcfglistersv1.MachineConfigPoolLister
87+
msLister mcfglistersalphav1.MachineConfigNodeLister
88+
ccLister mcfglistersv1.ControllerConfigLister
89+
mcLister mcfglistersv1.MachineConfigLister
90+
deployLister appslisterv1.DeploymentLister
91+
daemonsetLister appslisterv1.DaemonSetLister
92+
infraLister configlistersv1.InfrastructureLister
93+
networkLister configlistersv1.NetworkLister
94+
mcoCmLister corelisterv1.ConfigMapLister
95+
clusterCmLister corelisterv1.ConfigMapLister
96+
proxyLister configlistersv1.ProxyLister
97+
oseKubeAPILister corelisterv1.ConfigMapLister
98+
nodeLister corelisterv1.NodeLister
99+
dnsLister configlistersv1.DNSLister
100+
mcoSALister corelisterv1.ServiceAccountLister
101+
mcoSecretLister corelisterv1.SecretLister
102+
ocSecretLister corelisterv1.SecretLister
103+
ocManagedSecretLister corelisterv1.SecretLister
104+
ocManagedConfigMapLister corelisterv1.ConfigMapLister
105+
clusterOperatorLister configlistersv1.ClusterOperatorLister
106+
mcopLister mcoplistersv1.MachineConfigurationLister
107+
mckLister mcfglistersv1.KubeletConfigLister
108+
crcLister mcfglistersv1.ContainerRuntimeConfigLister
109+
nodeClusterLister configlistersv1.NodeLister
110+
moscLister mcfglistersalphav1.MachineOSConfigLister
111+
apiserverLister configlistersv1.APIServerLister
111112

112113
crdListerSynced cache.InformerSynced
113114
deployListerSynced cache.InformerSynced
@@ -132,6 +133,7 @@ type Operator struct {
132133
mcoSecretListerSynced cache.InformerSynced
133134
ocSecretListerSynced cache.InformerSynced
134135
ocManagedSecretListerSynced cache.InformerSynced
136+
ocManagedConfigMapListerSynced cache.InformerSynced
135137
clusterOperatorListerSynced cache.InformerSynced
136138
mcopListerSynced cache.InformerSynced
137139
mckListerSynced cache.InformerSynced
@@ -182,6 +184,7 @@ func New(
182184
mcoSecretInformer coreinformersv1.SecretInformer,
183185
ocSecretInformer coreinformersv1.SecretInformer,
184186
ocManagedSecretInformer coreinformersv1.SecretInformer,
187+
ocManagedConfigMapInformer coreinformersv1.ConfigMapInformer,
185188
clusterOperatorInformer configinformersv1.ClusterOperatorInformer,
186189
mcopClient mcopclientset.Interface,
187190
mcopInformer mcopinformersv1.MachineConfigurationInformer,
@@ -252,6 +255,7 @@ func New(
252255
mcoSecretInformer.Informer(),
253256
ocSecretInformer.Informer(),
254257
ocManagedSecretInformer.Informer(),
258+
ocManagedConfigMapInformer.Informer(),
255259
mcopInformer.Informer(),
256260
mckInformer.Informer(),
257261
crcInformer.Informer(),
@@ -310,6 +314,8 @@ func New(
310314
optr.ocSecretListerSynced = ocSecretInformer.Informer().HasSynced
311315
optr.ocManagedSecretLister = ocManagedSecretInformer.Lister()
312316
optr.ocManagedSecretListerSynced = ocManagedSecretInformer.Informer().HasSynced
317+
optr.ocManagedConfigMapLister = ocManagedConfigMapInformer.Lister()
318+
optr.ocManagedConfigMapListerSynced = ocManagedConfigMapInformer.Informer().HasSynced
313319
optr.clusterOperatorLister = clusterOperatorInformer.Lister()
314320
optr.clusterOperatorListerSynced = clusterOperatorInformer.Informer().HasSynced
315321
optr.mcopLister = mcopInformer.Lister()
@@ -366,6 +372,7 @@ func (optr *Operator) Run(workers int, stopCh <-chan struct{}) {
366372
optr.mcoSecretListerSynced,
367373
optr.ocSecretListerSynced,
368374
optr.ocManagedSecretListerSynced,
375+
optr.ocManagedConfigMapListerSynced,
369376
optr.clusterOperatorListerSynced,
370377
optr.mcopListerSynced,
371378
optr.mckListerSynced,

pkg/operator/sync.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,10 @@ func (optr *Operator) syncAll(syncFuncs []syncFunc) error {
235235
return fmt.Errorf("error syncing metrics: %w", err)
236236
}
237237

238+
if err := optr.syncAdminAckConfigMap(); err != nil {
239+
return fmt.Errorf("error syncing admin ack configmap: %w", err)
240+
}
241+
238242
if optr.inClusterBringup && syncErr.err == nil {
239243
klog.Infof("Initialization complete")
240244
optr.inClusterBringup = false

0 commit comments

Comments
 (0)