diff options
Diffstat (limited to 'cmd')
54 files changed, 244 insertions, 97 deletions
diff --git a/cmd/podman-mac-helper/install.go b/cmd/podman-mac-helper/install.go index 7f623ecb6..a1b99e66c 100644 --- a/cmd/podman-mac-helper/install.go +++ b/cmd/podman-mac-helper/install.go @@ -197,7 +197,7 @@ func installExecutable(user string) (string, error) { // suffix. The goal is to help users harden against privilege escalation from loose // filesystem permissions. // - // Since userpsace package management tools, such as brew, delegate management of system + // Since userspace package management tools, such as brew, delegate management of system // paths to standard unix users, the daemon executable is copied into a separate more // restricted area of the filesystem. if err := verifyRootDeep(installPrefix); err != nil { diff --git a/cmd/podman/common/completion.go b/cmd/podman/common/completion.go index 9ebdcda2b..1c0065006 100644 --- a/cmd/podman/common/completion.go +++ b/cmd/podman/common/completion.go @@ -1115,6 +1115,13 @@ func AutocompleteNetworkDriver(cmd *cobra.Command, args []string, toComplete str return drivers, cobra.ShellCompDirectiveNoFileComp } +// AutocompleteNetworkIPAMDriver - Autocomplete network ipam driver option. +// -> "bridge", "macvlan" +func AutocompleteNetworkIPAMDriver(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + drivers := []string{types.HostLocalIPAMDriver, types.DHCPIPAMDriver, types.NoneIPAMDriver} + return drivers, cobra.ShellCompDirectiveNoFileComp +} + // AutocompletePodShareNamespace - Autocomplete pod create --share flag option. // -> "ipc", "net", "pid", "user", "uts", "cgroup", "none" func AutocompletePodShareNamespace(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { diff --git a/cmd/podman/common/create.go b/cmd/podman/common/create.go index 634b49db7..8a3f02036 100644 --- a/cmd/podman/common/create.go +++ b/cmd/podman/common/create.go @@ -348,8 +348,7 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions, ) oomScoreAdjFlagName := "oom-score-adj" - createFlags.IntVar( - &cf.OOMScoreAdj, + createFlags.Int( oomScoreAdjFlagName, 0, "Tune the host's OOM preferences (-1000 to 1000)", ) @@ -394,14 +393,6 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions, ) _ = cmd.RegisterFlagCompletionFunc(platformFlagName, completion.AutocompleteNone) - podFlagName := "pod" - createFlags.StringVar( - &cf.Pod, - podFlagName, "", - "Run container in an existing pod", - ) - _ = cmd.RegisterFlagCompletionFunc(podFlagName, AutocompletePods) - podIDFileFlagName := "pod-id-file" createFlags.StringVar( &cf.PodIDFile, @@ -631,6 +622,14 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions, "Write the container process ID to the file") _ = cmd.RegisterFlagCompletionFunc(pidFileFlagName, completion.AutocompleteDefault) + chrootDirsFlagName := "chrootdirs" + createFlags.StringSliceVar( + &cf.ChrootDirs, + chrootDirsFlagName, []string{}, + "Chroot directories inside the container", + ) + _ = cmd.RegisterFlagCompletionFunc(chrootDirsFlagName, completion.AutocompleteDefault) + if registry.IsRemote() { _ = createFlags.MarkHidden("env-host") _ = createFlags.MarkHidden("http-proxy") @@ -713,7 +712,7 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions, "Optional parent cgroup for the container", ) _ = cmd.RegisterFlagCompletionFunc(cgroupParentFlagName, completion.AutocompleteDefault) - conmonPidfileFlagName := "" + var conmonPidfileFlagName string if !isInfra { conmonPidfileFlagName = "conmon-pidfile" } else { @@ -726,7 +725,7 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions, ) _ = cmd.RegisterFlagCompletionFunc(conmonPidfileFlagName, completion.AutocompleteDefault) - entrypointFlagName := "" + var entrypointFlagName string if !isInfra { entrypointFlagName = "entrypoint" } else { @@ -829,6 +828,14 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions, ) _ = cmd.RegisterFlagCompletionFunc(nameFlagName, completion.AutocompleteNone) + podFlagName := "pod" + createFlags.StringVar( + &cf.Pod, + podFlagName, "", + "Run container in an existing pod", + ) + _ = cmd.RegisterFlagCompletionFunc(podFlagName, AutocompletePods) + cpuPeriodFlagName := "cpu-period" createFlags.Uint64Var( &cf.CPUPeriod, diff --git a/cmd/podman/common/create_opts.go b/cmd/podman/common/create_opts.go index a4f94616c..ad6b3870a 100644 --- a/cmd/podman/common/create_opts.go +++ b/cmd/podman/common/create_opts.go @@ -97,12 +97,21 @@ func ContainerCreateToContainerCLIOpts(cc handlers.CreateContainerConfig, rtc *c } // mounts type=tmpfs/bind,source=...,target=...=,opt=val + volSources := make(map[string]bool) + volDestinations := make(map[string]bool) mounts := make([]string, 0, len(cc.HostConfig.Mounts)) var builder strings.Builder for _, m := range cc.HostConfig.Mounts { addField(&builder, "type", string(m.Type)) addField(&builder, "source", m.Source) addField(&builder, "target", m.Target) + + // Store source/dest so we don't add duplicates if a volume is + // also mentioned in cc.Volumes. + // Which Docker Compose v2.0 does, for unclear reasons... + volSources[m.Source] = true + volDestinations[m.Target] = true + if m.ReadOnly { addField(&builder, "ro", "true") } @@ -117,7 +126,7 @@ func ContainerCreateToContainerCLIOpts(cc handlers.CreateContainerConfig, rtc *c case mount.TypeTmpfs: if m.TmpfsOptions != nil { addField(&builder, "tmpfs-size", strconv.FormatInt(m.TmpfsOptions.SizeBytes, 10)) - addField(&builder, "tmpfs-mode", strconv.FormatUint(uint64(m.TmpfsOptions.Mode), 10)) + addField(&builder, "tmpfs-mode", strconv.FormatUint(uint64(m.TmpfsOptions.Mode), 8)) } case mount.TypeVolume: // All current VolumeOpts are handled above @@ -277,7 +286,7 @@ func ContainerCreateToContainerCLIOpts(cc handlers.CreateContainerConfig, rtc *c LogDriver: cc.HostConfig.LogConfig.Type, LogOptions: stringMaptoArray(cc.HostConfig.LogConfig.Config), Name: cc.Name, - OOMScoreAdj: cc.HostConfig.OomScoreAdj, + OOMScoreAdj: &cc.HostConfig.OomScoreAdj, Arch: "", OS: "", Variant: "", @@ -328,8 +337,6 @@ func ContainerCreateToContainerCLIOpts(cc handlers.CreateContainerConfig, rtc *c } // volumes - volSources := make(map[string]bool) - volDestinations := make(map[string]bool) for _, vol := range cc.HostConfig.Binds { cliOpts.Volume = append(cliOpts.Volume, vol) // Extract the destination so we don't add duplicate mounts in @@ -348,6 +355,8 @@ func ContainerCreateToContainerCLIOpts(cc handlers.CreateContainerConfig, rtc *c // format of `-v` so we can just append them in there. // Unfortunately, these may be duplicates of existing mounts in Binds. // So... We need to catch that. + // This also handles volumes duplicated between cc.HostConfig.Mounts and + // cc.Volumes, as seen in compose v2.0. for vol := range cc.Volumes { if _, ok := volDestinations[filepath.Clean(vol)]; ok { continue diff --git a/cmd/podman/containers/clone.go b/cmd/podman/containers/clone.go index d095d24ba..8a1473608 100644 --- a/cmd/podman/containers/clone.go +++ b/cmd/podman/containers/clone.go @@ -58,9 +58,8 @@ func clone(cmd *cobra.Command, args []string) error { case 3: ctrClone.CreateOpts.Name = args[1] ctrClone.Image = args[2] - rawImageName := "" if !cliVals.RootFS { - rawImageName = args[0] + rawImageName := args[0] name, err := PullImage(ctrClone.Image, ctrClone.CreateOpts) if err != nil { return err diff --git a/cmd/podman/containers/cp.go b/cmd/podman/containers/cp.go index 7ac28b799..eb18dfce4 100644 --- a/cmd/podman/containers/cp.go +++ b/cmd/podman/containers/cp.go @@ -449,7 +449,7 @@ func resolvePathOnDestinationContainer(container string, containerPath string, i containerInfo, err = registry.ContainerEngine().ContainerStat(registry.GetContext(), container, containerPath) if err == nil { baseName = filepath.Base(containerInfo.LinkTarget) - return + return // nolint: nilerr } if strings.HasSuffix(containerPath, "/") { diff --git a/cmd/podman/containers/create.go b/cmd/podman/containers/create.go index de1a41e25..bbc449a1e 100644 --- a/cmd/podman/containers/create.go +++ b/cmd/podman/containers/create.go @@ -238,6 +238,13 @@ func CreateInit(c *cobra.Command, vals entities.ContainerCreateOptions, isInfra vals.GroupAdd = groups } + if c.Flags().Changed("oom-score-adj") { + val, err := c.Flags().GetInt("oom-score-adj") + if err != nil { + return vals, err + } + vals.OOMScoreAdj = &val + } if c.Flags().Changed("pids-limit") { val := c.Flag("pids-limit").Value.String() // Convert -1 to 0, so that -1 maps to unlimited pids limit diff --git a/cmd/podman/containers/logs.go b/cmd/podman/containers/logs.go index 8b08a6313..374bf6b1c 100644 --- a/cmd/podman/containers/logs.go +++ b/cmd/podman/containers/logs.go @@ -64,6 +64,7 @@ var ( ValidArgsFunction: logsCommand.ValidArgsFunction, Example: `podman container logs ctrID podman container logs --names ctrID1 ctrID2 + podman container logs --color --names ctrID1 ctrID2 podman container logs --tail 2 mywebserver podman container logs --follow=true --since 10m ctrID podman container logs mywebserver mydbserver`, @@ -112,7 +113,9 @@ func logsFlags(cmd *cobra.Command) { _ = cmd.RegisterFlagCompletionFunc(tailFlagName, completion.AutocompleteNone) flags.BoolVarP(&logsOptions.Timestamps, "timestamps", "t", false, "Output the timestamps in the log") + flags.BoolVarP(&logsOptions.Colors, "color", "", false, "Output the containers with different colors in the log.") flags.BoolVarP(&logsOptions.Names, "names", "n", false, "Output the container name in the log") + flags.SetInterspersed(false) _ = flags.MarkHidden("details") } diff --git a/cmd/podman/containers/start.go b/cmd/podman/containers/start.go index a7731a0a1..b70e975b7 100644 --- a/cmd/podman/containers/start.go +++ b/cmd/podman/containers/start.go @@ -122,7 +122,7 @@ func start(cmd *cobra.Command, args []string) error { startOptions.Stdout = os.Stdout } - var containers []string = args + containers := args if len(filters) > 0 { for _, f := range filters { split := strings.SplitN(f, "=", 2) diff --git a/cmd/podman/early_init_unsupported.go b/cmd/podman/early_init_unsupported.go index 4e748559f..55bb0906f 100644 --- a/cmd/podman/early_init_unsupported.go +++ b/cmd/podman/early_init_unsupported.go @@ -1,3 +1,4 @@ +//go:build !linux // +build !linux package main diff --git a/cmd/podman/images/build.go b/cmd/podman/images/build.go index 729951a31..1f9e7ea9e 100644 --- a/cmd/podman/images/build.go +++ b/cmd/podman/images/build.go @@ -375,7 +375,7 @@ func buildFlagsWrapperToOptions(c *cobra.Command, contextDir string, flags *buil } } - cleanTmpFile := false + var cleanTmpFile bool flags.Authfile, cleanTmpFile = buildahUtil.MirrorToTempFileIfPathIsDescriptor(flags.Authfile) if cleanTmpFile { defer os.Remove(flags.Authfile) @@ -474,7 +474,7 @@ func buildFlagsWrapperToOptions(c *cobra.Command, contextDir string, flags *buil return nil, err } - format := "" + var format string flags.Format = strings.ToLower(flags.Format) switch { case strings.HasPrefix(flags.Format, buildahDefine.OCI): diff --git a/cmd/podman/images/import.go b/cmd/podman/images/import.go index a7416e298..1910fef6d 100644 --- a/cmd/podman/images/import.go +++ b/cmd/podman/images/import.go @@ -76,6 +76,18 @@ func importFlags(cmd *cobra.Command) { flags.StringVarP(&importOpts.Message, messageFlagName, "m", "", "Set commit message for imported image") _ = cmd.RegisterFlagCompletionFunc(messageFlagName, completion.AutocompleteNone) + osFlagName := "os" + flags.StringVar(&importOpts.OS, osFlagName, "", "Set the OS of the imported image") + _ = cmd.RegisterFlagCompletionFunc(osFlagName, completion.AutocompleteNone) + + archFlagName := "arch" + flags.StringVar(&importOpts.Architecture, archFlagName, "", "Set the architecture of the imported image") + _ = cmd.RegisterFlagCompletionFunc(archFlagName, completion.AutocompleteNone) + + variantFlagName := "variant" + flags.StringVar(&importOpts.Variant, variantFlagName, "", "Set the variant of the imported image") + _ = cmd.RegisterFlagCompletionFunc(variantFlagName, completion.AutocompleteNone) + flags.BoolVarP(&importOpts.Quiet, "quiet", "q", false, "Suppress output") if !registry.IsRemote() { flags.StringVar(&importOpts.SignaturePolicy, "signature-policy", "", "Path to a signature-policy file") @@ -106,14 +118,14 @@ func importCon(cmd *cobra.Command, args []string) error { if source == "-" { outFile, err := ioutil.TempFile("", "podman") if err != nil { - return errors.Errorf("error creating file %v", err) + return errors.Errorf("creating file %v", err) } defer os.Remove(outFile.Name()) defer outFile.Close() _, err = io.Copy(outFile, os.Stdin) if err != nil { - return errors.Errorf("error copying file %v", err) + return errors.Errorf("copying file %v", err) } source = outFile.Name() } diff --git a/cmd/podman/images/list.go b/cmd/podman/images/list.go index 9bddf1cff..10a2a4f87 100644 --- a/cmd/podman/images/list.go +++ b/cmd/podman/images/list.go @@ -87,6 +87,7 @@ func imageListFlagSet(cmd *cobra.Command) { flags := cmd.Flags() flags.BoolVarP(&listOptions.All, "all", "a", false, "Show all images (default hides intermediate images)") + flags.BoolVarP(&listOptions.Size, "size", "", true, "Compute the size of each image") filterFlagName := "filter" flags.StringSliceVarP(&listOptions.Filter, filterFlagName, "f", []string{}, "Filter output based on conditions provided (default [])") @@ -320,7 +321,10 @@ func lsFormatFromFlags(flags listFlagType) string { row = append(row, "{{.Digest}}") } - row = append(row, "{{.ID}}", "{{.Created}}", "{{.Size}}") + row = append(row, "{{.ID}}", "{{.Created}}") + if listOptions.Size { + row = append(row, "{{.Size}}") + } if flags.history { row = append(row, "{{if .History}}{{.History}}{{else}}<none>{{end}}") diff --git a/cmd/podman/images/load.go b/cmd/podman/images/load.go index bbcfe93ce..30f88b02b 100644 --- a/cmd/podman/images/load.go +++ b/cmd/podman/images/load.go @@ -95,14 +95,14 @@ func load(cmd *cobra.Command, args []string) error { } outFile, err := ioutil.TempFile(util.Tmpdir(), "podman") if err != nil { - return errors.Errorf("error creating file %v", err) + return errors.Errorf("creating file %v", err) } defer os.Remove(outFile.Name()) defer outFile.Close() _, err = io.Copy(outFile, os.Stdin) if err != nil { - return errors.Errorf("error copying file %v", err) + return errors.Errorf("copying file %v", err) } loadOpts.Input = outFile.Name() } diff --git a/cmd/podman/images/rm.go b/cmd/podman/images/rm.go index dd138d410..13dab62d4 100644 --- a/cmd/podman/images/rm.go +++ b/cmd/podman/images/rm.go @@ -56,6 +56,7 @@ func init() { func imageRemoveFlagSet(flags *pflag.FlagSet) { flags.BoolVarP(&imageOpts.All, "all", "a", false, "Remove all images") + flags.BoolVarP(&imageOpts.Ignore, "ignore", "i", false, "Ignore errors if a specified image does not exist") flags.BoolVarP(&imageOpts.Force, "force", "f", false, "Force Removal of the image") } diff --git a/cmd/podman/images/scp.go b/cmd/podman/images/scp.go index d07a5d99d..51a9d1c4e 100644 --- a/cmd/podman/images/scp.go +++ b/cmd/podman/images/scp.go @@ -105,7 +105,7 @@ func scp(cmd *cobra.Command, args []string) (finalErr error) { } locations := []*entities.ImageScpOptions{} cliConnections := []string{} - flipConnections := false + var flipConnections bool for _, arg := range args { loc, connect, err := parseImageSCPArg(arg) if err != nil { @@ -233,7 +233,7 @@ func loadToRemote(localFile string, tag string, url *urlP.URL, iden string) (str errOut := strconv.Itoa(int(n)) + " Bytes copied before error" return " ", errors.Wrapf(err, errOut) } - run := "" + var run string if tag != "" { return "", errors.Wrapf(define.ErrInvalidArg, "Renaming of an image is currently not supported") } @@ -264,10 +264,12 @@ func saveToRemote(image, localFile string, tag string, uri *urlP.URL, iden strin run := podman + " image save " + image + " --format=oci-archive --output=" + remoteFile // run ssh image load of the file copied via scp. Files are reverse in this case... _, err = connection.ExecRemoteCommand(dial, run) if err != nil { - return nil + return err } n, err := scpD.CopyFrom(dial, remoteFile, localFile) - connection.ExecRemoteCommand(dial, "rm "+remoteFile) + if _, conErr := connection.ExecRemoteCommand(dial, "rm "+remoteFile); conErr != nil { + logrus.Errorf("Removing file on endpoint: %v", conErr) + } if err != nil { errOut := strconv.Itoa(int(n)) + " Bytes copied before error" return errors.Wrapf(err, errOut) diff --git a/cmd/podman/images/search.go b/cmd/podman/images/search.go index 292a1d060..aa11cf254 100644 --- a/cmd/podman/images/search.go +++ b/cmd/podman/images/search.go @@ -105,7 +105,7 @@ func searchFlags(cmd *cobra.Command) { // imageSearch implements the command for searching images. func imageSearch(cmd *cobra.Command, args []string) error { - searchTerm := "" + var searchTerm string switch len(args) { case 1: searchTerm = args[0] diff --git a/cmd/podman/images/utils_unsupported.go b/cmd/podman/images/utils_unsupported.go index 69d1df786..7d4a19ded 100644 --- a/cmd/podman/images/utils_unsupported.go +++ b/cmd/podman/images/utils_unsupported.go @@ -1,3 +1,4 @@ +//go:build !linux // +build !linux package images diff --git a/cmd/podman/inspect/inspect.go b/cmd/podman/inspect/inspect.go index ef8a06163..b26b2d667 100644 --- a/cmd/podman/inspect/inspect.go +++ b/cmd/podman/inspect/inspect.go @@ -231,7 +231,7 @@ func (i *inspector) inspect(namesOrIDs []string) error { fmt.Fprintf(os.Stderr, "error inspecting object: %v\n", err) } } - return errors.Errorf("error inspecting object: %v", errs[0]) + return errors.Errorf("inspecting object: %v", errs[0]) } return nil } diff --git a/cmd/podman/machine/init.go b/cmd/podman/machine/init.go index ab13d8651..518e7490f 100644 --- a/cmd/podman/machine/init.go +++ b/cmd/podman/machine/init.go @@ -1,3 +1,4 @@ +//go:build amd64 || arm64 // +build amd64 arm64 package machine @@ -30,6 +31,10 @@ var ( now bool ) +// maxMachineNameSize is set to thirty to limit huge machine names primarily +// because macos has a much smaller file size limit. +const maxMachineNameSize = 30 + func init() { registry.Commands = append(registry.Commands, registry.CliCommand{ Command: initCmd, @@ -82,7 +87,7 @@ func init() { "reexec", false, "process was rexeced", ) - flags.MarkHidden("reexec") + _ = flags.MarkHidden("reexec") ImagePathFlagName := "image-path" flags.StringVar(&initOpts.ImagePath, ImagePathFlagName, cfg.Machine.Image, "Path to qcow image") @@ -101,7 +106,7 @@ func init() { _ = initCmd.RegisterFlagCompletionFunc(IgnitionPathFlagName, completion.AutocompleteDefault) rootfulFlagName := "rootful" - flags.BoolVar(&initOpts.Rootful, rootfulFlagName, false, "Whether this machine should prefer rootful container exectution") + flags.BoolVar(&initOpts.Rootful, rootfulFlagName, false, "Whether this machine should prefer rootful container execution") } // TODO should we allow for a users to append to the qemu cmdline? @@ -110,10 +115,12 @@ func initMachine(cmd *cobra.Command, args []string) error { vm machine.VM err error ) - provider := getSystemDefaultProvider() initOpts.Name = defaultMachineName if len(args) > 0 { + if len(args[0]) > maxMachineNameSize { + return errors.New("machine name must be 30 characters or less") + } initOpts.Name = args[0] } if _, err := provider.LoadVMByName(initOpts.Name); err == nil { diff --git a/cmd/podman/machine/machine.go b/cmd/podman/machine/machine.go index 4937fcbda..d3775f022 100644 --- a/cmd/podman/machine/machine.go +++ b/cmd/podman/machine/machine.go @@ -1,3 +1,4 @@ +//go:build amd64 || arm64 // +build amd64 arm64 package machine diff --git a/cmd/podman/machine/machine_unsupported.go b/cmd/podman/machine/machine_unsupported.go index 2f4189446..e11049888 100644 --- a/cmd/podman/machine/machine_unsupported.go +++ b/cmd/podman/machine/machine_unsupported.go @@ -1,3 +1,4 @@ +//go:build !amd64 && !arm64 // +build !amd64,!arm64 package machine diff --git a/cmd/podman/machine/platform.go b/cmd/podman/machine/platform.go index bbcf06c85..77fec083e 100644 --- a/cmd/podman/machine/platform.go +++ b/cmd/podman/machine/platform.go @@ -1,3 +1,4 @@ +//go:build (amd64 && !windows) || (arm64 && !windows) // +build amd64,!windows arm64,!windows package machine diff --git a/cmd/podman/machine/rm.go b/cmd/podman/machine/rm.go index 38873084a..617a70a76 100644 --- a/cmd/podman/machine/rm.go +++ b/cmd/podman/machine/rm.go @@ -1,3 +1,4 @@ +//go:build amd64 || arm64 // +build amd64 arm64 package machine @@ -26,7 +27,7 @@ var ( ) var ( - destoryOptions machine.RemoveOptions + destroyOptions machine.RemoveOptions ) func init() { @@ -37,16 +38,16 @@ func init() { flags := rmCmd.Flags() formatFlagName := "force" - flags.BoolVar(&destoryOptions.Force, formatFlagName, false, "Do not prompt before rming") + flags.BoolVarP(&destroyOptions.Force, formatFlagName, "f", false, "Stop and do not prompt before rming") keysFlagName := "save-keys" - flags.BoolVar(&destoryOptions.SaveKeys, keysFlagName, false, "Do not delete SSH keys") + flags.BoolVar(&destroyOptions.SaveKeys, keysFlagName, false, "Do not delete SSH keys") ignitionFlagName := "save-ignition" - flags.BoolVar(&destoryOptions.SaveIgnition, ignitionFlagName, false, "Do not delete ignition file") + flags.BoolVar(&destroyOptions.SaveIgnition, ignitionFlagName, false, "Do not delete ignition file") imageFlagName := "save-image" - flags.BoolVar(&destoryOptions.SaveImage, imageFlagName, false, "Do not delete the image file") + flags.BoolVar(&destroyOptions.SaveImage, imageFlagName, false, "Do not delete the image file") } func rm(cmd *cobra.Command, args []string) error { @@ -64,12 +65,12 @@ func rm(cmd *cobra.Command, args []string) error { if err != nil { return err } - confirmationMessage, remove, err := vm.Remove(vmName, machine.RemoveOptions{}) + confirmationMessage, remove, err := vm.Remove(vmName, destroyOptions) if err != nil { return err } - if !destoryOptions.Force { + if !destroyOptions.Force { // Warn user fmt.Println(confirmationMessage) reader := bufio.NewReader(os.Stdin) diff --git a/cmd/podman/machine/set.go b/cmd/podman/machine/set.go index c978206f0..4c15f1de1 100644 --- a/cmd/podman/machine/set.go +++ b/cmd/podman/machine/set.go @@ -1,3 +1,4 @@ +//go:build amd64 || arm64 // +build amd64 arm64 package machine @@ -16,7 +17,7 @@ var ( Long: "Sets an updatable virtual machine setting", RunE: setMachine, Args: cobra.MaximumNArgs(1), - Example: `podman machine set --root=false`, + Example: `podman machine set --rootful=false`, ValidArgsFunction: completion.AutocompleteNone, } ) diff --git a/cmd/podman/machine/ssh.go b/cmd/podman/machine/ssh.go index ba37f7ba4..e1175d632 100644 --- a/cmd/podman/machine/ssh.go +++ b/cmd/podman/machine/ssh.go @@ -1,3 +1,4 @@ +//go:build amd64 || arm64 // +build amd64 arm64 package machine diff --git a/cmd/podman/machine/start.go b/cmd/podman/machine/start.go index 16faa25ef..56acb09cb 100644 --- a/cmd/podman/machine/start.go +++ b/cmd/podman/machine/start.go @@ -57,10 +57,6 @@ func start(cmd *cobra.Command, args []string) error { } return errors.Wrapf(machine.ErrMultipleActiveVM, "cannot start VM %s. VM %s is currently running", vmName, activeName) } - vm, err = provider.LoadVMByName(vmName) - if err != nil { - return err - } fmt.Printf("Starting machine %q\n", vmName) if err := vm.Start(vmName, machine.StartOptions{}); err != nil { return err diff --git a/cmd/podman/main.go b/cmd/podman/main.go index 4f8131653..8f580601e 100644 --- a/cmd/podman/main.go +++ b/cmd/podman/main.go @@ -3,7 +3,6 @@ package main import ( "fmt" "os" - "strings" _ "github.com/containers/podman/v4/cmd/podman/completion" _ "github.com/containers/podman/v4/cmd/podman/containers" @@ -20,6 +19,7 @@ import ( _ "github.com/containers/podman/v4/cmd/podman/system" _ "github.com/containers/podman/v4/cmd/podman/system/connection" _ "github.com/containers/podman/v4/cmd/podman/volumes" + "github.com/containers/podman/v4/pkg/domain/entities" "github.com/containers/podman/v4/pkg/rootless" "github.com/containers/podman/v4/pkg/terminal" "github.com/containers/storage/pkg/reexec" @@ -44,7 +44,29 @@ func parseCommands() *cobra.Command { cfg := registry.PodmanConfig() for _, c := range registry.Commands { if supported, found := c.Command.Annotations[registry.EngineMode]; found { - if !strings.Contains(cfg.EngineMode.String(), supported) { + if cfg.EngineMode.String() != supported { + var client string + switch cfg.EngineMode { + case entities.TunnelMode: + client = "remote" + case entities.ABIMode: + client = "local" + } + + // add error message to the command so the user knows that this command is not supported with local/remote + c.Command.RunE = func(cmd *cobra.Command, args []string) error { + return fmt.Errorf("cannot use command %q with the %s podman client", cmd.CommandPath(), client) + } + // turn of flag parsing to make we do not get flag errors + c.Command.DisableFlagParsing = true + + // mark command as hidden so it is not shown in --help + c.Command.Hidden = true + + // overwrite persistent pre/post function to skip setup + c.Command.PersistentPostRunE = noop + c.Command.PersistentPreRunE = noop + addCommand(c) continue } } @@ -65,22 +87,9 @@ func parseCommands() *cobra.Command { } } } - - parent := rootCmd - if c.Parent != nil { - parent = c.Parent - } - parent.AddCommand(c.Command) - - c.Command.SetFlagErrorFunc(flagErrorFuncfunc) - - // - templates need to be set here, as PersistentPreRunE() is - // not called when --help is used. - // - rootCmd uses cobra default template not ours - c.Command.SetHelpTemplate(helpTemplate) - c.Command.SetUsageTemplate(usageTemplate) - c.Command.DisableFlagsInUseLine = true + addCommand(c) } + if err := terminal.SetConsole(); err != nil { logrus.Error(err) os.Exit(1) @@ -94,3 +103,24 @@ func flagErrorFuncfunc(c *cobra.Command, e error) error { e = fmt.Errorf("%w\nSee '%s --help'", e, c.CommandPath()) return e } + +func addCommand(c registry.CliCommand) { + parent := rootCmd + if c.Parent != nil { + parent = c.Parent + } + parent.AddCommand(c.Command) + + c.Command.SetFlagErrorFunc(flagErrorFuncfunc) + + // - templates need to be set here, as PersistentPreRunE() is + // not called when --help is used. + // - rootCmd uses cobra default template not ours + c.Command.SetHelpTemplate(helpTemplate) + c.Command.SetUsageTemplate(usageTemplate) + c.Command.DisableFlagsInUseLine = true +} + +func noop(cmd *cobra.Command, args []string) error { + return nil +} diff --git a/cmd/podman/networks/create.go b/cmd/podman/networks/create.go index 3dd393c46..84c58d4dc 100644 --- a/cmd/podman/networks/create.go +++ b/cmd/podman/networks/create.go @@ -33,6 +33,8 @@ var ( networkCreateOptions entities.NetworkCreateOptions labels []string opts []string + ipamDriverFlagName = "ipam-driver" + ipamDriver string ) func networkCreateFlags(cmd *cobra.Command) { @@ -60,14 +62,14 @@ func networkCreateFlags(cmd *cobra.Command) { macvlanFlagName := "macvlan" flags.StringVar(&networkCreateOptions.MacVLAN, macvlanFlagName, "", "create a Macvlan connection based on this device") // This option is deprecated - flags.MarkHidden(macvlanFlagName) + _ = flags.MarkHidden(macvlanFlagName) labelFlagName := "label" flags.StringArrayVar(&labels, labelFlagName, nil, "set metadata on a network") _ = cmd.RegisterFlagCompletionFunc(labelFlagName, completion.AutocompleteNone) - // TODO not supported yet - // flags.StringVar(&networkCreateOptions.IPamDriver, "ipam-driver", "", "IP Address Management Driver") + flags.StringVar(&ipamDriver, ipamDriverFlagName, "", "IP Address Management Driver") + _ = cmd.RegisterFlagCompletionFunc(ipamDriverFlagName, common.AutocompleteNetworkIPAMDriver) flags.BoolVar(&networkCreateOptions.IPv6, "ipv6", false, "enable IPv6 networking") @@ -112,6 +114,12 @@ func networkCreate(cmd *cobra.Command, args []string) error { Internal: networkCreateOptions.Internal, } + if cmd.Flags().Changed(ipamDriverFlagName) { + network.IPAMOptions = map[string]string{ + types.Driver: ipamDriver, + } + } + // old --macvlan option if networkCreateOptions.MacVLAN != "" { logrus.Warn("The --macvlan option is deprecated, use `--driver macvlan --opt parent=<device>` instead") diff --git a/cmd/podman/parse/json.go b/cmd/podman/parse/json.go index d7486d0b1..85572a057 100644 --- a/cmd/podman/parse/json.go +++ b/cmd/podman/parse/json.go @@ -4,7 +4,7 @@ import "regexp" var jsonFormatRegex = regexp.MustCompile(`^\s*(json|{{\s*json\s*(\.)?\s*}})\s*$`) -// MatchesJSONFormat test CLI --format string to be a JSON request +// MatchesJSONFormat test CLI --format string to be a JSON request. func MatchesJSONFormat(s string) bool { return jsonFormatRegex.Match([]byte(s)) } diff --git a/cmd/podman/play/kube.go b/cmd/podman/play/kube.go index 1a430f2dc..e92516eb4 100644 --- a/cmd/podman/play/kube.go +++ b/cmd/podman/play/kube.go @@ -4,6 +4,7 @@ import ( "fmt" "net" "os" + "strings" "github.com/containers/common/pkg/auth" "github.com/containers/common/pkg/completion" @@ -31,7 +32,8 @@ type playKubeOptionsWrapper struct { } var ( - macs []string + annotations []string + macs []string // https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/ defaultSeccompRoot = "/var/lib/kubelet/seccomp" kubeOptions = playKubeOptionsWrapper{} @@ -61,6 +63,13 @@ func init() { flags := kubeCmd.Flags() flags.SetNormalizeFunc(utils.AliasFlags) + annotationFlagName := "annotation" + flags.StringSliceVar( + &annotations, + annotationFlagName, []string{}, + "Add annotations to pods (key=value)", + ) + _ = kubeCmd.RegisterFlagCompletionFunc(annotationFlagName, completion.AutocompleteNone) credsFlagName := "creds" flags.StringVar(&kubeOptions.CredentialsCLI, credsFlagName, "", "`Credentials` (USERNAME:PASSWORD) to use for authenticating to a registry") _ = kubeCmd.RegisterFlagCompletionFunc(credsFlagName, completion.AutocompleteNone) @@ -119,9 +128,11 @@ func init() { buildFlagName := "build" flags.BoolVar(&kubeOptions.BuildCLI, buildFlagName, false, "Build all images in a YAML (given Containerfiles exist)") - } - if !registry.IsRemote() { + contextDirFlagName := "context-dir" + flags.StringVar(&kubeOptions.ContextDir, contextDirFlagName, "", "Path to top level of context directory") + _ = kubeCmd.RegisterFlagCompletionFunc(contextDirFlagName, completion.AutocompleteDefault) + flags.StringVar(&kubeOptions.SignaturePolicy, "signature-policy", "", "`Pathname` of signature policy file (not usually used)") _ = flags.MarkHidden("signature-policy") @@ -147,6 +158,9 @@ func kube(cmd *cobra.Command, args []string) error { return err } } + if kubeOptions.ContextDir != "" && kubeOptions.Build != types.OptionalBoolTrue { + return errors.New("--build must be specified when using --context-dir option") + } if kubeOptions.CredentialsCLI != "" { creds, err := util.ParseRegistryCreds(kubeOptions.CredentialsCLI) if err != nil { @@ -156,6 +170,16 @@ func kube(cmd *cobra.Command, args []string) error { kubeOptions.Password = creds.Password } + for _, annotation := range annotations { + splitN := strings.SplitN(annotation, "=", 2) + if len(splitN) > 2 { + return errors.Errorf("annotation %q must include an '=' sign", annotation) + } + if kubeOptions.Annotations == nil { + kubeOptions.Annotations = make(map[string]string) + } + kubeOptions.Annotations[splitN[0]] = splitN[1] + } yamlfile := args[0] if yamlfile == "-" { yamlfile = "/dev/stdin" @@ -185,10 +209,15 @@ func teardown(yamlfile string) error { podRmErrors utils.OutputErrors ) options := new(entities.PlayKubeDownOptions) - reports, err := registry.ContainerEngine().PlayKubeDown(registry.GetContext(), yamlfile, *options) + f, err := os.Open(yamlfile) if err != nil { return err } + defer f.Close() + reports, err := registry.ContainerEngine().PlayKubeDown(registry.GetContext(), f, *options) + if err != nil { + return errors.Wrap(err, yamlfile) + } // Output stopped pods fmt.Println("Pods stopped:") @@ -218,10 +247,15 @@ func teardown(yamlfile string) error { } func playkube(yamlfile string) error { - report, err := registry.ContainerEngine().PlayKube(registry.GetContext(), yamlfile, kubeOptions.PlayKubeOptions) + f, err := os.Open(yamlfile) if err != nil { return err } + defer f.Close() + report, err := registry.ContainerEngine().PlayKube(registry.GetContext(), f, kubeOptions.PlayKubeOptions) + if err != nil { + return errors.Wrap(err, yamlfile) + } // Print volumes report for i, volume := range report.Volumes { if i == 0 { diff --git a/cmd/podman/pods/create.go b/cmd/podman/pods/create.go index ab3a6d578..b45ed0d39 100644 --- a/cmd/podman/pods/create.go +++ b/cmd/podman/pods/create.go @@ -179,7 +179,7 @@ func create(cmd *cobra.Command, args []string) error { return errors.Errorf("pod id file exists. Ensure another pod is not using it or delete %s", podIDFile) } if err != nil { - return errors.Errorf("error opening pod-id-file %s", podIDFile) + return errors.Errorf("opening pod-id-file %s", podIDFile) } defer errorhandling.CloseQuiet(podIDFD) defer errorhandling.SyncQuiet(podIDFD) diff --git a/cmd/podman/pods/logs.go b/cmd/podman/pods/logs.go index e35b48bed..28e7b7a43 100644 --- a/cmd/podman/pods/logs.go +++ b/cmd/podman/pods/logs.go @@ -89,6 +89,8 @@ func logsFlags(cmd *cobra.Command) { flags.BoolVarP(&logsPodOptions.Names, "names", "n", false, "Output container names instead of container IDs in the log") flags.BoolVarP(&logsPodOptions.Timestamps, "timestamps", "t", false, "Output the timestamps in the log") + flags.BoolVarP(&logsPodOptions.Colors, "color", "", false, "Output the containers within a pod with different colors in the log") + flags.SetInterspersed(false) _ = flags.MarkHidden("details") } diff --git a/cmd/podman/registry/config_abi.go b/cmd/podman/registry/config_abi.go index 4a909c17e..7babfa169 100644 --- a/cmd/podman/registry/config_abi.go +++ b/cmd/podman/registry/config_abi.go @@ -1,3 +1,4 @@ +//go:build !remote // +build !remote package registry diff --git a/cmd/podman/registry/config_tunnel.go b/cmd/podman/registry/config_tunnel.go index bb3da947e..dfdbab8f8 100644 --- a/cmd/podman/registry/config_tunnel.go +++ b/cmd/podman/registry/config_tunnel.go @@ -1,3 +1,4 @@ +//go:build remote // +build remote package registry diff --git a/cmd/podman/root.go b/cmd/podman/root.go index 6d768c2e6..500a475bd 100644 --- a/cmd/podman/root.go +++ b/cmd/podman/root.go @@ -402,7 +402,7 @@ func rootFlags(cmd *cobra.Command, opts *entities.PodmanConfig) { networkBackendFlagName := "network-backend" pFlags.StringVar(&cfg.Network.NetworkBackend, networkBackendFlagName, cfg.Network.NetworkBackend, `Network backend to use ("cni"|"netavark")`) _ = cmd.RegisterFlagCompletionFunc(networkBackendFlagName, common.AutocompleteNetworkBackend) - pFlags.MarkHidden(networkBackendFlagName) + _ = pFlags.MarkHidden(networkBackendFlagName) rootFlagName := "root" pFlags.StringVar(&cfg.Engine.StaticDir, rootFlagName, "", "Path to the root directory in which data, including images, is stored") diff --git a/cmd/podman/secrets/inspect.go b/cmd/podman/secrets/inspect.go index 1948fef49..0977434f7 100644 --- a/cmd/podman/secrets/inspect.go +++ b/cmd/podman/secrets/inspect.go @@ -76,7 +76,7 @@ func inspect(cmd *cobra.Command, args []string) error { fmt.Fprintf(os.Stderr, "error inspecting secret: %v\n", err) } } - return errors.Errorf("error inspecting secret: %v", errs[0]) + return errors.Errorf("inspecting secret: %v", errs[0]) } return nil } diff --git a/cmd/podman/syslog_unsupported.go b/cmd/podman/syslog_unsupported.go index 3765d96b9..42a7851ab 100644 --- a/cmd/podman/syslog_unsupported.go +++ b/cmd/podman/syslog_unsupported.go @@ -1,3 +1,4 @@ +//go:build !linux // +build !linux package main diff --git a/cmd/podman/system/connection/add.go b/cmd/podman/system/connection/add.go index 324e02db4..db575a689 100644 --- a/cmd/podman/system/connection/add.go +++ b/cmd/podman/system/connection/add.go @@ -244,7 +244,7 @@ func getUDS(cmd *cobra.Command, uri *url.URL, iden string) (string, error) { // ValidateAndConfigure will take a ssh url and an identity key (rsa and the like) and ensure the information given is valid // iden iden can be blank to mean no identity key -// once the function validates the information it creates and returns an ssh.ClientConfig +// once the function validates the information it creates and returns an ssh.ClientConfig. func ValidateAndConfigure(uri *url.URL, iden string) (*ssh.ClientConfig, error) { var signers []ssh.Signer passwd, passwdSet := uri.User.Password() diff --git a/cmd/podman/system/connection/default.go b/cmd/podman/system/connection/default.go index c59ff36af..81866df55 100644 --- a/cmd/podman/system/connection/default.go +++ b/cmd/podman/system/connection/default.go @@ -11,7 +11,7 @@ import ( ) var ( - // Skip creating engines since this command will obtain connection information to said engines + // Skip creating engines since this command will obtain connection information to said engines. dfltCmd = &cobra.Command{ Use: "default NAME", Args: cobra.ExactArgs(1), diff --git a/cmd/podman/system/connection/remove.go b/cmd/podman/system/connection/remove.go index 84ec3e2ee..463eae9fa 100644 --- a/cmd/podman/system/connection/remove.go +++ b/cmd/podman/system/connection/remove.go @@ -10,7 +10,7 @@ import ( ) var ( - // Skip creating engines since this command will obtain connection information to said engines + // Skip creating engines since this command will obtain connection information to said engines. rmCmd = &cobra.Command{ Use: "remove [options] NAME", Aliases: []string{"rm"}, diff --git a/cmd/podman/system/df.go b/cmd/podman/system/df.go index b2325507a..dad14df6b 100644 --- a/cmd/podman/system/df.go +++ b/cmd/podman/system/df.go @@ -2,6 +2,7 @@ package system import ( "fmt" + "math" "os" "strings" "time" @@ -170,7 +171,7 @@ func printVerbose(cmd *cobra.Command, reports *entities.SystemDfReport) error { return err } if err := writeTemplate(rpt, hdrs, dfImages); err != nil { - return nil + return err } fmt.Fprint(rpt.Writer(), "\nContainers space usage:\n\n") @@ -190,7 +191,7 @@ func printVerbose(cmd *cobra.Command, reports *entities.SystemDfReport) error { return err } if err := writeTemplate(rpt, hdrs, dfContainers); err != nil { - return nil + return err } fmt.Fprint(rpt.Writer(), "\nLocal Volumes space usage:\n\n") @@ -288,6 +289,10 @@ func (d *dfSummary) Size() string { } func (d *dfSummary) Reclaimable() string { - percent := int(float64(d.reclaimable)/float64(d.size)) * 100 + percent := 0 + // make sure to check this to prevent div by zero problems + if d.size > 0 { + percent = int(math.Round(float64(d.reclaimable) / float64(d.size) * float64(100))) + } return fmt.Sprintf("%s (%d%%)", units.HumanSize(float64(d.reclaimable)), percent) } diff --git a/cmd/podman/system/dial_stdio.go b/cmd/podman/system/dial_stdio.go index f3445a49d..8b665bedc 100644 --- a/cmd/podman/system/dial_stdio.go +++ b/cmd/podman/system/dial_stdio.go @@ -88,10 +88,10 @@ func runDialStdio() error { 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) + logrus.Errorf("while CloseRead (%s): %v", debugDescription, err) } if err := to.CloseWrite(); err != nil { - logrus.Errorf("error while CloseWrite (%s): %v", debugDescription, err) + logrus.Errorf("while CloseWrite (%s): %v", debugDescription, err) } }() if _, err := io.Copy(to, from); err != nil { diff --git a/cmd/podman/system/migrate.go b/cmd/podman/system/migrate.go index c6b6546e7..5d7b31314 100644 --- a/cmd/podman/system/migrate.go +++ b/cmd/podman/system/migrate.go @@ -1,3 +1,4 @@ +//go:build !remote // +build !remote package system diff --git a/cmd/podman/system/renumber.go b/cmd/podman/system/renumber.go index b310dc607..f24488822 100644 --- a/cmd/podman/system/renumber.go +++ b/cmd/podman/system/renumber.go @@ -1,3 +1,4 @@ +//go:build !remote // +build !remote package system diff --git a/cmd/podman/system/reset.go b/cmd/podman/system/reset.go index 07904faaa..e8cf127b7 100644 --- a/cmd/podman/system/reset.go +++ b/cmd/podman/system/reset.go @@ -1,3 +1,4 @@ +//go:build !remote // +build !remote package system diff --git a/cmd/podman/system/service.go b/cmd/podman/system/service.go index daf252401..1a93b3137 100644 --- a/cmd/podman/system/service.go +++ b/cmd/podman/system/service.go @@ -1,3 +1,4 @@ +//go:build linux && !remote // +build linux,!remote package system @@ -66,7 +67,7 @@ func init() { flags.StringVarP(&srvArgs.PProfAddr, "pprof-address", "", "", "Binding network address for pprof profile endpoints, default: do not expose endpoints") - flags.MarkHidden("pprof-address") + _ = flags.MarkHidden("pprof-address") } func aliasTimeoutFlag(_ *pflag.FlagSet, name string) pflag.NormalizedName { diff --git a/cmd/podman/system/service_abi.go b/cmd/podman/system/service_abi.go index 560cce847..d6b42ed29 100644 --- a/cmd/podman/system/service_abi.go +++ b/cmd/podman/system/service_abi.go @@ -1,3 +1,4 @@ +//go:build linux && !remote // +build linux,!remote package system diff --git a/cmd/podman/system/version.go b/cmd/podman/system/version.go index 6239482b5..9fb4a966a 100644 --- a/cmd/podman/system/version.go +++ b/cmd/podman/system/version.go @@ -89,9 +89,7 @@ Client:\tPodman Engine Version:\t{{.Version}} API Version:\t{{.APIVersion}} Go Version:\t{{.GoVersion}} -{{if .GitCommit -}} - Git Commit:\t{{.GitCommit}} -{{- end}} +{{if .GitCommit -}}Git Commit:\t{{.GitCommit}}\n{{end -}} Built:\t{{.BuiltTime}} OS/Arch:\t{{.OsArch}} {{- end}} @@ -102,9 +100,7 @@ Server:\tPodman Engine Version:\t{{.Version}} API Version:\t{{.APIVersion}} Go Version:\t{{.GoVersion}} -{{if .GitCommit -}} - Git Commit:\t{{.GitCommit}} -{{- end}} +{{if .GitCommit -}}Git Commit:\t{{.GitCommit}}\n{{end -}} Built:\t{{.BuiltTime}} OS/Arch:\t{{.OsArch}} {{- end}}{{- end}} diff --git a/cmd/podman/utils/error.go b/cmd/podman/utils/error.go index b3b54876f..2aaa71373 100644 --- a/cmd/podman/utils/error.go +++ b/cmd/podman/utils/error.go @@ -41,5 +41,5 @@ func ExitCodeFromBuildError(errorMsg string) (int, error) { return buildahCLI.ExecErrorCodeGeneric, err } } - return buildahCLI.ExecErrorCodeGeneric, errors.New("error message does not contains a valid exit code") + return buildahCLI.ExecErrorCodeGeneric, errors.New("message does not contains a valid exit code") } diff --git a/cmd/podman/utils/signals_linux.go b/cmd/podman/utils/signals_linux.go index f0a14aff0..dd0507c0e 100644 --- a/cmd/podman/utils/signals_linux.go +++ b/cmd/podman/utils/signals_linux.go @@ -1,3 +1,4 @@ +//go:build !windows // +build !windows package utils diff --git a/cmd/podman/utils/signals_windows.go b/cmd/podman/utils/signals_windows.go index 30b058cb9..e6fcc1b32 100644 --- a/cmd/podman/utils/signals_windows.go +++ b/cmd/podman/utils/signals_windows.go @@ -1,3 +1,4 @@ +//go:build windows // +build windows package utils diff --git a/cmd/podman/validate/args.go b/cmd/podman/validate/args.go index 1642e2280..743ee1837 100644 --- a/cmd/podman/validate/args.go +++ b/cmd/podman/validate/args.go @@ -27,7 +27,7 @@ func SubCommandExists(cmd *cobra.Command, args []string) error { } return errors.Errorf("unrecognized command `%[1]s %[2]s`\n\nDid you mean this?\n\t%[3]s\n\nTry '%[1]s --help' for more information.", cmd.CommandPath(), args[0], strings.Join(suggestions, "\n\t")) } - cmd.Help() + cmd.Help() // nolint: errcheck return errors.Errorf("missing command '%[1]s COMMAND'", cmd.CommandPath()) } diff --git a/cmd/rootlessport/main.go b/cmd/rootlessport/main.go index 37e91fca8..e9ab8b076 100644 --- a/cmd/rootlessport/main.go +++ b/cmd/rootlessport/main.go @@ -253,9 +253,9 @@ func serve(listener net.Listener, pm rkport.Manager) { ctx := context.TODO() err = handler(ctx, conn, pm) if err != nil { - conn.Write([]byte(err.Error())) + _, _ = conn.Write([]byte(err.Error())) } else { - conn.Write([]byte("OK")) + _, _ = conn.Write([]byte("OK")) } conn.Close() } |
