Repository: osbuild/osbuild-composer
Pull request #2479 (2022-03-24 08:17:26)

cloudapi: improve gpgkey handling & enable edge-commit on Fedora
We have to do a small hack to enable edge-commit on Fedora because its name
is different. We can also change this in the image definition but I want to
iterate quickly on the Fedora Integration MVP and don't want to run in
any conflicts with
https://github.com/osbuild/osbuild-composer/pull/2461

This commit also enables a test for Fedora IoT built through the API.

Signed-off-by: Ondřej Budai <ondrej@budai.cz>


This pull request includes:

- [ ] adequate testing for the new functionality or fixed issue
- [ ] adequate documentation informing people about the change such as
  - [ ] submit a PR for the [guides](https://github.com/osbuild/guides) repository if this PR changed any behavior described there: https://www.osbuild.org/guides/

<!--
Thanks for proposing a change to osbuild-composer!

Please don't remove the above check list. These are things that each pull
request must have before it is merged. It helps maintainers to not forget
anything.

If the reason for ticking any of the boxes is ambiguous, please add a short
note explaining why.

In addition, if this pull request fixes a downstream issue, please refer to
test/README.md and add these additional items:

- [ ] 1st commit of any `rhbz#` related PR contains bug reproducer; CI reports FAIL or
- [ ] PR contains automated tests for new functionality and
- [ ] QE has approved reproducer/new tests and
- [ ] Subsequent commits provide bug fixes without modifying the reproducer; CI reports PASS and
- [ ] QE approves this PR; RHBZ status is set to `MODIFIED + Verified=Tested`

Information regarding our GitLab pipeline (Schutzbot):

CI will not be ran automatically if WIP label is applied or the PR is in DRAFT state, instead only
a link will be provided to the pipeline which can then be triggered manually if desired. To run the
CI automatically either switch the PR to ready or apply WIP+test label.

Outside contributors need manual approval from one of the osbuild-composer maintainers.

Schutzbot will only be triggered if all Tests jobs in GitHub workflow succeed.
-->


teg: I would love to just call it edge commit in our API long term, but I guess that's up to @nullr0ute . For now this is definitely fine though.
ondrejbudai: Agreed, more unification between Fedora and RHEL is always nice.

(Force-pushed a fix for missing Fedora bits in the test.)
nullr0ute: > I would love to just call it edge commit in our API long term, but I guess that's up to @nullr0ute . For now this is definitely fine though.

Happy to consider options, probably needs more context and OOB discussion though.

Patch looks fine to me
ondrejbudai: Oh my, so we were actually passing gpg keys in the wrong field in our tests so that's why this PR was failing: cloudapi uses a field named `gpg_key` whereas all our other APIs (and DNF repo files) use `gpgkey`.

I decided to change that in cloudapi: both `gpgkey` and `gpg_key` can now be used. `gpg_key` is marked as deprecated but kept for backward compatibility. Also, we now enforce that if `check_gpg` is present, a GPG key must be specified. This would have caught this issue.
ondrejbudai: So we in the end decided to change the API instead of introducing cumbersome hacks. This is a breaking change but since no one is using the API, it does little to no harm.

Patch:
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index acb0b1647..7b076fa89 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -392,6 +392,9 @@ API:
           - aws/rhel-8.6-nightly-x86_64
           - aws/rhel-9.0-nightly-x86_64
         INTERNAL_NETWORK: ["true"]
+      - IMAGE_TYPE: ["edge-commit"]
+        RUNNER:
+          - aws/fedora-35-x86_64
 
 libvirt:
   stage: test
diff --git a/internal/cloudapi/v2/errors.go b/internal/cloudapi/v2/errors.go
index 238b84728..3a0285811 100644
--- a/internal/cloudapi/v2/errors.go
+++ b/internal/cloudapi/v2/errors.go
@@ -42,6 +42,7 @@ const (
 	ErrorInvalidJobType               ServiceErrorCode = 26
 	ErrorInvalidOSTreeParams          ServiceErrorCode = 27
 	ErrorTenantNotFound               ServiceErrorCode = 28
+	ErrorNoGPGKey                     ServiceErrorCode = 29
 
 	// Internal errors, these are bugs
 	ErrorFailedToInitializeBlueprint              ServiceErrorCode = 1000
@@ -107,6 +108,7 @@ func getServiceErrors() serviceErrors {
 		serviceError{ErrorInvalidNumberOfImageBuilds, http.StatusBadRequest, "Compose request has unsupported number of image builds"},
 		serviceError{ErrorInvalidOSTreeParams, http.StatusBadRequest, "Invalid OSTree parameters or parameter combination"},
 		serviceError{ErrorTenantNotFound, http.StatusBadRequest, "Tenant not found in JWT claims"},
+		serviceError{ErrorNoGPGKey, http.StatusBadRequest, "Invalid repository, when check_gpg is set, gpgkey must be specified"},
 
 		serviceError{ErrorFailedToInitializeBlueprint, http.StatusInternalServerError, "Failed to initialize blueprint"},
 		serviceError{ErrorFailedToGenerateManifestSeed, http.StatusInternalServerError, "Failed to generate manifest seed"},
diff --git a/internal/cloudapi/v2/openapi.v2.gen.go b/internal/cloudapi/v2/openapi.v2.gen.go
index 124e7df1e..550aa6542 100644
--- a/internal/cloudapi/v2/openapi.v2.gen.go
+++ b/internal/cloudapi/v2/openapi.v2.gen.go
@@ -371,9 +371,11 @@ type PackageMetadata struct {
 
 // Repository defines model for Repository.
 type Repository struct {
-	Baseurl    *string `json:"baseurl,omitempty"`
-	CheckGpg   *bool   `json:"check_gpg,omitempty"`
-	GpgKey     *string `json:"gpg_key,omitempty"`
+	Baseurl  *string `json:"baseurl,omitempty"`
+	CheckGpg *bool   `json:"check_gpg,omitempty"`
+
+	// GPG key used to sign packages in this repository.
+	Gpgkey     *string `json:"gpgkey,omitempty"`
 	IgnoreSsl  *bool   `json:"ignore_ssl,omitempty"`
 	Metalink   *string `json:"metalink,omitempty"`
 	Mirrorlist *string `json:"mirrorlist,omitempty"`
@@ -650,80 +652,105 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL
 // Base64 encoded, gzipped, json marshaled Swagger object
 var swaggerSpec = []string{
 
-	"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",
-	"D7LRSqTlE6SKzTY6Nw//FwAA///Ls+uMj1AAAA==",
+	"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",
 }
 
 // GetSwagger returns the content of the embedded swagger specification file
diff --git a/internal/cloudapi/v2/openapi.v2.yml b/internal/cloudapi/v2/openapi.v2.yml
index 3efd3705f..e4f286a18 100644
--- a/internal/cloudapi/v2/openapi.v2.yml
+++ b/internal/cloudapi/v2/openapi.v2.yml
@@ -669,8 +669,10 @@ components:
           type: string
           format: url
           example: 'https://mirrors.fedoraproject.org/metalink?repo=fedora-32&arch=x86_64'
-        gpg_key:
+        gpgkey:
           type: string
+          example: "-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nmQINBGAcScoBEADLf8YHkezJ6adlMYw7aGGIlJalt8Jj2x/B2K+hIfIuxGtpVj7e\nLRgDU76jaT5pVD5mFMJ3pkeneR/cTmqqQkNyQshX2oQXwEzUSb1CNMCfCGgkX8Q2\nzZkrIcCrF0Q2wrKblaudhU+iVanADsm18YEqsb5AU37dtUrM3QYdWg9R+XiPfV8R\nKBjT03vVBOdMSsY39LaCn6Ip1Ovp8IEo/IeEVY1qmCOPAaK0bJH3ufg4Cueks+TS\nwQWTeCLxuZL6OMXoOPKwvMQfxbg1XD8vuZ0Ktj/cNH2xau0xmsAu9HJpekvOPRxl\nyqtjyZfroVieFypwZgvQwtnnM8/gSEu/JVTrY052mEUT7Ccb74kcHFTFfMklnkG/\n0fU4ARa504H3xj0ktbe3vKcPXoPOuKBVsHSv00UGYAyPeuy+87cU/YEhM7k3SVKj\n6eIZgyiMO0wl1YGDRKculwks9A+ulkg1oTb4s3zmZvP07GoTxW42jaK5WS+NhZee\n860XoVhbc1KpS+jfZojsrEtZ8PbUZ+YvF8RprdWArjHbJk2JpRKAxThxsQAsBhG1\n0Lux2WaMB0g2I5PcMdJ/cqjo08ccrjBXuixWri5iu9MXp8qT/fSzNmsdIgn8/qZK\ni8Qulfu77uqhW/wt2btnitgRsqjhxMujYU4Zb4hktF8hKU/XX742qhL5KwARAQAB\ntDFGZWRvcmEgKDM1KSA8ZmVkb3JhLTM1LXByaW1hcnlAZmVkb3JhcHJvamVjdC5v\ncmc+iQJOBBMBCAA4FiEEeH6mrhFH7uVsQLMM20Y5cZhnxY8FAmAcScoCGw8FCwkI\nBwIGFQoJCAsCBBYCAwECHgECF4AACgkQ20Y5cZhnxY+NYA/7BYpglySAZYHhjyKh\n/+f6zPfVvbH20Eq3kI7OFBN0nLX+BU1muvS+qTuS3WLrB3m3GultpKREJKLtm5ED\n1rGzXAoT1yp9YI8LADdMCCOyjAjsoWU87YUuC+/bnjrTeR2LROCfyPC76W985iOV\nm5S+bsQDw7C2LrldAM4MDuoyZ1SitGaZ4KQLVt+TEa14isYSGCjzo7PY8V3JOk50\ngqWg82N/bm2EzS7T83WEDb1lvj4IlvxgIqKeg11zXYxmrYSZJJCfvzf+lNS6uxgH\njx/J0ylZ2LibGr6GAAyO9UWrAZSwSM0EcjT8wECnxkSDuyqmWwVvNBXuEIV8Oe3Y\nMiU1fJN8sd7DpsFx5M+XdnMnQS+HrjTPKD3mWrlAdnEThdYV8jZkpWhDys3/99eO\nhk0rLny0jNwkauf/iU8Oc6XvMkjLRMJg5U9VKyJuWWtzwXnjMN5WRFBqK4sZomMM\nftbTH1+5ybRW/A3vBbaxRW2t7UzNjczekSZEiaLN9L/HcJCIR1QF8682DdAlEF9d\nk2gQiYSQAaaJ0JJAzHvRkRJLLgK2YQYiHNVy2t3JyFfsram5wSCWOfhPeIyLBTZJ\nvrpNlPbefsT957Tf2BNIugzZrC5VxDSKkZgRh1VGvSIQnCyzkQy6EU2qPpiW59G/\nhPIXZrKocK3KLS9/izJQTRltjMA=\n=PfT7\n-----END PGP PUBLIC KEY BLOCK-----\n"
+          description: 'GPG key used to sign packages in this repository.'
         check_gpg:
           type: boolean
         ignore_ssl:
diff --git a/internal/cloudapi/v2/v2.go b/internal/cloudapi/v2/v2.go
index b09dd921f..70ab6da5a 100644
--- a/internal/cloudapi/v2/v2.go
+++ b/internal/cloudapi/v2/v2.go
@@ -279,7 +279,7 @@ func (h *apiHandlers) PostCompose(ctx echo.Context) error {
 		if err != nil {
 			return HTTPError(ErrorUnsupportedArchitecture)
 		}
-		imageType, err := arch.GetImageType(imageTypeFromApiImageType(ir.ImageType))
+		imageType, err := arch.GetImageType(imageTypeFromApiImageType(ir.ImageType, arch))
 		if err != nil {
 			return HTTPError(ErrorUnsupportedImageType)
 		}
@@ -715,7 +715,7 @@ func generateManifest(ctx context.Context, cancel context.CancelFunc, workers *w
 	jobResult.Manifest = manifest
 }
 
-func imageTypeFromApiImageType(it ImageTypes) string {
+func imageTypeFromApiImageType(it ImageTypes, arch distro.Arch) string {
 	switch it {
 	case ImageTypesAws:
 		return "ami"
@@ -738,6 +738,13 @@ func imageTypeFromApiImageType(it ImageTypes) string {
 	case ImageTypesImageInstaller:
 		return "image-installer"
 	case ImageTypesEdgeCommit:
+		// Fedora doesn't define "rhel-edge-commit", or "edge-commit" yet.
+		// Assume that if the distro contains "fedora-iot-commit", it's Fedora
+		// and translate ImageTypesEdgeCommit to fedora-iot-commit in this case.
+		// This should definitely be removed in the near future.
+		if _, err := arch.GetImageType("fedora-iot-commit"); err == nil {
+			return "fedora-iot-commit"
+		}
 		return "rhel-edge-commit"
 	case ImageTypesEdgeContainer:
 		return "rhel-edge-container"
@@ -1258,12 +1265,16 @@ func genRepoConfig(repo Repository) (*rpmmd.RepoConfig, error) {
 	if repo.CheckGpg != nil {
 		repoConfig.CheckGPG = *repo.CheckGpg
 	}
-	if repo.GpgKey != nil {
-		repoConfig.GPGKey = *repo.GpgKey
+	if repo.Gpgkey != nil {
+		repoConfig.GPGKey = *repo.Gpgkey
 	}
 	if repo.IgnoreSsl != nil {
 		repoConfig.IgnoreSSL = *repo.IgnoreSsl
 	}
 
+	if repoConfig.CheckGPG && repoConfig.GPGKey == "" {
+		return nil, HTTPError(ErrorNoGPGKey)
+	}
+
 	return repoConfig, nil
 }


Test patch:
diff --git a/internal/cloudapi/v2/v2_internal_test.go b/internal/cloudapi/v2/v2_internal_test.go
index 1debeb848..ea8731c2c 100644
--- a/internal/cloudapi/v2/v2_internal_test.go
+++ b/internal/cloudapi/v2/v2_internal_test.go
@@ -3,10 +3,11 @@ package v2
 import (
 	"testing"
 
-	"github.com/osbuild/osbuild-composer/internal/common"
-	"github.com/osbuild/osbuild-composer/internal/rpmmd"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
+
+	"github.com/osbuild/osbuild-composer/internal/common"
+	"github.com/osbuild/osbuild-composer/internal/rpmmd"
 )
 
 func TestSplitExtension(t *testing.T) {
@@ -129,7 +130,7 @@ func TestRepoConfigConversion(t *testing.T) {
 			repo: Repository{
 				Baseurl:     common.StringToPtr("http://base.url"),
 				CheckGpg:    common.BoolToPtr(true),
-				GpgKey:      common.StringToPtr("some-kind-of-key"),
+				Gpgkey:      common.StringToPtr("some-kind-of-key"),
 				IgnoreSsl:   common.BoolToPtr(false),
 				Metalink:    nil,
 				Mirrorlist:  nil,
@@ -153,7 +154,7 @@ func TestRepoConfigConversion(t *testing.T) {
 			repo: Repository{
 				Baseurl:     common.StringToPtr("http://base.url"),
 				CheckGpg:    nil,
-				GpgKey:      nil,
+				Gpgkey:      nil,
 				IgnoreSsl:   common.BoolToPtr(true),
 				Metalink:    common.StringToPtr("http://example.org/metalink"),
 				Mirrorlist:  common.StringToPtr("http://example.org/mirrorlist"),
@@ -177,7 +178,7 @@ func TestRepoConfigConversion(t *testing.T) {
 			repo: Repository{
 				Baseurl:     nil,
 				CheckGpg:    nil,
-				GpgKey:      nil,
+				Gpgkey:      nil,
 				IgnoreSsl:   common.BoolToPtr(true),
 				Metalink:    common.StringToPtr("http://example.org/metalink"),
 				Mirrorlist:  common.StringToPtr("http://example.org/mirrorlist"),
@@ -201,7 +202,7 @@ func TestRepoConfigConversion(t *testing.T) {
 			repo: Repository{
 				Baseurl:     nil,
 				CheckGpg:    nil,
-				GpgKey:      nil,
+				Gpgkey:      nil,
 				IgnoreSsl:   common.BoolToPtr(true),
 				Metalink:    common.StringToPtr("http://example.org/metalink"),
 				Mirrorlist:  nil,
@@ -229,17 +230,44 @@ func TestRepoConfigConversion(t *testing.T) {
 		assert.Equal(rc, &tc.repoConfig, "mismatch in test case %d", idx)
 	}
 
-	// test error
-	noURL := Repository{
-		Baseurl:     nil,
-		CheckGpg:    nil,
-		GpgKey:      nil,
-		IgnoreSsl:   nil,
-		Metalink:    nil,
-		Mirrorlist:  nil,
-		Rhsm:        true,
-		PackageSets: nil,
+	errorTestCases := []struct {
+		repo Repository
+		err  string
+	}{
+		// invalid repo
+		{
+			repo: Repository{
+				Baseurl:     nil,
+				CheckGpg:    nil,
+				Gpgkey:      nil,
+				IgnoreSsl:   nil,
+				Metalink:    nil,
+				Mirrorlist:  nil,
+				Rhsm:        true,
+				PackageSets: nil,
+			},
+			err: HTTPError(ErrorInvalidRepository).Error(),
+		},
+
+		// check gpg required but no gpgkey given
+		{
+			repo: Repository{
+				Baseurl:     nil,
+				CheckGpg:    common.BoolToPtr(true),
+				Gpgkey:      nil,
+				IgnoreSsl:   common.BoolToPtr(true),
+				Metalink:    common.StringToPtr("http://example.org/metalink"),
+				Mirrorlist:  nil,
+				Rhsm:        true,
+				PackageSets: nil,
+			},
+			err: HTTPError(ErrorNoGPGKey).Error(),
+		},
+	}
+
+	for _, tc := range errorTestCases {
+		rc, err := genRepoConfig(tc.repo)
+		assert.Nil(rc)
+		assert.EqualError(err, tc.err)
 	}
-	_, err := genRepoConfig(noURL)
-	assert.EqualError(err, HTTPError(ErrorInvalidRepository).Error())
 }
diff --git a/test/cases/api.sh b/test/cases/api.sh
index 73cbbe9f9..b6219bfed 100755
--- a/test/cases/api.sh
+++ b/test/cases/api.sh
@@ -458,48 +458,22 @@ else
   TEST_ID=$(uuidgen);
 fi
 
-case "$ID-$VERSION_ID" in
-  "rhel-9.0")
-    DISTRO="rhel-90"
-    if [[ "$CLOUD_PROVIDER" == "$CLOUD_PROVIDER_AWS" ]]; then
-      SSH_USER="ec2-user"
-    else
-      SSH_USER="cloud-user"
-    fi
-    ;;
-  "rhel-8.6")
-    DISTRO="rhel-86"
-    if [[ "$CLOUD_PROVIDER" == "$CLOUD_PROVIDER_AWS" ]]; then
-      SSH_USER="ec2-user"
-    else
-      SSH_USER="cloud-user"
-    fi
-    ;;
-  "rhel-8.5")
-    DISTRO="rhel-85"
-    if [[ "$CLOUD_PROVIDER" == "$CLOUD_PROVIDER_AWS" ]]; then
-      SSH_USER="ec2-user"
-    else
-      SSH_USER="cloud-user"
-    fi
-    ;;
-  "centos-8")
-    DISTRO="centos-8"
-    if [[ "$CLOUD_PROVIDER" == "$CLOUD_PROVIDER_AWS" ]]; then
-      SSH_USER="ec2-user"
-    else
-      SSH_USER="cloud-user"
-    fi
-    ;;
-  "centos-9")
-    DISTRO="centos-9"
-    if [[ "$CLOUD_PROVIDER" == "$CLOUD_PROVIDER_AWS" ]]; then
-      SSH_USER="ec2-user"
-    else
-      SSH_USER="cloud-user"
-    fi
-    ;;
-esac
+if [[ "$ID" == "fedora" ]]; then
+  # fedora uses fedora for everything
+  SSH_USER="fedora"
+elif [[ "$CLOUD_PROVIDER" == "$CLOUD_PROVIDER_AWS" ]]; then
+  # RHEL and centos use ec2-user for AWS
+  SSH_USER="ec2-user"
+else
+  # RHEL and centos use cloud-user for other clouds
+  SSH_USER="cloud-user"
+fi
+
+# This removes dot from VERSION_ID.
+# ID == rhel   && VERSION_ID == 8.6 => DISTRO == rhel-86
+# ID == centos && VERSION_ID == 8   => DISTRO == centos-8
+# ID == fedora && VERSION_ID == 35  => DISTRO == fedora-35
+DISTRO="$ID-${VERSION_ID//./}"
 
 # Only RHEL need subscription block.
 if [[ "$ID" == "rhel" ]]; then