cmds
Useful cmds
The following utilities, defined in the cmd/
directory, are useful for
development and testing. They should not be relied on for production
purposes. In particular, command line options and default behavior can change
at any time.
The following are high level descriptions of what some of the utilities can do and how they can be used during development. For specific flags and options, refer to each command's help output and doc strings.
Each utility can be compiled using go build -o <outputfile> ./cmd/<utility>
or run directly using go run ./cmd/<utility>
. Use go run ./cmd/<utility> -help
for option descriptions (e.g. go run ./cmd/gen-manifests -help
).
Manifest generation
The gen-manifests
tool can be used to generate all or a subset of the
manifests for the images defined in the repository. This is useful for quickly
seeing the effects of changes in image definitions on the manifest and the
image build itself. While manifests are meant to be machine readable, it is
often much faster to inspect the difference between two manifests (before and
after a change in code) to evaluate if a change is having the desired effect.
Manifests can be generated with or without content resolution (e.g. package depsolving, containers, ostree commits). If you are working on changes in image definitions that do not rely on content (e.g. an image type's partition table), manifests without resolved content can be generated almost instantly. Note that even though content is not resolved and packages are not depsolved, the selected packages without their dependencies are still added to generated manifests, so disabling package depsolving can also be used to inspect package selection without dependencies.
Manifests should be generated with all content enabled if they are going to be built. A common workflow when working on changing image definitions, or adding a new image type, might be:
- Generate the manifests for the image types that you will be working on.
- Make changes in an existing image definition or add a new image type.
- Add appropriate configuration changes:
- If a new image type is added, add it to the config map under an appropriate configuration file or write a new one.
- If an existing image type is being modified, and the change depends on an image customization, make sure the modification is covered by an existing test config.
- Generate the relevant manifests without content (
-packages=false -containers=false -commits=false
).- If the change depends on a customization, it might be more useful to generate multiple manifests with different configuration options set and inspect the differences between them.
- Inspect the differences between manifests generated in steps 1 and 4.
- Generate manifest with all content enabled for the relevant image types.
- Build at least one of the manifests using
osuild
and inspect the output (boot the image or mount it to look for the desired changes).
NOTE: By default, manifests created with the gen-manifest
tool contain extra
metadata. The manifest itself is stored under the key "manifest". You can
extract the actual manifest using jq .manifest <manifestfile>.json
. Alternatively, you can generate manifests without
metadata using the -metadata=false
option.
Building images
You can build an image by generating its manifest and then running
osbuild. Alternatively, the cmd/build
tool can perform both steps in one
call. It will generate a manifest, build the image, and store both the image
and its manifest in the output directory.
The build tool must be run as root because image building with osbuild requires
superuser privileges. It is not recommended to run sudo go run ./cmd/build
however. The go run
command can make changes to the go build
cache and if these changes are made as root, it can cause issues when running
other go commands in the future as a regular user. Instead, it is recommended
to first build the binary and then run it as root:
go build -o bin/build ./cmd/build
sudo ./bin/build ...
Booting images
You can boot an image in its target environment by using the appropriate
command from cmd/
. Currently, only AWS is supported.
For example, to boot an AMI or EC2 image, you can use the ./cmd/boot-aws
command with the setup
subcommand:
go run ./cmd/boot-aws setup \
--access-key-id "${AWS_ACCESS_KEY_ID}" \
--secret-access-key "${AWS_SECRET_ACCESS_KEY}" \
--region "${AWS_REGION}" \
--bucket "${AWS_BUCKET}" \
--ami-name "${IMAGE_NAME}" \
--s3-key "${IMAGE_KEY}" \
--username "${USERNAME}" \
--arch "${IMAGE_ARCHITECTURE}" \
--ssh-pubkey "${PATH_TO_SSH_PUBLIC_KEY}" \
--ssh-privkey "${PATH_TO_SSH_PRIVATE_KEY}" \
--resourcefile ./aws-test-resources.json \
${PATH_TO_IMAGE_FILE}
where:
${AWS_ACCESS_KEY_ID}
and${AWS_SECRET_ACCESS_KEY}
are the AWS credentials,${AWS_REGION}
is the AWS region to use,${AWS_BUCKET}
is an S3 bucket (that must already exist),${IMAGE_NAME}
is the name to use for registering the AMI,${IMAGE_KEY}
is the key (filename) to use for the file in S3,${USERNAME}
is the username to set up on the instance,${IMAGE_ARCHITECTURE}
is the hardware architecture of the image being uploaded and booted,${PATH_TO_SSH_PUBLIC_KEY}
and${PATH_TO_SSH_PRIVATE_KEY}
point to an public/private SSH key pair.
This command will upload the image to S3, register the image as an AMI, create a security group configured to allow SSH access, and launch an instance from the AMI. It will then wait until the instance is ready and print its public IP address. It will also use the public ssh key and provided username to configure cloud-init to create a user and set the ssh key on first boot.
The IDs of all created resources are stored in the file specified by the
--resourcefile
flag. This can be used to tear down all the resources created
by the setup
subcommand:
go run ./cmd/boot-aws teardown \
--access-key-id "${AWS_ACCESS_KEY_ID}" \
--secret-access-key "${AWS_SECRET_ACCESS_KEY}" \
--region "${AWS_REGION}" \
--bucket "${AWS_BUCKET}" \
--name "${IMAGE_NAME}" \
--key "${IMAGE_KEY}" \
--username "${USERNAME}" \
--arch "${IMAGE_ARCHITECTURE}" \
--ssh-pubkey "${PATH_TO_SSH_PUBLIC_KEY}" \
--ssh-privkey "${PATH_TO_SSH_PRIVATE_KEY}" \
--resourcefile ./aws-test-resources.json
Alternatively, a setup-test-teardown procedure can be run in a single command using the run
subcommand:
go run ./cmd/boot-aws run \
--access-key-id "${AWS_ACCESS_KEY_ID}" \
--secret-access-key "${AWS_SECRET_ACCESS_KEY}" \
--region "${AWS_REGION}" \
--bucket "${AWS_BUCKET}" \
--ami-name "${IMAGE_NAME}" \
--s3-key "${IMAGE_KEY}" \
--username "${USERNAME}" \
--arch "${IMAGE_ARCHITECTURE}" \
--ssh-pubkey "${PATH_TO_SSH_PUBLIC_KEY}" \
--ssh-privkey "${PATH_TO_SSH_PRIVATE_KEY}" \
${PATH_TO_IMAGE_FILE} ${PATH_TO_SCRIPT}
This will perform the same steps as the setup
subcommand, then upload the
script specified by ${PATH_TO_SCRIPT}
to the instance, run it, and then
perform the same actions as the teardown
subcommand.
Listing available image type configurations
The cmd/list-images
utility simply lists all available combinations of
distribution, architecture, and image type. It also supports filtering one or
more of those three variables.