From 96c47ad0b8c95e6f6401d2a479c3444bb7b6415e Mon Sep 17 00:00:00 2001 From: Bruce Ashfield Date: Fri, 7 May 2021 12:16:41 -0400 Subject: oci-images: create backend .inc files As part of allowing different types of oci images to be created, we split our IMG_cmd into .inc files that can then be specific to the selected type. For the umoci backend: We can take the same options as sloci expects and use umoci to create images. The resulting OCI image is similar, but by using umoci, we set the stage to do multi-tag, or multi-layer images in the future. But for now, we are functionally equivalent to the sloci backend. Signed-off-by: Bruce Ashfield --- classes/image-oci-sloci-image.inc | 67 +++++++++++++++++++++++ classes/image-oci-umoci.inc | 111 ++++++++++++++++++++++++++++++++++++++ classes/image-oci.bbclass | 84 ++++++----------------------- 3 files changed, 195 insertions(+), 67 deletions(-) create mode 100644 classes/image-oci-sloci-image.inc create mode 100644 classes/image-oci-umoci.inc (limited to 'classes') diff --git a/classes/image-oci-sloci-image.inc b/classes/image-oci-sloci-image.inc new file mode 100644 index 00000000..36d3c2da --- /dev/null +++ b/classes/image-oci-sloci-image.inc @@ -0,0 +1,67 @@ +IMAGE_CMD_oci() { + sloci_options="" + + bbdebug 1 "OCI image settings:" + bbdebug 1 " author: ${OCI_IMAGE_AUTHOR}" + bbdebug 1 " author email: ${OCI_IMAGE_AUTHOR_EMAIL}" + bbdebug 1 " tag: ${OCI_IMAGE_TAG}" + bbdebug 1 " arch: ${OCI_IMAGE_ARCH}" + bbdebug 1 " subarch: ${OCI_IMAGE_SUBARCH}" + bbdebug 1 " entrypoint: ${OCI_IMAGE_ENTRYPOINT}" + bbdebug 1 " entrypoing args: ${OCI_IMAGE_ENTRYPOINT_ARGS}" + bbdebug 1 " labels: ${OCI_IMAGE_LABELS}" + bbdebug 1 " uid: ${OCI_IMAGE_RUNTIME_UID}" + bbdebug 1 " working dir: ${OCI_IMAGE_WORKINGDIR}" + bbdebug 1 " env vars: ${OCI_IMAGE_ENV_VARS}" + bbdebug 1 " ports: ${OCI_IMAGE_PORTS}" + + # Change into the image deploy dir to avoid having any output operations capture + # long directories or the location. + cd ${IMGDEPLOYDIR} + + oci_image_label_options="" + if [ -n "${OCI_IMAGE_LABELS}" ]; then + for l in ${OCI_IMAGE_LABELS}; do + oci_image_label_options="${oci_image_label_options} --label ${l}" + done + fi + oci_image_env_options="" + if [ -n "${OCI_IMAGE_ENV_VARS}" ]; then + for l in ${OCI_IMAGE_ENV_VARS}; do + oci_image_env_options="${oci_image_env_options} --env ${l}" + done + fi + oci_image_port_options="" + if [ -n "${OCI_IMAGE_PORTS}" ]; then + for l in ${OCI_IMAGE_PORTS}; do + oci_image_port_options="${oci_image_port_options} --port ${l}" + done + fi + + if [ -n "${OCI_IMAGE_RUNTIME_UID}" ]; then + oci_image_user_options="--user ${OCI_IMAGE_RUNTIME_UID}" + fi + + if [ -n "${OCI_IMAGE_WORKINGDIR}" ]; then + oci_image_working_dir_options="--working-dir ${OCI_IMAGE_WORKINGDIR}" + fi + + if [ -n "${OCI_IMAGE_TAR_OUTPUT}" ]; then + sloci_options="$sloci_options --tar" + fi + + # options that always appear are required for a valid oci container image + # others are optional based on settings. + sloci-image $sloci_options \ + --arch ${OCI_IMAGE_ARCH} \ + --arch-variant "${OCI_IMAGE_SUBARCH}" \ + --entrypoint ${OCI_IMAGE_ENTRYPOINT} \ + --cmd "${OCI_IMAGE_ENTRYPOINT_ARGS}" \ + --author ${OCI_IMAGE_AUTHOR_EMAIL} \ + ${oci_image_user_options} \ + ${oci_image_label_options} \ + ${oci_image_env_options} \ + ${oci_image_working_dir_options} \ + ${oci_image_port_options} \ + ${IMAGE_ROOTFS} ${IMAGE_NAME}${IMAGE_NAME_SUFFIX}-oci:${OCI_IMAGE_TAG} +} diff --git a/classes/image-oci-umoci.inc b/classes/image-oci-umoci.inc new file mode 100644 index 00000000..b622714e --- /dev/null +++ b/classes/image-oci-umoci.inc @@ -0,0 +1,111 @@ +IMAGE_CMD_oci() { + umoci_options="" + + bbdebug 1 "UMOCI image settings:" + bbdebug 1 " author: ${OCI_IMAGE_AUTHOR}" + bbdebug 1 " author email: ${OCI_IMAGE_AUTHOR_EMAIL}" + bbdebug 1 " tag: ${OCI_IMAGE_TAG}" + bbdebug 1 " arch: ${OCI_IMAGE_ARCH}" + bbdebug 1 " subarch: ${OCI_IMAGE_SUBARCH}" + bbdebug 1 " entrypoint: ${OCI_IMAGE_ENTRYPOINT}" + bbdebug 1 " entrypoint args: ${OCI_IMAGE_ENTRYPOINT_ARGS}" + bbdebug 1 " labels: ${OCI_IMAGE_LABELS}" + bbdebug 1 " uid: ${OCI_IMAGE_RUNTIME_UID}" + bbdebug 1 " working dir: ${OCI_IMAGE_WORKINGDIR}" + bbdebug 1 " env vars: ${OCI_IMAGE_ENV_VARS}" + bbdebug 1 " ports: ${OCI_IMAGE_PORTS}" + + OCI_REUSE_IMAGE="" + + # Change into the image deploy dir to avoid having any output operations capture + # long directories or the location. + cd ${IMGDEPLOYDIR} + + new_image=t + image_name="${IMAGE_NAME}${IMAGE_NAME_SUFFIX}-oci" + image_bundle_name="${IMAGE_NAME}${IMAGE_NAME_SUFFIX}-oci-bundle" + if [ -n "$OCI_REUSE_IMAGE" ]; then + if [ -d $image_name ]; then + bbdebug 1 "OCI: reusing image directory" + new_image="" + fi + else + bbdebug 1 "OCI: removing existing container image directory" + rm -rf $image_name $image_bundle_name + fi + + if [ -z "${OCI_IMAGE_TAG}" ]; then + OCI_IMAGE_TAG="initial-tag" + fi + + if [ -n "$new_image" ]; then + bbdebug 1 "OCI: umoci init --layout $image_name" + umoci init --layout $image_name + umoci new --image $image_name:${OCI_IMAGE_TAG} + umoci unpack --rootless --image $image_name:${OCI_IMAGE_TAG} $image_bundle_name + else + # todo: create a different tag, after checking if the passed one exists + true + fi + + bbdebug 1 "OCI: populating rootfs" + bbdebug 1 "OCI: cp -r ${IMAGE_ROOTFS}/* $image_bundle_name/rootfs/" + cp -r ${IMAGE_ROOTFS}/* $image_bundle_name/rootfs + + bbdebug 1 "OCI: umoci repack --image $image_name:${OCI_IMAGE_TAG} $image_bundle_name" + umoci repack --image $image_name:${OCI_IMAGE_TAG} $image_bundle_name + + bbdebug 1 "OCI: configuring image" + if [ -n "${OCI_IMAGE_LABELS}" ]; then + for l in ${OCI_IMAGE_LABELS}; do + bbdebug 1 "OCI: umoci config --image $image_name --config.label $l" + umoci config --image $image_name --config.label $l + done + fi + if [ -n "${OCI_IMAGE_ENV_VARS}" ]; then + for l in ${OCI_IMAGE_ENV_VARS}; do + bbdebug 1 "umoci config --image $image_name --config.env $l" + umoci config --image $image_name --config.env $l + done + fi + if [ -n "${OCI_IMAGE_PORTS}" ]; then + for l in ${OCI_IMAGE_PORTS}; do + bbdebug 1 "umoci config --image $image_name --config.exposedports $l" + umoci config --image $image_name --config.exposedports $l + done + fi + if [ -n "${OCI_IMAGE_RUNTIME_UID}" ]; then + bbdebug 1 "umoci config --image $image_name --config.user ${OCI_IMAGE_RUNTIME_UID}" + umoci config --image $image_name --config.user ${OCI_IMAGE_RUNTIME_UID} + fi + if [ -n "${OCI_IMAGE_WORKINGDIR}" ]; then + bbdebug 1 "umoci config --image $image_name --config.workingdir ${OCI_IMAGE_WORKINGDIR}" + umoci config --image $image_name --config.workingdir ${OCI_IMAGE_WORKINGDIR} + fi + if [ -n "${OCI_IMAGE_OS}" ]; then + bbdebug 1 "umoci config --image $image_name --os ${OCI_IMAGE_OS}" + umoci config --image $image_name --os ${OCI_IMAGE_OS} + fi + + bbdebug 1 "umoci config --image $image_name --architecture ${OCI_IMAGE_ARCH}" + umoci config --image $image_name --architecture ${OCI_IMAGE_ARCH} + # NOTE: umoci doesn't currently expose setting the architecture variant, + # so if you need it use sloci instead + if [ -n "${OCI_IMAGE_SUBARCH}" ]; then + bbnote "OCI: image subarch is set to: ${OCI_IMAGE_SUBARCH}, but umoci does not" + bbnote " expose variants. use sloci instead if this is important" + fi + umoci config --image $image_name --config.entrypoint ${OCI_IMAGE_ENTRYPOINT} + if [ -n "${OCI_IMAGE_ENTRYPOINT_ARGS}" ]; then + umoci config --image $image_name --config.cmd "${OCI_IMAGE_ENTRYPOINT_ARGS}" + fi + umoci config --image $image_name --author ${OCI_IMAGE_AUTHOR_EMAIL} + + # make a tar version of the image direcotry + if [ -n "${OCI_IMAGE_TAR_OUTPUT}" ]; then + tar -cf "$image_name.tar" "$image_name" + fi + + # We could make this optional, since the bundle is directly runnable via runc + rm -rf $image_bundle_name +} diff --git a/classes/image-oci.bbclass b/classes/image-oci.bbclass index c256b12c..464ea3b4 100644 --- a/classes/image-oci.bbclass +++ b/classes/image-oci.bbclass @@ -16,19 +16,32 @@ # And then create the bundle: # % oci-image-tool create --ref name=latest container-base--.rootfs-oci container-base-oci-bundle # +# Alternatively, the bundle can be created with umoci (use --rootless if sudo is not available) +# % sudo umoci unpack --image container-base--.rootfs-oci:latest container-base-oci-bundle +# # Or to copy (push) the oci image to a docker registry, skopeo can be used (vary the # tag based on the created oci image: # # % skopeo copy --dest-creds : oci:container-base--:latest docker://zeddii/container-base # +# If your build host architecture matches the target, you can execute the unbundled +# container with runc: +# +# % sudo runc run -b container-base-oci-bundle ctr-build +# / % uname -a +# Linux mrsdalloway 4.18.0-25-generic #26-Ubuntu SMP Mon Jun 24 09:32:08 UTC 2019 x86_64 GNU/Linux +# # We'd probably get this through the container image typdep, but just # to be sure, we'll repeat it here. ROOTFS_BOOTSTRAP_INSTALL = "" # we want container and tar.bz2's to be created IMAGE_TYPEDEP_oci = "container tar.bz2" + # sloci is the script/project that will create the oci image -do_image_oci[depends] += "sloci-image-native:do_populate_sysroot" +# OCI_IMAGE_BACKEND ?= "sloci-image" +OCI_IMAGE_BACKEND ?= "umoci" +do_image_oci[depends] += "${OCI_IMAGE_BACKEND}-native:do_populate_sysroot" # # image type configuration block @@ -75,70 +88,7 @@ def oci_map_subarch(a, f, d): return '' return '' -IMAGE_CMD_oci() { - sloci_options="" - - bbdebug 1 "OCI image settings:" - bbdebug 1 " author: ${OCI_IMAGE_AUTHOR}" - bbdebug 1 " author email: ${OCI_IMAGE_AUTHOR_EMAIL}" - bbdebug 1 " tag: ${OCI_IMAGE_TAG}" - bbdebug 1 " arch: ${OCI_IMAGE_ARCH}" - bbdebug 1 " subarch: ${OCI_IMAGE_SUBARCH}" - bbdebug 1 " entrypoint: ${OCI_IMAGE_ENTRYPOINT}" - bbdebug 1 " entrypoing args: ${OCI_IMAGE_ENTRYPOINT_ARGS}" - bbdebug 1 " labels: ${OCI_IMAGE_LABELS}" - bbdebug 1 " uid: ${OCI_IMAGE_RUNTIME_UID}" - bbdebug 1 " working dir: ${OCI_IMAGE_WORKINGDIR}" - bbdebug 1 " env vars: ${OCI_IMAGE_ENV_VARS}" - bbdebug 1 " ports: ${OCI_IMAGE_PORTS}" - - # Change into the image deploy dir to avoid having any output operations capture - # long directories or the location. - cd ${IMGDEPLOYDIR} - - oci_image_label_options="" - if [ -n "${OCI_IMAGE_LABELS}" ]; then - for l in ${OCI_IMAGE_LABELS}; do - oci_image_label_options="${oci_image_label_options} --label ${l}" - done - fi - oci_image_env_options="" - if [ -n "${OCI_IMAGE_ENV_VARS}" ]; then - for l in ${OCI_IMAGE_ENV_VARS}; do - oci_image_env_options="${oci_image_env_options} --env ${l}" - done - fi - oci_image_port_options="" - if [ -n "${OCI_IMAGE_PORTS}" ]; then - for l in ${OCI_IMAGE_PORTS}; do - oci_image_port_options="${oci_image_port_options} --port ${l}" - done - fi - - if [ -n "${OCI_IMAGE_RUNTIME_UID}" ]; then - oci_image_user_options="--user ${OCI_IMAGE_RUNTIME_UID}" - fi - - if [ -n "${OCI_IMAGE_WORKINGDIR}" ]; then - oci_image_working_dir_options="--working-dir ${OCI_IMAGE_WORKINGDIR}" - fi - - if [ -n "${OCI_IMAGE_TAR_OUTPUT}" ]; then - sloci_options="$sloci_options --tar" - fi +# the IMAGE_CMD_oci comes from the .inc +OCI_IMAGE_BACKEND_INC ?= "${@"image-oci-" + "${OCI_IMAGE_BACKEND}" + ".inc"}" +include ${OCI_IMAGE_BACKEND_INC} - # options that always appear are required for a valid oci container image - # others are optional based on settings. - sloci-image $sloci_options \ - --arch ${OCI_IMAGE_ARCH} \ - --arch-variant "${OCI_IMAGE_SUBARCH}" \ - --entrypoint ${OCI_IMAGE_ENTRYPOINT} \ - --cmd "${OCI_IMAGE_ENTRYPOINT_ARGS}" \ - --author ${OCI_IMAGE_AUTHOR_EMAIL} \ - ${oci_image_user_options} \ - ${oci_image_label_options} \ - ${oci_image_env_options} \ - ${oci_image_working_dir_options} \ - ${oci_image_port_options} \ - ${IMAGE_ROOTFS} ${IMAGE_NAME}${IMAGE_NAME_SUFFIX}-oci:${OCI_IMAGE_TAG} -} -- cgit v1.2.3-54-g00ecf