diff --git a/cmd/gen-manifests/main.go b/cmd/gen-manifests/main.go index d049b647e..f2b3adb6b 100644 --- a/cmd/gen-manifests/main.go +++ b/cmd/gen-manifests/main.go @@ -21,7 +21,6 @@ import ( "github.com/osbuild/osbuild-composer/internal/distro" "github.com/osbuild/osbuild-composer/internal/distroregistry" "github.com/osbuild/osbuild-composer/internal/dnfjson" - "github.com/osbuild/osbuild-composer/internal/ostree" "github.com/osbuild/osbuild-composer/internal/rpmmd" ) @@ -116,10 +115,10 @@ func makeManifestJob(name string, imgType distro.ImageType, cr composeRequest, d options := distro.ImageOptions{Size: 0} if cr.OSTree != nil { - options.OSTree = ostree.RequestParams{ - URL: cr.OSTree.URL, - Ref: cr.OSTree.Ref, - Parent: cr.OSTree.Parent, + options.OSTree = distro.OSTreeImageOptions{ + URL: cr.OSTree.URL, + ImageRef: cr.OSTree.Ref, + FetchChecksum: cr.OSTree.Parent, } } job := func(msgq chan string) (err error) { @@ -152,9 +151,9 @@ func makeManifestJob(name string, imgType distro.ImageType, cr composeRequest, d err = fmt.Errorf("[%s] nil package specs", filename) return } - if options.OSTree.Ref == "" { + if options.OSTree.ImageRef == "" { // use default OSTreeRef for image type - options.OSTree.Ref = imgType.OSTreeRef() + options.OSTree.ImageRef = imgType.OSTreeRef() } manifest, err := imgType.Manifest(cr.Blueprint.Customizations, options, repos, packageSpecs, containerSpecs, seedArg) if err != nil { diff --git a/cmd/osbuild-dnf-json-tests/main_test.go b/cmd/osbuild-dnf-json-tests/main_test.go index 256d8c32c..5d3f5f24b 100644 --- a/cmd/osbuild-dnf-json-tests/main_test.go +++ b/cmd/osbuild-dnf-json-tests/main_test.go @@ -16,7 +16,6 @@ import ( "github.com/osbuild/osbuild-composer/internal/distro/fedora" rhel "github.com/osbuild/osbuild-composer/internal/distro/rhel8" "github.com/osbuild/osbuild-composer/internal/dnfjson" - "github.com/osbuild/osbuild-composer/internal/ostree" "github.com/osbuild/osbuild-composer/internal/rpmmd" ) @@ -53,10 +52,10 @@ func TestCrossArchDepsolve(t *testing.T) { packages := imgType.PackageSets(blueprint.Blueprint{}, distro.ImageOptions{ - OSTree: ostree.RequestParams{ - URL: "foo", - Ref: "bar", - Parent: "baz", + OSTree: distro.OSTreeImageOptions{ + URL: "foo", + ImageRef: "bar", + FetchChecksum: "baz", }, }, repos[archStr]) diff --git a/cmd/osbuild-package-sets/main.go b/cmd/osbuild-package-sets/main.go index 6d49395ac..ade46548c 100644 --- a/cmd/osbuild-package-sets/main.go +++ b/cmd/osbuild-package-sets/main.go @@ -11,7 +11,6 @@ import ( "github.com/osbuild/osbuild-composer/internal/blueprint" "github.com/osbuild/osbuild-composer/internal/distro" "github.com/osbuild/osbuild-composer/internal/distroregistry" - "github.com/osbuild/osbuild-composer/internal/ostree" ) func main() { @@ -49,10 +48,10 @@ func main() { encoder := json.NewEncoder(os.Stdout) encoder.SetIndent("", " ") pkgset := image.PackageSets(blueprint.Blueprint{}, distro.ImageOptions{ - OSTree: ostree.RequestParams{ - URL: "foo", - Ref: "bar", - Parent: "baz", + OSTree: distro.OSTreeImageOptions{ + URL: "foo", + ImageRef: "bar", + FetchChecksum: "baz", }, }, nil) _ = encoder.Encode(pkgset) diff --git a/cmd/osbuild-pipeline/main.go b/cmd/osbuild-pipeline/main.go index 2d89a6acc..e63000704 100644 --- a/cmd/osbuild-pipeline/main.go +++ b/cmd/osbuild-pipeline/main.go @@ -13,7 +13,6 @@ import ( "github.com/osbuild/osbuild-composer/internal/distro" "github.com/osbuild/osbuild-composer/internal/distroregistry" "github.com/osbuild/osbuild-composer/internal/dnfjson" - "github.com/osbuild/osbuild-composer/internal/ostree" "github.com/osbuild/osbuild-composer/internal/blueprint" "github.com/osbuild/osbuild-composer/internal/rpmmd" @@ -159,10 +158,10 @@ func main() { options := distro.ImageOptions{ Size: imageType.Size(0), - OSTree: ostree.RequestParams{ - Ref: composeRequest.OSTree.Ref, - Parent: composeRequest.OSTree.Parent, - URL: composeRequest.OSTree.URL, + OSTree: distro.OSTreeImageOptions{ + ImageRef: composeRequest.OSTree.Ref, + FetchChecksum: composeRequest.OSTree.Parent, + URL: composeRequest.OSTree.URL, }, } diff --git a/internal/cloudapi/v2/handler.go b/internal/cloudapi/v2/handler.go index 243925ff5..ea745bc51 100644 --- a/internal/cloudapi/v2/handler.go +++ b/internal/cloudapi/v2/handler.go @@ -298,7 +298,8 @@ func (h *apiHandlers) PostCompose(ctx echo.Context) error { ostreeOptions.Parent = *ir.Ostree.Parent } } - if imageOptions.OSTree, err = ostree.ResolveParams(ostreeOptions, imageType.OSTreeRef()); err != nil { + ref, checksum, err := ostree.ResolveParams(ostreeOptions, imageType.OSTreeRef()) + if err != nil { switch v := err.(type) { case ostree.RefError: return HTTPError(ErrorInvalidOSTreeRef) @@ -311,6 +312,11 @@ func (h *apiHandlers) PostCompose(ctx echo.Context) error { return HTTPError(ErrorInvalidOSTreeParams) } } + imageOptions.OSTree = distro.OSTreeImageOptions{ + ImageRef: ref, + FetchChecksum: checksum, + URL: ostreeOptions.URL, + } var irTarget *target.Target if ir.UploadOptions == nil { diff --git a/internal/distro/distro.go b/internal/distro/distro.go index f11a1cfd5..3bf434d63 100644 --- a/internal/distro/distro.go +++ b/internal/distro/distro.go @@ -7,7 +7,6 @@ import ( "github.com/osbuild/osbuild-composer/internal/blueprint" "github.com/osbuild/osbuild-composer/internal/container" "github.com/osbuild/osbuild-composer/internal/disk" - "github.com/osbuild/osbuild-composer/internal/ostree" "github.com/osbuild/osbuild-composer/internal/rpmmd" ) @@ -126,12 +125,31 @@ type ImageType interface { // The ImageOptions specify options for a specific image build type ImageOptions struct { - OSTree ostree.RequestParams Size uint64 + OSTree OSTreeImageOptions Subscription *SubscriptionImageOptions Facts *FactsImageOptions } +// The OSTreeImageOptions specify an ostree ref, checksum, and URL. The meaning +// of each parameter depends on the image type being built. +type OSTreeImageOptions struct { + // For ostree commit and container types: The ref of the new commit to be + // built. + // For ostree installers and raw images: The ref of the commit being + // embedded in the installer or deployed in the image. + ImageRef string + + // For ostree commit and container types: The FetchChecksum specifies the parent + // ostree commit that the new commit will be based on. + // For ostree installers and raw images: The FetchChecksum specifies the commit + // ID that will be embedded in the installer or deployed in the image. + FetchChecksum string + + // The URL from which to fetch the commit specified by the checksum. + URL string +} + // The SubscriptionImageOptions specify subscription-specific image options // ServerUrl denotes the host to register the system with // BaseUrl specifies the repository URL for DNF diff --git a/internal/distro/distro_test.go b/internal/distro/distro_test.go index b632414c6..f336c447f 100644 --- a/internal/distro/distro_test.go +++ b/internal/distro/distro_test.go @@ -8,7 +8,6 @@ import ( "github.com/osbuild/osbuild-composer/internal/distro" "github.com/osbuild/osbuild-composer/internal/distro/distro_test_common" "github.com/osbuild/osbuild-composer/internal/distroregistry" - "github.com/osbuild/osbuild-composer/internal/ostree" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -118,10 +117,10 @@ func TestImageType_PackageSetsChains(t *testing.T) { require.Nil(t, err) imagePkgSets := imageType.PackageSets(blueprint.Blueprint{}, distro.ImageOptions{ - OSTree: ostree.RequestParams{ - URL: "foo", - Ref: "bar", - Parent: "baz", + OSTree: distro.OSTreeImageOptions{ + URL: "foo", + ImageRef: "bar", + FetchChecksum: "baz", }, }, nil) for packageSetName := range imageType.PackageSetsChains() { diff --git a/internal/distro/distro_test_common/distro_test_common.go b/internal/distro/distro_test_common/distro_test_common.go index a6ebf6fc8..e8ea16724 100644 --- a/internal/distro/distro_test_common/distro_test_common.go +++ b/internal/distro/distro_test_common/distro_test_common.go @@ -97,10 +97,10 @@ func TestDistro_Manifest(t *testing.T, pipelinePath string, prefix string, regis imageType, *tt.ComposeRequest.Blueprint, distro.ImageOptions{ - OSTree: ostree.RequestParams{ - URL: "foo", - Ref: "bar", - Parent: "baz", + OSTree: distro.OSTreeImageOptions{ + URL: "foo", + ImageRef: "bar", + FetchChecksum: "baz", }, }, repos, @@ -120,8 +120,12 @@ func TestDistro_Manifest(t *testing.T, pipelinePath string, prefix string, regis got, err := imageType.Manifest(tt.ComposeRequest.Blueprint.Customizations, distro.ImageOptions{ - Size: imageType.Size(0), - OSTree: ostreeOptions, + Size: imageType.Size(0), + OSTree: distro.OSTreeImageOptions{ + URL: ostreeOptions.URL, + ImageRef: ostreeOptions.Ref, + FetchChecksum: ostreeOptions.Parent, + }, }, repos, imgPackageSpecSets, @@ -164,10 +168,10 @@ func getImageTypePkgSpecSets(imageType distro.ImageType, bp blueprint.Blueprint, func isOSTree(imgType distro.ImageType) bool { packageSets := imgType.PackageSets(blueprint.Blueprint{}, distro.ImageOptions{ - OSTree: ostree.RequestParams{ - URL: "foo", - Ref: "bar", - Parent: "baz", + OSTree: distro.OSTreeImageOptions{ + URL: "foo", + ImageRef: "bar", + FetchChecksum: "baz", }, }, nil) for _, set := range packageSets["build-packages"] { @@ -185,10 +189,10 @@ var knownKernels = []string{"kernel", "kernel-debug", "kernel-rt"} // Returns the number of known kernels in the package list func kernelCount(imgType distro.ImageType) int { sets := imgType.PackageSets(blueprint.Blueprint{}, distro.ImageOptions{ - OSTree: ostree.RequestParams{ - URL: "foo", - Ref: "bar", - Parent: "baz", + OSTree: distro.OSTreeImageOptions{ + URL: "foo", + ImageRef: "bar", + FetchChecksum: "baz", }, }, nil) n := 0 @@ -274,17 +278,17 @@ func GetTestingPackageSpecSets(packageName, arch string, pkgSetNames []string) m func GetTestingImagePackageSpecSets(packageName string, i distro.ImageType) map[string][]rpmmd.PackageSpec { arch := i.Arch().Name() imagePackageSets := make([]string, 0, len(i.PackageSets(blueprint.Blueprint{}, distro.ImageOptions{ - OSTree: ostree.RequestParams{ - URL: "foo", - Ref: "bar", - Parent: "baz", + OSTree: distro.OSTreeImageOptions{ + URL: "foo", + ImageRef: "bar", + FetchChecksum: "baz", }, }, nil))) for pkgSetName := range i.PackageSets(blueprint.Blueprint{}, distro.ImageOptions{ - OSTree: ostree.RequestParams{ - URL: "foo", - Ref: "bar", - Parent: "baz", + OSTree: distro.OSTreeImageOptions{ + URL: "foo", + ImageRef: "bar", + FetchChecksum: "baz", }, }, nil) { imagePackageSets = append(imagePackageSets, pkgSetName) diff --git a/internal/distro/fedora/distro.go b/internal/distro/fedora/distro.go index f1795d3d7..3211c8a0b 100644 --- a/internal/distro/fedora/distro.go +++ b/internal/distro/fedora/distro.go @@ -677,7 +677,8 @@ func (t *imageType) checkOptions(customizations *blueprint.Customizations, optio } if t.bootISO && t.rpmOstree { - if options.OSTree.Parent == "" { + // check the checksum instead of the URL, because the URL should have been used to resolve the checksum and we need both + if options.OSTree.FetchChecksum == "" { return fmt.Errorf("boot ISO image type %q requires specifying a URL from which to retrieve the OSTree commit", t.name) } diff --git a/internal/distro/fedora/images.go b/internal/distro/fedora/images.go index 82239e0cd..dc37d8744 100644 --- a/internal/distro/fedora/images.go +++ b/internal/distro/fedora/images.go @@ -190,9 +190,9 @@ func iotCommitImage(workload workload.Workload, img.Workload = workload var parent *manifest.OSTreeParent - if options.OSTree.Parent != "" && options.OSTree.URL != "" { + if options.OSTree.FetchChecksum != "" && options.OSTree.URL != "" { parent = &manifest.OSTreeParent{ - Checksum: options.OSTree.Parent, + Checksum: options.OSTree.FetchChecksum, URL: options.OSTree.URL, } } @@ -200,7 +200,7 @@ func iotCommitImage(workload workload.Workload, Parent: parent, } - img.OSTreeRef = options.OSTree.Ref + img.OSTreeRef = options.OSTree.ImageRef img.OSVersion = t.arch.distro.osVersion img.Filename = t.Filename() @@ -224,9 +224,9 @@ func iotContainerImage(workload workload.Workload, img.Workload = workload var parent *manifest.OSTreeParent - if options.OSTree.Parent != "" && options.OSTree.URL != "" { + if options.OSTree.FetchChecksum != "" && options.OSTree.URL != "" { parent = &manifest.OSTreeParent{ - Checksum: options.OSTree.Parent, + Checksum: options.OSTree.FetchChecksum, URL: options.OSTree.URL, } } @@ -234,7 +234,7 @@ func iotContainerImage(workload workload.Workload, Parent: parent, } - img.OSTreeRef = options.OSTree.Ref + img.OSTreeRef = options.OSTree.ImageRef img.OSVersion = t.arch.distro.osVersion img.ExtraContainerPackages = packageSets[containerPkgsKey] @@ -268,8 +268,8 @@ func iotInstallerImage(workload workload.Workload, img.Release = "202010217.n.0" // ??? img.OSTreeURL = options.OSTree.URL - img.OSTreeRef = options.OSTree.Ref - img.OSTreeCommit = options.OSTree.Parent + img.OSTreeRef = options.OSTree.ImageRef + img.OSTreeCommit = options.OSTree.FetchChecksum img.Filename = t.Filename() @@ -304,8 +304,8 @@ func iotRawImage(workload workload.Workload, img.OSName = "fedora-iot" img.OSTreeURL = options.OSTree.URL - img.OSTreeRef = options.OSTree.Ref - img.OSTreeCommit = options.OSTree.Parent + img.OSTreeRef = options.OSTree.ImageRef + img.OSTreeCommit = options.OSTree.FetchChecksum // TODO: move generation into LiveImage pt, err := t.getPartitionTable(customizations.GetFilesystems(), options, rng) diff --git a/internal/distro/rhel8/distro.go b/internal/distro/rhel8/distro.go index a150f447f..bdcc93d71 100644 --- a/internal/distro/rhel8/distro.go +++ b/internal/distro/rhel8/distro.go @@ -547,8 +547,8 @@ func (t *imageType) Manifest(customizations *blueprint.Customizations, // handle OSTree commit inputs var commits []ostree.CommitSpec - if options.OSTree.Parent != "" && options.OSTree.URL != "" { - commits = []ostree.CommitSpec{{Checksum: options.OSTree.Parent, URL: options.OSTree.URL}} + if options.OSTree.FetchChecksum != "" && options.OSTree.URL != "" { + commits = []ostree.CommitSpec{{Checksum: options.OSTree.FetchChecksum, URL: options.OSTree.URL}} } // handle inline sources @@ -577,7 +577,8 @@ func (t *imageType) checkOptions(customizations *blueprint.Customizations, optio } if t.bootISO && t.rpmOstree { - if options.OSTree.Parent == "" { + // check the checksum instead of the URL, because the URL should have been used to resolve the checksum and we need both + if options.OSTree.FetchChecksum == "" { return fmt.Errorf("boot ISO image type %q requires specifying a URL from which to retrieve the OSTree commit", t.name) } @@ -616,7 +617,8 @@ func (t *imageType) checkOptions(customizations *blueprint.Customizations, optio } } - if t.name == "edge-raw-image" && options.OSTree.Parent == "" { + // check the checksum instead of the URL, because the URL should have been used to resolve the checksum and we need both + if t.name == "edge-raw-image" && options.OSTree.FetchChecksum == "" { return fmt.Errorf("edge raw images require specifying a URL from which to retrieve the OSTree commit") } diff --git a/internal/distro/rhel8/pipelines.go b/internal/distro/rhel8/pipelines.go index 06b2dc5f2..d2fade465 100644 --- a/internal/distro/rhel8/pipelines.go +++ b/internal/distro/rhel8/pipelines.go @@ -216,7 +216,7 @@ func edgeInstallerPipelines(t *imageType, customizations *blueprint.Customizatio kernelVer := rpmmd.GetVerStrFromPackageSpecListPanic(installerPackages, "kernel") ostreeRepoPath := "/ostree/repo" payloadStages := ostreePayloadStages(options, ostreeRepoPath) - kickstartOptions, err := osbuild.NewKickstartStageOptions(kspath, "", users.UsersFromBP(customizations.GetUsers()), users.GroupsFromBP(customizations.GetGroups()), makeISORootPath(ostreeRepoPath), options.OSTree.Ref, "rhel") + kickstartOptions, err := osbuild.NewKickstartStageOptions(kspath, "", users.UsersFromBP(customizations.GetUsers()), users.GroupsFromBP(customizations.GetGroups()), makeISORootPath(ostreeRepoPath), options.OSTree.ImageRef, "rhel") if err != nil { return nil, err } @@ -373,8 +373,8 @@ func osPipeline(t *imageType, } p.Build = "name:build" - if t.rpmOstree && options.OSTree.Parent != "" && options.OSTree.URL != "" { - p.AddStage(osbuild.NewOSTreePasswdStage("org.osbuild.source", options.OSTree.Parent)) + if t.rpmOstree && options.OSTree.FetchChecksum != "" && options.OSTree.URL != "" { + p.AddStage(osbuild.NewOSTreePasswdStage("org.osbuild.source", options.OSTree.FetchChecksum)) } rpmOptions := osbuild.NewRPMStageOptions(repos) @@ -686,9 +686,9 @@ func ostreeCommitPipeline(options distro.ImageOptions, osVersion string) *osbuil p.AddStage( osbuild.NewOSTreeCommitStage( &osbuild.OSTreeCommitStageOptions{ - Ref: options.OSTree.Ref, + Ref: options.OSTree.ImageRef, OSVersion: osVersion, - Parent: options.OSTree.Parent, + Parent: options.OSTree.FetchChecksum, }, "ostree-tree", ), @@ -714,7 +714,7 @@ func containerTreePipeline(repos []rpmmd.RepoConfig, packages []rpmmd.PackageSpe p.AddStage(osbuild.NewOSTreePullStage( &osbuild.OSTreePullStageOptions{Repo: repoPath}, - osbuild.NewOstreePullStageInputs("org.osbuild.pipeline", "name:ostree-commit", options.OSTree.Ref), + osbuild.NewOstreePullStageInputs("org.osbuild.pipeline", "name:ostree-commit", options.OSTree.ImageRef), )) // make nginx log directory world writeable, otherwise nginx can't start in @@ -750,7 +750,7 @@ func ostreePayloadStages(options distro.ImageOptions, ostreeRepoPath string) []* stages = append(stages, osbuild.NewOSTreeInitStage(&osbuild.OSTreeInitStageOptions{Path: ostreeRepoPath})) stages = append(stages, osbuild.NewOSTreePullStage( &osbuild.OSTreePullStageOptions{Repo: ostreeRepoPath}, - osbuild.NewOstreePullStageInputs("org.osbuild.source", options.OSTree.Parent, options.OSTree.Ref), + osbuild.NewOstreePullStageInputs("org.osbuild.source", options.OSTree.FetchChecksum, options.OSTree.ImageRef), )) return stages @@ -928,7 +928,7 @@ func ostreeDeployPipeline( p.AddStage(osbuild.OSTreeInitFsStage()) p.AddStage(osbuild.NewOSTreePullStage( &osbuild.OSTreePullStageOptions{Repo: repoPath, Remote: remote}, - osbuild.NewOstreePullStageInputs("org.osbuild.source", options.OSTree.Parent, options.OSTree.Ref), + osbuild.NewOstreePullStageInputs("org.osbuild.source", options.OSTree.FetchChecksum, options.OSTree.ImageRef), )) p.AddStage(osbuild.NewOSTreeOsInitStage( &osbuild.OSTreeOsInitStageOptions{ @@ -941,7 +941,7 @@ func ostreeDeployPipeline( p.AddStage(osbuild.NewOSTreeDeployStage( &osbuild.OSTreeDeployStageOptions{ OsName: osname, - Ref: options.OSTree.Ref, + Ref: options.OSTree.ImageRef, Remote: remote, Mounts: []string{"/boot", "/boot/efi"}, Rootfs: osbuild.Rootfs{ @@ -969,7 +969,7 @@ func ostreeDeployPipeline( &osbuild.OSTreeFillvarStageOptions{ Deployment: osbuild.OSTreeDeployment{ OSName: osname, - Ref: options.OSTree.Ref, + Ref: options.OSTree.ImageRef, }, }, )) @@ -978,7 +978,7 @@ func ostreeDeployPipeline( fstabOptions.OSTree = &osbuild.OSTreeFstab{ Deployment: osbuild.OSTreeDeployment{ OSName: osname, - Ref: options.OSTree.Ref, + Ref: options.OSTree.ImageRef, }, } p.AddStage(osbuild.NewFSTabStage(fstabOptions)) @@ -988,12 +988,12 @@ func ostreeDeployPipeline( if err != nil { panic(err) } - usersStage.MountOSTree(osname, options.OSTree.Ref, 0) + usersStage.MountOSTree(osname, options.OSTree.ImageRef, 0) p.AddStage(usersStage) } if bpGroups := c.GetGroups(); len(bpGroups) > 0 { groupsStage := osbuild.GenGroupsStage(users.GroupsFromBP(bpGroups)) - groupsStage.MountOSTree(osname, options.OSTree.Ref, 0) + groupsStage.MountOSTree(osname, options.OSTree.ImageRef, 0) p.AddStage(groupsStage) } @@ -1003,7 +1003,7 @@ func ostreeDeployPipeline( &osbuild.OSTreeSelinuxStageOptions{ Deployment: osbuild.OSTreeDeployment{ OSName: osname, - Ref: options.OSTree.Ref, + Ref: options.OSTree.ImageRef, }, }, )) diff --git a/internal/distro/rhel9/distro.go b/internal/distro/rhel9/distro.go index ef9b9adac..6ff443ea3 100644 --- a/internal/distro/rhel9/distro.go +++ b/internal/distro/rhel9/distro.go @@ -513,8 +513,8 @@ func (t *imageType) Manifest(customizations *blueprint.Customizations, // handle OSTree commit inputs var commits []ostree.CommitSpec - if options.OSTree.Parent != "" && options.OSTree.URL != "" { - commits = []ostree.CommitSpec{{Checksum: options.OSTree.Parent, URL: options.OSTree.URL}} + if options.OSTree.FetchChecksum != "" && options.OSTree.URL != "" { + commits = []ostree.CommitSpec{{Checksum: options.OSTree.FetchChecksum, URL: options.OSTree.URL}} } // handle inline sources @@ -543,7 +543,8 @@ func (t *imageType) checkOptions(customizations *blueprint.Customizations, optio } if t.bootISO && t.rpmOstree { - if options.OSTree.Parent == "" { + // check the checksum instead of the URL, because the URL should have been used to resolve the checksum and we need both + if options.OSTree.FetchChecksum == "" { return fmt.Errorf("boot ISO image type %q requires specifying a URL from which to retrieve the OSTree commit", t.name) } @@ -582,7 +583,8 @@ func (t *imageType) checkOptions(customizations *blueprint.Customizations, optio } } - if t.name == "edge-raw-image" && options.OSTree.Parent == "" { + // check the checksum instead of the URL, because the URL should have been used to resolve the checksum and we need both + if t.name == "edge-raw-image" && options.OSTree.FetchChecksum == "" { return fmt.Errorf("edge raw images require specifying a URL from which to retrieve the OSTree commit") } diff --git a/internal/distro/rhel9/pipelines.go b/internal/distro/rhel9/pipelines.go index 65b7e2ec7..f5f073e88 100644 --- a/internal/distro/rhel9/pipelines.go +++ b/internal/distro/rhel9/pipelines.go @@ -211,7 +211,7 @@ func edgeInstallerPipelines(t *imageType, customizations *blueprint.Customizatio kernelVer := rpmmd.GetVerStrFromPackageSpecListPanic(installerPackages, "kernel") ostreeRepoPath := "/ostree/repo" payloadStages := ostreePayloadStages(options, ostreeRepoPath) - kickstartOptions, err := osbuild.NewKickstartStageOptions(kspath, "", users.UsersFromBP(customizations.GetUsers()), users.GroupsFromBP(customizations.GetGroups()), makeISORootPath(ostreeRepoPath), options.OSTree.Ref, "rhel") + kickstartOptions, err := osbuild.NewKickstartStageOptions(kspath, "", users.UsersFromBP(customizations.GetUsers()), users.GroupsFromBP(customizations.GetGroups()), makeISORootPath(ostreeRepoPath), options.OSTree.ImageRef, "rhel") if err != nil { return nil, err } @@ -368,8 +368,8 @@ func osPipeline(t *imageType, } p.Build = "name:build" - if t.rpmOstree && options.OSTree.Parent != "" && options.OSTree.URL != "" { - p.AddStage(osbuild.NewOSTreePasswdStage("org.osbuild.source", options.OSTree.Parent)) + if t.rpmOstree && options.OSTree.FetchChecksum != "" && options.OSTree.URL != "" { + p.AddStage(osbuild.NewOSTreePasswdStage("org.osbuild.source", options.OSTree.FetchChecksum)) } rpmOptions := osbuild.NewRPMStageOptions(repos) @@ -686,9 +686,9 @@ func ostreeCommitPipeline(options distro.ImageOptions, osVersion string) *osbuil p.AddStage(osbuild.NewOSTreeCommitStage( &osbuild.OSTreeCommitStageOptions{ - Ref: options.OSTree.Ref, + Ref: options.OSTree.ImageRef, OSVersion: osVersion, - Parent: options.OSTree.Parent, + Parent: options.OSTree.FetchChecksum, }, "ostree-tree"), ) @@ -713,7 +713,7 @@ func containerTreePipeline(repos []rpmmd.RepoConfig, packages []rpmmd.PackageSpe p.AddStage(osbuild.NewOSTreePullStage( &osbuild.OSTreePullStageOptions{Repo: repoPath}, - osbuild.NewOstreePullStageInputs("org.osbuild.pipeline", "name:ostree-commit", options.OSTree.Ref), + osbuild.NewOstreePullStageInputs("org.osbuild.pipeline", "name:ostree-commit", options.OSTree.ImageRef), )) // make nginx log and lib directories world writeable, otherwise nginx can't start in @@ -750,7 +750,7 @@ func ostreePayloadStages(options distro.ImageOptions, ostreeRepoPath string) []* stages = append(stages, osbuild.NewOSTreeInitStage(&osbuild.OSTreeInitStageOptions{Path: ostreeRepoPath})) stages = append(stages, osbuild.NewOSTreePullStage( &osbuild.OSTreePullStageOptions{Repo: ostreeRepoPath}, - osbuild.NewOstreePullStageInputs("org.osbuild.source", options.OSTree.Parent, options.OSTree.Ref), + osbuild.NewOstreePullStageInputs("org.osbuild.source", options.OSTree.FetchChecksum, options.OSTree.ImageRef), )) return stages @@ -924,7 +924,7 @@ func ostreeDeployPipeline( p.AddStage(osbuild.OSTreeInitFsStage()) p.AddStage(osbuild.NewOSTreePullStage( &osbuild.OSTreePullStageOptions{Repo: repoPath, Remote: remote}, - osbuild.NewOstreePullStageInputs("org.osbuild.source", options.OSTree.Parent, options.OSTree.Ref), + osbuild.NewOstreePullStageInputs("org.osbuild.source", options.OSTree.FetchChecksum, options.OSTree.ImageRef), )) p.AddStage(osbuild.NewOSTreeOsInitStage( &osbuild.OSTreeOsInitStageOptions{ @@ -937,7 +937,7 @@ func ostreeDeployPipeline( p.AddStage(osbuild.NewOSTreeDeployStage( &osbuild.OSTreeDeployStageOptions{ OsName: osname, - Ref: options.OSTree.Ref, + Ref: options.OSTree.ImageRef, Remote: remote, Mounts: []string{"/boot", "/boot/efi"}, Rootfs: osbuild.Rootfs{ @@ -965,7 +965,7 @@ func ostreeDeployPipeline( &osbuild.OSTreeFillvarStageOptions{ Deployment: osbuild.OSTreeDeployment{ OSName: osname, - Ref: options.OSTree.Ref, + Ref: options.OSTree.ImageRef, }, }, )) @@ -974,7 +974,7 @@ func ostreeDeployPipeline( fstabOptions.OSTree = &osbuild.OSTreeFstab{ Deployment: osbuild.OSTreeDeployment{ OSName: osname, - Ref: options.OSTree.Ref, + Ref: options.OSTree.ImageRef, }, } p.AddStage(osbuild.NewFSTabStage(fstabOptions)) @@ -984,12 +984,12 @@ func ostreeDeployPipeline( if err != nil { panic(err) } - usersStage.MountOSTree(osname, options.OSTree.Ref, 0) + usersStage.MountOSTree(osname, options.OSTree.ImageRef, 0) p.AddStage(usersStage) } if bpGroups := c.GetGroups(); len(bpGroups) > 0 { groupsStage := osbuild.GenGroupsStage(users.GroupsFromBP(bpGroups)) - groupsStage.MountOSTree(osname, options.OSTree.Ref, 0) + groupsStage.MountOSTree(osname, options.OSTree.ImageRef, 0) p.AddStage(groupsStage) } @@ -999,7 +999,7 @@ func ostreeDeployPipeline( &osbuild.OSTreeSelinuxStageOptions{ Deployment: osbuild.OSTreeDeployment{ OSName: osname, - Ref: options.OSTree.Ref, + Ref: options.OSTree.ImageRef, }, }, )) diff --git a/internal/ostree/ostree.go b/internal/ostree/ostree.go index dc15d67e7..8f8d0cd3d 100644 --- a/internal/ostree/ostree.go +++ b/internal/ostree/ostree.go @@ -72,47 +72,56 @@ func ResolveRef(location, ref string) (string, error) { return parent, nil } -// ResolveParams resolves all necessary missing parameters in the given struct: -// it sets the defaultRef if none is provided and resolves the parent commit if -// a URL and Ref are provided. If there is an error, it will be of type -// InvalidParameterError or ResolveRefError (from the ResolveRef function) -func ResolveParams(params RequestParams, defaultRef string) (RequestParams, error) { - resolved := RequestParams{} - resolved.Ref = params.Ref - // if ref is not provided, use distro default - if resolved.Ref == "" { - resolved.Ref = defaultRef - } else if !VerifyRef(params.Ref) { // only verify if specified in params - return resolved, NewRefError("Invalid ostree ref %q", params.Ref) +// ResolveParams resolves the ostree request parameters into the necessary ref +// for the image build pipeline and a commit (checksum) to be fetched. +// +// If a URL is defined in the RequestParams, the checksum of the Parent ref is +// resolved, otherwise the checksum is an empty string. Specifying Parent +// without URL results in a ParameterComboError. Failure to resolve the +// checksum results in a ResolveRefError. +// +// If Ref is not specified in the RequestParams, the defaultRef is used. +// If Parent is not specified in the RequestParams, the value of Ref is used +// (which will be defaultRef if neither is specified). +// +// If any ref (Ref or Parent) is malformed, the function returns with a RefError. +func ResolveParams(params RequestParams, defaultRef string) (ref, checksum string, err error) { + // Determine value of ref + ref = params.Ref + if ref != "" { + // verify format of provided ref + if !VerifyRef(params.Ref) { + return "", "", NewRefError("Invalid ostree ref %q", params.Ref) + } + } else { + // if ref is not provided, use distro default + ref = defaultRef } - if params.Parent != "" { - // parent must also be a valid ref + // Determine value of parentRef + parentRef := params.Parent + if parentRef != "" { + // verify format of parent ref if !VerifyRef(params.Parent) { - return resolved, NewRefError("Invalid ostree parent ref %q", params.Parent) + return "", "", NewRefError("Invalid ostree parent ref %q", params.Parent) } if params.URL == "" { // specifying parent ref also requires URL - return resolved, NewParameterComboError("ostree parent ref specified, but no URL to retrieve it") + return "", "", NewParameterComboError("ostree parent ref specified, but no URL to retrieve it") } + } else { + // if parent is not provided, use ref + parentRef = ref } - resolved.URL = params.URL - if resolved.URL != "" { - // if a URL is specified, we need to fetch the commit at the URL - // the reference to resolve is the parent commit which is defined by - // the 'parent' argument - // if the parent argument is not specified, we use the specified ref - // if neither is specified, we use the default ref - parentRef := params.Parent - if parentRef == "" { - parentRef = resolved.Ref - } - parent, err := ResolveRef(resolved.URL, parentRef) + // Resolve parent checksum + if params.URL != "" { + // If a URL is specified, we need to fetch the commit at the URL. + parent, err := ResolveRef(params.URL, parentRef) if err != nil { - return resolved, err // ResolveRefError + return "", "", err // ResolveRefError } - resolved.Parent = parent + checksum = parent } - return resolved, nil + return } diff --git a/internal/weldr/api.go b/internal/weldr/api.go index aff0364aa..c4b92c745 100644 --- a/internal/weldr/api.go +++ b/internal/weldr/api.go @@ -2351,11 +2351,14 @@ func (api *API) composeHandler(writer http.ResponseWriter, request *http.Request } testMode := q.Get("test") + ostreeOptions := distro.OSTreeImageOptions{ + URL: cr.OSTree.URL, + } if testMode == "1" || testMode == "2" { // Fake a parent commit for test requests cr.OSTree.Parent = "02604b2da6e954bd34b8b82a835e5a77d2b60ffa" } else { - ostreeParams, err := ostree.ResolveParams(cr.OSTree, imageType.OSTreeRef()) + ref, checksum, err := ostree.ResolveParams(cr.OSTree, imageType.OSTreeRef()) if err != nil { errors := responseError{ ID: "OSTreeOptionsError", @@ -2364,7 +2367,8 @@ func (api *API) composeHandler(writer http.ResponseWriter, request *http.Request statusResponseError(writer, http.StatusBadRequest, errors) return } - cr.OSTree = ostreeParams + ostreeOptions.ImageRef = ref + ostreeOptions.FetchChecksum = checksum } var size uint64 @@ -2385,12 +2389,8 @@ func (api *API) composeHandler(writer http.ResponseWriter, request *http.Request seed := bigSeed.Int64() options := distro.ImageOptions{ - Size: size, - OSTree: ostree.RequestParams{ - Ref: cr.OSTree.Ref, - Parent: cr.OSTree.Parent, - URL: cr.OSTree.URL, - }, + Size: size, + OSTree: ostreeOptions, } options.Facts = &distro.FactsImageOptions{ ApiType: "weldr",