diff options
Diffstat (limited to 'cmd')
28 files changed, 251 insertions, 145 deletions
diff --git a/cmd/podman/common/completion.go b/cmd/podman/common/completion.go index 4d66b4e2b..00123f9e6 100644 --- a/cmd/podman/common/completion.go +++ b/cmd/podman/common/completion.go @@ -2,6 +2,7 @@ package common import ( "bufio" + "fmt" "os" "strings" @@ -22,62 +23,97 @@ var ( LogLevels = []string{"debug", "info", "warn", "error", "fatal", "panic"} ) -func getContainers(status string, toComplete string) ([]string, cobra.ShellCompDirective) { +func getContainers(toComplete string, statuses ...string) ([]string, cobra.ShellCompDirective) { suggestions := []string{} listOpts := entities.ContainerListOptions{ Filters: make(map[string][]string), } listOpts.All = true + listOpts.Pod = true - if status != "all" { - listOpts.Filters = map[string][]string{"status": {status}} - } + // TODO: The api doesn't handle several different statuses correct see: + // https://github.com/containers/podman/issues/8344 + // Instead of looping over the statuses we should be able to set + // listOpts.Filters["status"] = statuses - containers, err := registry.ContainerEngine().ContainerList(registry.GetContext(), listOpts) - if err != nil { - cobra.CompErrorln(err.Error()) - return nil, cobra.ShellCompDirectiveError + var containers []entities.ListContainer + var err error + if len(statuses) == 0 { + containers, err = registry.ContainerEngine().ContainerList(registry.GetContext(), listOpts) + if err != nil { + cobra.CompErrorln(err.Error()) + return nil, cobra.ShellCompDirectiveError + } + } else { + for _, s := range statuses { + listOpts.Filters["status"] = []string{s} + res, err := registry.ContainerEngine().ContainerList(registry.GetContext(), listOpts) + if err != nil { + cobra.CompErrorln(err.Error()) + return nil, cobra.ShellCompDirectiveError + } + containers = append(containers, res...) + } } - for _, container := range containers { + for _, c := range containers { // include ids in suggestions if more then 2 chars are typed - if len(toComplete) > 1 { - suggestions = append(suggestions, container.ID[0:12]) + if len(toComplete) > 1 && strings.HasPrefix(c.ID, toComplete) { + suggestions = append(suggestions, c.ID[0:12]+"\t"+c.PodName) } // include name in suggestions - suggestions = append(suggestions, container.Names...) + if strings.HasPrefix(c.Names[0], toComplete) { + suggestions = append(suggestions, c.Names[0]+"\t"+c.PodName) + } } return suggestions, cobra.ShellCompDirectiveNoFileComp } -func getPods(status string, toComplete string) ([]string, cobra.ShellCompDirective) { +func getPods(toComplete string, statuses ...string) ([]string, cobra.ShellCompDirective) { suggestions := []string{} listOpts := entities.PodPSOptions{ Filters: make(map[string][]string), } - if status != "all" { - listOpts.Filters = map[string][]string{"status": {status}} - } + // TODO: The api doesn't handle several different statuses correct see: + // https://github.com/containers/podman/issues/8344 + // Instead of looping over the statuses we should be able to set + // listOpts.Filters["status"] = statuses - pods, err := registry.ContainerEngine().PodPs(registry.GetContext(), listOpts) - if err != nil { - cobra.CompErrorln(err.Error()) - return nil, cobra.ShellCompDirectiveError + var pods []*entities.ListPodsReport + var err error + if len(statuses) == 0 { + pods, err = registry.ContainerEngine().PodPs(registry.GetContext(), listOpts) + if err != nil { + cobra.CompErrorln(err.Error()) + return nil, cobra.ShellCompDirectiveError + } + } else { + for _, s := range statuses { + listOpts.Filters["status"] = []string{s} + res, err := registry.ContainerEngine().PodPs(registry.GetContext(), listOpts) + if err != nil { + cobra.CompErrorln(err.Error()) + return nil, cobra.ShellCompDirectiveError + } + pods = append(pods, res...) + } } for _, pod := range pods { // include ids in suggestions if more then 2 chars are typed - if len(toComplete) > 1 { + if len(toComplete) > 1 && strings.HasPrefix(pod.Id, toComplete) { suggestions = append(suggestions, pod.Id[0:12]) } // include name in suggestions - suggestions = append(suggestions, pod.Name) + if strings.HasPrefix(pod.Name, toComplete) { + suggestions = append(suggestions, pod.Name) + } } return suggestions, cobra.ShellCompDirectiveNoFileComp } -func getVolumes() ([]string, cobra.ShellCompDirective) { +func getVolumes(toComplete string) ([]string, cobra.ShellCompDirective) { suggestions := []string{} lsOpts := entities.VolumeListOptions{} @@ -87,8 +123,10 @@ func getVolumes() ([]string, cobra.ShellCompDirective) { return nil, cobra.ShellCompDirectiveError } - for _, volume := range volumes { - suggestions = append(suggestions, volume.Name) + for _, v := range volumes { + if strings.HasPrefix(v.Name, toComplete) { + suggestions = append(suggestions, v.Name) + } } return suggestions, cobra.ShellCompDirectiveNoFileComp } @@ -104,16 +142,16 @@ func getImages(toComplete string) ([]string, cobra.ShellCompDirective) { } for _, image := range images { - // FIXME: need ux testing - // discuss when image ids should be completed // include ids in suggestions if more then 2 chars are typed - if len(toComplete) > 1 { + if len(toComplete) > 1 && strings.HasPrefix(image.ID, toComplete) { suggestions = append(suggestions, image.ID[0:12]) } for _, repo := range image.RepoTags { if toComplete == "" { // suggest only full repo path if no input is given - suggestions = append(suggestions, repo) + if strings.HasPrefix(repo, toComplete) { + suggestions = append(suggestions, repo) + } } else { // suggested "registry.fedoraproject.org/f29/httpd:latest" as // - "registry.fedoraproject.org/f29/httpd:latest" @@ -125,8 +163,13 @@ func getImages(toComplete string) ([]string, cobra.ShellCompDirective) { paths := strings.Split(repo, "/") for i := range paths { suggestionWithTag := strings.Join(paths[i:], "/") + if strings.HasPrefix(suggestionWithTag, toComplete) { + suggestions = append(suggestions, suggestionWithTag) + } suggestionWithoutTag := strings.SplitN(strings.SplitN(suggestionWithTag, ":", 2)[0], "@", 2)[0] - suggestions = append(suggestions, suggestionWithTag, suggestionWithoutTag) + if strings.HasPrefix(suggestionWithoutTag, toComplete) { + suggestions = append(suggestions, suggestionWithoutTag) + } } } } @@ -143,9 +186,11 @@ func getRegistries() ([]string, cobra.ShellCompDirective) { return regs, cobra.ShellCompDirectiveNoFileComp } -func getNetworks() ([]string, cobra.ShellCompDirective) { +func getNetworks(toComplete string) ([]string, cobra.ShellCompDirective) { suggestions := []string{} - networkListOptions := entities.NetworkListOptions{} + networkListOptions := entities.NetworkListOptions{ + Filter: "name=" + toComplete, + } networks, err := registry.ContainerEngine().NetworkList(registry.Context(), networkListOptions) if err != nil { @@ -159,76 +204,154 @@ func getNetworks() ([]string, cobra.ShellCompDirective) { return suggestions, cobra.ShellCompDirectiveNoFileComp } +// validCurrentCmdLine validates the current cmd line +// It utilizes the Args function from the cmd struct +// In most cases the Args function validates the args length but it +// is also used to verify that --latest is not given with an argument. +// This function helps to makes sure we only complete valid arguments. +func validCurrentCmdLine(cmd *cobra.Command, args []string, toComplete string) bool { + if cmd.Args == nil { + // Without an Args function we cannot check so assume it's correct + return true + } + // We have to append toComplete to the args otherwise the + // argument count would not match the expected behavior + if err := cmd.Args(cmd, append(args, toComplete)); err != nil { + // Special case if we use ExactArgs(2) or MinimumNArgs(2), + // They will error if we try to complete the first arg. + // Lets try to parse the common error and compare if we have less args than + // required. In this case we are fine and should provide completion. + + // Clean the err msg so we can parse it with fmt.Sscanf + // Trim MinimumNArgs prefix + cleanErr := strings.TrimPrefix(err.Error(), "requires at least ") + // Trim MinimumNArgs "only" part + cleanErr = strings.ReplaceAll(cleanErr, "only received", "received") + // Trim ExactArgs prefix + cleanErr = strings.TrimPrefix(cleanErr, "accepts ") + var need, got int + cobra.CompDebugln(cleanErr, true) + _, err = fmt.Sscanf(cleanErr, "%d arg(s), received %d", &need, &got) + if err == nil { + if need >= got { + // We still need more arguments so provide more completions + return true + } + } + cobra.CompDebugln(err.Error(), true) + return false + } + return true +} + /* Autocomplete Functions for cobra ValidArgsFunction */ // AutocompleteContainers - Autocomplete all container names. func AutocompleteContainers(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return getContainers("all", toComplete) + if !validCurrentCmdLine(cmd, args, toComplete) { + return nil, cobra.ShellCompDirectiveNoFileComp + } + return getContainers(toComplete) } // AutocompleteContainersCreated - Autocomplete only created container names. func AutocompleteContainersCreated(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return getContainers("created", toComplete) + if !validCurrentCmdLine(cmd, args, toComplete) { + return nil, cobra.ShellCompDirectiveNoFileComp + } + return getContainers(toComplete, "created") } // AutocompleteContainersExited - Autocomplete only exited container names. func AutocompleteContainersExited(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return getContainers("exited", toComplete) + if !validCurrentCmdLine(cmd, args, toComplete) { + return nil, cobra.ShellCompDirectiveNoFileComp + } + return getContainers(toComplete, "exited") } // AutocompleteContainersPaused - Autocomplete only paused container names. func AutocompleteContainersPaused(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return getContainers("paused", toComplete) + if !validCurrentCmdLine(cmd, args, toComplete) { + return nil, cobra.ShellCompDirectiveNoFileComp + } + return getContainers(toComplete, "paused") } // AutocompleteContainersRunning - Autocomplete only running container names. func AutocompleteContainersRunning(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return getContainers("running", toComplete) + if !validCurrentCmdLine(cmd, args, toComplete) { + return nil, cobra.ShellCompDirectiveNoFileComp + } + return getContainers(toComplete, "running") } // AutocompleteContainersStartable - Autocomplete only created and exited container names. func AutocompleteContainersStartable(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - containersCreated, _ := getContainers("created", toComplete) - containersExited, _ := getContainers("exited", toComplete) - return append(containersCreated, containersExited...), cobra.ShellCompDirectiveNoFileComp + if !validCurrentCmdLine(cmd, args, toComplete) { + return nil, cobra.ShellCompDirectiveNoFileComp + } + return getContainers(toComplete, "created", "exited") } // AutocompletePods - Autocomplete all pod names. func AutocompletePods(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return getPods("all", toComplete) + if !validCurrentCmdLine(cmd, args, toComplete) { + return nil, cobra.ShellCompDirectiveNoFileComp + } + return getPods(toComplete) } // AutocompletePodsRunning - Autocomplete only running pod names. +// It considers degraded as running. func AutocompletePodsRunning(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return getPods("running", toComplete) + if !validCurrentCmdLine(cmd, args, toComplete) { + return nil, cobra.ShellCompDirectiveNoFileComp + } + return getPods(toComplete, "running", "degraded") } // AutocompleteContainersAndPods - Autocomplete container names and pod names. func AutocompleteContainersAndPods(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - containers, _ := getContainers("all", toComplete) - pods, _ := getPods("all", toComplete) + if !validCurrentCmdLine(cmd, args, toComplete) { + return nil, cobra.ShellCompDirectiveNoFileComp + } + containers, _ := getContainers(toComplete) + pods, _ := getPods(toComplete) return append(containers, pods...), cobra.ShellCompDirectiveNoFileComp } // AutocompleteContainersAndImages - Autocomplete container names and pod names. func AutocompleteContainersAndImages(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - containers, _ := getContainers("all", toComplete) + if !validCurrentCmdLine(cmd, args, toComplete) { + return nil, cobra.ShellCompDirectiveNoFileComp + } + containers, _ := getContainers(toComplete) images, _ := getImages(toComplete) return append(containers, images...), cobra.ShellCompDirectiveNoFileComp } // AutocompleteVolumes - Autocomplete volumes. func AutocompleteVolumes(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return getVolumes() + if !validCurrentCmdLine(cmd, args, toComplete) { + return nil, cobra.ShellCompDirectiveNoFileComp + } + return getVolumes(toComplete) } // AutocompleteImages - Autocomplete images. func AutocompleteImages(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + if !validCurrentCmdLine(cmd, args, toComplete) { + return nil, cobra.ShellCompDirectiveNoFileComp + } return getImages(toComplete) } // AutocompleteCreateRun - Autocomplete only the fist argument as image and then do file completion. func AutocompleteCreateRun(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + if !validCurrentCmdLine(cmd, args, toComplete) { + return nil, cobra.ShellCompDirectiveNoFileComp + } if len(args) < 1 { return getImages(toComplete) } @@ -238,18 +361,27 @@ func AutocompleteCreateRun(cmd *cobra.Command, args []string, toComplete string) // AutocompleteRegistries - Autocomplete registries. func AutocompleteRegistries(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + if !validCurrentCmdLine(cmd, args, toComplete) { + return nil, cobra.ShellCompDirectiveNoFileComp + } return getRegistries() } // AutocompleteNetworks - Autocomplete networks. func AutocompleteNetworks(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return getNetworks() + if !validCurrentCmdLine(cmd, args, toComplete) { + return nil, cobra.ShellCompDirectiveNoFileComp + } + return getNetworks(toComplete) } // AutocompleteCpCommand - Autocomplete podman cp command args. func AutocompleteCpCommand(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + if !validCurrentCmdLine(cmd, args, toComplete) { + return nil, cobra.ShellCompDirectiveNoFileComp + } if len(args) < 2 { - containers, _ := getContainers("all", toComplete) + containers, _ := getContainers(toComplete) for _, container := range containers { // TODO: Add path completion for inside the container if possible if strings.HasPrefix(container, toComplete) { @@ -265,6 +397,9 @@ func AutocompleteCpCommand(cmd *cobra.Command, args []string, toComplete string) // AutocompleteSystemConnections - Autocomplete system connections. func AutocompleteSystemConnections(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + if !validCurrentCmdLine(cmd, args, toComplete) { + return nil, cobra.ShellCompDirectiveNoFileComp + } suggestions := []string{} cfg, err := config.ReadCustomConfig() if err != nil { @@ -318,7 +453,7 @@ func AutocompleteNamespace(cmd *cobra.Command, args []string, toComplete string) switch { case strings.HasPrefix(toComplete, "container:"): // Complete containers after colon - containers, _ := getContainers("all", toComplete[10:]) //trim "container:" + containers, _ := getContainers(toComplete[10:]) //trim "container:" // add "container:" in front of the suggestions var suggestions []string @@ -504,21 +639,13 @@ func AutocompleteMountFlag(cmd *cobra.Command, args []string, toComplete string) // AutocompleteVolumeFlag - Autocomplete volume flag options. // -> volumes and paths func AutocompleteVolumeFlag(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - result := []string{} - volumes, _ := getVolumes() - for _, volume := range volumes { - // If we don't filter on "toComplete", zsh and fish will not do file completion - // even if the prefix typed by the user does not match the returned completions - if strings.HasPrefix(volume, toComplete) { - result = append(result, volume) - } - } + volumes, _ := getVolumes(toComplete) directive := cobra.ShellCompDirectiveNoSpace | cobra.ShellCompDirectiveDefault if strings.Contains(toComplete, ":") { // add space after second path directive = cobra.ShellCompDirectiveDefault } - return result, directive + return volumes, directive } // AutocompleteJSONFormat - Autocomplete format flag option. diff --git a/cmd/podman/common/specgen.go b/cmd/podman/common/specgen.go index 39ff02857..0bb6e79e5 100644 --- a/cmd/podman/common/specgen.go +++ b/cmd/podman/common/specgen.go @@ -592,7 +592,7 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string case "max-size": logSize, err := units.FromHumanSize(split[1]) if err != nil { - return errors.Wrapf(err, "%s is not a valid option", o) + return err } s.LogConfiguration.Size = logSize default: @@ -662,7 +662,7 @@ func makeHealthCheckFromCli(inCmd, interval string, retries uint, timeout, start } intervalDuration, err := time.ParseDuration(interval) if err != nil { - return nil, errors.Wrapf(err, "invalid healthcheck-interval %s ", interval) + return nil, errors.Wrapf(err, "invalid healthcheck-interval") } hc.Interval = intervalDuration @@ -673,7 +673,7 @@ func makeHealthCheckFromCli(inCmd, interval string, retries uint, timeout, start hc.Retries = int(retries) timeoutDuration, err := time.ParseDuration(timeout) if err != nil { - return nil, errors.Wrapf(err, "invalid healthcheck-timeout %s", timeout) + return nil, errors.Wrapf(err, "invalid healthcheck-timeout") } if timeoutDuration < time.Duration(1) { return nil, errors.New("healthcheck-timeout must be at least 1 second") @@ -682,7 +682,7 @@ func makeHealthCheckFromCli(inCmd, interval string, retries uint, timeout, start startPeriodDuration, err := time.ParseDuration(startPeriod) if err != nil { - return nil, errors.Wrapf(err, "invalid healthcheck-start-period %s", startPeriod) + return nil, errors.Wrapf(err, "invalid healthcheck-start-period") } if startPeriodDuration < time.Duration(0) { return nil, errors.New("healthcheck-start-period must be 0 seconds or greater") diff --git a/cmd/podman/common/util.go b/cmd/podman/common/util.go index a971aa957..ef30e08d3 100644 --- a/cmd/podman/common/util.go +++ b/cmd/podman/common/util.go @@ -250,7 +250,7 @@ func parseAndValidateRange(portRange string) (uint16, uint16, error) { func parseAndValidatePort(port string) (uint16, error) { num, err := strconv.Atoi(port) if err != nil { - return 0, errors.Wrapf(err, "cannot parse %q as a port number", port) + return 0, errors.Wrapf(err, "invalid port number") } if num < 1 || num > 65535 { return 0, errors.Errorf("port numbers must be between 1 and 65535 (inclusive), got %d", num) diff --git a/cmd/podman/containers/prune.go b/cmd/podman/containers/prune.go index e8debd3ad..9ac529b1c 100644 --- a/cmd/podman/containers/prune.go +++ b/cmd/podman/containers/prune.go @@ -57,7 +57,7 @@ func prune(cmd *cobra.Command, args []string) error { fmt.Print("Are you sure you want to continue? [y/N] ") answer, err := reader.ReadString('\n') if err != nil { - return errors.Wrapf(err, "error reading input") + return err } if strings.ToLower(answer)[0] != 'y' { return nil diff --git a/cmd/podman/containers/run.go b/cmd/podman/containers/run.go index b17c13f46..6ff1b929d 100644 --- a/cmd/podman/containers/run.go +++ b/cmd/podman/containers/run.go @@ -205,7 +205,7 @@ func run(cmd *cobra.Command, args []string) error { if runRmi { _, rmErrors := registry.ImageEngine().Remove(registry.GetContext(), []string{imageName}, entities.ImageRemoveOptions{}) if len(rmErrors) > 0 { - logrus.Errorf("%s", errors.Wrapf(errorhandling.JoinErrors(rmErrors), "failed removing image")) + logrus.Errorf("%s", errorhandling.JoinErrors(rmErrors)) } } return nil diff --git a/cmd/podman/containers/start.go b/cmd/podman/containers/start.go index dba2c3c3e..7e57bb576 100644 --- a/cmd/podman/containers/start.go +++ b/cmd/podman/containers/start.go @@ -21,6 +21,7 @@ var ( Short: "Start one or more containers", Long: startDescription, RunE: start, + Args: validateStart, ValidArgsFunction: common.AutocompleteContainersStartable, Example: `podman start --latest podman start 860a4b231279 5421ab43b45 @@ -32,6 +33,7 @@ var ( Short: startCommand.Short, Long: startCommand.Long, RunE: startCommand.RunE, + Args: startCommand.Args, ValidArgsFunction: startCommand.ValidArgsFunction, Example: `podman container start --latest podman container start 860a4b231279 5421ab43b45 @@ -76,8 +78,7 @@ func init() { validate.AddLatestFlag(containerStartCommand, &startOptions.Latest) } -func start(cmd *cobra.Command, args []string) error { - var errs utils.OutputErrors +func validateStart(cmd *cobra.Command, args []string) error { if len(args) == 0 && !startOptions.Latest { return errors.New("start requires at least one argument") } @@ -87,7 +88,11 @@ func start(cmd *cobra.Command, args []string) error { if len(args) > 1 && startOptions.Attach { return errors.Errorf("you cannot start and attach multiple containers at once") } + return nil +} +func start(cmd *cobra.Command, args []string) error { + var errs utils.OutputErrors sigProxy := startOptions.SigProxy || startOptions.Attach if cmd.Flag("sig-proxy").Changed { sigProxy = startOptions.SigProxy diff --git a/cmd/podman/images/build.go b/cmd/podman/images/build.go index c76e4ac80..739e1c265 100644 --- a/cmd/podman/images/build.go +++ b/cmd/podman/images/build.go @@ -353,18 +353,18 @@ func buildFlagsWrapperToOptions(c *cobra.Command, contextDir string, flags *buil isolation, err := parse.IsolationOption(flags.Isolation) if err != nil { - return nil, errors.Wrapf(err, "error parsing ID mapping options") + return nil, err } usernsOption, idmappingOptions, err := parse.IDMappingOptions(c, isolation) if err != nil { - return nil, errors.Wrapf(err, "error parsing ID mapping options") + return nil, err } nsValues = append(nsValues, usernsOption...) systemContext, err := parse.SystemContextFromOptions(c) if err != nil { - return nil, errors.Wrapf(err, "error building system context") + return nil, err } format := "" diff --git a/cmd/podman/images/prune.go b/cmd/podman/images/prune.go index 3af56b015..e68fe5f40 100644 --- a/cmd/podman/images/prune.go +++ b/cmd/podman/images/prune.go @@ -11,7 +11,6 @@ import ( "github.com/containers/podman/v2/cmd/podman/utils" "github.com/containers/podman/v2/cmd/podman/validate" "github.com/containers/podman/v2/pkg/domain/entities" - "github.com/pkg/errors" "github.com/spf13/cobra" ) @@ -60,7 +59,7 @@ WARNING! This will remove all dangling images. Are you sure you want to continue? [y/N] `) answer, err := reader.ReadString('\n') if err != nil { - return errors.Wrapf(err, "error reading input") + return err } if strings.ToLower(answer)[0] != 'y' { return nil diff --git a/cmd/podman/images/sign.go b/cmd/podman/images/sign.go index 529fb3d92..342536f7c 100644 --- a/cmd/podman/images/sign.go +++ b/cmd/podman/images/sign.go @@ -58,7 +58,7 @@ func sign(cmd *cobra.Command, args []string) error { if len(signOptions.Directory) > 0 { sigStoreDir = signOptions.Directory if _, err := os.Stat(sigStoreDir); err != nil { - return errors.Wrapf(err, "invalid directory %s", sigStoreDir) + return err } } _, err := registry.ImageEngine().Sign(registry.Context(), args, signOptions) diff --git a/cmd/podman/images/trust_set.go b/cmd/podman/images/trust_set.go index f0399b110..1a7392f3e 100644 --- a/cmd/podman/images/trust_set.go +++ b/cmd/podman/images/trust_set.go @@ -55,7 +55,7 @@ func setTrust(cmd *cobra.Command, args []string) error { valid, err := image.IsValidImageURI(args[0]) if err != nil || !valid { - return errors.Wrapf(err, "invalid image uri %s", args[0]) + return err } if !util.StringInSlice(setOptions.Type, validTrustTypes) { diff --git a/cmd/podman/inspect/inspect.go b/cmd/podman/inspect/inspect.go index f9bd75c93..13f36ebbd 100644 --- a/cmd/podman/inspect/inspect.go +++ b/cmd/podman/inspect/inspect.go @@ -2,6 +2,7 @@ package inspect import ( "context" + "encoding/json" // due to a bug in json-iterator it cannot be used here "fmt" "os" "regexp" @@ -28,17 +29,14 @@ const ( ContainerType = "container" // ImageType is the image type. ImageType = "image" - //NetworkType is the network type + // NetworkType is the network type NetworkType = "network" - //PodType is the pod type. + // PodType is the pod type. PodType = "pod" - //VolumeType is the volume type + // VolumeType is the volume type VolumeType = "volume" ) -// Pull in configured json library -var json = registry.JSONLibrary() - // AddInspectFlagSet takes a command and adds the inspect flags and returns an // InspectOptions object. func AddInspectFlagSet(cmd *cobra.Command) *entities.InspectOptions { @@ -173,7 +171,7 @@ func (i *inspector) inspect(namesOrIDs []string) error { data = append(data, podData) } } - if i.podOptions.Latest { //latest means there are no names in the namesOrID array + if i.podOptions.Latest { // latest means there are no names in the namesOrID array podData, err := i.containerEngine.PodInspect(ctx, i.podOptions) if err != nil { cause := errors.Cause(err) @@ -238,9 +236,12 @@ func (i *inspector) inspect(namesOrIDs []string) error { } func printJSON(data []interface{}) error { - enc := json.NewEncoder(os.Stdout) - enc.SetIndent("", " ") - return enc.Encode(data) + buf, err := json.MarshalIndent(data, "", " ") + if err != nil { + return err + } + _, err = fmt.Println(string(buf)) + return err } func printTmpl(typ, row string, data []interface{}) error { diff --git a/cmd/podman/manifest/add.go b/cmd/podman/manifest/add.go index 91bd423b8..cb0838eeb 100644 --- a/cmd/podman/manifest/add.go +++ b/cmd/podman/manifest/add.go @@ -11,7 +11,6 @@ import ( "github.com/containers/podman/v2/cmd/podman/registry" "github.com/containers/podman/v2/pkg/domain/entities" "github.com/containers/podman/v2/pkg/util" - "github.com/pkg/errors" "github.com/spf13/cobra" ) @@ -116,7 +115,7 @@ func add(cmd *cobra.Command, args []string) error { listID, err := registry.ImageEngine().ManifestAdd(context.Background(), manifestAddOpts.ManifestAddOptions) if err != nil { - return errors.Wrapf(err, "error adding to manifest list %s", args[0]) + return err } fmt.Printf("%s\n", listID) return nil diff --git a/cmd/podman/manifest/annotate.go b/cmd/podman/manifest/annotate.go index dab8c4da6..71017e0ec 100644 --- a/cmd/podman/manifest/annotate.go +++ b/cmd/podman/manifest/annotate.go @@ -73,7 +73,7 @@ func annotate(cmd *cobra.Command, args []string) error { } updatedListID, err := registry.ImageEngine().ManifestAnnotate(context.Background(), args, manifestAnnotateOpts) if err != nil { - return errors.Wrapf(err, "error removing from manifest list %s", listImageSpec) + return err } fmt.Printf("%s\n", updatedListID) return nil diff --git a/cmd/podman/manifest/create.go b/cmd/podman/manifest/create.go index c903c6fa8..399f9440c 100644 --- a/cmd/podman/manifest/create.go +++ b/cmd/podman/manifest/create.go @@ -7,7 +7,6 @@ import ( "github.com/containers/podman/v2/cmd/podman/common" "github.com/containers/podman/v2/cmd/podman/registry" "github.com/containers/podman/v2/pkg/domain/entities" - "github.com/pkg/errors" "github.com/spf13/cobra" ) @@ -39,7 +38,7 @@ func init() { func create(cmd *cobra.Command, args []string) error { imageID, err := registry.ImageEngine().ManifestCreate(context.Background(), args[:1], args[1:], manifestCreateOpts) if err != nil { - return errors.Wrapf(err, "error creating manifest %s", args[0]) + return err } fmt.Printf("%s\n", imageID) return nil diff --git a/cmd/podman/manifest/inspect.go b/cmd/podman/manifest/inspect.go index 17c94aaba..39fd54445 100644 --- a/cmd/podman/manifest/inspect.go +++ b/cmd/podman/manifest/inspect.go @@ -7,7 +7,6 @@ import ( "github.com/containers/podman/v2/cmd/podman/common" "github.com/containers/podman/v2/cmd/podman/registry" "github.com/containers/podman/v2/pkg/domain/entities" - "github.com/pkg/errors" "github.com/spf13/cobra" ) @@ -35,7 +34,7 @@ func init() { func inspect(cmd *cobra.Command, args []string) error { buf, err := registry.ImageEngine().ManifestInspect(context.Background(), args[0]) if err != nil { - return errors.Wrapf(err, "error inspect manifest %s", args[0]) + return err } fmt.Printf("%s\n", buf) return nil diff --git a/cmd/podman/manifest/manifest.go b/cmd/podman/manifest/manifest.go index c3bcdc8c7..990ad0e95 100644 --- a/cmd/podman/manifest/manifest.go +++ b/cmd/podman/manifest/manifest.go @@ -18,7 +18,7 @@ var ( podman manifest create localhost/list podman manifest inspect localhost/list podman manifest annotate --annotation left=right mylist:v1.11 image:v1.11-amd64 - podman manifest push mylist:v1.11 quay.io/myimagelist + podman manifest push mylist:v1.11 docker://quay.io/myuser/image:v1.11 podman manifest remove mylist:v1.11 sha256:15352d97781ffdf357bf3459c037be3efac4133dc9070c2dce7eca7c05c3e736`, } ) diff --git a/cmd/podman/manifest/push.go b/cmd/podman/manifest/push.go index 9d0977834..a3b469491 100644 --- a/cmd/podman/manifest/push.go +++ b/cmd/podman/manifest/push.go @@ -28,7 +28,7 @@ var ( Short: "Push a manifest list or image index to a registry", Long: "Pushes manifest lists and image indexes to registries.", RunE: push, - Example: `podman manifest push mylist:v1.11 quay.io/myimagelist`, + Example: `podman manifest push mylist:v1.11 docker://quay.io/myuser/image:v1.11`, Args: cobra.ExactArgs(2), ValidArgsFunction: common.AutocompleteImages, } @@ -108,7 +108,7 @@ func push(cmd *cobra.Command, args []string) error { manifestPushOpts.SkipTLSVerify = types.NewOptionalBool(!manifestPushOpts.TLSVerifyCLI) } if err := registry.ImageEngine().ManifestPush(registry.Context(), args, manifestPushOpts.ManifestPushOptions); err != nil { - return errors.Wrapf(err, "error pushing manifest %s to %s", listImageSpec, destSpec) + return err } return nil } diff --git a/cmd/podman/networks/list.go b/cmd/podman/networks/list.go index bab6b45ea..f2a5a431a 100644 --- a/cmd/podman/networks/list.go +++ b/cmd/podman/networks/list.go @@ -87,8 +87,11 @@ func networkList(cmd *cobra.Command, args []string) error { nlprs = append(nlprs, ListPrintReports{r}) } + // Headers() gets lost resolving the embedded field names so add them headers := report.Headers(ListPrintReports{}, map[string]string{ + "Name": "name", "CNIVersion": "version", + "Version": "version", "Plugins": "plugins", }) renderHeaders := true @@ -110,7 +113,6 @@ func networkList(cmd *cobra.Command, args []string) error { if err := tmpl.Execute(w, headers); err != nil { return err } - } return tmpl.Execute(w, nlprs) } diff --git a/cmd/podman/play/kube.go b/cmd/podman/play/kube.go index a9e91bd68..db70ad7d4 100644 --- a/cmd/podman/play/kube.go +++ b/cmd/podman/play/kube.go @@ -22,6 +22,7 @@ type playKubeOptionsWrapper struct { TLSVerifyCLI bool CredentialsCLI string + StartCLI bool } var ( @@ -68,6 +69,7 @@ func init() { flags.BoolVarP(&kubeOptions.Quiet, "quiet", "q", false, "Suppress output information when pulling images") flags.BoolVar(&kubeOptions.TLSVerifyCLI, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries") + flags.BoolVar(&kubeOptions.StartCLI, "start", true, "Start the pod after creating it") authfileFlagName := "authfile" flags.StringVar(&kubeOptions.Authfile, authfileFlagName, auth.GetDefaultAuthFile(), "Path of the authentication file. Use REGISTRY_AUTH_FILE environment variable to override") @@ -100,6 +102,9 @@ func kube(cmd *cobra.Command, args []string) error { if cmd.Flags().Changed("tls-verify") { kubeOptions.SkipTLSVerify = types.NewOptionalBool(!kubeOptions.TLSVerifyCLI) } + if cmd.Flags().Changed("start") { + kubeOptions.Start = types.NewOptionalBool(kubeOptions.StartCLI) + } if kubeOptions.Authfile != "" { if _, err := os.Stat(kubeOptions.Authfile); err != nil { return err diff --git a/cmd/podman/pods/create.go b/cmd/podman/pods/create.go index d33455e81..449d60bb9 100644 --- a/cmd/podman/pods/create.go +++ b/cmd/podman/pods/create.go @@ -218,7 +218,7 @@ func create(cmd *cobra.Command, args []string) error { } if len(podIDFile) > 0 { if err = ioutil.WriteFile(podIDFile, []byte(response.Id), 0644); err != nil { - return errors.Wrapf(err, "failed to write pod ID to file %q", podIDFile) + return errors.Wrapf(err, "failed to write pod ID to file") } } fmt.Println(response.Id) diff --git a/cmd/podman/pods/prune.go b/cmd/podman/pods/prune.go index 626ef2895..444b0f5e0 100644 --- a/cmd/podman/pods/prune.go +++ b/cmd/podman/pods/prune.go @@ -12,7 +12,6 @@ import ( "github.com/containers/podman/v2/cmd/podman/utils" "github.com/containers/podman/v2/cmd/podman/validate" "github.com/containers/podman/v2/pkg/domain/entities" - "github.com/pkg/errors" "github.com/spf13/cobra" ) @@ -51,7 +50,7 @@ func prune(cmd *cobra.Command, args []string) error { fmt.Print("Are you sure you want to continue? [y/N] ") answer, err := reader.ReadString('\n') if err != nil { - return errors.Wrapf(err, "error reading input") + return err } if strings.ToLower(answer)[0] != 'y' { return nil diff --git a/cmd/podman/root.go b/cmd/podman/root.go index 0a44f5eac..34d92cd0f 100644 --- a/cmd/podman/root.go +++ b/cmd/podman/root.go @@ -189,8 +189,7 @@ func persistentPreRunE(cmd *cobra.Command, args []string) error { if cmd.Flag("cpu-profile").Changed { f, err := os.Create(cfg.CPUProfile) if err != nil { - return errors.Wrapf(err, "unable to create cpu profiling file %s", - cfg.CPUProfile) + return err } if err := pprof.StartCPUProfile(f); err != nil { return err diff --git a/cmd/podman/system/connection/add.go b/cmd/podman/system/connection/add.go index b3a23bffd..57e747451 100644 --- a/cmd/podman/system/connection/add.go +++ b/cmd/podman/system/connection/add.go @@ -79,14 +79,14 @@ func add(cmd *cobra.Command, args []string) error { // Default to ssh: schema if none given dest := args[1] if match, err := regexp.Match(schemaPattern, []byte(dest)); err != nil { - return errors.Wrapf(err, "internal regex error %q", schemaPattern) + return errors.Wrapf(err, "invalid destination") } else if !match { dest = "ssh://" + dest } uri, err := url.Parse(dest) if err != nil { - return errors.Wrapf(err, "failed to parse %q", dest) + return err } if uri.User.Username() == "" { @@ -109,7 +109,7 @@ func add(cmd *cobra.Command, args []string) error { if uri.Path == "" || uri.Path == "/" { if uri.Path, err = getUDS(cmd, uri); err != nil { - return errors.Wrapf(err, "failed to connect to %q", uri.String()) + return err } } @@ -151,7 +151,7 @@ func getUserInfo(uri *url.URL) (*url.Userinfo, error) { if u, found := os.LookupEnv("_CONTAINERS_ROOTLESS_UID"); found { usr, err = user.LookupId(u) if err != nil { - return nil, errors.Wrapf(err, "failed to find user %q", u) + return nil, errors.Wrapf(err, "failed to lookup rootless user") } } else { usr, err = user.Current() @@ -209,7 +209,7 @@ func getUDS(cmd *cobra.Command, uri *url.URL) (string, error) { } dial, err := ssh.Dial("tcp", uri.Host, cfg) if err != nil { - return "", errors.Wrapf(err, "failed to connect to %q", uri.Host) + return "", errors.Wrapf(err, "failed to connect") } defer dial.Close() @@ -229,7 +229,7 @@ func getUDS(cmd *cobra.Command, uri *url.URL) (string, error) { var buffer bytes.Buffer session.Stdout = &buffer if err := session.Run(run); err != nil { - return "", errors.Wrapf(err, "failed to run %q", run) + return "", err } var info define.Info @@ -238,7 +238,7 @@ func getUDS(cmd *cobra.Command, uri *url.URL) (string, error) { } if info.Host.RemoteSocket == nil || len(info.Host.RemoteSocket.Path) == 0 { - return "", fmt.Errorf("remote podman %q failed to report its UDS socket", uri.Host) + return "", errors.Errorf("remote podman %q failed to report its UDS socket", uri.Host) } return info.Host.RemoteSocket.Path, nil } diff --git a/cmd/podman/system/events.go b/cmd/podman/system/events.go index 224ef89f3..d2aefab67 100644 --- a/cmd/podman/system/events.go +++ b/cmd/podman/system/events.go @@ -13,7 +13,6 @@ import ( "github.com/containers/podman/v2/cmd/podman/validate" "github.com/containers/podman/v2/libpod/events" "github.com/containers/podman/v2/pkg/domain/entities" - "github.com/pkg/errors" "github.com/spf13/cobra" ) @@ -104,7 +103,7 @@ func eventsCmd(cmd *cobra.Command, _ []string) error { case doJSON: jsonStr, err := event.ToJSONString() if err != nil { - return errors.Wrapf(err, "unable to format json") + return err } fmt.Println(jsonStr) case cmd.Flags().Changed("format"): diff --git a/cmd/podman/system/prune.go b/cmd/podman/system/prune.go index be0d60604..f2b9a3db5 100644 --- a/cmd/podman/system/prune.go +++ b/cmd/podman/system/prune.go @@ -12,7 +12,6 @@ import ( "github.com/containers/podman/v2/cmd/podman/utils" "github.com/containers/podman/v2/cmd/podman/validate" "github.com/containers/podman/v2/pkg/domain/entities" - "github.com/pkg/errors" "github.com/spf13/cobra" ) @@ -68,7 +67,7 @@ WARNING! This will remove: Are you sure you want to continue? [y/N] `, volumeString) answer, err := reader.ReadString('\n') if err != nil { - return errors.Wrapf(err, "error reading input") + return err } if strings.ToLower(answer)[0] != 'y' { return nil diff --git a/cmd/podman/system/reset.go b/cmd/podman/system/reset.go index d38a1a427..97f4fba28 100644 --- a/cmd/podman/system/reset.go +++ b/cmd/podman/system/reset.go @@ -13,7 +13,7 @@ import ( "github.com/containers/podman/v2/cmd/podman/validate" "github.com/containers/podman/v2/pkg/domain/entities" "github.com/containers/podman/v2/pkg/domain/infra" - "github.com/pkg/errors" + "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -57,7 +57,7 @@ WARNING! This will remove: Are you sure you want to continue? [y/N] `) answer, err := reader.ReadString('\n') if err != nil { - fmt.Println(errors.Wrapf(err, "error reading input")) + logrus.Error(err) os.Exit(1) } if strings.ToLower(answer)[0] != 'y' { @@ -71,13 +71,13 @@ Are you sure you want to continue? [y/N] `) engine, err := infra.NewSystemEngine(entities.ResetMode, registry.PodmanConfig()) if err != nil { - fmt.Println(err) + logrus.Error(err) os.Exit(125) } defer engine.Shutdown(registry.Context()) if err := engine.Reset(registry.Context()); err != nil { - fmt.Println(err) + logrus.Error(err) os.Exit(125) } os.Exit(0) diff --git a/cmd/podman/system/service_abi.go b/cmd/podman/system/service_abi.go index 95cbd19d9..8c52616be 100644 --- a/cmd/podman/system/service_abi.go +++ b/cmd/podman/system/service_abi.go @@ -5,12 +5,8 @@ package system import ( "context" "net" - "os" - "os/signal" "strings" - "github.com/containers/podman/v2/cmd/podman/utils" - "github.com/containers/podman/v2/libpod" api "github.com/containers/podman/v2/pkg/api/server" "github.com/containers/podman/v2/pkg/domain/entities" "github.com/containers/podman/v2/pkg/domain/infra" @@ -33,7 +29,7 @@ func restService(opts entities.ServiceOptions, flags *pflag.FlagSet, cfg *entiti address := strings.Join(fields[1:], ":") l, err := net.Listen(fields[0], address) if err != nil { - return errors.Wrapf(err, "unable to create socket %s", opts.URI) + return errors.Wrapf(err, "unable to create socket") } listener = &l } @@ -43,7 +39,7 @@ func restService(opts entities.ServiceOptions, flags *pflag.FlagSet, cfg *entiti return err } - startWatcher(rt) + infra.StartWatcher(rt) server, err := api.NewServerWithSettings(rt, opts.Timeout, listener) if err != nil { return err @@ -60,24 +56,3 @@ func restService(opts entities.ServiceOptions, flags *pflag.FlagSet, cfg *entiti } return err } - -// startWatcher starts a new SIGHUP go routine for the current config. -func startWatcher(rt *libpod.Runtime) { - // Setup the signal notifier - ch := make(chan os.Signal, 1) - signal.Notify(ch, utils.SIGHUP) - - go func() { - for { - // Block until the signal is received - logrus.Debugf("waiting for SIGHUP to reload configuration") - <-ch - if err := rt.Reload(); err != nil { - logrus.Errorf("unable to reload configuration: %v", err) - continue - } - } - }() - - logrus.Debugf("registered SIGHUP watcher for config") -} diff --git a/cmd/podman/volumes/prune.go b/cmd/podman/volumes/prune.go index 2f58b668f..4c2136dcf 100644 --- a/cmd/podman/volumes/prune.go +++ b/cmd/podman/volumes/prune.go @@ -12,7 +12,6 @@ import ( "github.com/containers/podman/v2/cmd/podman/utils" "github.com/containers/podman/v2/cmd/podman/validate" "github.com/containers/podman/v2/pkg/domain/entities" - "github.com/pkg/errors" "github.com/spf13/cobra" ) @@ -53,7 +52,7 @@ func prune(cmd *cobra.Command, args []string) error { fmt.Print("Are you sure you want to continue? [y/N] ") answer, err := reader.ReadString('\n') if err != nil { - return errors.Wrapf(err, "error reading input") + return err } if strings.ToLower(answer)[0] != 'y' { return nil |