Skip to content

Commit

Permalink
Merge pull request #7030 from andfasano/check-machine-os-image-rhcos-…
Browse files Browse the repository at this point in the history
…version

OCPBUGS-10906: check extracted base iso coreos version is in sync
  • Loading branch information
openshift-ci[bot] authored Oct 23, 2023
2 parents bae6c39 + 41fcac2 commit 604d7fc
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 31 deletions.
89 changes: 59 additions & 30 deletions pkg/asset/agent/image/baseiso.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,42 +51,60 @@ func newGetIso(getter getIsoFile) *getIso {
// GetIsoPluggable defines the method to use get the baseIso file
var GetIsoPluggable = downloadIso

// Download the ISO using the URL in rhcos.json
func getMetalArtifact(archName string) (stream.PlatformArtifacts, error) {
ctx, cancel := context.WithTimeout(context.TODO(), 30*time.Second)
defer cancel()

// Get the ISO to use from rhcos.json
st, err := rhcos.FetchCoreOSBuild(ctx)
if err != nil {
return stream.PlatformArtifacts{}, err
}

streamArch, err := st.GetArchitecture(archName)
if err != nil {
return stream.PlatformArtifacts{}, err
}

metal, ok := streamArch.Artifacts["metal"]
if !ok {
return stream.PlatformArtifacts{}, fmt.Errorf("coreOs stream data not found for 'metal' artifact")
}

return metal, nil
}

// Download the ISO using the URL in rhcos.json.
func downloadIso(archName string) (string, error) {
streamArch, err := getStreamArch(archName)
metal, err := getMetalArtifact(archName)
if err != nil {
return "", err
}
if artifacts, ok := streamArch.Artifacts["metal"]; ok {
if format, ok := artifacts.Formats["iso"]; ok {
url := format.Disk.Location

cachedImage, err := DownloadImageFile(url)
if err != nil {
return "", errors.Wrapf(err, "failed to download base ISO image %s", url)
}
return cachedImage, nil
}
} else {
return "", errors.Wrap(err, "invalid artifact")
format, ok := metal.Formats["iso"]
if !ok {
return "", fmt.Errorf("no ISO found to download for %s", archName)
}

url := format.Disk.Location
cachedImage, err := DownloadImageFile(url)
if err != nil {
return "", errors.Wrapf(err, "failed to download base ISO image %s", url)
}

return "", fmt.Errorf("no ISO found to download for %s", archName)
return cachedImage, nil
}

// Fetch RootFS URL using the rhcos.json.
func (i *BaseIso) getRootFSURL(archName string) (string, error) {
streamArch, err := getStreamArch(archName)
metal, err := getMetalArtifact(archName)
if err != nil {
return "", err
}
if artifacts, ok := streamArch.Artifacts["metal"]; ok {
if format, ok := artifacts.Formats["pxe"]; ok {
rootFSUrl := format.Rootfs.Location
return rootFSUrl, nil
}
} else {
return "", errors.Wrap(err, "invalid artifact")

if format, ok := metal.Formats["pxe"]; ok {
rootFSUrl := format.Rootfs.Location
return rootFSUrl, nil
}

return "", fmt.Errorf("no RootFSURL found for %s", archName)
Expand All @@ -101,18 +119,27 @@ func (i *BaseIso) Dependencies() []asset.Asset {
}
}

func getStreamArch(archName string) (*stream.Arch, error) {
ctx, cancel := context.WithTimeout(context.TODO(), 30*time.Second)
defer cancel()
st, err := rhcos.FetchCoreOSBuild(ctx)
func (i *BaseIso) checkReleasePayloadBaseISOVersion(r Release, archName string) {
logrus.Debugf("Checking release payload base ISO version")

// Get current release payload CoreOS version
payloadRelease, err := r.GetBaseIsoVersion(archName)
if err != nil {
return nil, err
logrus.Warnf("unable to determine base ISO version: %s", err.Error())
return
}
streamArch, err := st.GetArchitecture(archName)

// Get pinned version from installer
metal, err := getMetalArtifact(archName)
if err != nil {
return nil, err
logrus.Warnf("unable to determine base ISO version: %s", err.Error())
return
}

// Check for a mismatch
if metal.Release != payloadRelease {
logrus.Warnf("base ISO version mismatch in release payload. Expected version %s but found %s", metal.Release, payloadRelease)
}
return streamArch, nil
}

// Generate the baseIso
Expand Down Expand Up @@ -170,6 +197,8 @@ func (i *BaseIso) retrieveBaseIso(dependencies asset.Parents) (string, error) {
logrus.Info("Extracting base ISO from release payload")
baseIsoFileName, err = ocRelease.GetBaseIso(archName)
if err == nil {
i.checkReleasePayloadBaseISOVersion(ocRelease, archName)

logrus.Debugf("Extracted base ISO image %s from release payload", baseIsoFileName)
i.File = &asset.File{Filename: baseIsoFileName}
return baseIsoFileName, nil
Expand Down
37 changes: 36 additions & 1 deletion pkg/asset/agent/image/oc.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"crypto/sha256"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"io"
"os"
Expand All @@ -16,6 +15,8 @@ import (
"strings"
"time"

"github.com/coreos/stream-metadata-go/stream"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/thedevsaddam/retry"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand All @@ -30,6 +31,7 @@ const (
machineOsImageName = "machine-os-images"
coreOsFileName = "/coreos/coreos-%s.iso"
coreOsSha256FileName = "/coreos/coreos-%s.iso.sha256"
coreOsStreamFileName = "/coreos/coreos-stream.json"
//OcDefaultTries is the number of times to execute the oc command on failues
OcDefaultTries = 5
// OcDefaultRetryDelay is the time between retries
Expand All @@ -45,6 +47,7 @@ type Config struct {
// Release is the interface to use the oc command to the get image info
type Release interface {
GetBaseIso(architecture string) (string, error)
GetBaseIsoVersion(architecture string) (string, error)
ExtractFile(image string, filename string) ([]string, error)
}

Expand Down Expand Up @@ -131,6 +134,38 @@ func (r *release) GetBaseIso(architecture string) (string, error) {
return path[0], err
}

func (r *release) GetBaseIsoVersion(architecture string) (string, error) {
files, err := r.ExtractFile(machineOsImageName, coreOsStreamFileName)
if err != nil {
return "", err
}

if len(files) > 1 {
return "", fmt.Errorf("too many files found for %s", coreOsStreamFileName)
}

rawData, err := os.ReadFile(files[0])
if err != nil {
return "", err
}

var st stream.Stream
if err := json.Unmarshal(rawData, &st); err != nil {
return "", errors.Wrap(err, "failed to parse CoreOS stream metadata")
}

streamArch, err := st.GetArchitecture(architecture)
if err != nil {
return "", err
}

if metal, ok := streamArch.Artifacts["metal"]; ok {
return metal.Release, nil
}

return "", errors.New("unable to determine CoreOS release version")
}

func (r *release) getImageFromRelease(imageName string) (string, error) {
// This requires the 'oc' command so make sure its available
_, err := exec.LookPath("oc")
Expand Down

0 comments on commit 604d7fc

Please sign in to comment.