Skip to content

Commit

Permalink
Worker: move GCE image guest OS features to upload target options
Browse files Browse the repository at this point in the history
Previously, the worker was determining the GCE image guest OS Features
on its own, based on the OS name. This caused problems, in case the
osbuild-composer was of a newer version than the worker.

Example:
osbuild-composer contained support for c10s GCE image type and its
implementation also contained the proper guest OS Features list for it.
However, when the worker got the osbuild job, it built it and tried to
fetch the guest OS Features for the distro. Since its implementation was
too old, it didn't contain the code that added the actual support for
c10s GCE images and got no guest OS features list (which is the default
for unsupported distros). The image was successfully uploaded and
shared, but it does not boot in GCP, because it does not know that it
should use UEFI to boot it.

This behavior could be considered a bug. The worker should be dumb. It
should not be making decisions about the image features, but instead it
should take them from the upload target options. And composer should be
the authoritative source of truth for this. Because otherwise, we
basically have two components that need to be updated in sync to add
support for GCE images on a new distro.

Move the GCE image guest OS features to the GCP upload target options.
The worker will just take what is specified there and use it when
importing the image to GCP. As a compatibility layer for the case when
the composer would be older than the worker (unlikely, but still),
worker will try to determine the image guest OS features in case the
list in the upload target options is empty.

Extend the GCP functional tests to check that the imported image has at
least some guest OS features set.

Signed-off-by: Tomáš Hozza <[email protected]>
  • Loading branch information
thozza committed Aug 29, 2024
1 parent 2442bae commit d7e59e6
Show file tree
Hide file tree
Showing 6 changed files with 41 additions and 7 deletions.
10 changes: 9 additions & 1 deletion cmd/osbuild-worker/jobimpl-osbuild.go
Original file line number Diff line number Diff line change
Expand Up @@ -807,9 +807,17 @@ func (impl *OSBuildJobImpl) Run(job worker.Job) error {
break
}

guestOSFeatures := targetOptions.GuestOsFeatures
// TODO: Remove this after "some time"
// This is just a backward compatibility for the old composer versions,
// which did not set the guest OS features in the target options.
if len(guestOSFeatures) == 0 {
guestOSFeatures = gcp.GuestOsFeaturesByDistro(targetOptions.Os)
}

logWithId.Infof("[GCP] 📥 Importing image into Compute Engine as '%s'", jobTarget.ImageName)

