go.mod: update osbuild/images to v0.171.0

Signed-off-by: Tomáš Hozza <thozza@redhat.com>
This commit is contained in:
Tomáš Hozza 2025-08-06 12:57:22 +02:00 committed by Simon de Vlieger
parent f76432ebb5
commit 19dd832876
32 changed files with 582 additions and 347 deletions

View file

@ -8,7 +8,7 @@ import (
"path"
"strings"
"github.com/osbuild/images/pkg/upload/azure"
"github.com/osbuild/images/pkg/cloud/azure"
)
func checkStringNotEmpty(variable string, errorMessage string) {

View file

@ -6,7 +6,7 @@ import (
"time"
"github.com/BurntSushi/toml"
"github.com/osbuild/images/pkg/upload/azure"
"github.com/osbuild/images/pkg/cloud/azure"
"github.com/sirupsen/logrus"
)

View file

@ -29,7 +29,7 @@ import (
"github.com/google/uuid"
"github.com/sirupsen/logrus"
"github.com/osbuild/images/pkg/upload/azure"
"github.com/osbuild/images/pkg/cloud/azure"
"github.com/osbuild/images/pkg/upload/koji"
"github.com/osbuild/osbuild-composer/internal/cloud/awscloud"
"github.com/osbuild/osbuild-composer/internal/cloud/gcp"

View file

@ -20,8 +20,8 @@ import (
"github.com/sirupsen/logrus"
"github.com/osbuild/images/pkg/arch"
"github.com/osbuild/images/pkg/cloud/azure"
"github.com/osbuild/images/pkg/dnfjson"
"github.com/osbuild/images/pkg/upload/azure"
"github.com/osbuild/images/pkg/upload/koji"
"github.com/osbuild/osbuild-composer/internal/cloud/awscloud"
"github.com/osbuild/osbuild-composer/internal/upload/oci"

2
go.mod
View file

@ -38,7 +38,7 @@ require (
github.com/openshift-online/ocm-sdk-go v0.1.473
github.com/oracle/oci-go-sdk/v54 v54.0.0
github.com/osbuild/blueprint v1.11.0
github.com/osbuild/images v0.168.0
github.com/osbuild/images v0.171.0
github.com/osbuild/osbuild-composer/pkg/splunk_logger v0.0.0-20240814102216-0239db53236d
github.com/osbuild/pulp-client v0.1.0
github.com/prometheus/client_golang v1.23.0

4
go.sum
View file

@ -522,8 +522,8 @@ github.com/oracle/oci-go-sdk/v54 v54.0.0 h1:CDLjeSejv2aDpElAJrhKpi6zvT/zhZCZuXch
github.com/oracle/oci-go-sdk/v54 v54.0.0/go.mod h1:+t+yvcFGVp+3ZnztnyxqXfQDsMlq8U25faBLa+mqCMc=
github.com/osbuild/blueprint v1.11.0 h1:Crqt+RRSE84JOoajzTIGrQaXXxnAgGUCDYe3nump54g=
github.com/osbuild/blueprint v1.11.0/go.mod h1:uknOfX/bAoi+dbeNJj+uAir1T++/LVEtoY8HO3U7MiQ=
github.com/osbuild/images v0.168.0 h1:qPmm9d28Py8/TrfzzyCjHAOdcXG4//NbF1EO3I8NanA=
github.com/osbuild/images v0.168.0/go.mod h1:WwKRXlJ7ksVf5jLNpKk2XBRBoX/+/7jrojS2hCm2aDw=
github.com/osbuild/images v0.171.0 h1:7lfYqIJUYh6QM6ioLW3cYLAzIu8lqPX5aGreyzEwRV8=
github.com/osbuild/images v0.171.0/go.mod h1:uZAQRhxUB5G9aAczIcgU2d9VxLude4OXEdvtnKNgAEs=
github.com/osbuild/osbuild-composer/pkg/splunk_logger v0.0.0-20240814102216-0239db53236d h1:r9BFPDv0uuA9k1947Jybcxs36c/pTywWS1gjeizvtcQ=
github.com/osbuild/osbuild-composer/pkg/splunk_logger v0.0.0-20240814102216-0239db53236d/go.mod h1:zR1iu/hOuf+OQNJlk70tju9IqzzM4ycq0ectkFBm94U=
github.com/osbuild/pulp-client v0.1.0 h1:L0C4ezBJGTamN3BKdv+rKLuq/WxXJbsFwz/Hj7aEmJ8=

View file

@ -13,7 +13,7 @@ import (
"github.com/osbuild/blueprint/pkg/blueprint"
"github.com/osbuild/images/pkg/customizations/subscription"
"github.com/osbuild/images/pkg/datasizes"
"github.com/osbuild/images/pkg/disk"
"github.com/osbuild/images/pkg/disk/partition"
"github.com/osbuild/images/pkg/distro"
"github.com/osbuild/images/pkg/distrofactory"
"github.com/osbuild/images/pkg/reporegistry"
@ -1168,21 +1168,21 @@ func (request *ComposeRequest) GetSubscription() (sub *subscription.ImageOptions
// GetPartitioningMode returns the partitioning mode included in the request
// or defaults to AutoLVMPartitioningMode if not included
func (request *ComposeRequest) GetPartitioningMode() (disk.PartitioningMode, error) {
func (request *ComposeRequest) GetPartitioningMode() (partition.PartitioningMode, error) {
if request.Customizations == nil || request.Customizations.PartitioningMode == nil {
return disk.AutoLVMPartitioningMode, nil
return partition.AutoLVMPartitioningMode, nil
}
switch *request.Customizations.PartitioningMode {
case CustomizationsPartitioningModeRaw:
return disk.RawPartitioningMode, nil
return partition.RawPartitioningMode, nil
case CustomizationsPartitioningModeLvm:
return disk.LVMPartitioningMode, nil
return partition.LVMPartitioningMode, nil
case CustomizationsPartitioningModeAutoLvm:
return disk.AutoLVMPartitioningMode, nil
return partition.AutoLVMPartitioningMode, nil
}
return disk.AutoLVMPartitioningMode, HTTPError(ErrorInvalidPartitioningMode)
return partition.AutoLVMPartitioningMode, HTTPError(ErrorInvalidPartitioningMode)
}
// GetImageRequests converts a composeRequest structure from the API to an intermediate imageRequest structure

View file

@ -9,7 +9,7 @@ import (
repos "github.com/osbuild/images/data/repositories"
"github.com/osbuild/images/pkg/customizations/subscription"
"github.com/osbuild/images/pkg/datasizes"
"github.com/osbuild/images/pkg/disk"
"github.com/osbuild/images/pkg/disk/partition"
"github.com/osbuild/images/pkg/distrofactory"
"github.com/osbuild/images/pkg/reporegistry"
"github.com/osbuild/osbuild-composer/internal/common"
@ -821,7 +821,7 @@ func TestGetPartitioningMode(t *testing.T) {
}}
pm, err := cr.GetPartitioningMode()
assert.NoError(t, err)
assert.Equal(t, disk.AutoLVMPartitioningMode, pm)
assert.Equal(t, partition.AutoLVMPartitioningMode, pm)
}
func TestGetImageRequests_ImageTypeConversion(t *testing.T) {

View file

@ -33,6 +33,7 @@ import (
"github.com/osbuild/blueprint/pkg/blueprint"
"github.com/osbuild/images/pkg/arch"
"github.com/osbuild/images/pkg/container"
"github.com/osbuild/images/pkg/disk/partition"
"github.com/osbuild/images/pkg/distro"
"github.com/osbuild/images/pkg/distrofactory"
"github.com/osbuild/images/pkg/distroidparser"
@ -2546,7 +2547,7 @@ func (api *API) composeHandler(writer http.ResponseWriter, request *http.Request
options := distro.ImageOptions{
Size: size,
OSTree: cr.OSTree,
PartitioningMode: pm,
PartitioningMode: partition.PartitioningMode(pm),
}
options.Facts = &facts.ImageOptions{
APIType: facts.WELDR_APITYPE,

View file

@ -0,0 +1,347 @@
# Image types definitions in YAML
This directory contains the supported distributions and the image
definitions in YAML that are used by the "images" library to build
disk or installer images for rpm based distributions.
## Overview
The definitions start with a "distros.yaml" file that contains details
about the supported distributions and distribution releases.
Note that in order to be available a distribution needs an auxiliary
repository JSON file under `./data/repositories` (or in a system
search path) that matches the canonical distribution name
(e.g. rhel-9.6.json or fedora-43.json).
The most simple `distros.yaml` file looks like this:
```yaml
distros:
- name: simonos-1
defs_path: ./simonos-1
```
This instructs the "images" library that the distro named
"simonos" with version "1" has its image definitions
under the subdirectory "simonos-1".
The library will search under `defs_path` for a file called
`imagetypes.yaml` that lists the available image types for
the given distro. Note that multiple distributions can point
to the same image defintions (e.g. rhel and centos do this)
and the `imagestypes.yaml` will contain conditions/templates
to match/substitute based on the distro name. This allows
re-use of existing imagetypes when only small tweaks are
needed.
The most simple `simonos-1/imagetypes.yaml` file looks like this:
```yaml
image_types:
container:
filename: container.tar
image_func: container
build_pipelines: ["build"]
payload_pipelines: ["os", "container"]
exports: ["container"]
platforms:
- arch: "x86_64"
package_set:
os:
- include:
- bash
```
With that the "images" library can now create a "container"
image type that is available on x86_64 and only adds "bash".
For the build_pipelines, payload_pipelines, exports some
knowledge about the inner workings of osbuild is required,
it is recommended to use the existing image types as examples.
We are exploring infering the pipelines from `image_func`
information.
Now only a `data/repositories/simonos-1.json` file is needed
to make a complete new distro.
## Existing defintions
### distros.yaml
The existing `distros.yaml` contains:
- fedora
- rhel-{7,8,9,10}
- centos-{8,9,10}
#### Example of a real distros.yaml snippet
```yaml
- name: "rhel-{{.MajorVersion}}.{{.MinorVersion}}"
match: 'rhel-10\.[0-9]{1,2}'
distro_like: rhel-10
product: "Red Hat Enterprise Linux"
os_version: "10.{{.MinorVersion}}"
release_version: 10
module_platform_id: "platform:el10"
vendor: "redhat"
ostree_ref_tmpl: "rhel/10/%s/edge"
default_fs_type: "xfs"
defs_path: rhel-10
iso_label_tmpl: "RHEL-{{.Distro.MajorVersion}}-{{.Distro.MinorVersion}}-0-BaseOS-{{.Arch}}"
runner:
name: "org.osbuild.rhel{{.MajorVersion}}{{.MinorVersion}}"
build_packages: &rhel10_runner_build_packages
- ..
conditions:
"some image types are rhel-only":
when:
not_distro_name: "rhel"
ignore_image_types:
- azure-cvm
- ...
# rhel & centos share the same list of allowed profiles so a
# single allow list can be used
oscap_profiles_allowlist: &oscap_profile_allowlist_rhel
- "xccdf_org.ssgproject.content_profile_anssi_bp28_enhanced"
- ...
bootstrap_containers:
x86_64: "registry.access.redhat.com/ubi{{.MajorVersion}}/ubi:latest"
```
Common keys:
#### name
This is the distribution name in the canonical
`<name>-<major>{,.<minor>}` form. E.g. `fedora-43` or `rhel-8.10`.
The name can contain go templates and the following variables are
supported "Name", "MajorVersion", "MinorVersion". This is useful
when combined with the `match` key (see below).
#### match
This key allows dynamic matching of distribution names. This is useful
when image types are shared accross multiple minor versions of a
distribution. In the example above `match` will match all names in the
range `rhel-10.0` to `rhel-10.99`. In other words, this file matches
all potential minor versions of RHEL 10.
#### product
A string that describes the product. This is displayed in the
installer image and in the bootloader.
#### os_version
This is used to construct the release string.
#### release_version
This is the `{{.MajorVersion}}` everywhere currently and
will probably be removed in a future update.
#### module_platform_id
The module_platform_id is used in the DNF resolving.
#### vendor
The vendor of the distribution. This is also used in the
bootloader UEFI setup.
#### default_fs_type
The default filesystem for OS and data partitions. This defines the
default filesystem type for the distribution and is as the fallback
for filesystems in the partition table that don't specify a type.
#### iso_label_tmpl
The string that is used to generate the ISO label. The
label can contain go templates. The following templates
are supported: ".Distro.{Name,MajorVersion,MinorVersion}",
".Product", ".Arch", ".ISOLabel".
#### conditions
Conditions to evaluate for the given distribution. This
can be used to change the behavior based on the distro
name, version or similar conditions (see below for a
list of the conditions). Currently the only operation
that is supported is the `ignore_image_types` key.
With that key certain image types can be skipped when
the condition(s) are met. This is useful to e.g. ensure
that certain image types are only available after a
specific distribution version added support for them
(e.g. rhel-9.6+ is required to build `azure-cvm`).
#### bootstrap_containers
Having this allows experimental cross architecture building.
A container in the target architecture to bootstrap the
build process is required here.
### imagetypes.yaml
The image types are defined in the following subdirectories:
- fedora
- rhel-7, rhel-8, rhel-9, rhel-10 (which also provide CentosOS Stream, Alma, Alma Kitten)
Under each of those directories there is a `imagetypes.yaml` file
that contains all image-types for the given distro.
#### Example for a real imagetypes.yaml snippet
```yaml
image_types:
qcow2: &qcow2
image_config: &qcow2_image_config
default_target: "multi-user.target"
kernel_options: ["console=tty0", "console=ttyS0,115200n8", "no_timer_check"]
conditions:
"tweak the rhsm config on rhel":
when:
distro_name: "rhel"
shallow_merge:
rhsm_config:
"no-subscription":
dnf_plugin:
product_id:
enabled: false
subscription_manager:
enabled: false
partition_table:
<<: *default_partition_tables
package_sets:
os:
- &qcow2_pkgset
include:
- "@core"
- ...
exclude:
- "aic94xx-firmware"
- ...
conditions:
"add insights pkgs on rhel":
when:
distro_name: "rhel"
append:
include:
- "insights-client"
- "subscription-manager-cockpit"
```
Common keys:
#### image_config
This maps directly to https://github.com/osbuild/images/blob/v0.154.0/pkg/distro/image_config.go#L18
Conditions can be used and *only* the "shallow_merge" action is supported,
this means that the image_config from the condition will be merged with
the original config (but only as a shallow merge, i.e. only top-levels
that are not already set will be merged).
#### partition_table
This maps directly to https://github.com/osbuild/images/blob/v0.154.0/pkg/disk/partition_table.go#L17
Conditions can be used and *only* the "override" action is supported,
this means that the original partition_table is fully replaced with
the one found via the condition.
#### package_sets
The package sets describe what packages should be included in the
"os" or "installer" pipelines. Under each keys there is a list of
objects with "include/exclude" sublists (see the example below).
Conditions can be used and *only* the "append" action is supported,
this means that the packages from the conditions is appended to the
original package sets.
#### platforms_override
This can be used to override the platforms for the image type based
on some condition. See the rhel-8 "ami" image type for an example
where the `aarch64` architecture is only available for rhel-8.9+.
#### conditions
Conditions are expressed using the following form:
```yaml
conditions:
<<: *shared_conditions
"some unique description":
when:
distro_name: "rhel"
arch: "x86_64"
version_less_than: "9.2"
version_equal: "9.1"
version_greater_or_equal: "9.3"
action:
# for "image_config" types only shallow_merge is supported
shallow_merge:
...
# for "partition_tables" types only "override" is supported
override:
...
# for "package_sets" types only "append" is supported
append:
...
```
Conditions are a "map" in YAML so that they can be easily
shared and merge via the `<<:` operation.
The `when` part of the condition can contain one or more
of:
- `distro_name`
- `not_distro_name`
- `arch`
- `version_less_than`
- `version_equal`
- `version_greater`
If multiple conditions are given under `when` they are
considered logical AND and only if they all match is
the condition executed.
### Pitfalls
All conditions will be evaluated, there is no ordering.
This means one needs to be careful about having something
like:
```yaml
conditions:
"f40plus kernel options":
when:
version_greater_or_equal: 40
action:
shallow_merge:
kernel_options:
- f40opts
"f41plus kernel options":
when:
version_greater_or_equal: 41
action:
shallow_merge:
kernel_options:
- f41opts
```
On fedora 42 both conditions will be executed but the
order is random. Because the merge is shallow only
`kernel_options` will have been set by one of the
conditions and it will either be f41opts or f40opts.
In a situation like this use either: `version_equal`
or:
```yaml
"f40-42 kernel options":
when:
version_greater_or_equal: 40
version_less_than: 43
action:
shallow_merge:
kernel_options:
- f40,41,42opts
```

View file

@ -0,0 +1,6 @@
package distrodefs
import "embed"
//go:embed *.yaml */*.yaml
var Data embed.FS

View file

@ -788,6 +788,7 @@ image_types:
- "redhat-release"
- "redhat-release-eula"
- "rsync"
- "system-reinstall-bootc"
- "tar"
- "tuned"
- "tcpdump"
@ -945,6 +946,7 @@ image_types:
- "patch"
- "rng-tools"
- "selinux-policy-targeted"
- "system-reinstall-bootc"
- "uuid"
- "WALinuxAgent"
- "yum-utils"
@ -1003,12 +1005,6 @@ image_types:
append:
include:
- "insights-client"
"add system-reinstall-bootc on rhel":
when:
distro_name: "rhel"
append:
include:
- "system-reinstall-bootc"
"azure": &azure
<<: *vhd
@ -1334,6 +1330,7 @@ image_types:
- "redhat-release"
- "redhat-release-eula"
- "rsync"
- "system-reinstall-bootc"
- "tuned"
- "tar"
exclude:
@ -1375,12 +1372,6 @@ image_types:
append:
include:
- "insights-client"
"add system-reinstall-bootc on rhel":
when:
distro_name: "rhel"
append:
include:
- "system-reinstall-bootc"
# RHEL internal-only x86_64 EC2 image type
ec2: &ec2

View file

@ -0,0 +1,34 @@
{
"x86_64": [
{
"name": "fedora",
"metalink": "https://mirrors.fedoraproject.org/metalink?repo=fedora-rawhide&arch=x86_64",
"gpgkey": "-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nmQINBGeGrzsBEAC4UV5Ij9oz6h6abEKIRoiezttFfnLhwOAfE9tWtfIFMRmhY91u\nL88PKf12n2xHBd3oc5ahBzGeTBhaMV+VJAppoQMSOIMI5q966D9GQ0LkJT+E5bwn\nxGRJKp7qccevh2KFOUt2vHtFskhDOuAIupoKfo5FgI9PkvAVBsrUpO/22yjNv0V/\naeDXxZhRX8m/8FKJ77VcZtBRPcp7M41bCmW9gV9IDpD81hAdTjYoQr1Y3KU0FTm5\nW4l1mf9mZcKMskOk08TyzQeC2YRB20EYRK439XCGJ4P7BFiOl96EbPpky2pHe2FV\nAvX474o3QEecTK3KxZrsRjmXOqpjRPy5YyMfKEYBM9j3zBDvpDFk79Mfuw5n2Nr5\nU4Wn/rqfhKLUKkfpfCow97nzq8NqynwS09yVobIfjHCKRtjwun6ife+s7R4L2nAu\nrTWPAHqzIjjW5nnjaFtoSulIadVKx+KibKajA6gRAc6K7xMyMTHfqZeTAIcawvX6\nh2d/nd8xCfogM5FTI5obNSUVNaMv5vQg6vcV1fb6oRgodF0Bi+1dssq5EMQpHFJM\nnIQ5NVwuzSjCLt3X2mWUp0mfIt2K9oBpBct12uXho7Nm1bSC5UFNYsvw+rj6vTqZ\nilK9pyfcYmELv7a/NPkyuACsBFGoc66nBfrEvk57kW9FaJK9mjSqGftykQARAQAB\ntDFGZWRvcmEgKDQ0KSA8ZmVkb3JhLTQ0LXByaW1hcnlAZmVkb3JhcHJvamVjdC5v\ncmc+iQJSBBMBCAA8FiEENvYS3PJ/fRpIqDXk2/z3HG2fkKYFAmeGrzsCGw8FCwkI\nBwIDIgIBBhUKCQgLAgQWAgMBAh4HAheAAAoJENv89xxtn5CmIU0P/iaFVxJjVi4P\nyu8A04PbdGy2vuBBCceIjYn5HaMDwJMRjdJT6uMS494pSKNEl/JJ8K5rRdigfUV1\n2Z22X3kI5aNb4k2wpaPg5Xq0JQS9FvG4Pjm//kNy5WplmEA8HVg4MVkvySWiXay4\n+tkCelhE8aQDstYEm3uh+lZ6udgoInfprwFMn6H+8RXkakTW1z5NkuAA8PpMDA9o\nSOFc4Hk6bhE6exEp4VNwBEkxwh4z9CGjarlXL4QEyM1UK60vtbXIHVjITjFfKVQP\nj6ifdn5X69oSuK+1mUFXEV+l9pc1mVjTVTwOrG3EMBsoekFyICp1pPtfMo1dxBed\nR8BFHqQFsFdmIG+59ycFznFOXzDRfaVn6OTEAk7T8nDqnpe/T4GlybLYic6KMKcM\nnbMLaJZjHZ97qJb5Scpsd1TWB5TDERi4VPB7NAVC/EwxMPC3IJUbRej/s05gNjg0\n+2yyuV/U/DDnNGWnLTJDFLUaE8HhQBMvNSfmdMA47mo5CCuYmpzX/3M9vlVsv8/R\nxJBxFLIj9VFCPFNgXPeu9gyyytXeWgsIpDzMNJil9tgbBuQ1dX5GFMkWtK/kPexM\nKfiSU0JgJFfFSm0OKI/KXcRlbA1zP3IF+2YwbL+P5ePinHsDiAPLCQt/dWgw2tfB\nZZLj9c3Ukew6Qobuy3V1knl564qQ6wjf\n=1m7R\n-----END PGP PUBLIC KEY BLOCK-----",
"check_gpg": true
}
],
"aarch64": [
{
"name": "fedora",
"metalink": "https://mirrors.fedoraproject.org/metalink?repo=fedora-rawhide&arch=aarch64",
"gpgkey": "-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nmQINBGeGrzsBEAC4UV5Ij9oz6h6abEKIRoiezttFfnLhwOAfE9tWtfIFMRmhY91u\nL88PKf12n2xHBd3oc5ahBzGeTBhaMV+VJAppoQMSOIMI5q966D9GQ0LkJT+E5bwn\nxGRJKp7qccevh2KFOUt2vHtFskhDOuAIupoKfo5FgI9PkvAVBsrUpO/22yjNv0V/\naeDXxZhRX8m/8FKJ77VcZtBRPcp7M41bCmW9gV9IDpD81hAdTjYoQr1Y3KU0FTm5\nW4l1mf9mZcKMskOk08TyzQeC2YRB20EYRK439XCGJ4P7BFiOl96EbPpky2pHe2FV\nAvX474o3QEecTK3KxZrsRjmXOqpjRPy5YyMfKEYBM9j3zBDvpDFk79Mfuw5n2Nr5\nU4Wn/rqfhKLUKkfpfCow97nzq8NqynwS09yVobIfjHCKRtjwun6ife+s7R4L2nAu\nrTWPAHqzIjjW5nnjaFtoSulIadVKx+KibKajA6gRAc6K7xMyMTHfqZeTAIcawvX6\nh2d/nd8xCfogM5FTI5obNSUVNaMv5vQg6vcV1fb6oRgodF0Bi+1dssq5EMQpHFJM\nnIQ5NVwuzSjCLt3X2mWUp0mfIt2K9oBpBct12uXho7Nm1bSC5UFNYsvw+rj6vTqZ\nilK9pyfcYmELv7a/NPkyuACsBFGoc66nBfrEvk57kW9FaJK9mjSqGftykQARAQAB\ntDFGZWRvcmEgKDQ0KSA8ZmVkb3JhLTQ0LXByaW1hcnlAZmVkb3JhcHJvamVjdC5v\ncmc+iQJSBBMBCAA8FiEENvYS3PJ/fRpIqDXk2/z3HG2fkKYFAmeGrzsCGw8FCwkI\nBwIDIgIBBhUKCQgLAgQWAgMBAh4HAheAAAoJENv89xxtn5CmIU0P/iaFVxJjVi4P\nyu8A04PbdGy2vuBBCceIjYn5HaMDwJMRjdJT6uMS494pSKNEl/JJ8K5rRdigfUV1\n2Z22X3kI5aNb4k2wpaPg5Xq0JQS9FvG4Pjm//kNy5WplmEA8HVg4MVkvySWiXay4\n+tkCelhE8aQDstYEm3uh+lZ6udgoInfprwFMn6H+8RXkakTW1z5NkuAA8PpMDA9o\nSOFc4Hk6bhE6exEp4VNwBEkxwh4z9CGjarlXL4QEyM1UK60vtbXIHVjITjFfKVQP\nj6ifdn5X69oSuK+1mUFXEV+l9pc1mVjTVTwOrG3EMBsoekFyICp1pPtfMo1dxBed\nR8BFHqQFsFdmIG+59ycFznFOXzDRfaVn6OTEAk7T8nDqnpe/T4GlybLYic6KMKcM\nnbMLaJZjHZ97qJb5Scpsd1TWB5TDERi4VPB7NAVC/EwxMPC3IJUbRej/s05gNjg0\n+2yyuV/U/DDnNGWnLTJDFLUaE8HhQBMvNSfmdMA47mo5CCuYmpzX/3M9vlVsv8/R\nxJBxFLIj9VFCPFNgXPeu9gyyytXeWgsIpDzMNJil9tgbBuQ1dX5GFMkWtK/kPexM\nKfiSU0JgJFfFSm0OKI/KXcRlbA1zP3IF+2YwbL+P5ePinHsDiAPLCQt/dWgw2tfB\nZZLj9c3Ukew6Qobuy3V1knl564qQ6wjf\n=1m7R\n-----END PGP PUBLIC KEY BLOCK-----\n",
"check_gpg": true
}
],
"ppc64le": [
{
"name": "fedora",
"metalink": "https://mirrors.fedoraproject.org/metalink?repo=fedora-rawhide&arch=ppc64le",
"gpgkey": "-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nmQINBGeGrzsBEAC4UV5Ij9oz6h6abEKIRoiezttFfnLhwOAfE9tWtfIFMRmhY91u\nL88PKf12n2xHBd3oc5ahBzGeTBhaMV+VJAppoQMSOIMI5q966D9GQ0LkJT+E5bwn\nxGRJKp7qccevh2KFOUt2vHtFskhDOuAIupoKfo5FgI9PkvAVBsrUpO/22yjNv0V/\naeDXxZhRX8m/8FKJ77VcZtBRPcp7M41bCmW9gV9IDpD81hAdTjYoQr1Y3KU0FTm5\nW4l1mf9mZcKMskOk08TyzQeC2YRB20EYRK439XCGJ4P7BFiOl96EbPpky2pHe2FV\nAvX474o3QEecTK3KxZrsRjmXOqpjRPy5YyMfKEYBM9j3zBDvpDFk79Mfuw5n2Nr5\nU4Wn/rqfhKLUKkfpfCow97nzq8NqynwS09yVobIfjHCKRtjwun6ife+s7R4L2nAu\nrTWPAHqzIjjW5nnjaFtoSulIadVKx+KibKajA6gRAc6K7xMyMTHfqZeTAIcawvX6\nh2d/nd8xCfogM5FTI5obNSUVNaMv5vQg6vcV1fb6oRgodF0Bi+1dssq5EMQpHFJM\nnIQ5NVwuzSjCLt3X2mWUp0mfIt2K9oBpBct12uXho7Nm1bSC5UFNYsvw+rj6vTqZ\nilK9pyfcYmELv7a/NPkyuACsBFGoc66nBfrEvk57kW9FaJK9mjSqGftykQARAQAB\ntDFGZWRvcmEgKDQ0KSA8ZmVkb3JhLTQ0LXByaW1hcnlAZmVkb3JhcHJvamVjdC5v\ncmc+iQJSBBMBCAA8FiEENvYS3PJ/fRpIqDXk2/z3HG2fkKYFAmeGrzsCGw8FCwkI\nBwIDIgIBBhUKCQgLAgQWAgMBAh4HAheAAAoJENv89xxtn5CmIU0P/iaFVxJjVi4P\nyu8A04PbdGy2vuBBCceIjYn5HaMDwJMRjdJT6uMS494pSKNEl/JJ8K5rRdigfUV1\n2Z22X3kI5aNb4k2wpaPg5Xq0JQS9FvG4Pjm//kNy5WplmEA8HVg4MVkvySWiXay4\n+tkCelhE8aQDstYEm3uh+lZ6udgoInfprwFMn6H+8RXkakTW1z5NkuAA8PpMDA9o\nSOFc4Hk6bhE6exEp4VNwBEkxwh4z9CGjarlXL4QEyM1UK60vtbXIHVjITjFfKVQP\nj6ifdn5X69oSuK+1mUFXEV+l9pc1mVjTVTwOrG3EMBsoekFyICp1pPtfMo1dxBed\nR8BFHqQFsFdmIG+59ycFznFOXzDRfaVn6OTEAk7T8nDqnpe/T4GlybLYic6KMKcM\nnbMLaJZjHZ97qJb5Scpsd1TWB5TDERi4VPB7NAVC/EwxMPC3IJUbRej/s05gNjg0\n+2yyuV/U/DDnNGWnLTJDFLUaE8HhQBMvNSfmdMA47mo5CCuYmpzX/3M9vlVsv8/R\nxJBxFLIj9VFCPFNgXPeu9gyyytXeWgsIpDzMNJil9tgbBuQ1dX5GFMkWtK/kPexM\nKfiSU0JgJFfFSm0OKI/KXcRlbA1zP3IF+2YwbL+P5ePinHsDiAPLCQt/dWgw2tfB\nZZLj9c3Ukew6Qobuy3V1knl564qQ6wjf\n=1m7R\n-----END PGP PUBLIC KEY BLOCK-----\n",
"check_gpg": true
}
],
"s390x": [
{
"name": "fedora",
"metalink": "https://mirrors.fedoraproject.org/metalink?repo=fedora-rawhide&arch=s390x",
"gpgkey": "-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nmQINBGeGrzsBEAC4UV5Ij9oz6h6abEKIRoiezttFfnLhwOAfE9tWtfIFMRmhY91u\nL88PKf12n2xHBd3oc5ahBzGeTBhaMV+VJAppoQMSOIMI5q966D9GQ0LkJT+E5bwn\nxGRJKp7qccevh2KFOUt2vHtFskhDOuAIupoKfo5FgI9PkvAVBsrUpO/22yjNv0V/\naeDXxZhRX8m/8FKJ77VcZtBRPcp7M41bCmW9gV9IDpD81hAdTjYoQr1Y3KU0FTm5\nW4l1mf9mZcKMskOk08TyzQeC2YRB20EYRK439XCGJ4P7BFiOl96EbPpky2pHe2FV\nAvX474o3QEecTK3KxZrsRjmXOqpjRPy5YyMfKEYBM9j3zBDvpDFk79Mfuw5n2Nr5\nU4Wn/rqfhKLUKkfpfCow97nzq8NqynwS09yVobIfjHCKRtjwun6ife+s7R4L2nAu\nrTWPAHqzIjjW5nnjaFtoSulIadVKx+KibKajA6gRAc6K7xMyMTHfqZeTAIcawvX6\nh2d/nd8xCfogM5FTI5obNSUVNaMv5vQg6vcV1fb6oRgodF0Bi+1dssq5EMQpHFJM\nnIQ5NVwuzSjCLt3X2mWUp0mfIt2K9oBpBct12uXho7Nm1bSC5UFNYsvw+rj6vTqZ\nilK9pyfcYmELv7a/NPkyuACsBFGoc66nBfrEvk57kW9FaJK9mjSqGftykQARAQAB\ntDFGZWRvcmEgKDQ0KSA8ZmVkb3JhLTQ0LXByaW1hcnlAZmVkb3JhcHJvamVjdC5v\ncmc+iQJSBBMBCAA8FiEENvYS3PJ/fRpIqDXk2/z3HG2fkKYFAmeGrzsCGw8FCwkI\nBwIDIgIBBhUKCQgLAgQWAgMBAh4HAheAAAoJENv89xxtn5CmIU0P/iaFVxJjVi4P\nyu8A04PbdGy2vuBBCceIjYn5HaMDwJMRjdJT6uMS494pSKNEl/JJ8K5rRdigfUV1\n2Z22X3kI5aNb4k2wpaPg5Xq0JQS9FvG4Pjm//kNy5WplmEA8HVg4MVkvySWiXay4\n+tkCelhE8aQDstYEm3uh+lZ6udgoInfprwFMn6H+8RXkakTW1z5NkuAA8PpMDA9o\nSOFc4Hk6bhE6exEp4VNwBEkxwh4z9CGjarlXL4QEyM1UK60vtbXIHVjITjFfKVQP\nj6ifdn5X69oSuK+1mUFXEV+l9pc1mVjTVTwOrG3EMBsoekFyICp1pPtfMo1dxBed\nR8BFHqQFsFdmIG+59ycFznFOXzDRfaVn6OTEAk7T8nDqnpe/T4GlybLYic6KMKcM\nnbMLaJZjHZ97qJb5Scpsd1TWB5TDERi4VPB7NAVC/EwxMPC3IJUbRej/s05gNjg0\n+2yyuV/U/DDnNGWnLTJDFLUaE8HhQBMvNSfmdMA47mo5CCuYmpzX/3M9vlVsv8/R\nxJBxFLIj9VFCPFNgXPeu9gyyytXeWgsIpDzMNJil9tgbBuQ1dX5GFMkWtK/kPexM\nKfiSU0JgJFfFSm0OKI/KXcRlbA1zP3IF+2YwbL+P5ePinHsDiAPLCQt/dWgw2tfB\nZZLj9c3Ukew6Qobuy3V1knl564qQ6wjf\n=1m7R\n-----END PGP PUBLIC KEY BLOCK-----\n",
"check_gpg": true
}
]
}

View file

@ -370,7 +370,7 @@ func (v *PartitionCustomization) UnmarshalTOML(data any) error {
// - Plain filesystem types are valid for the partition type
// - All non-empty properties are valid for the partition type (e.g.
// LogicalVolumes is empty when the type is "plain" or "btrfs")
// - Filesystems with FSType set to "swap" do not specify a mountpoint.
// - Filesystems with FSType set to "none" or "swap" do not specify a mountpoint.
//
// Note that in *addition* consumers should also call
// ValidateLayoutConstraints() to validate that the policy for disk
@ -593,6 +593,14 @@ func (p *PartitionCustomization) ValidatePartitionLabel(ptType string) error {
}
func (p *PartitionCustomization) validatePlain(mountpoints map[string]bool) error {
if p.FSType == "none" {
// make sure the mountpoint is empty and return
if p.Mountpoint != "" {
return fmt.Errorf("mountpoint for none partition must be empty (got %q)", p.Mountpoint)
}
return nil
}
if p.FSType == "swap" {
// make sure the mountpoint is empty and return
if p.Mountpoint != "" {

View file

@ -21,10 +21,21 @@ const (
)
type Client struct {
creds *azidentity.ClientSecretCredential
resFact *armresources.ClientFactory
storFact *armstorage.ClientFactory
compFact *armcompute.ClientFactory
creds *azidentity.ClientSecretCredential
resources ResourcesClient
resourceGroups ResourceGroupsClient
accounts AccountsClient
images ImagesClient
}
func newTestClient(rc ResourcesClient, rgc ResourceGroupsClient, ac AccountsClient, ic ImagesClient) *Client {
return &Client{
creds: nil,
resources: rc,
resourceGroups: rgc,
accounts: ac,
images: ic,
}
}
// NewClient creates a client for accessing the Azure API.
@ -53,9 +64,10 @@ func NewClient(credentials Credentials, tenantID, subscriptionID string) (*Clien
return &Client{
creds,
resFact,
storFact,
compFact,
resFact.NewClient(),
resFact.NewResourceGroupsClient(),
storFact.NewAccountsClient(),
compFact.NewImagesClient(),
}, nil
}
@ -70,9 +82,7 @@ type Tag struct {
// in the specified resource group, only one name is returned. It's undefined
// which one it is.
func (ac Client) GetResourceNameByTag(ctx context.Context, resourceGroup string, tag Tag) (string, error) {
c := ac.resFact.NewClient()
pager := c.NewListByResourceGroupPager(resourceGroup, &armresources.ClientListByResourceGroupOptions{
pager := ac.resources.NewListByResourceGroupPager(resourceGroup, &armresources.ClientListByResourceGroupOptions{
Filter: common.ToPtr(fmt.Sprintf("tagName eq '%s' and tagValue eq '%s'", tag.Name, tag.Value)),
})
@ -89,9 +99,7 @@ func (ac Client) GetResourceNameByTag(ctx context.Context, resourceGroup string,
// GetResourceGroupLocation returns the location of the given resource group.
func (ac Client) GetResourceGroupLocation(ctx context.Context, resourceGroup string) (string, error) {
c := ac.resFact.NewResourceGroupsClient()
group, err := c.Get(ctx, resourceGroup, nil)
group, err := ac.resourceGroups.Get(ctx, resourceGroup, nil)
if err != nil {
return "", fmt.Errorf("retrieving resource group failed: %w", err)
}
@ -105,8 +113,6 @@ func (ac Client) GetResourceGroupLocation(ctx context.Context, resourceGroup str
// The location is optional and if not provided, it is determined
// from the resource group.
func (ac Client) CreateStorageAccount(ctx context.Context, resourceGroup, name, location string, tag Tag) error {
c := ac.storFact.NewAccountsClient()
var err error
if location == "" {
location, err = ac.GetResourceGroupLocation(ctx, resourceGroup)
@ -115,7 +121,7 @@ func (ac Client) CreateStorageAccount(ctx context.Context, resourceGroup, name,
}
}
poller, err := c.BeginCreate(ctx, resourceGroup, name, armstorage.AccountCreateParameters{
poller, err := ac.accounts.BeginCreate(ctx, resourceGroup, name, armstorage.AccountCreateParameters{
SKU: &armstorage.SKU{
Name: common.ToPtr(armstorage.SKUNameStandardLRS),
Tier: common.ToPtr(armstorage.SKUTierStandard),
@ -145,8 +151,7 @@ func (ac Client) CreateStorageAccount(ctx context.Context, resourceGroup, name,
// access the given storage account. This method always returns only the first
// key.
func (ac Client) GetStorageAccountKey(ctx context.Context, resourceGroup string, storageAccount string) (string, error) {
c := ac.storFact.NewAccountsClient()
keys, err := c.ListKeys(ctx, resourceGroup, storageAccount, nil)
keys, err := ac.accounts.ListKeys(ctx, resourceGroup, storageAccount, nil)
if err != nil {
return "", fmt.Errorf("retrieving keys for a storage account failed: %w", err)
}
@ -162,7 +167,6 @@ func (ac Client) GetStorageAccountKey(ctx context.Context, resourceGroup string,
// The location is optional and if not provided, it is determined
// from the resource group.
func (ac Client) RegisterImage(ctx context.Context, resourceGroup, storageAccount, storageContainer, blobName, imageName, location string, hyperVGen HyperVGenerationType) error {
c := ac.compFact.NewImagesClient()
blobURI := fmt.Sprintf("https://%s.blob.core.windows.net/%s/%s", storageAccount, storageContainer, blobName)
var err error
@ -183,7 +187,7 @@ func (ac Client) RegisterImage(ctx context.Context, resourceGroup, storageAccoun
return fmt.Errorf("Unknown hyper v generation type %v", hyperVGen)
}
imageFuture, err := c.BeginCreateOrUpdate(ctx, resourceGroup, imageName, armcompute.Image{
imageFuture, err := ac.images.BeginCreateOrUpdate(ctx, resourceGroup, imageName, armcompute.Image{
Properties: &armcompute.ImageProperties{
HyperVGeneration: common.ToPtr(hypvgen),
SourceVirtualMachine: nil,

View file

@ -0,0 +1,27 @@
package azure
import (
"context"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5"
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources"
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage"
)
type ResourcesClient interface {
NewListByResourceGroupPager(string, *armresources.ClientListByResourceGroupOptions) *runtime.Pager[armresources.ClientListByResourceGroupResponse]
}
type ResourceGroupsClient interface {
Get(context.Context, string, *armresources.ResourceGroupsClientGetOptions) (armresources.ResourceGroupsClientGetResponse, error)
}
type AccountsClient interface {
BeginCreate(context.Context, string, string, armstorage.AccountCreateParameters, *armstorage.AccountsClientBeginCreateOptions) (*runtime.Poller[armstorage.AccountsClientCreateResponse], error)
ListKeys(context.Context, string, string, *armstorage.AccountsClientListKeysOptions) (armstorage.AccountsClientListKeysResponse, error)
}
type ImagesClient interface {
BeginCreateOrUpdate(context.Context, string, string, armcompute.Image, *armcompute.ImagesClientBeginCreateOrUpdateOptions) (*runtime.Poller[armcompute.ImagesClientCreateOrUpdateResponse], error)
}

View file

@ -0,0 +1,22 @@
package partition
type PartitioningMode string
const (
// AutoLVMPartitioningMode creates a LVM layout if the filesystem
// contains a mountpoint that's not defined in the base partition table
// of the specified image type. In the other case, a raw layout is used.
AutoLVMPartitioningMode PartitioningMode = "auto-lvm"
// LVMPartitioningMode always creates an LVM layout.
LVMPartitioningMode PartitioningMode = "lvm"
// RawPartitioningMode always creates a raw layout.
RawPartitioningMode PartitioningMode = "raw"
// BtrfsPartitioningMode creates a btrfs layout.
BtrfsPartitioningMode PartitioningMode = "btrfs"
// DefaultPartitioningMode is AutoLVMPartitioningMode and is the empty state
DefaultPartitioningMode PartitioningMode = ""
)

View file

@ -11,6 +11,7 @@ import (
"github.com/osbuild/images/pkg/arch"
"github.com/osbuild/images/pkg/blueprint"
"github.com/osbuild/images/pkg/datasizes"
"github.com/osbuild/images/pkg/disk/partition"
"github.com/osbuild/images/pkg/platform"
)
@ -31,6 +32,9 @@ type PartitionTable struct {
StartOffset uint64 `json:"start_offset,omitempty" yaml:"start_offset,omitempty"`
}
// TODO: PartitioningMode is a copy of
// pkg/disk/partition.PartitioningMode - drop once
// https://github.com/osbuild/blueprint/pull/26 is merged
type PartitioningMode string
const (
@ -110,10 +114,10 @@ const DefaultBootPartitionSize = 1 * datasizes.GiB
// containing the root filesystem is grown to fill any left over space on the
// partition table. Logical Volumes are not grown to fill the space in the
// Volume Group since they are trivial to grow on a live system.
func NewPartitionTable(basePT *PartitionTable, mountpoints []blueprint.FilesystemCustomization, imageSize uint64, mode PartitioningMode, architecture arch.Arch, requiredSizes map[string]uint64, rng *rand.Rand) (*PartitionTable, error) {
func NewPartitionTable(basePT *PartitionTable, mountpoints []blueprint.FilesystemCustomization, imageSize uint64, mode partition.PartitioningMode, architecture arch.Arch, requiredSizes map[string]uint64, rng *rand.Rand) (*PartitionTable, error) {
newPT := basePT.Clone().(*PartitionTable)
if basePT.features().LVM && (mode == RawPartitioningMode || mode == BtrfsPartitioningMode) {
if basePT.features().LVM && (mode == partition.RawPartitioningMode || mode == partition.BtrfsPartitioningMode) {
return nil, fmt.Errorf("%s partitioning mode set for a base partition table with LVM, this is unsupported", mode)
}
@ -122,13 +126,13 @@ func NewPartitionTable(basePT *PartitionTable, mountpoints []blueprint.Filesyste
var ensureLVM, ensureBtrfs bool
switch mode {
case LVMPartitioningMode:
case partition.LVMPartitioningMode:
ensureLVM = true
case RawPartitioningMode:
case partition.RawPartitioningMode:
ensureLVM = false
case DefaultPartitioningMode, AutoLVMPartitioningMode:
case partition.DefaultPartitioningMode, partition.AutoLVMPartitioningMode:
ensureLVM = len(newMountpoints) > 0
case BtrfsPartitioningMode:
case partition.BtrfsPartitioningMode:
ensureBtrfs = true
default:
return nil, fmt.Errorf("unsupported partitioning mode %q", mode)
@ -1427,6 +1431,8 @@ func addPlainPartition(pt *PartitionTable, partition blueprint.PartitionCustomiz
typeName = "usr"
case partition.Mountpoint == "/boot":
typeName = "boot"
case fstype == "none":
typeName = "data"
case fstype == "swap":
typeName = "swap"
default:
@ -1441,6 +1447,8 @@ func addPlainPartition(pt *PartitionTable, partition blueprint.PartitionCustomiz
var payload PayloadEntity
switch fstype {
case "none":
payload = nil
case "swap":
payload = &Swap{
Label: partition.Label,

View file

@ -1,170 +0,0 @@
# Image types definitions in YAML
This directory contains the "image-type" definitions in YAML.
We currently have subdirectories for:
- fedora
- rhel-7, rhel-8, rhel-9, rhel-10 (which also provide CentosOS Stream, Alma, Alma Kitten)
Under each of those directories there is a `distro.yaml` file
that contains all image-types for the given distro.
The image types are defined under `image_types` (and for rhel also in
go-code but that will be generalized soon, it is already for fedora).
## Example distro.yaml
```yaml
image_types:
qcow2: &qcow2
image_config: &qcow2_image_config
default_target: "multi-user.target"
kernel_options: ["console=tty0", "console=ttyS0,115200n8", "no_timer_check"]
conditions:
"tweak the rhsm config on rhel":
when:
distro_name: "rhel"
shallow_merge:
rhsm_config:
"no-subscription":
dnf_plugin:
product_id:
enabled: false
subscription_manager:
enabled: false
partition_table:
<<: *default_partition_tables
package_sets:
os:
- &qcow2_pkgset
include:
- "@core"
- ...
exclude:
- "aic94xx-firmware"
- ...
conditions:
"add insights pkgs on rhel":
when:
distro_name: "rhel"
append:
include:
- "insights-client"
- "subscription-manager-cockpit"
```
Common keys:
### image_config
This maps directly to https://github.com/osbuild/images/blob/v0.154.0/pkg/distro/image_config.go#L18
Conditions can be used and *only* the "shallow_merge" action is supported,
this means that the image_config from the condition will be merged with
the original config (but only as a shallow merge, i.e. only top-levels
that are not already set will be merged).
### partition_table
This maps directly to https://github.com/osbuild/images/blob/v0.154.0/pkg/disk/partition_table.go#L17
Conditions can be used and *only* the "override" action is supported,
this means that the original partition_table is fully replaced with
the one found via the condition.
### package_sets
The package sets describe what packages should be included in the
"os" or "installer" pipelines. Under each keys there is a list of
objects with "include/exclude" sublists (see the example below).
Conditions can be used and *only* the "append" action is supported,
this means that the packages from the conditions is appended to the
original package sets.
### platforms_override
This can be used to override the platforms for the image type based
on some condition. See the rhel-8 "ami" image type for an example
where the `aarch64` architecture is only available for rhel-8.9+.
### conditions
Conditions are expressed using the following form:
```yaml
conditions:
<<: *shared_conditions
"some unique description":
when:
distro_name: "rhel"
arch: "x86_64"
version_less_than: "9.2"
version_equal: "9.1"
version_greater_or_equal: "9.3"
action:
# for "image_config" types only shallow_merge is supported
shallow_merge:
...
# for "partition_tables" types only "override" is supported
override:
...
# for "package_sets" types only "append" is supported
append:
...
```
Conditions are a "map" in YAML so that they can be easily
shared and merge via the `<<:` operation.
The `when` part of the condition can contain one or more
of:
- `distro_name`
- `not_distro_name`
- `arch`
- `version_less_than`
- `version_equal`
- `version_greater`
If multiple conditions are given under `when` they are
considered logical AND and only if they all match is
the condition executed.
### Pitfalls
All conditions will be evaluated, there is no ordering.
This means one needs to be careful about having something
like:
```yaml
conditions:
"f40plus kernel options":
when:
version_greater_or_equal: 40
action:
shallow_merge:
kernel_options:
- f40opts
"f41plus kernel options":
when:
version_greater_or_equal: 41
action:
shallow_merge:
kernel_options:
- f41opts
```
On fedora 42 both conditions will be executed but the
order is random. Because the merge is shallow only
`kernel_options` will have been set by one of the
conditions and it will either be f41opts or f40opts.
In a situation like this use either: `version_equal`
or:
```yaml
"f40-42 kernel options":
when:
version_greater_or_equal: 40
version_less_than: 43
action:
shallow_merge:
kernel_options:
- f40,41,42opts
```

View file

@ -3,7 +3,6 @@ package defs
import (
"bytes"
"embed"
"errors"
"fmt"
"io/fs"
@ -15,11 +14,13 @@ import (
"gopkg.in/yaml.v3"
"github.com/osbuild/images/data/distrodefs"
"github.com/osbuild/images/internal/common"
"github.com/osbuild/images/internal/environment"
"github.com/osbuild/images/pkg/arch"
"github.com/osbuild/images/pkg/customizations/oscap"
"github.com/osbuild/images/pkg/disk"
"github.com/osbuild/images/pkg/disk/partition"
"github.com/osbuild/images/pkg/distro"
"github.com/osbuild/images/pkg/experimentalflags"
"github.com/osbuild/images/pkg/manifest"
@ -35,10 +36,8 @@ var (
ErrNoPartitionTableForArch = errors.New("no partition table for arch")
)
//go:embed *.yaml */*.yaml
var data embed.FS
var defaultDataFS fs.FS = data
// this can be overriden in tests
var defaultDataFS fs.FS = distrodefs.Data
func dataFS() fs.FS {
// XXX: this is a short term measure, pass a set of
@ -104,6 +103,9 @@ type DistroYAML struct {
// based on the distro, ideally it would not have this but
// here we are.
DistroLike manifest.Distro `yaml:"distro_like"`
// set by the loader
ID distro.ID
}
func (d *DistroYAML) ImageTypes() map[string]ImageTypeYAML {
@ -118,10 +120,8 @@ func (d *DistroYAML) ImageConfig() *distro.ImageConfig {
}
func (d *DistroYAML) SkipImageType(imgTypeName, archName string) bool {
id := common.Must(distro.ParseID(d.Name))
for _, cond := range d.Conditions {
if cond.When.Eval(id, archName) && slices.Contains(cond.IgnoreImageTypes, imgTypeName) {
if cond.When.Eval(d.ID, archName) && slices.Contains(cond.IgnoreImageTypes, imgTypeName) {
return true
}
}
@ -129,12 +129,7 @@ func (d *DistroYAML) SkipImageType(imgTypeName, archName string) bool {
return false
}
func (d *DistroYAML) runTemplates(nameVer string) error {
id, err := distro.ParseID(nameVer)
if err != nil {
return err
}
func (d *DistroYAML) runTemplates(id distro.ID) error {
var errs []error
subs := func(inp string) string {
var buf bytes.Buffer
@ -193,11 +188,6 @@ func NewDistroYAML(nameVer string) (*DistroYAML, error) {
return nil, err
}
// ParseID will also canonicalize the name
if id, err := ParseID(nameVer); err == nil && id != nil {
nameVer = id.String()
}
var foundDistro *DistroYAML
for _, distro := range distros.Distros {
if distro.Name == nameVer {
@ -219,12 +209,18 @@ func NewDistroYAML(nameVer string) (*DistroYAML, error) {
if foundDistro == nil {
return nil, nil
}
if err := foundDistro.runTemplates(nameVer); err != nil {
// having "foundDistro.id" avoid re-parsing this in the various helpers
id, err := distro.ParseID(nameVer)
if err != nil {
return nil, err
}
foundDistro.ID = *id
if err := foundDistro.runTemplates(*id); err != nil {
return nil, err
}
// load imageTypes
f, err := dataFS().Open(filepath.Join(foundDistro.DefsPath, "distro.yaml"))
f, err := dataFS().Open(filepath.Join(foundDistro.DefsPath, "imagetypes.yaml"))
if err != nil {
return nil, err
}
@ -247,10 +243,7 @@ func NewDistroYAML(nameVer string) (*DistroYAML, error) {
foundDistro.imageTypes[name] = v
}
}
foundDistro.imageConfig, err = toplevel.ImageConfig.For(nameVer)
if err != nil {
return nil, err
}
foundDistro.imageConfig = toplevel.ImageConfig.For(foundDistro.ID)
return foundDistro, nil
}
@ -279,7 +272,7 @@ type whenCondition struct {
VersionEqual string `yaml:"version_equal,omitempty"`
}
func (wc *whenCondition) Eval(id *distro.ID, archStr string) bool {
func (wc *whenCondition) Eval(id distro.ID, archStr string) bool {
match := true
if wc.DistroName != "" {
@ -292,10 +285,10 @@ func (wc *whenCondition) Eval(id *distro.ID, archStr string) bool {
match = match && (wc.Architecture == archStr)
}
if wc.VersionLessThan != "" {
match = match && (common.VersionLessThan(versionStringForVerCmp(*id), wc.VersionLessThan))
match = match && (common.VersionLessThan(versionStringForVerCmp(id), wc.VersionLessThan))
}
if wc.VersionGreaterOrEqual != "" {
match = match && (common.VersionGreaterThanOrEqual(versionStringForVerCmp(*id), wc.VersionGreaterOrEqual))
match = match && (common.VersionGreaterThanOrEqual(versionStringForVerCmp(id), wc.VersionGreaterOrEqual))
}
if wc.VersionEqual != "" {
match = match && (id.VersionString() == wc.VersionEqual)
@ -304,14 +297,10 @@ func (wc *whenCondition) Eval(id *distro.ID, archStr string) bool {
return match
}
func (di *distroImageConfig) For(nameVer string) (*distro.ImageConfig, error) {
func (di *distroImageConfig) For(id distro.ID) *distro.ImageConfig {
imgConfig := di.Default
if di.Conditions != nil {
id, err := distro.ParseID(nameVer)
if err != nil {
return nil, err
}
for _, cond := range di.Conditions {
// distro image config cannot have architecure
// specific conditions
@ -322,7 +311,7 @@ func (di *distroImageConfig) For(nameVer string) (*distro.ImageConfig, error) {
}
}
return imgConfig, nil
return imgConfig
}
type distroImageConfigConditions struct {
@ -399,7 +388,7 @@ type ImageTypeYAML struct {
DiskImagePartTool *osbuild.PartTool `yaml:"disk_image_part_tool"`
DiskImageVPCForceSize *bool `yaml:"disk_image_vpc_force_size"`
SupportedPartitioningModes []disk.PartitioningMode `yaml:"supported_partitioning_modes"`
SupportedPartitioningModes []partition.PartitioningMode `yaml:"supported_partitioning_modes"`
// name is set by the loader
name string
@ -409,13 +398,9 @@ func (it *ImageTypeYAML) Name() string {
return it.name
}
func (it *ImageTypeYAML) PlatformsFor(distroNameVer string) ([]platform.PlatformConf, error) {
func (it *ImageTypeYAML) PlatformsFor(id distro.ID) ([]platform.PlatformConf, error) {
pl := it.InternalPlatforms
if it.PlatformsOverride != nil {
id, err := distro.ParseID(distroNameVer)
if err != nil {
return nil, err
}
var nMatches int
for _, cond := range it.PlatformsOverride.Conditions {
// arch does not make sense for platform overrides
@ -536,7 +521,7 @@ type partitionTablesOverwriteCondition struct {
// The rational is that "centos-9" is always higher than any "rhel-9.X"
// version for our version compare (centos is always "rolling").
//
// TODO: this should become an explicit chose in "distro.yaml" but until
// TODO: this should become an explicit chose in "imagetypes.yaml" but until
// we have everything converted to generic.Distro accessing the properites
// from an image type is very hard so we start here.
func versionStringForVerCmp(u distro.ID) string {
@ -548,7 +533,7 @@ func versionStringForVerCmp(u distro.ID) string {
// PackageSets loads the PackageSets from the yaml source file
// discovered via the imagetype.
func (imgType *ImageTypeYAML) PackageSets(distroNameVer, archName string) (map[string]rpmmd.PackageSet, error) {
func (imgType *ImageTypeYAML) PackageSets(id distro.ID, archName string) map[string]rpmmd.PackageSet {
res := make(map[string]rpmmd.PackageSet)
for key, pkgSets := range imgType.PackageSetsYAML {
var rpmmdPkgSet rpmmd.PackageSet
@ -559,11 +544,6 @@ func (imgType *ImageTypeYAML) PackageSets(distroNameVer, archName string) (map[s
})
if pkgSet.Conditions != nil {
id, err := distro.ParseID(distroNameVer)
if err != nil {
return nil, err
}
for _, cond := range pkgSet.Conditions {
if cond.When.Eval(id, archName) {
rpmmdPkgSet = rpmmdPkgSet.Append(rpmmd.PackageSet{
@ -580,24 +560,20 @@ func (imgType *ImageTypeYAML) PackageSets(distroNameVer, archName string) (map[s
res[key] = rpmmdPkgSet
}
return res, nil
return res
}
// PartitionTable returns the partionTable for the given distro/imgType.
func (imgType *ImageTypeYAML) PartitionTable(distroNameVer, archName string) (*disk.PartitionTable, error) {
func (imgType *ImageTypeYAML) PartitionTable(id distro.ID, archName string) (*disk.PartitionTable, error) {
if imgType.PartitionTables == nil {
return nil, fmt.Errorf("%w: %q", ErrNoPartitionTableForImgType, distroNameVer)
return nil, fmt.Errorf("%w: %q", ErrNoPartitionTableForImgType, id)
}
pt, ok := imgType.PartitionTables[archName]
if !ok {
return nil, fmt.Errorf("%w (%q): %q", ErrNoPartitionTableForArch, distroNameVer, archName)
return nil, fmt.Errorf("%w (%q): %q", ErrNoPartitionTableForArch, id, archName)
}
if imgType.PartitionTablesOverrides != nil {
id, err := distro.ParseID(distroNameVer)
if err != nil {
return nil, err
}
for _, cond := range imgType.PartitionTablesOverrides.Conditions {
if cond.When.Eval(id, archName) {
pt = cond.Override[archName]
@ -609,43 +585,28 @@ func (imgType *ImageTypeYAML) PartitionTable(distroNameVer, archName string) (*d
}
// ImageConfig returns the image type specific ImageConfig
func (imgType *ImageTypeYAML) ImageConfig(distroNameVer, archName string) (*distro.ImageConfig, error) {
func (imgType *ImageTypeYAML) ImageConfig(id distro.ID, archName string) *distro.ImageConfig {
imgConfig := imgType.ImageConfigYAML.ImageConfig
condMap := imgType.ImageConfigYAML.Conditions
if condMap != nil {
id, err := distro.ParseID(distroNameVer)
if err != nil {
return nil, err
}
for _, cond := range imgType.ImageConfigYAML.Conditions {
if cond.When.Eval(id, archName) {
imgConfig = cond.ShallowMerge.InheritFrom(imgConfig)
for _, cond := range condMap {
if cond.When.Eval(id, archName) {
imgConfig = cond.ShallowMerge.InheritFrom(imgConfig)
}
}
}
return imgConfig, nil
return imgConfig
}
// InstallerConfig returns the InstallerConfig for the given imgType
// Note that on conditions the InstallerConfig is fully replaced, do
// any merging in YAML
func (imgType *ImageTypeYAML) InstallerConfig(distroNameVer, archName string) (*distro.InstallerConfig, error) {
func (imgType *ImageTypeYAML) InstallerConfig(id distro.ID, archName string) *distro.InstallerConfig {
installerConfig := imgType.InstallerConfigYAML.InstallerConfig
condMap := imgType.InstallerConfigYAML.Conditions
if condMap != nil {
id, err := distro.ParseID(distroNameVer)
if err != nil {
return nil, err
}
for _, cond := range condMap {
if cond.When.Eval(id, archName) {
installerConfig = cond.ShallowMerge.InheritFrom(installerConfig)
}
for _, cond := range imgType.InstallerConfigYAML.Conditions {
if cond.When.Eval(id, archName) {
installerConfig = cond.ShallowMerge.InheritFrom(installerConfig)
}
}
return installerConfig, nil
return installerConfig
}

View file

@ -6,6 +6,7 @@ import (
"github.com/osbuild/images/pkg/blueprint"
"github.com/osbuild/images/pkg/customizations/subscription"
"github.com/osbuild/images/pkg/disk"
"github.com/osbuild/images/pkg/disk/partition"
"github.com/osbuild/images/pkg/manifest"
"github.com/osbuild/images/pkg/ostree"
"github.com/osbuild/images/pkg/platform"
@ -137,7 +138,7 @@ type ImageOptions struct {
OSTree *ostree.ImageOptions `json:"ostree,omitempty"`
Subscription *subscription.ImageOptions `json:"subscription,omitempty"`
Facts *facts.ImageOptions `json:"facts,omitempty"`
PartitioningMode disk.PartitioningMode `json:"partitioning-mode,omitempty"`
PartitioningMode partition.PartitioningMode `json:"partitioning-mode,omitempty"`
UseBootstrapContainer bool `json:"use_bootstrap_container,omitempty"`
}

View file

@ -8,6 +8,7 @@ import (
"text/template"
"github.com/osbuild/images/internal/common"
"github.com/osbuild/images/pkg/arch"
"github.com/osbuild/images/pkg/distro"
"github.com/osbuild/images/pkg/distro/defs"
"github.com/osbuild/images/pkg/platform"
@ -88,14 +89,14 @@ func newDistro(nameVer string) (distro.Distro, error) {
if imgTypeYAML.Filename == "" {
continue
}
platforms, err := imgTypeYAML.PlatformsFor(nameVer)
platforms, err := imgTypeYAML.PlatformsFor(distroYAML.ID)
if err != nil {
return nil, err
}
for _, pl := range platforms {
ar, ok := rd.arches[pl.Arch.String()]
if !ok {
ar = newArchitecture(rd, pl.Arch.String())
ar = newArchitecture(rd, pl.Arch)
rd.arches[pl.Arch.String()] = ar
}
if distroYAML.SkipImageType(imgTypeYAML.Name(), pl.Arch.String()) {
@ -161,22 +162,22 @@ var _ = distro.Arch(&architecture{})
type architecture struct {
distro *distribution
name string
arch arch.Arch
imageTypes map[string]distro.ImageType
imageTypeAliases map[string]string
}
func newArchitecture(rd *distribution, name string) *architecture {
func newArchitecture(rd *distribution, arch arch.Arch) *architecture {
return &architecture{
distro: rd,
name: name,
arch: arch,
imageTypes: make(map[string]distro.ImageType),
imageTypeAliases: make(map[string]string),
}
}
func (a *architecture) Name() string {
return a.name
return a.arch.String()
}
func (a *architecture) ListImageTypes() []string {

View file

@ -26,10 +26,9 @@ import (
)
func osCustomizations(t *imageType, osPackageSet rpmmd.PackageSet, options distro.ImageOptions, containers []container.SourceSpec, c *blueprint.Customizations) (manifest.OSCustomizations, error) {
imageConfig := t.getDefaultImageConfig()
osc := manifest.OSCustomizations{}
imageConfig := t.getDefaultImageConfig()
if t.ImageTypeYAML.Bootable || t.ImageTypeYAML.RPMOSTree {
// TODO: for now the only image types that define a default kernel are
// ones that use UKIs and don't allow overriding, so this works.
@ -326,10 +325,9 @@ func ostreeDeploymentCustomizations(
if !t.ImageTypeYAML.RPMOSTree || !t.ImageTypeYAML.Bootable {
return manifest.OSTreeDeploymentCustomizations{}, fmt.Errorf("ostree deployment customizations are only supported for bootable rpm-ostree images")
}
imageConfig := t.getDefaultImageConfig()
deploymentConf := manifest.OSTreeDeploymentCustomizations{}
imageConfig := t.getDefaultImageConfig()
kernelOptions := imageConfig.KernelOptions
if bpKernel := c.GetKernel(); bpKernel != nil && bpKernel.Append != "" {
kernelOptions = append(kernelOptions, bpKernel.Append)
@ -523,13 +521,14 @@ func liveInstallerImage(workload workload.Workload,
img.Filename = t.Filename()
if locale := t.getDefaultImageConfig().Locale; locale != nil {
imgConfig := t.getDefaultImageConfig()
if locale := imgConfig.Locale; locale != nil {
img.Locale = *locale
}
if isoroot := t.getDefaultImageConfig().ISORootfsType; isoroot != nil {
if isoroot := imgConfig.ISORootfsType; isoroot != nil {
img.RootfsType = *isoroot
}
if isoboot := t.getDefaultImageConfig().ISOBootType; isoboot != nil {
if isoboot := imgConfig.ISOBootType; isoboot != nil {
img.ISOBoot = *isoboot
}
@ -633,10 +632,11 @@ func imageInstallerImage(workload workload.Workload,
img.Filename = t.Filename()
img.RootfsCompression = "xz" // This also triggers using the bcj filter
if isoroot := t.getDefaultImageConfig().ISORootfsType; isoroot != nil {
imgConfig := t.getDefaultImageConfig()
if isoroot := imgConfig.ISORootfsType; isoroot != nil {
img.RootfsType = *isoroot
}
if isoboot := t.getDefaultImageConfig().ISOBootType; isoboot != nil {
if isoboot := imgConfig.ISOBootType; isoboot != nil {
img.ISOBoot = *isoboot
}
@ -665,11 +665,9 @@ func iotCommitImage(workload workload.Workload,
}
imgConfig := t.getDefaultImageConfig()
if imgConfig != nil {
img.OSCustomizations.Presets = imgConfig.Presets
if imgConfig.InstallWeakDeps != nil {
img.InstallWeakDeps = *imgConfig.InstallWeakDeps
}
img.OSCustomizations.Presets = imgConfig.Presets
if imgConfig.InstallWeakDeps != nil {
img.InstallWeakDeps = *imgConfig.InstallWeakDeps
}
img.Environment = &t.ImageTypeYAML.Environment
@ -741,11 +739,9 @@ func iotContainerImage(workload workload.Workload,
}
imgConfig := t.getDefaultImageConfig()
if imgConfig != nil {
img.OSCustomizations.Presets = imgConfig.Presets
if imgConfig.InstallWeakDeps != nil {
img.OSCustomizations.InstallWeakDeps = *imgConfig.InstallWeakDeps
}
img.OSCustomizations.Presets = imgConfig.Presets
if imgConfig.InstallWeakDeps != nil {
img.OSCustomizations.InstallWeakDeps = *imgConfig.InstallWeakDeps
}
img.ContainerLanguage = img.OSCustomizations.Language
@ -837,13 +833,14 @@ func iotInstallerImage(workload workload.Workload,
img.Filename = t.Filename()
img.RootfsCompression = "xz" // This also triggers using the bcj filter
if locale := t.getDefaultImageConfig().Locale; locale != nil {
imgConfig := t.getDefaultImageConfig()
if locale := imgConfig.Locale; locale != nil {
img.Locale = *locale
}
if isoroot := t.getDefaultImageConfig().ISORootfsType; isoroot != nil {
if isoroot := imgConfig.ISORootfsType; isoroot != nil {
img.RootfsType = *isoroot
}
if isoboot := t.getDefaultImageConfig().ISOBootType; isoboot != nil {
if isoboot := imgConfig.ISOBootType; isoboot != nil {
img.ISOBoot = *isoboot
}

View file

@ -8,7 +8,6 @@ import (
"github.com/osbuild/images/internal/common"
"github.com/osbuild/images/internal/workload"
"github.com/osbuild/images/pkg/arch"
"github.com/osbuild/images/pkg/blueprint"
"github.com/osbuild/images/pkg/container"
"github.com/osbuild/images/pkg/datasizes"
@ -153,7 +152,7 @@ func (t *imageType) BootMode() platform.BootMode {
}
func (t *imageType) BasePartitionTable() (*disk.PartitionTable, error) {
return t.ImageTypeYAML.PartitionTable(t.arch.distro.Name(), t.arch.name)
return t.ImageTypeYAML.PartitionTable(t.arch.distro.ID, t.arch.arch.String())
}
func (t *imageType) getPartitionTable(customizations *blueprint.Customizations, options distro.ImageOptions, rng *rand.Rand) (*disk.PartitionTable, error) {
@ -191,7 +190,7 @@ func (t *imageType) getPartitionTable(customizations *blueprint.Customizations,
}
func (t *imageType) getDefaultImageConfig() *distro.ImageConfig {
imageConfig := common.Must(t.ImageConfig(t.arch.distro.Name(), t.arch.name))
imageConfig := t.ImageConfig(t.arch.distro.ID, t.arch.arch.String())
return imageConfig.InheritFrom(t.arch.distro.ImageConfig())
}
@ -200,7 +199,7 @@ func (t *imageType) getDefaultInstallerConfig() (*distro.InstallerConfig, error)
if !t.ImageTypeYAML.BootISO {
return nil, fmt.Errorf("image type %q is not an ISO", t.Name())
}
return t.InstallerConfig(t.arch.distro.Name(), t.arch.name)
return t.InstallerConfig(t.arch.distro.ID, t.arch.arch.String()), nil
}
func (t *imageType) PartitionType() disk.PartitionTableType {
@ -232,10 +231,7 @@ func (t *imageType) Manifest(bp *blueprint.Blueprint,
// don't add any static packages if Minimal was selected
if !bp.Minimal {
pkgSets, err := t.ImageTypeYAML.PackageSets(t.arch.distro.Name(), t.arch.name)
if err != nil {
return nil, nil, err
}
pkgSets := t.ImageTypeYAML.PackageSets(t.arch.distro.ID, t.arch.arch.String())
for name, pkgSet := range pkgSets {
staticPackageSets[name] = pkgSet
}
@ -347,6 +343,5 @@ func (t *imageType) checkOptions(bp *blueprint.Blueprint, options distro.ImageOp
}
func bootstrapContainerFor(t *imageType) string {
a := common.Must(arch.FromString(t.arch.name))
return t.arch.distro.DistroYAML.BootstrapContainers[a]
return t.arch.distro.DistroYAML.BootstrapContainers[t.arch.arch]
}

6
vendor/modules.txt vendored
View file

@ -961,9 +961,10 @@ github.com/oracle/oci-go-sdk/v54/workrequests
## explicit; go 1.23.9
github.com/osbuild/blueprint/internal/common
github.com/osbuild/blueprint/pkg/blueprint
# github.com/osbuild/images v0.168.0
# github.com/osbuild/images v0.171.0
## explicit; go 1.23.9
github.com/osbuild/images/data/dependencies
github.com/osbuild/images/data/distrodefs
github.com/osbuild/images/data/repositories
github.com/osbuild/images/internal/common
github.com/osbuild/images/internal/environment
@ -972,6 +973,7 @@ github.com/osbuild/images/pkg/arch
github.com/osbuild/images/pkg/artifact
github.com/osbuild/images/pkg/blueprint
github.com/osbuild/images/pkg/cert
github.com/osbuild/images/pkg/cloud/azure
github.com/osbuild/images/pkg/container
github.com/osbuild/images/pkg/crypt
github.com/osbuild/images/pkg/customizations/anaconda
@ -987,6 +989,7 @@ github.com/osbuild/images/pkg/customizations/users
github.com/osbuild/images/pkg/customizations/wsl
github.com/osbuild/images/pkg/datasizes
github.com/osbuild/images/pkg/disk
github.com/osbuild/images/pkg/disk/partition
github.com/osbuild/images/pkg/distro
github.com/osbuild/images/pkg/distro/defs
github.com/osbuild/images/pkg/distro/generic
@ -1011,7 +1014,6 @@ github.com/osbuild/images/pkg/rhsm/facts
github.com/osbuild/images/pkg/rpmmd
github.com/osbuild/images/pkg/runner
github.com/osbuild/images/pkg/sbom
github.com/osbuild/images/pkg/upload/azure
github.com/osbuild/images/pkg/upload/koji
# github.com/osbuild/osbuild-composer/pkg/splunk_logger v0.0.0-20240814102216-0239db53236d
## explicit; go 1.21