Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DNM] MCO-1437: MCO-1476: MCO-1477: MCO-1284: Adapt MCO to OCL v1 API #4756

Draft
wants to merge 7 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions pkg/controller/build/buildrequest/buildrequest.go
Original file line number Diff line number Diff line change
Expand Up @@ -486,11 +486,6 @@ func (br buildRequestImpl) toBuildahPod() *corev1.Pod {
volumes = append(volumes, opts.volumeForSecret(constants.EtcPkiRpmGpgSecretName))
}

// TODO: We need pull creds with permissions to pull the base image. By
// default, none of the MCO pull secrets can directly pull it. We can use the
// pull-secret creds from openshift-config to do that, though we'll need to
// mirror those creds into the MCO namespace. The operator portion of the MCO
// has some logic to detect whenever that secret changes.
return &corev1.Pod{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Expand Down
19 changes: 14 additions & 5 deletions pkg/controller/build/buildrequest/buildrequestopts.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ type BuildRequestOpts struct { //nolint:revive // This name is fine.
BaseImagePullSecret *corev1.Secret
FinalImagePushSecret *corev1.Secret

// Has user defined base image pull secret
HasUserDefinedBaseImagePullSecret bool
// Has /etc/pki/entitlement
HasEtcPkiEntitlementKeys bool
// Has /etc/yum.repos.d configs
Expand Down Expand Up @@ -108,10 +110,6 @@ func (o *optsGetter) validateMachineOSConfig(mosc *mcfgv1.MachineOSConfig) error
return fmt.Errorf("expected MachineOSConfig not to be nil")
}

if mosc.Spec.BaseImagePullSecret.Name == "" {
return fmt.Errorf("baseImagePullSecret empty for MachineOSConfig %s", mosc.Name)
}

if mosc.Spec.RenderedImagePushSecret.Name == "" {
return fmt.Errorf("renderedImagePushSecret empty for MachineOSConfig %s", mosc.Name)
}
Expand Down Expand Up @@ -165,7 +163,18 @@ func (o *optsGetter) getOpts(ctx context.Context, mosb *mcfgv1.MachineOSBuild, m
return nil, fmt.Errorf("could not get osImageURL config: %w", err)
}

baseImagePullSecret, err := o.getValidatedSecret(ctx, mosc.Spec.BaseImagePullSecret.Name)
var baseImagePullSecretName string
// Check if a base image pull secret was provided
opts.HasUserDefinedBaseImagePullSecret = mosc.Spec.BaseImagePullSecret != nil && mosc.Spec.BaseImagePullSecret.Name != ""
if opts.HasUserDefinedBaseImagePullSecret {
baseImagePullSecretName = mosc.Spec.BaseImagePullSecret.Name
} else {
// If not provided, fall back to the global pull secret copy in the MCO namespace
klog.Infof("BaseImagePullSecret not defined for MachineOConfig %s, falling back to global pull secret", mosc.Name)
baseImagePullSecretName = ctrlcommon.GlobalPullSecretCopyName
}

baseImagePullSecret, err := o.getValidatedSecret(ctx, baseImagePullSecretName)
if err != nil {
return nil, fmt.Errorf("could not get base image pull secret %s: %w", mosc.Spec.BaseImagePullSecret.Name, err)
}
Expand Down
1 change: 0 additions & 1 deletion pkg/controller/build/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ func validateMachineOSConfig(mcpGetter func(string) (*mcfgv1.MachineConfigPool,
}

secretFields := map[string]string{
mosc.Spec.BaseImagePullSecret.Name: "baseImagePullSecret",
mosc.Spec.RenderedImagePushSecret.Name: "renderedImagePushSecret",
}

Expand Down
9 changes: 9 additions & 0 deletions pkg/controller/common/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,15 @@ const (
// SimpleContentAccessSecret is the secret that holds the SimpleContentAccess cert which provides RHEL entitlements
SimpleContentAccessSecretName = "etc-pki-entitlement"

// GlobalPullSecretName is the name of the global pull secret
GlobalPullSecretName = "pull-secret"

// OpenshiftConfigNamespace is the namespace that has the global pull secret
OpenshiftConfigNamespace = "openshift-config"

// GlobalPullCopySecret is a copy of the cluster wide pull secret. In OCL, this is used if the base image pull secret is not provided.
GlobalPullSecretCopyName = "global-pull-secret-copy"

// GeneratedByControllerVersionAnnotationKey is used to tag the machineconfigs generated by the controller with the version of the controller.
GeneratedByControllerVersionAnnotationKey = "machineconfiguration.openshift.io/generated-by-controller-version"

Expand Down
57 changes: 57 additions & 0 deletions pkg/operator/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -1257,6 +1257,11 @@ func (optr *Operator) reconcileMachineOSBuilder(mob *appsv1.Deployment) error {
return fmt.Errorf("could not reconcile etc-pki-entitlement secrets: %w", err)
}

// Create/Deletes the global pull secret copy in the MCO namespace, depending on layered pool count.
if err := optr.reconcileGlobalPullSecretCopy(layeredMCPs); err != nil {
return fmt.Errorf("could not reconcile global pull secret copy: %w", err)
}

// If we have opted-in pools and the Machine OS Builder deployment is either
// not running or doesn't have the correct replica count, scale it up.
correctReplicaCount := optr.hasCorrectReplicaCount(mob)
Expand Down Expand Up @@ -1463,6 +1468,58 @@ func (optr *Operator) reconcileSimpleContentAccessSecrets(layeredMCPs []*mcfgv1.
return nil
}

func (optr *Operator) reconcileGlobalPullSecretCopy(layeredMCPs []*mcfgv1.MachineConfigPool) error {
secretCopyExists := true
currentSecretCopy, err := optr.mcoSecretLister.Secrets(ctrlcommon.MCONamespace).Get(ctrlcommon.GlobalPullSecretCopyName)
if apierrors.IsNotFound(err) {
secretCopyExists = false
} else if err != nil {
return err
}

if len(layeredMCPs) == 0 {
// If the secret copy doesn't exist, nothing to do here
if !secretCopyExists {
return nil
}
klog.Infof("deleting %s", ctrlcommon.GlobalPullSecretCopyName)
return optr.kubeClient.CoreV1().Secrets(ctrlcommon.MCONamespace).Delete(context.TODO(), ctrlcommon.GlobalPullSecretCopyName, metav1.DeleteOptions{})
}

// Atleast one pool is opted-in, let's create or update the copy if needed. First, grab the global pull secret.
// QOCL: Do we want to fatally exit here?
globalPullSecret, err := optr.ocSecretLister.Secrets(ctrlcommon.OpenshiftConfigNamespace).Get("pull-secret")
if err != nil {
return fmt.Errorf("error fetching cluster pull secret: %w", err)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to fatally exit here? If this secret is missing in cluster, the build will certainly fail, I'd think.

}

// Create a clone of clusterPullSecret, and modify it to be in the MCO namespace.
globalPullSecretCopy := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: ctrlcommon.GlobalPullSecretCopyName,
Namespace: ctrlcommon.MCONamespace,
},
Data: globalPullSecret.Data,
Type: corev1.SecretTypeDockerConfigJson,
}

// If the secret copy doesn't exist, create it.
if !secretCopyExists {
klog.Infof("creating %s", ctrlcommon.GlobalPullSecretCopyName)
_, err := optr.kubeClient.CoreV1().Secrets(ctrlcommon.MCONamespace).Create(context.TODO(), globalPullSecretCopy, metav1.CreateOptions{})
return err
}

// If it does exist, check if an update is required before making the update call.
if !reflect.DeepEqual(currentSecretCopy.Data, globalPullSecret.Data) {
klog.Infof("updating %s", ctrlcommon.GlobalPullSecretCopyName)
_, err := optr.kubeClient.CoreV1().Secrets(ctrlcommon.MCONamespace).Update(context.TODO(), globalPullSecretCopy, metav1.UpdateOptions{})
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if this update mechanism is necessary, I don't know if the global secret will ever get updated after installation?

return err
}

return nil
}

// Updates the Machine OS Builder Deployment, creating it if it does not exist.
func (optr *Operator) startMachineOSBuilderDeployment(mob *appsv1.Deployment, layeredMCPs []*mcfgv1.MachineConfigPool) error {
if err := build.ValidateOnClusterBuildConfig(optr.kubeClient, optr.client, layeredMCPs); err != nil {
Expand Down