|
Some checks failed
ci / path-filter (push) Has been cancelled
ci / Validate source code changes (push) Has been cancelled
ci / Cross Build (Linux, FreeBSD) (push) Has been cancelled
ci / build debian-sid (push) Has been cancelled
ci / build fedora-current (push) Has been cancelled
ci / build fedora-prior (push) Has been cancelled
ci / build fedora-rawhide (push) Has been cancelled
ci / windows installer hyperv (push) Has been cancelled
ci / windows installer wsl (push) Has been cancelled
ci / macos installer (push) Has been cancelled
zizmor: GitHub Actions Security Analysis / Zizmor (push) Has been cancelled
ci / int local root debian-sid (push) Has been cancelled
ci / sys local root debian-sid (push) Has been cancelled
ci / int local rootless debian-sid (push) Has been cancelled
ci / sys local rootless debian-sid (push) Has been cancelled
ci / int remote root debian-sid (push) Has been cancelled
ci / sys remote root debian-sid (push) Has been cancelled
ci / bud local root fedora-current (push) Has been cancelled
ci / int local root fedora-current (push) Has been cancelled
ci / sys local root fedora-current (push) Has been cancelled
ci / int local rootless fedora-current (push) Has been cancelled
ci / sys local rootless fedora-current (push) Has been cancelled
ci / bud remote root fedora-current (push) Has been cancelled
ci / int remote root fedora-current (push) Has been cancelled
ci / sys remote root fedora-current (push) Has been cancelled
ci / int remote rootless fedora-current (push) Has been cancelled
ci / sys remote rootless fedora-current (push) Has been cancelled
ci / int local root fedora-prior (push) Has been cancelled
ci / sys local root fedora-prior (push) Has been cancelled
ci / int local rootless fedora-prior (push) Has been cancelled
ci / sys local rootless fedora-prior (push) Has been cancelled
ci / int remote root fedora-prior (push) Has been cancelled
ci / sys remote root fedora-prior (push) Has been cancelled
ci / int local root fedora-rawhide (push) Has been cancelled
ci / sys local root fedora-rawhide (push) Has been cancelled
ci / int local rootless fedora-rawhide (push) Has been cancelled
ci / sys local rootless fedora-rawhide (push) Has been cancelled
ci / int remote root fedora-rawhide (push) Has been cancelled
ci / sys remote root fedora-rawhide (push) Has been cancelled
ci / apiv2 root fedora-current (push) Has been cancelled
ci / bindings root fedora-current (push) Has been cancelled
ci / compose_v2 root fedora-current (push) Has been cancelled
ci / docker_py root fedora-current (push) Has been cancelled
ci / unit root fedora-current (push) Has been cancelled
ci / apiv2 rootless fedora-current (push) Has been cancelled
ci / compose_v2 rootless fedora-current (push) Has been cancelled
ci / unit rootless fedora-current (push) Has been cancelled
ci / upgrade v5.3.1 root fedora-current (push) Has been cancelled
ci / upgrade v5.6.2 root fedora-current (push) Has been cancelled
ci / machine linux amd64 (push) Has been cancelled
ci / windows unit (push) Has been cancelled
ci / windows e2e (push) Has been cancelled
ci / windows machine hyperv (push) Has been cancelled
ci / windows machine wsl (push) Has been cancelled
ci / macos machine applehv (push) Has been cancelled
ci / macos machine libkrun (push) Has been cancelled
ci / Total Success (push) Has been cancelled
build: pass ignore file to buildah to consider empty ignore files |
||
|---|---|---|
| .. | ||
| artifact | ||
| common | ||
| completion | ||
| containers | ||
| diff | ||
| farm | ||
| generate | ||
| healthcheck | ||
| images | ||
| inspect | ||
| kube | ||
| machine | ||
| manifest | ||
| networks | ||
| parse | ||
| pods | ||
| quadlet | ||
| registry | ||
| secrets | ||
| system | ||
| utils | ||
| validate | ||
| volumes | ||
| auto-update.go | ||
| client.go | ||
| client_supported.go | ||
| client_unsupported.go | ||
| compose.go | ||
| compose_machine.go | ||
| compose_machine_unix.go | ||
| compose_machine_unsupported.go | ||
| compose_machine_windows.go | ||
| diff.go | ||
| early_init_darwin.go | ||
| early_init_linux.go | ||
| early_init_unsupported.go | ||
| inspect.go | ||
| login.go | ||
| logout.go | ||
| main.go | ||
| README.md | ||
| root.go | ||
| root_cgroups_linux.go | ||
| root_cgroups_unsupported.go | ||
| root_test.go | ||
| shell_completion_test.go | ||
| syslog_common.go | ||
| syslog_unsupported.go | ||
Podman CLI
The following is an example of how to add a new primary command (manifest) and a sub-command (inspect) to the Podman CLI.
This is example code, the production code has additional error checking and the business logic provided.
See items below for details on building, installing, contributing to Podman:
Adding a new command podman manifest
$ mkdir -p $GOPATH/src/github.com/containers/podman/cmd/podman/manifest
Create the file $GOPATH/src/github.com/containers/podman/cmd/podman/manifest/manifest.go
package manifest
import (
"go.podman.io/podman/v6/cmd/podman/registry"
"go.podman.io/podman/v6/cmd/podman/validate"
"go.podman.io/podman/v6/pkg/domain/entities"
"github.com/spf13/cobra"
)
var (
// podman _manifests_
manifestCmd = &cobra.Command{
Use: "manifest",
Short: "Manage manifests",
Args: cobra.ExactArgs(1),
Long: "Manage manifests",
Example: "podman manifest IMAGE",
TraverseChildren: true,
RunE: validate.SubCommandExists, // Report error if there is no sub command given
}
)
func init() {
// Subscribe command to podman
registry.Commands = append(registry.Commands, registry.CliCommand{
Command: manifestCmd,
})
}
To "wire" in the manifest command, edit the file $GOPATH/src/github.com/containers/podman/cmd/podman/main.go to add:
package main
import _ "go.podman.io/podman/v6/cmd/podman/manifest"
Adding a new sub command podman manifest list
Create the file $GOPATH/src/github.com/containers/podman/cmd/podman/manifest/inspect.go
package manifest
import (
"go.podman.io/podman/v6/cmd/podman/registry"
"go.podman.io/podman/v6/pkg/domain/entities"
"github.com/spf13/cobra"
)
var (
// podman manifests _inspect_
inspectCmd = &cobra.Command{
Use: "inspect IMAGE",
Short: "Display manifest from image",
Long: "Displays the low-level information on a manifest identified by image name or ID",
RunE: inspect,
Annotations: map[string]string{
// Add this annotation if this command cannot be run rootless
// registry.ParentNSRequired: "",
},
Example: "podman manifest inspect DEADBEEF",
}
)
func init() {
// Subscribe inspect sub command to manifest command
registry.Commands = append(registry.Commands, registry.CliCommand{
Command: inspectCmd,
// The parent command to proceed this command on the CLI
Parent: manifestCmd,
})
// This is where you would configure the cobra flags using inspectCmd.Flags()
}
// Business logic: cmd is inspectCmd, args is the positional arguments from os.Args
func inspect(cmd *cobra.Command, args []string) error {
// Business logic using registry.ImageEngine()
// Do not pull from libpod directly use the domain objects and types
return nil
}
Helper functions
The complete set can be found in the validate package, here are some examples:
cobra.Command{ Args: validate.NoArgs }used when the command does not accept errorscobra.Command{ Args: validate.IdOrLatestArgs }used to ensure either a list of ids given or the --latest flagcobra.Command{ RunE: validate.SubCommandExists }used to validate a subcommand given to a commandvalidate.ChoiceValueused to create apflag.Valuethat validate user input against a provided slice of values. For example:flags := cobraCommand.Flags() created := validate.ChoiceValue(&opts.Sort, "command", "created", "id", "image", "names", "runningfor", "size", "status") flags.Var(created, "sort", "Sort output by: "+created.Choices())
Adding CLI flags
When adding a new cli option that accepts a string array, there are two options to choose from: StringSlice() and StringArray().
They differ slightly in their behavior: StringSlice() allows the values to be comma separated so --opt v1,v2 --opt v3 results in
[]string{"v1", "v2", "v3"}, while StringArray() would result in []string{"v1,v2", "v3"}. Thus it is impossible to use values with comma in StringSlice(), which makes it unsuitable for flags that accept arbitrary values such as file paths as example. Also, because StringSlice() uses the csv lib to parse the values, it has special escaping rules for things like quotes, see https://github.com/containers/podman/issues/20064 for an example of how complicated things can get because of this.
Thus use StringSlice() only when the option accepts predefined values that do not contain special characters, for example --cap-add and --cap-drop are a good example for this. Using --cap-add NET_ADMIN,NET_RAW is equal to --cap-add NET_ADMIN --cap-add NET_RAW so it is better suited to save some typing for users.
When in doubt always choose StringArray() over StringSlice().