summaryrefslogtreecommitdiff
path: root/cmd/podmanV2
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/podmanV2')
-rw-r--r--cmd/podmanV2/containers/mount.go121
-rw-r--r--cmd/podmanV2/containers/unmount.go65
-rw-r--r--cmd/podmanV2/images/search.go157
3 files changed, 343 insertions, 0 deletions
diff --git a/cmd/podmanV2/containers/mount.go b/cmd/podmanV2/containers/mount.go
new file mode 100644
index 000000000..c2f5ae987
--- /dev/null
+++ b/cmd/podmanV2/containers/mount.go
@@ -0,0 +1,121 @@
+package containers
+
+import (
+ "encoding/json"
+ "fmt"
+ "os"
+ "text/tabwriter"
+ "text/template"
+
+ "github.com/containers/libpod/cmd/podmanV2/parse"
+ "github.com/containers/libpod/cmd/podmanV2/registry"
+ "github.com/containers/libpod/cmd/podmanV2/utils"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/spf13/cobra"
+)
+
+var (
+ mountDescription = `podman mount
+ Lists all mounted containers mount points if no container is specified
+
+ podman mount CONTAINER-NAME-OR-ID
+ Mounts the specified container and outputs the mountpoint
+`
+
+ mountCommand = &cobra.Command{
+ Use: "mount [flags] [CONTAINER]",
+ Short: "Mount a working container's root filesystem",
+ Long: mountDescription,
+ PreRunE: preRunE,
+ RunE: mount,
+ Args: func(cmd *cobra.Command, args []string) error {
+ return parse.CheckAllLatestAndCIDFile(cmd, args, true, false)
+ },
+ }
+)
+
+var (
+ mountOpts entities.ContainerMountOptions
+)
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode},
+ Command: mountCommand,
+ })
+ flags := mountCommand.Flags()
+ flags.BoolVarP(&mountOpts.All, "all", "a", false, "Mount all containers")
+ flags.StringVar(&mountOpts.Format, "format", "", "Change the output format to Go template")
+ flags.BoolVarP(&mountOpts.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
+ flags.BoolVar(&mountOpts.NoTruncate, "notruncate", false, "Do not truncate output")
+}
+
+func mount(cmd *cobra.Command, args []string) error {
+ var (
+ errs utils.OutputErrors
+ mrs []mountReporter
+ )
+ reports, err := registry.ContainerEngine().ContainerMount(registry.GetContext(), args, mountOpts)
+ if err != nil {
+ return err
+ }
+ if len(args) > 0 || mountOpts.Latest || mountOpts.All {
+ for _, r := range reports {
+ if r.Err == nil {
+ fmt.Println(r.Path)
+ continue
+ }
+ errs = append(errs, r.Err)
+ }
+ return errs.PrintErrors()
+ }
+ if mountOpts.Format == "json" {
+ return printJSON(reports)
+ }
+ for _, r := range reports {
+ mrs = append(mrs, mountReporter{r})
+ }
+ row := "{{.ID}} {{.Path}}"
+ format := "{{range . }}" + row + "{{end}}"
+ tmpl, err := template.New("mounts").Parse(format)
+ if err != nil {
+ return err
+ }
+ w := tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', 0)
+ defer w.Flush()
+ return tmpl.Execute(w, mrs)
+}
+
+func printJSON(reports []*entities.ContainerMountReport) error {
+ type jreport struct {
+ ID string `json:"id"`
+ Names []string
+ Mountpoint string `json:"mountpoint"`
+ }
+ var jreports []jreport
+
+ for _, r := range reports {
+ jreports = append(jreports, jreport{
+ ID: r.Id,
+ Names: []string{r.Name},
+ Mountpoint: r.Path,
+ })
+ }
+ b, err := json.MarshalIndent(jreports, "", " ")
+ if err != nil {
+ return err
+ }
+ fmt.Println(string(b))
+ return nil
+}
+
+type mountReporter struct {
+ *entities.ContainerMountReport
+}
+
+func (m mountReporter) ID() string {
+ if mountOpts.NoTruncate {
+ return m.Id
+ }
+ return m.Id[0:12]
+}
diff --git a/cmd/podmanV2/containers/unmount.go b/cmd/podmanV2/containers/unmount.go
new file mode 100644
index 000000000..2a6ef14b0
--- /dev/null
+++ b/cmd/podmanV2/containers/unmount.go
@@ -0,0 +1,65 @@
+package containers
+
+import (
+ "fmt"
+
+ "github.com/containers/libpod/cmd/podmanV2/parse"
+ "github.com/containers/libpod/cmd/podmanV2/registry"
+ "github.com/containers/libpod/cmd/podmanV2/utils"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/spf13/cobra"
+)
+
+var (
+ description = `Container storage increments a mount counter each time a container is mounted.
+
+ When a container is unmounted, the mount counter is decremented. The container's root filesystem is physically unmounted only when the mount counter reaches zero indicating no other processes are using the mount.
+
+ An unmount can be forced with the --force flag.
+`
+ umountCommand = &cobra.Command{
+ Use: "umount [flags] CONTAINER [CONTAINER...]",
+ Aliases: []string{"unmount"},
+ Short: "Unmounts working container's root filesystem",
+ Long: description,
+ RunE: unmount,
+ PreRunE: preRunE,
+ Args: func(cmd *cobra.Command, args []string) error {
+ return parse.CheckAllLatestAndCIDFile(cmd, args, false, false)
+ },
+ Example: `podman umount ctrID
+ podman umount ctrID1 ctrID2 ctrID3
+ podman umount --all`,
+ }
+)
+
+var (
+ unmountOpts entities.ContainerUnmountOptions
+)
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode},
+ Command: umountCommand,
+ })
+ flags := umountCommand.Flags()
+ flags.BoolVarP(&unmountOpts.All, "all", "a", false, "Umount all of the currently mounted containers")
+ flags.BoolVarP(&unmountOpts.Force, "force", "f", false, "Force the complete umount all of the currently mounted containers")
+ flags.BoolVarP(&unmountOpts.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
+}
+
+func unmount(cmd *cobra.Command, args []string) error {
+ var errs utils.OutputErrors
+ reports, err := registry.ContainerEngine().ContainerUnmount(registry.GetContext(), args, unmountOpts)
+ if err != nil {
+ return err
+ }
+ for _, r := range reports {
+ if r.Err == nil {
+ fmt.Println(r.Id)
+ } else {
+ errs = append(errs, r.Err)
+ }
+ }
+ return errs.PrintErrors()
+}
diff --git a/cmd/podmanV2/images/search.go b/cmd/podmanV2/images/search.go
new file mode 100644
index 000000000..2ab9735ec
--- /dev/null
+++ b/cmd/podmanV2/images/search.go
@@ -0,0 +1,157 @@
+package images
+
+import (
+ "reflect"
+ "strings"
+
+ buildahcli "github.com/containers/buildah/pkg/cli"
+ "github.com/containers/buildah/pkg/formats"
+ "github.com/containers/image/v5/types"
+ "github.com/containers/libpod/cmd/podmanV2/registry"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/containers/libpod/pkg/util/camelcase"
+ "github.com/pkg/errors"
+ "github.com/spf13/cobra"
+ "github.com/spf13/pflag"
+)
+
+// searchOptionsWrapper wraps entities.ImagePullOptions and prevents leaking
+// CLI-only fields into the API types.
+type searchOptionsWrapper struct {
+ entities.ImageSearchOptions
+ // CLI only flags
+ TLSVerifyCLI bool // Used to convert to an optional bool later
+ Format string // For go templating
+}
+
+var (
+ searchOptions = searchOptionsWrapper{}
+ searchDescription = `Search registries for a given image. Can search all the default registries or a specific registry.
+
+ Users can limit the number of results, and filter the output based on certain conditions.`
+
+ // Command: podman search
+ searchCmd = &cobra.Command{
+ Use: "search [flags] TERM",
+ Short: "Search registry for image",
+ Long: searchDescription,
+ PreRunE: preRunE,
+ RunE: imageSearch,
+ Args: cobra.ExactArgs(1),
+ Example: `podman search --filter=is-official --limit 3 alpine
+ podman search registry.fedoraproject.org/ # only works with v2 registries
+ podman search --format "table {{.Index}} {{.Name}}" registry.fedoraproject.org/fedora`,
+ }
+
+ // Command: podman image search
+ imageSearchCmd = &cobra.Command{
+ Use: searchCmd.Use,
+ Short: searchCmd.Short,
+ Long: searchCmd.Long,
+ PreRunE: searchCmd.PreRunE,
+ RunE: searchCmd.RunE,
+ Args: searchCmd.Args,
+ Example: `podman image search --filter=is-official --limit 3 alpine
+ podman image search registry.fedoraproject.org/ # only works with v2 registries
+ podman image search --format "table {{.Index}} {{.Name}}" registry.fedoraproject.org/fedora`,
+ }
+)
+
+func init() {
+ // search
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
+ Command: searchCmd,
+ })
+
+ searchCmd.SetHelpTemplate(registry.HelpTemplate())
+ searchCmd.SetUsageTemplate(registry.UsageTemplate())
+ flags := searchCmd.Flags()
+ searchFlags(flags)
+
+ // images search
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
+ Command: imageSearchCmd,
+ Parent: imageCmd,
+ })
+
+ imageSearchFlags := imageSearchCmd.Flags()
+ searchFlags(imageSearchFlags)
+}
+
+// searchFlags set the flags for the pull command.
+func searchFlags(flags *pflag.FlagSet) {
+ flags.StringSliceVarP(&searchOptions.Filters, "filter", "f", []string{}, "Filter output based on conditions provided (default [])")
+ flags.StringVar(&searchOptions.Format, "format", "", "Change the output format to a Go template")
+ flags.IntVar(&searchOptions.Limit, "limit", 0, "Limit the number of results")
+ flags.BoolVar(&searchOptions.NoTrunc, "no-trunc", false, "Do not truncate the output")
+ flags.StringVar(&searchOptions.Authfile, "authfile", buildahcli.GetDefaultAuthFile(), "Path of the authentication file. Use REGISTRY_AUTH_FILE environment variable to override")
+ flags.BoolVar(&searchOptions.TLSVerifyCLI, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries")
+ if registry.IsRemote() {
+ _ = flags.MarkHidden("authfile")
+ _ = flags.MarkHidden("tls-verify")
+ }
+}
+
+// imageSearch implements the command for searching images.
+func imageSearch(cmd *cobra.Command, args []string) error {
+ searchTerm := ""
+ switch len(args) {
+ case 1:
+ searchTerm = args[0]
+ default:
+ return errors.Errorf("search requires exactly one argument")
+ }
+
+ sarchOptsAPI := searchOptions.ImageSearchOptions
+ // TLS verification in c/image is controlled via a `types.OptionalBool`
+ // which allows for distinguishing among set-true, set-false, unspecified
+ // which is important to implement a sane way of dealing with defaults of
+ // boolean CLI flags.
+ if cmd.Flags().Changed("tls-verify") {
+ sarchOptsAPI.TLSVerify = types.NewOptionalBool(pullOptions.TLSVerifyCLI)
+ }
+
+ searchReport, err := registry.ImageEngine().Search(registry.GetContext(), searchTerm, sarchOptsAPI)
+ if err != nil {
+ return err
+ }
+
+ format := genSearchFormat(searchOptions.Format)
+ if len(searchReport) == 0 {
+ return nil
+ }
+ out := formats.StdoutTemplateArray{Output: searchToGeneric(searchReport), Template: format, Fields: searchHeaderMap()}
+ return out.Out()
+}
+
+// searchHeaderMap returns the headers of a SearchResult.
+func searchHeaderMap() map[string]string {
+ s := new(entities.ImageSearchReport)
+ v := reflect.Indirect(reflect.ValueOf(s))
+ values := make(map[string]string, v.NumField())
+
+ for i := 0; i < v.NumField(); i++ {
+ key := v.Type().Field(i).Name
+ value := key
+ values[key] = strings.ToUpper(strings.Join(camelcase.Split(value), " "))
+ }
+ return values
+}
+
+func genSearchFormat(format string) string {
+ if format != "" {
+ // "\t" from the command line is not being recognized as a tab
+ // replacing the string "\t" to a tab character if the user passes in "\t"
+ return strings.Replace(format, `\t`, "\t", -1)
+ }
+ return "table {{.Index}}\t{{.Name}}\t{{.Description}}\t{{.Stars}}\t{{.Official}}\t{{.Automated}}\t"
+}
+
+func searchToGeneric(params []entities.ImageSearchReport) (genericParams []interface{}) {
+ for _, v := range params {
+ genericParams = append(genericParams, interface{}(v))
+ }
+ return genericParams
+}