diff options
Diffstat (limited to 'cmd/podman')
-rw-r--r-- | cmd/podman/containers/stats.go | 12 | ||||
-rw-r--r-- | cmd/podman/images/buildx.go | 11 | ||||
-rw-r--r-- | cmd/podman/images/prune.go | 5 | ||||
-rw-r--r-- | cmd/podman/images/search.go | 30 | ||||
-rw-r--r-- | cmd/podman/pods/create.go | 2 | ||||
-rw-r--r-- | cmd/podman/system/dial_stdio.go | 145 | ||||
-rw-r--r-- | cmd/podman/system/service_abi.go | 2 |
7 files changed, 181 insertions, 26 deletions
diff --git a/cmd/podman/containers/stats.go b/cmd/podman/containers/stats.go index 11e8f6870..d21feaabc 100644 --- a/cmd/podman/containers/stats.go +++ b/cmd/podman/containers/stats.go @@ -11,9 +11,7 @@ import ( "github.com/containers/podman/v3/cmd/podman/registry" "github.com/containers/podman/v3/cmd/podman/validate" "github.com/containers/podman/v3/libpod/define" - "github.com/containers/podman/v3/pkg/cgroups" "github.com/containers/podman/v3/pkg/domain/entities" - "github.com/containers/podman/v3/pkg/rootless" "github.com/containers/podman/v3/utils" "github.com/docker/go-units" "github.com/pkg/errors" @@ -113,16 +111,6 @@ func checkStatOptions(cmd *cobra.Command, args []string) error { } func stats(cmd *cobra.Command, args []string) error { - if rootless.IsRootless() { - unified, err := cgroups.IsCgroup2UnifiedMode() - if err != nil { - return err - } - if !unified { - return errors.New("stats is not supported in rootless mode without cgroups v2") - } - } - // Convert to the entities options. We should not leak CLI-only // options into the backend and separate concerns. opts := entities.ContainerStatsOptions{ diff --git a/cmd/podman/images/buildx.go b/cmd/podman/images/buildx.go index 5c8e5aaa0..2577a3a74 100644 --- a/cmd/podman/images/buildx.go +++ b/cmd/podman/images/buildx.go @@ -14,11 +14,12 @@ var ( // If we are adding new buildx features, we will add them by default // to podman build. buildxCmd = &cobra.Command{ - Use: "buildx", - Short: "Build images", - Long: "Build images", - RunE: validate.SubCommandExists, - Hidden: true, + Use: "buildx", + Aliases: []string{"builder"}, + Short: "Build images", + Long: "Build images", + RunE: validate.SubCommandExists, + Hidden: true, } ) diff --git a/cmd/podman/images/prune.go b/cmd/podman/images/prune.go index 6c39e5c69..fc7451c41 100644 --- a/cmd/podman/images/prune.go +++ b/cmd/podman/images/prune.go @@ -36,6 +36,11 @@ var ( func init() { registry.Commands = append(registry.Commands, registry.CliCommand{ Command: pruneCmd, + Parent: buildxCmd, + }) + + registry.Commands = append(registry.Commands, registry.CliCommand{ + Command: pruneCmd, Parent: imageCmd, }) diff --git a/cmd/podman/images/search.go b/cmd/podman/images/search.go index 11e54578a..c9a4793aa 100644 --- a/cmd/podman/images/search.go +++ b/cmd/podman/images/search.go @@ -3,6 +3,7 @@ package images import ( "fmt" "os" + "strings" "github.com/containers/common/pkg/auth" "github.com/containers/common/pkg/completion" @@ -19,6 +20,7 @@ import ( type searchOptionsWrapper struct { entities.ImageSearchOptions // CLI only flags + Compatible bool // Docker compat TLSVerifyCLI bool // Used to convert to an optional bool later Format string // For go templating } @@ -79,7 +81,7 @@ func searchFlags(cmd *cobra.Command) { filterFlagName := "filter" flags.StringSliceVarP(&searchOptions.Filters, filterFlagName, "f", []string{}, "Filter output based on conditions provided (default [])") - //TODO add custom filter function + // TODO add custom filter function _ = cmd.RegisterFlagCompletionFunc(filterFlagName, completion.AutocompleteNone) formatFlagName := "format" @@ -90,7 +92,8 @@ func searchFlags(cmd *cobra.Command) { flags.IntVar(&searchOptions.Limit, limitFlagName, 0, "Limit the number of results") _ = cmd.RegisterFlagCompletionFunc(limitFlagName, completion.AutocompleteNone) - flags.BoolVar(&searchOptions.NoTrunc, "no-trunc", false, "Do not truncate the output") + flags.Bool("no-trunc", true, "Do not truncate the output. Default: true") + flags.BoolVar(&searchOptions.Compatible, "compatible", false, "List stars, official and automated columns (Docker compatibility)") authfileFlagName := "authfile" flags.StringVar(&searchOptions.Authfile, authfileFlagName, auth.GetDefaultAuthFile(), "Path of the authentication file. Use REGISTRY_AUTH_FILE environment variable to override") @@ -132,11 +135,20 @@ func imageSearch(cmd *cobra.Command, args []string) error { if err != nil { return err } - if len(searchReport) == 0 { return nil } + noTrunc, _ := cmd.Flags().GetBool("no-trunc") + isJSON := report.IsJSON(searchOptions.Format) + for i, element := range searchReport { + d := strings.ReplaceAll(element.Description, "\n", " ") + if len(d) > 44 && !(noTrunc || isJSON) { + d = strings.TrimSpace(d[:44]) + "..." + } + searchReport[i].Description = d + } + hdrs := report.Headers(entities.ImageSearchReport{}, nil) renderHeaders := true var row string @@ -145,18 +157,22 @@ func imageSearch(cmd *cobra.Command, args []string) error { if len(searchOptions.Filters) != 0 { return errors.Errorf("filters are not applicable to list tags result") } - if report.IsJSON(searchOptions.Format) { + if isJSON { listTagsEntries := buildListTagsJSON(searchReport) return printArbitraryJSON(listTagsEntries) } row = "{{.Name}}\t{{.Tag}}\n" - case report.IsJSON(searchOptions.Format): + case isJSON: return printArbitraryJSON(searchReport) case cmd.Flags().Changed("format"): renderHeaders = report.HasTable(searchOptions.Format) row = report.NormalizeFormat(searchOptions.Format) default: - row = "{{.Index}}\t{{.Name}}\t{{.Description}}\t{{.Stars}}\t{{.Official}}\t{{.Automated}}\n" + row = "{{.Name}}\t{{.Description}}" + if searchOptions.Compatible { + row += "\t{{.Stars}}\t{{.Official}}\t{{.Automated}}" + } + row += "\n" } format := report.EnforceRange(row) @@ -190,7 +206,7 @@ func printArbitraryJSON(v interface{}) error { } func buildListTagsJSON(searchReport []entities.ImageSearchReport) []listEntryTag { - entries := []listEntryTag{} + entries := make([]listEntryTag, 0) ReportLoop: for _, report := range searchReport { diff --git a/cmd/podman/pods/create.go b/cmd/podman/pods/create.go index d5aaf09ce..7c2c72171 100644 --- a/cmd/podman/pods/create.go +++ b/cmd/podman/pods/create.go @@ -132,7 +132,7 @@ func create(cmd *cobra.Command, args []string) error { } createOptions.Share = nil } else { - // reassign certain optios for lbpod api, these need to be populated in spec + // reassign certain options for lbpod api, these need to be populated in spec flags := cmd.Flags() infraOptions.Net, err = common.NetFlagsToNetOptions(nil, *flags, false) if err != nil { diff --git a/cmd/podman/system/dial_stdio.go b/cmd/podman/system/dial_stdio.go new file mode 100644 index 000000000..eae89f38e --- /dev/null +++ b/cmd/podman/system/dial_stdio.go @@ -0,0 +1,145 @@ +package system + +import ( + "context" + "io" + "os" + + "github.com/containers/podman/v3/cmd/podman/registry" + "github.com/containers/podman/v3/cmd/podman/validate" + "github.com/containers/podman/v3/pkg/bindings" + "github.com/pkg/errors" + "github.com/sirupsen/logrus" + "github.com/spf13/cobra" +) + +var ( + dialStdioCommand = &cobra.Command{ + Use: "dial-stdio", + Short: "Proxy the stdio stream to the daemon connection. Should not be invoked manually.", + Args: validate.NoArgs, + Hidden: true, + RunE: func(cmd *cobra.Command, args []string) error { + return runDialStdio() + }, + Example: "podman system dial-stdio", + } +) + +func init() { + registry.Commands = append(registry.Commands, registry.CliCommand{ + Command: dialStdioCommand, + Parent: systemCmd, + }) +} + +func runDialStdio() error { + ctx := registry.Context() + cfg := registry.PodmanConfig() + ctx, cancel := context.WithCancel(ctx) + defer cancel() + bindCtx, err := bindings.NewConnection(ctx, cfg.URI) + if err != nil { + return errors.Wrap(err, "failed to open connection to podman") + } + conn, err := bindings.GetClient(bindCtx) + if err != nil { + return errors.Wrap(err, "failed to get connection after initialization") + } + netConn, err := conn.GetDialer(bindCtx) + if err != nil { + return errors.Wrap(err, "failed to open the raw stream connection") + } + defer netConn.Close() + + var connHalfCloser halfCloser + switch t := netConn.(type) { + case halfCloser: + connHalfCloser = t + case halfReadWriteCloser: + connHalfCloser = &nopCloseReader{t} + default: + return errors.New("the raw stream connection does not implement halfCloser") + } + + stdin2conn := make(chan error, 1) + conn2stdout := make(chan error, 1) + go func() { + stdin2conn <- copier(connHalfCloser, &halfReadCloserWrapper{os.Stdin}, "stdin to stream") + }() + go func() { + conn2stdout <- copier(&halfWriteCloserWrapper{os.Stdout}, connHalfCloser, "stream to stdout") + }() + select { + case err = <-stdin2conn: + if err != nil { + return err + } + // wait for stdout + err = <-conn2stdout + case err = <-conn2stdout: + // return immediately + } + return err +} + +// Below portion taken from original docker CLI +// https://github.com/docker/cli/blob/v20.10.9/cli/command/system/dial_stdio.go +func copier(to halfWriteCloser, from halfReadCloser, debugDescription string) error { + defer func() { + if err := from.CloseRead(); err != nil { + logrus.Errorf("error while CloseRead (%s): %v", debugDescription, err) + } + if err := to.CloseWrite(); err != nil { + logrus.Errorf("error while CloseWrite (%s): %v", debugDescription, err) + } + }() + if _, err := io.Copy(to, from); err != nil { + return errors.Wrapf(err, "error while Copy (%s)", debugDescription) + } + return nil +} + +type halfReadCloser interface { + io.Reader + CloseRead() error +} + +type halfWriteCloser interface { + io.Writer + CloseWrite() error +} + +type halfCloser interface { + halfReadCloser + halfWriteCloser +} + +type halfReadWriteCloser interface { + io.Reader + halfWriteCloser +} + +type nopCloseReader struct { + halfReadWriteCloser +} + +func (x *nopCloseReader) CloseRead() error { + return nil +} + +type halfReadCloserWrapper struct { + io.ReadCloser +} + +func (x *halfReadCloserWrapper) CloseRead() error { + return x.Close() +} + +type halfWriteCloserWrapper struct { + io.WriteCloser +} + +func (x *halfWriteCloserWrapper) CloseWrite() error { + return x.Close() +} diff --git a/cmd/podman/system/service_abi.go b/cmd/podman/system/service_abi.go index 0a4be6aea..b9bd7538f 100644 --- a/cmd/podman/system/service_abi.go +++ b/cmd/podman/system/service_abi.go @@ -93,7 +93,7 @@ func restService(flags *pflag.FlagSet, cfg *entities.PodmanConfig, opts entities return err } defer func() { - if err := server.Shutdown(false); err != nil { + if err := server.Shutdown(true); err != nil { logrus.Warnf("Error when stopping API service: %s", err) } }() |