diff --git a/cmd/osbuild-worker/jobimpl-osbuild.go b/cmd/osbuild-worker/jobimpl-osbuild.go index 35da651d47..ce89a18f71 100644 --- a/cmd/osbuild-worker/jobimpl-osbuild.go +++ b/cmd/osbuild-worker/jobimpl-osbuild.go @@ -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") } diff --git a/internal/cloudapi/v2/imagerequest.go b/internal/cloudapi/v2/imagerequest.go index 664e93cca3..e666ff3ae6 100644 --- a/internal/cloudapi/v2/imagerequest.go +++ b/internal/cloudapi/v2/imagerequest.go @@ -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" ) @@ -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 { diff --git a/internal/target/gcp_target.go b/internal/target/gcp_target.go index 5d43e7030a..9034c6caef 100644 --- a/internal/target/gcp_target.go +++ b/internal/target/gcp_target.go @@ -1,5 +1,7 @@ package target +import "cloud.google.com/go/compute/apiv1/computepb" + const TargetNameGCP TargetName = "org.osbuild.gcp" type GCPTargetOptions struct { @@ -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() {} diff --git a/internal/weldr/upload.go b/internal/weldr/upload.go index 461f83c4a5..c67116a8d8 100644 --- a/internal/weldr/upload.go +++ b/internal/weldr/upload.go @@ -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" @@ -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 diff --git a/test/cases/api/gcp.sh b/test/cases/api/gcp.sh index a57297345d..b928ce1102 100644 --- a/test/cases/api/gcp.sh +++ b/test/cases/api/gcp.sh @@ -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" diff --git a/test/cases/gcp.sh b/test/cases/gcp.sh index 56bd460fcf..3182848e67 100755 --- a/test/cases/gcp.sh +++ b/test/cases/gcp.sh @@ -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"