Skip to content

Commit 81339f7

Browse files
committed
add global pull secret clone mechanism
1 parent 056db85 commit 81339f7

File tree

5 files changed

+83
-11
lines changed

5 files changed

+83
-11
lines changed

pkg/controller/build/buildrequest/buildrequest.go

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -486,11 +486,6 @@ func (br buildRequestImpl) toBuildahPod() *corev1.Pod {
486486
volumes = append(volumes, opts.volumeForSecret(constants.EtcPkiRpmGpgSecretName))
487487
}
488488

489-
// TODO: We need pull creds with permissions to pull the base image. By
490-
// default, none of the MCO pull secrets can directly pull it. We can use the
491-
// pull-secret creds from openshift-config to do that, though we'll need to
492-
// mirror those creds into the MCO namespace. The operator portion of the MCO
493-
// has some logic to detect whenever that secret changes.
494489
return &corev1.Pod{
495490
TypeMeta: metav1.TypeMeta{
496491
APIVersion: "v1",

pkg/controller/build/buildrequest/buildrequestopts.go

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ type BuildRequestOpts struct { //nolint:revive // This name is fine.
3030
BaseImagePullSecret *corev1.Secret
3131
FinalImagePushSecret *corev1.Secret
3232

33+
// Has user defined base image pull secret
34+
hasUserDefinedBaseImagePullSecret bool
3335
// Has /etc/pki/entitlement
3436
HasEtcPkiEntitlementKeys bool
3537
// Has /etc/yum.repos.d configs
@@ -108,10 +110,6 @@ func (o *optsGetter) validateMachineOSConfig(mosc *mcfgv1.MachineOSConfig) error
108110
return fmt.Errorf("expected MachineOSConfig not to be nil")
109111
}
110112

111-
if mosc.Spec.BaseImagePullSecret.Name == "" {
112-
return fmt.Errorf("baseImagePullSecret empty for MachineOSConfig %s", mosc.Name)
113-
}
114-
115113
if mosc.Spec.RenderedImagePushSecret.Name == "" {
116114
return fmt.Errorf("renderedImagePushSecret empty for MachineOSConfig %s", mosc.Name)
117115
}
@@ -165,7 +163,18 @@ func (o *optsGetter) getOpts(ctx context.Context, mosb *mcfgv1.MachineOSBuild, m
165163
return nil, fmt.Errorf("could not get osImageURL config: %w", err)
166164
}
167165

168-
baseImagePullSecret, err := o.getValidatedSecret(ctx, mosc.Spec.BaseImagePullSecret.Name)
166+
var baseImagePullSecretName string
167+
// Check if a base image pull secret was provided
168+
opts.hasUserDefinedBaseImagePullSecret = mosc.Spec.BaseImagePullSecret != nil
169+
if opts.hasUserDefinedBaseImagePullSecret {
170+
baseImagePullSecretName = mosc.Spec.BaseImagePullSecret.Name
171+
} else {
172+
// If not provided, fall back to the global pull secret copy in the MCO namespace
173+
klog.Infof("BaseImagePullSecret not defined for MachineOSConfig %s, falling back to global pull secret", mosc.Name)
174+
baseImagePullSecretName = ctrlcommon.GlobalPullSecretCopyName
175+
}
176+
177+
baseImagePullSecret, err := o.getValidatedSecret(ctx, baseImagePullSecretName)
169178
if err != nil {
170179
return nil, fmt.Errorf("could not get base image pull secret %s: %w", mosc.Spec.BaseImagePullSecret.Name, err)
171180
}

pkg/controller/build/helpers.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,12 @@ func validateMachineOSConfig(mcpGetter func(string) (*mcfgv1.MachineConfigPool,
7171
}
7272

7373
secretFields := map[string]string{
74-
mosc.Spec.BaseImagePullSecret.Name: "baseImagePullSecret",
7574
mosc.Spec.RenderedImagePushSecret.Name: "renderedImagePushSecret",
7675
}
76+
// Add base image pull secret if it has been defined in the MOSC
77+
if mosc.Spec.BaseImagePullSecret != nil {
78+
secretFields[mosc.Spec.BaseImagePullSecret.Name] = "baseImagePullSecret"
79+
}
7780

7881
for secretName, fieldName := range secretFields {
7982
if err := validateSecret(secretGetter, mosc, secretName); err != nil {

pkg/controller/common/constants.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,15 @@ const (
1212
// MachineAPINamespace is the namespace that should be used for all API objects owned by the machine api operator
1313
MachineAPINamespace = "openshift-machine-api"
1414

15+
// GlobalPullSecretName is the name of the global pull secret
16+
GlobalPullSecretName = "pull-secret"
17+
18+
// OpenshiftConfigNamespace is the namespace that has the global pull secret
19+
OpenshiftConfigNamespace = "openshift-config"
20+
21+
// GlobalPullCopySecret is a copy of the cluster wide pull secret. In OCL, this is used if the base image pull secret is not provided.
22+
GlobalPullSecretCopyName = "global-pull-secret-copy"
23+
1524
// GeneratedByControllerVersionAnnotationKey is used to tag the machineconfigs generated by the controller with the version of the controller.
1625
GeneratedByControllerVersionAnnotationKey = "machineconfiguration.openshift.io/generated-by-controller-version"
1726

pkg/operator/sync.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1251,6 +1251,11 @@ func (optr *Operator) reconcileMachineOSBuilder(mob *appsv1.Deployment) error {
12511251
return fmt.Errorf("could not reconcile etc-pki-entitlement secrets: %w", err)
12521252
}
12531253

1254+
// Create/Deletes the global pull secret copy in the MCO namespace, depending on layered pool count.
1255+
if err := optr.reconcileGlobalPullSecretCopy(layeredMCPs); err != nil {
1256+
return fmt.Errorf("could not reconcile global pull secret copy: %w", err)
1257+
}
1258+
12541259
// If we have opted-in pools and the Machine OS Builder deployment is either
12551260
// not running or doesn't have the correct replica count, scale it up.
12561261
correctReplicaCount := optr.hasCorrectReplicaCount(mob)
@@ -1457,6 +1462,57 @@ func (optr *Operator) reconcileSimpleContentAccessSecrets(layeredMCPs []*mcfgv1.
14571462
return nil
14581463
}
14591464

1465+
func (optr *Operator) reconcileGlobalPullSecretCopy(layeredMCPs []*mcfgv1.MachineConfigPool) error {
1466+
secretCopyExists := true
1467+
currentSecretCopy, err := optr.mcoSecretLister.Secrets(ctrlcommon.MCONamespace).Get(ctrlcommon.GlobalPullSecretCopyName)
1468+
if apierrors.IsNotFound(err) {
1469+
secretCopyExists = false
1470+
} else if err != nil {
1471+
return err
1472+
}
1473+
1474+
if len(layeredMCPs) == 0 {
1475+
// If the secret copy doesn't exist, nothing to do here
1476+
if !secretCopyExists {
1477+
return nil
1478+
}
1479+
klog.Infof("deleting %s", ctrlcommon.GlobalPullSecretCopyName)
1480+
return optr.kubeClient.CoreV1().Secrets(ctrlcommon.MCONamespace).Delete(context.TODO(), ctrlcommon.GlobalPullSecretCopyName, metav1.DeleteOptions{})
1481+
}
1482+
1483+
// Atleast one pool is opted-in, let's create or update the copy if needed. First, grab the global pull secret.
1484+
globalPullSecret, err := optr.ocSecretLister.Secrets(ctrlcommon.OpenshiftConfigNamespace).Get("pull-secret")
1485+
if err != nil {
1486+
return fmt.Errorf("error fetching cluster pull secret: %w", err)
1487+
}
1488+
1489+
// Create a clone of clusterPullSecret, and modify it to be in the MCO namespace.
1490+
globalPullSecretCopy := &corev1.Secret{
1491+
ObjectMeta: metav1.ObjectMeta{
1492+
Name: ctrlcommon.GlobalPullSecretCopyName,
1493+
Namespace: ctrlcommon.MCONamespace,
1494+
},
1495+
Data: globalPullSecret.Data,
1496+
Type: corev1.SecretTypeDockerConfigJson,
1497+
}
1498+
1499+
// If the secret copy doesn't exist, create it.
1500+
if !secretCopyExists {
1501+
klog.Infof("creating %s", ctrlcommon.GlobalPullSecretCopyName)
1502+
_, err := optr.kubeClient.CoreV1().Secrets(ctrlcommon.MCONamespace).Create(context.TODO(), globalPullSecretCopy, metav1.CreateOptions{})
1503+
return err
1504+
}
1505+
1506+
// If it does exist, check if an update is required before making the update call.
1507+
if !reflect.DeepEqual(currentSecretCopy.Data, globalPullSecret.Data) {
1508+
klog.Infof("updating %s", ctrlcommon.GlobalPullSecretCopyName)
1509+
_, err := optr.kubeClient.CoreV1().Secrets(ctrlcommon.MCONamespace).Update(context.TODO(), globalPullSecretCopy, metav1.UpdateOptions{})
1510+
return err
1511+
}
1512+
1513+
return nil
1514+
}
1515+
14601516
// Updates the Machine OS Builder Deployment, creating it if it does not exist.
14611517
func (optr *Operator) startMachineOSBuilderDeployment(mob *appsv1.Deployment, layeredMCPs []*mcfgv1.MachineConfigPool) error {
14621518
if err := build.ValidateOnClusterBuildConfig(optr.kubeClient, optr.client, layeredMCPs); err != nil {

0 commit comments

Comments
 (0)