diff --git a/completion/bash/toolbox b/completion/bash/toolbox index b25d8dd..6ae1318 100644 --- a/completion/bash/toolbox +++ b/completion/bash/toolbox @@ -5,6 +5,10 @@ __toolbox_containers() { podman ps --all --format '{{.Names}}' } +__toolbox_distros() { + echo "fedora" +} + __toolbox_images() { podman images --format '{{.Repository}}:{{.Tag}}' } @@ -16,14 +20,14 @@ __toolbox() { local commands="create enter help init-container list reset rm rmi run" declare -A options - local options=([create]="--container --image --release" \ - [enter]="--container --release" \ + local options=([create]="--container --distro --image --release" \ + [enter]="--container --distro --release" \ [help]="$commands" \ [init-container]="--home --home-link --monitor-host --shell --uid --user" \ [list]="--containers --images" \ [rm]="--all --force" \ [rmi]="--all --force" \ - [run]="--container --release") + [run]="--container --distro --release") _init_completion -s || return @@ -41,6 +45,10 @@ __toolbox() { mapfile -t COMPREPLY < <(compgen -W "$(__toolbox_containers)" -- "$2") return 0 ;; + --distro | -d) + mapfile -t COMPREPLY < <(compgen -W "$(__toolbox_distros)" -- "$2") + return 0 + ;; --image | -i) mapfile -t COMPREPLY < <(compgen -W "$(__toolbox_images)" -- "$2") return 0 diff --git a/doc/toolbox-create.1.md b/doc/toolbox-create.1.md index 0c7908b..3ce3358 100644 --- a/doc/toolbox-create.1.md +++ b/doc/toolbox-create.1.md @@ -5,6 +5,7 @@ toolbox\-create - Create a new toolbox container ## SYNOPSIS **toolbox create** [*--container NAME* | *-c NAME*] + [*--distro DISTRO* | *-d DISTRO*] [*--image NAME* | *-i NAME*] [*--release RELEASE* | *-r RELEASE*] @@ -15,9 +16,10 @@ to interact with the container at any point. A toolbox container is an OCI container created from an OCI image. On Fedora the base image is known as `fedora-toolbox`. If the image is not present -locally, then it is pulled from `registry.fedoraproject.org`. The base image is -locally customized for the current user to create a second image, from which -the container is finally created. +locally, then it is pulled from a well-known registry like +`registry.fedoraproject.org`. The base image is locally customized for the +current user to create a second image, from which the container is finally +created. Toolbox containers and images are tagged with the version of the OS that corresponds to the content inside them. The user-specific images and the @@ -34,6 +36,11 @@ Assign a different NAME to the toolbox container. This is useful for creating multiple toolbox containers from the same base image, or for entirely customized containers from custom-built base images. +**--distro** DISTRO, **-d** DISTRO + +Create a toolbox container for a different operating system DISTRO than the +host. Cannot be used with `--image`. + **--image** NAME, **-i** NAME Change the NAME of the base image used to create the toolbox container. This @@ -56,7 +63,7 @@ $ toolbox create ### Create a toolbox container using the default image for Fedora 30 ``` -$ toolbox create --release f30 +$ toolbox create --distro fedora --release f30 ``` ### Create a custom toolbox container from a custom image diff --git a/doc/toolbox-enter.1.md b/doc/toolbox-enter.1.md index e2c63e0..73dc5ac 100644 --- a/doc/toolbox-enter.1.md +++ b/doc/toolbox-enter.1.md @@ -5,6 +5,7 @@ toolbox\-enter - Enter a toolbox container for interactive use ## SYNOPSIS **toolbox enter** [*--container NAME* | *-c NAME*] + [*--distro DISTRO* | *-d DISTRO*] [*--release RELEASE* | *-r RELEASE*] ## DESCRIPTION @@ -18,7 +19,7 @@ fall back to it, even if it doesn't match the default name. A toolbox container is an OCI container. Therefore, `toolbox enter` is analogous to a `podman start` followed by a `podman exec`. -On Fedora the toolbox containers are tagged with the version of the OS that +By default, the toolbox containers are tagged with the version of the OS that corresponds to the content inside them. Their names are prefixed with the name of the base image and suffixed with the current user name. @@ -32,6 +33,11 @@ Enter a toolbox container with the given NAME. This is useful when there are multiple toolbox containers created from the same base image, or entirely customized containers created from custom-built base images. +**--distro** DISTRO, **-d** DISTRO + +Enter a toolbox container for a different operating system DISTRO than the +host. + **--release** RELEASE, **-r** RELEASE Enter a toolbox container for a different operating system RELEASE than the @@ -48,7 +54,7 @@ $ toolbox enter ### Enter a toolbox container using the default image for Fedora 30 ``` -$ toolbox enter --release f30 +$ toolbox enter --distro fedora --release f30 ``` ### Enter a custom toolbox container using a custom image diff --git a/doc/toolbox-run.1.md b/doc/toolbox-run.1.md index 4786e8f..ca00cc1 100644 --- a/doc/toolbox-run.1.md +++ b/doc/toolbox-run.1.md @@ -5,6 +5,7 @@ toolbox\-run - Run a command in an existing toolbox container ## SYNOPSIS **toolbox run** [*--container NAME* | *-c NAME*] + [*--distro DISTRO* | *-d DISTRO*] [*--release RELEASE* | *-r RELEASE*] [*COMMAND*] ## DESCRIPTION @@ -15,7 +16,7 @@ been created using the `toolbox create` command. A toolbox container is an OCI container. Therefore, `toolbox run` is analogous to a `podman start` followed by a `podman exec`. -On Fedora the toolbox containers are tagged with the version of the OS that +By default, the toolbox containers are tagged with the version of the OS that corresponds to the content inside them. Their names are prefixed with the name of the base image and suffixed with the current user name. @@ -29,6 +30,11 @@ Run command inside a toolbox container with the given NAME. This is useful when there are multiple toolbox containers created from the same base image, or entirely customized containers created from custom-built base images. +**--distro** DISTRO, **-d** DISTRO + +Run command inside a toolbox container for a different operating system DISTRO +than the host. + **--release** RELEASE, **-r** RELEASE Run command inside a toolbox container for a different operating system @@ -45,7 +51,7 @@ $ toolbox run ls -la ### Run emacs inside a toolbox container using the default image for Fedora 30 ``` -$ toolbox run --release f30 emacs +$ toolbox run --distro fedora --release f30 emacs ``` ### Run uptime inside a custom toolbox container using a custom image diff --git a/src/cmd/create.go b/src/cmd/create.go index 470127e..74e90b1 100644 --- a/src/cmd/create.go +++ b/src/cmd/create.go @@ -43,6 +43,7 @@ const ( var ( createFlags struct { container string + distro string image string release string } @@ -71,6 +72,12 @@ func init() { "", "Assign a different name to the toolbox container") + flags.StringVarP(&createFlags.distro, + "distro", + "d", + "", + "Create a toolbox container for a different operating system distribution than the host") + flags.StringVarP(&createFlags.image, "image", "i", @@ -100,6 +107,10 @@ func create(cmd *cobra.Command, args []string) error { return nil } + if cmd.Flag("distro").Changed && cmd.Flag("image").Changed { + return errors.New("options --distro and --image cannot be used together") + } + if cmd.Flag("image").Changed && cmd.Flag("release").Changed { return errors.New("options --image and --release cannot be used together") } @@ -130,7 +141,7 @@ func create(cmd *cobra.Command, args []string) error { var release string if createFlags.release != "" { var err error - release, err = utils.ParseRelease("", createFlags.release) + release, err = utils.ParseRelease(createFlags.distro, createFlags.release) if err != nil { err := utils.CreateErrorInvalidRelease(executableBase) return err @@ -138,7 +149,7 @@ func create(cmd *cobra.Command, args []string) error { } container, image, release, err := utils.ResolveContainerAndImageNames(container, - "", + createFlags.distro, createFlags.image, release) if err != nil { diff --git a/src/cmd/enter.go b/src/cmd/enter.go index 5e224ba..43b630c 100644 --- a/src/cmd/enter.go +++ b/src/cmd/enter.go @@ -29,6 +29,7 @@ import ( var ( enterFlags struct { container string + distro string release string } ) @@ -48,6 +49,12 @@ func init() { "", "Enter a toolbox container with the given name") + flags.StringVarP(&enterFlags.distro, + "distro", + "d", + "", + "Enter a toolbox container for a different operating system distribution than the host") + flags.StringVarP(&enterFlags.release, "release", "r", @@ -102,14 +109,14 @@ func enter(cmd *cobra.Command, args []string) error { nonDefaultContainer = true var err error - release, err = utils.ParseRelease("", enterFlags.release) + release, err = utils.ParseRelease(enterFlags.distro, enterFlags.release) if err != nil { err := utils.CreateErrorInvalidRelease(executableBase) return err } } - container, image, release, err := utils.ResolveContainerAndImageNames(container, "", "", release) + container, image, release, err := utils.ResolveContainerAndImageNames(container, enterFlags.distro, "", release) if err != nil { return err } diff --git a/src/cmd/run.go b/src/cmd/run.go index 6ea63dd..82356dc 100644 --- a/src/cmd/run.go +++ b/src/cmd/run.go @@ -33,6 +33,7 @@ import ( var ( runFlags struct { container string + distro string release string } ) @@ -53,6 +54,12 @@ func init() { "", "Run command inside a toolbox container with the given name") + flags.StringVarP(&runFlags.distro, + "distro", + "d", + "", + "Run command inside a toolbox container for a different operating system distribution than the host") + flags.StringVarP(&runFlags.release, "release", "r", @@ -97,7 +104,7 @@ func run(cmd *cobra.Command, args []string) error { nonDefaultContainer = true var err error - release, err = utils.ParseRelease("", runFlags.release) + release, err = utils.ParseRelease(runFlags.distro, runFlags.release) if err != nil { err := utils.CreateErrorInvalidRelease(executableBase) return err @@ -115,7 +122,7 @@ func run(cmd *cobra.Command, args []string) error { command := args - container, image, release, err := utils.ResolveContainerAndImageNames(runFlags.container, "", "", release) + container, image, release, err := utils.ResolveContainerAndImageNames(runFlags.container, runFlags.distro, "", release) if err != nil { return err } diff --git a/src/pkg/utils/utils.go b/src/pkg/utils/utils.go index 7cc52f1..16a835c 100644 --- a/src/pkg/utils/utils.go +++ b/src/pkg/utils/utils.go @@ -676,6 +676,10 @@ func ResolveContainerAndImageNames(container, distro, image, release string) (st distro = distroDefault } + if distro != distroDefault && release == "" { + return "", "", "", fmt.Errorf("release not found for non-default distribution %s", distro) + } + if release == "" { release = releaseDefault }