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

Seed image format version OCI image label #188

Merged
merged 1 commit into from
Jan 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
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
55 changes: 55 additions & 0 deletions controllers/prep_handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package controllers

import (
"context"
"encoding/json"
"errors"
"fmt"
"os"
Expand Down Expand Up @@ -68,8 +69,62 @@ func (r *ImageBasedUpgradeReconciler) getSeedImage(
return fmt.Errorf("failed to pull image: %w", err)
}

r.Log.Info("Checking seed image compatibility")
if err := r.checkSeedImageCompatibility(ctx, ibu.Spec.SeedImageRef.Image); err != nil {
return fmt.Errorf("checking seed image compatibility: %w", err)
}

return nil
}

// checkSeedImageCompatibility checks if the seed image is compatible with the
// current version of the lifecycle-agent by inspecting the OCI image's labels
// and checking if the specified format version equals the hard-coded one that
// this version of the lifecycle agent expects. That format version is set by
// the imager during the image build process, and is only manually bumped by
// developers when the image format changes in a way that is incompatible with
// previous versions of the lifecycle-agent.
func (r *ImageBasedUpgradeReconciler) checkSeedImageCompatibility(_ context.Context, seedImageRef string) error {
inspectArgs := []string{
"inspect",
"--format", "json",
seedImageRef,
}

var inspect []struct {
Labels map[string]string `json:"Labels"`
}

// TODO: use the context when execute supports it
if inspectRaw, err := r.Executor.Execute("podman", inspectArgs...); err != nil || inspectRaw == "" {
omertuc marked this conversation as resolved.
Show resolved Hide resolved
return fmt.Errorf("failed to inspect image: %w", err)
} else {
omertuc marked this conversation as resolved.
Show resolved Hide resolved
if err := json.Unmarshal([]byte(inspectRaw), &inspect); err != nil {
return fmt.Errorf("failed to unmarshal image inspect output: %w", err)
}
}

if len(inspect) != 1 {
return fmt.Errorf("expected 1 image inspect result, got %d", len(inspect))
}

seedFormatLabelValue, ok := inspect[0].Labels[common.SeedFormatOCILabel]
if !ok {
return fmt.Errorf(
"seed image %s is missing the %s label, please build a new image using the latest version of the imager",
seedImageRef, common.SeedFormatOCILabel)
}

// Hard equal since we don't have backwards compatibility guarantees yet.
// In the future we might want to have backwards compatibility code to
// handle older seed formats and in that case we'll look at the version
// number and do the right thing.
omertuc marked this conversation as resolved.
Show resolved Hide resolved
if seedFormatLabelValue != fmt.Sprintf("%d", common.SeedFormatVersion) {
return fmt.Errorf("seed image format version mismatch: expected %d, got %s",
common.SeedFormatVersion, seedFormatLabelValue)
}

return nil
}

func readPrecachingList(imageListFile, clusterRegistry, seedRegistry string, overrideSeedRegistry bool) (imageList []string, err error) {
Expand Down
9 changes: 8 additions & 1 deletion ibu-imager/seedcreator/seedcreator.go
Original file line number Diff line number Diff line change
Expand Up @@ -414,8 +414,15 @@ func (s *SeedCreator) createAndPushSeedImage() error {
_ = tmpfile.Close() // Close the temporary file

// Build the single OCI image (note: We could include --squash-all option, as well)
podmanBuildArgs := []string{
"build",
"--file", tmpfile.Name(),
"--tag", s.containerRegistry,
"--label", fmt.Sprintf("%s=%d", common.SeedFormatOCILabel, common.SeedFormatVersion),
s.backupDir,
}
_, err = s.ops.RunInHostNamespace(
"podman", []string{"build", "-f", tmpfile.Name(), "-t", s.containerRegistry, s.backupDir}...)
"podman", podmanBuildArgs...)
if err != nil {
return fmt.Errorf("failed to build seed image: %w", err)
}
Expand Down
4 changes: 4 additions & 0 deletions internal/common/consts.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ const (
InstallConfigCM = "cluster-config-v1"
// InstallConfigCMNamespace cm namespace
InstallConfigCMNamespace = "kube-system"

// Bump this every time the seed format changes in a backwards incompatible way
SeedFormatVersion = 1
SeedFormatOCILabel = "com.openshift.lifecycle-agent.seed_format_version"
)

// CertPrefixes is the list of certificate prefixes to be backed up
Expand Down