-
Notifications
You must be signed in to change notification settings - Fork 58
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
bib: switch to use bootc install to-filesystem
(HMS-3453)
#304
Changes from all commits
55dc919
9167b9a
84fcd50
1455c74
2585c73
0fb38da
811af24
1ebdf76
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,32 +23,35 @@ $ podman machine start | |
|
||
## 🚀 Examples | ||
|
||
The following example builds a [Fedora ELN](https://docs.fedoraproject.org/en-US/eln/) bootable container into a QCOW2 image for the architecture you're running | ||
the command on. | ||
|
||
The `fedora-bootc:eln` base image does not include a default user. This example injects a [user configuration file](#-build-config) | ||
by adding a volume-mount for the local file as well as the `--config` flag to the bootc-image-builder container. | ||
|
||
The following command will create a QCOW2 disk image. First, create `./config.json` as described above to configure user access. | ||
The following example builds a derrived [Fedora ELN](https://docs.fedoraproject.org/en-US/eln/) bootable container into a QCOW2 image for the architecture you're running the command on. | ||
|
||
```bash | ||
cat > Containerfile <<'EOF' | ||
FROM quay.io/centos-bootc/fedora-bootc:eln | ||
RUN useradd alice --password "$(openssl passwd -6 "bob")" --groups wheel | ||
EOF | ||
sudo podman build -f Containerfile -t my-bootc | ||
sudo podman run \ | ||
--rm \ | ||
-it \ | ||
--privileged \ | ||
--pull=newer \ | ||
--security-opt label=type:unconfined_t \ | ||
-v $(pwd)/config.json:/config.json \ | ||
-v $(pwd)/output:/output \ | ||
-v /var/lib/containers/storage:/var/lib/containers/storage \ | ||
quay.io/centos-bootc/bootc-image-builder:latest \ | ||
--type qcow2 \ | ||
--config /config.json \ | ||
quay.io/centos-bootc/fedora-bootc:eln | ||
--local \ | ||
localhost/my-bootc | ||
``` | ||
|
||
There is more in-depth discussion how to customize the image and the users in the [bootc documentation](https://bootc-org.gitlab.io/documentation/guide/building.html#logins-and-users). | ||
|
||
### Using local containers | ||
|
||
To use containers from local container's storage rather than a registry, we need to ensure two things: | ||
By default (without the `--local` flag) bootc-image-builder will use | ||
the podman registry. To use containers from local container's storage, | ||
we need to ensure two things: | ||
- the container exists in local storage | ||
- mount the local container storage | ||
|
||
|
@@ -61,12 +64,10 @@ sudo podman run \ | |
--privileged \ | ||
--pull=newer \ | ||
--security-opt label=type:unconfined_t \ | ||
-v $(pwd)/config.json:/config.json \ | ||
-v $(pwd)/output:/output \ | ||
-v /var/lib/containers/storage:/var/lib/containers/storage \ | ||
quay.io/centos-bootc/bootc-image-builder:latest \ | ||
--type qcow2 \ | ||
--config /config.json \ | ||
--local \ | ||
localhost/bootc:eln | ||
``` | ||
|
@@ -134,7 +135,6 @@ Usage: | |
|
||
Flags: | ||
--chown string chown the ouput directory to match the specified UID:GID | ||
--config string build config file | ||
--tls-verify require HTTPS and verify certificates when contacting registries (default true) | ||
--type string image type to build [qcow2, ami] (default "qcow2") | ||
``` | ||
|
@@ -144,7 +144,6 @@ Flags: | |
| Argument | Description | Default Value | | ||
|------------------|------------------------------------------------------------------|:-------------:| | ||
| **--chown** | chown the ouput directory to match the specified UID:GID | ❌ | | ||
| **--config** | Path to a [build config](#-build-config) | ❌ | | ||
| **--tls-verify** | Require HTTPS and verify certificates when contacting registries | `true` | | ||
| **--type** | [Image type](#-image-types) to build | `qcow2` | | ||
|
||
|
@@ -262,79 +261,6 @@ The following volumes can be mounted inside the container: | |
| `/store` | Used for the [osbuild store](https://www.osbuild.org/) | No | | ||
| `/rpmmd` | Used for the DNF cache | No | | ||
|
||
## 📝 Build config | ||
|
||
A build config is a JSON file with customizations for the resulting image. A path to the file is passed via the `--config` argument. The customizations are specified under a `blueprint.customizations` object. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would it be helpful to have a realtime sync on this? I sent an invite. |
||
|
||
As an example, let's show how you can add a user to the image: | ||
|
||
Firstly create a file `./config.json` and put the following content into it: | ||
|
||
```json | ||
{ | ||
"blueprint": { | ||
"customizations": { | ||
"user": [ | ||
{ | ||
"name": "alice", | ||
"password": "bob", | ||
"key": "ssh-rsa AAA ... [email protected]", | ||
"groups": [ | ||
"wheel" | ||
] | ||
} | ||
] | ||
} | ||
} | ||
} | ||
``` | ||
|
||
Then, run `bootc-image-builder` with the following arguments: | ||
|
||
```bash | ||
sudo podman run \ | ||
--rm \ | ||
-it \ | ||
--privileged \ | ||
--pull=newer \ | ||
--security-opt label=type:unconfined_t \ | ||
-v $(pwd)/config.json:/config.json \ | ||
-v $(pwd)/output:/output \ | ||
quay.io/centos-bootc/bootc-image-builder:latest \ | ||
--type qcow2 \ | ||
--config /config.json \ | ||
quay.io/centos-bootc/fedora-bootc:eln | ||
``` | ||
|
||
### Users (`user`, array) | ||
|
||
Possible fields: | ||
|
||
| Field | Use | Required | | ||
|------------|--------------------------------------------|:--------:| | ||
| `name` | Name of the user | ✅ | | ||
| `password` | Unencrypted password | No | | ||
| `key` | Public SSH key contents | No | | ||
| `groups` | An array of secondary to put the user into | No | | ||
|
||
Example: | ||
|
||
```json | ||
{ | ||
"user": [ | ||
{ | ||
"name": "alice", | ||
"password": "bob", | ||
"key": "ssh-rsa AAA ... [email protected]", | ||
"groups": [ | ||
"wheel", | ||
"admins" | ||
] | ||
} | ||
] | ||
} | ||
``` | ||
|
||
## Building | ||
|
||
To build the container locally you can run | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -78,8 +78,6 @@ func manifestForDiskImage(c *ManifestConfig, rng *rand.Rand) (*manifest.Manifest | |
|
||
img := image.NewBootcDiskImage(containerSource) | ||
img.Users = users.UsersFromBP(customizations.GetUsers()) | ||
img.Groups = users.GroupsFromBP(customizations.GetGroups()) | ||
|
||
img.KernelOptionsAppend = []string{ | ||
"rw", | ||
// TODO: Drop this as we expect kargs to come from the container image, | ||
|
@@ -88,8 +86,6 @@ func manifestForDiskImage(c *ManifestConfig, rng *rand.Rand) (*manifest.Manifest | |
"console=ttyS0", | ||
} | ||
|
||
img.SysrootReadOnly = true | ||
|
||
switch c.Architecture { | ||
case arch.ARCH_X86_64: | ||
img.Platform = &platform.X86{ | ||
|
@@ -265,8 +261,6 @@ func manifestForISO(c *ManifestConfig, rng *rand.Rand) (*manifest.Manifest, erro | |
}, | ||
} | ||
|
||
img.ISOLabelTmpl = "Container-Installer-%s" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we want something like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thank you! I fixed this in #342 |
||
|
||
var customizations *blueprint.Customizations | ||
if c.Config != nil && c.Config.Blueprint != nil { | ||
customizations = c.Config.Blueprint.Customizations | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,7 +11,10 @@ import ( | |
"strconv" | ||
"strings" | ||
|
||
"github.com/osbuild/bootc-image-builder/bib/internal/setup" | ||
"github.com/sirupsen/logrus" | ||
"github.com/spf13/cobra" | ||
"golang.org/x/exp/slices" | ||
|
||
"github.com/osbuild/images/pkg/arch" | ||
"github.com/osbuild/images/pkg/blueprint" | ||
"github.com/osbuild/images/pkg/cloud/awscloud" | ||
|
@@ -20,9 +23,8 @@ import ( | |
"github.com/osbuild/images/pkg/manifest" | ||
"github.com/osbuild/images/pkg/osbuild" | ||
"github.com/osbuild/images/pkg/rpmmd" | ||
"github.com/sirupsen/logrus" | ||
"github.com/spf13/cobra" | ||
"golang.org/x/exp/slices" | ||
|
||
"github.com/osbuild/bootc-image-builder/bib/internal/setup" | ||
) | ||
|
||
//go:embed fedora-eln.json | ||
|
@@ -233,12 +235,13 @@ func manifestFromCobra(cmd *cobra.Command, args []string) ([]byte, error) { | |
} | ||
|
||
imgref := args[0] | ||
configFile, _ := cmd.Flags().GetString("config") | ||
isoConfigFile, _ := cmd.Flags().GetString("iso-config") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I thought the config actually didn't apply to the ISO at all? Or am I missing something? |
||
imgTypes, _ := cmd.Flags().GetStringArray("type") | ||
rpmCacheRoot, _ := cmd.Flags().GetString("rpmmd") | ||
targetArch, _ := cmd.Flags().GetString("target-arch") | ||
tlsVerify, _ := cmd.Flags().GetBool("tls-verify") | ||
localStorage, _ := cmd.Flags().GetBool("local") | ||
rootSSHKey, _ := cmd.Flags().GetString("experimental-root-ssh-authorized-key") | ||
|
||
if targetArch != "" { | ||
// TODO: detect if binfmt_misc for target arch is | ||
|
@@ -259,16 +262,31 @@ func manifestFromCobra(cmd *cobra.Command, args []string) ([]byte, error) { | |
return nil, err | ||
} | ||
|
||
// bootc does not yet support arbitray blueprint customizations | ||
if buildType != BuildTypeISO && isoConfigFile != "" { | ||
return nil, fmt.Errorf("the --iso-config switch is only supported for ISO images") | ||
} | ||
|
||
var config *BuildConfig | ||
if configFile != "" { | ||
config, err = loadConfig(configFile) | ||
if isoConfigFile != "" { | ||
config, err = loadConfig(isoConfigFile) | ||
if err != nil { | ||
return nil, err | ||
return nil, fmt.Errorf("cannot load config: %w", err) | ||
} | ||
} else { | ||
config = &BuildConfig{} | ||
} | ||
|
||
if rootSSHKey != "" { | ||
config.Blueprint = &blueprint.Blueprint{ | ||
Customizations: &blueprint.Customizations{ | ||
User: []blueprint.UserCustomization{ | ||
{Name: "root", Key: &rootSSHKey}, | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
manifestConfig := &ManifestConfig{ | ||
Architecture: buildArch, | ||
Config: config, | ||
|
@@ -338,7 +356,7 @@ func cmdBuild(cmd *cobra.Command, args []string) error { | |
fmt.Printf("Generating manifest %s\n", manifest_fname) | ||
mf, err := manifestFromCobra(cmd, args) | ||
if err != nil { | ||
panic(err) | ||
return err | ||
} | ||
fmt.Print("DONE\n") | ||
|
||
|
@@ -455,11 +473,13 @@ func run() error { | |
} | ||
rootCmd.AddCommand(manifestCmd) | ||
manifestCmd.Flags().Bool("tls-verify", true, "require HTTPS and verify certificates when contacting registries") | ||
manifestCmd.Flags().String("config", "", "build config file") | ||
manifestCmd.Flags().String("iso-config", "", "build config file for the iso") | ||
manifestCmd.Flags().String("rpmmd", "/rpmmd", "rpm metadata cache directory") | ||
manifestCmd.Flags().String("target-arch", "", "build for the given target architecture (experimental)") | ||
manifestCmd.Flags().StringArray("type", []string{"qcow2"}, fmt.Sprintf("image types to build [%s]", allImageTypesString())) | ||
manifestCmd.Flags().Bool("local", false, "use a local container rather than a container from a registry") | ||
// XXX: hide from help? | ||
manifestCmd.Flags().String("experimental-root-ssh-authorized-key", "", "authorized ssh key for root as string") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not opposed to this, but the more I've been thinking about this (you probably saw) the more I feel we need to build up the story of using blueprints/kickstarts in container builds and align that with disk image generation and not emphasize one-offs like this. And yes I know I added it to bootc install, but the use case is different there in a way because the bootc install is really low level and I was thinking of it more like a generic low level escape hatch. But here we can be more opinionated I think. |
||
|
||
logrus.SetLevel(logrus.ErrorLevel) | ||
buildCmd.Flags().AddFlagSet(manifestCmd.Flags()) | ||
|
@@ -477,7 +497,7 @@ func run() error { | |
return err | ||
} | ||
} | ||
if err := buildCmd.MarkFlagFilename("config"); err != nil { | ||
if err := buildCmd.MarkFlagFilename("iso-config"); err != nil { | ||
return err | ||
} | ||
buildCmd.MarkFlagsRequiredTogether("aws-region", "aws-bucket", "aws-ami-name") | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The thing is this is used elsewhere so I think we may be partially committed short term.
(There is some things related to this, like the fact I don't quite understand why it's JSON and not TOML as seems would be expected for blueprints, but that's an aside)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No real (good) reason other than the initial version BIB was heavily based on https://github.com/osbuild/images/blob/main/cmd/build/main.go, which is used for test image builds and it was simpler to use the json formatting for config files.
Since we're moving towards making it more explicit that this config is an instance of an Image Builder blueprint, I agree that we should make it a toml to make the connection clearer.