-
Notifications
You must be signed in to change notification settings - Fork 414
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
MCO-1100: enable RHEL entitlements in on-cluster layering #4312
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -52,6 +52,17 @@ import ( | |
"github.com/openshift/machine-config-operator/internal/clients" | ||
) | ||
|
||
const ( | ||
// Name of the etc-pki-entitlement secret from the openshift-config-managed namespace. | ||
etcPkiEntitlementSecretName = "etc-pki-entitlement" | ||
|
||
// Name of the etc-pki-rpm-gpg secret. | ||
etcPkiRpmGpgSecretName = "etc-pki-rpm-gpg" | ||
|
||
// Name of the etc-yum-repos-d ConfigMap. | ||
etcYumReposDConfigMapName = "etc-yum-repos-d" | ||
) | ||
|
||
const ( | ||
targetMachineConfigPoolLabel = "machineconfiguration.openshift.io/targetMachineConfigPool" | ||
// TODO(zzlotnik): Is there a constant for this someplace else? | ||
|
@@ -472,6 +483,20 @@ func (ctrl *Controller) customBuildPodUpdater(pod *corev1.Pod) error { | |
|
||
ps := newPoolState(pool) | ||
|
||
// We cannot solely rely upon the pod phase to determine whether the build | ||
// pod is in an error state. This is because it is possible for the build | ||
// container to enter an error state while the wait-for-done container is | ||
// still running. The pod phase in this state will still be "Running" as | ||
// opposed to error. | ||
if isBuildPodError(pod) { | ||
if err := ctrl.markBuildFailed(ps); err != nil { | ||
return err | ||
} | ||
|
||
ctrl.enqueueMachineConfigPool(pool) | ||
return nil | ||
} | ||
|
||
switch pod.Status.Phase { | ||
case corev1.PodPending: | ||
if !ps.IsBuildPending() { | ||
|
@@ -503,6 +528,22 @@ func (ctrl *Controller) customBuildPodUpdater(pod *corev1.Pod) error { | |
return nil | ||
} | ||
|
||
// Determines if the build pod is in an error state by examining the individual | ||
// container statuses. Returns true if a single container is in an error state. | ||
func isBuildPodError(pod *corev1.Pod) bool { | ||
for _, container := range pod.Status.ContainerStatuses { | ||
if container.State.Waiting != nil && container.State.Waiting.Reason == "ErrImagePull" { | ||
return true | ||
} | ||
|
||
if container.State.Terminated != nil && container.State.Terminated.ExitCode != 0 { | ||
return true | ||
} | ||
} | ||
|
||
return false | ||
} | ||
|
||
func (ctrl *Controller) handleConfigMapError(pools []*mcfgv1.MachineConfigPool, err error, key interface{}) { | ||
klog.V(2).Infof("Error syncing configmap %v: %v", key, err) | ||
utilruntime.HandleError(err) | ||
|
@@ -950,17 +991,69 @@ func (ctrl *Controller) getBuildInputs(ps *poolState) (*buildInputs, error) { | |
return nil, fmt.Errorf("could not get MachineConfig %s: %w", currentMC, err) | ||
} | ||
|
||
etcPkiEntitlements, err := ctrl.getOptionalSecret(etcPkiEntitlementSecretName) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
etcPkiRpmGpgKeys, err := ctrl.getOptionalSecret(etcPkiRpmGpgSecretName) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
etcYumReposDConfigs, err := ctrl.getOptionalConfigMap(etcYumReposDConfigMapName) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
inputs := &buildInputs{ | ||
onClusterBuildConfig: onClusterBuildConfig, | ||
osImageURL: osImageURL, | ||
customDockerfiles: customDockerfiles, | ||
pool: ps.MachineConfigPool(), | ||
machineConfig: mc, | ||
onClusterBuildConfig: onClusterBuildConfig, | ||
osImageURL: osImageURL, | ||
customDockerfiles: customDockerfiles, | ||
pool: ps.MachineConfigPool(), | ||
machineConfig: mc, | ||
etcPkiEntitlementKeys: etcPkiEntitlements, | ||
etcYumReposDConfigs: etcYumReposDConfigs, | ||
etcPkiRpmGpgKeys: etcPkiRpmGpgKeys, | ||
} | ||
|
||
return inputs, nil | ||
} | ||
|
||
// Fetches an optional secret to inject into the build. Returns a nil error if | ||
// the secret is not found. | ||
func (ctrl *Controller) getOptionalSecret(secretName string) (*corev1.Secret, error) { | ||
optionalSecret, err := ctrl.kubeclient.CoreV1().Secrets(ctrlcommon.MCONamespace).Get(context.TODO(), secretName, metav1.GetOptions{}) | ||
if err == nil { | ||
klog.Infof("Optional build secret %q found, will include in build", secretName) | ||
return optionalSecret, nil | ||
} | ||
|
||
if k8serrors.IsNotFound(err) { | ||
klog.Infof("Could not find optional secret %q, will not include in build", secretName) | ||
return nil, nil | ||
} | ||
|
||
return nil, fmt.Errorf("could not retrieve optional secret: %s: %w", secretName, err) | ||
} | ||
|
||
// Fetches an optional ConfigMap to inject into the build. Returns a nil error if | ||
// the ConfigMap is not found. | ||
func (ctrl *Controller) getOptionalConfigMap(configmapName string) (*corev1.ConfigMap, error) { | ||
optionalConfigMap, err := ctrl.kubeclient.CoreV1().ConfigMaps(ctrlcommon.MCONamespace).Get(context.TODO(), configmapName, metav1.GetOptions{}) | ||
if err == nil { | ||
klog.Infof("Optional build ConfigMap %q found, will include in build", configmapName) | ||
return optionalConfigMap, nil | ||
} | ||
|
||
if k8serrors.IsNotFound(err) { | ||
klog.Infof("Could not find ConfigMap %q, will not include in build", configmapName) | ||
return nil, nil | ||
} | ||
|
||
return nil, fmt.Errorf("could not retrieve optional ConfigMap: %s: %w", configmapName, err) | ||
} | ||
Comment on lines
1022
to
+1055
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. another non mandatory suggestion. these can be combined into a "getOptionalResource" and just pass in a resource type, do something like, then combine the rest
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a good idea for the future, especially since both of these helpers only really concern themselves about the existence of the resource. That would blend nicely with some future refactoring ideas that I have. |
||
|
||
// Prepares all of the objects needed to perform an image build. | ||
func (ctrl *Controller) prepareForBuild(inputs *buildInputs) (ImageBuildRequest, error) { | ||
ibr := newImageBuildRequestFromBuildInputs(inputs) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For modularity, you could make a function that encapsulates this, only if you wanted to. This isnt really a mandatory, as your code looks good! just a suggestion:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried to do that, but I couldn't get it to work quite the way that I wanted it to. Admittedly, my Bash is a little rusty. But I did think of two interesting paths forward for the future: