From 7056f53f2950a821a93afabd1ef055bc0471f76b Mon Sep 17 00:00:00 2001 From: Hongkai Liu Date: Mon, 23 Jun 2025 10:15:20 -0400 Subject: [PATCH] NO-JIRA: Include the target version in the logging Before this full, the logging was only for the case that `findClusterIncludeConfigFromInstallConfig` is called, i.e., the path from an install-config file is provided. This pull extends it to the case where the configuration is taken from the current cluster. Another change from the pull is that the logging messages include the target version that is determined by inspecting the release image. The implementation for this is adding a new callback `ImageConfigCallback`. --- pkg/cli/admin/release/extract.go | 26 ++++++++++++++++++-- pkg/cli/admin/release/extract_tools.go | 33 +++++++++++++++++++------- pkg/cli/image/extract/extract.go | 5 ++++ 3 files changed, 53 insertions(+), 11 deletions(-) diff --git a/pkg/cli/admin/release/extract.go b/pkg/cli/admin/release/extract.go index a3c0a471cc..c117282df8 100644 --- a/pkg/cli/admin/release/extract.go +++ b/pkg/cli/admin/release/extract.go @@ -349,6 +349,28 @@ func (o *ExtractOptions) Run(ctx context.Context) error { } } + // versionInImageConfig stores the version from the label of the image + // At the moment it is used later only for the logging purpose and thus is not blocking if failures occur upon getting its value + var versionInImageConfig string + opts.ImageConfigCallback = func(imageConfig *dockerv1client.DockerImageConfig) { + if imageConfig == nil { + // This should never happen + klog.Error("Cannot retrieve the version because no image configuration is provided in the image to extract") + return + } + if imageConfig.Config == nil { + klog.Error("Cannot retrieve the version from image configuration in the image to extract because it has no configuration") + return + } + v, ok := imageConfig.Config.Labels["io.openshift.release"] + if !ok { + klog.Error("Cannot retrieve the version from image configuration in the image to extract because it does not have the required label 'io.openshift.release'") + return + } + klog.V(2).Infof("Retrieved the version from image configuration in the image to extract: %s", v) + versionInImageConfig = v + } + var manifestErrs []error // o.ExtractManifests implies o.File == "" if o.ExtractManifests { @@ -359,9 +381,9 @@ func (o *ExtractOptions) Run(ctx context.Context) error { context := "connected cluster" inclusionConfig := manifestInclusionConfiguration{} if o.InstallConfig == "" { - inclusionConfig, err = findClusterIncludeConfig(ctx, o.RESTConfig) + inclusionConfig, err = findClusterIncludeConfig(ctx, o.RESTConfig, versionInImageConfig) } else { - inclusionConfig, err = findClusterIncludeConfigFromInstallConfig(ctx, o.InstallConfig) + inclusionConfig, err = findClusterIncludeConfigFromInstallConfig(ctx, o.InstallConfig, versionInImageConfig) context = o.InstallConfig } if err != nil { diff --git a/pkg/cli/admin/release/extract_tools.go b/pkg/cli/admin/release/extract_tools.go index a1d12aa966..4451fd6994 100644 --- a/pkg/cli/admin/release/extract_tools.go +++ b/pkg/cli/admin/release/extract_tools.go @@ -1167,16 +1167,29 @@ func copyAndReplace(errorOutput io.Writer, w io.Writer, r io.Reader, bufferSize } -func findClusterIncludeConfigFromInstallConfig(ctx context.Context, installConfigPath string) (manifestInclusionConfiguration, error) { - config := manifestInclusionConfiguration{} - +// logCapabilitySetMayDiffer logs the messages if the oc-cli version is not the same as the target version +// * the enabled capability set may differ if the baseline is vCurrent, and +// * the known capability set may differ +// It raises an error if it fails to determine the oc-cli version. +func logCapabilitySetMayDiffer(capabilitiesSpec *configv1.ClusterVersionCapabilitiesSpec, targetVersion string) error { clientVersion, reportedVersion, err := version.ExtractVersion() if err != nil { - return config, err + return fmt.Errorf("failed to determine the version of 'oc': %w", err) } if reportedVersion == "" { reportedVersion = clientVersion.String() } + if reportedVersion != targetVersion { + if capabilitiesSpec != nil && capabilitiesSpec.BaselineCapabilitySet == configv1.ClusterVersionCapabilitySetCurrent { + klog.Infof("The eventual cluster %s will not be the same minor version as this %s 'oc', the actual %s capability set may differ.", targetVersion, reportedVersion, capabilitiesSpec.BaselineCapabilitySet) + } + klog.Infof("The eventual cluster %s will not be the same minor version as this %s 'oc', the known capability set may differ.", targetVersion, reportedVersion) + } + return nil +} + +func findClusterIncludeConfigFromInstallConfig(ctx context.Context, installConfigPath string, versionInImageConfig string) (manifestInclusionConfiguration, error) { + config := manifestInclusionConfiguration{} installConfigBytes, err := os.ReadFile(installConfigPath) if err != nil { @@ -1204,21 +1217,19 @@ func findClusterIncludeConfigFromInstallConfig(ctx context.Context, installConfi if enabled, ok := configv1.ClusterVersionCapabilitySets[data.Capabilities.BaselineCapabilitySet]; !ok { return config, fmt.Errorf("unrecognized baselineCapabilitySet %q", data.Capabilities.BaselineCapabilitySet) } else { - if data.Capabilities.BaselineCapabilitySet == configv1.ClusterVersionCapabilitySetCurrent { - klog.Infof("If the eventual cluster will not be the same minor version as this %s 'oc', the actual %s capability set may differ.", reportedVersion, data.Capabilities.BaselineCapabilitySet) + if err := logCapabilitySetMayDiffer(data.Capabilities, versionInImageConfig); err != nil { + return config, err } config.Capabilities.EnabledCapabilities = append(config.Capabilities.EnabledCapabilities, enabled...) } config.Capabilities.EnabledCapabilities = append(config.Capabilities.EnabledCapabilities, data.Capabilities.AdditionalEnabledCapabilities...) - - klog.Infof("If the eventual cluster will not be the same minor version as this %s 'oc', the known capability sets may differ.", reportedVersion) config.Capabilities.KnownCapabilities = configv1.KnownClusterVersionCapabilities } return config, nil } -func findClusterIncludeConfig(ctx context.Context, restConfig *rest.Config) (manifestInclusionConfiguration, error) { +func findClusterIncludeConfig(ctx context.Context, restConfig *rest.Config, versionInImageConfig string) (manifestInclusionConfiguration, error) { config := manifestInclusionConfiguration{} client, err := configv1client.NewForConfig(restConfig) @@ -1250,6 +1261,10 @@ func findClusterIncludeConfig(ctx context.Context, restConfig *rest.Config) (man config.Capabilities.EnabledCapabilities = append(config.Capabilities.EnabledCapabilities, configv1.ClusterVersionCapabilityMachineAPI, build, deploymentConfig, imageRegistry) config.Capabilities.KnownCapabilities = append(config.Capabilities.KnownCapabilities, configv1.ClusterVersionCapabilityMachineAPI, build, deploymentConfig, imageRegistry) } + + if err := logCapabilitySetMayDiffer(clusterVersion.Spec.Capabilities, versionInImageConfig); err != nil { + return config, err + } } if infrastructure, err := client.Infrastructures().Get(ctx, "cluster", metav1.GetOptions{}); err != nil { diff --git a/pkg/cli/image/extract/extract.go b/pkg/cli/image/extract/extract.go index ae4ac5042d..b1e9d3c745 100644 --- a/pkg/cli/image/extract/extract.go +++ b/pkg/cli/image/extract/extract.go @@ -141,6 +141,8 @@ type ExtractOptions struct { genericiooptions.IOStreams + // ImageConfigCallback is invoked once image config retrieved + ImageConfigCallback func(imageConfig *dockerv1client.DockerImageConfig) // ImageMetadataCallback is invoked once per image retrieved, and may be called in parallel if // MaxPerRegistry is set higher than 1. ImageMetadataCallback ImageMetadataFunc @@ -421,6 +423,9 @@ func (o *ExtractOptions) Run() error { if err != nil { return fmt.Errorf("unable to parse image %s: %v", from, err) } + if o.ImageConfigCallback != nil { + o.ImageConfigCallback(imageConfig) + } if mapping.ConditionFn != nil { ok, err := mapping.ConditionFn(&mapping, location.Manifest, imageConfig)