diff --git a/controllers/prep_handlers.go b/controllers/prep_handlers.go index 572269b00..e40aec7f2 100644 --- a/controllers/prep_handlers.go +++ b/controllers/prep_handlers.go @@ -26,6 +26,7 @@ import ( "strings" "time" + "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/wait" "golang.org/x/sync/errgroup" @@ -153,6 +154,29 @@ func readPrecachingList(imageListFile, clusterRegistry, seedRegistry string, ove return imageList, nil } +func (r *ImageBasedUpgradeReconciler) getPodEnvVars(ctx context.Context) (envVars []corev1.EnvVar, err error) { + pod := &corev1.Pod{} + if err = r.Client.Get(ctx, types.NamespacedName{Name: os.Getenv("MY_POD_NAME"), Namespace: common.LcaNamespace}, pod); err != nil { + err = fmt.Errorf("failed to get pod info: %w", err) + return + } + + for _, container := range pod.Spec.Containers { + if container.Name == "manager" { + for _, envVar := range container.Env { + if envVar.ValueFrom != nil { + // Skipping any valueFrom env variables + continue + } + envVars = append(envVars, envVar) + } + break + } + } + + return +} + func (r *ImageBasedUpgradeReconciler) launchPrecaching(ctx context.Context, imageListFile string, ibu *lcav1alpha1.ImageBasedUpgrade) (bool, error) { clusterRegistry, err := commonUtils.GetReleaseRegistry(ctx, r.Client) if err != nil { @@ -176,8 +200,14 @@ func (r *ImageBasedUpgradeReconciler) launchPrecaching(ctx context.Context, imag return false, err } + envVars, err := r.getPodEnvVars(ctx) + if err != nil { + err = fmt.Errorf("failed to get pod env vars: %w", err) + return false, err + } + // Create pre-cache config using default values - config := precache.NewConfig(imageList) + config := precache.NewConfig(imageList, envVars) err = r.Precache.CreateJob(ctx, config) if err != nil { r.Log.Error(err, "Failed to create precaching job") diff --git a/docs/precache-plugin.md b/docs/precache-plugin.md index f70fc985d..da629fd53 100644 --- a/docs/precache-plugin.md +++ b/docs/precache-plugin.md @@ -37,6 +37,7 @@ The `Config` struct defines the configuration options for a pre-caching job. The - `NicePriority`: Nice priority for pre-caching, affecting process scheduling. - `IoNiceClass`: I/O scheduling class for pre-caching (0: none, 1: realtime, 2: best-effort, 3: idle). - `IoNicePriority`: I/O nice priority for pre-caching. +- `EnvVars`: A list of container spec environment variables to be set in the job definition. ### 2. ConfigMap Generation diff --git a/internal/precache/helper.go b/internal/precache/helper.go index dd16e266e..04228ed58 100644 --- a/internal/precache/helper.go +++ b/internal/precache/helper.go @@ -156,7 +156,7 @@ func renderJob(config *Config, log logr.Logger) (*batchv1.Job, error) { execPrecacheArgs := fmt.Sprintf("nice -n %d ionice -c %d -n %d precache", nicePriority, ioNiceClass, ioNicePriority) - envVars := []corev1.EnvVar{ + precacheEnvVars := append(config.EnvVars, []corev1.EnvVar{ { Name: EnvPrecacheSpecFile, Value: filepath.Join(PrecachingSpecFilepath, PrecachingSpecFilename), @@ -165,15 +165,7 @@ func renderJob(config *Config, log logr.Logger) (*batchv1.Job, error) { Name: EnvMaxPullThreads, Value: strconv.Itoa(numConcurrentPulls), }, - } - - envBestEffort := os.Getenv(EnvPrecacheBestEffort) - if envBestEffort == "TRUE" { - envVars = append(envVars, corev1.EnvVar{ - Name: EnvPrecacheBestEffort, - Value: "TRUE", - }) - } + }...) job := &batchv1.Job{ ObjectMeta: metav1.ObjectMeta{ @@ -194,7 +186,7 @@ func renderJob(config *Config, log logr.Logger) (*batchv1.Job, error) { ImagePullPolicy: corev1.PullAlways, Command: []string{"sh", "-c", "--"}, Args: []string{execPrecacheArgs}, - Env: envVars, + Env: precacheEnvVars, SecurityContext: &corev1.SecurityContext{ Privileged: &privileged, RunAsUser: &runAsUser, diff --git a/internal/precache/helper_test.go b/internal/precache/helper_test.go index 1cd5e5b15..4f3b643f5 100644 --- a/internal/precache/helper_test.go +++ b/internal/precache/helper_test.go @@ -270,7 +270,7 @@ func TestRenderJob(t *testing.T) { }{ { name: "Fully specified, valid precaching config", - config: NewConfig([]string{}, "NumConcurrentPulls", 1, "NicePriority", 1, "IoNiceClass", IoNiceClassRealTime, "IoNicePriority", 5), + config: NewConfig([]string{}, []corev1.EnvVar{}, "NumConcurrentPulls", 1, "NicePriority", 1, "IoNiceClass", IoNiceClassRealTime, "IoNicePriority", 5), expectedError: nil, expectedArgs: []string{fmt.Sprintf("nice -n 1 ionice -c %d -n 5 precache", IoNiceClassRealTime)}, expectedEnvVars: []corev1.EnvVar{ @@ -282,7 +282,7 @@ func TestRenderJob(t *testing.T) { }, { name: "Partially specified, with some invalid precaching config", - config: NewConfig([]string{}, "NumConcurrentPulls", 10, "NicePriority", 100, "IoNiceClass", IoNiceClassRealTime), + config: NewConfig([]string{}, []corev1.EnvVar{}, "NumConcurrentPulls", 10, "NicePriority", 100, "IoNiceClass", IoNiceClassRealTime), expectedError: nil, expectedArgs: []string{fmt.Sprintf("nice -n %d ionice -c %d -n %d precache", DefaultNicePriority, IoNiceClassRealTime, DefaultIoNicePriority)}, @@ -295,7 +295,7 @@ func TestRenderJob(t *testing.T) { }, { name: "Only image list provided in precaching config", - config: NewConfig([]string{}), + config: NewConfig([]string{}, []corev1.EnvVar{}), expectedError: nil, expectedArgs: []string{fmt.Sprintf("nice -n %d ionice -c %d -n %d precache", DefaultNicePriority, DefaultIoNiceClass, DefaultIoNicePriority)}, diff --git a/internal/precache/precache.go b/internal/precache/precache.go index 13b77faf1..8a4556302 100644 --- a/internal/precache/precache.go +++ b/internal/precache/precache.go @@ -29,6 +29,8 @@ import ( "github.com/openshift-kni/lifecycle-agent/internal/common" "sigs.k8s.io/controller-runtime/pkg/client" + + corev1 "k8s.io/api/core/v1" ) // +kubebuilder:rbac:groups="",resources=configmaps,verbs=get;list;watch;create;update;delete @@ -44,12 +46,17 @@ type PHandler struct { type Config struct { ImageList []string NumConcurrentPulls int + // To run pre-caching job with an adjusted niceness, which affects process scheduling. // Niceness values range from -20 (most favorable to the process) to 19 (least favorable to the process). NicePriority int + // To configure the I/O-scheduling class and priority of a process. IoNiceClass int // 0: none, 1: realtime, 2: best-effort, 3: idle IoNicePriority int // priority (0..7) in the specified scheduling class, only for the realtime and best-effort classes + + // Allow for environment variables to be passed in + EnvVars []corev1.EnvVar } // NewConfig creates a new Config instance with the provided imageList and optional configuration parameters. @@ -63,13 +70,14 @@ type Config struct { // Example usage: // // config := NewConfig(imageList, "NumConcurrentPulls", 10, "NicePriority", 5) -func NewConfig(imageList []string, args ...interface{}) *Config { +func NewConfig(imageList []string, envVars []corev1.EnvVar, args ...interface{}) *Config { instance := &Config{ ImageList: imageList, NumConcurrentPulls: DefaultMaxConcurrentPulls, NicePriority: DefaultNicePriority, IoNiceClass: DefaultIoNiceClass, IoNicePriority: DefaultIoNicePriority, + EnvVars: envVars, } for i := 0; i < len(args); i += 2 {