_, importErr := g.ComputeImageInsert(ctx, bucket, targetOptions.Object, jobTarget.ImageName, []string{targetOptions.Region}, gcp.GuestOsFeaturesByDistro(targetOptions.Os))
_, importErr := g.ComputeImageInsert(ctx, bucket, targetOptions.Object, jobTarget.ImageName, []string{targetOptions.Region}, guestOSFeatures)
if importErr == nil {
logWithId.Infof("[GCP] 🎉 Image import finished successfully")
}
Expand Down
5 changes: 4 additions & 1 deletion internal/cloudapi/v2/imagerequest.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/osbuild/images/pkg/distro"
"github.com/osbuild/images/pkg/ostree"
"github.com/osbuild/osbuild-composer/internal/blueprint"
"github.com/osbuild/osbuild-composer/internal/cloud/gcp"
"github.com/osbuild/osbuild-composer/internal/common"
"github.com/osbuild/osbuild-composer/internal/target"
)
Expand Down Expand Up @@ -153,13 +154,15 @@ func newGCPTarget(options UploadOptions, imageType distro.ImageType) (*target.Ta
if gcpUploadOptions.Bucket != nil {
bucket = *gcpUploadOptions.Bucket
}
osName := imageType.Arch().Distro().Name()
t := target.NewGCPTarget(&target.GCPTargetOptions{
Region: gcpUploadOptions.Region,
Os: imageType.Arch().Distro().Name(), // not exposed in cloudapi
Os: osName, // not exposed in cloudapi
Bucket: bucket,
// the uploaded object must have a valid extension
Object: fmt.Sprintf("%s.tar.gz", imageName),
ShareWithAccounts: share,
GuestOsFeatures: gcp.GuestOsFeaturesByDistro(osName), // not exposed in cloudapi
})
// Import will fail if an image with this name already exists
if gcpUploadOptions.ImageName != nil {
Expand Down
5 changes: 5 additions & 0 deletions internal/target/gcp_target.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package target

import "cloud.google.com/go/compute/apiv1/computepb"

const TargetNameGCP TargetName = "org.osbuild.gcp"

type GCPTargetOptions struct {
Expand All @@ -13,6 +15,9 @@ type GCPTargetOptions struct {
// to GCP. If not provided, the worker will try to authenticate using the
// credentials from worker's configuration.
Credentials []byte `json:"credentials,omitempty"`

// The list of Guest OS Features to specify for the image being imported.
GuestOsFeatures []*computepb.GuestOsFeature `json:"guestOsFeatures,omitempty"`
}

func (GCPTargetOptions) isTargetOptions() {}
Expand Down
14 changes: 9 additions & 5 deletions internal/weldr/upload.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (

ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types"
"github.com/osbuild/images/pkg/distro"
"github.com/osbuild/osbuild-composer/internal/cloud/gcp"
"github.com/osbuild/osbuild-composer/internal/common"
"github.com/sirupsen/logrus"

Expand Down Expand Up @@ -346,12 +347,15 @@ func uploadRequestToTarget(u uploadRequest, imageType distro.ImageType) *target.
logrus.Infof("[GCP] object name must end with '.tar.gz', using %q as the object name", objectName)
}

osName := imageType.Arch().Distro().Name()

t.Options = &target.GCPTargetOptions{
Region: options.Region,
Os: imageType.Arch().Distro().Name(),
Bucket: options.Bucket,
Object: objectName,
Credentials: gcpCredentials,
Region: options.Region,
Os: osName,
Bucket: options.Bucket,
Object: objectName,
Credentials: gcpCredentials,
GuestOsFeatures: gcp.GuestOsFeaturesByDistro(osName),
}
case *vmwareUploadSettings:
t.Name = target.TargetNameVMWare
Expand Down
7 changes: 7 additions & 0 deletions test/cases/api/gcp.sh
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,13 @@ function verify() {
exit 1
fi

# Verify that the image has guestOsFeatures set
GCP_IMAGE_GUEST_OS_FEATURES_LEN=$($GCP_CMD compute images describe --project="$GCP_PROJECT" --format="json" "$GCP_IMAGE_NAME" | jq -r '.guestOsFeatures | length')
if [ "$GCP_IMAGE_GUEST_OS_FEATURES_LEN" -eq 0 ]; then
echo "❌ Image does not have guestOsFeatures set"
exit 1
fi

# Verify that the image boots and have customizations applied
# Create SSH keys to use
GCP_SSH_KEY="$WORKDIR/id_google_compute_engine"
Expand Down
7 changes: 7 additions & 0 deletions test/cases/gcp.sh
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,13 @@ function verifyInGCP() {
# Add "gitlab-ci-test" label to the image
$GCP_CMD compute images add-labels "$GCP_IMAGE_NAME" --labels=gitlab-ci-test=true

# Verify that the image has guestOsFeatures set
GCP_IMAGE_GUEST_OS_FEATURES_LEN=$($GCP_CMD compute images describe --project="$GCP_PROJECT" --format="json" "$GCP_IMAGE_NAME" | jq -r '.guestOsFeatures | length')
if [ "$GCP_IMAGE_GUEST_OS_FEATURES_LEN" -eq 0 ]; then
echo "❌ Image does not have guestOsFeatures set"
exit 1
fi

# Verify that the image boots and have customizations applied
# Create SSH keys to use
GCP_SSH_KEY="$TEMPDIR/id_google_compute_engine"
Expand Down

0 comments on commit d7e59e6

Please sign in to comment.