diff options
306 files changed, 7474 insertions, 1489 deletions
diff --git a/.cirrus.yml b/.cirrus.yml index 1eb516d84..d32275a39 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -30,17 +30,20 @@ env: PRIOR_UBUNTU_NAME: "ubuntu-2010" # Google-cloud VM Images + # TODO: At the time of this comment, an selinux-policy regression is blocking use of updated + # Fedora VM images: https://bugzilla.redhat.com/show_bug.cgi?id=1965743 + IMAGE_SUFFIX_UBUNTU: "c5521575421149184" IMAGE_SUFFIX: "c5348179051806720" FEDORA_CACHE_IMAGE_NAME: "fedora-${IMAGE_SUFFIX}" PRIOR_FEDORA_CACHE_IMAGE_NAME: "prior-fedora-${IMAGE_SUFFIX}" - UBUNTU_CACHE_IMAGE_NAME: "ubuntu-${IMAGE_SUFFIX}" - PRIOR_UBUNTU_CACHE_IMAGE_NAME: "prior-ubuntu-${IMAGE_SUFFIX}" + UBUNTU_CACHE_IMAGE_NAME: "ubuntu-${IMAGE_SUFFIX_UBUNTU}" + PRIOR_UBUNTU_CACHE_IMAGE_NAME: "prior-ubuntu-${IMAGE_SUFFIX_UBUNTU}" # Container FQIN's FEDORA_CONTAINER_FQIN: "quay.io/libpod/fedora_podman:${IMAGE_SUFFIX}" PRIOR_FEDORA_CONTAINER_FQIN: "quay.io/libpod/prior-fedora_podman:${IMAGE_SUFFIX}" - UBUNTU_CONTAINER_FQIN: "quay.io/libpod/ubuntu_podman:${IMAGE_SUFFIX}" - PRIOR_UBUNTU_CONTAINER_FQIN: "quay.io/libpod/prior-ubuntu_podman:${IMAGE_SUFFIX}" + UBUNTU_CONTAINER_FQIN: "quay.io/libpod/ubuntu_podman:${IMAGE_SUFFIX_UBUNTU}" + PRIOR_UBUNTU_CONTAINER_FQIN: "quay.io/libpod/prior-ubuntu_podman:${IMAGE_SUFFIX_UBUNTU}" #### #### Control variables that determine what to run and how to run it. @@ -670,11 +673,18 @@ meta_task: image: quay.io/libpod/imgts:$IMAGE_SUFFIX env: # Space-separated list of images used by this repository state + # TODO: Protect commonly tagged ubuntu images from puning in case + # workaround for BZ1965743 remains in use beyond the 30-days. + # Ref sha 404d5edb155 IMGNAMES: >- ${FEDORA_CACHE_IMAGE_NAME} ${PRIOR_FEDORA_CACHE_IMAGE_NAME} ${UBUNTU_CACHE_IMAGE_NAME} ${PRIOR_UBUNTU_CACHE_IMAGE_NAME} + fedora-${IMAGE_SUFFIX_UBUNTU} + prior-fedora-${IMAGE_SUFFIX_UBUNTU} + ubuntu-${IMAGE_SUFFIX} + prior-ubuntu-${IMAGE_SUFFIX} BUILDID: "${CIRRUS_BUILD_ID}" REPOREF: "${CIRRUS_REPO_NAME}" GCPJSON: ENCRYPTED[3a198350077849c8df14b723c0f4c9fece9ebe6408d35982e7adf2105a33f8e0e166ed3ed614875a0887e1af2b8775f4] diff --git a/.github/workflows/multi-arch-build.yaml b/.github/workflows/multi-arch-build.yaml index 2ade44ee6..9bd98078b 100644 --- a/.github/workflows/multi-arch-build.yaml +++ b/.github/workflows/multi-arch-build.yaml @@ -72,7 +72,10 @@ jobs: if: matrix.source == 'stable' id: sniff_test run: | - VERSION_OUTPUT="$(docker run localhost:5000/podman/${{ matrix.source }} \ + podman pull --tls-verify=false \ + localhost:5000/podman/${{ matrix.source }} + VERSION_OUTPUT="$(podman run \ + localhost:5000/podman/${{ matrix.source }} \ podman --storage-driver=vfs version)" echo "$VERSION_OUTPUT" VERSION=$(grep -Em1 '^Version: ' <<<"$VERSION_OUTPUT" | awk '{print $2}') diff --git a/CODE-OF-CONDUCT.md b/CODE-OF-CONDUCT.md index b23672b1a..e418693f7 100644 --- a/CODE-OF-CONDUCT.md +++ b/CODE-OF-CONDUCT.md @@ -1,3 +1,3 @@ ## The Podman Project Community Code of Conduct -The Podman project which includes Libpod, follows the [Containers Community Code of Conduct](https://github.com/containers/common/blob/master/CODE-OF-CONDUCT.md). +The Podman project which includes Libpod, follows the [Containers Community Code of Conduct](https://github.com/containers/common/blob/main/CODE-OF-CONDUCT.md). @@ -93,11 +93,14 @@ LIBPOD := ${PROJECT}/v3/libpod GCFLAGS ?= all=-trimpath=$(CURDIR) ASMFLAGS ?= all=-trimpath=$(CURDIR) LDFLAGS_PODMAN ?= \ - -X $(LIBPOD)/define.gitCommit=$(GIT_COMMIT) \ - -X $(LIBPOD)/define.buildInfo=$(BUILD_INFO) \ - -X $(LIBPOD)/config._installPrefix=$(PREFIX) \ - -X $(LIBPOD)/config._etcDir=$(ETCDIR) \ - $(EXTRA_LDFLAGS) + -X $(LIBPOD)/define.gitCommit=$(GIT_COMMIT) \ + -X $(LIBPOD)/define.buildInfo=$(BUILD_INFO) \ + -X $(LIBPOD)/config._installPrefix=$(PREFIX) \ + -X $(LIBPOD)/config._etcDir=$(ETCDIR) \ + $(EXTRA_LDFLAGS) +LDFLAGS_PODMAN_STATIC ?= \ + $(LDFLAGS_PODMAN) \ + -extldflags=-static #Update to LIBSECCOMP_COMMIT should reflect in Dockerfile too. LIBSECCOMP_COMMIT := v2.3.3 # Rarely if ever should integration tests take more than 50min, @@ -314,7 +317,7 @@ $(SRCBINDIR)/podman$(BINSFX): $(SRCBINDIR) .gopathok $(SOURCES) go.mod go.sum -o $@ ./cmd/podman $(SRCBINDIR)/podman-remote-static: $(SRCBINDIR) .gopathok $(SOURCES) go.mod go.sum - CGO_ENABLED=$(CGO_ENABLED) \ + CGO_ENABLED=0 \ GOOS=$(GOOS) \ $(GO) build \ $(BUILDFLAGS) \ @@ -389,10 +392,10 @@ cross: local-cross .PHONY: nixpkgs nixpkgs: @nix run \ - -f channel:nixos-20.09 nix-prefetch-git \ + -f channel:nixos-21.05 nix-prefetch-git \ -c nix-prefetch-git \ --no-deepClone \ - https://github.com/nixos/nixpkgs refs/heads/nixos-20.09 > nix/nixpkgs.json + https://github.com/nixos/nixpkgs refs/heads/nixos-21.05 > nix/nixpkgs.json # Build statically linked binary .PHONY: static @@ -437,7 +440,7 @@ $(MANPAGES): %: %.md .install.md2man docdir -e 's/\[\(podman[^]]*\)\]/\1/g' \ -e 's/\[\([^]]*\)](http[^)]\+)/\1/g' \ -e 's;<\(/\)\?\(a\|a\s\+[^>]*\|sup\)>;;g' \ - -e 's/\\$// /g' $< | \ + -e 's/\\$$/ /g' $< | \ $(GOMD2MAN) -in /dev/stdin -out $(subst source/markdown,build/man,$@) .PHONY: docdir @@ -748,11 +751,13 @@ install.systemd: install ${SELINUXOPT} -m 644 contrib/systemd/auto-update/podman-auto-update.timer ${DESTDIR}${USERSYSTEMDDIR}/podman-auto-update.timer install ${SELINUXOPT} -m 644 contrib/systemd/user/podman.socket ${DESTDIR}${USERSYSTEMDDIR}/podman.socket install ${SELINUXOPT} -m 644 contrib/systemd/user/podman.service ${DESTDIR}${USERSYSTEMDDIR}/podman.service + install ${SELINUXOPT} -m 644 contrib/systemd/user/podman-restart.service ${DESTDIR}${USERSYSTEMDDIR}/podman-restart.service # System services install ${SELINUXOPT} -m 644 contrib/systemd/auto-update/podman-auto-update.service ${DESTDIR}${SYSTEMDDIR}/podman-auto-update.service install ${SELINUXOPT} -m 644 contrib/systemd/auto-update/podman-auto-update.timer ${DESTDIR}${SYSTEMDDIR}/podman-auto-update.timer install ${SELINUXOPT} -m 644 contrib/systemd/system/podman.socket ${DESTDIR}${SYSTEMDDIR}/podman.socket install ${SELINUXOPT} -m 644 contrib/systemd/system/podman.service ${DESTDIR}${SYSTEMDDIR}/podman.service + install ${SELINUXOPT} -m 644 contrib/systemd/system/podman-restart.service ${DESTDIR}${SYSTEMDDIR}/podman-restart.service else install.systemd: endif diff --git a/SECURITY.md b/SECURITY.md index 03a192044..1f6d5088d 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -1,3 +1,3 @@ ## Security and Disclosure Information Policy for the Libpod Project -The Libpod Project follows the [Security and Disclosure Information Policy](https://github.com/containers/common/blob/master/SECURITY.md) for the Containers Projects. +The Libpod Project follows the [Security and Disclosure Information Policy](https://github.com/containers/common/blob/main/SECURITY.md) for the Containers Projects. diff --git a/cmd/podman/containers/create.go b/cmd/podman/containers/create.go index 68a17abd0..2144a6e10 100644 --- a/cmd/podman/containers/create.go +++ b/cmd/podman/containers/create.go @@ -8,7 +8,6 @@ import ( "strings" "github.com/containers/common/pkg/config" - storageTransport "github.com/containers/image/v5/storage" "github.com/containers/image/v5/transports/alltransports" "github.com/containers/podman/v3/cmd/podman/common" "github.com/containers/podman/v3/cmd/podman/registry" @@ -16,9 +15,7 @@ import ( "github.com/containers/podman/v3/pkg/domain/entities" "github.com/containers/podman/v3/pkg/specgen" "github.com/containers/podman/v3/pkg/util" - "github.com/containers/storage" "github.com/pkg/errors" - "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -236,30 +233,12 @@ func createInit(c *cobra.Command) error { return nil } -// TODO: we should let the backend take care of the pull policy (which it -// does!). The code below is at risk of causing regression and code divergence. func pullImage(imageName string) (string, error) { pullPolicy, err := config.ValidatePullPolicy(cliVals.Pull) if err != nil { return "", err } - // Check if the image is missing and hence if we need to pull it. - imageMissing := true - imageRef, err := alltransports.ParseImageName(imageName) - switch { - case err != nil: - // Assume we specified a local image without the explicit storage transport. - fallthrough - - case imageRef.Transport().Name() == storageTransport.Transport.Name(): - br, err := registry.ImageEngine().Exists(registry.GetContext(), imageName) - if err != nil { - return "", err - } - imageMissing = !br.Value - } - if cliVals.Platform != "" || cliVals.Arch != "" || cliVals.OS != "" { if cliVals.Platform != "" { if cliVals.Arch != "" || cliVals.OS != "" { @@ -271,31 +250,28 @@ func pullImage(imageName string) (string, error) { cliVals.Arch = split[1] } } + } - if pullPolicy != config.PullPolicyAlways { - logrus.Info("--platform --arch and --os causes the pull policy to be \"always\"") - pullPolicy = config.PullPolicyAlways - } + pullReport, pullErr := registry.ImageEngine().Pull(registry.GetContext(), imageName, entities.ImagePullOptions{ + Authfile: cliVals.Authfile, + Quiet: cliVals.Quiet, + Arch: cliVals.Arch, + OS: cliVals.OS, + Variant: cliVals.Variant, + SignaturePolicy: cliVals.SignaturePolicy, + PullPolicy: pullPolicy, + }) + if pullErr != nil { + return "", pullErr } - if imageMissing || pullPolicy == config.PullPolicyAlways { - if pullPolicy == config.PullPolicyNever { - return "", errors.Wrap(storage.ErrImageUnknown, imageName) - } - pullReport, pullErr := registry.ImageEngine().Pull(registry.GetContext(), imageName, entities.ImagePullOptions{ - Authfile: cliVals.Authfile, - Quiet: cliVals.Quiet, - Arch: cliVals.Arch, - OS: cliVals.OS, - Variant: cliVals.Variant, - SignaturePolicy: cliVals.SignaturePolicy, - PullPolicy: pullPolicy, - }) - if pullErr != nil { - return "", pullErr - } + // Return the input name such that the image resolves to correct + // repo/tag in the backend (see #8082). Unless we're referring to + // the image via a transport. + if _, err := alltransports.ParseImageName(imageName); err == nil { imageName = pullReport.Images[0] } + return imageName, nil } diff --git a/cmd/podman/containers/mount.go b/cmd/podman/containers/mount.go index 8a7c542ba..55f6a1c34 100644 --- a/cmd/podman/containers/mount.go +++ b/cmd/podman/containers/mount.go @@ -3,8 +3,6 @@ package containers import ( "fmt" "os" - "text/tabwriter" - "text/template" "github.com/containers/common/pkg/report" "github.com/containers/podman/v3/cmd/podman/common" @@ -117,12 +115,16 @@ func mount(_ *cobra.Command, args []string) error { mrs = append(mrs, mountReporter{r}) } - format := "{{range . }}{{.ID}}\t{{.Path}}\n{{end}}" - tmpl, err := template.New("mounts").Parse(format) + format := "{{range . }}{{.ID}}\t{{.Path}}\n{{end -}}" + tmpl, err := report.NewTemplate("mounts").Parse(format) + if err != nil { + return err + } + + w, err := report.NewWriterDefault(os.Stdout) if err != nil { return err } - w := tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', 0) defer w.Flush() return tmpl.Execute(w, mrs) } diff --git a/cmd/podman/containers/ps.go b/cmd/podman/containers/ps.go index 352f67f4e..a5b0795cd 100644 --- a/cmd/podman/containers/ps.go +++ b/cmd/podman/containers/ps.go @@ -6,15 +6,12 @@ import ( "sort" "strconv" "strings" - "text/tabwriter" - "text/template" "time" tm "github.com/buger/goterm" "github.com/containers/common/pkg/completion" "github.com/containers/common/pkg/report" "github.com/containers/podman/v3/cmd/podman/common" - "github.com/containers/podman/v3/cmd/podman/parse" "github.com/containers/podman/v3/cmd/podman/registry" "github.com/containers/podman/v3/cmd/podman/utils" "github.com/containers/podman/v3/cmd/podman/validate" @@ -226,18 +223,20 @@ func ps(cmd *cobra.Command, _ []string) error { hdrs, format := createPsOut() if cmd.Flags().Changed("format") { format = report.NormalizeFormat(listOpts.Format) - format = parse.EnforceRange(format) + format = report.EnforceRange(format) } ns := strings.NewReplacer(".Namespaces.", ".") format = ns.Replace(format) - tmpl, err := template.New("listContainers"). - Funcs(template.FuncMap(report.DefaultFuncs)). - Parse(format) + tmpl, err := report.NewTemplate("list").Parse(format) + if err != nil { + return err + } + + w, err := report.NewWriterDefault(os.Stdout) if err != nil { return err } - w := tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', 0) defer w.Flush() headers := func() error { return nil } @@ -320,7 +319,7 @@ func createPsOut() ([]map[string]string, string) { row += "\t{{.Size}}" } } - return hdrs, "{{range .}}" + row + "\n{{end}}" + return hdrs, "{{range .}}" + row + "\n{{end -}}" } type psReporter struct { diff --git a/cmd/podman/containers/stats.go b/cmd/podman/containers/stats.go index 568e410d2..208d5d58f 100644 --- a/cmd/podman/containers/stats.go +++ b/cmd/podman/containers/stats.go @@ -3,13 +3,10 @@ package containers import ( "fmt" "os" - "text/tabwriter" - "text/template" tm "github.com/buger/goterm" "github.com/containers/common/pkg/report" "github.com/containers/podman/v3/cmd/podman/common" - "github.com/containers/podman/v3/cmd/podman/parse" "github.com/containers/podman/v3/cmd/podman/registry" "github.com/containers/podman/v3/cmd/podman/validate" "github.com/containers/podman/v3/libpod/define" @@ -146,7 +143,9 @@ func stats(cmd *cobra.Command, args []string) error { func outputStats(reports []define.ContainerStats) error { headers := report.Headers(define.ContainerStats{}, map[string]string{ "ID": "ID", + "UpTime": "CPU TIME", "CPUPerc": "CPU %", + "AVGCPU": "Avg CPU %", "MemUsage": "MEM USAGE / LIMIT", "MemUsageBytes": "MEM USAGE / LIMIT", "MemPerc": "MEM %", @@ -166,17 +165,21 @@ func outputStats(reports []define.ContainerStats) error { if report.IsJSON(statsOptions.Format) { return outputJSON(stats) } - format := "{{.ID}}\t{{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.MemPerc}}\t{{.NetIO}}\t{{.BlockIO}}\t{{.PIDS}}\n" + format := "{{.ID}}\t{{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.MemPerc}}\t{{.NetIO}}\t{{.BlockIO}}\t{{.PIDS}}\t{{.UpTime}}\t{{.AVGCPU}}\n" if len(statsOptions.Format) > 0 { format = report.NormalizeFormat(statsOptions.Format) } - format = parse.EnforceRange(format) + format = report.EnforceRange(format) - tmpl, err := template.New("stats").Parse(format) + tmpl, err := report.NewTemplate("stats").Parse(format) + if err != nil { + return err + } + + w, err := report.NewWriterDefault(os.Stdout) if err != nil { return err } - w := tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', 0) defer w.Flush() if len(statsOptions.Format) < 1 { @@ -202,6 +205,14 @@ func (s *containerStats) CPUPerc() string { return floatToPercentString(s.CPU) } +func (s *containerStats) AVGCPU() string { + return floatToPercentString(s.AvgCPU) +} + +func (s *containerStats) Up() string { + return (s.UpTime.String()) +} + func (s *containerStats) MemPerc() string { return floatToPercentString(s.ContainerStats.MemPerc) } @@ -257,7 +268,9 @@ func outputJSON(stats []containerStats) error { type jstat struct { Id string `json:"id"` // nolint Name string `json:"name"` + CPUTime string `json:"cpu_time"` CpuPercent string `json:"cpu_percent"` // nolint + AverageCPU string `json:"avg_cpu"` MemUsage string `json:"mem_usage"` MemPerc string `json:"mem_percent"` NetIO string `json:"net_io"` @@ -269,7 +282,9 @@ func outputJSON(stats []containerStats) error { jstats = append(jstats, jstat{ Id: j.ID(), Name: j.Name, + CPUTime: j.Up(), CpuPercent: j.CPUPerc(), + AverageCPU: j.AVGCPU(), MemUsage: j.MemUsage(), MemPerc: j.MemPerc(), NetIO: j.NetIO(), diff --git a/cmd/podman/containers/top.go b/cmd/podman/containers/top.go index 3fde2e954..808c6c494 100644 --- a/cmd/podman/containers/top.go +++ b/cmd/podman/containers/top.go @@ -5,8 +5,8 @@ import ( "fmt" "os" "strings" - "text/tabwriter" + "github.com/containers/common/pkg/report" "github.com/containers/podman/v3/cmd/podman/common" "github.com/containers/podman/v3/cmd/podman/registry" "github.com/containers/podman/v3/cmd/podman/validate" @@ -77,7 +77,7 @@ func init() { validate.AddLatestFlag(containerTopCommand, &topOptions.Latest) } -func top(cmd *cobra.Command, args []string) error { +func top(_ *cobra.Command, args []string) error { if topOptions.ListDescriptors { descriptors, err := util.GetContainerPidInformationDescriptors() if err != nil { @@ -103,7 +103,11 @@ func top(cmd *cobra.Command, args []string) error { return err } - w := tabwriter.NewWriter(os.Stdout, 5, 1, 3, ' ', 0) + w, err := report.NewWriterDefault(os.Stdout) + if err != nil { + return err + } + for _, proc := range topResponse.Value { if _, err := fmt.Fprintln(w, proc); err != nil { return err diff --git a/cmd/podman/images/history.go b/cmd/podman/images/history.go index 69268c261..c065acfad 100644 --- a/cmd/podman/images/history.go +++ b/cmd/podman/images/history.go @@ -5,14 +5,11 @@ import ( "fmt" "os" "strings" - "text/tabwriter" - "text/template" "time" "unicode" "github.com/containers/common/pkg/report" "github.com/containers/podman/v3/cmd/podman/common" - "github.com/containers/podman/v3/cmd/podman/parse" "github.com/containers/podman/v3/cmd/podman/registry" "github.com/containers/podman/v3/pkg/domain/entities" "github.com/docker/go-units" @@ -125,13 +122,17 @@ func history(cmd *cobra.Command, args []string) error { case opts.quiet: row = "{{.ID}}\n" } - format := parse.EnforceRange(row) + format := report.EnforceRange(row) - tmpl, err := template.New("report").Parse(format) + tmpl, err := report.NewTemplate("history").Parse(format) + if err != nil { + return err + } + + w, err := report.NewWriterDefault(os.Stdout) if err != nil { return err } - w := tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', 0) defer w.Flush() if !opts.quiet && !cmd.Flags().Changed("format") { diff --git a/cmd/podman/images/list.go b/cmd/podman/images/list.go index cc38a45c7..01286daf2 100644 --- a/cmd/podman/images/list.go +++ b/cmd/podman/images/list.go @@ -5,8 +5,6 @@ import ( "os" "sort" "strings" - "text/tabwriter" - "text/template" "time" "unicode" @@ -14,7 +12,6 @@ import ( "github.com/containers/common/pkg/report" "github.com/containers/image/v5/docker/reference" "github.com/containers/podman/v3/cmd/podman/common" - "github.com/containers/podman/v3/cmd/podman/parse" "github.com/containers/podman/v3/cmd/podman/registry" "github.com/containers/podman/v3/pkg/domain/entities" "github.com/docker/go-units" @@ -140,7 +137,7 @@ func images(cmd *cobra.Command, args []string) error { case listFlag.quiet: return writeID(imgs) default: - if cmd.Flags().Changed("format") && !parse.HasTable(listFlag.format) { + if cmd.Flags().Changed("format") && !report.HasTable(listFlag.format) { listFlag.noHeading = true } return writeTemplate(imgs) @@ -195,20 +192,23 @@ func writeTemplate(imgs []imageReporter) error { "ReadOnly": "R/O", }) - var row string + var format string if listFlag.format == "" { - row = lsFormatFromFlags(listFlag) + format = lsFormatFromFlags(listFlag) } else { - row = report.NormalizeFormat(listFlag.format) + format = report.NormalizeFormat(listFlag.format) + format = report.EnforceRange(format) } - format := parse.EnforceRange(row) - tmpl, err := template.New("list").Parse(format) + tmpl, err := report.NewTemplate("list").Parse(format) if err != nil { return err } - w := tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', 0) + w, err := report.NewWriterDefault(os.Stdout) + if err != nil { + return err + } defer w.Flush() if !listFlag.noHeading { @@ -337,7 +337,7 @@ func lsFormatFromFlags(flags listFlagType) string { row = append(row, "{{.ReadOnly}}") } - return strings.Join(row, "\t") + "\n" + return "{{range . }}" + strings.Join(row, "\t") + "\n{{end -}}" } type imageReporter struct { diff --git a/cmd/podman/images/mount.go b/cmd/podman/images/mount.go index efcff8264..89c00cb70 100644 --- a/cmd/podman/images/mount.go +++ b/cmd/podman/images/mount.go @@ -3,8 +3,6 @@ package images import ( "fmt" "os" - "text/tabwriter" - "text/template" "github.com/containers/common/pkg/report" "github.com/containers/podman/v3/cmd/podman/common" @@ -99,13 +97,18 @@ func mount(cmd *cobra.Command, args []string) error { mrs = append(mrs, mountReporter{r}) } - row := "{{range . }}{{.ID}}\t{{.Path}}\n{{end}}" - tmpl, err := template.New("mounts").Parse(row) + row := "{{range . }}{{.ID}}\t{{.Path}}\n{{end -}}" + tmpl, err := report.NewTemplate("mounts").Parse(row) + if err != nil { + return err + } + + w, err := report.NewWriterDefault(os.Stdout) if err != nil { return err } - w := tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', 0) defer w.Flush() + return tmpl.Execute(w, mrs) } diff --git a/cmd/podman/images/push.go b/cmd/podman/images/push.go index edf8e9203..a13976612 100644 --- a/cmd/podman/images/push.go +++ b/cmd/podman/images/push.go @@ -96,7 +96,7 @@ func pushFlags(cmd *cobra.Command) { _ = cmd.RegisterFlagCompletionFunc(digestfileFlagName, completion.AutocompleteDefault) formatFlagName := "format" - flags.StringVarP(&pushOptions.Format, formatFlagName, "f", "", "Manifest type (oci, v2s2, or v2s1) to use when pushing an image using the 'dir' transport (default is manifest type of source)") + flags.StringVarP(&pushOptions.Format, formatFlagName, "f", "", "Manifest type (oci, v2s2, or v2s1) to use in the destination (default is manifest type of source, with fallbacks)") _ = cmd.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteManifestFormat) flags.BoolVarP(&pushOptions.Quiet, "quiet", "q", false, "Suppress output information when pushing images") diff --git a/cmd/podman/images/search.go b/cmd/podman/images/search.go index 08bf3cf6b..11e54578a 100644 --- a/cmd/podman/images/search.go +++ b/cmd/podman/images/search.go @@ -3,14 +3,11 @@ package images import ( "fmt" "os" - "text/tabwriter" - "text/template" "github.com/containers/common/pkg/auth" "github.com/containers/common/pkg/completion" "github.com/containers/common/pkg/report" "github.com/containers/image/v5/types" - "github.com/containers/podman/v3/cmd/podman/parse" "github.com/containers/podman/v3/cmd/podman/registry" "github.com/containers/podman/v3/pkg/domain/entities" "github.com/pkg/errors" @@ -156,18 +153,22 @@ func imageSearch(cmd *cobra.Command, args []string) error { case report.IsJSON(searchOptions.Format): return printArbitraryJSON(searchReport) case cmd.Flags().Changed("format"): - renderHeaders = parse.HasTable(searchOptions.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" } - format := parse.EnforceRange(row) + format := report.EnforceRange(row) - tmpl, err := template.New("search").Parse(format) + tmpl, err := report.NewTemplate("search").Parse(format) + if err != nil { + return err + } + + w, err := report.NewWriterDefault(os.Stdout) if err != nil { return err } - w := tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', 0) defer w.Flush() if renderHeaders { diff --git a/cmd/podman/images/trust_show.go b/cmd/podman/images/trust_show.go index 5d9376068..c0e56f504 100644 --- a/cmd/podman/images/trust_show.go +++ b/cmd/podman/images/trust_show.go @@ -3,9 +3,8 @@ package images import ( "fmt" "os" - "text/tabwriter" - "text/template" + "github.com/containers/common/pkg/report" "github.com/containers/podman/v3/cmd/podman/common" "github.com/containers/podman/v3/cmd/podman/registry" "github.com/containers/podman/v3/pkg/domain/entities" @@ -45,16 +44,16 @@ func init() { } func showTrust(cmd *cobra.Command, args []string) error { - report, err := registry.ImageEngine().ShowTrust(registry.Context(), args, showTrustOptions) + trust, err := registry.ImageEngine().ShowTrust(registry.Context(), args, showTrustOptions) if err != nil { return err } if showTrustOptions.Raw { - fmt.Println(string(report.Raw)) + fmt.Println(string(trust.Raw)) return nil } if showTrustOptions.JSON { - b, err := json.MarshalIndent(report.Policies, "", " ") + b, err := json.MarshalIndent(trust.Policies, "", " ") if err != nil { return err } @@ -62,14 +61,18 @@ func showTrust(cmd *cobra.Command, args []string) error { return nil } - row := "{{.RepoName}}\t{{.Type}}\t{{.GPGId}}\t{{.SignatureStore}}\n" - format := "{{range . }}" + row + "{{end}}" - tmpl, err := template.New("listContainers").Parse(format) + format := "{{range . }}{{.RepoName}}\t{{.Type}}\t{{.GPGId}}\t{{.SignatureStore}}\n{{end -}}" + tmpl, err := report.NewTemplate("list").Parse(format) if err != nil { return err } - w := tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', 0) - if err := tmpl.Execute(w, report.Policies); err != nil { + + w, err := report.NewWriterDefault(os.Stdout) + if err != nil { + return err + } + + if err := tmpl.Execute(w, trust.Policies); err != nil { return err } if err := w.Flush(); err != nil { diff --git a/cmd/podman/inspect/inspect.go b/cmd/podman/inspect/inspect.go index 351684af1..bd3060882 100644 --- a/cmd/podman/inspect/inspect.go +++ b/cmd/podman/inspect/inspect.go @@ -7,7 +7,6 @@ import ( "os" "regexp" "strings" - "text/tabwriter" "text/template" "github.com/containers/common/pkg/completion" @@ -217,7 +216,7 @@ func (i *inspector) inspect(namesOrIDs []string) error { err = printJSON(data) default: row := inspectNormalize(i.options.Format) - row = "{{range . }}" + report.NormalizeFormat(row) + "{{end}}" + row = "{{range . }}" + report.NormalizeFormat(row) + "{{end -}}" err = printTmpl(tmpType, row, data) } if err != nil { @@ -250,7 +249,11 @@ func printTmpl(typ, row string, data []interface{}) error { if err != nil { return err } - w := tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', 0) + + w, err := report.NewWriterDefault(os.Stdout) + if err != nil { + return err + } return t.Execute(w, data) } diff --git a/cmd/podman/machine/list.go b/cmd/podman/machine/list.go index 77b47161a..134a081ab 100644 --- a/cmd/podman/machine/list.go +++ b/cmd/podman/machine/list.go @@ -5,14 +5,11 @@ package machine import ( "os" "sort" - "text/tabwriter" - "text/template" "time" "github.com/containers/common/pkg/completion" "github.com/containers/common/pkg/config" "github.com/containers/common/pkg/report" - "github.com/containers/podman/v3/cmd/podman/parse" "github.com/containers/podman/v3/cmd/podman/registry" "github.com/containers/podman/v3/cmd/podman/validate" "github.com/containers/podman/v3/pkg/machine" @@ -93,16 +90,20 @@ func outputTemplate(cmd *cobra.Command, responses []*machineReporter) error { }) row := report.NormalizeFormat(listFlag.format) - format := parse.EnforceRange(row) + format := report.EnforceRange(row) - tmpl, err := template.New("list machines").Parse(format) + tmpl, err := report.NewTemplate("list").Parse(format) + if err != nil { + return err + } + + w, err := report.NewWriterDefault(os.Stdout) if err != nil { return err } - w := tabwriter.NewWriter(os.Stdout, 12, 2, 2, ' ', 0) defer w.Flush() - if cmd.Flags().Changed("format") && !parse.HasTable(listFlag.format) { + if cmd.Flags().Changed("format") && !report.HasTable(listFlag.format) { listFlag.noHeading = true } diff --git a/cmd/podman/networks/list.go b/cmd/podman/networks/list.go index 46872d078..0ac637ea5 100644 --- a/cmd/podman/networks/list.go +++ b/cmd/podman/networks/list.go @@ -4,8 +4,6 @@ import ( "fmt" "os" "strings" - "text/tabwriter" - "text/template" "github.com/containers/common/pkg/completion" "github.com/containers/common/pkg/report" @@ -133,11 +131,15 @@ func templateOut(responses []*entities.NetworkListReport, cmd *cobra.Command) er } format = report.EnforceRange(row) - tmpl, err := template.New("listNetworks").Parse(format) + tmpl, err := report.NewTemplate("list").Parse(format) + if err != nil { + return err + } + + w, err := report.NewWriterDefault(os.Stdout) if err != nil { return err } - w := tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', 0) defer w.Flush() noHeading, _ := cmd.Flags().GetBool("noheading") diff --git a/cmd/podman/parse/template.go b/cmd/podman/parse/template.go deleted file mode 100644 index 0b80f1b3a..000000000 --- a/cmd/podman/parse/template.go +++ /dev/null @@ -1,22 +0,0 @@ -package parse - -import ( - "regexp" - "strings" -) - -var rangeRegex = regexp.MustCompile(`{{\s*range\s*\.\s*}}.*{{\s*end\s*}}`) - -// TODO move to github.com/containers/common/pkg/report -// EnforceRange ensures that the format string contains a range -func EnforceRange(format string) string { - if !rangeRegex.MatchString(format) { - return "{{range .}}" + format + "{{end}}" - } - return format -} - -// EnforceRange ensures that the format string contains a range -func HasTable(format string) bool { - return strings.HasPrefix(format, "table ") -} diff --git a/cmd/podman/parse/template_test.go b/cmd/podman/parse/template_test.go deleted file mode 100644 index 7880d9bec..000000000 --- a/cmd/podman/parse/template_test.go +++ /dev/null @@ -1,30 +0,0 @@ -package parse - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestEnforceRange(t *testing.T) { - tests := []struct { - input string - expected string - }{ - {"{{range .}}{{.ID}}{{end}}", "{{range .}}{{.ID}}{{end}}"}, - {"{{.ID}}", "{{range .}}{{.ID}}{{end}}"}, - {"{{ range . }}{{ .ID }}{{ end }}", "{{ range . }}{{ .ID }}{{ end }}"}, - // EnforceRange does not verify syntax or semantics, that will happen later - {"{{range .}}{{.ID}}", "{{range .}}{{range .}}{{.ID}}{{end}}"}, - {".ID", "{{range .}}.ID{{end}}"}, - } - - for _, tc := range tests { - tc := tc - label := "TestEnforceRange_" + tc.input - t.Run(label, func(t *testing.T) { - t.Parallel() - assert.Equal(t, tc.expected, EnforceRange(tc.input)) - }) - } -} diff --git a/cmd/podman/pods/inspect.go b/cmd/podman/pods/inspect.go index d38f0062c..4bb88f48a 100644 --- a/cmd/podman/pods/inspect.go +++ b/cmd/podman/pods/inspect.go @@ -3,8 +3,6 @@ package pods import ( "context" "os" - "text/tabwriter" - "text/template" "github.com/containers/common/pkg/report" "github.com/containers/podman/v3/cmd/podman/common" @@ -73,11 +71,14 @@ func inspect(cmd *cobra.Command, args []string) error { row := report.NormalizeFormat(inspectOptions.Format) - t, err := template.New("pod inspect").Parse(row) + t, err := report.NewTemplate("inspect").Parse(row) if err != nil { return err } - w := tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', 0) + w, err := report.NewWriterDefault(os.Stdout) + if err != nil { + return err + } return t.Execute(w, *responses) } diff --git a/cmd/podman/pods/ps.go b/cmd/podman/pods/ps.go index 0271930e8..3e5ab86f4 100644 --- a/cmd/podman/pods/ps.go +++ b/cmd/podman/pods/ps.go @@ -6,14 +6,11 @@ import ( "os" "sort" "strings" - "text/tabwriter" - "text/template" "time" "github.com/containers/common/pkg/completion" "github.com/containers/common/pkg/report" "github.com/containers/podman/v3/cmd/podman/common" - "github.com/containers/podman/v3/cmd/podman/parse" "github.com/containers/podman/v3/cmd/podman/registry" "github.com/containers/podman/v3/cmd/podman/validate" "github.com/containers/podman/v3/pkg/domain/entities" @@ -131,20 +128,24 @@ func pods(cmd *cobra.Command, _ []string) error { renderHeaders := true row := podPsFormat() if cmd.Flags().Changed("format") { - renderHeaders = parse.HasTable(psInput.Format) + renderHeaders = report.HasTable(psInput.Format) row = report.NormalizeFormat(psInput.Format) } noHeading, _ := cmd.Flags().GetBool("noheading") if noHeading { renderHeaders = false } - format := parse.EnforceRange(row) + format := report.EnforceRange(row) - tmpl, err := template.New("listPods").Parse(format) + tmpl, err := report.NewTemplate("list").Parse(format) + if err != nil { + return err + } + + w, err := report.NewWriterDefault(os.Stdout) if err != nil { return err } - w := tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', 0) defer w.Flush() if renderHeaders { diff --git a/cmd/podman/pods/stats.go b/cmd/podman/pods/stats.go index 057b3dead..ba2c1495b 100644 --- a/cmd/podman/pods/stats.go +++ b/cmd/podman/pods/stats.go @@ -4,14 +4,11 @@ import ( "context" "fmt" "os" - "text/tabwriter" - "text/template" "time" "github.com/buger/goterm" "github.com/containers/common/pkg/report" "github.com/containers/podman/v3/cmd/podman/common" - "github.com/containers/podman/v3/cmd/podman/parse" "github.com/containers/podman/v3/cmd/podman/registry" "github.com/containers/podman/v3/cmd/podman/validate" "github.com/containers/podman/v3/pkg/domain/entities" @@ -123,8 +120,12 @@ func printJSONPodStats(stats []*entities.PodStatsReport) error { return nil } -func printPodStatsLines(stats []*entities.PodStatsReport) { - w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0) +func printPodStatsLines(stats []*entities.PodStatsReport) error { + w, err := report.NewWriterDefault(os.Stdout) + if err != nil { + return err + } + outFormat := "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n" fmt.Fprintf(w, outFormat, "POD", "CID", "NAME", "CPU %", "MEM USAGE/ LIMIT", "MEM %", "NET IO", "BLOCK IO", "PIDS") if len(stats) == 0 { @@ -134,7 +135,7 @@ func printPodStatsLines(stats []*entities.PodStatsReport) { fmt.Fprintf(w, outFormat, i.Pod, i.CID, i.Name, i.CPU, i.MemUsage, i.Mem, i.NetIO, i.BlockIO, i.PIDS) } } - w.Flush() + return w.Flush() } func printFormattedPodStatsLines(headerNames []map[string]string, row string, stats []*entities.PodStatsReport) error { @@ -142,13 +143,17 @@ func printFormattedPodStatsLines(headerNames []map[string]string, row string, st return nil } - row = parse.EnforceRange(row) + row = report.EnforceRange(row) + + tmpl, err := report.NewTemplate("stats").Parse(row) + if err != nil { + return err + } - tmpl, err := template.New("pod stats").Parse(row) + w, err := report.NewWriterDefault(os.Stdout) if err != nil { return err } - w := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0) defer w.Flush() if err := tmpl.Execute(w, headerNames); err != nil { diff --git a/cmd/podman/pods/top.go b/cmd/podman/pods/top.go index e26e281c8..a6e442b96 100644 --- a/cmd/podman/pods/top.go +++ b/cmd/podman/pods/top.go @@ -5,8 +5,8 @@ import ( "fmt" "os" "strings" - "text/tabwriter" + "github.com/containers/common/pkg/report" "github.com/containers/podman/v3/cmd/podman/common" "github.com/containers/podman/v3/cmd/podman/registry" "github.com/containers/podman/v3/cmd/podman/validate" @@ -82,7 +82,11 @@ func top(_ *cobra.Command, args []string) error { return err } - w := tabwriter.NewWriter(os.Stdout, 5, 1, 3, ' ', 0) + w, err := report.NewWriterDefault(os.Stdout) + if err != nil { + return err + } + for _, proc := range topResponse.Value { if _, err := fmt.Fprintln(w, proc); err != nil { return err diff --git a/cmd/podman/secrets/inspect.go b/cmd/podman/secrets/inspect.go index 874456f29..d0a5328d8 100644 --- a/cmd/podman/secrets/inspect.go +++ b/cmd/podman/secrets/inspect.go @@ -4,13 +4,10 @@ import ( "context" "encoding/json" "fmt" - "html/template" "os" - "text/tabwriter" "github.com/containers/common/pkg/report" "github.com/containers/podman/v3/cmd/podman/common" - "github.com/containers/podman/v3/cmd/podman/parse" "github.com/containers/podman/v3/cmd/podman/registry" "github.com/containers/podman/v3/pkg/domain/entities" "github.com/pkg/errors" @@ -52,13 +49,17 @@ func inspect(cmd *cobra.Command, args []string) error { if cmd.Flags().Changed("format") { row := report.NormalizeFormat(format) - formatted := parse.EnforceRange(row) + formatted := report.EnforceRange(row) - tmpl, err := template.New("inspect secret").Parse(formatted) + tmpl, err := report.NewTemplate("inspect").Parse(formatted) + if err != nil { + return err + } + + w, err := report.NewWriterDefault(os.Stdout) if err != nil { return err } - w := tabwriter.NewWriter(os.Stdout, 12, 2, 2, ' ', 0) defer w.Flush() tmpl.Execute(w, inspected) } else { diff --git a/cmd/podman/secrets/list.go b/cmd/podman/secrets/list.go index 448a69994..e64990c6f 100644 --- a/cmd/podman/secrets/list.go +++ b/cmd/podman/secrets/list.go @@ -2,15 +2,12 @@ package secrets import ( "context" - "html/template" "os" - "text/tabwriter" "time" "github.com/containers/common/pkg/completion" "github.com/containers/common/pkg/report" "github.com/containers/podman/v3/cmd/podman/common" - "github.com/containers/podman/v3/cmd/podman/parse" "github.com/containers/podman/v3/cmd/podman/registry" "github.com/containers/podman/v3/cmd/podman/validate" "github.com/containers/podman/v3/pkg/domain/entities" @@ -75,16 +72,20 @@ func outputTemplate(cmd *cobra.Command, responses []*entities.SecretListReport) }) row := report.NormalizeFormat(listFlag.format) - format := parse.EnforceRange(row) + format := report.EnforceRange(row) - tmpl, err := template.New("list secret").Parse(format) + tmpl, err := report.NewTemplate("list").Parse(format) + if err != nil { + return err + } + + w, err := report.NewWriterDefault(os.Stdout) if err != nil { return err } - w := tabwriter.NewWriter(os.Stdout, 12, 2, 2, ' ', 0) defer w.Flush() - if cmd.Flags().Changed("format") && !parse.HasTable(listFlag.format) { + if cmd.Flags().Changed("format") && !report.HasTable(listFlag.format) { listFlag.noHeading = true } diff --git a/cmd/podman/system/connection/list.go b/cmd/podman/system/connection/list.go index ae88b0b30..b0b15b57d 100644 --- a/cmd/podman/system/connection/list.go +++ b/cmd/podman/system/connection/list.go @@ -2,11 +2,10 @@ package connection import ( "os" - "text/tabwriter" - "text/template" "github.com/containers/common/pkg/completion" "github.com/containers/common/pkg/config" + "github.com/containers/common/pkg/report" "github.com/containers/podman/v3/cmd/podman/registry" "github.com/containers/podman/v3/cmd/podman/system" "github.com/containers/podman/v3/cmd/podman/validate" @@ -73,13 +72,16 @@ func list(_ *cobra.Command, _ []string) error { } // TODO: Allow user to override format - format := "{{range . }}{{.Name}}\t{{.Identity}}\t{{.URI}}\n{{end}}" - tmpl, err := template.New("connection").Parse(format) + format := "{{range . }}{{.Name}}\t{{.Identity}}\t{{.URI}}\n{{end -}}" + tmpl, err := report.NewTemplate("list").Parse(format) if err != nil { return err } - w := tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', 0) + w, err := report.NewWriterDefault(os.Stdout) + if err != nil { + return err + } defer w.Flush() _ = tmpl.Execute(w, hdrs) diff --git a/cmd/podman/system/df.go b/cmd/podman/system/df.go index de56c57d0..dfde3bc07 100644 --- a/cmd/podman/system/df.go +++ b/cmd/podman/system/df.go @@ -4,13 +4,10 @@ import ( "fmt" "os" "strings" - "text/tabwriter" - "text/template" "time" "github.com/containers/common/pkg/completion" "github.com/containers/common/pkg/report" - "github.com/containers/podman/v3/cmd/podman/parse" "github.com/containers/podman/v3/cmd/podman/registry" "github.com/containers/podman/v3/cmd/podman/validate" "github.com/containers/podman/v3/pkg/domain/entities" @@ -57,7 +54,10 @@ func df(cmd *cobra.Command, args []string) error { return err } - w := tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', 0) + w, err := report.NewWriterDefault(os.Stdout) + if err != nil { + return err + } if dfOptions.Verbose { return printVerbose(w, cmd, reports) @@ -65,7 +65,7 @@ func df(cmd *cobra.Command, args []string) error { return printSummary(w, cmd, reports) } -func printSummary(w *tabwriter.Writer, cmd *cobra.Command, reports *entities.SystemDfReport) error { +func printSummary(w *report.Writer, cmd *cobra.Command, reports *entities.SystemDfReport) error { var ( dfSummaries []*dfSummary active int @@ -143,7 +143,7 @@ func printSummary(w *tabwriter.Writer, cmd *cobra.Command, reports *entities.Sys return writeTemplate(w, cmd, hdrs, row, dfSummaries) } -func printVerbose(w *tabwriter.Writer, cmd *cobra.Command, reports *entities.SystemDfReport) error { +func printVerbose(w *report.Writer, cmd *cobra.Command, reports *entities.SystemDfReport) error { defer w.Flush() fmt.Fprint(w, "Images space usage:\n\n") @@ -191,11 +191,11 @@ func printVerbose(w *tabwriter.Writer, cmd *cobra.Command, reports *entities.Sys return writeTemplate(w, cmd, hdrs, volumeRow, dfVolumes) } -func writeTemplate(w *tabwriter.Writer, cmd *cobra.Command, hdrs []map[string]string, format string, output interface{}) error { +func writeTemplate(w *report.Writer, cmd *cobra.Command, hdrs []map[string]string, format string, output interface{}) error { defer w.Flush() - format = parse.EnforceRange(format) - tmpl, err := template.New("df").Parse(format) + format = report.EnforceRange(format) + tmpl, err := report.NewTemplate("df").Parse(format) if err != nil { return err } diff --git a/cmd/podman/system/events.go b/cmd/podman/system/events.go index 4aa413ec6..677504cfc 100644 --- a/cmd/podman/system/events.go +++ b/cmd/podman/system/events.go @@ -4,7 +4,6 @@ import ( "context" "fmt" "os" - "text/template" "github.com/containers/common/pkg/completion" "github.com/containers/common/pkg/report" @@ -75,7 +74,7 @@ func eventsCmd(cmd *cobra.Command, _ []string) error { errChannel := make(chan error) var ( - tmpl *template.Template + tmpl *report.Template doJSON bool ) @@ -83,7 +82,7 @@ func eventsCmd(cmd *cobra.Command, _ []string) error { doJSON = report.IsJSON(eventFormat) if !doJSON { var err error - tmpl, err = template.New("events").Parse(eventFormat) + tmpl, err = report.NewTemplate("events").Parse(eventFormat) if err != nil { return err } diff --git a/cmd/podman/system/info.go b/cmd/podman/system/info.go index 1dc90f79a..c3f543e6a 100644 --- a/cmd/podman/system/info.go +++ b/cmd/podman/system/info.go @@ -3,7 +3,6 @@ package system import ( "fmt" "os" - "text/template" "github.com/containers/common/pkg/completion" "github.com/containers/common/pkg/report" @@ -85,7 +84,7 @@ func info(cmd *cobra.Command, args []string) error { } fmt.Println(string(b)) case cmd.Flags().Changed("format"): - tmpl, err := template.New("info").Parse(inFormat) + tmpl, err := report.NewTemplate("info").Parse(inFormat) if err != nil { return err } diff --git a/cmd/podman/system/version.go b/cmd/podman/system/version.go index 5575fc87d..4502b156c 100644 --- a/cmd/podman/system/version.go +++ b/cmd/podman/system/version.go @@ -5,8 +5,6 @@ import ( "io" "os" "strings" - "text/tabwriter" - "text/template" "github.com/containers/common/pkg/completion" "github.com/containers/common/pkg/report" @@ -55,19 +53,22 @@ func version(cmd *cobra.Command, args []string) error { return nil } - w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0) + w, err := report.NewWriterDefault(os.Stdout) + if err != nil { + return err + } defer w.Flush() if cmd.Flag("format").Changed { row := report.NormalizeFormat(versionFormat) - tmpl, err := template.New("version 2.0.0").Parse(row) + tmpl, err := report.NewTemplate("version 2.0.0").Parse(row) if err != nil { return err } if err := tmpl.Execute(w, versions); err != nil { // On Failure, assume user is using older version of podman version --format and check client row = strings.Replace(row, ".Server.", ".", 1) - tmpl, err := template.New("version 1.0.0").Parse(row) + tmpl, err := report.NewTemplate("version 1.0.0").Parse(row) if err != nil { return err } diff --git a/cmd/podman/volumes/list.go b/cmd/podman/volumes/list.go index 990b39435..0243054af 100644 --- a/cmd/podman/volumes/list.go +++ b/cmd/podman/volumes/list.go @@ -5,13 +5,10 @@ import ( "fmt" "os" "strings" - "text/tabwriter" - "text/template" "github.com/containers/common/pkg/completion" "github.com/containers/common/pkg/report" "github.com/containers/podman/v3/cmd/podman/common" - "github.com/containers/podman/v3/cmd/podman/parse" "github.com/containers/podman/v3/cmd/podman/registry" "github.com/containers/podman/v3/cmd/podman/validate" "github.com/containers/podman/v3/libpod/define" @@ -104,13 +101,17 @@ func outputTemplate(cmd *cobra.Command, responses []*entities.VolumeListReport) if cliOpts.Quiet { row = "{{.Name}}\n" } - format := parse.EnforceRange(row) + format := report.EnforceRange(row) - tmpl, err := template.New("list volume").Parse(format) + tmpl, err := report.NewTemplate("list").Parse(format) + if err != nil { + return err + } + + w, err := report.NewWriterDefault(os.Stdout) if err != nil { return err } - w := tabwriter.NewWriter(os.Stdout, 12, 2, 2, ' ', 0) defer w.Flush() if !(noHeading || cliOpts.Quiet || cmd.Flag("format").Changed) { diff --git a/contrib/podmanimage/stable/Dockerfile b/contrib/podmanimage/stable/Dockerfile index 696268c85..2f86dd4ae 100644 --- a/contrib/podmanimage/stable/Dockerfile +++ b/contrib/podmanimage/stable/Dockerfile @@ -21,6 +21,7 @@ echo podman:10000:5000 > /etc/subgid; VOLUME /var/lib/containers VOLUME /home/podman/.local/share/containers +RUN mkdir -p /home/podman/.local/share/containers ADD https://raw.githubusercontent.com/containers/libpod/master/contrib/podmanimage/stable/containers.conf /etc/containers/containers.conf ADD https://raw.githubusercontent.com/containers/libpod/master/contrib/podmanimage/stable/podman-containers.conf /home/podman/.config/containers/containers.conf diff --git a/contrib/podmanimage/testing/Dockerfile b/contrib/podmanimage/testing/Dockerfile index c20b26ac4..63b31252f 100644 --- a/contrib/podmanimage/testing/Dockerfile +++ b/contrib/podmanimage/testing/Dockerfile @@ -21,6 +21,7 @@ echo podman:10000:5000 > /etc/subgid; VOLUME /var/lib/containers VOLUME /home/podman/.local/share/containers +RUN mkdir -p /home/podman/.local/share/containers ADD https://raw.githubusercontent.com/containers/libpod/master/contrib/podmanimage/stable/containers.conf /etc/containers/containers.conf ADD https://raw.githubusercontent.com/containers/libpod/master/contrib/podmanimage/stable/podman-containers.conf /home/podman/.config/containers/containers.conf diff --git a/contrib/podmanimage/upstream/Dockerfile b/contrib/podmanimage/upstream/Dockerfile index 1277f9ba8..922eee748 100644 --- a/contrib/podmanimage/upstream/Dockerfile +++ b/contrib/podmanimage/upstream/Dockerfile @@ -69,6 +69,7 @@ echo podman:10000:5000 > /etc/subgid; VOLUME /var/lib/containers VOLUME /home/podman/.local/share/containers +RUN mkdir -p /home/podman/.local/share/containers ADD https://raw.githubusercontent.com/containers/libpod/master/contrib/podmanimage/stable/containers.conf /etc/containers/containers.conf ADD https://raw.githubusercontent.com/containers/libpod/master/contrib/podmanimage/stable/podman-containers.conf /home/podman/.config/containers/containers.conf diff --git a/contrib/spec/podman.spec.in b/contrib/spec/podman.spec.in index 6146a2c0e..ef8523f8c 100644 --- a/contrib/spec/podman.spec.in +++ b/contrib/spec/podman.spec.in @@ -531,10 +531,12 @@ export GOPATH=%{buildroot}/%{gopath}:$(pwd)/vendor:%{gopath} %{_unitdir}/podman-auto-update.timer %{_unitdir}/podman.service %{_unitdir}/podman.socket +%{_unitdir}/podman-restart.service %{_usr}/lib/systemd/user/podman.service %{_usr}/lib/systemd/user/podman.socket %{_usr}/lib/systemd/user/podman-auto-update.service %{_usr}/lib/systemd/user/podman-auto-update.timer +%{_usr}/lib/systemd/user/podman-restart.service %{_usr}/lib/tmpfiles.d/podman.conf %if 0%{?with_devel} diff --git a/contrib/systemd/system/podman-restart.service b/contrib/systemd/system/podman-restart.service new file mode 100644 index 000000000..baf12b3ae --- /dev/null +++ b/contrib/systemd/system/podman-restart.service @@ -0,0 +1,12 @@ +[Unit] +Description=Podman Start All Containers With Restart Policy Set To Always +Documentation=man:podman-start(1) +StartLimitIntervalSec=0 + +[Service] +Type=oneshot +Environment=LOGGING="--log-level=info" +ExecStart=/usr/bin/podman $LOGGING start --all --filter restart-policy=always + +[Install] +WantedBy=multi-user.target diff --git a/contrib/systemd/system/podman.service b/contrib/systemd/system/podman.service index 7e5195e7a..cefb13ae3 100644 --- a/contrib/systemd/system/podman.service +++ b/contrib/systemd/system/podman.service @@ -10,3 +10,6 @@ Type=exec KillMode=process Environment=LOGGING="--log-level=info" ExecStart=/usr/bin/podman $LOGGING system service + +[Install] +WantedBy=multi-user.target diff --git a/contrib/tmpfile/podman.conf b/contrib/tmpfile/podman.conf index 650678a21..bd7dec5ce 100644 --- a/contrib/tmpfile/podman.conf +++ b/contrib/tmpfile/podman.conf @@ -2,5 +2,6 @@ # for many days. This following line prevents systemd from removing this content. x /tmp/podman-run-* x /tmp/containers-user-* +x /tmp/run-*/libpod D! /run/podman 0700 root root D! /var/lib/cni/networks diff --git a/docs/MANPAGE_SYNTAX.md b/docs/MANPAGE_SYNTAX.md index c9b677688..553f5d977 100644 --- a/docs/MANPAGE_SYNTAX.md +++ b/docs/MANPAGE_SYNTAX.md @@ -4,7 +4,8 @@ podman\-command - short description ## SYNOPSIS -(Shows the command structure.) +(Shows the command structure. If the command can be written in two different ways, both of them have to be shown.\ +Many manpages include the OPTIONS **--all**, **-a** and/or **--latest**, **-l**. In this case there is no `container name` or `ID` needed after the initial command. Because most of the other OPTIONS still need the `container name` or ` ID`, it is defined that the *container* argument in the command should **not** be put in brackets. It should also be noted in the *IMPORTANT* section in the description of the OPTION with the following sentence: *IMPORTANT: This OPTION does not need a container name or ID as input argument.*.) **podman command** [*optional*] *mandatory value* @@ -16,7 +17,7 @@ podman\-command - short description **podman subcommand command** [*optional*] *value1* | *value2* -(If an optinal value follows a mandatory one.) +(If an optional value follows a mandatory one.) **podman command** [*optional*] *value1* | *value2* [*optional*] @@ -30,26 +31,36 @@ podman\-command - short description ## DESCRIPTION **podman command** is always the beginning of the DESCRIPTION section. Putting the command as the first part of the DESCRIPTION ensures uniformity. All commands mentioned in the text retain their appearance and form.\ -Example sentence: The command **podman command** is an example command. +Example for the first sentence: **podman command** is an example command. Commands or files that are quoted from other podman manpages or podman repositories have to be linked to those. Non-podman commands are not to be linked.\ -Example sentence: You can use **[podman-run](podman-run.1.md)** or **[containers.conf(5)](https://github.com/containers/common/blob/master/docs/containers.conf.5.md)** for the problem. +Example sentence: Use **[podman-run](podman-run.1.md)** or **[containers.conf(5)](https://github.com/containers/common/blob/master/docs/containers.conf.5.md)** for the problem. -It should also be specified if the command can only be run as root. In addition, it should be described when a command, OPTION, or other content cannot be executed with the remote client or in combination with other commands, OPTIONS, or content. In this case, the following sentence is put at the end of a command, OPTION, or content: *IMPORTANT: This option/command/other is not available with the command/OPTION/content/remote Podman client*. For a command, this should be done in the DESCRIPTION section. For the OPTIONS, it should be done in the DESCRIPTION of the specified OPTION. Do not use pronouns in the man pages, especially the word `you`. +It should also be specified if the command can only be run as root. In addition, it should be described when a command, OPTION, or other content cannot be executed with the remote client or in combination with other commands, OPTIONS, or content. In this case, the following sentence is put at the end of a command, OPTION, or content: *IMPORTANT: This OPTION/command/other is not available with the command/OPTION/content/remote Podman client*. For a command, this should be done in the DESCRIPTION section. For the OPTIONS, it should be done in the DESCRIPTION of the specified OPTION. + +Do not use pronouns in the man pages, especially the word `you`. + +There should be **no** new line after H2-headers (`##`). ## OPTIONS All flags are referred to as OPTIONS. The term flags should not be used. All OPTIONS are listed in this section. OPTIONS that appear in descriptions of other OPTIONS and sections retain their appearance, for example: **--exit**. OPTIONS that are quoted from other podman manpages or podman repositories have to be linked to those.\ -Example sentence: You can use **[podman-generate-systemd --new](podman-generate-systemd.1.md#--new)** for the problem. +Example sentence: Use **[podman-generate-systemd --new](./source/markdown/podman-generate-systemd.1.md#--new)** for the problem. + + Each OPTION should be explained to the fullest extent below the OPTION itself. Each OPTION is behind an H4-header (`####`). If the OPTION has a default argument, it has to be explained in the description of the OPTION. If the OPTION is also not available with a command/OPTION/content/remote Podman client, the sentence about the default argument should the second to last sentence. The sentence about the default argument should be in a new line as well as the *IMPORTANT* sentence. - Each OPTION should be explained to the fullest extent below the OPTION itself. Each OPTION is behind an H4-header (`####`). If the OPTION has a default argument, it has to be explained in the description of the OPTION. If the OPTION is also not available with the remote client, the sentence about the default argument should the second to last sentence. + All OPTIONS are to be sorted in alphabetical order. + + Tables should be used when there is a different definition for different arguments and these have to be explained. This is shown with the OPTION **--test**.\ + Lists should be used when arguments are used that do not need a definition for each argument and a single description explains them. An example is shown with **[podman-commit --change](./source/markdown/podman-commit.1.md#--change--cinstruction)** #### **--version**, **-v** -OPTIONS can be put after the command in two different ways. Eather the long version with **--option** or as the short version **-o**. If there are two ways to write an OPTION they are separated by a comma. If there are two versions of one command the long version is always shown in front.\ -Example: The default is **false**. *IMPORTANT: This option is not available with the remote Podman client*. +OPTIONS can be put after the command in two different ways. Either the long version with **--option** or as the short version **-o**. If there are two ways to write an OPTION they are separated by a comma. If there are two versions of one command the long version is always shown in front. If the arguments behind the OPTION are boolean, it is not shown behind the OPTION itself. The default boolean argument is shown in the same way normal default arguments are displayed.\ +Example: The default is **false**.\ +*IMPORTANT: This OPTION is not available with the remote Podman client.* #### **--exit** @@ -57,15 +68,17 @@ An example of an OPTION that has only one possible structure. Thus, it cannot be #### **--answer**=, **-a**=**active** | *disable* -The "answer" option above is an example of an OPTION that accepts two possible arguments as inputs. If there is a default argument that is selected when the OPTION is not used in the command, it is shown in **bold**. If the OPTION is used it must include an argument afterwards. It must always be ensured that the standard argument is in the first position after the OPTION. In this example, there are two different ways to execute the command. Both possible OPTIONS have to be shown with the arguments following them. The default value is shown as **active**. +The **--answer** OPTION above is an example of an OPTION that accepts two possible arguments as inputs. If there is a default argument that is selected when the OPTION is not used in the command, it is shown in **bold**. If the OPTION is used it must include an argument afterwards. It must always be ensured that the standard argument is in the first position after the OPTION. In this example, there are two different ways to execute the command. Both possible OPTIONS have to be shown with the arguments following them.\ +The default value is shown as **active**. #### **--status**=**good** | *better* | *best* -This is an example of three arguments following an OPTION. If the number of arguments is greater than three, the arguments are **not** listed after the equal sign. The arguments have to be shown in a table like in **--test**=**_test_**, regardless of the number of arguments. The default value is shown as **good**. +This is an example of three arguments following an OPTION. If the number of arguments is greater than three, the arguments are **not** listed after the equal sign. The arguments have to be shown in a table like in **--test**=**_test_**. This form should also be used if the understanding of the content is in danger of becoming incomprehensible. An example for this is **[podman-container-prune --filters](./source/markdown/podman-container-prune.1.md#--filterfilters)**.\ +The default value is shown as **good**. #### **--test**=**test** -OPTIONS that are followed by an equal sign include an argument after the equal sign in **bold**. If there is a default argument, that is used if the OPTION is not specified in the command, the argument after the eqaul sign is displayed in **bold**. All arguments must be listed and explained in the text below the OPTION. +OPTIONS that are followed by an equal sign include an argument after the equal sign in **bold** or *italic*. If there is a default argument, that is used if the OPTION is not specified in the command, the argument after the equal sign is displayed in **bold**. All arguments must be listed and explained in the text below the OPTION. | Argument | Description | | ------------------ | --------------------------------------------------------------------------- | @@ -75,8 +88,8 @@ OPTIONS that are followed by an equal sign include an argument after the equal s | *example four* | Example: Can be combined with **--exit**. | | *example five* | The fifth description | -The table shows an example for a listing of arguments. The contents in the table should be aligned left. If the content in the table conflicts with this, it can be aligned in a way that supports the understanding of the content. If there is a default argument, it **must** listed as the first entry in the table. The default value is shown as **example one**. - +The table shows an example for a listing of arguments. The contents in the table should be aligned left. If the content in the table conflicts with this, it can be aligned in a way that supports the understanding of the content. If there is a default argument, it **must** listed as the first entry in the table.\ +The default value is shown as **example one**. If the number of arguments is smaller than four they have to be listed behind the OPTION as seen in the OPTION **--status**. @@ -102,18 +115,26 @@ All EXAMPLES are listed in this section. This section should be at the end of ea Description of the EXAMPLE ``` +### Example comment $ podman command - $ podman command -o - $ cat $HOME/Dockerfile | podman command --option ``` Description of the EXAMPLE two ``` -$ podman command --redhat +# podman command --status=better +``` +## SEE ALSO +All commands, including commands with OPTIONS, and config-files mentioned in the manpage have to be listed here. Podman commands, including commands with OPTIONS, and config-files have to be linked. If a command is mentioned several times with different OPTIONS it just have to be linked once. All other commands, including commands with OPTIONS, and config-files just have to be mentioned. If a command is mentioned several times with different OPTIONS it just has to be linked once. -$ podman command --redhat better +Example: +**[podman(1)](podman.1.md)**, **[podman-run(1)](podman-run.1.md)**, **[podman-create(1)](podman-create.1.md)** -$ podman command --redhat=better -``` +## HISTORY +Normally, the dates of changes, the content of the changes and the person who provided them is listed here. Most manpages don't keep this record. + +Example:\ +December 2021, Originally compiled by Alexander Richter <example@redhat.com> + +`A new line is needed of the end of every manpage.` diff --git a/docs/source/markdown/podman-attach.1.md b/docs/source/markdown/podman-attach.1.md index 092772916..b86b981d2 100644 --- a/docs/source/markdown/podman-attach.1.md +++ b/docs/source/markdown/podman-attach.1.md @@ -10,17 +10,19 @@ podman\-attach - Attach to a running container ## DESCRIPTION **podman attach** attaches to a running *container* using the *container's name* or *ID*, to either view its ongoing output or to control it interactively.\ -The *container* can detached from (and leave it running) using a configurable key sequence. The default sequence is `ctrl-p,ctrl-q`. Configure the keys sequence using the **--detach-keys** option, or specifying it in the `containers.conf` file: see **[containers.conf(5)](https://github.com/containers/common/blob/master/docs/containers.conf.5.md)** for more information. +The *container* can detached from (and leave it running) using a configurable key sequence. The default sequence is `ctrl-p,ctrl-q`. Configure the keys sequence using the **--detach-keys** OPTION, or specifying it in the `containers.conf` file: see **[containers.conf(5)](https://github.com/containers/common/blob/master/docs/containers.conf.5.md)** for more information. ## OPTIONS #### **--detach-keys**=**sequence** -Specify the key **sequence** for detaching a *container*. Format is a single character `[a-Z]` or one or more `ctrl-<value>` characters where `<value>` is one of: `a-z`, `@`, `^`, `[`, `,` or `_`. Specifying "" will disable this feature. The default is `ctrl-p,ctrl-q`. +Specify the key **sequence** for detaching a *container*. Format is a single character `[a-Z]` or one or more `ctrl-<value>` characters where `<value>` is one of: `a-z`, `@`, `^`, `[`, `,` or `_`. Specifying "" will disable this feature.\ +The default is `ctrl-p,ctrl-q`. #### **--latest**, **-l** -Instead of providing the *container name* or *ID*, use the last created *container*. If you use methods other than Podman to run containers such as CRI-O, the last started *container* could be from either of those methods. The default is **false**.\ -*IMPORTANT: This option is not available with the remote Podman client* +Instead of providing the *container ID* or *name*, use the last created *container*. If other methods than Podman are used to run *containers* such as `CRI-O`, the last started *container* could be from either of those methods.\ +The default is **false**.\ +*IMPORTANT: This OPTION is not available with the remote Podman client. This OPTION does not need a container name or ID as input argument.* #### **--no-stdin** @@ -28,10 +30,10 @@ Do not attach STDIN. The default is **false**. #### **--sig-proxy** -Proxy received signals to the process (non-TTY mode only). SIGCHLD, SIGSTOP, and SIGKILL are not proxied. The default is **true**. +Proxy received signals to the process (non-TTY mode only). SIGCHLD, SIGSTOP, and SIGKILL are not proxied.\ +The default is **true**. ## EXAMPLES - Attach to a container called "foobar". ``` $ podman attach foobar diff --git a/docs/source/markdown/podman-auto-update.1.md b/docs/source/markdown/podman-auto-update.1.md index 52a9a3fec..24b910470 100644 --- a/docs/source/markdown/podman-auto-update.1.md +++ b/docs/source/markdown/podman-auto-update.1.md @@ -9,8 +9,7 @@ podman\-auto-update - Auto update containers according to their auto-update poli ## DESCRIPTION **podman auto-update** looks up containers with a specified `io.containers.autoupdate` label (i.e., the auto-update policy). -If the label is present and set to `registry`, Podman reaches out to the corresponding registry to check if the image has been updated. -The label `image` is an alternative to `registry` maintained for backwards compatibility. +If the label is present and set to `registry`, Podman reaches out to the corresponding registry to check if the image has been updated. The label `image` is an alternative to `registry` maintained for backwards compatibility. An image is considered updated if the digest in the local storage is different than the one of the remote image. If an image must be updated, Podman pulls it down and restarts the systemd unit executing the container. @@ -35,7 +34,6 @@ Systemd units that start and stop a container cannot run a new image. Podman ships with a `podman-auto-update.service` systemd unit. This unit is triggered daily at midnight by the `podman-auto-update.timer` systemd timer. The timer can be altered for custom time-based updates if desired. The unit can further be invoked by other systemd units (e.g., via the dependency tree) or manually via **systemctl start podman-auto-update.service**. ## OPTIONS - #### **--authfile**=*path* Path of the authentication file. Default is `${XDG_RUNTIME_DIR}/containers/auth.json`, which is set using **[podman login](podman-login.1.md)**. @@ -44,7 +42,6 @@ If the authorization state is not found there, `$HOME/.docker/config.json` is ch Note: There is also the option to override the default path of the authentication file by setting the `REGISTRY_AUTH_FILE` environment variable. This can be done with **export REGISTRY_AUTH_FILE=_path_**. ## EXAMPLES - Autoupdate with registry policy ``` diff --git a/docs/source/markdown/podman-commit.1.md b/docs/source/markdown/podman-commit.1.md index 92574cdc5..87b7e8aea 100644 --- a/docs/source/markdown/podman-commit.1.md +++ b/docs/source/markdown/podman-commit.1.md @@ -15,7 +15,6 @@ If `image` does not begin with a registry name component, `localhost` will be ad If `image` is not provided, the values for the `REPOSITORY` and `TAG` values of the created image will each be set to `<none>`. ## OPTIONS - #### **--author**, **-a**=*author* Set the author for the committed image. @@ -23,13 +22,24 @@ Set the author for the committed image. #### **--change**, **-c**=*instruction* Apply the following possible instructions to the created image: -**CMD** | **ENTRYPOINT** | **ENV** | **EXPOSE** | **LABEL** | **ONBUILD** | **STOPSIGNAL** | **USER** | **VOLUME** | **WORKDIR** + +- *CMD* +- *ENTRYPOINT* +- *ENV* +- *EXPOSE* +- *LABEL* +- *ONBUILD* +- *STOPSIGNAL* +- *USER* +- *VOLUME* +- *WORKDIR* Can be set multiple times. #### **--format**, **-f** =**oci** | *docker* -Set the format of the image manifest and metadata. The currently supported formats are **oci** and *docker*. The default is **oci**. +Set the format of the image manifest and metadata. The currently supported formats are **oci** and *docker*.\ +The default is **oci**. #### **--iidfile**=*ImageIDfile* @@ -37,7 +47,8 @@ Write the image ID to the file. #### **--include-volumes** -Include in the committed image any volumes added to the container by the **--volume** or **--mount** OPTIONS to the **[podman create](podman-create.1.md)** and **[podman run](podman-run.1.md)** commands. The default is **false**. +Include in the committed image any volumes added to the container by the **--volume** or **--mount** OPTIONS to the **[podman create](podman-create.1.md)** and **[podman run](podman-run.1.md)** commands.\ +The default is **false**. #### **--message**, **-m**=*message* @@ -46,14 +57,15 @@ Set commit message for committed image.\ #### **--pause**, **-p** -Pause the container when creating an image. The default is **false**. +Pause the container when creating an image.\ +The default is **false**. #### **--quiet**, **-q** -Suppresses output. The default is **false**. +Suppresses output.\ +The default is **false**. ## EXAMPLES - Create image from container with entrypoint and label ``` $ podman commit --change CMD=/bin/bash --change ENTRYPOINT=/bin/sh --change "LABEL blue=image" reverent_golick image-committed diff --git a/docs/source/markdown/podman-completion.1.md b/docs/source/markdown/podman-completion.1.md index 4ebe4e2e1..639332365 100644 --- a/docs/source/markdown/podman-completion.1.md +++ b/docs/source/markdown/podman-completion.1.md @@ -4,60 +4,61 @@ podman\-completion - Generate shell completion scripts ## SYNOPSIS -**podman completion** [*options*] *bash*|*zsh*|*fish*|*powershell* +**podman completion** [*options*] *bash* | *zsh* | *fish* | *powershell* ## DESCRIPTION -The completion command generates shell completion scripts for a variety of shells. Supported shells are **bash**, **zsh**, **fish** and **powershell**. +**podman completion** generates shell completion scripts for a variety of shells. Supported shells are *bash*, *zsh*, *fish* and *powershell*. -These script are used by the shell to provide suggestions and complete commands when you are typing the command and press [TAB]. +These script are used by the shell to provide suggestions and complete commands when the command is typed and `[TAB]` is pressed. Usually these scripts are automatically installed via the package manager. ## OPTIONS -#### **--file**, **-f** +#### **--file**, **-f**=*file* -Write the generated output to file. +Write the generated output to a file. #### **--no-desc** -Do not provide description in the completions. +Do not provide description in the completions.\ +The default is **false**. ## Installation ### BASH -Make sure you have `bash-completion` installed on the system. +`bash-completion` has to be installed on the system. -To load the completion script into the current session run: -`source <(podman completion bash)` +To load the completion script into the current session run:\ +**source <(podman completion bash)**. -To make it available for all bash sessions run: -`podman completion bash -f /etc/bash_completion.d/podman` +To make it available for all bash sessions run:\ +**podman completion -f /etc/bash_completion.d/podman bash**. ### ZSH -If shell completion is not already enabled in the environment you will need to enable it. You can execute the following once: -`echo "autoload -U compinit; compinit" >> ~/.zshrc` +Shell completion needs to be already enabled in the environment. The following can be executed:\ +**echo "autoload -U compinit; compinit" >> ~/.zshrc** -To make it available for all zsh sessions run: -`podman completion zsh -f "${fpath[1]}/_podman"` +To make it available for all zsh sessions run:\ +**podman completion -f "${fpath[1]}/_podman zsh"** -Once you reload the shell the auto-completion should be working. +Once the shell is reloaded the auto-completion should be working. ### FISH To load the completion script into the current session run: -`podman completion fish | source` +**podman completion fish | source** To make it available for all fish sessions run: -`podman completion fish -f ~/.config/fish/completions/podman.fish` +**podman completion -f ~/.config/fish/completions/podman.fish fish** ### POWERSHELL To load the completion script into the current session run: -`podman.exe completion powershell | Out-String | Invoke-Expression` +**podman.exe completion powershell | Out-String | Invoke-Expression** To make it available in all powershell sessions that a user has, write the completion output to a file and source that to the user's powershell profile. -More information about profiles is available with `Get-Help about_Profiles`. +More information about profiles is available with **Get-Help about_Profiles**. ## SEE ALSO -[podman(1)](podman.1.md) +**[podman(1)](podman.1.md)**, zsh(1), fish(1), powershell(1) diff --git a/docs/source/markdown/podman-container-checkpoint.1.md b/docs/source/markdown/podman-container-checkpoint.1.md index 271a44c9d..56fd848ac 100644 --- a/docs/source/markdown/podman-container-checkpoint.1.md +++ b/docs/source/markdown/podman-container-checkpoint.1.md @@ -4,96 +4,109 @@ podman\-container\-checkpoint - Checkpoints one or more running containers ## SYNOPSIS -**podman container checkpoint** [*options*] *container* ... +**podman container checkpoint** [*options*] *container* [*container* ...] ## DESCRIPTION -Checkpoints all the processes in one or more containers. You may use container IDs or names as input. +**podman container checkpoint** checkpoints all the processes in one or more *containers*. A *container* can be restored from a checkpoint with **[podman-container-restore](podman-container-restore.1.md)**. The *container IDs* or *names* are used as input. ## OPTIONS #### **--all**, **-a** -Checkpoint all running containers. +Checkpoint all running *containers*.\ +The default is **false**.\ +*IMPORTANT: This OPTION does not need a container name or ID as input argument.* -#### **--compress**, **-c** +#### **--compress**, **-c**=**zstd** | *none* | *gzip* Specify the compression algorithm used for the checkpoint archive created -with the **--export, -e** option. Possible algorithms are *gzip*, *none* -and *zstd*. If no compression algorithm is specified Podman will use -*zstd*. - +with the **--export, -e** OPTION. Possible algorithms are **zstd**, *none* +and *gzip*.\ One possible reason to use *none* is to enable faster creation of checkpoint archives. Not compressing the checkpoint archive can result in faster checkpoint -archive creation. - -``` -# podman container checkpoint -l --compress=none --export=dump.tar -# podman container checkpoint -l --compress=gzip --export=dump.tar.gz -``` +archive creation.\ +The default is **zstd**. -#### **--export**, **-e** +#### **--export**, **-e**=*archive* Export the checkpoint to a tar.gz file. The exported checkpoint can be used -to import the container on another system and thus enabling container live -migration. This checkpoint archive also includes all changes to the container's -root file-system, if not explicitly disabled using **--ignore-rootfs** +to import the *container* on another system and thus enabling container live +migration. This checkpoint archive also includes all changes to the *container's* +root file-system, if not explicitly disabled using **--ignore-rootfs**. #### **--ignore-rootfs** -This only works in combination with **--export, -e**. If a checkpoint is -exported to a tar.gz file it is possible with the help of **--ignore-rootfs** -to explicitly disable including changes to the root file-system into -the checkpoint archive file. +If a checkpoint is exported to a tar.gz file it is possible with the help of **--ignore-rootfs** to explicitly disable including changes to the root file-system into the checkpoint archive file.\ +The default is **false**.\ +*IMPORTANT: This OPTION only works in combination with **--export, -e**.* #### **--ignore-volumes** -This option must be used in combination with the **--export, -e** option. -When this option is specified, the content of volumes associated with -the container will not be included into the checkpoint tar.gz file. +This OPTION must be used in combination with the **--export, -e** OPTION. +When this OPTION is specified, the content of volumes associated with +the *container* will not be included into the checkpoint tar.gz file.\ +The default is **false**. #### **--keep**, **-k** -Keep all temporary log and statistics files created by CRIU during checkpointing. These files -are not deleted if checkpointing fails for further debugging. If checkpointing succeeds these -files are theoretically not needed, but if these files are needed Podman can keep the files -for further analysis. +Keep all temporary log and statistics files created by CRIU during checkpointing. These files are not deleted if checkpointing fails for further debugging. If checkpointing succeeds these files are theoretically not needed, but if these files are needed Podman can keep the files for further analysis.\ +The default is **false**. #### **--latest**, **-l** -Instead of providing the container name or ID, checkpoint the last created container. (This option is not available with the remote Podman client) +Instead of providing the *container ID* or *name*, use the last created *container*. If other methods than Podman are used to run *containers* such as `CRI-O`, the last started *container* could be from either of those methods.\ +The default is **false**.\ +*IMPORTANT: This OPTION is not available with the remote Podman client. This OPTION does not need a container name or ID as input argument.* #### **--leave-running**, **-R** -Leave the container running after checkpointing instead of stopping it. +Leave the *container* running after checkpointing instead of stopping it.\ +The default is **false**. #### **--pre-checkpoint**, **-P** -Dump the container's memory information only, leaving the container running. Later -operations will supersede prior dumps. It only works on runc 1.0-rc3 or higher. +Dump the *container's* memory information only, leaving the *container* running. Later +operations will supersede prior dumps. It only works on `runc 1.0-rc3` or `higher`.\ +The default is **false**. #### **--tcp-established** -Checkpoint a container with established TCP connections. If the checkpoint -image contains established TCP connections, this options is required during -restore. Defaults to not checkpointing containers with established TCP -connections. +Checkpoint a *container* with established TCP connections. If the checkpoint +image contains established TCP connections, this OPTION is required during +restore. Defaults to not checkpointing *containers* with established TCP +connections.\ +The default is **false**. #### **--with-previous** -Check out the container with previous criu image files in pre-dump. It only works -without **--pre-checkpoint** or **-P**. It only works on runc 1.0-rc3 or higher. +Check out the *container* with previous criu image files in pre-dump. It only works on `runc 1.0-rc3` or `higher`.\ +The default is **false**.\ +*IMPORTANT: This OPTION is not available with **--pre-checkpoint***. -## EXAMPLE -podman container checkpoint mywebserver +## EXAMPLES +Make a checkpoint for the container "mywebserver". +``` +# podman container checkpoint mywebserver +``` -podman container checkpoint 860a4b23 +Dumps the container's memory information of the latest container into an archive. +``` +# podman container checkpoint -P -e pre-checkpoint.tar.gz -l +``` -podman container checkpoint -P -e pre-checkpoint.tar.gz -l +Keep the container's memory information from an older dump and add the new container's memory information. +``` +# podman container checkpoint --with-previous -e checkpoint.tar.gz -l +``` -podman container checkpoint --with-previous -e checkpoint.tar.gz -l +Dump the container's memory information of the latest container into an archive with the specified compress method. +``` +# podman container checkpoint -l --compress=none --export=dump.tar +# podman container checkpoint -l --compress=gzip --export=dump.tar.gz +``` ## SEE ALSO -podman(1), podman-container-restore(1) +**[podman(1)](podman.1.md)**, **[podman-container-restore(1)](podman-container-restore.1.md)** ## HISTORY September 2018, Originally compiled by Adrian Reber <areber@redhat.com> diff --git a/docs/source/markdown/podman-container-cleanup.1.md b/docs/source/markdown/podman-container-cleanup.1.md index 19d0b7818..29e34f1cf 100644 --- a/docs/source/markdown/podman-container-cleanup.1.md +++ b/docs/source/markdown/podman-container-cleanup.1.md @@ -4,51 +4,54 @@ podman\-container\-cleanup - Cleanup the container's network and mountpoints ## SYNOPSIS -**podman container cleanup** [*options*] *container* +**podman container cleanup** [*options*] *container* [*container* ...] ## DESCRIPTION -**podman container cleanup** cleans up exited containers by removing all mountpoints and network configuration from the host. The container name or ID can be used. The cleanup command does not remove the containers. Running containers will not be cleaned up. -Sometimes container's mount points and network stacks can remain if the podman command was killed or the container ran in daemon mode. This command is automatically executed when you run containers in daemon mode by the conmon process when the container exits. +**podman container cleanup** cleans up exited *containers* by removing all mountpoints and network configuration from the host. The *container name* or *ID* can be used. The cleanup command does not remove the *containers*. Running *containers* will not be cleaned up.\ +Sometimes container mount points and network stacks can remain if the podman command was killed or the *container* ran in daemon mode. This command is automatically executed when *containers* are run in daemon mode by the `conmon process` when the *container* exits. ## OPTIONS - #### **--all**, **-a** -Cleanup all containers. +Cleanup all *containers*.\ +The default is **false**.\ +*IMPORTANT: This OPTION does not need a container name or ID as input argument.* -#### **--exec**=_session_ +#### **--exec**=*session* -Clean up an exec session for a single container. -Can only be specified if a single container is being cleaned up (conflicts with **--all** as such). -If **--rm** is not specified, temporary files for the exec session will be cleaned up; if it is, the exec session will be removed from the container. -Conflicts with **--rmi** as the container is not being cleaned up so the image cannot be removed. +Clean up an exec session for a single *container*. +Can only be specified if a single *container* is being cleaned up (conflicts with **--all** as such). If **--rm** is not specified, temporary files for the exec session will be cleaned up; if it is, the exec session will be removed from the *container*.\ +*IMPORTANT: Conflicts with **--rmi** as the container is not being cleaned up so the image cannot be removed.* #### **--latest**, **-l** -Instead of providing the container name or ID, use the last created container. If you use methods other than Podman -to run containers such as CRI-O, the last started container could be from either of those methods. (This option is not available with the remote Podman client) + +Instead of providing the *container ID* or *name*, use the last created *container*. If other methods than Podman are used to run *containers* such as `CRI-O`, the last started *container* could be from either of those methods.\ +The default is **false**.\ +*IMPORTANT: This OPTION is not available with the remote Podman client. This OPTION does not need a container name or ID as input argument.* #### **--rm** -After cleanup, remove the container entirely. +After cleanup, remove the *container* entirely.\ +The default is **false**. #### **--rmi** -After cleanup, remove the image entirely. - -## EXAMPLE - -`podman container cleanup mywebserver` - -`podman container cleanup mywebserver myflaskserver 860a4b23` - -`podman container cleanup 860a4b23` +After cleanup, remove the image entirely.\ +The default is **false**. -`podman container cleanup -a` +## EXAMPLES +Cleanup the container "mywebserver". +``` +$ podman container cleanup mywebserver +``` -`podman container cleanup --latest` +Cleanup the containers with the names "mywebserver", "myflaskserver", "860a4b23". +``` +$ podman container cleanup mywebserver myflaskserver 860a4b23 +``` ## SEE ALSO -**podman**(1), **podman-container**(1), **conmon**(8). +**[podman(1)](podman.1.md)**, **[podman-container(1)](podman-container.1.md)**, conmon(8) ## HISTORY Jun 2018, Originally compiled by Dan Walsh <dwalsh@redhat.com> diff --git a/docs/source/markdown/podman-container-exists.1.md b/docs/source/markdown/podman-container-exists.1.md index 381d968ab..d059276d7 100644 --- a/docs/source/markdown/podman-container-exists.1.md +++ b/docs/source/markdown/podman-container-exists.1.md @@ -1,42 +1,43 @@ % podman-container-exists(1) ## NAME -podman-container-exists - Check if a container exists in local storage +podman\-container\-exists - Check if a container exists in local storage ## SYNOPSIS **podman container exists** [*options*] *container* ## DESCRIPTION -**podman container exists** checks if a container exists in local storage. The **ID** or **Name** -of the container may be used as input. Podman will return an exit code -of `0` when the container is found. A `1` will be returned otherwise. An exit code of `125` indicates there -was an issue accessing the local storage. +**podman container exists** checks if a container exists in local storage. The *container ID* or *name* is used as input. Podman will return an exit code +of `0` when the container is found. A `1` will be returned otherwise. An exit code of `125` indicates there was an issue accessing the local storage. ## OPTIONS +#### **--external** -#### **--external**=*true|false* -Check for external containers as well as Podman containers. These external containers are generally created via other container technology such as Buildah or CRI-O. +Check for external *containers* as well as Podman *containers*. These external *containers* are generally created via other container technology such as `Buildah` or `CRI-O`.\ +The default is **false**. **-h**, **--help** -Print usage statement + +Prints usage statement.\ +The default is **false**. ## EXAMPLES -Check if an container called `webclient` exists in local storage (the container does actually exist). +Check if an container called "webclient" exists in local storage. Here, the container does exist. ``` $ podman container exists webclient $ echo $? 0 ``` -Check if an container called `webbackend` exists in local storage (the container does not actually exist). +Check if an container called "webbackend" exists in local storage. Here, the container does not exist. ``` $ podman container exists webbackend $ echo $? 1 ``` -Check if an container called `ubi8-working-container` created via Buildah exists in local storage (the container does not actually exist). +Check if an container called "ubi8-working-container" created via Buildah exists in local storage. Here, the container does not exist. ``` $ podman container exists --external ubi8-working-container $ echo $? @@ -44,7 +45,7 @@ $ echo $? ``` ## SEE ALSO -podman(1) +**[podman(1)](podman.1.md)** ## HISTORY -November 2018, Originally compiled by Brent Baude (bbaude at redhat dot com) +November 2018, Originally compiled by Brent Baude <bbaude@redhat.com> diff --git a/docs/source/markdown/podman-container-prune.1.md b/docs/source/markdown/podman-container-prune.1.md index b199f9ebb..06014897f 100644 --- a/docs/source/markdown/podman-container-prune.1.md +++ b/docs/source/markdown/podman-container-prune.1.md @@ -1,7 +1,7 @@ % podman-container-prune(1) ## NAME -podman-container-prune - Remove all stopped containers from local storage +podman\-container\-prune - Remove all stopped containers from local storage ## SYNOPSIS **podman container prune** [*options*] @@ -10,35 +10,37 @@ podman-container-prune - Remove all stopped containers from local storage **podman container prune** removes all stopped containers from local storage. ## OPTIONS - #### **--filter**=*filters* Provide filter values. -The --filter flag format is of “key=value”. If there is more than one filter, then pass multiple flags (e.g., --filter "foo=bar" --filter "bif=baz") +The *filters* argument format is of `key=value`. If there is more than one *filter*, then pass multiple OPTIONS: **--filter** *foo=bar* **--filter** *bif=baz*. Supported filters: -- `until` (_timestamp_) - only remove containers and images created before given timestamp -- `label` (label=_key_, label=_key=value_, label!=_key_, or label!=_key=value_) - only remove containers and images, with (or without, in case label!=... is used) the specified labels. +| Filter | Description | +| :----------------: | --------------------------------------------------------------------------- | +| *until* | Only remove containers and images created before given timestamp. | +| *label* | Only remove containers and images, with (or without, in case label!=[...] is used) the specified labels. | -The until filter can be Unix timestamps, date formatted timestamps, or Go duration strings (e.g. 10m, 1h30m) computed relative to the machine’s time. +The `until` *filter* can be Unix timestamps, date formatted timestamps, or Go duration strings (e.g. 10m, 1h30m) computed relative to the machine’s time. -The label filter accepts two formats. One is the label=... (label=_key_ or label=_key=value_), which removes containers with the specified labels. The other format is the label!=... (label!=_key_ or label!=_key=value_), which removes containers without the specified labels. +The `label` *filter* accepts two formats. One is the `label`=*key*, `label`=*key*=*value*, which removes containers with the specified labels. The other format is the `label!`=*key*, or `label!`=*key*=*value*, which removes containers without the specified labels. #### **--force**, **-f** -Do not provide an interactive prompt for container removal. +Do not provide an interactive prompt for container removal.\ +The default is **false**. **-h**, **--help** -Print usage statement +Print usage statement.\ +The default is **false**. ## EXAMPLES - Remove all stopped containers from local storage ``` -$ sudo podman container prune +$ podman container prune WARNING! This will remove all stopped containers. Are you sure you want to continue? [y/N] y 878392adf2e6c5c9bb1fc19b69d37d2e98c8abf9d539c0bce4b15b46bbcce471 @@ -51,7 +53,7 @@ fff1c5b6c3631746055ec40598ce8ecaa4b82aef122f9e3a85b03b55c0d06c23 Remove all stopped containers from local storage without confirmation. ``` -$ sudo podman container prune -f +$ podman container prune -f 878392adf2e6c5c9bb1fc19b69d37d2e98c8abf9d539c0bce4b15b46bbcce471 37664467fbe3618bf9479c34393ac29c02696675addf1750f9e346581636cde7 ed0c6468b8e1cb641b4621d1fe30cb477e1fefc5c0bceb66feaf2f7cb50e5962 @@ -63,15 +65,15 @@ fff1c5b6c3631746055ec40598ce8ecaa4b82aef122f9e3a85b03b55c0d06c23 Remove all stopped containers from local storage created within last 10 minutes ``` -$ sudo podman container prune --filter until="10m" +$ podman container prune --filter until="10m" WARNING! This will remove all stopped containers. Are you sure you want to continue? [y/N] y 3d366295e33d8cc612c4d873199bacadd55088d90d17dcafaa9a2d317ad50b4e ``` ## SEE ALSO -podman(1), podman-ps +**[podman(1)](podman.1.md)**, **[podman-ps](podman-ps.1.md)** ## HISTORY -December 2018, Originally compiled by Brent Baude (bbaude at redhat dot com) -December 2020, converted filter information from docs.docker.com documentation by Dan Walsh (dwalsh at redhat dot com) +December 2018, Originally compiled by Brent Baude <bbaude@redhat.com>\ +December 2020, converted filter information from docs.docker.com documentation by Dan Walsh <dwalsh@redhat.com> diff --git a/docs/source/markdown/podman-container-restore.1.md b/docs/source/markdown/podman-container-restore.1.md index 82bf76d1e..21021b952 100644 --- a/docs/source/markdown/podman-container-restore.1.md +++ b/docs/source/markdown/podman-container-restore.1.md @@ -4,120 +4,131 @@ podman\-container\-restore - Restores one or more containers from a checkpoint ## SYNOPSIS -**podman container restore** [*options*] *container* ... +**podman container restore** [*options*] *container* [*container* ...] ## DESCRIPTION -Restores a container from a checkpoint. You may use container IDs or names as input. +**podman container restore** restores a container from a checkpoint. The *container IDs* or *names* are used as input. ## OPTIONS +#### **--all**, **-a** + +Restore all checkpointed *containers*.\ +The default is **false**.\ +*IMPORTANT: This OPTION does not need a container name or ID as input argument.* + #### **--keep**, **-k** -Keep all temporary log and statistics files created by CRIU during +Keep all temporary log and statistics files created by `CRIU` during checkpointing as well as restoring. These files are not deleted if restoring fails for further debugging. If restoring succeeds these files are theoretically not needed, but if these files are needed Podman can keep the files for further analysis. This includes the checkpoint directory with all files created during checkpointing. The size required by the checkpoint directory is roughly the same as the amount of memory required by the -processes in the checkpointed container. - -Without the **-k**, **--keep** option the checkpoint will be consumed and cannot be used -again. - -#### **--all**, **-a** - -Restore all checkpointed containers. +processes in the checkpointed *container*.\ +Without the **--keep**, **-k** option the checkpoint will be consumed and cannot be used again.\ +The default is **false**. #### **--latest**, **-l** -Instead of providing the container name or ID, restore the last created container. (This option is not available with the remote Podman client) - -#### **--tcp-established** - -Restore a container with established TCP connections. If the checkpoint image -contains established TCP connections, this option is required during restore. -If the checkpoint image does not contain established TCP connections this -option is ignored. Defaults to not restoring containers with established TCP -connections. - -#### **--import**, **-i** - -Import a checkpoint tar.gz file, which was exported by Podman. This can be used -to import a checkpointed container from another host. Do not specify a *container* -argument when using this option. - -#### **--import-previous** - -Import a pre-checkpoint tar.gz file which was exported by Podman. This option -must be used with **-i** or **--import**. It only works on runc 1.0-rc3 or higher. - -#### **--name**, **-n** - -This is only available in combination with **--import, -i**. If a container is restored -from a checkpoint tar.gz file it is possible to rename it with **--name, -n**. This -way it is possible to restore a container from a checkpoint multiple times with different -names. - -If the **--name, -n** option is used, Podman will not attempt to assign the same IP -address to the container it was using before checkpointing as each IP address can only -be used once and the restored container will have another IP address. This also means -that **--name, -n** cannot be used in combination with **--tcp-established**. +Instead of providing the *container ID* or *name*, use the last created *container*. If other methods than Podman are used to run *containers* such as `CRI-O`, the last started *container* could be from either of those methods.\ +The default is **false**.\ +*IMPORTANT: This OPTION is not available with the remote Podman client. This OPTION does not need a container name or ID as input argument.* #### **--ignore-rootfs** -This is only available in combination with **--import, -i**. If a container is restored -from a checkpoint tar.gz file it is possible that it also contains all root file-system -changes. With **--ignore-rootfs** it is possible to explicitly disable applying these -root file-system changes to the restored container. +If a *container* is restored from a checkpoint tar.gz file it is possible that it also contains all root file-system changes. With **--ignore-rootfs** it is possible to explicitly disable applying these root file-system changes to the restored *container*.\ +The default is **false**.\ +*IMPORTANT: This OPTION is only available in combination with **--import, -i**.* #### **--ignore-static-ip** -If the container was started with **--ip** the restored container also tries to use that +If the *container* was started with **--ip** the restored *container* also tries to use that IP address and restore fails if that IP address is already in use. This can happen, if -a container is restored multiple times from an exported checkpoint with **--name, -n**. +a *container* is restored multiple times from an exported checkpoint with **--name, -n**. Using **--ignore-static-ip** tells Podman to ignore the IP address if it was configured -with **--ip** during container creation. +with **--ip** during *container* creation. + +The default is **false**. #### **--ignore-static-mac** -If the container was started with **--mac-address** the restored container also +If the *container* was started with **--mac-address** the restored *container* also tries to use that MAC address and restore fails if that MAC address is already -in use. This can happen, if a container is restored multiple times from an +in use. This can happen, if a *container* is restored multiple times from an exported checkpoint with **--name, -n**. Using **--ignore-static-mac** tells Podman to ignore the MAC address if it was -configured with **--mac-address** during container creation. +configured with **--mac-address** during *container* creation. + +The default is **false**. #### **--ignore-volumes** This option must be used in combination with the **--import, -i** option. -When restoring containers from a checkpoint tar.gz file with this option, -the content of associated volumes will not be restored. +When restoring *containers* from a checkpoint tar.gz file with this option, +the content of associated volumes will not be restored.\ +The default is **false**. -#### **--publish**, **-p** +#### **--import**, **-i**=*file* -Replaces the ports that the container publishes, as configured during the -initial container start, with a new set of port forwarding rules. +Import a checkpoint tar.gz file, which was exported by Podman. This can be used +to import a checkpointed *container* from another host.\ +*IMPORTANT: This OPTION does not need a container name or ID as input argument.* -``` -# podman run --rm -p 2345:80 -d webserver -# podman container checkpoint -l --export=dump.tar -# podman container restore -p 5432:8080 --import=dump.tar -``` +#### **--import-previous**=*file* -For more details please see **podman run --publish**. +Import a pre-checkpoint tar.gz file which was exported by Podman. This option +must be used with **-i** or **--import**. It only works on `runc 1.0-rc3` or `higher`. -## EXAMPLE +#### **--name**, **-n**=*name* + +If a *container* is restored from a checkpoint tar.gz file it is possible to rename it with **--name, -n**. This way it is possible to restore a *container* from a checkpoint multiple times with different +names. + +If the **--name, -n** option is used, Podman will not attempt to assign the same IP +address to the *container* it was using before checkpointing as each IP address can only +be used once and the restored *container* will have another IP address. This also means +that **--name, -n** cannot be used in combination with **--tcp-established**.\ +*IMPORTANT: This OPTION is only available in combination with **--import, -i**.* + +#### **--publish**, **-p**=*port* + +Replaces the ports that the *container* publishes, as configured during the +initial *container* start, with a new set of port forwarding rules. + +For more details please see **[podman run --publish](podman-run.1.md#--publish)**. + +#### **--tcp-established** -podman container restore mywebserver +Restore a *container* with established TCP connections. If the checkpoint image +contains established TCP connections, this option is required during restore. +If the checkpoint image does not contain established TCP connections this +option is ignored. Defaults to not restoring *containers* with established TCP +connections.\ +The default is **false**. -podman container restore 860a4b23 +## EXAMPLE +Restores the container "mywebserver". +``` +# podman container restore mywebserver +``` -podman container restore --import-previous pre-checkpoint.tar.gz --import checkpoint.tar.gz +Import a checkpoint file and a pre-checkpoint file. +``` +# podman container restore --import-previous pre-checkpoint.tar.gz --import checkpoint.tar.gz +``` + +Remove the container "mywebserver". Make a checkpoint of the container and export it. Restore the container with other port ranges from the exported file. +``` +$ podman run --rm -p 2345:80 -d webserver +# podman container checkpoint -l --export=dump.tar +# podman container restore -p 5432:8080 --import=dump.tar +``` ## SEE ALSO -podman(1), podman-container-checkpoint(1), podman-run(1) +**[podman(1)](podman.1.md)**, **[podman-container-checkpoint(1)](podman-container-checkpoint.1.md)**, **[podman-run(1)](podman-run.1.md)** ## HISTORY September 2018, Originally compiled by Adrian Reber <areber@redhat.com> diff --git a/docs/source/markdown/podman-image-unmount.1.md b/docs/source/markdown/podman-image-unmount.1.md index 62e879fa1..2fedb8f58 100644 --- a/docs/source/markdown/podman-image-unmount.1.md +++ b/docs/source/markdown/podman-image-unmount.1.md @@ -12,7 +12,7 @@ podman\-image\-unmount - Unmount an image's root filesystem Unmounts the specified images' root file system, if no other processes are using it. -Image storage increments a mount counter each time a image is mounted. +Image storage increments a mount counter each time an image is mounted. When a image is unmounted, the mount counter is decremented, and the image's root filesystem is physically unmounted only when the mount counter reaches zero indicating no other processes are using the mount. diff --git a/docs/source/markdown/podman-image.1.md b/docs/source/markdown/podman-image.1.md index bbf5f6d84..1b0dc395d 100644 --- a/docs/source/markdown/podman-image.1.md +++ b/docs/source/markdown/podman-image.1.md @@ -18,7 +18,7 @@ The image command allows you to manage images | exists | [podman-image-exists(1)](podman-image-exists.1.md) | Check if an image exists in local storage. | | history | [podman-history(1)](podman-history.1.md) | Show the history of an image. | | import | [podman-import(1)](podman-import.1.md) | Import a tarball and save it as a filesystem image. | -| inspect | [podman-inspect(1)](podman-inspect.1.md) | Display a image or image's configuration. | +| inspect | [podman-inspect(1)](podman-inspect.1.md) | Display an image or image's configuration. | | list | [podman-images(1)](podman-images.1.md) | List the container images on the system.(alias ls) | | load | [podman-load(1)](podman-load.1.md) | Load an image from the docker archive. | | mount | [podman-image-mount(1)](podman-image-mount.1.md) | Mount an image's root filesystem. | diff --git a/docs/source/markdown/podman-login.1.md b/docs/source/markdown/podman-login.1.md index 88d025c70..3e23600fa 100644 --- a/docs/source/markdown/podman-login.1.md +++ b/docs/source/markdown/podman-login.1.md @@ -28,18 +28,6 @@ For more details about format and configurations of the auth.json file, please r ## OPTIONS -#### **--password**, **-p**=*password* - -Password for registry - -#### **--password-stdin** - -Take the password from stdin - -#### **--username**, **-u**=*username* - -Username for registry - #### **--authfile**=*path* Path of the authentication file. Default is ${XDG\_RUNTIME\_DIR}/containers/auth.json. @@ -47,14 +35,26 @@ Path of the authentication file. Default is ${XDG\_RUNTIME\_DIR}/containers/auth Note: You can also override the default path of the authentication file by setting the REGISTRY\_AUTH\_FILE environment variable. `export REGISTRY_AUTH_FILE=path` +#### **--cert-dir**=*path* + +Use certificates at *path* (\*.crt, \*.cert, \*.key) to connect to the registry. +Please refer to containers-certs.d(5) for details. (This option is not available with the remote Podman client) + #### **--get-login** Return the logged-in user for the registry. Return error if no login is found. -#### **--cert-dir**=*path* +#### **--help**, **-h** -Use certificates at *path* (\*.crt, \*.cert, \*.key) to connect to the registry. -Please refer to containers-certs.d(5) for details. (This option is not available with the remote Podman client) +Print usage statement + +#### **--password**, **-p**=*password* + +Password for registry + +#### **--password-stdin** + +Take the password from stdin #### **--tls-verify**=*true|false* @@ -62,9 +62,13 @@ Require HTTPS and verify certificates when contacting registries (default: true) then TLS verification will be used. If set to false, then TLS verification will not be used. If not specified, TLS verification will be used unless the target registry is listed as an insecure registry in registries.conf. -#### **--help**, **-h** +#### **--username**, **-u**=*username* -Print usage statement +Username for registry + +#### **--verbose**, **-v** + +print detailed information about credential store ## EXAMPLES @@ -107,6 +111,14 @@ $ echo $testpassword | podman login -u testuser --password-stdin docker.io Login Succeeded! ``` +``` +$ podman login quay.io --verbose +Username: myusername +Password: +Used: /run/user/1000/containers/auth.json +Login Succeeded! +``` + ## SEE ALSO podman(1), podman-logout(1), containers-auth.json(5), containers-certs.d(5), containers-registries.conf(5) diff --git a/docs/source/markdown/podman-manifest-rm.1.md b/docs/source/markdown/podman-manifest-rm.1.md index 396dd49c7..a65f32936 100644 --- a/docs/source/markdown/podman-manifest-rm.1.md +++ b/docs/source/markdown/podman-manifest-rm.1.md @@ -11,7 +11,7 @@ Removes one or more locally stored manifest lists. ## EXAMPLE -podman manifest rm <list> +podman manifest rm `<list>` podman manifest rm listid1 listid2 diff --git a/docs/source/markdown/podman-network-create.1.md b/docs/source/markdown/podman-network-create.1.md index 3d5d98055..d110c4ceb 100644 --- a/docs/source/markdown/podman-network-create.1.md +++ b/docs/source/markdown/podman-network-create.1.md @@ -9,7 +9,7 @@ podman\-network-create - Create a Podman CNI network ## DESCRIPTION Create a CNI-network configuration for use with Podman. By default, Podman creates a bridge connection. A *Macvlan* connection can be created with the *-d macvlan* option. A parent device for macvlan can -be designated with the *-o parent=\<device>* option. In the case of *Macvlan* connections, the +be designated with the *-o parent=`<device>`* option. In the case of *Macvlan* connections, the CNI *dhcp* plugin needs to be activated or the container image must have a DHCP client to interact with the host network's DHCP server. diff --git a/docs/source/markdown/podman-pod-create.1.md b/docs/source/markdown/podman-pod-create.1.md index 37eb098d1..4b890a7af 100644 --- a/docs/source/markdown/podman-pod-create.1.md +++ b/docs/source/markdown/podman-pod-create.1.md @@ -10,8 +10,8 @@ podman\-pod\-create - Create a new pod Creates an empty pod, or unit of multiple containers, and prepares it to have containers added to it. The pod id is printed to STDOUT. You can then use -**podman create --pod \<pod_id|pod_name\> ...** to add containers to the pod, and -**podman pod start \<pod_id|pod_name\>** to start the pod. +**podman create --pod `<pod_id|pod_name>` ...** to add containers to the pod, and +**podman pod start `<pod_id|pod_name>`** to start the pod. ## OPTIONS diff --git a/docs/source/markdown/podman-pull.1.md b/docs/source/markdown/podman-pull.1.md index 54f990601..084327efd 100644 --- a/docs/source/markdown/podman-pull.1.md +++ b/docs/source/markdown/podman-pull.1.md @@ -21,42 +21,30 @@ Images are stored in local image storage. ## SOURCE - The SOURCE is the location from which the container images are pulled. - The Image "SOURCE" uses a "transport":"details" format. Only the `docker` (container registry) - transport is allowed for remote access. + SOURCE is the location from the container image is pulled from. It supports all transports from `containers-transports(5)`. If no transport is specified, the input is subject to short-name resolution and the `docker` (i.e., container registry) transport is used. For remote clients, `docker` is the only supported transport. - Multiple transports are supported: - - **dir:**_path_ - An existing local directory _path_ storing the manifest, layer tarballs and signatures as individual files. This - is a non-standardized format, primarily useful for debugging or noninvasive container inspection. - - $ podman pull dir:/tmp/myimage - - **docker://**_docker-reference_ (Default) - An image reference stored in a remote container image registry. The reference can include a path to a - specific registry; if it does not, the registries listed in registries.conf will be queried to find a matching - image. By default, credentials from podman login (stored at $XDG_RUNTIME_DIR/containers/auth.json by default) - will be used to authenticate; if these cannot be found, we will fall back to using credentials in - $HOME/.docker/config.json. - - $ podman pull quay.io/username/myimage +``` +# Pull from a container registry +$ podman pull quay.io/username/myimage - **docker-archive:**_path_[**:**_docker-reference_] - An image is stored in the `docker save` formatted file. _docker-reference_ is only used when creating such a - file, and it must not contain a digest. +# Pull from a container registry with short-name resolution +$ podman pull fedora - $ podman pull docker-archive:/tmp/myimage +# Pull from a container registry via the docker transport +$ podman pull docker://quay.io/username/myimage - **docker-daemon:**_docker-reference_ - An image in _docker-reference_ format stored in the docker daemon internal storage. The _docker-reference_ can also be an image ID (docker-daemon:algo:digest). +# Pull from a local directory +$ podman pull dir:/tmp/myimage - $ sudo podman pull docker-daemon:docker.io/library/myimage:33 +# Pull from a tarball in the docker-archive format +$ podman pull docker-archive:/tmp/myimage - **oci-archive:**_path_**:**_tag_ - An image _tag_ in a directory compliant with "Open Container Image Layout Specification" at _path_. +# Pull from a local docker daemon +$ sudo podman pull docker-daemon:docker.io/library/myimage:33 - $ podman pull oci-archive:/tmp/myimage +# Pull from a tarball in the OCI-archive format +$ podman pull oci-archive:/tmp/myimage +``` ## OPTIONS @@ -217,7 +205,7 @@ registries.conf is the configuration file which specifies which container regist NOTE: Use the environment variable `TMPDIR` to change the temporary storage location of downloaded container images. Podman defaults to use `/var/tmp`. ## SEE ALSO -podman(1), podman-push(1), podman-login(1), containers-certs.d(5), containers-registries.conf(5) +podman(1), podman-push(1), podman-login(1), containers-certs.d(5), containers-registries.conf(5), containers-transports(5) ## HISTORY July 2017, Originally compiled by Urvashi Mohnani <umohnani@redhat.com> diff --git a/docs/source/markdown/podman-push.1.md b/docs/source/markdown/podman-push.1.md index e26d73891..68478accd 100644 --- a/docs/source/markdown/podman-push.1.md +++ b/docs/source/markdown/podman-push.1.md @@ -20,37 +20,30 @@ Images are pushed from those stored in local image storage. ## DESTINATION - The DESTINATION is a location to store container images - The Image "DESTINATION" uses a "transport":"details" format. - If a transport is not given, podman push will attempt to push - to a registry. + DESTINATION is the location the container image is pushed to. It supports all transports from `containers-transports(5)`. If no transport is specified, the `docker` (i.e., container registry) transport is used. For remote clients, `docker` is the only supported transport. - Multiple transports are supported: - - **dir:**_path_ - An existing local directory _path_ storing the manifest, layer tarballs and signatures as individual files. This is a non-standardized format, primarily useful for debugging or noninvasive container inspection. - - $ podman push myimage dir:/tmp/myimage - - **docker://**_docker-reference_ - An image in a registry implementing the "Docker Registry HTTP API V2". By default, uses the authorization state in `$XDG_RUNTIME_DIR/containers/auth.json`, which is set using `(podman login)`. If the authorization state is not found there, `$HOME/.docker/config.json` is checked, which is set using `(docker login)`. - - $ podman push myimage quay.io/username/myimage +``` +# Push to a container registry +$ podman push quay.io/podman/stable - **docker-archive:**_path_[**:**_docker-reference_] - An image is stored in the `docker save` formatted file. _docker-reference_ is only used when creating such a file, and it must not contain a digest. +# Push to a container registry via the docker transport +$ podman push docker://quay.io/podman/stable - $ podman push myimage docker-archive:/tmp/myimage +# Push to a container registry with another tag +$ podman push myimage quay.io/username/myimage - **docker-daemon:**_docker-reference_ - An image in _docker-reference_ format stored in the docker daemon internal storage. _docker-reference_ must contain a tag. +# Push to a local directory +$ podman push myimage dir:/tmp/myimage - $ sudo podman push myimage docker-daemon:docker.io/library/myimage:33 +# Push to a tarball in the docker-archive format +$ podman push myimage docker-archive:/tmp/myimage - **oci-archive:**_path_**:**_tag_ - An image _tag_ in a directory compliant with "Open Container Image Layout Specification" at _path_. +# Push to a local docker daemon +$ sudo podman push myimage docker-daemon:docker.io/library/myimage:33 - $ podman push myimage oci-archive:/tmp/myimage +# Push to a tarball in the OCI format +$ podman push myimage oci-archive:/tmp/myimage +``` ## OPTIONS @@ -161,4 +154,4 @@ Storing signatures ``` ## SEE ALSO -podman(1), podman-pull(1), podman-login(1), containers-certs.d(5) +podman(1), podman-pull(1), podman-login(1), containers-certs.d(5), containers-transports(5) diff --git a/docs/source/markdown/podman-rmi.1.md b/docs/source/markdown/podman-rmi.1.md index 765c1bd6d..1f62d6133 100644 --- a/docs/source/markdown/podman-rmi.1.md +++ b/docs/source/markdown/podman-rmi.1.md @@ -10,6 +10,7 @@ podman\-rmi - Removes one or more locally stored images ## DESCRIPTION Removes one or more locally stored images. +Passing an argument _image_ deletes it, along with any of its dangling (untagged) parent images. ## OPTIONS diff --git a/docs/source/markdown/podman-run.1.md b/docs/source/markdown/podman-run.1.md index 46e15d62f..6027a14a5 100644 --- a/docs/source/markdown/podman-run.1.md +++ b/docs/source/markdown/podman-run.1.md @@ -281,12 +281,10 @@ it in the **containers.conf** file: see **containers.conf(5)** for more informat #### **--detach-keys**=*sequence* -Specify the key sequence for detaching a container. Format is a single character `[a-Z]` or one or more `ctrl-<value>` characters where `<value>` is one of: `a-z`, `@`, `^`, `[`, `,` or `_`. Specifying "" will disable this feature. The default is *ctrl-p,ctrl-q*. +Specify the key sequence for detaching a container. Format is a single character `[a-Z]` or one or more `ctrl-<value>` characters where `<value>` is one of: `a-z`, `@`, `^`, `[`, `,` or `_`. Specifying "" will set the sequence to the default value of *ctrl-p,ctrl-q*. This option can also be set in **containers.conf**(5) file. -Specifying "" will disable this feature. The default is **ctrl-p,ctrl-q**. - #### **--device**=_host-device_[**:**_container-device_][**:**_permissions_] Add a host device to the container. Optional *permissions* parameter diff --git a/docs/source/markdown/podman.1.md b/docs/source/markdown/podman.1.md index 734d00971..2510eaa81 100644 --- a/docs/source/markdown/podman.1.md +++ b/docs/source/markdown/podman.1.md @@ -336,9 +336,11 @@ Images are pulled under `XDG_DATA_HOME` when specified, otherwise in the home di Currently the slirp4netns package is required to be installed to create a network device, otherwise rootless containers need to run in the network namespace of the host. +In certain environments like HPC (High Performance Computing), users cannot take advantage of the additional UIDs and GIDs from the /etc/subuid and /etc/subgid systems. However, in this environment, rootless Podman can operate with a single UID. To make this work, set the `ignore_chown_errors` option in the /etc/containers/storage.conf or in ~/.config/containers/storage.conf files. This option tells Podman when pulling an image to ignore chown errors when attempting to change a file in a container image to match the non-root UID in the image. This means all files get saved as the user's UID. Note this could cause issues when running the container. + ### **NOTE:** Unsupported file systems in rootless mode -The Overlay file system (OverlayFS) is not supported in rootless mode. The fuse-overlayfs package is a tool that provides the functionality of OverlayFS in user namespace that allows mounting file systems in rootless environments. It is recommended to install the fuse-overlayfs package. In rootless mode Podman will automatically use the fuse-overlafs program as the mount_program if installed, as long as the $HOME/.config/containers/storage.conf file was not previously created. If storage.conf exists in the homedir, add `mount_program = "/usr/bin/fuse-overlayfs"` under `[storage.options.overlay]` to enable this feature. +The Overlay file system (OverlayFS) is not supported with kernels prior to 5.12.9 in rootless mode. The fuse-overlayfs package is a tool that provides the functionality of OverlayFS in user namespace that allows mounting file systems in rootless environments. It is recommended to install the fuse-overlayfs package. In rootless mode, Podman will automatically use the fuse-overlayfs program as the mount_program if installed, as long as the $HOME/.config/containers/storage.conf file was not previously created. If storage.conf exists in the homedir, add `mount_program = "/usr/bin/fuse-overlayfs"` under `[storage.options.overlay]` to enable this feature. The Network File System (NFS) and other distributed file systems (for example: Lustre, Spectrum Scale, the General Parallel File System (GPFS)) are not supported when running in rootless mode as these file systems do not understand user namespace. However, rootless Podman can make use of an NFS Homedir by modifying the `$HOME/.config/containers/storage.conf` to have the `graphroot` option point to a directory stored on local (Non NFS) storage. @@ -12,15 +12,15 @@ require ( github.com/containernetworking/cni v0.8.1 github.com/containernetworking/plugins v0.9.1 github.com/containers/buildah v1.21.1 - github.com/containers/common v0.39.1-0.20210527140106-e5800a20386a + github.com/containers/common v0.40.2-0.20210623133759-d13a31743aec github.com/containers/conmon v2.0.20+incompatible - github.com/containers/image/v5 v5.12.0 + github.com/containers/image/v5 v5.13.2 github.com/containers/ocicrypt v1.1.1 github.com/containers/psgo v1.5.2 - github.com/containers/storage v1.32.1 + github.com/containers/storage v1.32.3 github.com/coreos/go-systemd/v22 v22.3.2 github.com/coreos/stream-metadata-go v0.0.0-20210225230131-70edb9eb47b3 - github.com/cri-o/ocicni v0.2.1-0.20210301205850-541cf7c703cf + github.com/cri-o/ocicni v0.2.1-0.20210621164014-d0acc7862283 github.com/cyphar/filepath-securejoin v0.2.2 github.com/davecgh/go-spew v1.1.1 github.com/digitalocean/go-qemu v0.0.0-20210209191958-152a1535e49f @@ -64,8 +64,8 @@ require ( go.etcd.io/bbolt v1.3.6 golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 golang.org/x/sync v0.0.0-20201207232520-09787c993a3a - golang.org/x/sys v0.0.0-20210514084401-e8d321eab015 + golang.org/x/sys v0.0.0-20210603125802-9665404d3644 gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 - k8s.io/api v0.21.1 - k8s.io/apimachinery v0.21.1 + k8s.io/api v0.21.2 + k8s.io/apimachinery v0.21.2 ) @@ -221,12 +221,13 @@ github.com/containernetworking/plugins v0.9.1/go.mod h1:xP/idU2ldlzN6m4p5LmGiwRD github.com/containers/buildah v1.21.1 h1:e9LmTCUKUBLg72v5DnIOT/wc8ffkfB7LbpQBywLZo20= github.com/containers/buildah v1.21.1/go.mod h1:yPdlpVd93T+i91yGxrJbW1YOWrqN64j5ZhHOZmHUejs= github.com/containers/common v0.38.4/go.mod h1:egfpX/Y3+19Dz4Wa1eRZDdgzoEOeneieF9CQppKzLBg= -github.com/containers/common v0.39.1-0.20210527140106-e5800a20386a h1:XzYOUf7qjgVJ59YGqAzehlbT63EgjUJhMnfhsPSSJV0= -github.com/containers/common v0.39.1-0.20210527140106-e5800a20386a/go.mod h1:CxHAf4iQOZZ8nASIjMdYHHRyA8dMR4tINSS7WQWlv90= +github.com/containers/common v0.40.2-0.20210623133759-d13a31743aec h1:ZcteA2klZSZAZgVonwJAqezF6hdO9SMKUy49ZHXZd38= +github.com/containers/common v0.40.2-0.20210623133759-d13a31743aec/go.mod h1:J23CfuhN1fAg85q5HxS6SKYhKbGqmqieKQqoHaQbEI8= github.com/containers/conmon v2.0.20+incompatible h1:YbCVSFSCqFjjVwHTPINGdMX1F6JXHGTUje2ZYobNrkg= github.com/containers/conmon v2.0.20+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I= -github.com/containers/image/v5 v5.12.0 h1:1hNS2QkzFQ4lH3GYQLyAXB0acRMhS1Ubm6oV++8vw4w= github.com/containers/image/v5 v5.12.0/go.mod h1:VasTuHmOw+uD0oHCfApQcMO2+36SfyncoSahU7513Xs= +github.com/containers/image/v5 v5.13.2 h1:AgYunV/9d2fRkrmo23wH2MkqeHolFd6oQCkK+1PpuFA= +github.com/containers/image/v5 v5.13.2/go.mod h1:GkWursKDlDcUIT7L7vZf70tADvZCk/Ga0wgS0MuF0ag= github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b h1:Q8ePgVfHDplZ7U33NwHZkrVELsZP5fYj9pM5WBZB2GE= github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b/go.mod h1:9rfv8iPl1ZP7aqh9YA68wnZv2NUDbXdcdPHVz0pFbPY= github.com/containers/ocicrypt v1.0.1/go.mod h1:MeJDzk1RJHv89LjsH0Sp5KTY3ZYkjXO/C+bKAeWFIrc= @@ -238,9 +239,9 @@ github.com/containers/psgo v1.5.2/go.mod h1:2ubh0SsreMZjSXW1Hif58JrEcFudQyIy9EzP github.com/containers/storage v1.23.5/go.mod h1:ha26Q6ngehFNhf3AWoXldvAvwI4jFe3ETQAf/CeZPyM= github.com/containers/storage v1.30.1/go.mod h1:NDJkiwxnSHD1Is+4DGcyR3SIEYSDOa0xnAW+uGQFx9E= github.com/containers/storage v1.31.1/go.mod h1:IFEf+yRTS0pvCGQt2tBv1Kzz2XUSPvED6uFBmWG7V/E= -github.com/containers/storage v1.32.0/go.mod h1:J3q772EVbN9vgqoN/dkvInKnp4xK9ZXm7wHNfuiIDgE= -github.com/containers/storage v1.32.1 h1:JgvHY5dokiff+Ee4TdvPYO++Oq2BAave5DmyPetH2iU= -github.com/containers/storage v1.32.1/go.mod h1:do6oIF71kfkVS3CPUZr+6He94fIaj6pzF8ywevPuuOw= +github.com/containers/storage v1.32.2/go.mod h1:YIBxxjfXZTi04Ah49sh1uSGfmT1V89+I5i3deRobzQo= +github.com/containers/storage v1.32.3 h1:e/e8kUKrYCFpc6FFcItNCwWrZfj2YuyVI6K09ENG9So= +github.com/containers/storage v1.32.3/go.mod h1:s1xFaWvj8qwm1+OnlbPE8RBzdTTpIWuHzVivOqzRKiQ= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= @@ -269,14 +270,15 @@ github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7Do github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw= github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/cri-o/ocicni v0.2.1-0.20210301205850-541cf7c703cf h1:k2wrxBiBseRfOD7h+9fABEuesABBQuUuW5fWwpARbeI= -github.com/cri-o/ocicni v0.2.1-0.20210301205850-541cf7c703cf/go.mod h1:vingr1ztOAzP2WyTgGbpMov9dFhbjNxdLtDv0+PhAvY= +github.com/cri-o/ocicni v0.2.1-0.20210621164014-d0acc7862283 h1:7FyIYKksGvRF8XjMkG5T6uIxg8PcgZoPyO+f6kHT5+s= +github.com/cri-o/ocicni v0.2.1-0.20210621164014-d0acc7862283/go.mod h1:vingr1ztOAzP2WyTgGbpMov9dFhbjNxdLtDv0+PhAvY= github.com/cyphar/filepath-securejoin v0.2.2 h1:jCwT2GTP+PY5nBz3c/YL5PAIbusElVrPujOBSCj8xRg= github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ= github.com/d2g/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s= github.com/d2g/dhcp4server v0.0.0-20181031114812-7d4a0a7f59a5/go.mod h1:Eo87+Kg/IX2hfWJfwxMzLyuSZyxSoAug2nGa1G2QAi8= github.com/d2g/hardwareaddr v0.0.0-20190221164911-e7d9fbe030e4/go.mod h1:bMl4RjIciD2oAxI7DmWRx6gbeqrkoLqv3MV0vzNad+I= +github.com/danieljoos/wincred v1.1.0/go.mod h1:XYlo+eRTsVA9aHGp7NGjFkPla4m+DCL7hqDjlFjiygg= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -300,8 +302,9 @@ github.com/docker/docker v20.10.3-0.20210216175712-646072ed6524+incompatible/go. github.com/docker/docker v20.10.6+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v20.10.7+incompatible h1:Z6O9Nhsjv+ayUEeI1IojKbYcsGdgYSNqxe1s2MYzUhQ= github.com/docker/docker v20.10.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker-credential-helpers v0.6.3 h1:zI2p9+1NQYdnG6sMU26EX4aVGlqbInSQxQXLvzJ4RPQ= github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y= +github.com/docker/docker-credential-helpers v0.6.4 h1:axCks+yV+2MR3/kZhAmy07yC56WZ2Pwu/fKWtKuZB0o= +github.com/docker/docker-credential-helpers v0.6.4/go.mod h1:ofX3UI0Gz1TteYBjtgs07O36Pyasyp66D2uKT7H8W1c= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= @@ -499,8 +502,9 @@ github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1: github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= +github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/insomniacslk/dhcp v0.0.0-20210120172423-cc9239ac6294/go.mod h1:TKl4jN3Voofo4UJIicyNhWGp/nlQqQkFxmwIFTvBkKI= @@ -508,8 +512,9 @@ github.com/ishidawataru/sctp v0.0.0-20210226210310-f2269e66cdee h1:PAXLXk1heNZ5y github.com/ishidawataru/sctp v0.0.0-20210226210310-f2269e66cdee/go.mod h1:co9pwDoBCm1kGxawmb4sPq0cSIOOWNPT4KnHotMP1Zg= github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA= github.com/jamescun/tuntap v0.0.0-20190712092105-cb1fb277045c/go.mod h1:zzwpsgcYhzzIP5WyF8g9ivCv38cY9uAV9Gu0m3lThhE= -github.com/jinzhu/copier v0.3.0 h1:P5zN9OYSxmtzZmwgcVmt5Iu8egfP53BGMPAFgEksKPI= github.com/jinzhu/copier v0.3.0/go.mod h1:24xnZezI2Yqac9J61UC6/dG/k76ttpq0DdJI3QmUvro= +github.com/jinzhu/copier v0.3.2 h1:QdBOCbaouLDYaIPFfi1bKv5F5tPpeTwXe4sD0jqtz5w= +github.com/jinzhu/copier v0.3.2/go.mod h1:24xnZezI2Yqac9J61UC6/dG/k76ttpq0DdJI3QmUvro= github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= @@ -536,8 +541,9 @@ github.com/klauspost/compress v1.11.0/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYs github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.12.2/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= -github.com/klauspost/compress v1.12.3 h1:G5AfA94pHPysR56qqrkO2pxEexdDzrpFJ6yt/VqWxVU= -github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= +github.com/klauspost/compress v1.13.0/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= +github.com/klauspost/compress v1.13.1 h1:wXr2uRxZTJXHLly6qhJabee5JqIhTRoLBhDOA74hDEQ= +github.com/klauspost/compress v1.13.1/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE= github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -572,12 +578,14 @@ github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Ky github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= -github.com/mattn/go-runewidth v0.0.12 h1:Y41i/hVW3Pgwr8gV+J23B9YEY0zxjptBuCWEaxmAOow= github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= +github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= github.com/mattn/go-shellwords v1.0.10/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= -github.com/mattn/go-shellwords v1.0.11 h1:vCoR9VPpsk/TZFW2JwK5I9S0xdrtUq2bph6/YjEPnaw= github.com/mattn/go-shellwords v1.0.11/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= +github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk= +github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= @@ -847,6 +855,8 @@ github.com/vbatts/tar-split v0.11.1/go.mod h1:LEuURwDEiWjRjwu46yU3KVGuUdVv/dcnpc github.com/vbauerster/mpb/v6 v6.0.3/go.mod h1:5luBx4rDLWxpA4t6I5sdeeQuZhqDxc+wr5Nqf35+tnM= github.com/vbauerster/mpb/v6 v6.0.4 h1:h6J5zM/2wimP5Hj00unQuV8qbo5EPcj6wbkCqgj7KcY= github.com/vbauerster/mpb/v6 v6.0.4/go.mod h1:a/+JT57gqh6Du0Ay5jSR+uBMfXGdlR7VQlGP52fJxLM= +github.com/vbauerster/mpb/v7 v7.0.2 h1:eN6AD/ytv1nqCO7Dm8MO0/pGMKmMyH/WMnTJhAUuc/w= +github.com/vbauerster/mpb/v7 v7.0.2/go.mod h1:Mnq3gESXJ9eQhccbGZDggJ1faTCrmaA4iN57fUloRGE= github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852 h1:cPXZWzzG0NllBLdjWoD1nDfaqu98YMv+OneaKc8sPOA= @@ -1071,12 +1081,12 @@ golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210216224549-f992740a1bac/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210514084401-e8d321eab015 h1:hZR0X1kPW+nwyJ9xRxqZk1vx5RUObAPBdKVvXPDUH/E= golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603125802-9665404d3644 h1:CA1DEQ4NdKphKeL70tvsWNdT5oFh1lOjihRcEDROi0I= +golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201113234701-d7a72108b828/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -1259,13 +1269,13 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9 k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo= k8s.io/api v0.20.4/go.mod h1:++lNL1AJMkDymriNniQsWRkMDzRaX2Y/POTUi8yvqYQ= k8s.io/api v0.20.6/go.mod h1:X9e8Qag6JV/bL5G6bU8sdVRltWKmdHsFUGS3eVndqE8= -k8s.io/api v0.21.1 h1:94bbZ5NTjdINJEdzOkpS4vdPhkb1VFpTYC9zh43f75c= -k8s.io/api v0.21.1/go.mod h1:FstGROTmsSHBarKc8bylzXih8BLNYTiS3TZcsoEDg2s= +k8s.io/api v0.21.2 h1:vz7DqmRsXTCSa6pNxXwQ1IYeAZgdIsua+DZU+o+SX3Y= +k8s.io/api v0.21.2/go.mod h1:Lv6UGJZ1rlMI1qusN8ruAp9PUBFyBwpEHAdG24vIsiU= k8s.io/apimachinery v0.20.1/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= k8s.io/apimachinery v0.20.4/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= k8s.io/apimachinery v0.20.6/go.mod h1:ejZXtW1Ra6V1O5H8xPBGz+T3+4gfkTCeExAHKU57MAc= -k8s.io/apimachinery v0.21.1 h1:Q6XuHGlj2xc+hlMCvqyYfbv3H7SRGn2c8NycxJquDVs= -k8s.io/apimachinery v0.21.1/go.mod h1:jbreFvJo3ov9rj7eWT7+sYiRx+qZuCYXwWT1bcDswPY= +k8s.io/apimachinery v0.21.2 h1:vezUc/BHqWlQDnZ+XkrpXSmnANSLbpnlpwo0Lhk0gpc= +k8s.io/apimachinery v0.21.2/go.mod h1:CdTY8fU/BlvAbJ2z/8kBwimGki5Zp8/fbVuLY8gJumM= k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU= k8s.io/apiserver v0.20.4/go.mod h1:Mc80thBKOyy7tbvFtB4kJv1kbdD0eIH8k8vianJcbFM= k8s.io/apiserver v0.20.6/go.mod h1:QIJXNt6i6JB+0YQRNcS0hdRHJlMhflFmsBDeSgT1r8Q= diff --git a/libpod/container.go b/libpod/container.go index c6f0cd618..4b9bea5fc 100644 --- a/libpod/container.go +++ b/libpod/container.go @@ -957,6 +957,12 @@ func (c *Container) cGroupPath() (string, error) { // is the libpod-specific one we're looking for. // // See #8397 on the need for the longest-path look up. + // + // And another workaround for containers running systemd as the payload. + // containers running systemd moves themselves into a child subgroup of + // the named systemd cgroup hierarchy. Ignore any named cgroups during + // the lookup. + // See #10602 for more details. procPath := fmt.Sprintf("/proc/%d/cgroup", c.state.PID) lines, err := ioutil.ReadFile(procPath) if err != nil { @@ -972,6 +978,10 @@ func (c *Container) cGroupPath() (string, error) { logrus.Debugf("Error parsing cgroup: expected 3 fields but got %d: %s", len(fields), procPath) continue } + // Ignore named cgroups like name=systemd. + if bytes.Contains(fields[1], []byte("=")) { + continue + } path := string(fields[2]) if len(path) > len(cgroupPath) { cgroupPath = path diff --git a/libpod/container_exec.go b/libpod/container_exec.go index c359f1e5d..5d4bcb422 100644 --- a/libpod/container_exec.go +++ b/libpod/container_exec.go @@ -1,6 +1,7 @@ package libpod import ( + "context" "io/ioutil" "net/http" "os" @@ -276,9 +277,10 @@ func (c *Container) ExecStart(sessionID string) error { } // ExecStartAndAttach starts and attaches to an exec session in a container. +// newSize resizes the tty to this size before the process is started, must be nil if the exec session has no tty // TODO: Should we include detach keys in the signature to allow override? // TODO: How do we handle AttachStdin/AttachStdout/AttachStderr? -func (c *Container) ExecStartAndAttach(sessionID string, streams *define.AttachStreams) error { +func (c *Container) ExecStartAndAttach(sessionID string, streams *define.AttachStreams, newSize *define.TerminalSize) error { if !c.batched { c.lock.Lock() defer c.lock.Unlock() @@ -309,7 +311,7 @@ func (c *Container) ExecStartAndAttach(sessionID string, streams *define.AttachS return err } - pid, attachChan, err := c.ociRuntime.ExecContainer(c, session.ID(), opts, streams) + pid, attachChan, err := c.ociRuntime.ExecContainer(c, session.ID(), opts, streams, newSize) if err != nil { return err } @@ -372,7 +374,9 @@ func (c *Container) ExecStartAndAttach(sessionID string, streams *define.AttachS } // ExecHTTPStartAndAttach starts and performs an HTTP attach to an exec session. -func (c *Container) ExecHTTPStartAndAttach(sessionID string, r *http.Request, w http.ResponseWriter, streams *HTTPAttachStreams, detachKeys *string, cancel <-chan bool, hijackDone chan<- bool) error { +// newSize resizes the tty to this size before the process is started, must be nil if the exec session has no tty +func (c *Container) ExecHTTPStartAndAttach(sessionID string, r *http.Request, w http.ResponseWriter, + streams *HTTPAttachStreams, detachKeys *string, cancel <-chan bool, hijackDone chan<- bool, newSize *define.TerminalSize) error { // TODO: How do we combine streams with the default streams set in the exec session? // Ensure that we don't leak a goroutine here @@ -430,7 +434,7 @@ func (c *Container) ExecHTTPStartAndAttach(sessionID string, r *http.Request, w close(holdConnOpen) }() - pid, attachChan, err := c.ociRuntime.ExecContainerHTTP(c, session.ID(), execOpts, r, w, streams, cancel, hijackDone, holdConnOpen) + pid, attachChan, err := c.ociRuntime.ExecContainerHTTP(c, session.ID(), execOpts, r, w, streams, cancel, hijackDone, holdConnOpen, newSize) if err != nil { session.State = define.ExecStateStopped session.ExitCode = define.TranslateExecErrorToExitCode(define.ExecErrorCodeGeneric, err) @@ -539,18 +543,7 @@ func (c *Container) ExecStop(sessionID string, timeout *uint) error { var cleanupErr error // Retrieve exit code and update status - exitCode, err := c.readExecExitCode(session.ID()) - if err != nil { - cleanupErr = err - } - session.ExitCode = exitCode - session.PID = 0 - session.State = define.ExecStateStopped - - if err := c.save(); err != nil { - if cleanupErr != nil { - logrus.Errorf("Error stopping container %s exec session %s: %v", c.ID(), session.ID(), cleanupErr) - } + if err := retrieveAndWriteExecExitCode(c, session.ID()); err != nil { cleanupErr = err } @@ -592,15 +585,7 @@ func (c *Container) ExecCleanup(sessionID string) error { return errors.Wrapf(define.ErrExecSessionStateInvalid, "cannot clean up container %s exec session %s as it is running", c.ID(), session.ID()) } - exitCode, err := c.readExecExitCode(session.ID()) - if err != nil { - return err - } - session.ExitCode = exitCode - session.PID = 0 - session.State = define.ExecStateStopped - - if err := c.save(); err != nil { + if err := retrieveAndWriteExecExitCode(c, session.ID()); err != nil { return err } } @@ -637,9 +622,9 @@ func (c *Container) ExecRemove(sessionID string, force bool) error { return err } if !running { - session.State = define.ExecStateStopped - // TODO: should we retrieve exit code here? - // TODO: Might be worth saving state here. + if err := retrieveAndWriteExecExitCode(c, session.ID()); err != nil { + return err + } } } @@ -653,6 +638,10 @@ func (c *Container) ExecRemove(sessionID string, force bool) error { return err } + if err := retrieveAndWriteExecExitCode(c, session.ID()); err != nil { + return err + } + if err := c.cleanupExecBundle(session.ID()); err != nil { return err } @@ -733,7 +722,10 @@ func (c *Container) Exec(config *ExecConfig, streams *define.AttachStreams, resi // API there. // TODO: Refactor so this is closed here, before we remove the exec // session. + var size *define.TerminalSize if resize != nil { + s := <-resize + size = &s go func() { logrus.Debugf("Sending resize events to exec session %s", sessionID) for resizeRequest := range resize { @@ -751,16 +743,31 @@ func (c *Container) Exec(config *ExecConfig, streams *define.AttachStreams, resi }() } - if err := c.ExecStartAndAttach(sessionID, streams); err != nil { + if err := c.ExecStartAndAttach(sessionID, streams, size); err != nil { return -1, err } session, err := c.ExecSession(sessionID) if err != nil { + if errors.Cause(err) == define.ErrNoSuchExecSession { + // TODO: If a proper Context is ever plumbed in here, we + // should use it. + // As things stand, though, it's not worth it - this + // should always terminate quickly since it's not + // streaming. + diedEvent, err := c.runtime.GetExecDiedEvent(context.Background(), c.ID(), sessionID) + if err != nil { + return -1, errors.Wrapf(err, "error retrieving exec session %s exit code", sessionID) + } + return diedEvent.ContainerExitCode, nil + } return -1, err } exitCode := session.ExitCode if err := c.ExecRemove(sessionID, false); err != nil { + if errors.Cause(err) == define.ErrNoSuchExecSession { + return exitCode, nil + } return -1, err } @@ -927,6 +934,8 @@ func (c *Container) getActiveExecSessions() ([]string, error) { session.PID = 0 session.State = define.ExecStateStopped + c.newExecDiedEvent(session.ID(), exitCode) + needSave = true } if err := c.cleanupExecBundle(id); err != nil { @@ -1036,6 +1045,22 @@ func writeExecExitCode(c *Container, sessionID string, exitCode int) error { return errors.Wrapf(err, "error syncing container %s state to remove exec session %s", c.ID(), sessionID) } + return justWriteExecExitCode(c, sessionID, exitCode) +} + +func retrieveAndWriteExecExitCode(c *Container, sessionID string) error { + exitCode, err := c.readExecExitCode(sessionID) + if err != nil { + return err + } + + return justWriteExecExitCode(c, sessionID, exitCode) +} + +func justWriteExecExitCode(c *Container, sessionID string, exitCode int) error { + // Write an event first + c.newExecDiedEvent(sessionID, exitCode) + session, ok := c.state.ExecSessions[sessionID] if !ok { // Exec session already removed. diff --git a/libpod/container_internal.go b/libpod/container_internal.go index f77825efd..545b78976 100644 --- a/libpod/container_internal.go +++ b/libpod/container_internal.go @@ -42,6 +42,7 @@ const ( // name of the directory holding the artifacts artifactsDir = "artifacts" execDirPermission = 0755 + preCheckpointDir = "pre-checkpoint" ) // rootFsSize gets the size of the container's root filesystem @@ -141,7 +142,7 @@ func (c *Container) CheckpointPath() string { // PreCheckpointPath returns the path to the directory containing the pre-checkpoint-images func (c *Container) PreCheckPointPath() string { - return filepath.Join(c.bundlePath(), "pre-checkpoint") + return filepath.Join(c.bundlePath(), preCheckpointDir) } // AttachSocketPath retrieves the path of the container's attach socket @@ -427,7 +428,7 @@ func (c *Container) setupStorage(ctx context.Context) error { }, LabelOpts: c.config.LabelOpts, } - if c.restoreFromCheckpoint { + if c.restoreFromCheckpoint && !c.config.Privileged { // If restoring from a checkpoint, the root file-system // needs to be mounted with the same SELinux labels as // it was mounted previously. @@ -1061,7 +1062,7 @@ func (c *Container) init(ctx context.Context, retainRetries bool) error { } for _, v := range c.config.NamedVolumes { - if err := c.chownVolume(v.Name); err != nil { + if err := c.fixVolumePermissions(v); err != nil { return err } } @@ -1680,64 +1681,6 @@ func (c *Container) mountNamedVolume(v *ContainerNamedVolume, mountpoint string) return vol, nil } -// Chown the specified volume if necessary. -func (c *Container) chownVolume(volumeName string) error { - vol, err := c.runtime.state.Volume(volumeName) - if err != nil { - return errors.Wrapf(err, "error retrieving named volume %s for container %s", volumeName, c.ID()) - } - - vol.lock.Lock() - defer vol.lock.Unlock() - - // The volume may need a copy-up. Check the state. - if err := vol.update(); err != nil { - return err - } - - // TODO: For now, I've disabled chowning volumes owned by non-Podman - // drivers. This may be safe, but it's really going to be a case-by-case - // thing, I think - safest to leave disabled now and re-enable later if - // there is a demand. - if vol.state.NeedsChown && !vol.UsesVolumeDriver() { - vol.state.NeedsChown = false - - uid := int(c.config.Spec.Process.User.UID) - gid := int(c.config.Spec.Process.User.GID) - - if c.config.IDMappings.UIDMap != nil { - p := idtools.IDPair{ - UID: uid, - GID: gid, - } - mappings := idtools.NewIDMappingsFromMaps(c.config.IDMappings.UIDMap, c.config.IDMappings.GIDMap) - newPair, err := mappings.ToHost(p) - if err != nil { - return errors.Wrapf(err, "error mapping user %d:%d", uid, gid) - } - uid = newPair.UID - gid = newPair.GID - } - - vol.state.UIDChowned = uid - vol.state.GIDChowned = gid - - if err := vol.save(); err != nil { - return err - } - - mountPoint, err := vol.MountPoint() - if err != nil { - return err - } - - if err := os.Lchown(mountPoint, uid, gid); err != nil { - return err - } - } - return nil -} - // cleanupStorage unmounts and cleans up the container's root filesystem func (c *Container) cleanupStorage() error { if !c.state.Mounted { diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go index 94bf7855b..25db3cff0 100644 --- a/libpod/container_internal_linux.go +++ b/libpod/container_internal_linux.go @@ -909,14 +909,15 @@ func (c *Container) exportCheckpoint(options ContainerCheckpointOptions) error { includeFiles := []string{ "artifacts", "ctr.log", - metadata.CheckpointDirectory, metadata.ConfigDumpFile, metadata.SpecDumpFile, metadata.NetworkStatusFile, } if options.PreCheckPoint { - includeFiles[0] = "pre-checkpoint" + includeFiles = append(includeFiles, preCheckpointDir) + } else { + includeFiles = append(includeFiles, metadata.CheckpointDirectory) } // Get root file-system changes included in the checkpoint archive var addToTarFiles []string @@ -1660,9 +1661,13 @@ func (c *Container) generateResolvConf() (string, error) { // check if systemd-resolved is used, assume it is used when 127.0.0.53 is the only nameserver if len(ns) == 1 && ns[0] == "127.0.0.53" { // read the actual resolv.conf file for systemd-resolved - contents, err = ioutil.ReadFile("/run/systemd/resolve/resolv.conf") + resolvedContents, err := ioutil.ReadFile("/run/systemd/resolve/resolv.conf") if err != nil { - return "", errors.Wrapf(err, "detected that systemd-resolved is in use, but could not locate real resolv.conf") + if !os.IsNotExist(err) { + return "", errors.Wrapf(err, "detected that systemd-resolved is in use, but could not locate real resolv.conf") + } + } else { + contents = resolvedContents } } @@ -1815,7 +1820,7 @@ func (c *Container) getHosts() string { if c.Hostname() != "" { if c.config.NetMode.IsSlirp4netns() { // When using slirp4netns, the interface gets a static IP - slirp4netnsIP, err := GetSlirp4netnsGateway(c.slirp4netnsSubnet) + slirp4netnsIP, err := GetSlirp4netnsIP(c.slirp4netnsSubnet) if err != nil { logrus.Warn("failed to determine slirp4netnsIP: ", err.Error()) } else { @@ -2425,3 +2430,77 @@ func (c *Container) createSecretMountDir() error { return err } + +// Fix ownership and permissions of the specified volume if necessary. +func (c *Container) fixVolumePermissions(v *ContainerNamedVolume) error { + vol, err := c.runtime.state.Volume(v.Name) + if err != nil { + return errors.Wrapf(err, "error retrieving named volume %s for container %s", v.Name, c.ID()) + } + + vol.lock.Lock() + defer vol.lock.Unlock() + + // The volume may need a copy-up. Check the state. + if err := vol.update(); err != nil { + return err + } + + // TODO: For now, I've disabled chowning volumes owned by non-Podman + // drivers. This may be safe, but it's really going to be a case-by-case + // thing, I think - safest to leave disabled now and re-enable later if + // there is a demand. + if vol.state.NeedsChown && !vol.UsesVolumeDriver() { + vol.state.NeedsChown = false + + uid := int(c.config.Spec.Process.User.UID) + gid := int(c.config.Spec.Process.User.GID) + + if c.config.IDMappings.UIDMap != nil { + p := idtools.IDPair{ + UID: uid, + GID: gid, + } + mappings := idtools.NewIDMappingsFromMaps(c.config.IDMappings.UIDMap, c.config.IDMappings.GIDMap) + newPair, err := mappings.ToHost(p) + if err != nil { + return errors.Wrapf(err, "error mapping user %d:%d", uid, gid) + } + uid = newPair.UID + gid = newPair.GID + } + + vol.state.UIDChowned = uid + vol.state.GIDChowned = gid + + if err := vol.save(); err != nil { + return err + } + + mountPoint, err := vol.MountPoint() + if err != nil { + return err + } + + if err := os.Lchown(mountPoint, uid, gid); err != nil { + return err + } + + // Make sure the new volume matches the permissions of the target directory. + // https://github.com/containers/podman/issues/10188 + st, err := os.Lstat(filepath.Join(c.state.Mountpoint, v.Dest)) + if err == nil { + if err := os.Chmod(mountPoint, st.Mode()|0111); err != nil { + return err + } + stat := st.Sys().(*syscall.Stat_t) + atime := time.Unix(int64(stat.Atim.Sec), int64(stat.Atim.Nsec)) + if err := os.Chtimes(mountPoint, atime, st.ModTime()); err != nil { + return err + } + } else if !os.IsNotExist(err) { + return err + } + } + return nil +} diff --git a/libpod/container_internal_unsupported.go b/libpod/container_internal_unsupported.go index f979bcbde..125329ce5 100644 --- a/libpod/container_internal_unsupported.go +++ b/libpod/container_internal_unsupported.go @@ -57,3 +57,8 @@ func (c *Container) reloadNetwork() error { func (c *Container) getUserOverrides() *lookup.Overrides { return nil } + +// Fix ownership and permissions of the specified volume if necessary. +func (c *Container) fixVolumePermissions(v *ContainerNamedVolume) error { + return define.ErrNotImplemented +} diff --git a/libpod/container_log.go b/libpod/container_log.go index a30e4f5cc..43b3f7736 100644 --- a/libpod/container_log.go +++ b/libpod/container_log.go @@ -4,10 +4,12 @@ import ( "context" "fmt" "os" + "time" "github.com/containers/podman/v3/libpod/define" "github.com/containers/podman/v3/libpod/events" "github.com/containers/podman/v3/libpod/logs" + "github.com/hpcloud/tail/watch" "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -74,7 +76,7 @@ func (c *Container) readFromLogFile(ctx context.Context, options *logs.LogOption } nll, err := logs.NewLogLine(line.Text) if err != nil { - logrus.Error(err) + logrus.Errorf("Error getting new log line: %v", err) continue } if nll.Partial() { @@ -93,17 +95,20 @@ func (c *Container) readFromLogFile(ctx context.Context, options *logs.LogOption }() // Check if container is still running or paused if options.Follow { + // If the container isn't running or if we encountered an error + // getting its state, instruct the logger to read the file + // until EOF. state, err := c.State() if err != nil || state != define.ContainerStateRunning { - // If the container isn't running or if we encountered - // an error getting its state, instruct the logger to - // read the file until EOF. + // Make sure to wait at least for the poll duration + // before stopping the file logger (see #10675). + time.Sleep(watch.POLL_DURATION) tailError := t.StopAtEOF() if tailError != nil && fmt.Sprintf("%v", tailError) != "tail: stop at eof" { - logrus.Error(tailError) + logrus.Errorf("Error stopping logger: %v", tailError) } - if errors.Cause(err) != define.ErrNoSuchCtr { - logrus.Error(err) + if err != nil && errors.Cause(err) != define.ErrNoSuchCtr { + logrus.Errorf("Error getting container state: %v", err) } return nil } @@ -124,9 +129,12 @@ func (c *Container) readFromLogFile(ctx context.Context, options *logs.LogOption // Now wait for the died event and signal to finish // reading the log until EOF. <-eventChannel + // Make sure to wait at least for the poll duration + // before stopping the file logger (see #10675). + time.Sleep(watch.POLL_DURATION) tailError := t.StopAtEOF() if tailError != nil && fmt.Sprintf("%v", tailError) != "tail: stop at eof" { - logrus.Error(tailError) + logrus.Errorf("Error stopping logger: %v", tailError) } }() } diff --git a/libpod/define/containerstate.go b/libpod/define/containerstate.go index 5d2bc9099..fc272beaa 100644 --- a/libpod/define/containerstate.go +++ b/libpod/define/containerstate.go @@ -1,6 +1,10 @@ package define -import "github.com/pkg/errors" +import ( + "time" + + "github.com/pkg/errors" +) // ContainerStatus represents the current state of a container type ContainerStatus int @@ -120,12 +124,14 @@ func (s ContainerExecStatus) String() string { // ContainerStats contains the statistics information for a running container type ContainerStats struct { + AvgCPU float64 ContainerID string Name string PerCPU []uint64 CPU float64 CPUNano uint64 CPUSystemNano uint64 + DataPoints int64 SystemNano uint64 MemUsage uint64 MemLimit uint64 @@ -135,4 +141,6 @@ type ContainerStats struct { BlockInput uint64 BlockOutput uint64 PIDs uint64 + UpTime time.Duration + Duration uint64 } diff --git a/libpod/events.go b/libpod/events.go index 839229674..22c51aeec 100644 --- a/libpod/events.go +++ b/libpod/events.go @@ -46,7 +46,22 @@ func (c *Container) newContainerExitedEvent(exitCode int32) { e.Type = events.Container e.ContainerExitCode = int(exitCode) if err := c.runtime.eventer.Write(e); err != nil { - logrus.Errorf("unable to write pod event: %q", err) + logrus.Errorf("unable to write container exited event: %q", err) + } +} + +// newExecDiedEvent creates a new event for an exec session's death +func (c *Container) newExecDiedEvent(sessionID string, exitCode int) { + e := events.NewEvent(events.ExecDied) + e.ID = c.ID() + e.Name = c.Name() + e.Image = c.config.RootfsImageName + e.Type = events.Container + e.ContainerExitCode = exitCode + e.Attributes = make(map[string]string) + e.Attributes["execID"] = sessionID + if err := c.runtime.eventer.Write(e); err != nil { + logrus.Errorf("unable to write exec died event: %q", err) } } @@ -154,3 +169,25 @@ func (r *Runtime) GetLastContainerEvent(ctx context.Context, nameOrID string, co // return the last element in the slice return containerEvents[len(containerEvents)-1], nil } + +// GetExecDiedEvent takes a container name or ID, exec session ID, and returns +// that exec session's Died event (if it has already occurred). +func (r *Runtime) GetExecDiedEvent(ctx context.Context, nameOrID, execSessionID string) (*events.Event, error) { + filters := []string{ + fmt.Sprintf("container=%s", nameOrID), + "event=exec_died", + "type=container", + fmt.Sprintf("label=execID=%s", execSessionID), + } + + containerEvents, err := r.GetEvents(ctx, filters) + if err != nil { + return nil, err + } + // There *should* only be one event maximum. + // But... just in case... let's not blow up if there's more than one. + if len(containerEvents) < 1 { + return nil, errors.Wrapf(events.ErrEventNotFound, "exec died event for session %s (container %s) not found", execSessionID, nameOrID) + } + return containerEvents[len(containerEvents)-1], nil +} diff --git a/libpod/events/config.go b/libpod/events/config.go index 085fa9d52..d88d7b6e3 100644 --- a/libpod/events/config.go +++ b/libpod/events/config.go @@ -127,6 +127,8 @@ const ( Create Status = "create" // Exec ... Exec Status = "exec" + // ExecDied indicates that an exec session in a container died. + ExecDied Status = "exec_died" // Exited indicates that a container's process died Exited Status = "died" // Export ... diff --git a/libpod/events/events.go b/libpod/events/events.go index 01ea6a386..e03215eff 100644 --- a/libpod/events/events.go +++ b/libpod/events/events.go @@ -149,6 +149,8 @@ func StringToStatus(name string) (Status, error) { return Create, nil case Exec.String(): return Exec, nil + case ExecDied.String(): + return ExecDied, nil case Exited.String(): return Exited, nil case Export.String(): diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go index c928e02a6..1b775a4f3 100644 --- a/libpod/networking_linux.go +++ b/libpod/networking_linux.go @@ -46,6 +46,9 @@ const ( // rootlessCNINSName is the file name for the rootless network namespace bind mount rootlessCNINSName = "rootless-cni-ns" + + // persistentCNIDir is the directory where the CNI files are stored + persistentCNIDir = "/var/lib/cni" ) // Get an OCICNI network config @@ -150,14 +153,31 @@ func (r *RootlessCNI) Do(toRun func() error) error { } } - // cni plugins need access to /var and /run - runDir := filepath.Join(r.dir, "run") - varDir := filepath.Join(r.dir, "var") + // cni plugins need access to /var/lib/cni and /run + varDir := "" + varTarget := persistentCNIDir + // we can only mount to a target dir which exists, check /var/lib/cni recursively + // while we could always use /var there are cases where a user might store the cni + // configs under /var/custom and this would break + for { + if _, err := os.Stat(varTarget); err == nil { + varDir = filepath.Join(r.dir, strings.TrimPrefix(varTarget, "/")) + break + } + varTarget = filepath.Base(varTarget) + if varTarget == "/" { + break + } + } + if varDir == "" { + return errors.New("failed to stat /var directory") + } // make sure to mount var first - err = unix.Mount(varDir, "/var", "none", unix.MS_BIND, "") + err = unix.Mount(varDir, varTarget, "none", unix.MS_BIND, "") if err != nil { - return errors.Wrap(err, "failed to mount /var for rootless cni") + return errors.Wrapf(err, "failed to mount %s for rootless cni", varTarget) } + runDir := filepath.Join(r.dir, "run") // recursive mount to keep the netns mount err = unix.Mount(runDir, "/run", "none", unix.MS_BIND|unix.MS_REC, "") if err != nil { @@ -385,7 +405,7 @@ func (r *Runtime) GetRootlessCNINetNs(new bool) (*RootlessCNI, error) { // create cni directories to store files // they will be bind mounted to the correct location in a extra mount ns - err = os.MkdirAll(filepath.Join(cniDir, "var"), 0700) + err = os.MkdirAll(filepath.Join(cniDir, strings.TrimPrefix(persistentCNIDir, "/")), 0700) if err != nil { return nil, errors.Wrap(err, "could not create rootless-cni var directory") } @@ -888,6 +908,10 @@ func (c *Container) getContainerNetworkInfo() (*define.InspectNetworkSettings, e if err != nil { return nil, err } + // see https://github.com/containers/podman/issues/10090 + // the container has to be locked for syncContainer() + netNsCtr.lock.Lock() + defer netNsCtr.lock.Unlock() // Have to sync to ensure that state is populated if err := netNsCtr.syncContainer(); err != nil { return nil, err @@ -1043,7 +1067,7 @@ func resultToBasicNetworkConfig(result *cnitypes.Result) (define.InspectBasicNet // after itself on an unclean reboot. Return what we're pretty sure is the path // to CNI's internal files (it's not really exposed to us). func getCNINetworksDir() (string, error) { - return "/var/lib/cni/networks", nil + return filepath.Join(persistentCNIDir, "networks"), nil } type logrusDebugWriter struct { @@ -1090,7 +1114,7 @@ func (c *Container) NetworkDisconnect(nameOrID, netName string, force bool) erro } c.newNetworkEvent(events.NetworkDisconnect, netName) - if c.state.State != define.ContainerStateRunning { + if !c.ensureState(define.ContainerStateRunning, define.ContainerStateCreated) { return nil } @@ -1145,7 +1169,7 @@ func (c *Container) NetworkConnect(nameOrID, netName string, aliases []string) e return err } c.newNetworkEvent(events.NetworkConnect, netName) - if c.state.State != define.ContainerStateRunning { + if !c.ensureState(define.ContainerStateRunning, define.ContainerStateCreated) { return nil } if c.state.NetNS == nil { diff --git a/libpod/oci.go b/libpod/oci.go index 1f2c7dd71..c92d9a077 100644 --- a/libpod/oci.go +++ b/libpod/oci.go @@ -72,13 +72,16 @@ type OCIRuntime interface { // has completed, as one might expect. The attach session will remain // running, in a goroutine that will return via the chan error in the // return signature. - ExecContainer(ctr *Container, sessionID string, options *ExecOptions, streams *define.AttachStreams) (int, chan error, error) + // newSize resizes the tty to this size before the process is started, must be nil if the exec session has no tty + ExecContainer(ctr *Container, sessionID string, options *ExecOptions, streams *define.AttachStreams, newSize *define.TerminalSize) (int, chan error, error) // ExecContainerHTTP executes a command in a running container and // attaches its standard streams to a provided hijacked HTTP session. // Maintains the same invariants as ExecContainer (returns on session // start, with a goroutine running in the background to handle attach). // The HTTP attach itself maintains the same invariants as HTTPAttach. - ExecContainerHTTP(ctr *Container, sessionID string, options *ExecOptions, r *http.Request, w http.ResponseWriter, streams *HTTPAttachStreams, cancel <-chan bool, hijackDone chan<- bool, holdConnOpen <-chan bool) (int, chan error, error) + // newSize resizes the tty to this size before the process is started, must be nil if the exec session has no tty + ExecContainerHTTP(ctr *Container, sessionID string, options *ExecOptions, r *http.Request, w http.ResponseWriter, + streams *HTTPAttachStreams, cancel <-chan bool, hijackDone chan<- bool, holdConnOpen <-chan bool, newSize *define.TerminalSize) (int, chan error, error) // ExecContainerDetached executes a command in a running container, but // does not attach to it. Returns the PID of the exec session and an // error (if starting the exec session failed) diff --git a/libpod/oci_attach_linux.go b/libpod/oci_attach_linux.go index b5040de3e..de435b58a 100644 --- a/libpod/oci_attach_linux.go +++ b/libpod/oci_attach_linux.go @@ -94,17 +94,18 @@ func (c *Container) attach(streams *define.AttachStreams, keys string, resize <- // this ensures attachToExec gets all of the output of the called process // conmon will then send the exit code of the exec process, or an error in the exec session // startFd must be the input side of the fd. +// newSize resizes the tty to this size before the process is started, must be nil if the exec session has no tty // conmon will wait to start the exec session until the parent process has setup the console socket. // Once attachToExec successfully attaches to the console socket, the child conmon process responsible for calling runtime exec // will read from the output side of start fd, thus learning to start the child process. // Thus, the order goes as follow: // 1. conmon parent process sets up its console socket. sends on attachFd -// 2. attachToExec attaches to the console socket after reading on attachFd +// 2. attachToExec attaches to the console socket after reading on attachFd and resizes the tty // 3. child waits on startFd for attachToExec to attach to said console socket // 4. attachToExec sends on startFd, signalling it has attached to the socket and child is ready to go // 5. child receives on startFd, runs the runtime exec command // attachToExec is responsible for closing startFd and attachFd -func (c *Container) attachToExec(streams *define.AttachStreams, keys *string, sessionID string, startFd, attachFd *os.File) error { +func (c *Container) attachToExec(streams *define.AttachStreams, keys *string, sessionID string, startFd, attachFd *os.File, newSize *define.TerminalSize) error { if !streams.AttachOutput && !streams.AttachError && !streams.AttachInput { return errors.Wrapf(define.ErrInvalidArg, "must provide at least one stream to attach to") } @@ -137,6 +138,14 @@ func (c *Container) attachToExec(streams *define.AttachStreams, keys *string, se return err } + // resize before we start the container process + if newSize != nil { + err = c.ociRuntime.ExecAttachResize(c, sessionID, *newSize) + if err != nil { + logrus.Warn("resize failed", err) + } + } + // 2: then attach conn, err := openUnixSocket(sockPath) if err != nil { diff --git a/libpod/oci_conmon_exec_linux.go b/libpod/oci_conmon_exec_linux.go index 76338b86c..09d3d1833 100644 --- a/libpod/oci_conmon_exec_linux.go +++ b/libpod/oci_conmon_exec_linux.go @@ -25,7 +25,7 @@ import ( ) // ExecContainer executes a command in a running container -func (r *ConmonOCIRuntime) ExecContainer(c *Container, sessionID string, options *ExecOptions, streams *define.AttachStreams) (int, chan error, error) { +func (r *ConmonOCIRuntime) ExecContainer(c *Container, sessionID string, options *ExecOptions, streams *define.AttachStreams, newSize *define.TerminalSize) (int, chan error, error) { if options == nil { return -1, nil, errors.Wrapf(define.ErrInvalidArg, "must provide an ExecOptions struct to ExecContainer") } @@ -68,7 +68,7 @@ func (r *ConmonOCIRuntime) ExecContainer(c *Container, sessionID string, options attachChan := make(chan error) go func() { // attachToExec is responsible for closing pipes - attachChan <- c.attachToExec(streams, options.DetachKeys, sessionID, pipes.startPipe, pipes.attachPipe) + attachChan <- c.attachToExec(streams, options.DetachKeys, sessionID, pipes.startPipe, pipes.attachPipe, newSize) close(attachChan) }() @@ -83,7 +83,8 @@ func (r *ConmonOCIRuntime) ExecContainer(c *Container, sessionID string, options // ExecContainerHTTP executes a new command in an existing container and // forwards its standard streams over an attach -func (r *ConmonOCIRuntime) ExecContainerHTTP(ctr *Container, sessionID string, options *ExecOptions, req *http.Request, w http.ResponseWriter, streams *HTTPAttachStreams, cancel <-chan bool, hijackDone chan<- bool, holdConnOpen <-chan bool) (int, chan error, error) { +func (r *ConmonOCIRuntime) ExecContainerHTTP(ctr *Container, sessionID string, options *ExecOptions, req *http.Request, w http.ResponseWriter, + streams *HTTPAttachStreams, cancel <-chan bool, hijackDone chan<- bool, holdConnOpen <-chan bool, newSize *define.TerminalSize) (int, chan error, error) { if streams != nil { if !streams.Stdin && !streams.Stdout && !streams.Stderr { return -1, nil, errors.Wrapf(define.ErrInvalidArg, "must provide at least one stream to attach to") @@ -133,7 +134,7 @@ func (r *ConmonOCIRuntime) ExecContainerHTTP(ctr *Container, sessionID string, o conmonPipeDataChan := make(chan conmonPipeData) go func() { // attachToExec is responsible for closing pipes - attachChan <- attachExecHTTP(ctr, sessionID, req, w, streams, pipes, detachKeys, options.Terminal, cancel, hijackDone, holdConnOpen, execCmd, conmonPipeDataChan, ociLog) + attachChan <- attachExecHTTP(ctr, sessionID, req, w, streams, pipes, detachKeys, options.Terminal, cancel, hijackDone, holdConnOpen, execCmd, conmonPipeDataChan, ociLog, newSize) close(attachChan) }() @@ -486,7 +487,7 @@ func (r *ConmonOCIRuntime) startExec(c *Container, sessionID string, options *Ex } // Attach to a container over HTTP -func attachExecHTTP(c *Container, sessionID string, r *http.Request, w http.ResponseWriter, streams *HTTPAttachStreams, pipes *execPipes, detachKeys []byte, isTerminal bool, cancel <-chan bool, hijackDone chan<- bool, holdConnOpen <-chan bool, execCmd *exec.Cmd, conmonPipeDataChan chan<- conmonPipeData, ociLog string) (deferredErr error) { +func attachExecHTTP(c *Container, sessionID string, r *http.Request, w http.ResponseWriter, streams *HTTPAttachStreams, pipes *execPipes, detachKeys []byte, isTerminal bool, cancel <-chan bool, hijackDone chan<- bool, holdConnOpen <-chan bool, execCmd *exec.Cmd, conmonPipeDataChan chan<- conmonPipeData, ociLog string, newSize *define.TerminalSize) (deferredErr error) { // NOTE: As you may notice, the attach code is quite complex. // Many things happen concurrently and yet are interdependent. // If you ever change this function, make sure to write to the @@ -524,6 +525,14 @@ func attachExecHTTP(c *Container, sessionID string, r *http.Request, w http.Resp return err } + // resize before we start the container process + if newSize != nil { + err = c.ociRuntime.ExecAttachResize(c, sessionID, *newSize) + if err != nil { + logrus.Warn("resize failed", err) + } + } + // 2: then attach conn, err := openUnixSocket(sockPath) if err != nil { diff --git a/libpod/oci_conmon_linux.go b/libpod/oci_conmon_linux.go index 3da49b85f..2914bd1a1 100644 --- a/libpod/oci_conmon_linux.go +++ b/libpod/oci_conmon_linux.go @@ -787,7 +787,11 @@ func (r *ConmonOCIRuntime) CheckpointContainer(ctr *Container, options Container args = append(args, "--pre-dump") } if !options.PreCheckPoint && options.WithPrevious { - args = append(args, "--parent-path", ctr.PreCheckPointPath()) + args = append( + args, + "--parent-path", + filepath.Join("..", preCheckpointDir), + ) } runtimeDir, err := util.GetRuntimeDir() if err != nil { diff --git a/libpod/oci_missing.go b/libpod/oci_missing.go index 10526f368..fcf2ffca8 100644 --- a/libpod/oci_missing.go +++ b/libpod/oci_missing.go @@ -119,12 +119,13 @@ func (r *MissingRuntime) AttachResize(ctr *Container, newSize define.TerminalSiz } // ExecContainer is not available as the runtime is missing -func (r *MissingRuntime) ExecContainer(ctr *Container, sessionID string, options *ExecOptions, streams *define.AttachStreams) (int, chan error, error) { +func (r *MissingRuntime) ExecContainer(ctr *Container, sessionID string, options *ExecOptions, streams *define.AttachStreams, newSize *define.TerminalSize) (int, chan error, error) { return -1, nil, r.printError() } // ExecContainerHTTP is not available as the runtime is missing -func (r *MissingRuntime) ExecContainerHTTP(ctr *Container, sessionID string, options *ExecOptions, req *http.Request, w http.ResponseWriter, streams *HTTPAttachStreams, cancel <-chan bool, hijackDone chan<- bool, holdConnOpen <-chan bool) (int, chan error, error) { +func (r *MissingRuntime) ExecContainerHTTP(ctr *Container, sessionID string, options *ExecOptions, req *http.Request, w http.ResponseWriter, + streams *HTTPAttachStreams, cancel <-chan bool, hijackDone chan<- bool, holdConnOpen <-chan bool, newSize *define.TerminalSize) (int, chan error, error) { return -1, nil, r.printError() } diff --git a/libpod/options.go b/libpod/options.go index f942d264b..f2468e41b 100644 --- a/libpod/options.go +++ b/libpod/options.go @@ -7,6 +7,7 @@ import ( "strings" "syscall" + "github.com/containers/buildah/pkg/parse" "github.com/containers/common/pkg/config" "github.com/containers/common/pkg/secrets" "github.com/containers/image/v5/manifest" @@ -268,8 +269,11 @@ func WithRegistriesConf(path string) RuntimeOption { return errors.Wrap(err, "error locating specified registries.conf") } if rt.imageContext == nil { - rt.imageContext = &types.SystemContext{} + rt.imageContext = &types.SystemContext{ + BigFilesTemporaryDir: parse.GetTempDir(), + } } + rt.imageContext.SystemRegistriesConfPath = path return nil } @@ -1641,6 +1645,19 @@ func WithVolumeGID(gid int) VolumeCreateOption { } } +// WithVolumeNoChown prevents the volume from being chowned to the process uid at first use. +func WithVolumeNoChown() VolumeCreateOption { + return func(volume *Volume) error { + if volume.valid { + return define.ErrVolumeFinalized + } + + volume.state.NeedsChown = false + + return nil + } +} + // withSetAnon sets a bool notifying libpod that this volume is anonymous and // should be removed when containers using it are removed and volumes are // specified for removal. diff --git a/libpod/runtime.go b/libpod/runtime.go index d775b55e1..f53789e89 100644 --- a/libpod/runtime.go +++ b/libpod/runtime.go @@ -15,6 +15,7 @@ import ( "syscall" "time" + "github.com/containers/buildah/pkg/parse" "github.com/containers/common/libimage" "github.com/containers/common/pkg/config" "github.com/containers/common/pkg/defaultnet" @@ -381,7 +382,9 @@ func makeRuntime(ctx context.Context, runtime *Runtime) (retErr error) { // Set up containers/image if runtime.imageContext == nil { - runtime.imageContext = &types.SystemContext{} + runtime.imageContext = &types.SystemContext{ + BigFilesTemporaryDir: parse.GetTempDir(), + } } runtime.imageContext.SignaturePolicyPath = runtime.config.Engine.SignaturePolicyPath @@ -465,7 +468,7 @@ func makeRuntime(ctx context.Context, runtime *Runtime) (retErr error) { } // Set up the CNI net plugin - netPlugin, err := ocicni.InitCNI(runtime.config.Network.DefaultNetwork, runtime.config.Network.NetworkConfigDir, runtime.config.Network.CNIPluginDirs...) + netPlugin, err := ocicni.InitCNINoInotify(runtime.config.Network.DefaultNetwork, runtime.config.Network.NetworkConfigDir, "", runtime.config.Network.CNIPluginDirs...) if err != nil { return errors.Wrapf(err, "error configuring CNI network plugin") } diff --git a/libpod/stats.go b/libpod/stats.go index f4732b4fc..6f0360ef1 100644 --- a/libpod/stats.go +++ b/libpod/stats.go @@ -56,7 +56,11 @@ func (c *Container) GetContainerStats(previousStats *define.ContainerStats) (*de previousCPU := previousStats.CPUNano now := uint64(time.Now().UnixNano()) + stats.Duration = cgroupStats.CPU.Usage.Total + stats.UpTime = time.Duration(stats.Duration) stats.CPU = calculateCPUPercent(cgroupStats, previousCPU, now, previousStats.SystemNano) + stats.AvgCPU = calculateAvgCPU(stats.CPU, previousStats.AvgCPU, previousStats.DataPoints) + stats.DataPoints = previousStats.DataPoints + 1 stats.MemUsage = cgroupStats.Memory.Usage.Usage stats.MemLimit = getMemLimit(cgroupStats.Memory.Usage.Limit) stats.MemPerc = (float64(stats.MemUsage) / float64(stats.MemLimit)) * 100 @@ -127,3 +131,9 @@ func calculateBlockIO(stats *cgroups.Metrics) (read uint64, write uint64) { } return } + +// calculateAvgCPU calculates the avg CPU percentage given the previous average and the number of data points. +func calculateAvgCPU(statsCPU float64, prevAvg float64, prevData int64) float64 { + avgPer := ((prevAvg * float64(prevData)) + statsCPU) / (float64(prevData) + 1) + return avgPer +} diff --git a/libpod/volume_internal.go b/libpod/volume_internal.go index 694cdd149..19008a253 100644 --- a/libpod/volume_internal.go +++ b/libpod/volume_internal.go @@ -39,8 +39,23 @@ func (v *Volume) needsMount() bool { return true } - // Local driver with options needs mount - return len(v.config.Options) > 0 + // Commit 28138dafcc added the UID and GID options to this map + // However we should only mount when options other than uid and gid are set. + // see https://github.com/containers/podman/issues/10620 + index := 0 + if _, ok := v.config.Options["UID"]; ok { + index++ + } + if _, ok := v.config.Options["GID"]; ok { + index++ + } + // when uid or gid is set there is also the "o" option + // set so we have to ignore this one as well + if index > 0 { + index++ + } + // Local driver with options other than uid,gid needs mount + return len(v.config.Options) > index } // update() updates the volume state from the DB. diff --git a/nix/default-arm64.nix b/nix/default-arm64.nix index 3e374c1bd..d29f75520 100644 --- a/nix/default-arm64.nix +++ b/nix/default-arm64.nix @@ -25,6 +25,21 @@ let -i "$dev"/include/glib-2.0/gobject/gobjectnotifyqueue.c ''; }); + pcsclite = (static pkg.pcsclite).overrideAttrs (x: { + configureFlags = [ + "--enable-confdir=/etc" + "--enable-usbdropdir=/var/lib/pcsc/drivers" + "--disable-libsystemd" + ]; + buildInputs = [ pkgs.python3 pkgs.udev pkgs.dbus pkgs.systemd ]; + }); + systemd = (static pkg.systemd).overrideAttrs (x: { + outputs = [ "out" "dev" ]; + mesonFlags = x.mesonFlags ++ [ + "-Dglib=false" + "-Dstatic-libsystemd=true" + ]; + }); }; }; }); @@ -47,8 +62,8 @@ let doCheck = false; enableParallelBuilding = true; outputs = [ "out" ]; - nativeBuildInputs = [ bash gitMinimal go-md2man installShellFiles makeWrapper pkg-config which ]; - buildInputs = [ glibc glibc.static gpgme libassuan libgpgerror libseccomp libapparmor libselinux ]; + nativeBuildInputs = [ bash gitMinimal go-md2man pkg-config which ]; + buildInputs = [ glibc glibc.static glib gpgme libassuan libgpgerror libseccomp libapparmor libselinux ]; prePatch = '' export CFLAGS='-static -pthread' export LDFLAGS='-s -w -static-libgcc -static' diff --git a/nix/default.nix b/nix/default.nix index aae520c9e..f6194e3d9 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -23,6 +23,21 @@ let -i "$dev"/include/glib-2.0/gobject/gobjectnotifyqueue.c ''; }); + pcsclite = (static pkg.pcsclite).overrideAttrs (x: { + configureFlags = [ + "--enable-confdir=/etc" + "--enable-usbdropdir=/var/lib/pcsc/drivers" + "--with-systemdsystemunitdir=${placeholder "bin"}/lib/systemd/system" + ]; + buildInputs = [ pkgs.python3 pkgs.udev pkgs.dbus pkgs.systemd ]; + }); + systemd = (static pkg.systemd).overrideAttrs (x: { + outputs = [ "out" "dev" ]; + mesonFlags = x.mesonFlags ++ [ + "-Dglib=false" + "-Dstatic-libsystemd=true" + ]; + }); }; }; }); @@ -45,8 +60,8 @@ let doCheck = false; enableParallelBuilding = true; outputs = [ "out" ]; - nativeBuildInputs = [ bash gitMinimal go-md2man installShellFiles makeWrapper pkg-config which ]; - buildInputs = [ glibc glibc.static gpgme libassuan libgpgerror libseccomp libapparmor libselinux ]; + nativeBuildInputs = [ bash gitMinimal go-md2man pkg-config which ]; + buildInputs = [ glibc glibc.static glib gpgme libassuan libgpgerror libseccomp libapparmor libselinux ]; prePatch = '' export CFLAGS='-static -pthread' export LDFLAGS='-s -w -static-libgcc -static' diff --git a/nix/nixpkgs.json b/nix/nixpkgs.json index 9b8b8289e..a9771eade 100644 --- a/nix/nixpkgs.json +++ b/nix/nixpkgs.json @@ -1,9 +1,9 @@ { "url": "https://github.com/nixos/nixpkgs", - "rev": "eb7e1ef185f6c990cda5f71fdc4fb02e76ab06d5", - "date": "2021-05-05T23:16:00+02:00", - "path": "/nix/store/a98lkhjlsqh32ic2kkrv5kkik6jy25wh-nixpkgs", - "sha256": "1ibz204c41g7baqga2iaj11yz9l75cfdylkiqjnk5igm81ivivxg", + "rev": "60cce7e5e1fdf62421ef6d4184ee399b46209366", + "date": "2021-06-09T01:18:50-04:00", + "path": "/nix/store/fixgn194626rb7gf99l9jaqm0hbqn2ix-nixpkgs", + "sha256": "100xrb925cana1kfd0c7gwkjjalq891vfgr0rn1gl9j8gp3l3gx6", "fetchSubmodules": false, "deepClone": false, "leaveDotGit": false diff --git a/nix/nixpkgs.nix b/nix/nixpkgs.nix index 21e7f17a2..11c20380a 100644 --- a/nix/nixpkgs.nix +++ b/nix/nixpkgs.nix @@ -5,4 +5,5 @@ let url = "${json.url}/archive/${json.rev}.tar.gz"; inherit (json) sha256; }); -in nixpkgs +in +nixpkgs diff --git a/pkg/api/handlers/compat/exec.go b/pkg/api/handlers/compat/exec.go index 1b7b884e0..77e62c112 100644 --- a/pkg/api/handlers/compat/exec.go +++ b/pkg/api/handlers/compat/exec.go @@ -178,8 +178,16 @@ func ExecStartHandler(w http.ResponseWriter, r *http.Request) { logrus.Error(errors.Wrapf(e, "error attaching to container %s exec session %s", sessionCtr.ID(), sessionID)) } + var size *define.TerminalSize + if bodyParams.Tty && (bodyParams.Height > 0 || bodyParams.Width > 0) { + size = &define.TerminalSize{ + Height: bodyParams.Height, + Width: bodyParams.Width, + } + } + hijackChan := make(chan bool, 1) - err = sessionCtr.ExecHTTPStartAndAttach(sessionID, r, w, nil, nil, nil, hijackChan) + err = sessionCtr.ExecHTTPStartAndAttach(sessionID, r, w, nil, nil, nil, hijackChan, size) if <-hijackChan { // If connection was Hijacked, we have to signal it's being closed diff --git a/pkg/api/handlers/compat/images.go b/pkg/api/handlers/compat/images.go index ac212474b..7baa1145a 100644 --- a/pkg/api/handlers/compat/images.go +++ b/pkg/api/handlers/compat/images.go @@ -166,10 +166,11 @@ func CreateImageFromSrc(w http.ResponseWriter, r *http.Request) { runtime := r.Context().Value("runtime").(*libpod.Runtime) query := struct { - FromSrc string `schema:"fromSrc"` - Changes []string `schema:"changes"` - Message string `schema:"message"` - Repo string `shchema:"repo"` + Changes []string `schema:"changes"` + FromSrc string `schema:"fromSrc"` + Message string `schema:"message"` + Platform string `schema:"platform"` + Repo string `shchema:"repo"` }{ // This is where you can override the golang default value for one of fields } @@ -192,9 +193,21 @@ func CreateImageFromSrc(w http.ResponseWriter, r *http.Request) { utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "failed to write temporary file")) } } + + platformSpecs := strings.Split(query.Platform, "/") + opts := entities.ImageImportOptions{ + Source: source, + Changes: query.Changes, + Message: query.Message, + Reference: query.Repo, + OS: platformSpecs[0], + } + if len(platformSpecs) > 1 { + opts.Architecture = platformSpecs[1] + } + imageEngine := abi.ImageEngine{Libpod: runtime} - // TODO: add support for ImageImportOptions to take a platform parameter. Also import https://github.com/opencontainers/image-spec/tree/master/specs-go/v1 either here or within imageEngine.Import to get default platform - report, err := imageEngine.Import(r.Context(), entities.ImageImportOptions{Source: source, Changes: query.Changes, Message: query.Message, Reference: query.Repo}) + report, err := imageEngine.Import(r.Context(), opts) if err != nil { utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to import tarball")) return diff --git a/pkg/api/handlers/compat/images_build.go b/pkg/api/handlers/compat/images_build.go index 6ff557291..e933b9811 100644 --- a/pkg/api/handlers/compat/images_build.go +++ b/pkg/api/handlers/compat/images_build.go @@ -139,6 +139,31 @@ func BuildImage(w http.ResponseWriter, r *http.Request) { addCaps = m } + // convert addcaps formats + containerFiles := []string{} + if _, found := r.URL.Query()["dockerfile"]; found { + var m = []string{} + if err := json.Unmarshal([]byte(query.Dockerfile), &m); err != nil { + // it's not json, assume just a string + m = append(m, query.Dockerfile) + } + containerFiles = m + } else { + containerFiles = []string{"Dockerfile"} + if utils.IsLibpodRequest(r) { + containerFiles = []string{"Containerfile"} + if _, err = os.Stat(filepath.Join(contextDirectory, "Containerfile")); err != nil { + if _, err1 := os.Stat(filepath.Join(contextDirectory, "Dockerfile")); err1 == nil { + containerFiles = []string{"Dockerfile"} + } else { + utils.BadRequest(w, "dockerfile", query.Dockerfile, err) + } + } + } else { + containerFiles = []string{"Dockerfile"} + } + } + addhosts := []string{} if _, found := r.URL.Query()["extrahosts"]; found { if err := json.Unmarshal([]byte(query.AddHosts), &addhosts); err != nil { @@ -164,8 +189,8 @@ func BuildImage(w http.ResponseWriter, r *http.Request) { var devices = []string{} if _, found := r.URL.Query()["devices"]; found { var m = []string{} - if err := json.Unmarshal([]byte(query.DropCapabilities), &m); err != nil { - utils.BadRequest(w, "devices", query.DropCapabilities, err) + if err := json.Unmarshal([]byte(query.Devices), &m); err != nil { + utils.BadRequest(w, "devices", query.Devices, err) return } devices = m @@ -470,7 +495,7 @@ func BuildImage(w http.ResponseWriter, r *http.Request) { runCtx, cancel := context.WithCancel(context.Background()) go func() { defer cancel() - imageID, _, err = runtime.Build(r.Context(), buildOptions, query.Dockerfile) + imageID, _, err = runtime.Build(r.Context(), buildOptions, containerFiles...) if err == nil { success = true } else { diff --git a/pkg/api/handlers/compat/resize.go b/pkg/api/handlers/compat/resize.go index f65e313fc..844fb74c4 100644 --- a/pkg/api/handlers/compat/resize.go +++ b/pkg/api/handlers/compat/resize.go @@ -73,7 +73,7 @@ func ResizeTTY(w http.ResponseWriter, r *http.Request) { return } if err := ctnr.ExecResize(name, sz); err != nil { - if errors.Cause(err) != define.ErrCtrStateInvalid || !query.IgnoreNotRunning { + if errors.Cause(err) != define.ErrExecSessionStateInvalid || !query.IgnoreNotRunning { utils.InternalServerError(w, errors.Wrapf(err, "cannot resize session")) return } diff --git a/pkg/api/handlers/libpod/images_pull.go b/pkg/api/handlers/libpod/images_pull.go index e88b53a4b..04b415638 100644 --- a/pkg/api/handlers/libpod/images_pull.go +++ b/pkg/api/handlers/libpod/images_pull.go @@ -26,14 +26,16 @@ func ImagesPull(w http.ResponseWriter, r *http.Request) { runtime := r.Context().Value("runtime").(*libpod.Runtime) decoder := r.Context().Value("decoder").(*schema.Decoder) query := struct { - Reference string `schema:"reference"` - OS string `schema:"OS"` - Arch string `schema:"Arch"` - Variant string `schema:"Variant"` - TLSVerify bool `schema:"tlsVerify"` - AllTags bool `schema:"allTags"` + Reference string `schema:"reference"` + OS string `schema:"OS"` + Arch string `schema:"Arch"` + Variant string `schema:"Variant"` + TLSVerify bool `schema:"tlsVerify"` + AllTags bool `schema:"allTags"` + PullPolicy string `schema:"policy"` }{ - TLSVerify: true, + TLSVerify: true, + PullPolicy: "always", } if err := decoder.Decode(&query, r.URL.Query()); err != nil { @@ -83,12 +85,18 @@ func ImagesPull(w http.ResponseWriter, r *http.Request) { pullOptions.Writer = writer + pullPolicy, err := config.ParsePullPolicy(query.PullPolicy) + if err != nil { + utils.Error(w, "failed to parse pull policy", http.StatusBadRequest, err) + return + } + var pulledImages []*libimage.Image var pullError error runCtx, cancel := context.WithCancel(r.Context()) go func() { defer cancel() - pulledImages, pullError = runtime.LibimageRuntime().Pull(runCtx, query.Reference, config.PullPolicyAlways, pullOptions) + pulledImages, pullError = runtime.LibimageRuntime().Pull(runCtx, query.Reference, pullPolicy, pullOptions) }() flush := func() { diff --git a/pkg/api/handlers/types.go b/pkg/api/handlers/types.go index f94c9a1f5..ee157cb56 100644 --- a/pkg/api/handlers/types.go +++ b/pkg/api/handlers/types.go @@ -157,8 +157,10 @@ type ExecCreateResponse struct { } type ExecStartConfig struct { - Detach bool `json:"Detach"` - Tty bool `json:"Tty"` + Detach bool `json:"Detach"` + Tty bool `json:"Tty"` + Height uint16 `json:"h"` + Width uint16 `json:"w"` } func ImageToImageSummary(l *libimage.Image) (*entities.ImageSummary, error) { diff --git a/pkg/api/server/register_exec.go b/pkg/api/server/register_exec.go index 3716ef6a2..e353d714c 100644 --- a/pkg/api/server/register_exec.go +++ b/pkg/api/server/register_exec.go @@ -269,10 +269,16 @@ func (s *APIServer) registerExecHandlers(r *mux.Router) error { // properties: // Detach: // type: boolean - // description: Detach from the command. Not presently supported. + // description: Detach from the command. // Tty: // type: boolean - // description: Allocate a pseudo-TTY. Presently ignored. + // description: Allocate a pseudo-TTY. + // h: + // type: integer + // description: Height of the TTY session in characters. Tty must be set to true to use it. + // w: + // type: integer + // description: Width of the TTY session in characters. Tty must be set to true to use it. // produces: // - application/json // responses: diff --git a/pkg/api/server/register_images.go b/pkg/api/server/register_images.go index b28818768..3410c53cd 100644 --- a/pkg/api/server/register_images.go +++ b/pkg/api/server/register_images.go @@ -962,10 +962,6 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // description: "Mandatory reference to the image (e.g., quay.io/image/name:tag)" // type: string // - in: query - // name: credentials - // description: "username:password for the registry" - // type: string - // - in: query // name: Arch // description: Pull image for the specified architecture. // type: string @@ -978,6 +974,10 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // description: Pull image for the specified variant. // type: string // - in: query + // name: policy + // description: Pull policy, "always" (default), "missing", "newer", "never". + // type: string + // - in: query // name: tlsVerify // description: Require TLS verification. // type: boolean @@ -986,6 +986,10 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // name: allTags // description: Pull all tagged images in the repository. // type: boolean + // - in: header + // name: X-Registry-Auth + // description: "base-64 encoded auth config. Must include the following four values: username, password, email and server address OR simply just an identity token." + // type: string // produces: // - application/json // responses: diff --git a/pkg/bindings/containers/attach.go b/pkg/bindings/containers/attach.go index adef1e7c8..cc12c8ab7 100644 --- a/pkg/bindings/containers/attach.go +++ b/pkg/bindings/containers/attach.go @@ -343,7 +343,7 @@ func attachHandleResize(ctx, winCtx context.Context, winChange chan os.Signal, i resizeErr = ResizeContainerTTY(ctx, id, new(ResizeTTYOptions).WithHeight(h).WithWidth(w)) } if resizeErr != nil { - logrus.Warnf("failed to resize TTY: %v", resizeErr) + logrus.Infof("failed to resize TTY: %v", resizeErr) } } @@ -408,6 +408,17 @@ func ExecStartAndAttach(ctx context.Context, sessionID string, options *ExecStar // If we are in TTY mode, we need to set raw mode for the terminal. // TODO: Share all of this with Attach() for containers. needTTY := terminalFile != nil && terminal.IsTerminal(int(terminalFile.Fd())) && isTerm + + body := struct { + Detach bool `json:"Detach"` + TTY bool `json:"Tty"` + Height uint16 `json:"h"` + Width uint16 `json:"w"` + }{ + Detach: false, + TTY: needTTY, + } + if needTTY { state, err := setRawTerminal(terminalFile) if err != nil { @@ -419,13 +430,14 @@ func ExecStartAndAttach(ctx context.Context, sessionID string, options *ExecStar } logrus.SetFormatter(&logrus.TextFormatter{}) }() + w, h, err := terminal.GetSize(int(terminalFile.Fd())) + if err != nil { + logrus.Warnf("failed to obtain TTY size: %v", err) + } + body.Width = uint16(w) + body.Height = uint16(h) } - body := struct { - Detach bool `json:"Detach"` - }{ - Detach: false, - } bodyJSON, err := json.Marshal(body) if err != nil { return err diff --git a/pkg/bindings/images/build.go b/pkg/bindings/images/build.go index 346d55c47..937d05330 100644 --- a/pkg/bindings/images/build.go +++ b/pkg/bindings/images/build.go @@ -282,10 +282,6 @@ func Build(ctx context.Context, containerFiles []string, options entities.BuildO stdout = options.Out } - entries := make([]string, len(containerFiles)) - copy(entries, containerFiles) - entries = append(entries, options.ContextDirectory) - excludes := options.Excludes if len(excludes) == 0 { excludes, err = parseDockerignore(options.ContextDirectory) @@ -294,33 +290,73 @@ func Build(ctx context.Context, containerFiles []string, options entities.BuildO } } - tarfile, err := nTar(excludes, entries...) + contextDir, err := filepath.Abs(options.ContextDirectory) if err != nil { - logrus.Errorf("cannot tar container entries %v error: %v", entries, err) + logrus.Errorf("cannot find absolute path of %v: %v", options.ContextDirectory, err) return nil, err } - defer func() { - if err := tarfile.Close(); err != nil { - logrus.Errorf("%v\n", err) + + tarContent := []string{options.ContextDirectory} + newContainerFiles := []string{} + for _, c := range containerFiles { + if c == "/dev/stdin" { + content, err := ioutil.ReadAll(os.Stdin) + if err != nil { + return nil, err + } + tmpFile, err := ioutil.TempFile("", "build") + if err != nil { + return nil, err + } + defer os.Remove(tmpFile.Name()) // clean up + defer tmpFile.Close() + if _, err := tmpFile.Write(content); err != nil { + return nil, err + } + c = tmpFile.Name() + } + containerfile, err := filepath.Abs(c) + if err != nil { + logrus.Errorf("cannot find absolute path of %v: %v", c, err) + return nil, err } - }() - containerFile, err := filepath.Abs(entries[0]) - if err != nil { - logrus.Errorf("cannot find absolute path of %v: %v", entries[0], err) - return nil, err + // Check if Containerfile is in the context directory, if so truncate the contextdirectory off path + // Do NOT add to tarfile + if strings.HasPrefix(containerfile, contextDir+string(filepath.Separator)) { + containerfile = strings.TrimPrefix(containerfile, contextDir+string(filepath.Separator)) + } else { + // If Containerfile does not exists assume it is in context directory, do Not add to tarfile + if _, err := os.Lstat(containerfile); err != nil { + if !os.IsNotExist(err) { + return nil, err + } + containerfile = c + } else { + // If Containerfile does exists but is not in context directory add it to the tarfile + tarContent = append(tarContent, containerfile) + } + } + newContainerFiles = append(newContainerFiles, containerfile) } - contextDir, err := filepath.Abs(entries[1]) - if err != nil { - logrus.Errorf("cannot find absolute path of %v: %v", entries[1], err) - return nil, err + if len(newContainerFiles) > 0 { + cFileJSON, err := json.Marshal(newContainerFiles) + if err != nil { + return nil, err + } + params.Set("dockerfile", string(cFileJSON)) } - if strings.HasPrefix(containerFile, contextDir+string(filepath.Separator)) { - containerFile = strings.TrimPrefix(containerFile, contextDir+string(filepath.Separator)) + tarfile, err := nTar(excludes, tarContent...) + if err != nil { + logrus.Errorf("cannot tar container entries %v error: %v", tarContent, err) + return nil, err } - - params.Set("dockerfile", containerFile) + defer func() { + if err := tarfile.Close(); err != nil { + logrus.Errorf("%v\n", err) + } + }() conn, err := bindings.GetClient(ctx) if err != nil { diff --git a/pkg/bindings/images/pull.go b/pkg/bindings/images/pull.go index 9780c3bff..7dfe9560c 100644 --- a/pkg/bindings/images/pull.go +++ b/pkg/bindings/images/pull.go @@ -13,7 +13,7 @@ import ( "github.com/containers/podman/v3/pkg/auth" "github.com/containers/podman/v3/pkg/bindings" "github.com/containers/podman/v3/pkg/domain/entities" - "github.com/hashicorp/go-multierror" + "github.com/containers/podman/v3/pkg/errorhandling" "github.com/pkg/errors" ) @@ -65,7 +65,7 @@ func Pull(ctx context.Context, rawImage string, options *PullOptions) ([]string, dec := json.NewDecoder(response.Body) var images []string - var mErr error + var pullErrors []error for { var report entities.ImagePullReport if err := dec.Decode(&report); err != nil { @@ -77,7 +77,7 @@ func Pull(ctx context.Context, rawImage string, options *PullOptions) ([]string, select { case <-response.Request.Context().Done(): - return images, mErr + break default: // non-blocking select } @@ -86,7 +86,7 @@ func Pull(ctx context.Context, rawImage string, options *PullOptions) ([]string, case report.Stream != "": fmt.Fprint(stderr, report.Stream) case report.Error != "": - mErr = multierror.Append(mErr, errors.New(report.Error)) + pullErrors = append(pullErrors, errors.New(report.Error)) case len(report.Images) > 0: images = report.Images case report.ID != "": @@ -94,5 +94,5 @@ func Pull(ctx context.Context, rawImage string, options *PullOptions) ([]string, return images, errors.Errorf("failed to parse pull results stream, unexpected input: %v", report) } } - return images, mErr + return images, errorhandling.JoinErrors(pullErrors) } diff --git a/pkg/bindings/images/types.go b/pkg/bindings/images/types.go index 1f3e46729..0aa75a81e 100644 --- a/pkg/bindings/images/types.go +++ b/pkg/bindings/images/types.go @@ -147,6 +147,9 @@ type PullOptions struct { // OS will overwrite the local operating system (OS) for image // pulls. OS *string + // Policy is the pull policy. Supported values are "missing", "never", + // "newer", "always". An empty string defaults to "always". + Policy *string // Password for authenticating against the registry. Password *string // Quiet can be specified to suppress pull progress when pulling. Ignored diff --git a/pkg/bindings/images/types_pull_options.go b/pkg/bindings/images/types_pull_options.go index 0611c4447..8fcf499eb 100644 --- a/pkg/bindings/images/types_pull_options.go +++ b/pkg/bindings/images/types_pull_options.go @@ -84,6 +84,22 @@ func (o *PullOptions) GetOS() string { return *o.OS } +// WithPolicy +func (o *PullOptions) WithPolicy(value string) *PullOptions { + v := &value + o.Policy = v + return o +} + +// GetPolicy +func (o *PullOptions) GetPolicy() string { + var policy string + if o.Policy == nil { + return policy + } + return *o.Policy +} + // WithPassword func (o *PullOptions) WithPassword(value string) *PullOptions { v := &value diff --git a/pkg/cgroups/cgroups.go b/pkg/cgroups/cgroups.go index 911edeb5b..9cb32a364 100644 --- a/pkg/cgroups/cgroups.go +++ b/pkg/cgroups/cgroups.go @@ -165,14 +165,13 @@ func getAvailableControllers(exclude map[string]controllerHandler, cgroup2 bool) if _, found := exclude[name]; found { continue } - isSymLink := false fileInfo, err := os.Stat(cgroupRoot + "/" + name) if err != nil { - isSymLink = !fileInfo.IsDir() + continue } c := controller{ name: name, - symlink: isSymLink, + symlink: !fileInfo.IsDir(), } controllers = append(controllers, c) } diff --git a/pkg/domain/entities/images.go b/pkg/domain/entities/images.go index 3cc46ed0a..3140a47c5 100644 --- a/pkg/domain/entities/images.go +++ b/pkg/domain/entities/images.go @@ -184,7 +184,7 @@ type ImagePushOptions struct { // image to the file. Ignored for remote calls. DigestFile string // Format is the Manifest type (oci, v2s1, or v2s2) to use when pushing an - // image using the 'dir' transport. Default is manifest type of source. + // image. Default is manifest type of source, with fallbacks. // Ignored for remote calls. Format string // Quiet can be specified to suppress pull progress when pulling. Ignored @@ -271,8 +271,10 @@ type ImageLoadReport struct { } type ImageImportOptions struct { + Architecture string Changes []string Message string + OS string Quiet bool Reference string SignaturePolicy string diff --git a/pkg/domain/infra/abi/containers.go b/pkg/domain/infra/abi/containers.go index 4908e72f6..e6dd19e63 100644 --- a/pkg/domain/infra/abi/containers.go +++ b/pkg/domain/infra/abi/containers.go @@ -595,7 +595,7 @@ func (ic *ContainerEngine) ContainerAttach(ctx context.Context, nameOrID string, return nil } -func makeExecConfig(options entities.ExecOptions) *libpod.ExecConfig { +func makeExecConfig(options entities.ExecOptions, rt *libpod.Runtime) (*libpod.ExecConfig, error) { execConfig := new(libpod.ExecConfig) execConfig.Command = options.Cmd execConfig.Terminal = options.Tty @@ -607,7 +607,20 @@ func makeExecConfig(options entities.ExecOptions) *libpod.ExecConfig { execConfig.PreserveFDs = options.PreserveFDs execConfig.AttachStdin = options.Interactive - return execConfig + // Make an exit command + storageConfig := rt.StorageConfig() + runtimeConfig, err := rt.GetConfig() + if err != nil { + return nil, errors.Wrapf(err, "error retrieving Libpod configuration to build exec exit command") + } + // TODO: Add some ability to toggle syslog + exitCommandArgs, err := generate.CreateExitCommandArgs(storageConfig, runtimeConfig, false, true, true) + if err != nil { + return nil, errors.Wrapf(err, "error constructing exit command for exec session") + } + execConfig.ExitCommand = exitCommandArgs + + return execConfig, nil } func checkExecPreserveFDs(options entities.ExecOptions) error { @@ -647,7 +660,10 @@ func (ic *ContainerEngine) ContainerExec(ctx context.Context, nameOrID string, o } ctr := ctrs[0] - execConfig := makeExecConfig(options) + execConfig, err := makeExecConfig(options, ic.Libpod) + if err != nil { + return ec, err + } ec, err = terminal.ExecAttachCtr(ctx, ctr, execConfig, &streams) return define.TranslateExecErrorToExitCode(ec, err), err @@ -664,20 +680,10 @@ func (ic *ContainerEngine) ContainerExecDetached(ctx context.Context, nameOrID s } ctr := ctrs[0] - execConfig := makeExecConfig(options) - - // Make an exit command - storageConfig := ic.Libpod.StorageConfig() - runtimeConfig, err := ic.Libpod.GetConfig() - if err != nil { - return "", errors.Wrapf(err, "error retrieving Libpod configuration to build exec exit command") - } - // TODO: Add some ability to toggle syslog - exitCommandArgs, err := generate.CreateExitCommandArgs(storageConfig, runtimeConfig, false, true, true) + execConfig, err := makeExecConfig(options, ic.Libpod) if err != nil { - return "", errors.Wrapf(err, "error constructing exit command for exec session") + return "", err } - execConfig.ExitCommand = exitCommandArgs // Create and start the exec session id, err := ctr.ExecCreate(execConfig) @@ -696,7 +702,9 @@ func (ic *ContainerEngine) ContainerStart(ctx context.Context, namesOrIds []stri reports := []*entities.ContainerStartReport{} var exitCode = define.ExecErrorCodeGeneric containersNamesOrIds := namesOrIds + all := options.All if len(options.Filters) > 0 { + all = false filterFuncs := make([]libpod.ContainerFilter, 0, len(options.Filters)) if len(options.Filters) > 0 { for k, v := range options.Filters { @@ -713,6 +721,10 @@ func (ic *ContainerEngine) ContainerStart(ctx context.Context, namesOrIds []stri } containersNamesOrIds = []string{} for _, candidate := range candidates { + if options.All { + containersNamesOrIds = append(containersNamesOrIds, candidate.ID()) + continue + } for _, nameOrID := range namesOrIds { if nameOrID == candidate.ID() || nameOrID == candidate.Name() { containersNamesOrIds = append(containersNamesOrIds, nameOrID) @@ -720,8 +732,7 @@ func (ic *ContainerEngine) ContainerStart(ctx context.Context, namesOrIds []stri } } } - - ctrs, rawInputs, err := getContainersAndInputByContext(options.All, options.Latest, containersNamesOrIds, ic.Libpod) + ctrs, rawInputs, err := getContainersAndInputByContext(all, options.Latest, containersNamesOrIds, ic.Libpod) if err != nil { return nil, err } diff --git a/pkg/domain/infra/abi/images.go b/pkg/domain/infra/abi/images.go index 083566201..5992181d3 100644 --- a/pkg/domain/infra/abi/images.go +++ b/pkg/domain/infra/abi/images.go @@ -388,6 +388,8 @@ func (ir *ImageEngine) Import(ctx context.Context, options entities.ImageImportO importOptions.CommitMessage = options.Message importOptions.Tag = options.Reference importOptions.SignaturePolicyPath = options.SignaturePolicy + importOptions.OS = options.OS + importOptions.Architecture = options.Architecture if !options.Quiet { importOptions.Writer = os.Stderr diff --git a/pkg/domain/infra/abi/parse/parse.go b/pkg/domain/infra/abi/parse/parse.go index 1c590d2d6..56c747711 100644 --- a/pkg/domain/infra/abi/parse/parse.go +++ b/pkg/domain/infra/abi/parse/parse.go @@ -37,7 +37,7 @@ func VolumeOptions(opts map[string]string) ([]libpod.VolumeCreateOption, error) return nil, errors.Wrapf(err, "cannot convert UID %s to integer", splitO[1]) } logrus.Debugf("Removing uid= from options and adding WithVolumeUID for UID %d", intUID) - libpodOptions = append(libpodOptions, libpod.WithVolumeUID(intUID)) + libpodOptions = append(libpodOptions, libpod.WithVolumeUID(intUID), libpod.WithVolumeNoChown()) finalVal = append(finalVal, o) // set option "UID": "$uid" volumeOptions["UID"] = splitO[1] @@ -50,7 +50,7 @@ func VolumeOptions(opts map[string]string) ([]libpod.VolumeCreateOption, error) return nil, errors.Wrapf(err, "cannot convert GID %s to integer", splitO[1]) } logrus.Debugf("Removing gid= from options and adding WithVolumeGID for GID %d", intGID) - libpodOptions = append(libpodOptions, libpod.WithVolumeGID(intGID)) + libpodOptions = append(libpodOptions, libpod.WithVolumeGID(intGID), libpod.WithVolumeNoChown()) finalVal = append(finalVal, o) // set option "GID": "$gid" volumeOptions["GID"] = splitO[1] diff --git a/pkg/domain/infra/abi/terminal/terminal_linux.go b/pkg/domain/infra/abi/terminal/terminal_linux.go index ab71f8f6f..09c0f802d 100644 --- a/pkg/domain/infra/abi/terminal/terminal_linux.go +++ b/pkg/domain/infra/abi/terminal/terminal_linux.go @@ -15,12 +15,13 @@ import ( // ExecAttachCtr execs and attaches to a container func ExecAttachCtr(ctx context.Context, ctr *libpod.Container, execConfig *libpod.ExecConfig, streams *define.AttachStreams) (int, error) { - resize := make(chan define.TerminalSize) + var resize chan define.TerminalSize haveTerminal := terminal.IsTerminal(int(os.Stdin.Fd())) // Check if we are attached to a terminal. If we are, generate resize // events, and set the terminal to raw mode if haveTerminal && execConfig.Terminal { + resize = make(chan define.TerminalSize) cancel, oldTermState, err := handleTerminalAttach(ctx, resize) if err != nil { return -1, err @@ -32,7 +33,6 @@ func ExecAttachCtr(ctx context.Context, ctr *libpod.Container, execConfig *libpo } }() } - return ctr.Exec(execConfig, streams, resize) } diff --git a/pkg/domain/infra/tunnel/containers.go b/pkg/domain/infra/tunnel/containers.go index 74ced300a..0047fc839 100644 --- a/pkg/domain/infra/tunnel/containers.go +++ b/pkg/domain/infra/tunnel/containers.go @@ -508,7 +508,9 @@ func (ic *ContainerEngine) ContainerStart(ctx context.Context, namesOrIds []stri reports := []*entities.ContainerStartReport{} var exitCode = define.ExecErrorCodeGeneric containersNamesOrIds := namesOrIds + all := options.All if len(options.Filters) > 0 { + all = false containersNamesOrIds = []string{} opts := new(containers.ListOptions).WithFilters(options.Filters).WithAll(true) candidates, listErr := containers.List(ic.ClientCtx, opts) @@ -516,6 +518,10 @@ func (ic *ContainerEngine) ContainerStart(ctx context.Context, namesOrIds []stri return nil, listErr } for _, candidate := range candidates { + if options.All { + containersNamesOrIds = append(containersNamesOrIds, candidate.ID) + continue + } for _, nameOrID := range namesOrIds { if nameOrID == candidate.ID { containersNamesOrIds = append(containersNamesOrIds, nameOrID) @@ -530,7 +536,7 @@ func (ic *ContainerEngine) ContainerStart(ctx context.Context, namesOrIds []stri } } } - ctrs, err := getContainersByContext(ic.ClientCtx, options.All, false, containersNamesOrIds) + ctrs, err := getContainersByContext(ic.ClientCtx, all, false, containersNamesOrIds) if err != nil { return nil, err } diff --git a/pkg/domain/infra/tunnel/images.go b/pkg/domain/infra/tunnel/images.go index 3fd9a755d..42027a2dc 100644 --- a/pkg/domain/infra/tunnel/images.go +++ b/pkg/domain/infra/tunnel/images.go @@ -107,7 +107,7 @@ func (ir *ImageEngine) Pull(ctx context.Context, rawImage string, opts entities. options := new(images.PullOptions) options.WithAllTags(opts.AllTags).WithAuthfile(opts.Authfile).WithArch(opts.Arch).WithOS(opts.OS) options.WithVariant(opts.Variant).WithPassword(opts.Password) - options.WithQuiet(opts.Quiet).WithUsername(opts.Username) + options.WithQuiet(opts.Quiet).WithUsername(opts.Username).WithPolicy(opts.PullPolicy.String()) if s := opts.SkipTLSVerify; s != types.OptionalBoolUndefined { if s == types.OptionalBoolTrue { options.WithSkipTLSVerify(true) diff --git a/pkg/errorhandling/errorhandling.go b/pkg/errorhandling/errorhandling.go index 9b1740006..6adbc9f34 100644 --- a/pkg/errorhandling/errorhandling.go +++ b/pkg/errorhandling/errorhandling.go @@ -15,6 +15,12 @@ func JoinErrors(errs []error) error { return nil } + // If there's just one error, return it. This prevents the "%d errors + // occurred:" header plus list from the multierror package. + if len(errs) == 1 { + return errs[0] + } + // `multierror` appends new lines which we need to remove to prevent // blank lines when printing the error. var multiE *multierror.Error @@ -24,9 +30,6 @@ func JoinErrors(errs []error) error { if finalErr == nil { return finalErr } - if len(multiE.WrappedErrors()) == 1 && logrus.IsLevelEnabled(logrus.TraceLevel) { - return multiE.WrappedErrors()[0] - } return errors.New(strings.TrimSpace(finalErr.Error())) } diff --git a/pkg/machine/config.go b/pkg/machine/config.go index 58794ce42..db9bfa7de 100644 --- a/pkg/machine/config.go +++ b/pkg/machine/config.go @@ -1,3 +1,5 @@ +// +build amd64,linux arm64,linux amd64,darwin arm64,darwin + package machine import ( diff --git a/pkg/machine/connection.go b/pkg/machine/connection.go index e3985d8ac..3edcbd10e 100644 --- a/pkg/machine/connection.go +++ b/pkg/machine/connection.go @@ -1,3 +1,5 @@ +// +build amd64,linux arm64,linux amd64,darwin arm64,darwin + package machine import ( diff --git a/pkg/machine/fcos.go b/pkg/machine/fcos.go index 32f943c87..11936aee7 100644 --- a/pkg/machine/fcos.go +++ b/pkg/machine/fcos.go @@ -1,3 +1,5 @@ +// +build amd64,linux arm64,linux amd64,darwin arm64,darwin + package machine import ( diff --git a/pkg/machine/ignition.go b/pkg/machine/ignition.go index a5c7210af..1d77083d0 100644 --- a/pkg/machine/ignition.go +++ b/pkg/machine/ignition.go @@ -1,3 +1,5 @@ +// +build amd64,linux arm64,linux amd64,darwin arm64,darwin + package machine import ( diff --git a/pkg/machine/ignition_schema.go b/pkg/machine/ignition_schema.go index 9dbd90ba4..6ac8af826 100644 --- a/pkg/machine/ignition_schema.go +++ b/pkg/machine/ignition_schema.go @@ -1,3 +1,5 @@ +// +build amd64,linux arm64,linux amd64,darwin arm64,darwin + package machine /* diff --git a/pkg/machine/keys.go b/pkg/machine/keys.go index 907e28f55..81ec44ea8 100644 --- a/pkg/machine/keys.go +++ b/pkg/machine/keys.go @@ -1,3 +1,5 @@ +// +build amd64,linux arm64,linux amd64,darwin arm64,darwin + package machine import ( diff --git a/pkg/machine/libvirt/config.go b/pkg/machine/libvirt/config.go index 903f15fbc..1ce5ab154 100644 --- a/pkg/machine/libvirt/config.go +++ b/pkg/machine/libvirt/config.go @@ -1,3 +1,5 @@ +// +build amd64,linux arm64,linux amd64,darwin arm64,darwin + package libvirt type MachineVM struct { diff --git a/pkg/machine/libvirt/machine.go b/pkg/machine/libvirt/machine.go index c38f63853..e1aa1569b 100644 --- a/pkg/machine/libvirt/machine.go +++ b/pkg/machine/libvirt/machine.go @@ -1,3 +1,5 @@ +// +build amd64,linux arm64,linux amd64,darwin arm64,darwin + package libvirt import "github.com/containers/podman/v3/pkg/machine" diff --git a/pkg/machine/libvirt/machine_unsupported.go b/pkg/machine/libvirt/machine_unsupported.go new file mode 100644 index 000000000..8b54440fe --- /dev/null +++ b/pkg/machine/libvirt/machine_unsupported.go @@ -0,0 +1,3 @@ +// +build !amd64 amd64,windows + +package libvirt diff --git a/pkg/machine/machine_unsupported.go b/pkg/machine/machine_unsupported.go new file mode 100644 index 000000000..9309d16bc --- /dev/null +++ b/pkg/machine/machine_unsupported.go @@ -0,0 +1,3 @@ +// +build !amd64 amd64,windows + +package machine diff --git a/pkg/machine/pull.go b/pkg/machine/pull.go index 68bb551dc..662896de5 100644 --- a/pkg/machine/pull.go +++ b/pkg/machine/pull.go @@ -1,3 +1,5 @@ +// +build amd64,linux arm64,linux amd64,darwin arm64,darwin + package machine import ( diff --git a/pkg/machine/qemu/config.go b/pkg/machine/qemu/config.go index e4687914d..013f28960 100644 --- a/pkg/machine/qemu/config.go +++ b/pkg/machine/qemu/config.go @@ -1,3 +1,5 @@ +// +build amd64,linux arm64,linux amd64,darwin arm64,darwin + package qemu import "time" diff --git a/pkg/machine/qemu/machine.go b/pkg/machine/qemu/machine.go index 31c355d4a..22fb78a5c 100644 --- a/pkg/machine/qemu/machine.go +++ b/pkg/machine/qemu/machine.go @@ -1,3 +1,5 @@ +// +build amd64,linux arm64,linux amd64,darwin arm64,darwin + package qemu import ( diff --git a/pkg/machine/qemu/machine_unsupported.go b/pkg/machine/qemu/machine_unsupported.go new file mode 100644 index 000000000..da06ac324 --- /dev/null +++ b/pkg/machine/qemu/machine_unsupported.go @@ -0,0 +1,3 @@ +// +build !amd64 amd64,windows + +package qemu diff --git a/pkg/rootless/rootless_linux.c b/pkg/rootless/rootless_linux.c index 0d1d6e93e..e5f9e88d9 100644 --- a/pkg/rootless/rootless_linux.c +++ b/pkg/rootless/rootless_linux.c @@ -333,7 +333,7 @@ static void __attribute__((constructor)) init() uid_t uid; gid_t gid; char path[PATH_MAX]; - const char *const suffix = "/libpod/pause.pid"; + const char *const suffix = "/libpod/tmp/pause.pid"; char *cwd = getcwd (NULL, 0); char uid_fmt[16]; char gid_fmt[16]; diff --git a/pkg/specgen/generate/container.go b/pkg/specgen/generate/container.go index d00e51e82..e7276892d 100644 --- a/pkg/specgen/generate/container.go +++ b/pkg/specgen/generate/container.go @@ -24,7 +24,8 @@ func CompleteSpec(ctx context.Context, r *libpod.Runtime, s *specgen.SpecGenerat var inspectData *libimage.ImageData var err error if s.Image != "" { - newImage, _, err = r.LibimageRuntime().LookupImage(s.Image, nil) + lookupOptions := &libimage.LookupImageOptions{IgnorePlatform: true} + newImage, _, err = r.LibimageRuntime().LookupImage(s.Image, lookupOptions) if err != nil { return nil, err } diff --git a/pkg/specgen/generate/container_create.go b/pkg/specgen/generate/container_create.go index a0f5cc7e6..087ff59df 100644 --- a/pkg/specgen/generate/container_create.go +++ b/pkg/specgen/generate/container_create.go @@ -92,7 +92,8 @@ func MakeContainer(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGener options = append(options, libpod.WithRootFS(s.Rootfs)) } else { var resolvedImageName string - newImage, resolvedImageName, err = rt.LibimageRuntime().LookupImage(s.Image, nil) + lookupOptions := &libimage.LookupImageOptions{IgnorePlatform: true} + newImage, resolvedImageName, err = rt.LibimageRuntime().LookupImage(s.Image, lookupOptions) if err != nil { return nil, err } diff --git a/test/apiv2/10-images.at b/test/apiv2/10-images.at index 037a4c01f..9e464dbc7 100644 --- a/test/apiv2/10-images.at +++ b/test/apiv2/10-images.at @@ -147,4 +147,39 @@ t GET "images/get?names=alpine&names=busybox" 200 '[POSIX tar archive]' img_cnt=$(tar xf "$WORKDIR/curl.result.out" manifest.json -O | jq "length") is "$img_cnt" 2 "number of images in tar archive" +# check build works when uploading container file as a tar, see issue #10660 +TMPD=$(mktemp -d podman-apiv2-test.build.XXXXXXXX) +function cleanBuildTest() { + podman rmi -a -f + rm -rf "${TMPD}" &> /dev/null +} +CONTAINERFILE_TAR="${TMPD}/containerfile.tar" +cat > $TMPD/containerfile << EOF +FROM quay.io/libpod/alpine_labels:latest +EOF +tar --format=posix -C $TMPD -cvf ${CONTAINERFILE_TAR} containerfile &> /dev/null + +curl -XPOST --data-binary @<(cat $CONTAINERFILE_TAR) \ + -H "content-type: application/x-tar" \ + --dump-header "${TMPD}/headers.txt" \ + -o "${TMPD}/response.txt" \ + "http://$HOST:$PORT/v1.40/libpod/build?dockerfile=containerfile" &> /dev/null + +BUILD_TEST_ERROR="" + +if ! grep -q '200 OK' "${TMPD}/headers.txt"; then + echo -e "${red}NOK: Image build from tar failed response was not 200 OK" + BUILD_TEST_ERROR="1" +fi + +if ! grep -q 'quay.io/libpod/alpine_labels' "${TMPD}/response.txt"; then + echo -e "${red}NOK: Image build from tar failed image name not in response" + BUILD_TEST_ERROR="1" +fi + +cleanBuildTest +if [[ "${BUILD_TEST_ERROR}" ]]; then + exit 1 +fi + # vim: filetype=sh diff --git a/test/apiv2/python/rest_api/test_v2_0_0_image.py b/test/apiv2/python/rest_api/test_v2_0_0_image.py index cea34e2e7..3e8ecb1ef 100644 --- a/test/apiv2/python/rest_api/test_v2_0_0_image.py +++ b/test/apiv2/python/rest_api/test_v2_0_0_image.py @@ -94,7 +94,8 @@ class ImageTestCase(APITestCase): ) self.assertEqual(r.status_code, 200, r.text) r = requests.post( - self.podman_url + "/v1.40/images/create?fromSrc=-&repo=fedora&message=testing123", + self.podman_url + + "/v1.40/images/create?fromSrc=-&repo=fedora&message=testing123&platform=linux/amd64", timeout=15, ) self.assertEqual(r.status_code, 200, r.text) diff --git a/test/compose/test-compose b/test/compose/test-compose index 981f78a79..70db6dd55 100755 --- a/test/compose/test-compose +++ b/test/compose/test-compose @@ -183,6 +183,8 @@ function test_port() { fi echo "# cat $WORKDIR/server.log:" cat $WORKDIR/server.log + echo "# cat $logfile:" + cat $logfile return fi diff --git a/test/e2e/build_test.go b/test/e2e/build_test.go index 6255690b1..abaacdd5e 100644 --- a/test/e2e/build_test.go +++ b/test/e2e/build_test.go @@ -604,4 +604,38 @@ RUN echo hello`, ALPINE) Expect(inspect.OutputToString()).To(Equal("windows")) }) + + It("podman build device test", func() { + if _, err := os.Lstat("/dev/fuse"); err != nil { + Skip(fmt.Sprintf("test requires stat /dev/fuse to work: %v", err)) + } + containerfile := fmt.Sprintf(`FROM %s +RUN ls /dev/fuse`, ALPINE) + containerfilePath := filepath.Join(podmanTest.TempDir, "Containerfile") + err := ioutil.WriteFile(containerfilePath, []byte(containerfile), 0755) + Expect(err).To(BeNil()) + session := podmanTest.Podman([]string{"build", "--pull-never", "-t", "test", "--file", containerfilePath, podmanTest.TempDir}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(125)) + + session = podmanTest.Podman([]string{"build", "--pull-never", "--device", "/dev/fuse", "-t", "test", "--file", containerfilePath, podmanTest.TempDir}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + }) + + It("podman build device rename test", func() { + SkipIfRootless("rootless builds do not currently support renaming devices") + containerfile := fmt.Sprintf(`FROM %s +RUN ls /dev/test1`, ALPINE) + containerfilePath := filepath.Join(podmanTest.TempDir, "Containerfile") + err := ioutil.WriteFile(containerfilePath, []byte(containerfile), 0755) + Expect(err).To(BeNil()) + session := podmanTest.Podman([]string{"build", "--pull-never", "-t", "test", "--file", containerfilePath, podmanTest.TempDir}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(125)) + + session = podmanTest.Podman([]string{"build", "--pull-never", "--device", "/dev/zero:/dev/test1", "-t", "test", "--file", containerfilePath, podmanTest.TempDir}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + }) }) diff --git a/test/e2e/info_test.go b/test/e2e/info_test.go index f5b70d6bf..83d185be1 100644 --- a/test/e2e/info_test.go +++ b/test/e2e/info_test.go @@ -101,11 +101,11 @@ var _ = Describe("Podman Info", func() { u, err := user.Current() Expect(err).To(BeNil()) + // Cannot use podmanTest.Podman() and test for storage path expect := filepath.Join("/tmp", os.Getenv("HOME"), u.Username, u.Uid, "storage") podmanPath := podmanTest.PodmanTest.PodmanBinary - cmd := exec.Command(podmanPath, "info", "--format", "{{.Store.GraphRoot}}") + cmd := exec.Command(podmanPath, "info", "--format", "{{.Store.GraphRoot -}}") out, err := cmd.CombinedOutput() - fmt.Println(string(out)) Expect(err).To(BeNil()) Expect(string(out)).To(Equal(expect)) }) diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go index 58538b689..e71e7a248 100644 --- a/test/e2e/run_test.go +++ b/test/e2e/run_test.go @@ -904,6 +904,18 @@ USER bin`, BB) Expect(session.ExitCode()).To(Equal(100)) }) + It("podman run with named volume", func() { + session := podmanTest.Podman([]string{"run", "--rm", ALPINE, "stat", "-c", "%a %Y", "/var/tmp"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + perms := session.OutputToString() + + session = podmanTest.Podman([]string{"run", "--rm", "-v", "test:/var/tmp", ALPINE, "stat", "-c", "%a %Y", "/var/tmp"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(session.OutputToString()).To(Equal(perms)) + }) + It("podman run with built-in volume image", func() { session := podmanTest.Podman([]string{"run", "--rm", redis, "ls"}) session.WaitWithDefaultTimeout() @@ -921,17 +933,6 @@ USER mail`, BB) Expect(session.OutputToString()).To(ContainSubstring("mail root")) }) - It("podman run with incorect VOLUME", func() { - dockerfile := fmt.Sprintf(`FROM %s -VOLUME ['/etc/foo'] -WORKDIR /etc/foo`, BB) - podmanTest.BuildImage(dockerfile, "test", "false") - session := podmanTest.Podman([]string{"run", "--rm", "test", "echo", "test"}) - session.WaitWithDefaultTimeout() - Expect(session.ExitCode()).To(Equal(0)) - Expect(session.OutputToString()).To(ContainSubstring("test")) - }) - It("podman run --volumes-from flag", func() { vol := filepath.Join(podmanTest.TempDir, "vol-test") err := os.MkdirAll(vol, 0755) diff --git a/test/e2e/run_volume_test.go b/test/e2e/run_volume_test.go index 9b77aaef8..4be1b2009 100644 --- a/test/e2e/run_volume_test.go +++ b/test/e2e/run_volume_test.go @@ -668,4 +668,36 @@ USER testuser`, fedoraMinimal) Expect(strings.Contains(test2.OutputToString(), testString)).To(BeTrue()) }) + + It("podman volume with uid and gid works", func() { + volName := "testVol" + volCreate := podmanTest.Podman([]string{"volume", "create", "--opt", "o=uid=1000", volName}) + volCreate.WaitWithDefaultTimeout() + Expect(volCreate.ExitCode()).To(Equal(0)) + + volMount := podmanTest.Podman([]string{"run", "--rm", "-v", fmt.Sprintf("%s:/test", volName), ALPINE, "stat", "-c", "%u", "/test"}) + volMount.WaitWithDefaultTimeout() + Expect(volMount.ExitCode()).To(Equal(0)) + Expect(volMount.OutputToString()).To(Equal("1000")) + + volName = "testVol2" + volCreate = podmanTest.Podman([]string{"volume", "create", "--opt", "o=gid=1000", volName}) + volCreate.WaitWithDefaultTimeout() + Expect(volCreate.ExitCode()).To(Equal(0)) + + volMount = podmanTest.Podman([]string{"run", "--rm", "-v", fmt.Sprintf("%s:/test", volName), ALPINE, "stat", "-c", "%g", "/test"}) + volMount.WaitWithDefaultTimeout() + Expect(volMount.ExitCode()).To(Equal(0)) + Expect(volMount.OutputToString()).To(Equal("1000")) + + volName = "testVol3" + volCreate = podmanTest.Podman([]string{"volume", "create", "--opt", "o=uid=1000,gid=1000", volName}) + volCreate.WaitWithDefaultTimeout() + Expect(volCreate.ExitCode()).To(Equal(0)) + + volMount = podmanTest.Podman([]string{"run", "--rm", "-v", fmt.Sprintf("%s:/test", volName), ALPINE, "stat", "-c", "%u:%g", "/test"}) + volMount.WaitWithDefaultTimeout() + Expect(volMount.ExitCode()).To(Equal(0)) + Expect(volMount.OutputToString()).To(Equal("1000:1000")) + }) }) diff --git a/test/e2e/stats_test.go b/test/e2e/stats_test.go index 2218d72b5..7ab3dabc9 100644 --- a/test/e2e/stats_test.go +++ b/test/e2e/stats_test.go @@ -83,6 +83,17 @@ var _ = Describe("Podman stats", func() { Expect(session.ExitCode()).To(Equal(0)) }) + It("podman stats only output CPU data", func() { + session := podmanTest.RunTopContainer("") + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + session = podmanTest.Podman([]string{"stats", "--all", "--no-stream", "--format", "\"{{.ID}} {{.UpTime}} {{.AVGCPU}}\""}) + session.WaitWithDefaultTimeout() + Expect(session.LineInOutputContains("UpTime")).To(BeTrue()) + Expect(session.LineInOutputContains("AVGCPU")).To(BeTrue()) + Expect(session.ExitCode()).To(Equal(0)) + }) + It("podman stats with json output", func() { var found bool session := podmanTest.RunTopContainer("") diff --git a/test/e2e/systemd_test.go b/test/e2e/systemd_test.go index b132750b0..8dc14d5f7 100644 --- a/test/e2e/systemd_test.go +++ b/test/e2e/systemd_test.go @@ -6,6 +6,7 @@ import ( "strings" "time" + "github.com/containers/podman/v3/pkg/rootless" . "github.com/containers/podman/v3/test/utils" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -115,6 +116,12 @@ WantedBy=multi-user.target conData := result.InspectContainerToJSON() Expect(len(conData)).To(Equal(1)) Expect(conData[0].Config.SystemdMode).To(BeTrue()) + + if CGROUPSV2 || !rootless.IsRootless() { + stats := podmanTest.Podman([]string{"stats", "--no-stream", ctrName}) + stats.WaitWithDefaultTimeout() + Expect(stats.ExitCode()).To(Equal(0)) + } }) It("podman create container with systemd entrypoint triggers systemd mode", func() { diff --git a/test/system/010-images.bats b/test/system/010-images.bats index 2d7ac1e0c..649987dfd 100644 --- a/test/system/010-images.bats +++ b/test/system/010-images.bats @@ -19,21 +19,22 @@ load helpers @test "podman images - custom formats" { tests=" ---format {{.ID}} | [0-9a-f]\\\{12\\\} ---format {{.ID}} --no-trunc | sha256:[0-9a-f]\\\{64\\\} ---format {{.Repository}}:{{.Tag}} | $PODMAN_TEST_IMAGE_FQN ---format {{.Labels.created_by}} | test/system/build-testimage ---format {{.Labels.created_at}} | 20[0-9-]\\\+T[0-9:]\\\+Z +{{.ID}} | [0-9a-f]\\\{12\\\} +{{.ID| upper}} | [0-9A-F]\\\{12\\\} +{{.Repository}}:{{.Tag}} | $PODMAN_TEST_IMAGE_FQN +{{.Labels.created_by}} | test/system/build-testimage +{{.Labels.created_at}} | 20[0-9-]\\\+T[0-9:]\\\+Z " parse_table "$tests" | while read fmt expect; do - run_podman images $fmt + run_podman images --format "$fmt" is "$output" "$expect\$" "podman images $fmt" done + run_podman images --format "{{.ID}}" --no-trunc + is "$output" "sha256:[0-9a-f]\\{64\\}\$" "podman images --no-trunc" } - @test "podman images - json" { # 'created': podman includes fractional seconds, podman-remote does not tests=" diff --git a/test/system/045-start.bats b/test/system/045-start.bats index 3e0118dba..7e4bbde8d 100644 --- a/test/system/045-start.bats +++ b/test/system/045-start.bats @@ -59,4 +59,15 @@ load helpers is "$output" "Error: fakepolicy invalid restart policy" } +@test "podman start --all --filter" { + run_podman run -d $IMAGE /bin/true + cid_exited_0="$output" + run_podman run -d $IMAGE /bin/false + cid_exited_1="$output" + + run_podman wait $cid_exited_0 $cid_exited_1 + run_podman start --all --filter exited=0 + is "$output" "$cid_exited_0" +} + # vim: filetype=sh diff --git a/test/system/070-build.bats b/test/system/070-build.bats index 0f3f3fa7f..6843e28a5 100644 --- a/test/system/070-build.bats +++ b/test/system/070-build.bats @@ -29,6 +29,29 @@ EOF run_podman rmi -f build_test } +@test "podman build test -f -" { + rand_filename=$(random_string 20) + rand_content=$(random_string 50) + + tmpdir=$PODMAN_TMPDIR/build-test + mkdir -p $tmpdir + containerfile=$PODMAN_TMPDIR/Containerfile + cat >$containerfile <<EOF +FROM $IMAGE +RUN apk add nginx +RUN echo $rand_content > /$rand_filename +EOF + + # The 'apk' command can take a long time to fetch files; bump timeout + PODMAN_TIMEOUT=240 run_podman build -t build_test -f - --format=docker $tmpdir < $containerfile + is "$output" ".*STEP 4: COMMIT" "COMMIT seen in log" + + run_podman run --rm build_test cat /$rand_filename + is "$output" "$rand_content" "reading generated file in image" + + run_podman rmi -f build_test +} + @test "podman build - global runtime flags test" { skip_if_remote "--runtime-flag flag not supported for remote" @@ -794,6 +817,32 @@ EOF run_podman rmi -f build_test } +@test "podman build -f test " { + tmpdir=$PODMAN_TMPDIR/build-test + subdir=$tmpdir/subdir + mkdir -p $subdir + + containerfile1=$tmpdir/Containerfile1 + cat >$containerfile1 <<EOF +FROM scratch +copy . /tmp +EOF + containerfile2=$PODMAN_TMPDIR/Containerfile2 + cat >$containerfile2 <<EOF +FROM $IMAGE +EOF + run_podman build -t build_test -f Containerfile1 $tmpdir + run_podman 125 build -t build_test -f Containerfile2 $tmpdir + is "$output" ".*Containerfile2: no such file or directory" "Containerfile2 should not exist" + run_podman build -t build_test -f $containerfile1 $tmpdir + run_podman build -t build_test -f $containerfile2 $tmpdir + run_podman build -t build_test -f $containerfile1 + run_podman build -t build_test -f $containerfile2 + run_podman build -t build_test -f $containerfile1 -f $containerfile2 $tmpdir + is "$output" ".*$IMAGE" "Containerfile2 is also passed to server" + run_podman rmi -f build_test +} + function teardown() { # A timeout or other error in 'build' can leave behind stale images # that podman can't even see and which will cascade into subsequent diff --git a/test/system/255-auto-update.bats b/test/system/255-auto-update.bats index 9bfb44791..3713243d5 100644 --- a/test/system/255-auto-update.bats +++ b/test/system/255-auto-update.bats @@ -194,7 +194,7 @@ function _confirm_update() { run_podman 125 auto-update update_log=$output is "$update_log" ".*invalid auto-update policy.*" "invalid policy setup" - is "$update_log" ".*1 error occurred.*" "invalid policy setup" + is "$update_log" ".*Error: invalid auto-update policy.*" "invalid policy setup" local n_updated=$(grep -c 'Trying to pull' <<<"$update_log") is "$n_updated" "2" "Number of images updated from registry." diff --git a/test/system/410-selinux.bats b/test/system/410-selinux.bats index f8cee0e59..4ef9c8b30 100644 --- a/test/system/410-selinux.bats +++ b/test/system/410-selinux.bats @@ -183,7 +183,10 @@ function check_label() { # runc and crun emit different diagnostics runtime=$(podman_runtime) case "$runtime" in - crun) expect="\`/proc/thread-self/attr/exec\`: OCI runtime error: unable to assign security attribute" ;; + # crun 0.20.1 changes the error message + # from /proc/thread-self/attr/exec`: .* unable to assign + # to /proc/self/attr/keycreate`: .* unable to process + crun) expect="\`/proc/.*\`: OCI runtime error: unable to \(assign\|process\) security attribute" ;; runc) expect="OCI runtime error: .*: failed to set /proc/self/attr/keycreate on procfs" ;; *) skip "Unknown runtime '$runtime'";; esac diff --git a/test/system/450-interactive.bats b/test/system/450-interactive.bats index a2db39492..47bdff9ab 100644 --- a/test/system/450-interactive.bats +++ b/test/system/450-interactive.bats @@ -57,7 +57,18 @@ function teardown() { # ...and make sure stty under podman reads that. run_podman run -it --name mystty $IMAGE stty size <$PODMAN_TEST_PTY - is "$output" "$rows $cols" "stty under podman reads the correct dimensions" + is "$output" "$rows $cols" "stty under podman run reads the correct dimensions" + + run_podman rm -f mystty + + # FIXME: the checks below are flaking a lot (see #10710). + + # check that the same works for podman exec +# run_podman run -d --name mystty $IMAGE top +# run_podman exec -it mystty stty size <$PODMAN_TEST_PTY +# is "$output" "$rows $cols" "stty under podman exec reads the correct dimensions" +# +# run_podman rm -f mystty } diff --git a/test/system/500-networking.bats b/test/system/500-networking.bats index 55ec80bb2..d55a786f7 100644 --- a/test/system/500-networking.bats +++ b/test/system/500-networking.bats @@ -162,23 +162,25 @@ load helpers done } -@test "podman run with slirp4ns assigns correct gateway address to host.containers.internal" { +@test "podman run with slirp4ns assigns correct addresses to /etc/hosts" { CIDR="$(random_rfc1918_subnet)" - run_podman run --network slirp4netns:cidr="${CIDR}.0/24" \ - $IMAGE grep 'host.containers.internal' /etc/hosts - is "$output" "${CIDR}.2 host.containers.internal" "host.containers.internal should be the cidr+2 address" + local conname=con-$(random_string 10) + run_podman run --rm --network slirp4netns:cidr="${CIDR}.0/24" \ + --name $conname --hostname $conname $IMAGE cat /etc/hosts + is "$output" ".*${CIDR}.2 host.containers.internal" "host.containers.internal should be the cidr+2 address" + is "$output" ".*${CIDR}.100 $conname $conname" "$conname should be the cidr+100 address" } @test "podman run with slirp4ns adds correct dns address to resolv.conf" { CIDR="$(random_rfc1918_subnet)" - run_podman run --network slirp4netns:cidr="${CIDR}.0/24" \ + run_podman run --rm --network slirp4netns:cidr="${CIDR}.0/24" \ $IMAGE grep "${CIDR}" /etc/resolv.conf is "$output" "nameserver ${CIDR}.3" "resolv.conf should have slirp4netns cidr+3 as a nameserver" } @test "podman run with slirp4ns assigns correct ip address container" { CIDR="$(random_rfc1918_subnet)" - run_podman run --network slirp4netns:cidr="${CIDR}.0/24" \ + run_podman run --rm --network slirp4netns:cidr="${CIDR}.0/24" \ $IMAGE sh -c "ip address | grep ${CIDR}" is "$output" ".*inet ${CIDR}.100/24 \+" "container should have slirp4netns cidr+100 assigned to interface" } diff --git a/test/system/build-testimage b/test/system/build-testimage index 3e5b982ce..eb5849b5e 100755 --- a/test/system/build-testimage +++ b/test/system/build-testimage @@ -61,8 +61,8 @@ chmod 755 pause # - check for updates @ https://hub.docker.com/_/alpine # busybox-extras provides httpd needed in 500-networking.bats cat >Containerfile <<EOF -ARG ARCH=please-override-arch -FROM docker.io/\${ARCH}/alpine:3.12.0 +ARG REPO=please-override-repo +FROM docker.io/\${REPO}/alpine:3.13.5 RUN apk add busybox-extras ADD testimage-id pause /home/podman/ LABEL created_by=$create_script @@ -74,17 +74,46 @@ EOF # --squash-all : needed by 'tree' test in 070-build.bats podman rmi -f testimage &> /dev/null || true +# There should always be a testimage tagged ':0000000<X>' (eight digits, +# zero-padded sequence ID) in the same location; this is used by tests +# which need to pull a non-locally-cached image. This image will rarely +# if ever need to change, nor in fact does it even have to be a copy of +# this testimage since all we use it for is 'true'. +# However, it does need to be multiarch :-( +zerotag_latest=$(skopeo list-tags docker://quay.io/libpod/testimage |\ + jq -r '.Tags[]' |\ + sort --version-sort |\ + grep '^000' |\ + tail -n 1) +zerotag_next=$(printf "%08d" $((zerotag_latest + 1))) + +# We don't always need to push the :00xx image, but build it anyway. +zeroimg=quay.io/libpod/testimage:${zerotag_next} +buildah manifest create $zeroimg + # We need to use buildah because (as of 2021-02-23) only buildah has --manifest # and because Dan says arch emulation is not currently working on podman # (no further details). # Arch emulation on Fedora requires the qemu-user-static package. -for arch in amd64 arm64v8 ppc64le s390x;do +for arch in amd64 arm64 ppc64le s390x;do + # docker.io repo is usually the same name as the desired arch; except + # for arm64, where podman needs to have the arch be 'arm64' but the + # image lives in 'arm64v8'. + repo=$arch + if [[ $repo = "arm64" ]]; then + repo="${repo}v8" + fi + ${BUILDAH} bud \ --arch=$arch \ - --build-arg ARCH=$arch \ + --build-arg REPO=$repo \ --manifest=testimage \ --squash \ . + + # The zero-tag image + ${BUILDAH} pull --arch $arch docker.io/$repo/busybox:1.33.1 + ${BUILDAH} manifest add $zeroimg docker.io/$repo/busybox:1.33.1 done # Clean up @@ -94,23 +123,13 @@ rm -rf $tmpdir # Tag image and push (all arches) to quay. remote_tag=quay.io/libpod/testimage:$YMD podman tag testimage ${remote_tag} -${BUILDAH} manifest push --all ${remote_tag} docker://${remote_tag} +cat <<EOF -# Side note: there should always be a testimage tagged ':0000000<X>' -# (eight digits, zero-padded sequence ID) in the same location; this is -# used by tests which need to pull a non-locally-cached image. This -# image will rarely if ever need to change, nor in fact does it even -# have to be a copy of this testimage since all we use it for is 'true'. -# However, it does need to be multiarch :-( -# -# As of 2021-02-24 it is simply busybox, because it is super small, -# but it's complicated because of multiarch: -# -# img=quay.io/libpod/testimage:0000000<current+1> -# buildah manifest create $img -# for arch in amd64 arm64v8 ppc64le s390x;do -# buildah pull --arch $arch docker.io/$arch/busybox:1.32.0 -# buildah manifest add $img docker.io/$arch/busybox:1.32.0 -# done -# buildah manifest push --all $img docker://$img -# +If you're happy with these images, run: + + ${BUILDAH} manifest push --all ${remote_tag} docker://${remote_tag} + ${BUILDAH} manifest push --all ${zeroimg} docker://${zeroimg} + +(You do not always need to push the :0000 image) + +EOF diff --git a/test/system/helpers.bash b/test/system/helpers.bash index e0c208f57..1859a2168 100644 --- a/test/system/helpers.bash +++ b/test/system/helpers.bash @@ -7,14 +7,15 @@ PODMAN=${PODMAN:-podman} PODMAN_TEST_IMAGE_REGISTRY=${PODMAN_TEST_IMAGE_REGISTRY:-"quay.io"} PODMAN_TEST_IMAGE_USER=${PODMAN_TEST_IMAGE_USER:-"libpod"} PODMAN_TEST_IMAGE_NAME=${PODMAN_TEST_IMAGE_NAME:-"testimage"} -PODMAN_TEST_IMAGE_TAG=${PODMAN_TEST_IMAGE_TAG:-"20210427"} +PODMAN_TEST_IMAGE_TAG=${PODMAN_TEST_IMAGE_TAG:-"20210610"} PODMAN_TEST_IMAGE_FQN="$PODMAN_TEST_IMAGE_REGISTRY/$PODMAN_TEST_IMAGE_USER/$PODMAN_TEST_IMAGE_NAME:$PODMAN_TEST_IMAGE_TAG" PODMAN_TEST_IMAGE_ID= # Remote image that we *DO NOT* fetch or keep by default; used for testing pull -# This changed from 0 to 1 on 2021-02-24 due to multiarch considerations; it -# should change only very rarely. -PODMAN_NONLOCAL_IMAGE_FQN="$PODMAN_TEST_IMAGE_REGISTRY/$PODMAN_TEST_IMAGE_USER/$PODMAN_TEST_IMAGE_NAME:00000002" +# This has changed in 2021, from 0 through 3, various iterations of getting +# multiarch to work. It should change only very rarely. +PODMAN_NONLOCAL_IMAGE_TAG=${PODMAN_NONLOCAL_IMAGE_TAG:-"00000003"} +PODMAN_NONLOCAL_IMAGE_FQN="$PODMAN_TEST_IMAGE_REGISTRY/$PODMAN_TEST_IMAGE_USER/$PODMAN_TEST_IMAGE_NAME:$PODMAN_NONLOCAL_IMAGE_TAG" # Because who wants to spell that out each time? IMAGE=$PODMAN_TEST_IMAGE_FQN diff --git a/utils/utils_supported.go b/utils/utils_supported.go index ad6192255..8668e3fba 100644 --- a/utils/utils_supported.go +++ b/utils/utils_supported.go @@ -172,7 +172,7 @@ func moveUnderCgroup(cgroup, subtree string, processes []uint32) error { if len(processes) > 0 { for _, pid := range processes { if _, err := f.Write([]byte(fmt.Sprintf("%d\n", pid))); err != nil { - logrus.Warnf("Cannot move process %d to cgroup %q", pid, newCgroup) + logrus.Debugf("Cannot move process %d to cgroup %q: %v", pid, newCgroup, err) } } } else { @@ -185,7 +185,7 @@ func moveUnderCgroup(cgroup, subtree string, processes []uint32) error { continue } if _, err := f.Write(pid); err != nil { - logrus.Warnf("Cannot move process %s to cgroup %q", string(pid), newCgroup) + logrus.Debugf("Cannot move process %s to cgroup %q: %v", string(pid), newCgroup, err) } } } diff --git a/vendor/github.com/containers/common/libimage/download.go b/vendor/github.com/containers/common/libimage/download.go index 5ea11f084..54edf1b9a 100644 --- a/vendor/github.com/containers/common/libimage/download.go +++ b/vendor/github.com/containers/common/libimage/download.go @@ -11,7 +11,7 @@ import ( ) // tmpdir returns a path to a temporary directory. -func (r *Runtime) tmpdir() string { +func tmpdir() string { tmpdir := os.Getenv("TMPDIR") if tmpdir == "" { tmpdir = "/var/tmp" @@ -25,7 +25,7 @@ func (r *Runtime) tmpdir() string { func (r *Runtime) downloadFromURL(source string) (string, error) { fmt.Printf("Downloading from %q\n", source) - outFile, err := ioutil.TempFile(r.tmpdir(), "import") + outFile, err := ioutil.TempFile(r.systemContext.BigFilesTemporaryDir, "import") if err != nil { return "", errors.Wrap(err, "error creating file") } diff --git a/vendor/github.com/containers/common/libimage/image.go b/vendor/github.com/containers/common/libimage/image.go index de0b4b2c5..f1272f507 100644 --- a/vendor/github.com/containers/common/libimage/image.go +++ b/vendor/github.com/containers/common/libimage/image.go @@ -61,6 +61,24 @@ func (i *Image) reload() error { return nil } +// isCorrupted returns an error if the image may be corrupted. +func (i *Image) isCorrupted(name string) error { + // If it's a manifest list, we're good for now. + if _, err := i.getManifestList(); err == nil { + return nil + } + + ref, err := i.StorageReference() + if err != nil { + return err + } + + if _, err := ref.NewImage(context.Background(), nil); err != nil { + return errors.Errorf("Image %s exists in local storage but may be corrupted: %v", name, err) + } + return nil +} + // Names returns associated names with the image which may be a mix of tags and // digests. func (i *Image) Names() []string { @@ -329,17 +347,19 @@ func (i *Image) remove(ctx context.Context, rmMap map[string]*RemoveImageReport, // an `rmi foo` will not untag "foo" but instead attempt to remove the // entire image. If there's a container using "foo", we should get an // error. - if options.Force || referencedBy == "" || numNames == 1 { + if referencedBy == "" || numNames == 1 { // DO NOTHING, the image will be removed } else { byID := strings.HasPrefix(i.ID(), referencedBy) byDigest := strings.HasPrefix(referencedBy, "sha256:") - if byID && numNames > 1 { - return errors.Errorf("unable to delete image %q by ID with more than one tag (%s): please force removal", i.ID(), i.Names()) - } else if byDigest && numNames > 1 { - // FIXME - Docker will remove the digest but containers storage - // does not support that yet, so our hands are tied. - return errors.Errorf("unable to delete image %q by digest with more than one tag (%s): please force removal", i.ID(), i.Names()) + if !options.Force { + if byID && numNames > 1 { + return errors.Errorf("unable to delete image %q by ID with more than one tag (%s): please force removal", i.ID(), i.Names()) + } else if byDigest && numNames > 1 { + // FIXME - Docker will remove the digest but containers storage + // does not support that yet, so our hands are tied. + return errors.Errorf("unable to delete image %q by digest with more than one tag (%s): please force removal", i.ID(), i.Names()) + } } // Only try to untag if we know it's not an ID or digest. diff --git a/vendor/github.com/containers/common/libimage/import.go b/vendor/github.com/containers/common/libimage/import.go index 4cce4c9ca..2addfdf98 100644 --- a/vendor/github.com/containers/common/libimage/import.go +++ b/vendor/github.com/containers/common/libimage/import.go @@ -23,6 +23,10 @@ type ImportOptions struct { CommitMessage string // Tag the imported image with this value. Tag string + // Overwrite OS of imported image. + OS string + // Overwrite Arch of imported image. + Arch string } // Import imports a custom tarball at the specified path. Returns the name of @@ -48,8 +52,10 @@ func (r *Runtime) Import(ctx context.Context, path string, options *ImportOption } config := v1.Image{ - Config: ic, - History: hist, + Config: ic, + History: hist, + OS: options.OS, + Architecture: options.Arch, } u, err := url.ParseRequestURI(path) diff --git a/vendor/github.com/containers/common/libimage/pull.go b/vendor/github.com/containers/common/libimage/pull.go index acf5c818f..0a5e49fd2 100644 --- a/vendor/github.com/containers/common/libimage/pull.go +++ b/vendor/github.com/containers/common/libimage/pull.go @@ -105,6 +105,20 @@ func (r *Runtime) Pull(ctx context.Context, name string, pullPolicy config.PullP r.writeEvent(&Event{ID: "", Name: name, Time: time.Now(), Type: EventTypeImagePull}) } + // Some callers may set the platform via the system context at creation + // time of the runtime. We need this information to decide whether we + // need to enforce pulling from a registry (see + // containers/podman/issues/10682). + if options.Architecture == "" { + options.Architecture = r.systemContext.ArchitectureChoice + } + if options.OS == "" { + options.OS = r.systemContext.OSChoice + } + if options.Variant == "" { + options.Variant = r.systemContext.VariantChoice + } + var ( pulledImages []string pullError error @@ -333,7 +347,7 @@ func (r *Runtime) copyFromRegistry(ctx context.Context, ref types.ImageReference // from a registry. On successful pull it returns the used fully-qualified // name that can later be used to look up the image in the local containers // storage. -func (r *Runtime) copySingleImageFromRegistry(ctx context.Context, imageName string, pullPolicy config.PullPolicy, options *PullOptions) ([]string, error) { +func (r *Runtime) copySingleImageFromRegistry(ctx context.Context, imageName string, pullPolicy config.PullPolicy, options *PullOptions) ([]string, error) { //nolint:gocyclo // Sanity check. if err := pullPolicy.Validate(); err != nil { return nil, err @@ -349,9 +363,39 @@ func (r *Runtime) copySingleImageFromRegistry(ctx context.Context, imageName str // resolved name for pulling. Assume we're doing a `pull foo`. // If there's already a local image "localhost/foo", then we should // attempt pulling that instead of doing the full short-name dance. - localImage, resolvedImageName, err = r.LookupImage(imageName, nil) + lookupOptions := &LookupImageOptions{ + // NOTE: we must ignore the platform of a local image when + // doing lookups. Some images set an incorrect or even invalid + // platform (see containers/podman/issues/10682). Doing the + // lookup while ignoring the platform checks prevents + // redundantly downloading the same image. + IgnorePlatform: true, + } + localImage, resolvedImageName, err = r.LookupImage(imageName, lookupOptions) if err != nil && errors.Cause(err) != storage.ErrImageUnknown { - return nil, errors.Wrap(err, "error looking up local image") + logrus.Errorf("Looking up %s in local storage: %v", imageName, err) + } + + // If the local image is corrupted, we need to repull it. + if localImage != nil { + if err := localImage.isCorrupted(imageName); err != nil { + logrus.Error(err) + localImage = nil + } + } + + // Unless the pull policy is "always", we must pessimistically assume + // that the local image has an invalid architecture (see + // containers/podman/issues/10682). Hence, whenever the user requests + // a custom platform, set the pull policy to "always" to make sure + // we're pulling down the image. + // + // NOTE that this is will even override --pull={false,never}. This is + // very likely a bug but a consistent one in Podman/Buildah and should + // be addressed at a later point. + if pullPolicy != config.PullPolicyAlways && len(options.Architecture)+len(options.OS)+len(options.Variant) > 0 { + logrus.Debugf("Enforcing pull policy to %q to support custom platform (arch: %q, os: %q, variant: %q)", "always", options.Architecture, options.OS, options.Variant) + pullPolicy = config.PullPolicyAlways } if pullPolicy == config.PullPolicyNever { diff --git a/vendor/github.com/containers/common/libimage/runtime.go b/vendor/github.com/containers/common/libimage/runtime.go index bbf1c2a61..3cbd3dcf4 100644 --- a/vendor/github.com/containers/common/libimage/runtime.go +++ b/vendor/github.com/containers/common/libimage/runtime.go @@ -84,6 +84,9 @@ func RuntimeFromStore(store storage.Store, options *RuntimeOptions) (*Runtime, e } else { systemContext = types.SystemContext{} } + if systemContext.BigFilesTemporaryDir == "" { + systemContext.BigFilesTemporaryDir = tmpdir() + } setRegistriesConfPath(&systemContext) @@ -132,13 +135,20 @@ func (r *Runtime) storageToImage(storageImage *storage.Image, ref types.ImageRef } // Exists returns true if the specicifed image exists in the local containers -// storage. +// storage. Note that it may return false if an image corrupted. func (r *Runtime) Exists(name string) (bool, error) { image, _, err := r.LookupImage(name, &LookupImageOptions{IgnorePlatform: true}) if err != nil && errors.Cause(err) != storage.ErrImageUnknown { return false, err } - return image != nil, nil + if image == nil { + return false, nil + } + if err := image.isCorrupted(name); err != nil { + logrus.Error(err) + return false, nil + } + return true, nil } // LookupImageOptions allow for customizing local image lookups. @@ -148,6 +158,13 @@ type LookupImageOptions struct { // the platform does not matter, for instance, for image removal. IgnorePlatform bool + // Lookup an image matching the specified architecture. + Architecture string + // Lookup an image matching the specified OS. + OS string + // Lookup an image matching the specified variant. + Variant string + // If set, do not look for items/instances in the manifest list that // match the current platform but return the manifest list as is. lookupManifest bool @@ -199,6 +216,25 @@ func (r *Runtime) LookupImage(name string, options *LookupImageOptions) (*Image, name = strings.TrimPrefix(name, "sha256:") } + // Set the platform for matching local images. + if !options.IgnorePlatform { + if options.Architecture == "" { + options.Architecture = r.systemContext.ArchitectureChoice + } + if options.Architecture == "" { + options.Architecture = runtime.GOARCH + } + if options.OS == "" { + options.OS = r.systemContext.OSChoice + } + if options.OS == "" { + options.OS = runtime.GOOS + } + if options.Variant == "" { + options.Variant = r.systemContext.VariantChoice + } + } + // First, check if we have an exact match in the storage. Maybe an ID // or a fully-qualified image name. img, err := r.lookupImageInLocalStorage(name, name, options) @@ -284,7 +320,7 @@ func (r *Runtime) lookupImageInLocalStorage(name, candidate string, options *Loo if err != nil { return nil, err } - instance, err := manifestList.LookupInstance(context.Background(), "", "", "") + instance, err := manifestList.LookupInstance(context.Background(), options.Architecture, options.OS, options.Variant) if err != nil { // NOTE: If we are not looking for a specific platform // and already found the manifest list, then return it @@ -305,7 +341,7 @@ func (r *Runtime) lookupImageInLocalStorage(name, candidate string, options *Loo return image, nil } - matches, err := imageReferenceMatchesContext(context.Background(), ref, &r.systemContext) + matches, err := r.imageReferenceMatchesContext(ref, options) if err != nil { return nil, err } @@ -417,12 +453,13 @@ func (r *Runtime) ResolveName(name string) (string, error) { } // imageReferenceMatchesContext return true if the specified reference matches -// the platform (os, arch, variant) as specified by the system context. -func imageReferenceMatchesContext(ctx context.Context, ref types.ImageReference, sys *types.SystemContext) (bool, error) { - if sys == nil { +// the platform (os, arch, variant) as specified by the lookup options. +func (r *Runtime) imageReferenceMatchesContext(ref types.ImageReference, options *LookupImageOptions) (bool, error) { + if options.IgnorePlatform { return true, nil } - img, err := ref.NewImage(ctx, sys) + ctx := context.Background() + img, err := ref.NewImage(ctx, &r.systemContext) if err != nil { return false, err } @@ -431,16 +468,8 @@ func imageReferenceMatchesContext(ctx context.Context, ref types.ImageReference, if err != nil { return false, err } - osChoice := sys.OSChoice - if osChoice == "" { - osChoice = runtime.GOOS - } - arch := sys.ArchitectureChoice - if arch == "" { - arch = runtime.GOARCH - } - if osChoice == data.Os && arch == data.Architecture { - if sys.VariantChoice == "" || sys.VariantChoice == data.Variant { + if options.OS == data.Os && options.Architecture == data.Architecture { + if options.Variant == "" || options.Variant == data.Variant { return true, nil } } diff --git a/vendor/github.com/containers/common/pkg/auth/auth.go b/vendor/github.com/containers/common/pkg/auth/auth.go index a9ad60f43..d2e75c1f7 100644 --- a/vendor/github.com/containers/common/pkg/auth/auth.go +++ b/vendor/github.com/containers/common/pkg/auth/auth.go @@ -134,9 +134,13 @@ func Login(ctx context.Context, systemContext *types.SystemContext, opts *LoginO if err = docker.CheckAuth(ctx, systemContext, username, password, server); err == nil { // Write the new credentials to the authfile - if err := config.SetAuthentication(systemContext, server, username, password); err != nil { + desc, err := config.SetCredentials(systemContext, server, username, password) + if err != nil { return err } + if opts.Verbose { + fmt.Fprintln(opts.Stdout, "Used: ", desc) + } } if err == nil { fmt.Fprintln(opts.Stdout, "Login Succeeded!") diff --git a/vendor/github.com/containers/common/pkg/auth/cli.go b/vendor/github.com/containers/common/pkg/auth/cli.go index 1d8eed4ac..5a7c1137c 100644 --- a/vendor/github.com/containers/common/pkg/auth/cli.go +++ b/vendor/github.com/containers/common/pkg/auth/cli.go @@ -20,6 +20,7 @@ type LoginOptions struct { Username string StdinPassword bool GetLoginSet bool + Verbose bool // set to true for verbose output // Options caller can set Stdin io.Reader // set to os.Stdin Stdout io.Writer // set to os.Stdout @@ -47,6 +48,7 @@ func GetLoginFlags(flags *LoginOptions) *pflag.FlagSet { fs.StringVarP(&flags.Username, "username", "u", "", "Username for registry") fs.BoolVar(&flags.StdinPassword, "password-stdin", false, "Take the password from stdin") fs.BoolVar(&flags.GetLoginSet, "get-login", false, "Return the current login user for the registry") + fs.BoolVarP(&flags.Verbose, "verbose", "v", false, "Write more detailed information to stdout") return &fs } diff --git a/vendor/github.com/containers/common/pkg/config/config.go b/vendor/github.com/containers/common/pkg/config/config.go index edd52f49d..af6efbbf2 100644 --- a/vendor/github.com/containers/common/pkg/config/config.go +++ b/vendor/github.com/containers/common/pkg/config/config.go @@ -5,6 +5,7 @@ import ( "os" "os/exec" "path/filepath" + "sort" "strings" "sync" @@ -23,7 +24,7 @@ const ( _configPath = "containers/containers.conf" // DefaultContainersConfig holds the default containers config path DefaultContainersConfig = "/usr/share/" + _configPath - // OverrideContainersConfig holds the default config paths overridden by the root user + // OverrideContainersConfig holds the default config path overridden by the root user OverrideContainersConfig = "/etc/" + _configPath // UserOverrideContainersConfig holds the containers config path overridden by the rootless user UserOverrideContainersConfig = ".config/" + _configPath @@ -55,6 +56,8 @@ type Config struct { Engine EngineConfig `toml:"engine"` // Network section defines the configuration of CNI Plugins Network NetworkConfig `toml:"network"` + // Secret section defines configurations for the secret management + Secrets SecretConfig `toml:"secrets"` } // ContainersConfig represents the "containers" TOML config table @@ -137,6 +140,11 @@ type ContainersConfig struct { // Negative values indicate that the log file won't be truncated. LogSizeMax int64 `toml:"log_size_max,omitempty"` + // Specifies default format tag for container log messages. + // This is useful for creating a specific tag for container log messages. + // Containers logs default to truncated container ID as a tag. + LogTag string `toml:"log_tag,omitempty"` + // NetNS indicates how to create a network namespace for the container NetNS string `toml:"netns,omitempty"` @@ -440,6 +448,17 @@ type NetworkConfig struct { NetworkConfigDir string `toml:"network_config_dir,omitempty"` } +// SecretConfig represents the "secret" TOML config table +type SecretConfig struct { + // Driver specifies the secret driver to use. + // Current valid value: + // * file + // * pass + Driver string `toml:"driver,omitempty"` + // Opts contains driver specific options + Opts map[string]string `toml:"opts,omitempty"` +} + // Destination represents destination for remote service type Destination struct { // URI, required. Example: ssh://root@example.com:22/run/podman/podman.sock @@ -513,10 +532,49 @@ func readConfigFromFile(path string, config *Config) error { return nil } +// addConfigs will search one level in the config dirPath for config files +// If the dirPath does not exist, addConfigs will return nil +func addConfigs(dirPath string, configs []string) ([]string, error) { + newConfigs := []string{} + + err := filepath.Walk(dirPath, + // WalkFunc to read additional configs + func(path string, info os.FileInfo, err error) error { + switch { + case err != nil: + // return error (could be a permission problem) + return err + case info == nil: + // this should only happen when err != nil but let's be sure + return nil + case info.IsDir(): + if path != dirPath { + // make sure to not recurse into sub-directories + return filepath.SkipDir + } + // ignore directories + return nil + default: + // only add *.conf files + if strings.HasSuffix(path, ".conf") { + newConfigs = append(newConfigs, path) + } + return nil + } + }, + ) + if os.IsNotExist(err) { + err = nil + } + sort.Strings(newConfigs) + return append(configs, newConfigs...), err +} + // Returns the list of configuration files, if they exist in order of hierarchy. // The files are read in order and each new file can/will override previous // file settings. func systemConfigs() ([]string, error) { + var err error configs := []string{} path := os.Getenv("CONTAINERS_CONF") if path != "" { @@ -531,7 +589,12 @@ func systemConfigs() ([]string, error) { if _, err := os.Stat(OverrideContainersConfig); err == nil { configs = append(configs, OverrideContainersConfig) } - path, err := ifRootlessConfigPath() + configs, err = addConfigs(OverrideContainersConfig+".d", configs) + if err != nil { + return nil, err + } + + path, err = ifRootlessConfigPath() if err != nil { return nil, err } @@ -539,6 +602,10 @@ func systemConfigs() ([]string, error) { if _, err := os.Stat(path); err == nil { configs = append(configs, path) } + configs, err = addConfigs(path+".d", configs) + if err != nil { + return nil, err + } } return configs, nil } @@ -986,7 +1053,7 @@ func (c *Config) Write() error { if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil { return err } - configFile, err := os.OpenFile(path, os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0600) + configFile, err := os.OpenFile(path, os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0644) if err != nil { return err } diff --git a/vendor/github.com/containers/common/pkg/config/containers.conf b/vendor/github.com/containers/common/pkg/config/containers.conf index d9b379eae..0c8c7532e 100644 --- a/vendor/github.com/containers/common/pkg/config/containers.conf +++ b/vendor/github.com/containers/common/pkg/config/containers.conf @@ -16,30 +16,16 @@ [containers] -# List of devices. Specified as -# "<device-on-host>:<device-on-container>:<permissions>", for example: -# "/dev/sdc:/dev/xvdc:rwm". -# If it is empty or commented out, only the default devices will be used -# -# devices = [] - -# List of volumes. Specified as -# "<directory-on-host>:<directory-in-container>:<options>", for example: -# "/db:/var/lib/db:ro". -# If it is empty or commented out, no volumes will be added +# List of annotation. Specified as +# "key = value" +# If it is empty or commented out, no annotations will be added # -# volumes = [] +# annotations = [] # Used to change the name of the default AppArmor profile of container engine. # # apparmor_profile = "container-default" -# List of annotation. Specified as -# "key=value" -# If it is empty or commented out, no annotations will be added -# -# annotations = [] - # Default way to to create a cgroup namespace for the container # Options are: # `private` Create private Cgroup Namespace for the container. @@ -93,6 +79,13 @@ default_sysctls = [ # "nofile=1280:2560", # ] +# List of devices. Specified as +# "<device-on-host>:<device-on-container>:<permissions>", for example: +# "/dev/sdc:/dev/xvdc:rwm". +# If it is empty or commented out, only the default devices will be used +# +# devices = [] + # List of default DNS options to be added to /etc/resolv.conf inside of the container. # # dns_options = [] @@ -166,6 +159,12 @@ default_sysctls = [ # # log_size_max = -1 +# Specifies default format tag for container log messages. +# This is useful for creating a specific tag for container log messages. +# Containers logs default to truncated container ID as a tag. +# +# log_tag = "" + # Default way to to create a Network namespace for the container # Options are: # `private` Create private Network Namespace for the container. @@ -179,10 +178,6 @@ default_sysctls = [ # # no_hosts = false -# Maximum number of processes allowed in a container. -# -# pids_limit = 2048 - # Default way to to create a PID namespace for the container # Options are: # `private` Create private PID Namespace for the container. @@ -190,6 +185,13 @@ default_sysctls = [ # # pidns = "private" +# Maximum number of processes allowed in a container. +# +# pids_limit = 2048 + +# Indicates the networking to be used for rootless containers +# rootless_networking = "slirp4netns" + # Path to the seccomp.json profile which is used as the default seccomp profile # for the runtime. # @@ -209,14 +211,7 @@ default_sysctls = [ # Set umask inside the container # -# umask="0022" - -# Default way to to create a UTS namespace for the container -# Options are: -# `private` Create private UTS Namespace for the container. -# `host` Share host UTS Namespace with the container. -# -# utsns = "private" +# umask = "0022" # Default way to to create a User namespace for the container # Options are: @@ -229,7 +224,21 @@ default_sysctls = [ # UIDs are allocated from the "container" UIDs listed in # /etc/subuid & /etc/subgid # -# userns_size=65536 +# userns_size = 65536 + +# Default way to to create a UTS namespace for the container +# Options are: +# `private` Create private UTS Namespace for the container. +# `host` Share host UTS Namespace with the container. +# +# utsns = "private" + +# List of volumes. Specified as +# "<directory-on-host>:<directory-in-container>:<options>", for example: +# "/db:/var/lib/db:ro". +# If it is empty or commented out, no volumes will be added +# +# volumes = [] # The network table contains settings pertaining to the management of # CNI plugins. @@ -254,14 +263,8 @@ default_sysctls = [ # network_config_dir = "/etc/cni/net.d/" [engine] -# Maximum number of image layers to be copied (pulled/pushed) simultaneously. -# Not setting this field, or setting it to zero, will fall back to containers/image defaults. -# image_parallel_copies=0 - -# Manifest Type (oci, v2s2, or v2s1) to use when pulling, pushing, building -# container images. By default image pulled and pushed match the format of the -# source image. Building/committing defaults to OCI. -# image_default_format = "" +# Index to the active service +# active_service = production # Cgroup management implementation used for the runtime. # Valid options "systemd" or "cgroupfs" @@ -319,10 +322,19 @@ default_sysctls = [ # "/usr/share/containers/oci/hooks.d", # ] +# Manifest Type (oci, v2s2, or v2s1) to use when pulling, pushing, building +# container images. By default image pulled and pushed match the format of the +# source image. Building/committing defaults to OCI. +# image_default_format = "" + # Default transport method for pulling and pushing for images # # image_default_transport = "docker://" +# Maximum number of image layers to be copied (pulled/pushed) simultaneously. +# Not setting this field, or setting it to zero, will fall back to containers/image defaults. +# image_parallel_copies = 0 + # Default command to run the infra container # # infra_command = "/pause" @@ -345,7 +357,7 @@ default_sysctls = [ # Indicates if Podman is running inside a VM via Podman Machine. # Podman uses this value to do extra setup around networking from the # container inside the VM to to host. -# machine_enabled=false +# machine_enabled = false # MultiImageArchive - if true, the container engine allows for storing archives # (e.g., of the docker-archive transport) with multiple images. By default, @@ -364,12 +376,12 @@ default_sysctls = [ # Path to the slirp4netns binary # -# network_cmd_path="" +# network_cmd_path = "" # Default options to pass to the slirp4netns binary. # For example "allow_host_loopback=true" # -# network_cmd_options=[] +# network_cmd_options = [] # Whether to use chroot instead of pivot_root in the runtime # @@ -389,27 +401,6 @@ default_sysctls = [ # `podman --remote=true` for access to the remote Podman service. # remote = false -# Indicates the networking to be used for rootless containers -# rootless_networking="slirp4netns" - -# Directory for persistent engine files (database, etc) -# By default, this will be configured relative to where the containers/storage -# stores containers -# Uncomment to change location from this default -# -# static_dir = "/var/lib/containers/storage/libpod" - -# Directory for temporary files. Must be tmpfs (wiped after reboot) -# -# tmp_dir = "/run/libpod" - -# Directory for libpod named volumes. -# By default, this will be configured relative to where containers/storage -# stores containers. -# Uncomment to change location from this default. -# -# volume_path = "/var/lib/containers/storage/volumes" - # Default OCI runtime # # runtime = "crun" @@ -419,20 +410,24 @@ default_sysctls = [ # # runtime_supports_json = ["crun", "runc", "kata", "runsc"] +# List of the OCI runtimes that supports running containers with KVM Separation. +# +# runtime_supports_kvm = ["kata"] + # List of the OCI runtimes that supports running containers without cgroups. # # runtime_supports_nocgroups = ["crun"] -# List of the OCI runtimes that supports running containers with KVM Separation. +# Directory for persistent engine files (database, etc) +# By default, this will be configured relative to where the containers/storage +# stores containers +# Uncomment to change location from this default # -# runtime_supports_kvm = ["kata"] +# static_dir = "/var/lib/containers/storage/libpod" # Number of seconds to wait for container to exit before sending kill signal. # stop_timeout = 10 -# Index to the active service -# active_service = production - # map of service destinations # [service_destinations] # [service_destinations.production] @@ -442,10 +437,21 @@ default_sysctls = [ # rootfull "unix://run/podman/podman.sock (Default) # remote rootless ssh://engineering.lab.company.com/run/user/1000/podman/podman.sock # remote rootfull ssh://root@10.10.1.136:22/run/podman/podman.sock -# uri="ssh://user@production.example.com/run/user/1001/podman/podman.sock" +# uri = "ssh://user@production.example.com/run/user/1001/podman/podman.sock" # Path to file containing ssh identity key # identity = "~/.ssh/id_rsa" +# Directory for temporary files. Must be tmpfs (wiped after reboot) +# +# tmp_dir = "/run/libpod" + +# Directory for libpod named volumes. +# By default, this will be configured relative to where containers/storage +# stores containers. +# Uncomment to change location from this default. +# +# volume_path = "/var/lib/containers/storage/volumes" + # Paths to look for a valid OCI runtime (crun, runc, kata, runsc, etc) [engine.runtimes] # crun = [ @@ -458,16 +464,6 @@ default_sysctls = [ # "/run/current-system/sw/bin/crun", # ] -# runc = [ -# "/usr/bin/runc", -# "/usr/sbin/runc", -# "/usr/local/bin/runc", -# "/usr/local/sbin/runc", -# "/sbin/runc", -# "/bin/runc", -# "/usr/lib/cri-o-runc/sbin/runc", -# ] - # kata = [ # "/usr/bin/kata-runtime", # "/usr/sbin/kata-runtime", @@ -479,6 +475,16 @@ default_sysctls = [ # "/usr/bin/kata-fc", # ] +# runc = [ +# "/usr/bin/runc", +# "/usr/sbin/runc", +# "/usr/local/bin/runc", +# "/usr/local/sbin/runc", +# "/sbin/runc", +# "/bin/runc", +# "/usr/lib/cri-o-runc/sbin/runc", +# ] + # runsc = [ # "/usr/bin/runsc", # "/usr/sbin/runsc", @@ -497,3 +503,9 @@ default_sysctls = [ # TOML does not provide a way to end a table other than a further table being # defined, so every key hereafter will be part of [volume_plugins] and not the # main config. + +[secret] +# driver = "file" + +[secret.opts] +# root = "/example/directory" diff --git a/vendor/github.com/containers/common/pkg/config/default.go b/vendor/github.com/containers/common/pkg/config/default.go index d5a7d5b84..5abb6326f 100644 --- a/vendor/github.com/containers/common/pkg/config/default.go +++ b/vendor/github.com/containers/common/pkg/config/default.go @@ -144,8 +144,6 @@ func DefaultConfig() (*Config, error) { return nil, err } - netns := "bridge" - cniConfig := _cniConfigDir defaultEngineConfig.SignaturePolicyPath = DefaultSignaturePolicyPath @@ -161,7 +159,6 @@ func DefaultConfig() (*Config, error) { defaultEngineConfig.SignaturePolicyPath = DefaultSignaturePolicyPath } } - netns = "slirp4netns" cniConfig = filepath.Join(configHome, _cniConfigDirRootless) } @@ -197,12 +194,10 @@ func DefaultConfig() (*Config, error) { IPCNS: "private", LogDriver: defaultLogDriver(), LogSizeMax: DefaultLogSizeMax, - NetNS: netns, NoHosts: false, PidsLimit: DefaultPidsLimit, PidNS: "private", RootlessNetworking: DefaultRootlessNetwork, - SeccompProfile: SeccompDefaultPath, ShmSize: DefaultShmSize, TZ: "", Umask: "0022", @@ -216,10 +211,19 @@ func DefaultConfig() (*Config, error) { NetworkConfigDir: cniConfig, CNIPluginDirs: cniBinDir, }, - Engine: *defaultEngineConfig, + Engine: *defaultEngineConfig, + Secrets: defaultSecretConfig(), }, nil } +// defaultSecretConfig returns the default secret configuration. +// Please note that the default is choosing the "file" driver. +func defaultSecretConfig() SecretConfig { + return SecretConfig{ + Driver: "file", + } +} + // defaultConfigFromMemory returns a default engine configuration. Note that the // config is different for root and rootless. It also parses the storage.conf. func defaultConfigFromMemory() (*EngineConfig, error) { diff --git a/vendor/github.com/containers/common/pkg/report/template.go b/vendor/github.com/containers/common/pkg/report/template.go index f7b4506bb..f86b07034 100644 --- a/vendor/github.com/containers/common/pkg/report/template.go +++ b/vendor/github.com/containers/common/pkg/report/template.go @@ -130,7 +130,7 @@ func NewTemplate(name string) *Template { func (t *Template) Parse(text string) (*Template, error) { if strings.HasPrefix(text, "table ") { t.isTable = true - text = "{{range .}}" + NormalizeFormat(text) + "{{end}}" + text = "{{range .}}" + NormalizeFormat(text) + "{{end -}}" } else { text = NormalizeFormat(text) } @@ -157,12 +157,12 @@ func (t *Template) IsTable() bool { return t.isTable } -var rangeRegex = regexp.MustCompile(`{{\s*range\s*\.\s*}}.*{{\s*end\s*}}`) +var rangeRegex = regexp.MustCompile(`{{\s*range\s*\.\s*}}.*{{\s*end\s*-?\s*}}`) // EnforceRange ensures that the format string contains a range func EnforceRange(format string) string { if !rangeRegex.MatchString(format) { - return "{{range .}}" + format + "{{end}}" + return "{{range .}}" + format + "{{end -}}" } return format } diff --git a/vendor/github.com/containers/common/pkg/seccomp/conversion.go b/vendor/github.com/containers/common/pkg/seccomp/conversion.go index dfab381a5..4c25cb1b1 100644 --- a/vendor/github.com/containers/common/pkg/seccomp/conversion.go +++ b/vendor/github.com/containers/common/pkg/seccomp/conversion.go @@ -118,6 +118,7 @@ func specToSeccomp(spec *specs.LinuxSeccomp) (*Seccomp, error) { return nil, errors.Wrap(err, "convert default action") } res.DefaultAction = newDefaultAction + res.DefaultErrnoRet = spec.DefaultErrnoRet // Loop through all syscall blocks and convert them to the internal format for _, call := range spec.Syscalls { diff --git a/vendor/github.com/containers/common/pkg/seccomp/default_linux.go b/vendor/github.com/containers/common/pkg/seccomp/default_linux.go index f86f3e2ba..725e0bfc7 100644 --- a/vendor/github.com/containers/common/pkg/seccomp/default_linux.go +++ b/vendor/github.com/containers/common/pkg/seccomp/default_linux.go @@ -44,10 +44,47 @@ func arches() []Architecture { // DefaultProfile defines the allowlist for the default seccomp profile. func DefaultProfile() *Seccomp { einval := uint(unix.EINVAL) + enosys := uint(unix.ENOSYS) + eperm := uint(unix.EPERM) syscalls := []*Syscall{ { Names: []string{ + "bdflush", + "io_pgetevents", + "kexec_file_load", + "kexec_load", + "migrate_pages", + "move_pages", + "nfsservctl", + "nice", + "oldfstat", + "oldlstat", + "oldolduname", + "oldstat", + "olduname", + "pciconfig_iobase", + "pciconfig_read", + "pciconfig_write", + "sgetmask", + "ssetmask", + "swapcontext", + "swapoff", + "swapon", + "sysfs", + "uselib", + "userfaultfd", + "ustat", + "vm86", + "vm86old", + "vmsplice", + }, + Action: ActErrno, + ErrnoRet: &eperm, + Args: []*Arg{}, + }, + { + Names: []string{ "_llseek", "_newselect", "accept", @@ -72,6 +109,7 @@ func DefaultProfile() *Seccomp { "clock_nanosleep", "clock_nanosleep_time64", "clone", + "clone3", "close", "close_range", "connect", @@ -128,6 +166,7 @@ func DefaultProfile() *Seccomp { "ftruncate", "ftruncate64", "futex", + "futex_time64", "futimesat", "get_robust_list", "get_thread_area", @@ -144,6 +183,7 @@ func DefaultProfile() *Seccomp { "getgroups", "getgroups32", "getitimer", + "get_mempolicy", "getpeername", "getpgid", "getpgrp", @@ -194,6 +234,7 @@ func DefaultProfile() *Seccomp { "lstat", "lstat64", "madvise", + "mbind", "memfd_create", "mincore", "mkdir", @@ -212,7 +253,9 @@ func DefaultProfile() *Seccomp { "mq_notify", "mq_open", "mq_timedreceive", + "mq_timedreceive_time64", "mq_timedsend", + "mq_timedsend_time64", "mq_unlink", "mremap", "msgctl", @@ -237,6 +280,9 @@ func DefaultProfile() *Seccomp { "pipe", "pipe2", "pivot_root", + "pkey_alloc", + "pkey_free", + "pkey_mprotect", "poll", "ppoll", "ppoll_time64", @@ -252,6 +298,7 @@ func DefaultProfile() *Seccomp { "pwritev2", "read", "readahead", + "readdir", "readlink", "readlinkat", "readv", @@ -259,6 +306,7 @@ func DefaultProfile() *Seccomp { "recv", "recvfrom", "recvmmsg", + "recvmmsg_time64", "recvmsg", "remap_file_pages", "removexattr", @@ -267,6 +315,7 @@ func DefaultProfile() *Seccomp { "renameat2", "restart_syscall", "rmdir", + "rseq", "rt_sigaction", "rt_sigpending", "rt_sigprocmask", @@ -274,6 +323,7 @@ func DefaultProfile() *Seccomp { "rt_sigreturn", "rt_sigsuspend", "rt_sigtimedwait", + "rt_sigtimedwait_time64", "rt_tgsigqueueinfo", "sched_get_priority_max", "sched_get_priority_min", @@ -282,6 +332,7 @@ func DefaultProfile() *Seccomp { "sched_getparam", "sched_getscheduler", "sched_rr_get_interval", + "sched_rr_get_interval_time64", "sched_setaffinity", "sched_setattr", "sched_setparam", @@ -293,6 +344,7 @@ func DefaultProfile() *Seccomp { "semget", "semop", "semtimedop", + "semtimedop_time64", "send", "sendfile", "sendfile64", @@ -300,6 +352,7 @@ func DefaultProfile() *Seccomp { "sendmsg", "sendto", "setns", + "set_mempolicy", "set_robust_list", "set_thread_area", "set_tid_address", @@ -361,6 +414,7 @@ func DefaultProfile() *Seccomp { "timer_gettime", "timer_gettime64", "timer_settime", + "timer_settime64", "timerfd_create", "timerfd_gettime", "timerfd_gettime64", @@ -516,6 +570,17 @@ func DefaultProfile() *Seccomp { }, { Names: []string{ + "open_by_handle_at", + }, + Action: ActErrno, + ErrnoRet: &eperm, + Args: []*Arg{}, + Excludes: Filter{ + Caps: []string{"CAP_DAC_READ_SEARCH"}, + }, + }, + { + Names: []string{ "bpf", "fanotify_init", "lookup_dcookie", @@ -533,6 +598,24 @@ func DefaultProfile() *Seccomp { }, { Names: []string{ + "bpf", + "fanotify_init", + "lookup_dcookie", + "perf_event_open", + "quotactl", + "setdomainname", + "sethostname", + "setns", + }, + Action: ActErrno, + ErrnoRet: &eperm, + Args: []*Arg{}, + Excludes: Filter{ + Caps: []string{"CAP_SYS_ADMIN"}, + }, + }, + { + Names: []string{ "chroot", }, Action: ActAllow, @@ -543,6 +626,17 @@ func DefaultProfile() *Seccomp { }, { Names: []string{ + "chroot", + }, + Action: ActErrno, + ErrnoRet: &eperm, + Args: []*Arg{}, + Excludes: Filter{ + Caps: []string{"CAP_SYS_CHROOT"}, + }, + }, + { + Names: []string{ "delete_module", "init_module", "finit_module", @@ -556,14 +650,16 @@ func DefaultProfile() *Seccomp { }, { Names: []string{ - "get_mempolicy", - "mbind", - "set_mempolicy", + "delete_module", + "init_module", + "finit_module", + "query_module", }, - Action: ActAllow, - Args: []*Arg{}, - Includes: Filter{ - Caps: []string{"CAP_SYS_NICE"}, + Action: ActErrno, + ErrnoRet: &eperm, + Args: []*Arg{}, + Excludes: Filter{ + Caps: []string{"CAP_SYS_MODULE"}, }, }, { @@ -578,6 +674,17 @@ func DefaultProfile() *Seccomp { }, { Names: []string{ + "acct", + }, + Action: ActErrno, + ErrnoRet: &eperm, + Args: []*Arg{}, + Excludes: Filter{ + Caps: []string{"CAP_SYS_PACCT"}, + }, + }, + { + Names: []string{ "kcmp", "process_madvise", "process_vm_readv", @@ -592,6 +699,21 @@ func DefaultProfile() *Seccomp { }, { Names: []string{ + "kcmp", + "process_madvise", + "process_vm_readv", + "process_vm_writev", + "ptrace", + }, + Action: ActErrno, + ErrnoRet: &eperm, + Args: []*Arg{}, + Excludes: Filter{ + Caps: []string{"CAP_SYS_PTRACE"}, + }, + }, + { + Names: []string{ "iopl", "ioperm", }, @@ -603,6 +725,18 @@ func DefaultProfile() *Seccomp { }, { Names: []string{ + "iopl", + "ioperm", + }, + Action: ActErrno, + ErrnoRet: &eperm, + Args: []*Arg{}, + Excludes: Filter{ + Caps: []string{"CAP_SYS_RAWIO"}, + }, + }, + { + Names: []string{ "settimeofday", "stime", "clock_settime", @@ -616,6 +750,20 @@ func DefaultProfile() *Seccomp { }, { Names: []string{ + "settimeofday", + "stime", + "clock_settime", + "clock_settime64", + }, + Action: ActErrno, + ErrnoRet: &eperm, + Args: []*Arg{}, + Excludes: Filter{ + Caps: []string{"CAP_SYS_TIME"}, + }, + }, + { + Names: []string{ "vhangup", }, Action: ActAllow, @@ -626,6 +774,17 @@ func DefaultProfile() *Seccomp { }, { Names: []string{ + "vhangup", + }, + Action: ActErrno, + ErrnoRet: &eperm, + Args: []*Arg{}, + Excludes: Filter{ + Caps: []string{"CAP_SYS_TTY_CONFIG"}, + }, + }, + { + Names: []string{ "socket", }, Action: ActErrno, @@ -706,8 +865,9 @@ func DefaultProfile() *Seccomp { } return &Seccomp{ - DefaultAction: ActErrno, - ArchMap: arches(), - Syscalls: syscalls, + DefaultAction: ActErrno, + DefaultErrnoRet: &enosys, + ArchMap: arches(), + Syscalls: syscalls, } } diff --git a/vendor/github.com/containers/common/pkg/seccomp/filter.go b/vendor/github.com/containers/common/pkg/seccomp/filter.go index ac9b2698f..90da99f0a 100644 --- a/vendor/github.com/containers/common/pkg/seccomp/filter.go +++ b/vendor/github.com/containers/common/pkg/seccomp/filter.go @@ -41,7 +41,7 @@ func BuildFilter(spec *specs.LinuxSeccomp) (*libseccomp.ScmpFilter, error) { return nil, errors.Wrap(err, "convert spec to seccomp profile") } - defaultAction, err := toAction(profile.DefaultAction, nil) + defaultAction, err := toAction(profile.DefaultAction, profile.DefaultErrnoRet) if err != nil { return nil, errors.Wrapf(err, "convert default action %s", profile.DefaultAction) } diff --git a/vendor/github.com/containers/common/pkg/seccomp/seccomp.json b/vendor/github.com/containers/common/pkg/seccomp/seccomp.json index 8d799fd02..eeb41d5d8 100644 --- a/vendor/github.com/containers/common/pkg/seccomp/seccomp.json +++ b/vendor/github.com/containers/common/pkg/seccomp/seccomp.json @@ -1,5 +1,6 @@ { "defaultAction": "SCMP_ACT_ERRNO", + "defaultErrnoRet": 38, "archMap": [ { "architecture": "SCMP_ARCH_X86_64", @@ -52,6 +53,44 @@ "syscalls": [ { "names": [ + "bdflush", + "io_pgetevents", + "kexec_file_load", + "kexec_load", + "migrate_pages", + "move_pages", + "nfsservctl", + "nice", + "oldfstat", + "oldlstat", + "oldolduname", + "oldstat", + "olduname", + "pciconfig_iobase", + "pciconfig_read", + "pciconfig_write", + "sgetmask", + "ssetmask", + "swapcontext", + "swapoff", + "swapon", + "sysfs", + "uselib", + "userfaultfd", + "ustat", + "vm86", + "vm86old", + "vmsplice" + ], + "action": "SCMP_ACT_ERRNO", + "args": [], + "comment": "", + "includes": {}, + "excludes": {}, + "errnoRet": 1 + }, + { + "names": [ "_llseek", "_newselect", "accept", @@ -76,6 +115,7 @@ "clock_nanosleep", "clock_nanosleep_time64", "clone", + "clone3", "close", "close_range", "connect", @@ -132,6 +172,7 @@ "ftruncate", "ftruncate64", "futex", + "futex_time64", "futimesat", "get_robust_list", "get_thread_area", @@ -148,6 +189,7 @@ "getgroups", "getgroups32", "getitimer", + "get_mempolicy", "getpeername", "getpgid", "getpgrp", @@ -198,6 +240,7 @@ "lstat", "lstat64", "madvise", + "mbind", "memfd_create", "mincore", "mkdir", @@ -216,7 +259,9 @@ "mq_notify", "mq_open", "mq_timedreceive", + "mq_timedreceive_time64", "mq_timedsend", + "mq_timedsend_time64", "mq_unlink", "mremap", "msgctl", @@ -241,6 +286,9 @@ "pipe", "pipe2", "pivot_root", + "pkey_alloc", + "pkey_free", + "pkey_mprotect", "poll", "ppoll", "ppoll_time64", @@ -256,6 +304,7 @@ "pwritev2", "read", "readahead", + "readdir", "readlink", "readlinkat", "readv", @@ -263,6 +312,7 @@ "recv", "recvfrom", "recvmmsg", + "recvmmsg_time64", "recvmsg", "remap_file_pages", "removexattr", @@ -271,6 +321,7 @@ "renameat2", "restart_syscall", "rmdir", + "rseq", "rt_sigaction", "rt_sigpending", "rt_sigprocmask", @@ -278,6 +329,7 @@ "rt_sigreturn", "rt_sigsuspend", "rt_sigtimedwait", + "rt_sigtimedwait_time64", "rt_tgsigqueueinfo", "sched_get_priority_max", "sched_get_priority_min", @@ -286,6 +338,7 @@ "sched_getparam", "sched_getscheduler", "sched_rr_get_interval", + "sched_rr_get_interval_time64", "sched_setaffinity", "sched_setattr", "sched_setparam", @@ -297,6 +350,7 @@ "semget", "semop", "semtimedop", + "semtimedop_time64", "send", "sendfile", "sendfile64", @@ -304,6 +358,7 @@ "sendmsg", "sendto", "setns", + "set_mempolicy", "set_robust_list", "set_thread_area", "set_tid_address", @@ -365,6 +420,7 @@ "timer_gettime", "timer_gettime64", "timer_settime", + "timer_settime64", "timerfd_create", "timerfd_gettime", "timerfd_gettime64", @@ -582,6 +638,21 @@ }, { "names": [ + "open_by_handle_at" + ], + "action": "SCMP_ACT_ERRNO", + "args": [], + "comment": "", + "includes": {}, + "excludes": { + "caps": [ + "CAP_DAC_READ_SEARCH" + ] + }, + "errnoRet": 1 + }, + { + "names": [ "bpf", "fanotify_init", "lookup_dcookie", @@ -603,6 +674,28 @@ }, { "names": [ + "bpf", + "fanotify_init", + "lookup_dcookie", + "perf_event_open", + "quotactl", + "setdomainname", + "sethostname", + "setns" + ], + "action": "SCMP_ACT_ERRNO", + "args": [], + "comment": "", + "includes": {}, + "excludes": { + "caps": [ + "CAP_SYS_ADMIN" + ] + }, + "errnoRet": 1 + }, + { + "names": [ "chroot" ], "action": "SCMP_ACT_ALLOW", @@ -617,6 +710,21 @@ }, { "names": [ + "chroot" + ], + "action": "SCMP_ACT_ERRNO", + "args": [], + "comment": "", + "includes": {}, + "excludes": { + "caps": [ + "CAP_SYS_CHROOT" + ] + }, + "errnoRet": 1 + }, + { + "names": [ "delete_module", "init_module", "finit_module", @@ -634,19 +742,21 @@ }, { "names": [ - "get_mempolicy", - "mbind", - "set_mempolicy" + "delete_module", + "init_module", + "finit_module", + "query_module" ], - "action": "SCMP_ACT_ALLOW", + "action": "SCMP_ACT_ERRNO", "args": [], "comment": "", - "includes": { + "includes": {}, + "excludes": { "caps": [ - "CAP_SYS_NICE" + "CAP_SYS_MODULE" ] }, - "excludes": {} + "errnoRet": 1 }, { "names": [ @@ -664,6 +774,21 @@ }, { "names": [ + "acct" + ], + "action": "SCMP_ACT_ERRNO", + "args": [], + "comment": "", + "includes": {}, + "excludes": { + "caps": [ + "CAP_SYS_PACCT" + ] + }, + "errnoRet": 1 + }, + { + "names": [ "kcmp", "process_madvise", "process_vm_readv", @@ -682,6 +807,25 @@ }, { "names": [ + "kcmp", + "process_madvise", + "process_vm_readv", + "process_vm_writev", + "ptrace" + ], + "action": "SCMP_ACT_ERRNO", + "args": [], + "comment": "", + "includes": {}, + "excludes": { + "caps": [ + "CAP_SYS_PTRACE" + ] + }, + "errnoRet": 1 + }, + { + "names": [ "iopl", "ioperm" ], @@ -697,6 +841,22 @@ }, { "names": [ + "iopl", + "ioperm" + ], + "action": "SCMP_ACT_ERRNO", + "args": [], + "comment": "", + "includes": {}, + "excludes": { + "caps": [ + "CAP_SYS_RAWIO" + ] + }, + "errnoRet": 1 + }, + { + "names": [ "settimeofday", "stime", "clock_settime", @@ -714,6 +874,24 @@ }, { "names": [ + "settimeofday", + "stime", + "clock_settime", + "clock_settime64" + ], + "action": "SCMP_ACT_ERRNO", + "args": [], + "comment": "", + "includes": {}, + "excludes": { + "caps": [ + "CAP_SYS_TIME" + ] + }, + "errnoRet": 1 + }, + { + "names": [ "vhangup" ], "action": "SCMP_ACT_ALLOW", @@ -728,6 +906,21 @@ }, { "names": [ + "vhangup" + ], + "action": "SCMP_ACT_ERRNO", + "args": [], + "comment": "", + "includes": {}, + "excludes": { + "caps": [ + "CAP_SYS_TTY_CONFIG" + ] + }, + "errnoRet": 1 + }, + { + "names": [ "socket" ], "action": "SCMP_ACT_ERRNO", diff --git a/vendor/github.com/containers/common/pkg/seccomp/seccomp_linux.go b/vendor/github.com/containers/common/pkg/seccomp/seccomp_linux.go index 19500cc97..af36b9990 100644 --- a/vendor/github.com/containers/common/pkg/seccomp/seccomp_linux.go +++ b/vendor/github.com/containers/common/pkg/seccomp/seccomp_linux.go @@ -111,6 +111,7 @@ func setupSeccomp(config *Seccomp, rs *specs.Spec) (*specs.LinuxSeccomp, error) } newConfig.DefaultAction = specs.LinuxSeccompAction(config.DefaultAction) + newConfig.DefaultErrnoRet = config.DefaultErrnoRet Loop: // Loop through all syscall blocks and convert them to libcontainer format after filtering them diff --git a/vendor/github.com/containers/common/pkg/seccomp/types.go b/vendor/github.com/containers/common/pkg/seccomp/types.go index 7b0436dfc..36712458a 100644 --- a/vendor/github.com/containers/common/pkg/seccomp/types.go +++ b/vendor/github.com/containers/common/pkg/seccomp/types.go @@ -6,7 +6,8 @@ package seccomp // Seccomp represents the config for a seccomp profile for syscall restriction. type Seccomp struct { - DefaultAction Action `json:"defaultAction"` + DefaultAction Action `json:"defaultAction"` + DefaultErrnoRet *uint `json:"defaultErrnoRet"` // Architectures is kept to maintain backward compatibility with the old // seccomp profile. Architectures []Arch `json:"architectures,omitempty"` diff --git a/vendor/github.com/containers/common/pkg/secrets/passdriver/passdriver.go b/vendor/github.com/containers/common/pkg/secrets/passdriver/passdriver.go new file mode 100644 index 000000000..6dc00b34c --- /dev/null +++ b/vendor/github.com/containers/common/pkg/secrets/passdriver/passdriver.go @@ -0,0 +1,176 @@ +package passdriver + +import ( + "bytes" + "context" + "io" + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "sort" + "strings" + + "github.com/pkg/errors" +) + +var ( + // errNoSecretData indicates that there is not data associated with an id + errNoSecretData = errors.New("no secret data with ID") + + // errNoSecretData indicates that there is secret data already associated with an id + errSecretIDExists = errors.New("secret data with ID already exists") + + // errInvalidKey indicates that something about your key is wrong + errInvalidKey = errors.New("invalid key") +) + +type driverConfig struct { + // Root contains the root directory where the secrets are stored + Root string + // KeyID contains the key id that will be used for encryption (i.e. user@domain.tld) + KeyID string +} + +func (cfg *driverConfig) ParseOpts(opts map[string]string) { + if val, ok := opts["root"]; ok { + cfg.Root = val + cfg.findGpgID() // try to find a .gpg-id in the parent directories of Root + } + if val, ok := opts["key"]; ok { + cfg.KeyID = val + } +} + +func defaultDriverConfig() *driverConfig { + cfg := &driverConfig{} + + if home, err := os.UserHomeDir(); err == nil { + defaultLocations := []string{ + filepath.Join(home, ".password-store"), + filepath.Join(home, ".local/share/gopass/stores/root"), + } + for _, path := range defaultLocations { + if stat, err := os.Stat(path); err != nil || !stat.IsDir() { + continue + } + cfg.Root = path + bs, err := ioutil.ReadFile(filepath.Join(path, ".gpg-id")) + if err != nil { + continue + } + cfg.KeyID = string(bytes.Trim(bs, "\r\n")) + break + } + } + + return cfg +} + +func (cfg *driverConfig) findGpgID() { + path := cfg.Root + for len(path) > 1 { + if _, err := os.Stat(filepath.Join(path, ".gpg-id")); err == nil { + bs, err := ioutil.ReadFile(filepath.Join(path, ".gpg-id")) + if err != nil { + continue + } + cfg.KeyID = string(bytes.Trim(bs, "\r\n")) + break + } + path = filepath.Dir(path) + } +} + +// Driver is the passdriver object +type Driver struct { + driverConfig +} + +// NewDriver creates a new secret driver. +func NewDriver(opts map[string]string) (*Driver, error) { + cfg := defaultDriverConfig() + cfg.ParseOpts(opts) + + driver := &Driver{ + driverConfig: *cfg, + } + + return driver, nil +} + +// List returns all secret IDs +func (d *Driver) List() (secrets []string, err error) { + files, err := ioutil.ReadDir(d.Root) + if err != nil { + return nil, errors.Wrap(err, "failed to read secret directory") + } + for _, f := range files { + fileName := f.Name() + withoutSuffix := fileName[:len(fileName)-len(".gpg")] + secrets = append(secrets, withoutSuffix) + } + sort.Strings(secrets) + return secrets, nil +} + +// Lookup returns the bytes associated with a secret ID +func (d *Driver) Lookup(id string) ([]byte, error) { + out := &bytes.Buffer{} + key, err := d.getPath(id) + if err != nil { + return nil, err + } + if err := d.gpg(context.TODO(), nil, out, "--decrypt", key); err != nil { + return nil, errors.Wrapf(errNoSecretData, id) + } + if out.Len() == 0 { + return nil, errors.Wrapf(errNoSecretData, id) + } + return out.Bytes(), nil +} + +// Store saves the bytes associated with an ID. An error is returned if the ID already exists +func (d *Driver) Store(id string, data []byte) error { + if _, err := d.Lookup(id); err == nil { + return errors.Wrap(errSecretIDExists, id) + } + in := bytes.NewReader(data) + key, err := d.getPath(id) + if err != nil { + return err + } + return d.gpg(context.TODO(), in, nil, "--encrypt", "-r", d.KeyID, "-o", key) +} + +// Delete removes the secret associated with the specified ID. An error is returned if no matching secret is found. +func (d *Driver) Delete(id string) error { + key, err := d.getPath(id) + if err != nil { + return err + } + if err := os.Remove(key); err != nil { + return errors.Wrap(errNoSecretData, id) + } + return nil +} + +func (d *Driver) gpg(ctx context.Context, in io.Reader, out io.Writer, args ...string) error { + cmd := exec.CommandContext(ctx, "gpg", args...) + cmd.Env = os.Environ() + cmd.Stdin = in + cmd.Stdout = out + cmd.Stderr = ioutil.Discard + return cmd.Run() +} + +func (d *Driver) getPath(id string) (string, error) { + path, err := filepath.Abs(filepath.Join(d.Root, id)) + if err != nil { + return "", errInvalidKey + } + if !strings.HasPrefix(path, d.Root) { + return "", errInvalidKey + } + return path + ".gpg", nil +} diff --git a/vendor/github.com/containers/common/pkg/secrets/secrets.go b/vendor/github.com/containers/common/pkg/secrets/secrets.go index d27bb7472..2573b80e2 100644 --- a/vendor/github.com/containers/common/pkg/secrets/secrets.go +++ b/vendor/github.com/containers/common/pkg/secrets/secrets.go @@ -8,6 +8,7 @@ import ( "time" "github.com/containers/common/pkg/secrets/filedriver" + "github.com/containers/common/pkg/secrets/passdriver" "github.com/containers/storage/pkg/lockfile" "github.com/containers/storage/pkg/stringid" "github.com/pkg/errors" @@ -271,12 +272,15 @@ func validateSecretName(name string) error { // getDriver creates a new driver. func getDriver(name string, opts map[string]string) (SecretsDriver, error) { - if name == "file" { + switch name { + case "file": if path, ok := opts["path"]; ok { return filedriver.NewDriver(path) } else { return nil, errors.Wrap(errInvalidDriverOpt, "need path for filedriver") } + case "pass": + return passdriver.NewDriver(opts) } return nil, errInvalidDriver } diff --git a/vendor/github.com/containers/common/version/version.go b/vendor/github.com/containers/common/version/version.go index ff3bf9a32..8907e21ab 100644 --- a/vendor/github.com/containers/common/version/version.go +++ b/vendor/github.com/containers/common/version/version.go @@ -1,4 +1,4 @@ package version // Version is the version of the build. -const Version = "0.39.1-dev" +const Version = "0.40.2-dev" diff --git a/vendor/github.com/containers/image/v5/copy/copy.go b/vendor/github.com/containers/image/v5/copy/copy.go index ed76283f9..62f47c013 100644 --- a/vendor/github.com/containers/image/v5/copy/copy.go +++ b/vendor/github.com/containers/image/v5/copy/copy.go @@ -29,10 +29,10 @@ import ( imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1" "github.com/pkg/errors" "github.com/sirupsen/logrus" - "github.com/vbauerster/mpb/v6" - "github.com/vbauerster/mpb/v6/decor" - "golang.org/x/crypto/ssh/terminal" + "github.com/vbauerster/mpb/v7" + "github.com/vbauerster/mpb/v7/decor" "golang.org/x/sync/semaphore" + "golang.org/x/term" ) type digestingReader struct { @@ -43,10 +43,6 @@ type digestingReader struct { validationSucceeded bool } -// FIXME: disable early layer commits temporarily until a solid solution to -// address #1205 has been found. -const enableEarlyCommit = false - var ( // ErrDecryptParamsMissing is returned if there is missing decryption parameters ErrDecryptParamsMissing = errors.New("Necessary DecryptParameters not present") @@ -864,7 +860,7 @@ func (ic *imageCopier) noPendingManifestUpdates() bool { // isTTY returns true if the io.Writer is a file and a tty. func isTTY(w io.Writer) bool { if f, ok := w.(*os.File); ok { - return terminal.IsTerminal(int(f.Fd())) + return term.IsTerminal(int(f.Fd())) } return false } @@ -893,6 +889,18 @@ func (ic *imageCopier) copyLayers(ctx context.Context) error { err error } + // The manifest is used to extract the information whether a given + // layer is empty. + manifestBlob, manifestType, err := ic.src.Manifest(ctx) + if err != nil { + return err + } + man, err := manifest.FromBlob(manifestBlob, manifestType) + if err != nil { + return err + } + manifestLayerInfos := man.LayerInfos() + // copyGroup is used to determine if all layers are copied copyGroup := sync.WaitGroup{} @@ -925,7 +933,7 @@ func (ic *imageCopier) copyLayers(ctx context.Context) error { logrus.Debugf("Skipping foreign layer %q copy to %s", cld.destInfo.Digest, ic.c.dest.Reference().Transport().Name()) } } else { - cld.destInfo, cld.diffID, cld.err = ic.copyLayer(ctx, srcLayer, toEncrypt, pool, index, srcRef) + cld.destInfo, cld.diffID, cld.err = ic.copyLayer(ctx, srcLayer, toEncrypt, pool, index, srcRef, manifestLayerInfos[index].EmptyLayer) } data[index] = cld } @@ -1094,8 +1102,9 @@ func (c *copier) createProgressBar(pool *mpb.Progress, info types.BlobInfo, kind ), ) } else { + sstyle := mpb.SpinnerStyle(".", "..", "...", "....", "").PositionLeft() bar = pool.Add(0, - mpb.NewSpinnerFiller([]string{".", "..", "...", "....", ""}, mpb.SpinnerOnLeft), + sstyle.Build(), mpb.BarFillerClearOnComplete(), mpb.PrependDecorators( decor.OnComplete(decor.Name(prefix), onComplete), @@ -1121,7 +1130,7 @@ func (c *copier) copyConfig(ctx context.Context, src types.Image) error { progressPool, progressCleanup := c.newProgressPool(ctx) defer progressCleanup() bar := c.createProgressBar(progressPool, srcInfo, "config", "done") - destInfo, err := c.copyBlobFromStream(ctx, bytes.NewReader(configBlob), srcInfo, nil, false, true, false, bar, -1) + destInfo, err := c.copyBlobFromStream(ctx, bytes.NewReader(configBlob), srcInfo, nil, false, true, false, bar, -1, false) if err != nil { return types.BlobInfo{}, err } @@ -1148,7 +1157,7 @@ type diffIDResult struct { // copyLayer copies a layer with srcInfo (with known Digest and Annotations and possibly known Size) in src to dest, perhaps (de/re/)compressing it, // and returns a complete blobInfo of the copied layer, and a value for LayerDiffIDs if diffIDIsNeeded // srcRef can be used as an additional hint to the destination during checking whehter a layer can be reused but srcRef can be nil. -func (ic *imageCopier) copyLayer(ctx context.Context, srcInfo types.BlobInfo, toEncrypt bool, pool *mpb.Progress, layerIndex int, srcRef reference.Named) (types.BlobInfo, digest.Digest, error) { +func (ic *imageCopier) copyLayer(ctx context.Context, srcInfo types.BlobInfo, toEncrypt bool, pool *mpb.Progress, layerIndex int, srcRef reference.Named, emptyLayer bool) (types.BlobInfo, digest.Digest, error) { // If the srcInfo doesn't contain compression information, try to compute it from the // MediaType, which was either read from a manifest by way of LayerInfos() or constructed // by LayerInfosForCopy(), if it was supplied at all. If we succeed in copying the blob, @@ -1195,10 +1204,9 @@ func (ic *imageCopier) copyLayer(ctx context.Context, srcInfo types.BlobInfo, to Cache: ic.c.blobInfoCache, CanSubstitute: ic.canSubstituteBlobs, SrcRef: srcRef, + EmptyLayer: emptyLayer, } - if enableEarlyCommit { - options.LayerIndex = &layerIndex - } + options.LayerIndex = &layerIndex reused, blobInfo, err = dest.TryReusingBlobWithOptions(ctx, srcInfo, options) } else { reused, blobInfo, err = ic.c.dest.TryReusingBlob(ctx, srcInfo, ic.c.blobInfoCache, ic.canSubstituteBlobs) @@ -1245,7 +1253,7 @@ func (ic *imageCopier) copyLayer(ctx context.Context, srcInfo types.BlobInfo, to bar := ic.c.createProgressBar(pool, srcInfo, "blob", "done") - blobInfo, diffIDChan, err := ic.copyLayerFromStream(ctx, srcStream, types.BlobInfo{Digest: srcInfo.Digest, Size: srcBlobSize, MediaType: srcInfo.MediaType, Annotations: srcInfo.Annotations}, diffIDIsNeeded, toEncrypt, bar, layerIndex) + blobInfo, diffIDChan, err := ic.copyLayerFromStream(ctx, srcStream, types.BlobInfo{Digest: srcInfo.Digest, Size: srcBlobSize, MediaType: srcInfo.MediaType, Annotations: srcInfo.Annotations}, diffIDIsNeeded, toEncrypt, bar, layerIndex, emptyLayer) if err != nil { return types.BlobInfo{}, "", err } @@ -1276,7 +1284,7 @@ func (ic *imageCopier) copyLayer(ctx context.Context, srcInfo types.BlobInfo, to // perhaps (de/re/)compressing the stream, // and returns a complete blobInfo of the copied blob and perhaps a <-chan diffIDResult if diffIDIsNeeded, to be read by the caller. func (ic *imageCopier) copyLayerFromStream(ctx context.Context, srcStream io.Reader, srcInfo types.BlobInfo, - diffIDIsNeeded bool, toEncrypt bool, bar *mpb.Bar, layerIndex int) (types.BlobInfo, <-chan diffIDResult, error) { + diffIDIsNeeded bool, toEncrypt bool, bar *mpb.Bar, layerIndex int, emptyLayer bool) (types.BlobInfo, <-chan diffIDResult, error) { var getDiffIDRecorder func(compression.DecompressorFunc) io.Writer // = nil var diffIDChan chan diffIDResult @@ -1301,7 +1309,7 @@ func (ic *imageCopier) copyLayerFromStream(ctx context.Context, srcStream io.Rea } } - blobInfo, err := ic.c.copyBlobFromStream(ctx, srcStream, srcInfo, getDiffIDRecorder, ic.canModifyManifest, false, toEncrypt, bar, layerIndex) // Sets err to nil on success + blobInfo, err := ic.c.copyBlobFromStream(ctx, srcStream, srcInfo, getDiffIDRecorder, ic.canModifyManifest, false, toEncrypt, bar, layerIndex, emptyLayer) // Sets err to nil on success return blobInfo, diffIDChan, err // We need the defer … pipeWriter.CloseWithError() to happen HERE so that the caller can block on reading from diffIDChan } @@ -1353,7 +1361,7 @@ func (r errorAnnotationReader) Read(b []byte) (n int, err error) { // and returns a complete blobInfo of the copied blob. func (c *copier) copyBlobFromStream(ctx context.Context, srcStream io.Reader, srcInfo types.BlobInfo, getOriginalLayerCopyWriter func(decompressor compression.DecompressorFunc) io.Writer, - canModifyBlob bool, isConfig bool, toEncrypt bool, bar *mpb.Bar, layerIndex int) (types.BlobInfo, error) { + canModifyBlob bool, isConfig bool, toEncrypt bool, bar *mpb.Bar, layerIndex int, emptyLayer bool) (types.BlobInfo, error) { if isConfig { // This is guaranteed by the caller, but set it here to be explicit. canModifyBlob = false } @@ -1556,10 +1564,11 @@ func (c *copier) copyBlobFromStream(ctx context.Context, srcStream io.Reader, sr dest, ok := c.dest.(internalTypes.ImageDestinationWithOptions) if ok { options := internalTypes.PutBlobOptions{ - Cache: c.blobInfoCache, - IsConfig: isConfig, + Cache: c.blobInfoCache, + IsConfig: isConfig, + EmptyLayer: emptyLayer, } - if !isConfig && enableEarlyCommit { + if !isConfig { options.LayerIndex = &layerIndex } uploadedInfo, err = dest.PutBlobWithOptions(ctx, &errorAnnotationReader{destStream}, inputInfo, options) diff --git a/vendor/github.com/containers/image/v5/internal/pkg/platform/platform_matcher.go b/vendor/github.com/containers/image/v5/internal/pkg/platform/platform_matcher.go index 3e81e06c0..3bda6af29 100644 --- a/vendor/github.com/containers/image/v5/internal/pkg/platform/platform_matcher.go +++ b/vendor/github.com/containers/image/v5/internal/pkg/platform/platform_matcher.go @@ -9,7 +9,7 @@ package platform // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. diff --git a/vendor/github.com/containers/image/v5/internal/types/types.go b/vendor/github.com/containers/image/v5/internal/types/types.go index bf89a69b8..4a863ba34 100644 --- a/vendor/github.com/containers/image/v5/internal/types/types.go +++ b/vendor/github.com/containers/image/v5/internal/types/types.go @@ -39,6 +39,8 @@ type PutBlobOptions struct { Cache publicTypes.BlobInfoCache // Denotes whether the blob is a config or not. IsConfig bool + // Indicates an empty layer. + EmptyLayer bool // The corresponding index in the layer slice. LayerIndex *int } @@ -49,6 +51,8 @@ type TryReusingBlobOptions struct { Cache publicTypes.BlobInfoCache // Use an equivalent of the desired blob. CanSubstitute bool + // Indicates an empty layer. + EmptyLayer bool // The corresponding index in the layer slice. LayerIndex *int // The reference of the image that contains the target blob. diff --git a/vendor/github.com/containers/image/v5/pkg/docker/config/config.go b/vendor/github.com/containers/image/v5/pkg/docker/config/config.go index b84aac6e4..ec7c2fcc3 100644 --- a/vendor/github.com/containers/image/v5/pkg/docker/config/config.go +++ b/vendor/github.com/containers/image/v5/pkg/docker/config/config.go @@ -51,21 +51,26 @@ var ( ErrNotSupported = errors.New("not supported") ) -// SetAuthentication stores the username and password in the credential helper or file -func SetAuthentication(sys *types.SystemContext, registry, username, password string) error { +// SetCredentials stores the username and password in the credential helper or file +// and returns path to file or helper name in format (helper:%s). +// Returns a human-redable description of the location that was updated. +// NOTE: The return value is only intended to be read by humans; its form is not an API, +// it may change (or new forms can be added) any time. +func SetCredentials(sys *types.SystemContext, registry, username, password string) (string, error) { helpers, err := sysregistriesv2.CredentialHelpers(sys) if err != nil { - return err + return "", err } // Make sure to collect all errors. var multiErr error for _, helper := range helpers { + var desc string var err error switch helper { // Special-case the built-in helpers for auth files. case sysregistriesv2.AuthenticationFileHelper: - err = modifyJSON(sys, func(auths *dockerConfigFile) (bool, error) { + desc, err = modifyJSON(sys, func(auths *dockerConfigFile) (bool, error) { if ch, exists := auths.CredHelpers[registry]; exists { return false, setAuthToCredHelper(ch, registry, username, password) } @@ -76,6 +81,7 @@ func SetAuthentication(sys *types.SystemContext, registry, username, password st }) // External helpers. default: + desc = fmt.Sprintf("credential helper: %s", helper) err = setAuthToCredHelper(helper, registry, username, password) } if err != nil { @@ -84,9 +90,15 @@ func SetAuthentication(sys *types.SystemContext, registry, username, password st continue } logrus.Debugf("Stored credentials for %s in credential helper %s", registry, helper) - return nil + return desc, nil } - return multiErr + return "", multiErr +} + +// SetAuthentication stores the username and password in the credential helper or file +func SetAuthentication(sys *types.SystemContext, registry, username, password string) error { + _, err := SetCredentials(sys, registry, username, password) + return err } // GetAllCredentials returns the registry credentials for all registries stored @@ -322,7 +334,7 @@ func RemoveAuthentication(sys *types.SystemContext, registry string) error { switch helper { // Special-case the built-in helper for auth files. case sysregistriesv2.AuthenticationFileHelper: - err = modifyJSON(sys, func(auths *dockerConfigFile) (bool, error) { + _, err = modifyJSON(sys, func(auths *dockerConfigFile) (bool, error) { if innerHelper, exists := auths.CredHelpers[registry]; exists { removeFromCredHelper(innerHelper) } @@ -368,7 +380,7 @@ func RemoveAllAuthentication(sys *types.SystemContext) error { switch helper { // Special-case the built-in helper for auth files. case sysregistriesv2.AuthenticationFileHelper: - err = modifyJSON(sys, func(auths *dockerConfigFile) (bool, error) { + _, err = modifyJSON(sys, func(auths *dockerConfigFile) (bool, error) { for registry, helper := range auths.CredHelpers { // Helpers in auth files are expected // to exist, so no special treatment @@ -493,42 +505,44 @@ func readJSONFile(path string, legacyFormat bool) (dockerConfigFile, error) { return auths, nil } -// modifyJSON writes to auth.json if the dockerConfigFile has been updated -func modifyJSON(sys *types.SystemContext, editor func(auths *dockerConfigFile) (bool, error)) error { +// modifyJSON finds an auth.json file, calls editor on the contents, and +// writes it back if editor returns true. +// Returns a human-redable description of the file, to be returned by SetCredentials. +func modifyJSON(sys *types.SystemContext, editor func(auths *dockerConfigFile) (bool, error)) (string, error) { path, legacyFormat, err := getPathToAuth(sys) if err != nil { - return err + return "", err } if legacyFormat { - return fmt.Errorf("writes to %s using legacy format are not supported", path) + return "", fmt.Errorf("writes to %s using legacy format are not supported", path) } dir := filepath.Dir(path) if err = os.MkdirAll(dir, 0700); err != nil { - return err + return "", err } auths, err := readJSONFile(path, false) if err != nil { - return errors.Wrapf(err, "error reading JSON file %q", path) + return "", errors.Wrapf(err, "error reading JSON file %q", path) } updated, err := editor(&auths) if err != nil { - return errors.Wrapf(err, "error updating %q", path) + return "", errors.Wrapf(err, "error updating %q", path) } if updated { newData, err := json.MarshalIndent(auths, "", "\t") if err != nil { - return errors.Wrapf(err, "error marshaling JSON %q", path) + return "", errors.Wrapf(err, "error marshaling JSON %q", path) } if err = ioutil.WriteFile(path, newData, 0600); err != nil { - return errors.Wrapf(err, "error writing to file %q", path) + return "", errors.Wrapf(err, "error writing to file %q", path) } } - return nil + return path, nil } func getAuthFromCredHelper(credHelper, registry string) (types.DockerAuthConfig, error) { diff --git a/vendor/github.com/containers/image/v5/pkg/docker/config/config_linux.go b/vendor/github.com/containers/image/v5/pkg/docker/config/config_linux.go index 5bbfb450f..93c75b944 100644 --- a/vendor/github.com/containers/image/v5/pkg/docker/config/config_linux.go +++ b/vendor/github.com/containers/image/v5/pkg/docker/config/config_linux.go @@ -13,9 +13,9 @@ import ( // reenable keyring support, we should introduce a similar built-in credential // helpers as for `sysregistriesv2.AuthenticationFileHelper`. -const keyDescribePrefix = "container-registry-login:" // nolint +const keyDescribePrefix = "container-registry-login:" //nolint:deadcode,unused -func getAuthFromKernelKeyring(registry string) (string, string, error) { // nolint +func getAuthFromKernelKeyring(registry string) (string, string, error) { //nolint:deadcode,unused userkeyring, err := keyctl.UserKeyring() if err != nil { return "", "", err @@ -35,7 +35,7 @@ func getAuthFromKernelKeyring(registry string) (string, string, error) { // noli return parts[0], parts[1], nil } -func deleteAuthFromKernelKeyring(registry string) error { // nolint +func deleteAuthFromKernelKeyring(registry string) error { //nolint:deadcode,unused userkeyring, err := keyctl.UserKeyring() if err != nil { @@ -48,7 +48,7 @@ func deleteAuthFromKernelKeyring(registry string) error { // nolint return key.Unlink() } -func removeAllAuthFromKernelKeyring() error { // nolint +func removeAllAuthFromKernelKeyring() error { //nolint:deadcode,unused keys, err := keyctl.ReadUserKeyring() if err != nil { return err @@ -81,7 +81,7 @@ func removeAllAuthFromKernelKeyring() error { // nolint return nil } -func setAuthToKernelKeyring(registry, username, password string) error { // nolint +func setAuthToKernelKeyring(registry, username, password string) error { //nolint:deadcode,unused keyring, err := keyctl.SessionKeyring() if err != nil { return err @@ -114,6 +114,6 @@ func setAuthToKernelKeyring(registry, username, password string) error { // noli return nil } -func genDescription(registry string) string { // nolint +func genDescription(registry string) string { //nolint:deadcode,unused return fmt.Sprintf("%s%s", keyDescribePrefix, registry) } diff --git a/vendor/github.com/containers/image/v5/pkg/docker/config/config_unsupported.go b/vendor/github.com/containers/image/v5/pkg/docker/config/config_unsupported.go index 9b0e8bee2..65e580410 100644 --- a/vendor/github.com/containers/image/v5/pkg/docker/config/config_unsupported.go +++ b/vendor/github.com/containers/image/v5/pkg/docker/config/config_unsupported.go @@ -3,18 +3,18 @@ package config -func getAuthFromKernelKeyring(registry string) (string, string, error) { +func getAuthFromKernelKeyring(registry string) (string, string, error) { //nolint:deadcode,unused return "", "", ErrNotSupported } -func deleteAuthFromKernelKeyring(registry string) error { +func deleteAuthFromKernelKeyring(registry string) error { //nolint:deadcode,unused return ErrNotSupported } -func setAuthToKernelKeyring(registry, username, password string) error { +func setAuthToKernelKeyring(registry, username, password string) error { //nolint:deadcode,unused return ErrNotSupported } -func removeAllAuthFromKernelKeyring() error { +func removeAllAuthFromKernelKeyring() error { //nolint:deadcode,unused return ErrNotSupported } diff --git a/vendor/github.com/containers/image/v5/pkg/shortnames/shortnames.go b/vendor/github.com/containers/image/v5/pkg/shortnames/shortnames.go index b64f44674..ab1eee8f3 100644 --- a/vendor/github.com/containers/image/v5/pkg/shortnames/shortnames.go +++ b/vendor/github.com/containers/image/v5/pkg/shortnames/shortnames.go @@ -11,7 +11,7 @@ import ( "github.com/manifoldco/promptui" "github.com/opencontainers/go-digest" "github.com/pkg/errors" - "golang.org/x/crypto/ssh/terminal" + "golang.org/x/term" ) // IsShortName returns true if the specified input is a "short name". A "short @@ -343,7 +343,7 @@ func Resolve(ctx *types.SystemContext, name string) (*Resolved, error) { } // If we don't have a TTY, act according to the mode. - if !terminal.IsTerminal(int(os.Stdout.Fd())) || !terminal.IsTerminal(int(os.Stdin.Fd())) { + if !term.IsTerminal(int(os.Stdout.Fd())) || !term.IsTerminal(int(os.Stdin.Fd())) { switch mode { case types.ShortNameModePermissive: // Permissive falls back to using all candidates. diff --git a/vendor/github.com/containers/image/v5/storage/storage_image.go b/vendor/github.com/containers/image/v5/storage/storage_image.go index f4747357c..7072d6860 100644 --- a/vendor/github.com/containers/image/v5/storage/storage_image.go +++ b/vendor/github.com/containers/image/v5/storage/storage_image.go @@ -76,12 +76,12 @@ type storageImageDestination struct { indexToStorageID map[int]*string // All accesses to below data are protected by `lock` which is made // *explicit* in the code. - blobDiffIDs map[digest.Digest]digest.Digest // Mapping from layer blobsums to their corresponding DiffIDs - fileSizes map[digest.Digest]int64 // Mapping from layer blobsums to their sizes - filenames map[digest.Digest]string // Mapping from layer blobsums to names of files we used to hold them - currentIndex int // The index of the layer to be committed (i.e., lower indices have already been committed) - indexToPulledBlob map[int]*types.BlobInfo // Mapping from layer (by index) to pulled down blob - blobAdditionalLayer map[digest.Digest]storage.AdditionalLayer // Mapping from layer blobsums to their corresponding additional layer + blobDiffIDs map[digest.Digest]digest.Digest // Mapping from layer blobsums to their corresponding DiffIDs + fileSizes map[digest.Digest]int64 // Mapping from layer blobsums to their sizes + filenames map[digest.Digest]string // Mapping from layer blobsums to names of files we used to hold them + currentIndex int // The index of the layer to be committed (i.e., lower indices have already been committed) + indexToPulledLayerInfo map[int]*manifest.LayerInfo // Mapping from layer (by index) to pulled down blob + blobAdditionalLayer map[digest.Digest]storage.AdditionalLayer // Mapping from layer blobsums to their corresponding additional layer } type storageImageCloser struct { @@ -392,17 +392,17 @@ func newImageDestination(sys *types.SystemContext, imageRef storageReference) (* return nil, errors.Wrapf(err, "error creating a temporary directory") } image := &storageImageDestination{ - imageRef: imageRef, - directory: directory, - signatureses: make(map[digest.Digest][]byte), - blobDiffIDs: make(map[digest.Digest]digest.Digest), - blobAdditionalLayer: make(map[digest.Digest]storage.AdditionalLayer), - fileSizes: make(map[digest.Digest]int64), - filenames: make(map[digest.Digest]string), - SignatureSizes: []int{}, - SignaturesSizes: make(map[digest.Digest][]int), - indexToStorageID: make(map[int]*string), - indexToPulledBlob: make(map[int]*types.BlobInfo), + imageRef: imageRef, + directory: directory, + signatureses: make(map[digest.Digest][]byte), + blobDiffIDs: make(map[digest.Digest]digest.Digest), + blobAdditionalLayer: make(map[digest.Digest]storage.AdditionalLayer), + fileSizes: make(map[digest.Digest]int64), + filenames: make(map[digest.Digest]string), + SignatureSizes: []int{}, + SignaturesSizes: make(map[digest.Digest][]int), + indexToStorageID: make(map[int]*string), + indexToPulledLayerInfo: make(map[int]*manifest.LayerInfo), } return image, nil } @@ -449,7 +449,7 @@ func (s *storageImageDestination) PutBlobWithOptions(ctx context.Context, stream return info, nil } - return info, s.queueOrCommit(ctx, info, *options.LayerIndex) + return info, s.queueOrCommit(ctx, info, *options.LayerIndex, options.EmptyLayer) } // HasThreadSafePutBlob indicates whether PutBlob can be executed concurrently. @@ -542,7 +542,7 @@ func (s *storageImageDestination) TryReusingBlobWithOptions(ctx context.Context, return reused, info, err } - return reused, info, s.queueOrCommit(ctx, info, *options.LayerIndex) + return reused, info, s.queueOrCommit(ctx, info, *options.LayerIndex, options.EmptyLayer) } // tryReusingBlobWithSrcRef is a wrapper around TryReusingBlob. @@ -731,7 +731,7 @@ func (s *storageImageDestination) getConfigBlob(info types.BlobInfo) ([]byte, er // queueOrCommit queues in the specified blob to be committed to the storage. // If no other goroutine is already committing layers, the layer and all // subsequent layers (if already queued) will be committed to the storage. -func (s *storageImageDestination) queueOrCommit(ctx context.Context, blob types.BlobInfo, index int) error { +func (s *storageImageDestination) queueOrCommit(ctx context.Context, blob types.BlobInfo, index int, emptyLayer bool) error { // NOTE: whenever the code below is touched, make sure that all code // paths unlock the lock and to unlock it exactly once. // @@ -751,7 +751,10 @@ func (s *storageImageDestination) queueOrCommit(ctx context.Context, blob types. // caller is the "worker" routine comitting layers. All other routines // can continue pulling and queuing in layers. s.lock.Lock() - s.indexToPulledBlob[index] = &blob + s.indexToPulledLayerInfo[index] = &manifest.LayerInfo{ + BlobInfo: blob, + EmptyLayer: emptyLayer, + } // We're still waiting for at least one previous/parent layer to be // committed, so there's nothing to do. @@ -760,14 +763,10 @@ func (s *storageImageDestination) queueOrCommit(ctx context.Context, blob types. return nil } - for info := s.indexToPulledBlob[index]; info != nil; info = s.indexToPulledBlob[index] { + for info := s.indexToPulledLayerInfo[index]; info != nil; info = s.indexToPulledLayerInfo[index] { s.lock.Unlock() - layerInfo := manifest.LayerInfo{ - BlobInfo: *info, - EmptyLayer: info.Digest == image.GzippedEmptyLayerDigest, - } // Note: commitLayer locks on-demand. - if err := s.commitLayer(ctx, layerInfo, index); err != nil { + if err := s.commitLayer(ctx, *info, index); err != nil { return err } s.lock.Lock() @@ -1034,25 +1033,6 @@ func (s *storageImageDestination) Commit(ctx context.Context, unparsedToplevel t return errors.Wrapf(err, "error saving big data %q for image %q", blob.String(), img.ID) } } - // Set the reference's name on the image. We don't need to worry about avoiding duplicate - // values because SetNames() will deduplicate the list that we pass to it. - if name := s.imageRef.DockerReference(); len(oldNames) > 0 || name != nil { - names := []string{} - if name != nil { - names = append(names, name.String()) - } - if len(oldNames) > 0 { - names = append(names, oldNames...) - } - if err := s.imageRef.transport.store.SetNames(img.ID, names); err != nil { - if _, err2 := s.imageRef.transport.store.DeleteImage(img.ID, true); err2 != nil { - logrus.Debugf("error deleting incomplete image %q: %v", img.ID, err2) - } - logrus.Debugf("error setting names %v on image %q: %v", names, img.ID, err) - return errors.Wrapf(err, "error setting names %v on image %q", names, img.ID) - } - logrus.Debugf("set names of image %q to %v", img.ID, names) - } // Save the unparsedToplevel's manifest. if len(toplevelManifest) != 0 { manifestDigest, err := manifest.Digest(toplevelManifest) @@ -1130,6 +1110,25 @@ func (s *storageImageDestination) Commit(ctx context.Context, unparsedToplevel t } logrus.Debugf("saved image metadata %q", string(metadata)) } + // Set the reference's name on the image. We don't need to worry about avoiding duplicate + // values because SetNames() will deduplicate the list that we pass to it. + if name := s.imageRef.DockerReference(); len(oldNames) > 0 || name != nil { + names := []string{} + if name != nil { + names = append(names, name.String()) + } + if len(oldNames) > 0 { + names = append(names, oldNames...) + } + if err := s.imageRef.transport.store.SetNames(img.ID, names); err != nil { + if _, err2 := s.imageRef.transport.store.DeleteImage(img.ID, true); err2 != nil { + logrus.Debugf("error deleting incomplete image %q: %v", img.ID, err2) + } + logrus.Debugf("error setting names %v on image %q: %v", names, img.ID, err) + return errors.Wrapf(err, "error setting names %v on image %q", names, img.ID) + } + logrus.Debugf("set names of image %q to %v", img.ID, names) + } return nil } diff --git a/vendor/github.com/containers/image/v5/version/version.go b/vendor/github.com/containers/image/v5/version/version.go index 4afb3b90b..edf4681de 100644 --- a/vendor/github.com/containers/image/v5/version/version.go +++ b/vendor/github.com/containers/image/v5/version/version.go @@ -6,9 +6,9 @@ const ( // VersionMajor is for an API incompatible changes VersionMajor = 5 // VersionMinor is for functionality in a backwards-compatible manner - VersionMinor = 12 + VersionMinor = 13 // VersionPatch is for backwards-compatible bug fixes - VersionPatch = 0 + VersionPatch = 2 // VersionDev indicates development branch. Releases will be empty string. VersionDev = "" diff --git a/vendor/github.com/containers/storage/.cirrus.yml b/vendor/github.com/containers/storage/.cirrus.yml index 96714c2fc..12f6f10c6 100644 --- a/vendor/github.com/containers/storage/.cirrus.yml +++ b/vendor/github.com/containers/storage/.cirrus.yml @@ -143,7 +143,7 @@ lint_task: meta_task: container: - image: "quay.io/libpod/imgts:master" + image: "quay.io/libpod/imgts:${_BUILT_IMAGE_SUFFIX}" cpu: 1 memory: 1 diff --git a/vendor/github.com/containers/storage/CODE-OF-CONDUCT.md b/vendor/github.com/containers/storage/CODE-OF-CONDUCT.md index be0791620..f4f7df4b8 100644 --- a/vendor/github.com/containers/storage/CODE-OF-CONDUCT.md +++ b/vendor/github.com/containers/storage/CODE-OF-CONDUCT.md @@ -1,3 +1,3 @@ ## The Containers Storage Project Community Code of Conduct -The Containers Storage project follows the [Containers Community Code of Conduct](https://github.com/containers/common/blob/master/CODE-OF-CONDUCT.md). +The Containers Storage project follows the [Containers Community Code of Conduct](https://github.com/containers/common/blob/main/CODE-OF-CONDUCT.md). diff --git a/vendor/github.com/containers/storage/SECURITY.md b/vendor/github.com/containers/storage/SECURITY.md index 1496a4c00..ab2c14182 100644 --- a/vendor/github.com/containers/storage/SECURITY.md +++ b/vendor/github.com/containers/storage/SECURITY.md @@ -1,3 +1,3 @@ ## Security and Disclosure Information Policy for the Containers Storage Project -The Containers Storage Project follows the [Security and Disclosure Information Policy](https://github.com/containers/common/blob/master/SECURITY.md) for the Containers Projects. +The Containers Storage Project follows the [Security and Disclosure Information Policy](https://github.com/containers/common/blob/main/SECURITY.md) for the Containers Projects. diff --git a/vendor/github.com/containers/storage/VERSION b/vendor/github.com/containers/storage/VERSION index 96cd6ee1e..00b225209 100644 --- a/vendor/github.com/containers/storage/VERSION +++ b/vendor/github.com/containers/storage/VERSION @@ -1 +1 @@ -1.32.1 +1.32.3 diff --git a/vendor/github.com/containers/storage/drivers/devmapper/deviceset.go b/vendor/github.com/containers/storage/drivers/devmapper/deviceset.go index 19fb3fda9..c5168bfdd 100644 --- a/vendor/github.com/containers/storage/drivers/devmapper/deviceset.go +++ b/vendor/github.com/containers/storage/drivers/devmapper/deviceset.go @@ -2229,7 +2229,7 @@ func (devices *DeviceSet) cancelDeferredRemovalIfNeeded(info *devInfo) error { // Cancel deferred remove if err := devices.cancelDeferredRemoval(info); err != nil { // If Error is ErrEnxio. Device is probably already gone. Continue. - if errors.Cause(err) != devicemapper.ErrBusy { + if errors.Cause(err) != devicemapper.ErrEnxio { return err } } diff --git a/vendor/github.com/containers/storage/drivers/overlay/overlay.go b/vendor/github.com/containers/storage/drivers/overlay/overlay.go index d5d161bfd..87d608393 100644 --- a/vendor/github.com/containers/storage/drivers/overlay/overlay.go +++ b/vendor/github.com/containers/storage/drivers/overlay/overlay.go @@ -1189,7 +1189,11 @@ func (d *Driver) get(id string, disableShifting bool, options graphdriver.MountO if d.usingMetacopy { optsList = append(optsList, "metacopy=on") } else { - logrus.Warnf("ignoring metacopy option from storage.conf, not supported with booted kernel") + logLevel := logrus.WarnLevel + if unshare.IsRootless() { + logLevel = logrus.DebugLevel + } + logrus.StandardLogger().Logf(logLevel, "ignoring metacopy option from storage.conf, not supported with booted kernel") } } } diff --git a/vendor/github.com/containers/storage/go.mod b/vendor/github.com/containers/storage/go.mod index e7ca56e64..40eeaf837 100644 --- a/vendor/github.com/containers/storage/go.mod +++ b/vendor/github.com/containers/storage/go.mod @@ -10,15 +10,15 @@ require ( github.com/google/go-intervals v0.0.2 github.com/hashicorp/go-multierror v1.1.1 github.com/json-iterator/go v1.1.11 - github.com/klauspost/compress v1.12.3 + github.com/klauspost/compress v1.13.1 github.com/klauspost/pgzip v1.2.5 - github.com/mattn/go-shellwords v1.0.11 + github.com/mattn/go-shellwords v1.0.12 github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible github.com/moby/sys/mountinfo v0.4.1 github.com/opencontainers/go-digest v1.0.0 github.com/opencontainers/runc v1.0.0-rc95 github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417 - github.com/opencontainers/selinux v1.8.1 + github.com/opencontainers/selinux v1.8.2 github.com/pkg/errors v0.9.1 github.com/sirupsen/logrus v1.8.1 github.com/stretchr/testify v1.7.0 diff --git a/vendor/github.com/containers/storage/go.sum b/vendor/github.com/containers/storage/go.sum index 5373d0597..16da895f5 100644 --- a/vendor/github.com/containers/storage/go.sum +++ b/vendor/github.com/containers/storage/go.sum @@ -77,6 +77,8 @@ github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+Ce github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= +github.com/bits-and-blooms/bitset v1.2.0 h1:Kn4yilvwNtMACtf1eYDlG8H77R07mZSPbMjLyS07ChA= +github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= @@ -383,8 +385,8 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.12.3 h1:G5AfA94pHPysR56qqrkO2pxEexdDzrpFJ6yt/VqWxVU= -github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= +github.com/klauspost/compress v1.13.1 h1:wXr2uRxZTJXHLly6qhJabee5JqIhTRoLBhDOA74hDEQ= +github.com/klauspost/compress v1.13.1/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE= github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -408,8 +410,8 @@ github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaO github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= -github.com/mattn/go-shellwords v1.0.11 h1:vCoR9VPpsk/TZFW2JwK5I9S0xdrtUq2bph6/YjEPnaw= -github.com/mattn/go-shellwords v1.0.11/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= +github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk= +github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= @@ -476,8 +478,8 @@ github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.m github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs= github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE= github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo= -github.com/opencontainers/selinux v1.8.1 h1:yvEZh7CsfnJNwKzG9ZeXwbvR05RAZsu5RS/3vA6qFTA= -github.com/opencontainers/selinux v1.8.1/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo= +github.com/opencontainers/selinux v1.8.2 h1:c4ca10UMgRcvZ6h0K4HtS15UaVSBEaE+iln2LVpAuGc= +github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= @@ -588,7 +590,6 @@ github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmF github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= -github.com/willf/bitset v1.1.11 h1:N7Z7E9UvjW+sGsEl7k/SJrvY2reP1A07MrGuCjIOjRE= github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= diff --git a/vendor/github.com/containers/storage/layers.go b/vendor/github.com/containers/storage/layers.go index 9b05474bb..fa0dce033 100644 --- a/vendor/github.com/containers/storage/layers.go +++ b/vendor/github.com/containers/storage/layers.go @@ -271,21 +271,22 @@ type LayerStore interface { } type layerStore struct { - lockfile Locker - mountsLockfile Locker - rundir string - driver drivers.Driver - layerdir string - layers []*Layer - idindex *truncindex.TruncIndex - byid map[string]*Layer - byname map[string]*Layer - bymount map[string]*Layer - bycompressedsum map[digest.Digest][]string - byuncompressedsum map[digest.Digest][]string - uidMap []idtools.IDMap - gidMap []idtools.IDMap - loadMut sync.Mutex + lockfile Locker + mountsLockfile Locker + rundir string + driver drivers.Driver + layerdir string + layers []*Layer + idindex *truncindex.TruncIndex + byid map[string]*Layer + byname map[string]*Layer + bymount map[string]*Layer + bycompressedsum map[digest.Digest][]string + byuncompressedsum map[digest.Digest][]string + uidMap []idtools.IDMap + gidMap []idtools.IDMap + loadMut sync.Mutex + layerspathModified time.Time } func copyLayer(l *Layer) *Layer { @@ -1744,7 +1745,7 @@ func (r *layerStore) Touch() error { } func (r *layerStore) Modified() (bool, error) { - var mmodified bool + var mmodified, tmodified bool lmodified, err := r.lockfile.Modified() if err != nil { return lmodified, err @@ -1757,7 +1758,23 @@ func (r *layerStore) Modified() (bool, error) { return lmodified, err } } - return lmodified || mmodified, nil + + if lmodified || mmodified { + return true, nil + } + + // If the layers.json file has been modified manually, then we have to + // reload the storage in any case. + info, err := os.Stat(r.layerspath()) + if err != nil && !os.IsNotExist(err) { + return false, errors.Wrap(err, "stat layers file") + } + if info != nil { + tmodified = info.ModTime() != r.layerspathModified + r.layerspathModified = info.ModTime() + } + + return tmodified, nil } func (r *layerStore) IsReadWrite() bool { diff --git a/vendor/github.com/containers/storage/pkg/lockfile/lockfile_unix.go b/vendor/github.com/containers/storage/pkg/lockfile/lockfile_unix.go index 0a92da2c0..f0e46b6b6 100644 --- a/vendor/github.com/containers/storage/pkg/lockfile/lockfile_unix.go +++ b/vendor/github.com/containers/storage/pkg/lockfile/lockfile_unix.go @@ -194,11 +194,7 @@ func (l *lockfile) Touch() error { defer l.stateMutex.Unlock() l.lw = stringid.GenerateRandomID() id := []byte(l.lw) - _, err := unix.Seek(int(l.fd), 0, os.SEEK_SET) - if err != nil { - return err - } - n, err := unix.Write(int(l.fd), id) + n, err := unix.Pwrite(int(l.fd), id, 0) if err != nil { return err } @@ -217,11 +213,7 @@ func (l *lockfile) Modified() (bool, error) { panic("attempted to check last-writer in lockfile without locking it first") } defer l.stateMutex.Unlock() - _, err := unix.Seek(int(l.fd), 0, os.SEEK_SET) - if err != nil { - return true, err - } - n, err := unix.Read(int(l.fd), id) + n, err := unix.Pread(int(l.fd), id, 0) if err != nil { return true, err } diff --git a/vendor/github.com/containers/storage/store.go b/vendor/github.com/containers/storage/store.go index d6d547c64..dc6eaafa2 100644 --- a/vendor/github.com/containers/storage/store.go +++ b/vendor/github.com/containers/storage/store.go @@ -937,7 +937,7 @@ func (s *store) ContainerStore() (ContainerStore, error) { } func (s *store) canUseShifting(uidmap, gidmap []idtools.IDMap) bool { - if !s.graphDriver.SupportsShifting() { + if s.graphDriver == nil || !s.graphDriver.SupportsShifting() { return false } if uidmap != nil && !idtools.IsContiguous(uidmap) { @@ -2668,6 +2668,10 @@ func (s *store) mount(id string, options drivers.MountOpts) (string, error) { s.lastLoaded = time.Now() } + if options.UidMaps != nil || options.GidMaps != nil { + options.DisableShifting = !s.canUseShifting(options.UidMaps, options.GidMaps) + } + if rlstore.Exists(id) { return rlstore.Mount(id, options) } @@ -2708,7 +2712,6 @@ func (s *store) Mount(id, mountLabel string) (string, error) { options.Volatile = v.(bool) } } - options.DisableShifting = !s.canUseShifting(container.UIDMap, container.GIDMap) } return s.mount(id, options) } diff --git a/vendor/github.com/containers/storage/types/default_override_test.conf b/vendor/github.com/containers/storage/types/default_override_test.conf new file mode 100644 index 000000000..caa537ba9 --- /dev/null +++ b/vendor/github.com/containers/storage/types/default_override_test.conf @@ -0,0 +1,11 @@ +[storage] + +# Default Storage Driver +driver = "" + +# Primary Read/Write location of container storage +graphroot = "environment_override_graphroot" + +# Storage path for rootless users +# +rootless_storage_path = "environment_override_rootless_storage_path" diff --git a/vendor/github.com/containers/storage/types/utils.go b/vendor/github.com/containers/storage/types/utils.go index d2dca7b68..4d62b151a 100644 --- a/vendor/github.com/containers/storage/types/utils.go +++ b/vendor/github.com/containers/storage/types/utils.go @@ -160,7 +160,14 @@ func expandEnvPath(path string, rootlessUID int) (string, error) { } func DefaultConfigFile(rootless bool) (string, error) { - if defaultConfigFileSet || !rootless { + if defaultConfigFileSet { + return defaultConfigFile, nil + } + + if path, ok := os.LookupEnv("CONTAINERS_STORAGE_CONF"); ok { + return path, nil + } + if !rootless { return defaultConfigFile, nil } diff --git a/vendor/github.com/cri-o/ocicni/pkg/ocicni/ocicni.go b/vendor/github.com/cri-o/ocicni/pkg/ocicni/ocicni.go index b38340126..90d5b6c50 100644 --- a/vendor/github.com/cri-o/ocicni/pkg/ocicni/ocicni.go +++ b/vendor/github.com/cri-o/ocicni/pkg/ocicni/ocicni.go @@ -195,16 +195,21 @@ func (plugin *cniNetworkPlugin) monitorConfDir(start *sync.WaitGroup) { // If defaultNetName is empty, CNI config files should be reloaded real-time and // defaultNetName should be changeable and determined by file sorting. func InitCNI(defaultNetName string, confDir string, binDirs ...string) (CNIPlugin, error) { - return initCNI(nil, "", defaultNetName, confDir, binDirs...) + return initCNI(nil, "", defaultNetName, confDir, true, binDirs...) } // InitCNIWithCache works like InitCNI except that it takes the cni cache directory as third param. func InitCNIWithCache(defaultNetName, confDir, cacheDir string, binDirs ...string) (CNIPlugin, error) { - return initCNI(nil, cacheDir, defaultNetName, confDir, binDirs...) + return initCNI(nil, cacheDir, defaultNetName, confDir, true, binDirs...) +} + +// InitCNINoInotify works like InitCNI except that it does not use inotify to watch for changes in the CNI config dir. +func InitCNINoInotify(defaultNetName, confDir, cacheDir string, binDirs ...string) (CNIPlugin, error) { + return initCNI(nil, cacheDir, defaultNetName, confDir, false, binDirs...) } // Internal function to allow faking out exec functions for testing -func initCNI(exec cniinvoke.Exec, cacheDir, defaultNetName string, confDir string, binDirs ...string) (CNIPlugin, error) { +func initCNI(exec cniinvoke.Exec, cacheDir, defaultNetName string, confDir string, useInotify bool, binDirs ...string) (CNIPlugin, error) { if confDir == "" { confDir = DefaultConfDir } @@ -245,22 +250,26 @@ func initCNI(exec cniinvoke.Exec, cacheDir, defaultNetName string, confDir strin plugin.syncNetworkConfig() - plugin.watcher, err = newWatcher(plugin.confDir) - if err != nil { - return nil, err - } + if useInotify { + plugin.watcher, err = newWatcher(plugin.confDir) + if err != nil { + return nil, err + } - startWg := sync.WaitGroup{} - startWg.Add(1) - go plugin.monitorConfDir(&startWg) - startWg.Wait() + startWg := sync.WaitGroup{} + startWg.Add(1) + go plugin.monitorConfDir(&startWg) + startWg.Wait() + } return plugin, nil } func (plugin *cniNetworkPlugin) Shutdown() error { close(plugin.shutdownChan) - plugin.watcher.Close() + if plugin.watcher != nil { + plugin.watcher.Close() + } plugin.done.Wait() return nil } @@ -539,10 +548,11 @@ func (plugin *cniNetworkPlugin) SetUpPodWithContext(ctx context.Context, podNetw results := make([]NetResult, 0) if err := plugin.forEachNetwork(&podNetwork, false, func(network *cniNetwork, podNetwork *PodNetwork, rt *libcni.RuntimeConf) error { + fullPodName := buildFullPodName(*podNetwork) + logrus.Infof("Adding pod %s to CNI network %q (type=%v)", fullPodName, network.name, network.config.Plugins[0].Network.Type) result, err := network.addToNetwork(ctx, rt, plugin.cniConfig) if err != nil { - logrus.Errorf("Error while adding pod to CNI network %q: %s", network.name, err) - return err + return fmt.Errorf("error adding pod %s to CNI network %q: %v", fullPodName, network.name, err) } results = append(results, NetResult{ Result: result, @@ -654,8 +664,10 @@ func (plugin *cniNetworkPlugin) TearDownPodWithContext(ctx context.Context, podN } return plugin.forEachNetwork(&podNetwork, true, func(network *cniNetwork, podNetwork *PodNetwork, rt *libcni.RuntimeConf) error { + fullPodName := buildFullPodName(*podNetwork) + logrus.Infof("Deleting pod %s from CNI network %q (type=%v)", fullPodName, network.name, network.config.Plugins[0].Network.Type) if err := network.deleteFromNetwork(ctx, rt, plugin.cniConfig); err != nil { - return fmt.Errorf("Error while removing pod from CNI network %q: %s", network.name, err) + return fmt.Errorf("error removing pod %s from CNI network %q: %v", fullPodName, network.name, err) } return nil }) @@ -680,10 +692,11 @@ func (plugin *cniNetworkPlugin) GetPodNetworkStatusWithContext(ctx context.Conte results := make([]NetResult, 0) if err := plugin.forEachNetwork(&podNetwork, true, func(network *cniNetwork, podNetwork *PodNetwork, rt *libcni.RuntimeConf) error { + fullPodName := buildFullPodName(*podNetwork) + logrus.Infof("Checking pod %s for CNI network %s (type=%v)", fullPodName, network.name, network.config.Plugins[0].Network.Type) result, err := network.checkNetwork(ctx, rt, plugin.cniConfig, plugin.nsManager, podNetwork.NetNS) if err != nil { - logrus.Errorf("Error while checking pod to CNI network %q: %s", network.name, err) - return err + return fmt.Errorf("error checking pod %s for CNI network %q: %v", fullPodName, network.name, err) } if result != nil { results = append(results, NetResult{ @@ -703,19 +716,10 @@ func (plugin *cniNetworkPlugin) GetPodNetworkStatusWithContext(ctx context.Conte } func (network *cniNetwork) addToNetwork(ctx context.Context, rt *libcni.RuntimeConf, cni *libcni.CNIConfig) (cnitypes.Result, error) { - logrus.Infof("About to add CNI network %s (type=%v)", network.name, network.config.Plugins[0].Network.Type) - res, err := cni.AddNetworkList(ctx, network.config, rt) - if err != nil { - logrus.Errorf("Error adding network: %v", err) - return nil, err - } - - return res, nil + return cni.AddNetworkList(ctx, network.config, rt) } func (network *cniNetwork) checkNetwork(ctx context.Context, rt *libcni.RuntimeConf, cni *libcni.CNIConfig, nsManager *nsManager, netns string) (cnitypes.Result, error) { - logrus.Infof("About to check CNI network %s (type=%v)", network.name, network.config.Plugins[0].Network.Type) - gtet, err := cniversion.GreaterThanOrEqualTo(network.config.CNIVersion, "0.4.0") if err != nil { return nil, err @@ -786,11 +790,7 @@ func (network *cniNetwork) checkNetwork(ctx context.Context, rt *libcni.RuntimeC } func (network *cniNetwork) deleteFromNetwork(ctx context.Context, rt *libcni.RuntimeConf, cni *libcni.CNIConfig) error { - logrus.Infof("About to del CNI network %s (type=%v)", network.name, network.config.Plugins[0].Network.Type) - if err := cni.DelNetworkList(ctx, network.config, rt); err != nil { - return err - } - return nil + return cni.DelNetworkList(ctx, network.config, rt) } func buildCNIRuntimeConf(podNetwork *PodNetwork, ifName string, runtimeConfig RuntimeConfig) (*libcni.RuntimeConf, error) { @@ -809,6 +809,13 @@ func buildCNIRuntimeConf(podNetwork *PodNetwork, ifName string, runtimeConfig Ru CapabilityArgs: map[string]interface{}{}, } + // Propagate existing CNI_ARGS to non-k8s consumers + for _, kvpairs := range strings.Split(os.Getenv("CNI_ARGS"), ";") { + if keyval := strings.SplitN(kvpairs, "=", 2); len(keyval) == 2 { + rt.Args = append(rt.Args, [2]string{keyval[0], keyval[1]}) + } + } + // Add requested static IP to CNI_ARGS ip := runtimeConfig.IP if ip != "" { diff --git a/vendor/github.com/docker/docker-credential-helpers/client/command.go b/vendor/github.com/docker/docker-credential-helpers/client/command.go index 8da334306..0183c0639 100644 --- a/vendor/github.com/docker/docker-credential-helpers/client/command.go +++ b/vendor/github.com/docker/docker-credential-helpers/client/command.go @@ -4,7 +4,8 @@ import ( "fmt" "io" "os" - "os/exec" + + exec "golang.org/x/sys/execabs" ) // Program is an interface to execute external programs. diff --git a/vendor/github.com/docker/docker-credential-helpers/credentials/version.go b/vendor/github.com/docker/docker-credential-helpers/credentials/version.go index c2cc3e2e0..185e36796 100644 --- a/vendor/github.com/docker/docker-credential-helpers/credentials/version.go +++ b/vendor/github.com/docker/docker-credential-helpers/credentials/version.go @@ -1,4 +1,4 @@ package credentials // Version holds a string describing the current version -const Version = "0.6.3" +const Version = "0.6.4" diff --git a/vendor/github.com/imdario/mergo/.travis.yml b/vendor/github.com/imdario/mergo/.travis.yml index dad29725f..d324c43ba 100644 --- a/vendor/github.com/imdario/mergo/.travis.yml +++ b/vendor/github.com/imdario/mergo/.travis.yml @@ -1,4 +1,7 @@ language: go +arch: + - amd64 + - ppc64le install: - go get -t - go get golang.org/x/tools/cmd/cover diff --git a/vendor/github.com/imdario/mergo/README.md b/vendor/github.com/imdario/mergo/README.md index 876abb500..aa8cbd7ce 100644 --- a/vendor/github.com/imdario/mergo/README.md +++ b/vendor/github.com/imdario/mergo/README.md @@ -97,7 +97,7 @@ If Mergo is useful to you, consider buying me a coffee, a beer, or making a mont - [mantasmatelis/whooplist-server](https://github.com/mantasmatelis/whooplist-server) - [jnuthong/item_search](https://github.com/jnuthong/item_search) - [bukalapak/snowboard](https://github.com/bukalapak/snowboard) -- [janoszen/containerssh](https://github.com/janoszen/containerssh) +- [containerssh/containerssh](https://github.com/containerssh/containerssh) ## Install diff --git a/vendor/github.com/imdario/mergo/merge.go b/vendor/github.com/imdario/mergo/merge.go index afa84a1e2..8c2a8fcd9 100644 --- a/vendor/github.com/imdario/mergo/merge.go +++ b/vendor/github.com/imdario/mergo/merge.go @@ -95,13 +95,18 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, co } } } else { - if (isReflectNil(dst) || overwrite) && (!isEmptyValue(src) || overwriteWithEmptySrc) { + if dst.CanSet() && (isReflectNil(dst) || overwrite) && (!isEmptyValue(src) || overwriteWithEmptySrc) { dst.Set(src) } } case reflect.Map: if dst.IsNil() && !src.IsNil() { - dst.Set(reflect.MakeMap(dst.Type())) + if dst.CanSet() { + dst.Set(reflect.MakeMap(dst.Type())) + } else { + dst = src + return + } } if src.Kind() != reflect.Map { diff --git a/vendor/github.com/jinzhu/copier/README.md b/vendor/github.com/jinzhu/copier/README.md index cff72405c..ec04b4be0 100644 --- a/vendor/github.com/jinzhu/copier/README.md +++ b/vendor/github.com/jinzhu/copier/README.md @@ -27,9 +27,10 @@ import ( ) type User struct { - Name string - Role string - Age int32 + Name string + Role string + Age int32 + EmployeCode int64 `copier:"EmployeNum"` // specify field name // Explicitly ignored in the destination struct. Salary int @@ -52,7 +53,7 @@ type Employee struct { Salary int `copier:"-"` DoubleAge int32 - EmployeId int64 + EmployeId int64 `copier:"EmployeNum"` // specify field name SuperRole string } diff --git a/vendor/github.com/jinzhu/copier/copier.go b/vendor/github.com/jinzhu/copier/copier.go index 72bf65c78..412ff5497 100644 --- a/vendor/github.com/jinzhu/copier/copier.go +++ b/vendor/github.com/jinzhu/copier/copier.go @@ -3,9 +3,11 @@ package copier import ( "database/sql" "database/sql/driver" + "errors" "fmt" "reflect" "strings" + "unicode" ) // These flags define options for tag handling @@ -32,6 +34,19 @@ type Option struct { DeepCopy bool } +// Tag Flags +type flags struct { + BitFlags map[string]uint8 + SrcNames tagNameMapping + DestNames tagNameMapping +} + +// Field Tag name mapping +type tagNameMapping struct { + FieldNameToTag map[string]string + TagToFieldName map[string]string +} + // Copy copy things func Copy(toValue interface{}, fromValue interface{}) (err error) { return copier(toValue, fromValue, Option{}) @@ -134,7 +149,8 @@ func copier(toValue interface{}, fromValue interface{}, opt Option) (err error) } if !set(to.Index(i), from.Index(i), opt.DeepCopy) { - err = CopyWithOption(to.Index(i).Addr().Interface(), from.Index(i).Interface(), opt) + // ignore error while copy slice element + err = copier(to.Index(i).Addr().Interface(), from.Index(i).Interface(), opt) if err != nil { continue } @@ -148,7 +164,7 @@ func copier(toValue interface{}, fromValue interface{}, opt Option) (err error) return } - if to.Kind() == reflect.Slice { + if from.Kind() == reflect.Slice || to.Kind() == reflect.Slice { isSlice = true if from.Kind() == reflect.Slice { amount = from.Len() @@ -180,9 +196,9 @@ func copier(toValue interface{}, fromValue interface{}, opt Option) (err error) } // Get tag options - tagBitFlags := map[string]uint8{} - if dest.IsValid() { - tagBitFlags = getBitFlags(toType) + flgs, err := getFlags(dest, source, toType, fromType) + if err != nil { + return err } // check source @@ -193,17 +209,18 @@ func copier(toValue interface{}, fromValue interface{}, opt Option) (err error) name := field.Name // Get bit flags for field - fieldFlags, _ := tagBitFlags[name] + fieldFlags, _ := flgs.BitFlags[name] // Check if we should ignore copying if (fieldFlags & tagIgnore) != 0 { continue } - if fromField := source.FieldByName(name); fromField.IsValid() && !shouldIgnore(fromField, opt.IgnoreEmpty) { + srcFieldName, destFieldName := getFieldName(name, flgs) + if fromField := source.FieldByName(srcFieldName); fromField.IsValid() && !shouldIgnore(fromField, opt.IgnoreEmpty) { // process for nested anonymous field destFieldNotSet := false - if f, ok := dest.Type().FieldByName(name); ok { + if f, ok := dest.Type().FieldByName(destFieldName); ok { for idx := range f.Index { destField := dest.FieldByIndex(f.Index[:idx+1]) @@ -229,7 +246,7 @@ func copier(toValue interface{}, fromValue interface{}, opt Option) (err error) break } - toField := dest.FieldByName(name) + toField := dest.FieldByName(destFieldName) if toField.IsValid() { if toField.CanSet() { if !set(toField, fromField, opt.DeepCopy) { @@ -239,16 +256,16 @@ func copier(toValue interface{}, fromValue interface{}, opt Option) (err error) } if fieldFlags != 0 { // Note that a copy was made - tagBitFlags[name] = fieldFlags | hasCopied + flgs.BitFlags[name] = fieldFlags | hasCopied } } } else { // try to set to method var toMethod reflect.Value if dest.CanAddr() { - toMethod = dest.Addr().MethodByName(name) + toMethod = dest.Addr().MethodByName(destFieldName) } else { - toMethod = dest.MethodByName(name) + toMethod = dest.MethodByName(destFieldName) } if toMethod.IsValid() && toMethod.Type().NumIn() == 1 && fromField.Type().AssignableTo(toMethod.Type().In(0)) { @@ -261,16 +278,17 @@ func copier(toValue interface{}, fromValue interface{}, opt Option) (err error) // Copy from from method to dest field for _, field := range deepFields(toType) { name := field.Name + srcFieldName, destFieldName := getFieldName(name, flgs) var fromMethod reflect.Value if source.CanAddr() { - fromMethod = source.Addr().MethodByName(name) + fromMethod = source.Addr().MethodByName(srcFieldName) } else { - fromMethod = source.MethodByName(name) + fromMethod = source.MethodByName(srcFieldName) } if fromMethod.IsValid() && fromMethod.Type().NumIn() == 0 && fromMethod.Type().NumOut() == 1 && !shouldIgnore(fromMethod, opt.IgnoreEmpty) { - if toField := dest.FieldByName(name); toField.IsValid() && toField.CanSet() { + if toField := dest.FieldByName(destFieldName); toField.IsValid() && toField.CanSet() { values := fromMethod.Call([]reflect.Value{}) if len(values) >= 1 { set(toField, values[0], opt.DeepCopy) @@ -280,25 +298,37 @@ func copier(toValue interface{}, fromValue interface{}, opt Option) (err error) } } - if isSlice { + if isSlice && to.Kind() == reflect.Slice { if dest.Addr().Type().AssignableTo(to.Type().Elem()) { if to.Len() < i+1 { to.Set(reflect.Append(to, dest.Addr())) } else { - set(to.Index(i), dest.Addr(), opt.DeepCopy) + if !set(to.Index(i), dest.Addr(), opt.DeepCopy) { + // ignore error while copy slice element + err = copier(to.Index(i).Addr().Interface(), dest.Addr().Interface(), opt) + if err != nil { + continue + } + } } } else if dest.Type().AssignableTo(to.Type().Elem()) { if to.Len() < i+1 { to.Set(reflect.Append(to, dest)) } else { - set(to.Index(i), dest, opt.DeepCopy) + if !set(to.Index(i), dest, opt.DeepCopy) { + // ignore error while copy slice element + err = copier(to.Index(i).Addr().Interface(), dest.Interface(), opt) + if err != nil { + continue + } + } } } } else if initDest { to.Set(dest) } - err = checkBitFlags(tagBitFlags) + err = checkBitFlags(flgs.BitFlags) } return @@ -432,46 +462,90 @@ func set(to, from reflect.Value, deepCopy bool) bool { } // parseTags Parses struct tags and returns uint8 bit flags. -func parseTags(tag string) (flags uint8) { +func parseTags(tag string) (flg uint8, name string, err error) { for _, t := range strings.Split(tag, ",") { switch t { case "-": - flags = tagIgnore + flg = tagIgnore return case "must": - flags = flags | tagMust + flg = flg | tagMust case "nopanic": - flags = flags | tagNoPanic + flg = flg | tagNoPanic + default: + if unicode.IsUpper([]rune(t)[0]) { + name = strings.TrimSpace(t) + } else { + err = errors.New("copier field name tag must be start upper case") + } } } return } -// getBitFlags Parses struct tags for bit flags. -func getBitFlags(toType reflect.Type) map[string]uint8 { - flags := map[string]uint8{} - toTypeFields := deepFields(toType) +// getTagFlags Parses struct tags for bit flags, field name. +func getFlags(dest, src reflect.Value, toType, fromType reflect.Type) (flags, error) { + flgs := flags{ + BitFlags: map[string]uint8{}, + SrcNames: tagNameMapping{ + FieldNameToTag: map[string]string{}, + TagToFieldName: map[string]string{}, + }, + DestNames: tagNameMapping{ + FieldNameToTag: map[string]string{}, + TagToFieldName: map[string]string{}, + }, + } + var toTypeFields, fromTypeFields []reflect.StructField + if dest.IsValid() { + toTypeFields = deepFields(toType) + } + if src.IsValid() { + fromTypeFields = deepFields(fromType) + } // Get a list dest of tags for _, field := range toTypeFields { tags := field.Tag.Get("copier") if tags != "" { - flags[field.Name] = parseTags(tags) + var name string + var err error + if flgs.BitFlags[field.Name], name, err = parseTags(tags); err != nil { + return flags{}, err + } else if name != "" { + flgs.DestNames.FieldNameToTag[field.Name] = name + flgs.DestNames.TagToFieldName[name] = field.Name + } + } + } + + // Get a list source of tags + for _, field := range fromTypeFields { + tags := field.Tag.Get("copier") + if tags != "" { + var name string + var err error + if _, name, err = parseTags(tags); err != nil { + return flags{}, err + } else if name != "" { + flgs.SrcNames.FieldNameToTag[field.Name] = name + flgs.SrcNames.TagToFieldName[name] = field.Name + } } } - return flags + return flgs, nil } // checkBitFlags Checks flags for error or panic conditions. func checkBitFlags(flagsList map[string]uint8) (err error) { // Check flag conditions were met - for name, flags := range flagsList { - if flags&hasCopied == 0 { + for name, flgs := range flagsList { + if flgs&hasCopied == 0 { switch { - case flags&tagMust != 0 && flags&tagNoPanic != 0: + case flgs&tagMust != 0 && flgs&tagNoPanic != 0: err = fmt.Errorf("field %s has must tag but was not copied", name) return - case flags&(tagMust) != 0: + case flgs&(tagMust) != 0: panic(fmt.Sprintf("Field %s has must tag but was not copied", name)) } } @@ -479,6 +553,40 @@ func checkBitFlags(flagsList map[string]uint8) (err error) { return } +func getFieldName(fieldName string, flgs flags) (srcFieldName string, destFieldName string) { + // get dest field name + if srcTagName, ok := flgs.SrcNames.FieldNameToTag[fieldName]; ok { + destFieldName = srcTagName + if destTagName, ok := flgs.DestNames.TagToFieldName[srcTagName]; ok { + destFieldName = destTagName + } + } else { + if destTagName, ok := flgs.DestNames.TagToFieldName[fieldName]; ok { + destFieldName = destTagName + } + } + if destFieldName == "" { + destFieldName = fieldName + } + + // get source field name + if destTagName, ok := flgs.DestNames.FieldNameToTag[fieldName]; ok { + srcFieldName = destTagName + if srcField, ok := flgs.SrcNames.TagToFieldName[destTagName]; ok { + srcFieldName = srcField + } + } else { + if srcField, ok := flgs.SrcNames.TagToFieldName[fieldName]; ok { + srcFieldName = srcField + } + } + + if srcFieldName == "" { + srcFieldName = fieldName + } + return +} + func driverValuer(v reflect.Value) (i driver.Valuer, ok bool) { if !v.CanAddr() { diff --git a/vendor/github.com/klauspost/compress/zstd/blockdec.go b/vendor/github.com/klauspost/compress/zstd/blockdec.go index 6cea054d2..8a98c4562 100644 --- a/vendor/github.com/klauspost/compress/zstd/blockdec.go +++ b/vendor/github.com/klauspost/compress/zstd/blockdec.go @@ -144,7 +144,7 @@ func (b *blockDec) reset(br byteBuffer, windowSize uint64) error { } cSize = 1 case blockTypeCompressed: - if debug { + if debugDecoder { println("Data size on stream:", cSize) } b.RLESize = 0 @@ -153,7 +153,7 @@ func (b *blockDec) reset(br byteBuffer, windowSize uint64) error { maxSize = int(windowSize) } if cSize > maxCompressedBlockSize || uint64(cSize) > b.WindowSize { - if debug { + if debugDecoder { printf("compressed block too big: csize:%d block: %+v\n", uint64(cSize), b) } return ErrCompressedSizeTooBig @@ -168,10 +168,10 @@ func (b *blockDec) reset(br byteBuffer, windowSize uint64) error { // Read block data. if cap(b.dataStorage) < cSize { - if b.lowMem { + if b.lowMem || cSize > maxCompressedBlockSize { b.dataStorage = make([]byte, 0, cSize) } else { - b.dataStorage = make([]byte, 0, maxBlockSize) + b.dataStorage = make([]byte, 0, maxCompressedBlockSize) } } if cap(b.dst) <= maxSize { @@ -179,7 +179,7 @@ func (b *blockDec) reset(br byteBuffer, windowSize uint64) error { } b.data, err = br.readBig(cSize, b.dataStorage) if err != nil { - if debug { + if debugDecoder { println("Reading block:", err, "(", cSize, ")", len(b.data)) printf("%T", br) } @@ -249,7 +249,7 @@ func (b *blockDec) startDecoder() { b: b.dst, err: err, } - if debug { + if debugDecoder { println("Decompressed to", len(b.dst), "bytes, error:", err) } b.result <- o @@ -264,7 +264,7 @@ func (b *blockDec) startDecoder() { default: panic("Invalid block type") } - if debug { + if debugDecoder { println("blockDec: Finished block") } } @@ -297,7 +297,7 @@ func (b *blockDec) decodeBuf(hist *history) error { b.dst = hist.b hist.b = nil err := b.decodeCompressed(hist) - if debug { + if debugDecoder { println("Decompressed to total", len(b.dst), "bytes, hash:", xxhash.Sum64(b.dst), "error:", err) } hist.b = b.dst @@ -390,7 +390,7 @@ func (b *blockDec) decodeCompressed(hist *history) error { in = in[5:] } } - if debug { + if debugDecoder { println("literals type:", litType, "litRegenSize:", litRegenSize, "litCompSize:", litCompSize, "sizeFormat:", sizeFormat, "4X:", fourStreams) } var literals []byte @@ -428,7 +428,7 @@ func (b *blockDec) decodeCompressed(hist *history) error { literals[i] = v } in = in[1:] - if debug { + if debugDecoder { printf("Found %d RLE compressed literals\n", litRegenSize) } case literalsBlockTreeless: @@ -439,7 +439,7 @@ func (b *blockDec) decodeCompressed(hist *history) error { // Store compressed literals, so we defer decoding until we get history. literals = in[:litCompSize] in = in[litCompSize:] - if debug { + if debugDecoder { printf("Found %d compressed literals\n", litCompSize) } case literalsBlockCompressed: @@ -481,7 +481,7 @@ func (b *blockDec) decodeCompressed(hist *history) error { if len(literals) != litRegenSize { return fmt.Errorf("literal output size mismatch want %d, got %d", litRegenSize, len(literals)) } - if debug { + if debugDecoder { printf("Decompressed %d literals into %d bytes\n", litCompSize, litRegenSize) } } @@ -532,12 +532,12 @@ func (b *blockDec) decodeCompressed(hist *history) error { br := byteReader{b: in, off: 0} compMode := br.Uint8() br.advance(1) - if debug { + if debugDecoder { printf("Compression modes: 0b%b", compMode) } for i := uint(0); i < 3; i++ { mode := seqCompMode((compMode >> (6 - i*2)) & 3) - if debug { + if debugDecoder { println("Table", tableIndex(i), "is", mode) } var seq *sequenceDec @@ -568,7 +568,7 @@ func (b *blockDec) decodeCompressed(hist *history) error { } dec.setRLE(symb) seq.fse = dec - if debug { + if debugDecoder { printf("RLE set to %+v, code: %v", symb, v) } case compModeFSE: @@ -584,7 +584,7 @@ func (b *blockDec) decodeCompressed(hist *history) error { println("Transform table error:", err) return err } - if debug { + if debugDecoder { println("Read table ok", "symbolLen:", dec.symbolLen) } seq.fse = dec @@ -652,7 +652,7 @@ func (b *blockDec) decodeCompressed(hist *history) error { if huff != nil { hist.huffTree = huff } - if debug { + if debugDecoder { println("Final literals:", len(literals), "hash:", xxhash.Sum64(literals), "and", nSeqs, "sequences.") } @@ -669,7 +669,7 @@ func (b *blockDec) decodeCompressed(hist *history) error { if err != nil { return err } - if debug { + if debugDecoder { println("History merged ok") } br := &bitReader{} @@ -728,7 +728,7 @@ func (b *blockDec) decodeCompressed(hist *history) error { } hist.append(b.dst) hist.recentOffsets = seqs.prevOffset - if debug { + if debugDecoder { println("Finished block with literals:", len(literals), "and", nSeqs, "sequences.") } diff --git a/vendor/github.com/klauspost/compress/zstd/blockenc.go b/vendor/github.com/klauspost/compress/zstd/blockenc.go index e1be092f3..3df185ee4 100644 --- a/vendor/github.com/klauspost/compress/zstd/blockenc.go +++ b/vendor/github.com/klauspost/compress/zstd/blockenc.go @@ -156,7 +156,7 @@ func (h *literalsHeader) setSize(regenLen int) { switch { case inBits < 5: lh |= (uint64(regenLen) << 3) | (1 << 60) - if debug { + if debugEncoder { got := int(lh>>3) & 0xff if got != regenLen { panic(fmt.Sprint("litRegenSize = ", regenLen, "(want) != ", got, "(got)")) @@ -184,7 +184,7 @@ func (h *literalsHeader) setSizes(compLen, inLen int, single bool) { lh |= 1 << 2 } lh |= (uint64(inLen) << 4) | (uint64(compLen) << (10 + 4)) | (3 << 60) - if debug { + if debugEncoder { const mmask = (1 << 24) - 1 n := (lh >> 4) & mmask if int(n&1023) != inLen { @@ -312,7 +312,7 @@ func (b *blockEnc) encodeRaw(a []byte) { bh.setType(blockTypeRaw) b.output = bh.appendTo(b.output[:0]) b.output = append(b.output, a...) - if debug { + if debugEncoder { println("Adding RAW block, length", len(a), "last:", b.last) } } @@ -325,7 +325,7 @@ func (b *blockEnc) encodeRawTo(dst, src []byte) []byte { bh.setType(blockTypeRaw) dst = bh.appendTo(dst) dst = append(dst, src...) - if debug { + if debugEncoder { println("Adding RAW block, length", len(src), "last:", b.last) } return dst @@ -339,7 +339,7 @@ func (b *blockEnc) encodeLits(lits []byte, raw bool) error { // Don't compress extremely small blocks if len(lits) < 8 || (len(lits) < 32 && b.dictLitEnc == nil) || raw { - if debug { + if debugEncoder { println("Adding RAW block, length", len(lits), "last:", b.last) } bh.setType(blockTypeRaw) @@ -371,7 +371,7 @@ func (b *blockEnc) encodeLits(lits []byte, raw bool) error { switch err { case huff0.ErrIncompressible: - if debug { + if debugEncoder { println("Adding RAW block, length", len(lits), "last:", b.last) } bh.setType(blockTypeRaw) @@ -379,7 +379,7 @@ func (b *blockEnc) encodeLits(lits []byte, raw bool) error { b.output = append(b.output, lits...) return nil case huff0.ErrUseRLE: - if debug { + if debugEncoder { println("Adding RLE block, length", len(lits)) } bh.setType(blockTypeRLE) @@ -396,12 +396,12 @@ func (b *blockEnc) encodeLits(lits []byte, raw bool) error { bh.setType(blockTypeCompressed) var lh literalsHeader if reUsed { - if debug { + if debugEncoder { println("Reused tree, compressed to", len(out)) } lh.setType(literalsBlockTreeless) } else { - if debug { + if debugEncoder { println("New tree, compressed to", len(out), "tree size:", len(b.litEnc.OutTable)) } lh.setType(literalsBlockCompressed) @@ -517,7 +517,7 @@ func (b *blockEnc) encode(org []byte, raw, rawAllLits bool) error { lh.setSize(len(b.literals)) b.output = lh.appendTo(b.output) b.output = append(b.output, b.literals...) - if debug { + if debugEncoder { println("Adding literals RAW, length", len(b.literals)) } case huff0.ErrUseRLE: @@ -525,22 +525,22 @@ func (b *blockEnc) encode(org []byte, raw, rawAllLits bool) error { lh.setSize(len(b.literals)) b.output = lh.appendTo(b.output) b.output = append(b.output, b.literals[0]) - if debug { + if debugEncoder { println("Adding literals RLE") } case nil: // Compressed litLen... if reUsed { - if debug { + if debugEncoder { println("reused tree") } lh.setType(literalsBlockTreeless) } else { - if debug { + if debugEncoder { println("new tree, size:", len(b.litEnc.OutTable)) } lh.setType(literalsBlockCompressed) - if debug { + if debugEncoder { _, _, err := huff0.ReadTable(out, nil) if err != nil { panic(err) @@ -548,18 +548,18 @@ func (b *blockEnc) encode(org []byte, raw, rawAllLits bool) error { } } lh.setSizes(len(out), len(b.literals), single) - if debug { + if debugEncoder { printf("Compressed %d literals to %d bytes", len(b.literals), len(out)) println("Adding literal header:", lh) } b.output = lh.appendTo(b.output) b.output = append(b.output, out...) b.litEnc.Reuse = huff0.ReusePolicyAllow - if debug { + if debugEncoder { println("Adding literals compressed") } default: - if debug { + if debugEncoder { println("Adding literals ERROR:", err) } return err @@ -577,7 +577,7 @@ func (b *blockEnc) encode(org []byte, raw, rawAllLits bool) error { n := len(b.sequences) - 0x7f00 b.output = append(b.output, 255, uint8(n), uint8(n>>8)) } - if debug { + if debugEncoder { println("Encoding", len(b.sequences), "sequences") } b.genCodes() @@ -611,17 +611,17 @@ func (b *blockEnc) encode(org []byte, raw, rawAllLits bool) error { nSize = nSize + (nSize+2*8*16)>>4 switch { case predefSize <= prevSize && predefSize <= nSize || forcePreDef: - if debug { + if debugEncoder { println("Using predefined", predefSize>>3, "<=", nSize>>3) } return preDef, compModePredefined case prevSize <= nSize: - if debug { + if debugEncoder { println("Using previous", prevSize>>3, "<=", nSize>>3) } return prev, compModeRepeat default: - if debug { + if debugEncoder { println("Using new, predef", predefSize>>3, ". previous:", prevSize>>3, ">", nSize>>3, "header max:", cur.maxHeaderSize()>>3, "bytes") println("tl:", cur.actualTableLog, "symbolLen:", cur.symbolLen, "norm:", cur.norm[:cur.symbolLen], "hist", cur.count[:cur.symbolLen]) } @@ -634,7 +634,7 @@ func (b *blockEnc) encode(org []byte, raw, rawAllLits bool) error { if llEnc.useRLE { mode |= uint8(compModeRLE) << 6 llEnc.setRLE(b.sequences[0].llCode) - if debug { + if debugEncoder { println("llEnc.useRLE") } } else { @@ -645,7 +645,7 @@ func (b *blockEnc) encode(org []byte, raw, rawAllLits bool) error { if ofEnc.useRLE { mode |= uint8(compModeRLE) << 4 ofEnc.setRLE(b.sequences[0].ofCode) - if debug { + if debugEncoder { println("ofEnc.useRLE") } } else { @@ -657,7 +657,7 @@ func (b *blockEnc) encode(org []byte, raw, rawAllLits bool) error { if mlEnc.useRLE { mode |= uint8(compModeRLE) << 2 mlEnc.setRLE(b.sequences[0].mlCode) - if debug { + if debugEncoder { println("mlEnc.useRLE, code: ", b.sequences[0].mlCode, "value", b.sequences[0].matchLen) } } else { @@ -666,7 +666,7 @@ func (b *blockEnc) encode(org []byte, raw, rawAllLits bool) error { mode |= uint8(m) << 2 } b.output = append(b.output, mode) - if debug { + if debugEncoder { printf("Compression modes: 0b%b", mode) } b.output, err = llEnc.writeCount(b.output) @@ -786,7 +786,7 @@ func (b *blockEnc) encode(org []byte, raw, rawAllLits bool) error { // Size is output minus block header. bh.setSize(uint32(len(b.output)-bhOffset) - 3) - if debug { + if debugEncoder { println("Rewriting block header", bh) } _ = bh.appendTo(b.output[bhOffset:bhOffset]) diff --git a/vendor/github.com/klauspost/compress/zstd/bytebuf.go b/vendor/github.com/klauspost/compress/zstd/bytebuf.go index 17e820a6a..aab71c6cf 100644 --- a/vendor/github.com/klauspost/compress/zstd/bytebuf.go +++ b/vendor/github.com/klauspost/compress/zstd/bytebuf.go @@ -91,7 +91,7 @@ func (r *readerWrapper) readSmall(n int) ([]byte, error) { if err == io.EOF { return nil, io.ErrUnexpectedEOF } - if debug { + if debugDecoder { println("readSmall: got", n2, "want", n, "err", err) } return nil, err diff --git a/vendor/github.com/klauspost/compress/zstd/decoder.go b/vendor/github.com/klauspost/compress/zstd/decoder.go index f593e464b..4d984c3b2 100644 --- a/vendor/github.com/klauspost/compress/zstd/decoder.go +++ b/vendor/github.com/klauspost/compress/zstd/decoder.go @@ -113,9 +113,6 @@ func NewReader(r io.Reader, opts ...DOption) (*Decoder, error) { // Returns the number of bytes written and any error that occurred. // When the stream is done, io.EOF will be returned. func (d *Decoder) Read(p []byte) (int, error) { - if d.stream == nil { - return 0, ErrDecoderNilInput - } var n int for { if len(d.current.b) > 0 { @@ -138,7 +135,7 @@ func (d *Decoder) Read(p []byte) (int, error) { } } if len(d.current.b) > 0 { - if debug { + if debugDecoder { println("returning", n, "still bytes left:", len(d.current.b)) } // Only return error at end of block @@ -147,7 +144,7 @@ func (d *Decoder) Read(p []byte) (int, error) { if d.current.err != nil { d.drainOutput() } - if debug { + if debugDecoder { println("returning", n, d.current.err, len(d.decoders)) } return n, d.current.err @@ -167,20 +164,17 @@ func (d *Decoder) Reset(r io.Reader) error { if r == nil { d.current.err = ErrDecoderNilInput + if len(d.current.b) > 0 { + d.current.b = d.current.b[:0] + } d.current.flushed = true return nil } - if d.stream == nil { - d.stream = make(chan decodeStream, 1) - d.streamWg.Add(1) - go d.startStreamDecoder(d.stream) - } - - // If bytes buffer and < 1MB, do sync decoding anyway. - if bb, ok := r.(byter); ok && bb.Len() < 1<<20 { + // If bytes buffer and < 5MB, do sync decoding anyway. + if bb, ok := r.(byter); ok && bb.Len() < 5<<20 { bb2 := bb - if debug { + if debugDecoder { println("*bytes.Buffer detected, doing sync decode, len:", bb.Len()) } b := bb2.Bytes() @@ -196,12 +190,18 @@ func (d *Decoder) Reset(r io.Reader) error { d.current.b = dst d.current.err = err d.current.flushed = true - if debug { + if debugDecoder { println("sync decode to", len(dst), "bytes, err:", err) } return nil } + if d.stream == nil { + d.stream = make(chan decodeStream, 1) + d.streamWg.Add(1) + go d.startStreamDecoder(d.stream) + } + // Remove current block. d.current.decodeOutput = decodeOutput{} d.current.err = nil @@ -225,7 +225,7 @@ func (d *Decoder) drainOutput() { d.current.cancel = nil } if d.current.d != nil { - if debug { + if debugDecoder { printf("re-adding current decoder %p, decoders: %d", d.current.d, len(d.decoders)) } d.decoders <- d.current.d @@ -238,7 +238,7 @@ func (d *Decoder) drainOutput() { } for v := range d.current.output { if v.d != nil { - if debug { + if debugDecoder { printf("re-adding decoder %p", v.d) } d.decoders <- v.d @@ -255,9 +255,6 @@ func (d *Decoder) drainOutput() { // The return value n is the number of bytes written. // Any error encountered during the write is also returned. func (d *Decoder) WriteTo(w io.Writer) (int64, error) { - if d.stream == nil { - return 0, ErrDecoderNilInput - } var n int64 for { if len(d.current.b) > 0 { @@ -297,7 +294,7 @@ func (d *Decoder) DecodeAll(input, dst []byte) ([]byte, error) { block := <-d.decoders frame := block.localFrame defer func() { - if debug { + if debugDecoder { printf("re-adding decoder: %p", block) } frame.rawInput = nil @@ -310,7 +307,7 @@ func (d *Decoder) DecodeAll(input, dst []byte) ([]byte, error) { frame.history.reset() err := frame.reset(&frame.bBuf) if err == io.EOF { - if debug { + if debugDecoder { println("frame reset return EOF") } return dst, nil @@ -355,7 +352,7 @@ func (d *Decoder) DecodeAll(input, dst []byte) ([]byte, error) { return dst, err } if len(frame.bBuf) == 0 { - if debug { + if debugDecoder { println("frame dbuf empty") } break @@ -371,7 +368,7 @@ func (d *Decoder) DecodeAll(input, dst []byte) ([]byte, error) { // if no data was available without blocking. func (d *Decoder) nextBlock(blocking bool) (ok bool) { if d.current.d != nil { - if debug { + if debugDecoder { printf("re-adding current decoder %p", d.current.d) } d.decoders <- d.current.d @@ -391,7 +388,7 @@ func (d *Decoder) nextBlock(blocking bool) (ok bool) { return false } } - if debug { + if debugDecoder { println("got", len(d.current.b), "bytes, error:", d.current.err) } return true @@ -485,7 +482,7 @@ func (d *Decoder) startStreamDecoder(inStream chan decodeStream) { defer d.streamWg.Done() frame := newFrameDec(d.o) for stream := range inStream { - if debug { + if debugDecoder { println("got new stream") } br := readerWrapper{r: stream.r} @@ -493,7 +490,7 @@ func (d *Decoder) startStreamDecoder(inStream chan decodeStream) { for { frame.history.reset() err := frame.reset(&br) - if debug && err != nil { + if debugDecoder && err != nil { println("Frame decoder returned", err) } if err == nil && frame.DictionaryID != nil { @@ -510,7 +507,7 @@ func (d *Decoder) startStreamDecoder(inStream chan decodeStream) { } break } - if debug { + if debugDecoder { println("starting frame decoder") } diff --git a/vendor/github.com/klauspost/compress/zstd/decoder_options.go b/vendor/github.com/klauspost/compress/zstd/decoder_options.go index c0fd058c2..95cc9b8b8 100644 --- a/vendor/github.com/klauspost/compress/zstd/decoder_options.go +++ b/vendor/github.com/klauspost/compress/zstd/decoder_options.go @@ -17,14 +17,16 @@ type decoderOptions struct { lowMem bool concurrent int maxDecodedSize uint64 + maxWindowSize uint64 dicts []dict } func (o *decoderOptions) setDefault() { *o = decoderOptions{ // use less ram: true for now, but may change. - lowMem: true, - concurrent: runtime.GOMAXPROCS(0), + lowMem: true, + concurrent: runtime.GOMAXPROCS(0), + maxWindowSize: MaxWindowSize, } o.maxDecodedSize = 1 << 63 } @@ -52,7 +54,6 @@ func WithDecoderConcurrency(n int) DOption { // WithDecoderMaxMemory allows to set a maximum decoded size for in-memory // non-streaming operations or maximum window size for streaming operations. // This can be used to control memory usage of potentially hostile content. -// For streaming operations, the maximum window size is capped at 1<<30 bytes. // Maximum and default is 1 << 63 bytes. func WithDecoderMaxMemory(n uint64) DOption { return func(o *decoderOptions) error { @@ -81,3 +82,21 @@ func WithDecoderDicts(dicts ...[]byte) DOption { return nil } } + +// WithDecoderMaxWindow allows to set a maximum window size for decodes. +// This allows rejecting packets that will cause big memory usage. +// The Decoder will likely allocate more memory based on the WithDecoderLowmem setting. +// If WithDecoderMaxMemory is set to a lower value, that will be used. +// Default is 512MB, Maximum is ~3.75 TB as per zstandard spec. +func WithDecoderMaxWindow(size uint64) DOption { + return func(o *decoderOptions) error { + if size < MinWindowSize { + return errors.New("WithMaxWindowSize must be at least 1KB, 1024 bytes") + } + if size > (1<<41)+7*(1<<38) { + return errors.New("WithMaxWindowSize must be less than (1<<41) + 7*(1<<38) ~ 3.75TB") + } + o.maxWindowSize = size + return nil + } +} diff --git a/vendor/github.com/klauspost/compress/zstd/dict.go b/vendor/github.com/klauspost/compress/zstd/dict.go index fa25a18d8..a36ae83ef 100644 --- a/vendor/github.com/klauspost/compress/zstd/dict.go +++ b/vendor/github.com/klauspost/compress/zstd/dict.go @@ -82,7 +82,7 @@ func loadDict(b []byte) (*dict, error) { println("Transform table error:", err) return err } - if debug { + if debugDecoder || debugEncoder { println("Read table ok", "symbolLen:", dec.symbolLen) } // Set decoders as predefined so they aren't reused. diff --git a/vendor/github.com/klauspost/compress/zstd/enc_best.go b/vendor/github.com/klauspost/compress/zstd/enc_best.go index dc1eed5f0..b7d4b9004 100644 --- a/vendor/github.com/klauspost/compress/zstd/enc_best.go +++ b/vendor/github.com/klauspost/compress/zstd/enc_best.go @@ -132,7 +132,7 @@ func (e *bestFastEncoder) Encode(blk *blockEnc, src []byte) { } _ = addLiterals - if debug { + if debugEncoder { println("recent offsets:", blk.recentOffsets) } @@ -274,7 +274,7 @@ encodeLoop: nextEmit = s if s >= sLimit { - if debug { + if debugEncoder { println("repeat ended", s, best.length) } @@ -412,7 +412,7 @@ encodeLoop: blk.recentOffsets[0] = uint32(offset1) blk.recentOffsets[1] = uint32(offset2) blk.recentOffsets[2] = uint32(offset3) - if debug { + if debugEncoder { println("returning, recent offsets:", blk.recentOffsets, "extra literals:", blk.extraLits) } } diff --git a/vendor/github.com/klauspost/compress/zstd/enc_better.go b/vendor/github.com/klauspost/compress/zstd/enc_better.go index 604954290..eab7b5083 100644 --- a/vendor/github.com/klauspost/compress/zstd/enc_better.go +++ b/vendor/github.com/klauspost/compress/zstd/enc_better.go @@ -138,7 +138,7 @@ func (e *betterFastEncoder) Encode(blk *blockEnc, src []byte) { blk.literals = append(blk.literals, src[nextEmit:until]...) s.litLen = uint32(until - nextEmit) } - if debug { + if debugEncoder { println("recent offsets:", blk.recentOffsets) } @@ -204,7 +204,7 @@ encodeLoop: nextEmit = s if s >= sLimit { - if debug { + if debugEncoder { println("repeat ended", s, lenght) } @@ -264,7 +264,7 @@ encodeLoop: s += lenght + repOff2 nextEmit = s if s >= sLimit { - if debug { + if debugEncoder { println("repeat ended", s, lenght) } @@ -553,7 +553,7 @@ encodeLoop: } blk.recentOffsets[0] = uint32(offset1) blk.recentOffsets[1] = uint32(offset2) - if debug { + if debugEncoder { println("returning, recent offsets:", blk.recentOffsets, "extra literals:", blk.extraLits) } } @@ -656,7 +656,7 @@ func (e *betterFastEncoderDict) Encode(blk *blockEnc, src []byte) { blk.literals = append(blk.literals, src[nextEmit:until]...) s.litLen = uint32(until - nextEmit) } - if debug { + if debugEncoder { println("recent offsets:", blk.recentOffsets) } @@ -724,7 +724,7 @@ encodeLoop: nextEmit = s if s >= sLimit { - if debug { + if debugEncoder { println("repeat ended", s, lenght) } @@ -787,7 +787,7 @@ encodeLoop: s += lenght + repOff2 nextEmit = s if s >= sLimit { - if debug { + if debugEncoder { println("repeat ended", s, lenght) } @@ -1084,7 +1084,7 @@ encodeLoop: } blk.recentOffsets[0] = uint32(offset1) blk.recentOffsets[1] = uint32(offset2) - if debug { + if debugEncoder { println("returning, recent offsets:", blk.recentOffsets, "extra literals:", blk.extraLits) } } diff --git a/vendor/github.com/klauspost/compress/zstd/enc_dfast.go b/vendor/github.com/klauspost/compress/zstd/enc_dfast.go index 8629d43d8..96b21b90e 100644 --- a/vendor/github.com/klauspost/compress/zstd/enc_dfast.go +++ b/vendor/github.com/klauspost/compress/zstd/enc_dfast.go @@ -109,7 +109,7 @@ func (e *doubleFastEncoder) Encode(blk *blockEnc, src []byte) { blk.literals = append(blk.literals, src[nextEmit:until]...) s.litLen = uint32(until - nextEmit) } - if debug { + if debugEncoder { println("recent offsets:", blk.recentOffsets) } @@ -170,7 +170,7 @@ encodeLoop: s += lenght + repOff nextEmit = s if s >= sLimit { - if debug { + if debugEncoder { println("repeat ended", s, lenght) } @@ -368,7 +368,7 @@ encodeLoop: } blk.recentOffsets[0] = uint32(offset1) blk.recentOffsets[1] = uint32(offset2) - if debug { + if debugEncoder { println("returning, recent offsets:", blk.recentOffsets, "extra literals:", blk.extraLits) } } @@ -427,7 +427,7 @@ func (e *doubleFastEncoder) EncodeNoHist(blk *blockEnc, src []byte) { blk.literals = append(blk.literals, src[nextEmit:until]...) s.litLen = uint32(until - nextEmit) } - if debug { + if debugEncoder { println("recent offsets:", blk.recentOffsets) } @@ -483,7 +483,7 @@ encodeLoop: s += length + repOff nextEmit = s if s >= sLimit { - if debug { + if debugEncoder { println("repeat ended", s, length) } @@ -677,7 +677,7 @@ encodeLoop: blk.literals = append(blk.literals, src[nextEmit:]...) blk.extraLits = len(src) - int(nextEmit) } - if debug { + if debugEncoder { println("returning, recent offsets:", blk.recentOffsets, "extra literals:", blk.extraLits) } @@ -767,7 +767,7 @@ func (e *doubleFastEncoderDict) Encode(blk *blockEnc, src []byte) { blk.literals = append(blk.literals, src[nextEmit:until]...) s.litLen = uint32(until - nextEmit) } - if debug { + if debugEncoder { println("recent offsets:", blk.recentOffsets) } @@ -830,7 +830,7 @@ encodeLoop: s += lenght + repOff nextEmit = s if s >= sLimit { - if debug { + if debugEncoder { println("repeat ended", s, lenght) } @@ -1039,7 +1039,7 @@ encodeLoop: } blk.recentOffsets[0] = uint32(offset1) blk.recentOffsets[1] = uint32(offset2) - if debug { + if debugEncoder { println("returning, recent offsets:", blk.recentOffsets, "extra literals:", blk.extraLits) } // If we encoded more than 64K mark all dirty. diff --git a/vendor/github.com/klauspost/compress/zstd/enc_fast.go b/vendor/github.com/klauspost/compress/zstd/enc_fast.go index ba4a17e10..2246d286d 100644 --- a/vendor/github.com/klauspost/compress/zstd/enc_fast.go +++ b/vendor/github.com/klauspost/compress/zstd/enc_fast.go @@ -103,7 +103,7 @@ func (e *fastEncoder) Encode(blk *blockEnc, src []byte) { blk.literals = append(blk.literals, src[nextEmit:until]...) s.litLen = uint32(until - nextEmit) } - if debug { + if debugEncoder { println("recent offsets:", blk.recentOffsets) } @@ -178,7 +178,7 @@ encodeLoop: s += length + 2 nextEmit = s if s >= sLimit { - if debug { + if debugEncoder { println("repeat ended", s, length) } @@ -330,7 +330,7 @@ encodeLoop: } blk.recentOffsets[0] = uint32(offset1) blk.recentOffsets[1] = uint32(offset2) - if debug { + if debugEncoder { println("returning, recent offsets:", blk.recentOffsets, "extra literals:", blk.extraLits) } } @@ -343,7 +343,7 @@ func (e *fastEncoder) EncodeNoHist(blk *blockEnc, src []byte) { inputMargin = 8 minNonLiteralBlockSize = 1 + 1 + inputMargin ) - if debug { + if debugEncoder { if len(src) > maxBlockSize { panic("src too big") } @@ -391,7 +391,7 @@ func (e *fastEncoder) EncodeNoHist(blk *blockEnc, src []byte) { blk.literals = append(blk.literals, src[nextEmit:until]...) s.litLen = uint32(until - nextEmit) } - if debug { + if debugEncoder { println("recent offsets:", blk.recentOffsets) } @@ -462,7 +462,7 @@ encodeLoop: s += length + 2 nextEmit = s if s >= sLimit { - if debug { + if debugEncoder { println("repeat ended", s, length) } @@ -616,7 +616,7 @@ encodeLoop: blk.literals = append(blk.literals, src[nextEmit:]...) blk.extraLits = len(src) - int(nextEmit) } - if debug { + if debugEncoder { println("returning, recent offsets:", blk.recentOffsets, "extra literals:", blk.extraLits) } // We do not store history, so we must offset e.cur to avoid false matches for next user. @@ -696,7 +696,7 @@ func (e *fastEncoderDict) Encode(blk *blockEnc, src []byte) { blk.literals = append(blk.literals, src[nextEmit:until]...) s.litLen = uint32(until - nextEmit) } - if debug { + if debugEncoder { println("recent offsets:", blk.recentOffsets) } @@ -773,7 +773,7 @@ encodeLoop: s += length + 2 nextEmit = s if s >= sLimit { - if debug { + if debugEncoder { println("repeat ended", s, length) } @@ -926,7 +926,7 @@ encodeLoop: } blk.recentOffsets[0] = uint32(offset1) blk.recentOffsets[1] = uint32(offset2) - if debug { + if debugEncoder { println("returning, recent offsets:", blk.recentOffsets, "extra literals:", blk.extraLits) } } diff --git a/vendor/github.com/klauspost/compress/zstd/encoder.go b/vendor/github.com/klauspost/compress/zstd/encoder.go index 4871dd03a..ea85548fc 100644 --- a/vendor/github.com/klauspost/compress/zstd/encoder.go +++ b/vendor/github.com/klauspost/compress/zstd/encoder.go @@ -245,7 +245,7 @@ func (e *Encoder) nextBlock(final bool) error { s.filling, s.current, s.previous = s.previous[:0], s.filling, s.current s.wg.Add(1) go func(src []byte) { - if debug { + if debugEncoder { println("Adding block,", len(src), "bytes, final:", final) } defer func() { @@ -290,7 +290,7 @@ func (e *Encoder) nextBlock(final bool) error { } switch err { case errIncompressible: - if debug { + if debugEncoder { println("Storing incompressible block as raw") } blk.encodeRaw(src) @@ -313,7 +313,7 @@ func (e *Encoder) nextBlock(final bool) error { // // The Copy function uses ReaderFrom if available. func (e *Encoder) ReadFrom(r io.Reader) (n int64, err error) { - if debug { + if debugEncoder { println("Using ReadFrom") } @@ -336,20 +336,20 @@ func (e *Encoder) ReadFrom(r io.Reader) (n int64, err error) { switch err { case io.EOF: e.state.filling = e.state.filling[:len(e.state.filling)-len(src)] - if debug { + if debugEncoder { println("ReadFrom: got EOF final block:", len(e.state.filling)) } return n, nil case nil: default: - if debug { + if debugEncoder { println("ReadFrom: got error:", err) } e.state.err = err return n, err } if len(src) > 0 { - if debug { + if debugEncoder { println("ReadFrom: got space left in source:", len(src)) } continue @@ -512,7 +512,7 @@ func (e *Encoder) EncodeAll(src, dst []byte) []byte { switch err { case errIncompressible: - if debug { + if debugEncoder { println("Storing incompressible block as raw") } dst = blk.encodeRawTo(dst, src) @@ -548,7 +548,7 @@ func (e *Encoder) EncodeAll(src, dst []byte) []byte { switch err { case errIncompressible: - if debug { + if debugEncoder { println("Storing incompressible block as raw") } dst = blk.encodeRawTo(dst, todo) diff --git a/vendor/github.com/klauspost/compress/zstd/framedec.go b/vendor/github.com/klauspost/compress/zstd/framedec.go index 4dc151213..989c79f8c 100644 --- a/vendor/github.com/klauspost/compress/zstd/framedec.go +++ b/vendor/github.com/klauspost/compress/zstd/framedec.go @@ -22,10 +22,6 @@ type frameDec struct { WindowSize uint64 - // maxWindowSize is the maximum windows size to support. - // should never be bigger than max-int. - maxWindowSize uint64 - // In order queue of blocks being decoded. decoding chan *blockDec @@ -50,8 +46,11 @@ type frameDec struct { } const ( - // The minimum Window_Size is 1 KB. + // MinWindowSize is the minimum Window Size, which is 1 KB. MinWindowSize = 1 << 10 + + // MaxWindowSize is the maximum encoder window size + // and the default decoder maximum window size. MaxWindowSize = 1 << 29 ) @@ -61,12 +60,11 @@ var ( ) func newFrameDec(o decoderOptions) *frameDec { - d := frameDec{ - o: o, - maxWindowSize: MaxWindowSize, + if o.maxWindowSize > o.maxDecodedSize { + o.maxWindowSize = o.maxDecodedSize } - if d.maxWindowSize > o.maxDecodedSize { - d.maxWindowSize = o.maxDecodedSize + d := frameDec{ + o: o, } return &d } @@ -78,20 +76,33 @@ func newFrameDec(o decoderOptions) *frameDec { func (d *frameDec) reset(br byteBuffer) error { d.HasCheckSum = false d.WindowSize = 0 - var b []byte + var signature [4]byte for { var err error - b, err = br.readSmall(4) + // Check if we can read more... + b, err := br.readSmall(1) switch err { case io.EOF, io.ErrUnexpectedEOF: return io.EOF default: return err case nil: + signature[0] = b[0] + } + // Read the rest, don't allow io.ErrUnexpectedEOF + b, err = br.readSmall(3) + switch err { + case io.EOF: + return io.EOF + default: + return err + case nil: + copy(signature[1:], b) } - if !bytes.Equal(b[1:4], skippableFrameMagic) || b[0]&0xf0 != 0x50 { - if debug { - println("Not skippable", hex.EncodeToString(b), hex.EncodeToString(skippableFrameMagic)) + + if !bytes.Equal(signature[1:4], skippableFrameMagic) || signature[0]&0xf0 != 0x50 { + if debugDecoder { + println("Not skippable", hex.EncodeToString(signature[:]), hex.EncodeToString(skippableFrameMagic)) } // Break if not skippable frame. break @@ -99,28 +110,34 @@ func (d *frameDec) reset(br byteBuffer) error { // Read size to skip b, err = br.readSmall(4) if err != nil { - println("Reading Frame Size", err) + if debugDecoder { + println("Reading Frame Size", err) + } return err } n := uint32(b[0]) | (uint32(b[1]) << 8) | (uint32(b[2]) << 16) | (uint32(b[3]) << 24) println("Skipping frame with", n, "bytes.") err = br.skipN(int(n)) if err != nil { - if debug { + if debugDecoder { println("Reading discarded frame", err) } return err } } - if !bytes.Equal(b, frameMagic) { - println("Got magic numbers: ", b, "want:", frameMagic) + if !bytes.Equal(signature[:], frameMagic) { + if debugDecoder { + println("Got magic numbers: ", signature, "want:", frameMagic) + } return ErrMagicMismatch } // Read Frame_Header_Descriptor fhd, err := br.readByte() if err != nil { - println("Reading Frame_Header_Descriptor", err) + if debugDecoder { + println("Reading Frame_Header_Descriptor", err) + } return err } d.SingleSegment = fhd&(1<<5) != 0 @@ -135,7 +152,9 @@ func (d *frameDec) reset(br byteBuffer) error { if !d.SingleSegment { wd, err := br.readByte() if err != nil { - println("Reading Window_Descriptor", err) + if debugDecoder { + println("Reading Window_Descriptor", err) + } return err } printf("raw: %x, mantissa: %d, exponent: %d\n", wd, wd&7, wd>>3) @@ -153,7 +172,7 @@ func (d *frameDec) reset(br byteBuffer) error { size = 4 } - b, err = br.readSmall(int(size)) + b, err := br.readSmall(int(size)) if err != nil { println("Reading Dictionary_ID", err) return err @@ -167,7 +186,7 @@ func (d *frameDec) reset(br byteBuffer) error { case 4: id = uint32(b[0]) | (uint32(b[1]) << 8) | (uint32(b[2]) << 16) | (uint32(b[3]) << 24) } - if debug { + if debugDecoder { println("Dict size", size, "ID:", id) } if id > 0 { @@ -191,7 +210,7 @@ func (d *frameDec) reset(br byteBuffer) error { } d.FrameContentSize = 0 if fcsSize > 0 { - b, err = br.readSmall(fcsSize) + b, err := br.readSmall(fcsSize) if err != nil { println("Reading Frame content", err) return err @@ -209,7 +228,7 @@ func (d *frameDec) reset(br byteBuffer) error { d2 := uint32(b[4]) | (uint32(b[5]) << 8) | (uint32(b[6]) << 16) | (uint32(b[7]) << 24) d.FrameContentSize = uint64(d1) | (uint64(d2) << 32) } - if debug { + if debugDecoder { println("field size bits:", v, "fcsSize:", fcsSize, "FrameContentSize:", d.FrameContentSize, hex.EncodeToString(b[:fcsSize]), "singleseg:", d.SingleSegment, "window:", d.WindowSize) } } @@ -230,13 +249,17 @@ func (d *frameDec) reset(br byteBuffer) error { } } - if d.WindowSize > d.maxWindowSize { - printf("window size %d > max %d\n", d.WindowSize, d.maxWindowSize) + if d.WindowSize > uint64(d.o.maxWindowSize) { + if debugDecoder { + printf("window size %d > max %d\n", d.WindowSize, d.o.maxWindowSize) + } return ErrWindowSizeExceeded } // The minimum Window_Size is 1 KB. if d.WindowSize < MinWindowSize { - println("got window size: ", d.WindowSize) + if debugDecoder { + println("got window size: ", d.WindowSize) + } return ErrWindowSizeTooSmall } d.history.windowSize = int(d.WindowSize) @@ -252,7 +275,7 @@ func (d *frameDec) reset(br byteBuffer) error { // next will start decoding the next block from stream. func (d *frameDec) next(block *blockDec) error { - if debug { + if debugDecoder { printf("decoding new block %p:%p", block, block.data) } err := block.reset(d.rawInput, d.WindowSize) @@ -263,7 +286,7 @@ func (d *frameDec) next(block *blockDec) error { return err } block.input <- struct{}{} - if debug { + if debugDecoder { println("next block:", block) } d.asyncRunningMu.Lock() @@ -318,12 +341,12 @@ func (d *frameDec) checkCRC() error { } if !bytes.Equal(tmp[:], want) { - if debug { + if debugDecoder { println("CRC Check Failed:", tmp[:], "!=", want) } return ErrCRCMismatch } - if debug { + if debugDecoder { println("CRC ok", tmp[:]) } return nil @@ -331,8 +354,8 @@ func (d *frameDec) checkCRC() error { func (d *frameDec) initAsync() { if !d.o.lowMem && !d.SingleSegment { - // set max extra size history to 10MB. - d.history.maxSize = d.history.windowSize + maxBlockSize*5 + // set max extra size history to 2MB. + d.history.maxSize = d.history.windowSize + maxBlockSize } // re-alloc if more than one extra block size. if d.o.lowMem && cap(d.history.b) > d.history.maxSize+maxBlockSize { @@ -344,7 +367,7 @@ func (d *frameDec) initAsync() { if cap(d.decoding) < d.o.concurrent { d.decoding = make(chan *blockDec, d.o.concurrent) } - if debug { + if debugDecoder { h := d.history printf("history init. len: %d, cap: %d", len(h.b), cap(h.b)) } @@ -392,7 +415,7 @@ func (d *frameDec) startDecoder(output chan decodeOutput) { output <- r return } - if debug { + if debugDecoder { println("got result, from ", d.offset, "to", d.offset+int64(len(r.b))) d.offset += int64(len(r.b)) } @@ -400,7 +423,7 @@ func (d *frameDec) startDecoder(output chan decodeOutput) { // Send history to next block select { case next = <-d.decoding: - if debug { + if debugDecoder { println("Sending ", len(d.history.b), "bytes as history") } next.history <- &d.history @@ -438,7 +461,7 @@ func (d *frameDec) startDecoder(output chan decodeOutput) { output <- r if next == nil { // There was no decoder available, we wait for one now that we have sent to the writer. - if debug { + if debugDecoder { println("Sending ", len(d.history.b), " bytes as history") } next = <-d.decoding @@ -462,7 +485,7 @@ func (d *frameDec) runDecoder(dst []byte, dec *blockDec) ([]byte, error) { if err != nil { break } - if debug { + if debugDecoder { println("next block:", dec) } err = dec.decodeBuf(&d.history) diff --git a/vendor/github.com/klauspost/compress/zstd/fse_encoder.go b/vendor/github.com/klauspost/compress/zstd/fse_encoder.go index c74681b99..b4757ee3f 100644 --- a/vendor/github.com/klauspost/compress/zstd/fse_encoder.go +++ b/vendor/github.com/klauspost/compress/zstd/fse_encoder.go @@ -229,7 +229,7 @@ func (s *fseEncoder) setRLE(val byte) { deltaFindState: 0, deltaNbBits: 0, } - if debug { + if debugEncoder { println("setRLE: val", val, "symbolTT", s.ct.symbolTT[val]) } s.rleVal = val diff --git a/vendor/github.com/klauspost/compress/zstd/snappy.go b/vendor/github.com/klauspost/compress/zstd/snappy.go index 9d9d1d567..0372b1714 100644 --- a/vendor/github.com/klauspost/compress/zstd/snappy.go +++ b/vendor/github.com/klauspost/compress/zstd/snappy.go @@ -203,7 +203,7 @@ func (r *SnappyConverter) Convert(in io.Reader, w io.Writer) (int64, error) { written += int64(n) continue case chunkTypeUncompressedData: - if debug { + if debugEncoder { println("Uncompressed, chunklen", chunkLen) } // Section 4.3. Uncompressed data (chunk type 0x01). @@ -246,7 +246,7 @@ func (r *SnappyConverter) Convert(in io.Reader, w io.Writer) (int64, error) { continue case chunkTypeStreamIdentifier: - if debug { + if debugEncoder { println("stream id", chunkLen, len(snappyMagicBody)) } // Section 4.1. Stream identifier (chunk type 0xff). diff --git a/vendor/github.com/klauspost/compress/zstd/zstd.go b/vendor/github.com/klauspost/compress/zstd/zstd.go index 1ba308c8b..ef1d49a00 100644 --- a/vendor/github.com/klauspost/compress/zstd/zstd.go +++ b/vendor/github.com/klauspost/compress/zstd/zstd.go @@ -15,6 +15,12 @@ import ( // enable debug printing const debug = false +// enable encoding debug printing +const debugEncoder = debug + +// enable decoding debug printing +const debugDecoder = debug + // Enable extra assertions. const debugAsserts = debug || false @@ -82,13 +88,13 @@ var ( ) func println(a ...interface{}) { - if debug { + if debug || debugDecoder || debugEncoder { log.Println(a...) } } func printf(format string, a ...interface{}) { - if debug { + if debug || debugDecoder || debugEncoder { log.Printf(format, a...) } } diff --git a/vendor/github.com/mattn/go-runewidth/go.mod b/vendor/github.com/mattn/go-runewidth/go.mod index 8a9d524ec..62dba1bfc 100644 --- a/vendor/github.com/mattn/go-runewidth/go.mod +++ b/vendor/github.com/mattn/go-runewidth/go.mod @@ -2,4 +2,4 @@ module github.com/mattn/go-runewidth go 1.9 -require github.com/rivo/uniseg v0.1.0 +require github.com/rivo/uniseg v0.2.0 diff --git a/vendor/github.com/mattn/go-runewidth/go.sum b/vendor/github.com/mattn/go-runewidth/go.sum index 02135660b..03f902d56 100644 --- a/vendor/github.com/mattn/go-runewidth/go.sum +++ b/vendor/github.com/mattn/go-runewidth/go.sum @@ -1,2 +1,2 @@ -github.com/rivo/uniseg v0.1.0 h1:+2KBaVoUmb9XzDsrx/Ct0W/EYOSFf/nWTauy++DprtY= -github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= diff --git a/vendor/github.com/mattn/go-shellwords/shellwords.go b/vendor/github.com/mattn/go-shellwords/shellwords.go index 01afd94d1..1b42a0017 100644 --- a/vendor/github.com/mattn/go-shellwords/shellwords.go +++ b/vendor/github.com/mattn/go-shellwords/shellwords.go @@ -232,7 +232,7 @@ loop: case '\'': if !doubleQuoted && !dollarQuote { if singleQuoted { - got = argSingle + got = argQuoted } singleQuoted = !singleQuoted continue diff --git a/vendor/github.com/vbauerster/mpb/v7/.gitignore b/vendor/github.com/vbauerster/mpb/v7/.gitignore new file mode 100644 index 000000000..63bd91672 --- /dev/null +++ b/vendor/github.com/vbauerster/mpb/v7/.gitignore @@ -0,0 +1,5 @@ +# Test binary, build with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out diff --git a/vendor/github.com/vbauerster/mpb/v7/.travis.yml b/vendor/github.com/vbauerster/mpb/v7/.travis.yml new file mode 100644 index 000000000..9a203a67d --- /dev/null +++ b/vendor/github.com/vbauerster/mpb/v7/.travis.yml @@ -0,0 +1,11 @@ +language: go +arch: + - amd64 + - ppc64le + +go: + - 1.14.x + +script: + - go test -race ./... + - for i in _examples/*/; do go build $i/*.go || exit 1; done diff --git a/vendor/github.com/vbauerster/mpb/v7/README.md b/vendor/github.com/vbauerster/mpb/v7/README.md new file mode 100644 index 000000000..d0560d799 --- /dev/null +++ b/vendor/github.com/vbauerster/mpb/v7/README.md @@ -0,0 +1,121 @@ +# Multi Progress Bar + +[![GoDoc](https://pkg.go.dev/badge/github.com/vbauerster/mpb)](https://pkg.go.dev/github.com/vbauerster/mpb/v7) +[![Build Status](https://travis-ci.org/vbauerster/mpb.svg?branch=master)](https://travis-ci.org/vbauerster/mpb) +[![Go Report Card](https://goreportcard.com/badge/github.com/vbauerster/mpb)](https://goreportcard.com/report/github.com/vbauerster/mpb) +[![Donate with PayPal](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.me/vbauerster) + +**mpb** is a Go lib for rendering progress bars in terminal applications. + +## Features + +- **Multiple Bars**: Multiple progress bars are supported +- **Dynamic Total**: Set total while bar is running +- **Dynamic Add/Remove**: Dynamically add or remove bars +- **Cancellation**: Cancel whole rendering process +- **Predefined Decorators**: Elapsed time, [ewma](https://github.com/VividCortex/ewma) based ETA, Percentage, Bytes counter +- **Decorator's width sync**: Synchronized decorator's width among multiple bars + +## Usage + +#### [Rendering single bar](_examples/singleBar/main.go) + +```go +package main + +import ( + "math/rand" + "time" + + "github.com/vbauerster/mpb/v7" + "github.com/vbauerster/mpb/v7/decor" +) + +func main() { + // initialize progress container, with custom width + p := mpb.New(mpb.WithWidth(64)) + + total := 100 + name := "Single Bar:" + // adding a single bar, which will inherit container's width + bar := p.Add(int64(total), + // progress bar filler with customized style + mpb.NewBarFiller(mpb.BarStyle().Lbound("╢").Filler("▌").Tip("▌").Padding("░").Rbound("╟")), + mpb.PrependDecorators( + // display our name with one space on the right + decor.Name(name, decor.WC{W: len(name) + 1, C: decor.DidentRight}), + // replace ETA decorator with "done" message, OnComplete event + decor.OnComplete( + decor.AverageETA(decor.ET_STYLE_GO, decor.WC{W: 4}), "done", + ), + ), + mpb.AppendDecorators(decor.Percentage()), + ) + // simulating some work + max := 100 * time.Millisecond + for i := 0; i < total; i++ { + time.Sleep(time.Duration(rand.Intn(10)+1) * max / 10) + bar.Increment() + } + // wait for our bar to complete and flush + p.Wait() +} +``` + +#### [Rendering multiple bars](_examples/multiBars/main.go) + +```go + var wg sync.WaitGroup + // passed &wg will be accounted at p.Wait() call + p := mpb.New(mpb.WithWaitGroup(&wg)) + total, numBars := 100, 3 + wg.Add(numBars) + + for i := 0; i < numBars; i++ { + name := fmt.Sprintf("Bar#%d:", i) + bar := p.AddBar(int64(total), + mpb.PrependDecorators( + // simple name decorator + decor.Name(name), + // decor.DSyncWidth bit enables column width synchronization + decor.Percentage(decor.WCSyncSpace), + ), + mpb.AppendDecorators( + // replace ETA decorator with "done" message, OnComplete event + decor.OnComplete( + // ETA decorator with ewma age of 60 + decor.EwmaETA(decor.ET_STYLE_GO, 60), "done", + ), + ), + ) + // simulating some work + go func() { + defer wg.Done() + rng := rand.New(rand.NewSource(time.Now().UnixNano())) + max := 100 * time.Millisecond + for i := 0; i < total; i++ { + // start variable is solely for EWMA calculation + // EWMA's unit of measure is an iteration's duration + start := time.Now() + time.Sleep(time.Duration(rng.Intn(10)+1) * max / 10) + bar.Increment() + // we need to call DecoratorEwmaUpdate to fulfill ewma decorator's contract + bar.DecoratorEwmaUpdate(time.Since(start)) + } + }() + } + // Waiting for passed &wg and for all bars to complete and flush + p.Wait() +``` + +#### [Dynamic total](_examples/dynTotal/main.go) + +![dynamic total](_svg/godEMrCZmJkHYH1X9dN4Nm0U7.svg) + +#### [Complex example](_examples/complex/main.go) + +![complex](_svg/wHzf1M7sd7B3zVa2scBMnjqRf.svg) + +#### [Bytes counters](_examples/io/main.go) + +![byte counters](_svg/hIpTa3A5rQz65ssiVuRJu87X6.svg) diff --git a/vendor/github.com/vbauerster/mpb/v7/UNLICENSE b/vendor/github.com/vbauerster/mpb/v7/UNLICENSE new file mode 100644 index 000000000..68a49daad --- /dev/null +++ b/vendor/github.com/vbauerster/mpb/v7/UNLICENSE @@ -0,0 +1,24 @@ +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to <http://unlicense.org/> diff --git a/vendor/github.com/vbauerster/mpb/v7/bar.go b/vendor/github.com/vbauerster/mpb/v7/bar.go new file mode 100644 index 000000000..ed6c73eda --- /dev/null +++ b/vendor/github.com/vbauerster/mpb/v7/bar.go @@ -0,0 +1,492 @@ +package mpb + +import ( + "bytes" + "context" + "fmt" + "io" + "log" + "runtime/debug" + "strings" + "time" + + "github.com/acarl005/stripansi" + "github.com/mattn/go-runewidth" + "github.com/vbauerster/mpb/v7/decor" +) + +// Bar represents a progress bar. +type Bar struct { + priority int // used by heap + index int // used by heap + + extendedLines int + toShutdown bool + toDrop bool + noPop bool + hasEwmaDecorators bool + operateState chan func(*bState) + frameCh chan io.Reader + syncTableCh chan [][]chan int + completed chan bool + + // cancel is called either by user or on complete event + cancel func() + // done is closed after cacheState is assigned + done chan struct{} + // cacheState is populated, right after close(shutdown) + cacheState *bState + + container *Progress + dlogger *log.Logger + recoveredPanic interface{} +} + +type extenderFunc func(in io.Reader, reqWidth int, st decor.Statistics) (out io.Reader, lines int) + +// bState is actual bar state. It gets passed to *Bar.serve(...) monitor +// goroutine. +type bState struct { + id int + priority int + reqWidth int + total int64 + current int64 + refill int64 + lastN int64 + iterated bool + trimSpace bool + completed bool + completeFlushed bool + triggerComplete bool + dropOnComplete bool + noPop bool + aDecorators []decor.Decorator + pDecorators []decor.Decorator + averageDecorators []decor.AverageDecorator + ewmaDecorators []decor.EwmaDecorator + shutdownListeners []decor.ShutdownListener + bufP, bufB, bufA *bytes.Buffer + filler BarFiller + middleware func(BarFiller) BarFiller + extender extenderFunc + + // runningBar is a key for *pState.parkedBars + runningBar *Bar + + debugOut io.Writer +} + +func newBar(container *Progress, bs *bState) *Bar { + logPrefix := fmt.Sprintf("%sbar#%02d ", container.dlogger.Prefix(), bs.id) + ctx, cancel := context.WithCancel(container.ctx) + + bar := &Bar{ + container: container, + priority: bs.priority, + toDrop: bs.dropOnComplete, + noPop: bs.noPop, + operateState: make(chan func(*bState)), + frameCh: make(chan io.Reader, 1), + syncTableCh: make(chan [][]chan int, 1), + completed: make(chan bool, 1), + done: make(chan struct{}), + cancel: cancel, + dlogger: log.New(bs.debugOut, logPrefix, log.Lshortfile), + } + + go bar.serve(ctx, bs) + return bar +} + +// ProxyReader wraps r with metrics required for progress tracking. +// Panics if r is nil. +func (b *Bar) ProxyReader(r io.Reader) io.ReadCloser { + if r == nil { + panic("expected non nil io.Reader") + } + return newProxyReader(r, b) +} + +// ID returs id of the bar. +func (b *Bar) ID() int { + result := make(chan int) + select { + case b.operateState <- func(s *bState) { result <- s.id }: + return <-result + case <-b.done: + return b.cacheState.id + } +} + +// Current returns bar's current number, in other words sum of all increments. +func (b *Bar) Current() int64 { + result := make(chan int64) + select { + case b.operateState <- func(s *bState) { result <- s.current }: + return <-result + case <-b.done: + return b.cacheState.current + } +} + +// SetRefill sets refill flag with specified amount. +// The underlying BarFiller will change its visual representation, to +// indicate refill event. Refill event may be referred to some retry +// operation for example. +func (b *Bar) SetRefill(amount int64) { + select { + case b.operateState <- func(s *bState) { + s.refill = amount + }: + case <-b.done: + } +} + +// TraverseDecorators traverses all available decorators and calls cb func on each. +func (b *Bar) TraverseDecorators(cb func(decor.Decorator)) { + select { + case b.operateState <- func(s *bState) { + for _, decorators := range [...][]decor.Decorator{ + s.pDecorators, + s.aDecorators, + } { + for _, d := range decorators { + cb(extractBaseDecorator(d)) + } + } + }: + case <-b.done: + } +} + +// SetTotal sets total dynamically. +// If total is less than or equal to zero it takes progress' current value. +func (b *Bar) SetTotal(total int64, triggerComplete bool) { + select { + case b.operateState <- func(s *bState) { + s.triggerComplete = triggerComplete + if total <= 0 { + s.total = s.current + } else { + s.total = total + } + if s.triggerComplete && !s.completed { + s.current = s.total + s.completed = true + go b.refreshTillShutdown() + } + }: + case <-b.done: + } +} + +// SetCurrent sets progress' current to an arbitrary value. +// Setting a negative value will cause a panic. +func (b *Bar) SetCurrent(current int64) { + select { + case b.operateState <- func(s *bState) { + s.iterated = true + s.lastN = current - s.current + s.current = current + if s.triggerComplete && s.current >= s.total { + s.current = s.total + s.completed = true + go b.refreshTillShutdown() + } + }: + case <-b.done: + } +} + +// Increment is a shorthand for b.IncrInt64(1). +func (b *Bar) Increment() { + b.IncrInt64(1) +} + +// IncrBy is a shorthand for b.IncrInt64(int64(n)). +func (b *Bar) IncrBy(n int) { + b.IncrInt64(int64(n)) +} + +// IncrInt64 increments progress by amount of n. +func (b *Bar) IncrInt64(n int64) { + select { + case b.operateState <- func(s *bState) { + s.iterated = true + s.lastN = n + s.current += n + if s.triggerComplete && s.current >= s.total { + s.current = s.total + s.completed = true + go b.refreshTillShutdown() + } + }: + case <-b.done: + } +} + +// DecoratorEwmaUpdate updates all EWMA based decorators. Should be +// called on each iteration, because EWMA's unit of measure is an +// iteration's duration. Panics if called before *Bar.Incr... family +// methods. +func (b *Bar) DecoratorEwmaUpdate(dur time.Duration) { + select { + case b.operateState <- func(s *bState) { + ewmaIterationUpdate(false, s, dur) + }: + case <-b.done: + ewmaIterationUpdate(true, b.cacheState, dur) + } +} + +// DecoratorAverageAdjust adjusts all average based decorators. Call +// if you need to adjust start time of all average based decorators +// or after progress resume. +func (b *Bar) DecoratorAverageAdjust(start time.Time) { + select { + case b.operateState <- func(s *bState) { + for _, d := range s.averageDecorators { + d.AverageAdjust(start) + } + }: + case <-b.done: + } +} + +// SetPriority changes bar's order among multiple bars. Zero is highest +// priority, i.e. bar will be on top. If you don't need to set priority +// dynamically, better use BarPriority option. +func (b *Bar) SetPriority(priority int) { + select { + case <-b.done: + default: + b.container.setBarPriority(b, priority) + } +} + +// Abort interrupts bar's running goroutine. Call this, if you'd like +// to stop/remove bar before completion event. It has no effect after +// completion event. If drop is true bar will be removed as well. +func (b *Bar) Abort(drop bool) { + select { + case <-b.done: + default: + if drop { + b.container.dropBar(b) + } + b.cancel() + } +} + +// Completed reports whether the bar is in completed state. +func (b *Bar) Completed() bool { + select { + case b.operateState <- func(s *bState) { b.completed <- s.completed }: + return <-b.completed + case <-b.done: + return true + } +} + +func (b *Bar) serve(ctx context.Context, s *bState) { + defer b.container.bwg.Done() + for { + select { + case op := <-b.operateState: + op(s) + case <-ctx.Done(): + b.cacheState = s + close(b.done) + // Notifying decorators about shutdown event + for _, sl := range s.shutdownListeners { + sl.Shutdown() + } + return + } + } +} + +func (b *Bar) render(tw int) { + select { + case b.operateState <- func(s *bState) { + stat := newStatistics(tw, s) + defer func() { + // recovering if user defined decorator panics for example + if p := recover(); p != nil { + if b.recoveredPanic == nil { + s.extender = makePanicExtender(p) + b.toShutdown = !b.toShutdown + b.recoveredPanic = p + } + frame, lines := s.extender(nil, s.reqWidth, stat) + b.extendedLines = lines + b.frameCh <- frame + b.dlogger.Println(p) + } + s.completeFlushed = s.completed + }() + frame, lines := s.extender(s.draw(stat), s.reqWidth, stat) + b.extendedLines = lines + b.toShutdown = s.completed && !s.completeFlushed + b.frameCh <- frame + }: + case <-b.done: + s := b.cacheState + stat := newStatistics(tw, s) + var r io.Reader + if b.recoveredPanic == nil { + r = s.draw(stat) + } + frame, lines := s.extender(r, s.reqWidth, stat) + b.extendedLines = lines + b.frameCh <- frame + } +} + +func (b *Bar) subscribeDecorators() { + var averageDecorators []decor.AverageDecorator + var ewmaDecorators []decor.EwmaDecorator + var shutdownListeners []decor.ShutdownListener + b.TraverseDecorators(func(d decor.Decorator) { + if d, ok := d.(decor.AverageDecorator); ok { + averageDecorators = append(averageDecorators, d) + } + if d, ok := d.(decor.EwmaDecorator); ok { + ewmaDecorators = append(ewmaDecorators, d) + } + if d, ok := d.(decor.ShutdownListener); ok { + shutdownListeners = append(shutdownListeners, d) + } + }) + select { + case b.operateState <- func(s *bState) { + s.averageDecorators = averageDecorators + s.ewmaDecorators = ewmaDecorators + s.shutdownListeners = shutdownListeners + }: + b.hasEwmaDecorators = len(ewmaDecorators) != 0 + case <-b.done: + } +} + +func (b *Bar) refreshTillShutdown() { + for { + select { + case b.container.refreshCh <- time.Now(): + case <-b.done: + return + } + } +} + +func (b *Bar) wSyncTable() [][]chan int { + select { + case b.operateState <- func(s *bState) { b.syncTableCh <- s.wSyncTable() }: + return <-b.syncTableCh + case <-b.done: + return b.cacheState.wSyncTable() + } +} + +func (s *bState) draw(stat decor.Statistics) io.Reader { + nlr := strings.NewReader("\n") + tw := stat.AvailableWidth + for _, d := range s.pDecorators { + str := d.Decor(stat) + stat.AvailableWidth -= runewidth.StringWidth(stripansi.Strip(str)) + s.bufP.WriteString(str) + } + if stat.AvailableWidth < 1 { + trunc := strings.NewReader(runewidth.Truncate(stripansi.Strip(s.bufP.String()), tw, "…")) + s.bufP.Reset() + return io.MultiReader(trunc, nlr) + } + + if !s.trimSpace && stat.AvailableWidth > 1 { + stat.AvailableWidth -= 2 + s.bufB.WriteByte(' ') + defer s.bufB.WriteByte(' ') + } + + tw = stat.AvailableWidth + for _, d := range s.aDecorators { + str := d.Decor(stat) + stat.AvailableWidth -= runewidth.StringWidth(stripansi.Strip(str)) + s.bufA.WriteString(str) + } + if stat.AvailableWidth < 1 { + trunc := strings.NewReader(runewidth.Truncate(stripansi.Strip(s.bufA.String()), tw, "…")) + s.bufA.Reset() + return io.MultiReader(s.bufP, s.bufB, trunc, nlr) + } + + s.filler.Fill(s.bufB, s.reqWidth, stat) + + return io.MultiReader(s.bufP, s.bufB, s.bufA, nlr) +} + +func (s *bState) wSyncTable() [][]chan int { + columns := make([]chan int, 0, len(s.pDecorators)+len(s.aDecorators)) + var pCount int + for _, d := range s.pDecorators { + if ch, ok := d.Sync(); ok { + columns = append(columns, ch) + pCount++ + } + } + var aCount int + for _, d := range s.aDecorators { + if ch, ok := d.Sync(); ok { + columns = append(columns, ch) + aCount++ + } + } + table := make([][]chan int, 2) + table[0] = columns[0:pCount] + table[1] = columns[pCount : pCount+aCount : pCount+aCount] + return table +} + +func newStatistics(tw int, s *bState) decor.Statistics { + return decor.Statistics{ + ID: s.id, + AvailableWidth: tw, + Total: s.total, + Current: s.current, + Refill: s.refill, + Completed: s.completeFlushed, + } +} + +func extractBaseDecorator(d decor.Decorator) decor.Decorator { + if d, ok := d.(decor.Wrapper); ok { + return extractBaseDecorator(d.Base()) + } + return d +} + +func ewmaIterationUpdate(done bool, s *bState, dur time.Duration) { + if !done && !s.iterated { + panic("increment required before ewma iteration update") + } else { + s.iterated = false + } + for _, d := range s.ewmaDecorators { + d.EwmaUpdate(s.lastN, dur) + } +} + +func makePanicExtender(p interface{}) extenderFunc { + pstr := fmt.Sprint(p) + stack := debug.Stack() + stackLines := bytes.Count(stack, []byte("\n")) + return func(_ io.Reader, _ int, st decor.Statistics) (io.Reader, int) { + mr := io.MultiReader( + strings.NewReader(runewidth.Truncate(pstr, st.AvailableWidth, "…")), + strings.NewReader(fmt.Sprintf("\n%#v\n", st)), + bytes.NewReader(stack), + ) + return mr, stackLines + 1 + } +} diff --git a/vendor/github.com/vbauerster/mpb/v7/bar_filler.go b/vendor/github.com/vbauerster/mpb/v7/bar_filler.go new file mode 100644 index 000000000..a69087c47 --- /dev/null +++ b/vendor/github.com/vbauerster/mpb/v7/bar_filler.go @@ -0,0 +1,39 @@ +package mpb + +import ( + "io" + + "github.com/vbauerster/mpb/v7/decor" +) + +// BarFiller interface. +// Bar (without decorators) renders itself by calling BarFiller's Fill method. +// +// reqWidth is requested width, set by `func WithWidth(int) ContainerOption`. +// If not set, it defaults to terminal width. +// +// Default implementations can be obtained via: +// +// func NewBarFiller(BarStyle()) BarFiller +// func NewBarFiller(SpinnerStyle()) BarFiller +// +type BarFiller interface { + Fill(w io.Writer, reqWidth int, stat decor.Statistics) +} + +// BarFillerBuilder interface. +type BarFillerBuilder interface { + Build() BarFiller +} + +// BarFillerFunc is function type adapter to convert function into BarFiller. +type BarFillerFunc func(w io.Writer, reqWidth int, stat decor.Statistics) + +func (f BarFillerFunc) Fill(w io.Writer, reqWidth int, stat decor.Statistics) { + f(w, reqWidth, stat) +} + +// NewBarFiller constructs a BarFiller from provided BarFillerBuilder. +func NewBarFiller(b BarFillerBuilder) BarFiller { + return b.Build() +} diff --git a/vendor/github.com/vbauerster/mpb/v7/bar_filler_bar.go b/vendor/github.com/vbauerster/mpb/v7/bar_filler_bar.go new file mode 100644 index 000000000..e30d4921c --- /dev/null +++ b/vendor/github.com/vbauerster/mpb/v7/bar_filler_bar.go @@ -0,0 +1,219 @@ +package mpb + +import ( + "io" + + "github.com/acarl005/stripansi" + "github.com/mattn/go-runewidth" + "github.com/vbauerster/mpb/v7/decor" + "github.com/vbauerster/mpb/v7/internal" +) + +const ( + iLbound = iota + iRbound + iFiller + iRefiller + iPadding + components +) + +// BarStyleComposer interface. +type BarStyleComposer interface { + BarFillerBuilder + Lbound(string) BarStyleComposer + Rbound(string) BarStyleComposer + Filler(string) BarStyleComposer + Refiller(string) BarStyleComposer + Padding(string) BarStyleComposer + Tip(...string) BarStyleComposer + Reverse() BarStyleComposer +} + +type bFiller struct { + components [components]*component + tip struct { + count uint + frames []*component + } + flush func(dst io.Writer, filling, padding [][]byte) +} + +type component struct { + width int + bytes []byte +} + +type barStyle struct { + lbound string + rbound string + filler string + refiller string + padding string + tip []string + rev bool +} + +// BarStyle constructs default bar style which can be altered via +// BarStyleComposer interface. +func BarStyle() BarStyleComposer { + return &barStyle{ + lbound: "[", + rbound: "]", + filler: "=", + refiller: "+", + padding: "-", + tip: []string{">"}, + } +} + +func (s *barStyle) Lbound(bound string) BarStyleComposer { + s.lbound = bound + return s +} + +func (s *barStyle) Rbound(bound string) BarStyleComposer { + s.rbound = bound + return s +} + +func (s *barStyle) Filler(filler string) BarStyleComposer { + s.filler = filler + return s +} + +func (s *barStyle) Refiller(refiller string) BarStyleComposer { + s.refiller = refiller + return s +} + +func (s *barStyle) Padding(padding string) BarStyleComposer { + s.padding = padding + return s +} + +func (s *barStyle) Tip(tip ...string) BarStyleComposer { + if len(tip) != 0 { + s.tip = append(s.tip[:0], tip...) + } + return s +} + +func (s *barStyle) Reverse() BarStyleComposer { + s.rev = true + return s +} + +func (s *barStyle) Build() BarFiller { + bf := new(bFiller) + if s.rev { + bf.flush = func(dst io.Writer, filling, padding [][]byte) { + flush(dst, padding, filling) + } + } else { + bf.flush = flush + } + bf.components[iLbound] = &component{ + width: runewidth.StringWidth(stripansi.Strip(s.lbound)), + bytes: []byte(s.lbound), + } + bf.components[iRbound] = &component{ + width: runewidth.StringWidth(stripansi.Strip(s.rbound)), + bytes: []byte(s.rbound), + } + bf.components[iFiller] = &component{ + width: runewidth.StringWidth(stripansi.Strip(s.filler)), + bytes: []byte(s.filler), + } + bf.components[iRefiller] = &component{ + width: runewidth.StringWidth(stripansi.Strip(s.refiller)), + bytes: []byte(s.refiller), + } + bf.components[iPadding] = &component{ + width: runewidth.StringWidth(stripansi.Strip(s.padding)), + bytes: []byte(s.padding), + } + bf.tip.frames = make([]*component, len(s.tip)) + for i, t := range s.tip { + bf.tip.frames[i] = &component{ + width: runewidth.StringWidth(stripansi.Strip(t)), + bytes: []byte(t), + } + } + return bf +} + +func (s *bFiller) Fill(w io.Writer, width int, stat decor.Statistics) { + width = internal.CheckRequestedWidth(width, stat.AvailableWidth) + brackets := s.components[iLbound].width + s.components[iRbound].width + if width < brackets { + return + } + // don't count brackets as progress + width -= brackets + + w.Write(s.components[iLbound].bytes) + defer w.Write(s.components[iRbound].bytes) + + curWidth := int(internal.PercentageRound(stat.Total, stat.Current, width)) + refWidth, filled := 0, curWidth + filling := make([][]byte, 0, curWidth) + + if curWidth > 0 && curWidth != width { + tipFrame := s.tip.frames[s.tip.count%uint(len(s.tip.frames))] + filling = append(filling, tipFrame.bytes) + curWidth -= tipFrame.width + s.tip.count++ + } + + if stat.Refill > 0 && curWidth > 0 { + refWidth = int(internal.PercentageRound(stat.Total, int64(stat.Refill), width)) + if refWidth > curWidth { + refWidth = curWidth + } + curWidth -= refWidth + } + + for curWidth > 0 && curWidth >= s.components[iFiller].width { + filling = append(filling, s.components[iFiller].bytes) + curWidth -= s.components[iFiller].width + if s.components[iFiller].width == 0 { + break + } + } + + for refWidth > 0 && refWidth >= s.components[iRefiller].width { + filling = append(filling, s.components[iRefiller].bytes) + refWidth -= s.components[iRefiller].width + if s.components[iRefiller].width == 0 { + break + } + } + + filled -= curWidth + refWidth + padWidth := width - filled + padding := make([][]byte, 0, padWidth) + for padWidth > 0 && padWidth >= s.components[iPadding].width { + padding = append(padding, s.components[iPadding].bytes) + padWidth -= s.components[iPadding].width + if s.components[iPadding].width == 0 { + break + } + } + + for padWidth > 0 { + padding = append(padding, []byte("…")) + padWidth-- + } + + s.flush(w, filling, padding) +} + +func flush(dst io.Writer, filling, padding [][]byte) { + for i := len(filling) - 1; i >= 0; i-- { + dst.Write(filling[i]) + } + for i := 0; i < len(padding); i++ { + dst.Write(padding[i]) + } +} diff --git a/vendor/github.com/vbauerster/mpb/v7/bar_filler_spinner.go b/vendor/github.com/vbauerster/mpb/v7/bar_filler_spinner.go new file mode 100644 index 000000000..58ae1c532 --- /dev/null +++ b/vendor/github.com/vbauerster/mpb/v7/bar_filler_spinner.go @@ -0,0 +1,87 @@ +package mpb + +import ( + "io" + "strings" + + "github.com/acarl005/stripansi" + "github.com/mattn/go-runewidth" + "github.com/vbauerster/mpb/v7/decor" + "github.com/vbauerster/mpb/v7/internal" +) + +const ( + positionLeft = 1 + iota + positionRight +) + +// SpinnerStyleComposer interface. +type SpinnerStyleComposer interface { + BarFillerBuilder + PositionLeft() SpinnerStyleComposer + PositionRight() SpinnerStyleComposer +} + +type sFiller struct { + count uint + position uint + frames []string +} + +type spinnerStyle struct { + position uint + frames []string +} + +// SpinnerStyle constructs default spinner style which can be altered via +// SpinnerStyleComposer interface. +func SpinnerStyle(frames ...string) SpinnerStyleComposer { + ss := new(spinnerStyle) + if len(frames) != 0 { + ss.frames = append(ss.frames, frames...) + } else { + ss.frames = []string{"⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"} + } + return ss +} + +func (s *spinnerStyle) PositionLeft() SpinnerStyleComposer { + s.position = positionLeft + return s +} + +func (s *spinnerStyle) PositionRight() SpinnerStyleComposer { + s.position = positionRight + return s +} + +func (s *spinnerStyle) Build() BarFiller { + sf := &sFiller{ + position: s.position, + frames: s.frames, + } + return sf +} + +func (s *sFiller) Fill(w io.Writer, width int, stat decor.Statistics) { + width = internal.CheckRequestedWidth(width, stat.AvailableWidth) + + frame := s.frames[s.count%uint(len(s.frames))] + frameWidth := runewidth.StringWidth(stripansi.Strip(frame)) + + if width < frameWidth { + return + } + + rest := width - frameWidth + switch s.position { + case positionLeft: + io.WriteString(w, frame+strings.Repeat(" ", rest)) + case positionRight: + io.WriteString(w, strings.Repeat(" ", rest)+frame) + default: + str := strings.Repeat(" ", rest/2) + frame + strings.Repeat(" ", rest/2+rest%2) + io.WriteString(w, str) + } + s.count++ +} diff --git a/vendor/github.com/vbauerster/mpb/v7/bar_option.go b/vendor/github.com/vbauerster/mpb/v7/bar_option.go new file mode 100644 index 000000000..46b7de0bf --- /dev/null +++ b/vendor/github.com/vbauerster/mpb/v7/bar_option.go @@ -0,0 +1,153 @@ +package mpb + +import ( + "bytes" + "io" + + "github.com/vbauerster/mpb/v7/decor" + "github.com/vbauerster/mpb/v7/internal" +) + +// BarOption is a func option to alter default behavior of a bar. +type BarOption func(*bState) + +func (s *bState) addDecorators(dest *[]decor.Decorator, decorators ...decor.Decorator) { + type mergeWrapper interface { + MergeUnwrap() []decor.Decorator + } + for _, decorator := range decorators { + if mw, ok := decorator.(mergeWrapper); ok { + *dest = append(*dest, mw.MergeUnwrap()...) + } + *dest = append(*dest, decorator) + } +} + +// AppendDecorators let you inject decorators to the bar's right side. +func AppendDecorators(decorators ...decor.Decorator) BarOption { + return func(s *bState) { + s.addDecorators(&s.aDecorators, decorators...) + } +} + +// PrependDecorators let you inject decorators to the bar's left side. +func PrependDecorators(decorators ...decor.Decorator) BarOption { + return func(s *bState) { + s.addDecorators(&s.pDecorators, decorators...) + } +} + +// BarID sets bar id. +func BarID(id int) BarOption { + return func(s *bState) { + s.id = id + } +} + +// BarWidth sets bar width independent of the container. +func BarWidth(width int) BarOption { + return func(s *bState) { + s.reqWidth = width + } +} + +// BarQueueAfter queues this (being constructed) bar to relplace +// runningBar after it has been completed. +func BarQueueAfter(runningBar *Bar) BarOption { + if runningBar == nil { + return nil + } + return func(s *bState) { + s.runningBar = runningBar + } +} + +// BarRemoveOnComplete removes both bar's filler and its decorators +// on complete event. +func BarRemoveOnComplete() BarOption { + return func(s *bState) { + s.dropOnComplete = true + } +} + +// BarFillerClearOnComplete clears bar's filler on complete event. +// It's shortcut for BarFillerOnComplete(""). +func BarFillerClearOnComplete() BarOption { + return BarFillerOnComplete("") +} + +// BarFillerOnComplete replaces bar's filler with message, on complete event. +func BarFillerOnComplete(message string) BarOption { + return BarFillerMiddleware(func(base BarFiller) BarFiller { + return BarFillerFunc(func(w io.Writer, reqWidth int, st decor.Statistics) { + if st.Completed { + io.WriteString(w, message) + } else { + base.Fill(w, reqWidth, st) + } + }) + }) +} + +// BarFillerMiddleware provides a way to augment the underlying BarFiller. +func BarFillerMiddleware(middle func(BarFiller) BarFiller) BarOption { + return func(s *bState) { + s.middleware = middle + } +} + +// BarPriority sets bar's priority. Zero is highest priority, i.e. bar +// will be on top. If `BarReplaceOnComplete` option is supplied, this +// option is ignored. +func BarPriority(priority int) BarOption { + return func(s *bState) { + s.priority = priority + } +} + +// BarExtender provides a way to extend bar to the next new line. +func BarExtender(filler BarFiller) BarOption { + if filler == nil { + return nil + } + return func(s *bState) { + s.extender = makeExtenderFunc(filler) + } +} + +func makeExtenderFunc(filler BarFiller) extenderFunc { + buf := new(bytes.Buffer) + return func(r io.Reader, reqWidth int, st decor.Statistics) (io.Reader, int) { + filler.Fill(buf, reqWidth, st) + return io.MultiReader(r, buf), bytes.Count(buf.Bytes(), []byte("\n")) + } +} + +// BarFillerTrim removes leading and trailing space around the underlying BarFiller. +func BarFillerTrim() BarOption { + return func(s *bState) { + s.trimSpace = true + } +} + +// BarNoPop disables bar pop out of container. Effective when +// PopCompletedMode of container is enabled. +func BarNoPop() BarOption { + return func(s *bState) { + s.noPop = true + } +} + +// BarOptional will invoke provided option only when pick is true. +func BarOptional(option BarOption, pick bool) BarOption { + return BarOptOn(option, internal.Predicate(pick)) +} + +// BarOptOn will invoke provided option only when higher order predicate +// evaluates to true. +func BarOptOn(option BarOption, predicate func() bool) BarOption { + if predicate() { + return option + } + return nil +} diff --git a/vendor/github.com/vbauerster/mpb/v7/container_option.go b/vendor/github.com/vbauerster/mpb/v7/container_option.go new file mode 100644 index 000000000..e4254f662 --- /dev/null +++ b/vendor/github.com/vbauerster/mpb/v7/container_option.go @@ -0,0 +1,112 @@ +package mpb + +import ( + "io" + "io/ioutil" + "sync" + "time" + + "github.com/vbauerster/mpb/v7/internal" +) + +// ContainerOption is a func option to alter default behavior of a bar +// container. Container term refers to a Progress struct which can +// hold one or more Bars. +type ContainerOption func(*pState) + +// WithWaitGroup provides means to have a single joint point. If +// *sync.WaitGroup is provided, you can safely call just p.Wait() +// without calling Wait() on provided *sync.WaitGroup. Makes sense +// when there are more than one bar to render. +func WithWaitGroup(wg *sync.WaitGroup) ContainerOption { + return func(s *pState) { + s.uwg = wg + } +} + +// WithWidth sets container width. If not set it defaults to terminal +// width. A bar added to the container will inherit its width, unless +// overridden by `func BarWidth(int) BarOption`. +func WithWidth(width int) ContainerOption { + return func(s *pState) { + s.reqWidth = width + } +} + +// WithRefreshRate overrides default 120ms refresh rate. +func WithRefreshRate(d time.Duration) ContainerOption { + return func(s *pState) { + s.rr = d + } +} + +// WithManualRefresh disables internal auto refresh time.Ticker. +// Refresh will occur upon receive value from provided ch. +func WithManualRefresh(ch <-chan interface{}) ContainerOption { + return func(s *pState) { + s.externalRefresh = ch + } +} + +// WithRenderDelay delays rendering. By default rendering starts as +// soon as bar is added, with this option it's possible to delay +// rendering process by keeping provided chan unclosed. In other words +// rendering will start as soon as provided chan is closed. +func WithRenderDelay(ch <-chan struct{}) ContainerOption { + return func(s *pState) { + s.renderDelay = ch + } +} + +// WithShutdownNotifier provided chanel will be closed, after all bars +// have been rendered. +func WithShutdownNotifier(ch chan struct{}) ContainerOption { + return func(s *pState) { + s.shutdownNotifier = ch + } +} + +// WithOutput overrides default os.Stdout output. Setting it to nil +// will effectively disable auto refresh rate and discard any output, +// useful if you want to disable progress bars with little overhead. +func WithOutput(w io.Writer) ContainerOption { + return func(s *pState) { + if w == nil { + s.output = ioutil.Discard + s.outputDiscarded = true + return + } + s.output = w + } +} + +// WithDebugOutput sets debug output. +func WithDebugOutput(w io.Writer) ContainerOption { + if w == nil { + return nil + } + return func(s *pState) { + s.debugOut = w + } +} + +// PopCompletedMode will pop and stop rendering completed bars. +func PopCompletedMode() ContainerOption { + return func(s *pState) { + s.popCompleted = true + } +} + +// ContainerOptional will invoke provided option only when pick is true. +func ContainerOptional(option ContainerOption, pick bool) ContainerOption { + return ContainerOptOn(option, internal.Predicate(pick)) +} + +// ContainerOptOn will invoke provided option only when higher order +// predicate evaluates to true. +func ContainerOptOn(option ContainerOption, predicate func() bool) ContainerOption { + if predicate() { + return option + } + return nil +} diff --git a/vendor/github.com/vbauerster/mpb/v7/cwriter/doc.go b/vendor/github.com/vbauerster/mpb/v7/cwriter/doc.go new file mode 100644 index 000000000..93c8f8268 --- /dev/null +++ b/vendor/github.com/vbauerster/mpb/v7/cwriter/doc.go @@ -0,0 +1,2 @@ +// Package cwriter is a console writer abstraction for the underlying OS. +package cwriter diff --git a/vendor/github.com/vbauerster/mpb/v7/cwriter/util_bsd.go b/vendor/github.com/vbauerster/mpb/v7/cwriter/util_bsd.go new file mode 100644 index 000000000..4e3564ece --- /dev/null +++ b/vendor/github.com/vbauerster/mpb/v7/cwriter/util_bsd.go @@ -0,0 +1,7 @@ +// +build darwin dragonfly freebsd netbsd openbsd + +package cwriter + +import "golang.org/x/sys/unix" + +const ioctlReadTermios = unix.TIOCGETA diff --git a/vendor/github.com/vbauerster/mpb/v7/cwriter/util_linux.go b/vendor/github.com/vbauerster/mpb/v7/cwriter/util_linux.go new file mode 100644 index 000000000..253f12dd2 --- /dev/null +++ b/vendor/github.com/vbauerster/mpb/v7/cwriter/util_linux.go @@ -0,0 +1,7 @@ +// +build aix linux + +package cwriter + +import "golang.org/x/sys/unix" + +const ioctlReadTermios = unix.TCGETS diff --git a/vendor/github.com/vbauerster/mpb/v7/cwriter/util_solaris.go b/vendor/github.com/vbauerster/mpb/v7/cwriter/util_solaris.go new file mode 100644 index 000000000..4b29ff5c0 --- /dev/null +++ b/vendor/github.com/vbauerster/mpb/v7/cwriter/util_solaris.go @@ -0,0 +1,7 @@ +// +build solaris + +package cwriter + +import "golang.org/x/sys/unix" + +const ioctlReadTermios = unix.TCGETA diff --git a/vendor/github.com/vbauerster/mpb/v7/cwriter/writer.go b/vendor/github.com/vbauerster/mpb/v7/cwriter/writer.go new file mode 100644 index 000000000..1ade54761 --- /dev/null +++ b/vendor/github.com/vbauerster/mpb/v7/cwriter/writer.go @@ -0,0 +1,84 @@ +package cwriter + +import ( + "bytes" + "errors" + "io" + "os" + "strconv" +) + +// ErrNotTTY not a TeleTYpewriter error. +var ErrNotTTY = errors.New("not a terminal") + +// http://ascii-table.com/ansi-escape-sequences.php +const ( + escOpen = "\x1b[" + cuuAndEd = "A\x1b[J" +) + +// Writer is a buffered the writer that updates the terminal. The +// contents of writer will be flushed when Flush is called. +type Writer struct { + out io.Writer + buf bytes.Buffer + lineCount int + fd int + isTerminal bool +} + +// New returns a new Writer with defaults. +func New(out io.Writer) *Writer { + w := &Writer{out: out} + if f, ok := out.(*os.File); ok { + w.fd = int(f.Fd()) + w.isTerminal = IsTerminal(w.fd) + } + return w +} + +// Flush flushes the underlying buffer. +func (w *Writer) Flush(lineCount int) (err error) { + // some terminals interpret 'cursor up 0' as 'cursor up 1' + if w.lineCount > 0 { + err = w.clearLines() + if err != nil { + return + } + } + w.lineCount = lineCount + _, err = w.buf.WriteTo(w.out) + return +} + +// Write appends the contents of p to the underlying buffer. +func (w *Writer) Write(p []byte) (n int, err error) { + return w.buf.Write(p) +} + +// WriteString writes string to the underlying buffer. +func (w *Writer) WriteString(s string) (n int, err error) { + return w.buf.WriteString(s) +} + +// ReadFrom reads from the provided io.Reader and writes to the +// underlying buffer. +func (w *Writer) ReadFrom(r io.Reader) (n int64, err error) { + return w.buf.ReadFrom(r) +} + +// GetWidth returns width of underlying terminal. +func (w *Writer) GetWidth() (int, error) { + if !w.isTerminal { + return -1, ErrNotTTY + } + tw, _, err := GetSize(w.fd) + return tw, err +} + +func (w *Writer) ansiCuuAndEd() (err error) { + buf := make([]byte, 8) + buf = strconv.AppendInt(buf[:copy(buf, escOpen)], int64(w.lineCount), 10) + _, err = w.out.Write(append(buf, cuuAndEd...)) + return +} diff --git a/vendor/github.com/vbauerster/mpb/v7/cwriter/writer_posix.go b/vendor/github.com/vbauerster/mpb/v7/cwriter/writer_posix.go new file mode 100644 index 000000000..f54a5d06b --- /dev/null +++ b/vendor/github.com/vbauerster/mpb/v7/cwriter/writer_posix.go @@ -0,0 +1,26 @@ +// +build !windows + +package cwriter + +import ( + "golang.org/x/sys/unix" +) + +func (w *Writer) clearLines() error { + return w.ansiCuuAndEd() +} + +// GetSize returns the dimensions of the given terminal. +func GetSize(fd int) (width, height int, err error) { + ws, err := unix.IoctlGetWinsize(fd, unix.TIOCGWINSZ) + if err != nil { + return -1, -1, err + } + return int(ws.Col), int(ws.Row), nil +} + +// IsTerminal returns whether the given file descriptor is a terminal. +func IsTerminal(fd int) bool { + _, err := unix.IoctlGetTermios(fd, ioctlReadTermios) + return err == nil +} diff --git a/vendor/github.com/vbauerster/mpb/v7/cwriter/writer_windows.go b/vendor/github.com/vbauerster/mpb/v7/cwriter/writer_windows.go new file mode 100644 index 000000000..1a69c81ac --- /dev/null +++ b/vendor/github.com/vbauerster/mpb/v7/cwriter/writer_windows.go @@ -0,0 +1,73 @@ +// +build windows + +package cwriter + +import ( + "unsafe" + + "golang.org/x/sys/windows" +) + +var kernel32 = windows.NewLazySystemDLL("kernel32.dll") + +var ( + procSetConsoleCursorPosition = kernel32.NewProc("SetConsoleCursorPosition") + procFillConsoleOutputCharacter = kernel32.NewProc("FillConsoleOutputCharacterW") +) + +func (w *Writer) clearLines() error { + if !w.isTerminal { + // hope it's cygwin or similar + return w.ansiCuuAndEd() + } + + var info windows.ConsoleScreenBufferInfo + if err := windows.GetConsoleScreenBufferInfo(windows.Handle(w.fd), &info); err != nil { + return err + } + + info.CursorPosition.Y -= int16(w.lineCount) + if info.CursorPosition.Y < 0 { + info.CursorPosition.Y = 0 + } + _, _, _ = procSetConsoleCursorPosition.Call( + uintptr(w.fd), + uintptr(uint32(uint16(info.CursorPosition.Y))<<16|uint32(uint16(info.CursorPosition.X))), + ) + + // clear the lines + cursor := &windows.Coord{ + X: info.Window.Left, + Y: info.CursorPosition.Y, + } + count := uint32(info.Size.X) * uint32(w.lineCount) + _, _, _ = procFillConsoleOutputCharacter.Call( + uintptr(w.fd), + uintptr(' '), + uintptr(count), + *(*uintptr)(unsafe.Pointer(cursor)), + uintptr(unsafe.Pointer(new(uint32))), + ) + return nil +} + +// GetSize returns the visible dimensions of the given terminal. +// +// These dimensions don't include any scrollback buffer height. +func GetSize(fd int) (width, height int, err error) { + var info windows.ConsoleScreenBufferInfo + if err := windows.GetConsoleScreenBufferInfo(windows.Handle(fd), &info); err != nil { + return 0, 0, err + } + // terminal.GetSize from crypto/ssh adds "+ 1" to both width and height: + // https://go.googlesource.com/crypto/+/refs/heads/release-branch.go1.14/ssh/terminal/util_windows.go#75 + // but looks like this is a root cause of issue #66, so removing both "+ 1" have fixed it. + return int(info.Window.Right - info.Window.Left), int(info.Window.Bottom - info.Window.Top), nil +} + +// IsTerminal returns whether the given file descriptor is a terminal. +func IsTerminal(fd int) bool { + var st uint32 + err := windows.GetConsoleMode(windows.Handle(fd), &st) + return err == nil +} diff --git a/vendor/github.com/vbauerster/mpb/v7/decor/any.go b/vendor/github.com/vbauerster/mpb/v7/decor/any.go new file mode 100644 index 000000000..39518f594 --- /dev/null +++ b/vendor/github.com/vbauerster/mpb/v7/decor/any.go @@ -0,0 +1,21 @@ +package decor + +// Any decorator displays text, that can be changed during decorator's +// lifetime via provided DecorFunc. +// +// `fn` DecorFunc callback +// +// `wcc` optional WC config +// +func Any(fn DecorFunc, wcc ...WC) Decorator { + return &any{initWC(wcc...), fn} +} + +type any struct { + WC + fn DecorFunc +} + +func (d *any) Decor(s Statistics) string { + return d.FormatMsg(d.fn(s)) +} diff --git a/vendor/github.com/vbauerster/mpb/v7/decor/counters.go b/vendor/github.com/vbauerster/mpb/v7/decor/counters.go new file mode 100644 index 000000000..4a5343d41 --- /dev/null +++ b/vendor/github.com/vbauerster/mpb/v7/decor/counters.go @@ -0,0 +1,243 @@ +package decor + +import ( + "fmt" + "strings" +) + +const ( + _ = iota + UnitKiB + UnitKB +) + +// CountersNoUnit is a wrapper around Counters with no unit param. +func CountersNoUnit(pairFmt string, wcc ...WC) Decorator { + return Counters(0, pairFmt, wcc...) +} + +// CountersKibiByte is a wrapper around Counters with predefined unit +// UnitKiB (bytes/1024). +func CountersKibiByte(pairFmt string, wcc ...WC) Decorator { + return Counters(UnitKiB, pairFmt, wcc...) +} + +// CountersKiloByte is a wrapper around Counters with predefined unit +// UnitKB (bytes/1000). +func CountersKiloByte(pairFmt string, wcc ...WC) Decorator { + return Counters(UnitKB, pairFmt, wcc...) +} + +// Counters decorator with dynamic unit measure adjustment. +// +// `unit` one of [0|UnitKiB|UnitKB] zero for no unit +// +// `pairFmt` printf compatible verbs for current and total pair +// +// `wcc` optional WC config +// +// pairFmt example if unit=UnitKB: +// +// pairFmt="%.1f / %.1f" output: "1.0MB / 12.0MB" +// pairFmt="% .1f / % .1f" output: "1.0 MB / 12.0 MB" +// pairFmt="%d / %d" output: "1MB / 12MB" +// pairFmt="% d / % d" output: "1 MB / 12 MB" +// +func Counters(unit int, pairFmt string, wcc ...WC) Decorator { + producer := func(unit int, pairFmt string) DecorFunc { + if pairFmt == "" { + pairFmt = "%d / %d" + } else if strings.Count(pairFmt, "%") != 2 { + panic("expected pairFmt with exactly 2 verbs") + } + switch unit { + case UnitKiB: + return func(s Statistics) string { + return fmt.Sprintf(pairFmt, SizeB1024(s.Current), SizeB1024(s.Total)) + } + case UnitKB: + return func(s Statistics) string { + return fmt.Sprintf(pairFmt, SizeB1000(s.Current), SizeB1000(s.Total)) + } + default: + return func(s Statistics) string { + return fmt.Sprintf(pairFmt, s.Current, s.Total) + } + } + } + return Any(producer(unit, pairFmt), wcc...) +} + +// TotalNoUnit is a wrapper around Total with no unit param. +func TotalNoUnit(format string, wcc ...WC) Decorator { + return Total(0, format, wcc...) +} + +// TotalKibiByte is a wrapper around Total with predefined unit +// UnitKiB (bytes/1024). +func TotalKibiByte(format string, wcc ...WC) Decorator { + return Total(UnitKiB, format, wcc...) +} + +// TotalKiloByte is a wrapper around Total with predefined unit +// UnitKB (bytes/1000). +func TotalKiloByte(format string, wcc ...WC) Decorator { + return Total(UnitKB, format, wcc...) +} + +// Total decorator with dynamic unit measure adjustment. +// +// `unit` one of [0|UnitKiB|UnitKB] zero for no unit +// +// `format` printf compatible verb for Total +// +// `wcc` optional WC config +// +// format example if unit=UnitKiB: +// +// format="%.1f" output: "12.0MiB" +// format="% .1f" output: "12.0 MiB" +// format="%d" output: "12MiB" +// format="% d" output: "12 MiB" +// +func Total(unit int, format string, wcc ...WC) Decorator { + producer := func(unit int, format string) DecorFunc { + if format == "" { + format = "%d" + } else if strings.Count(format, "%") != 1 { + panic("expected format with exactly 1 verb") + } + + switch unit { + case UnitKiB: + return func(s Statistics) string { + return fmt.Sprintf(format, SizeB1024(s.Total)) + } + case UnitKB: + return func(s Statistics) string { + return fmt.Sprintf(format, SizeB1000(s.Total)) + } + default: + return func(s Statistics) string { + return fmt.Sprintf(format, s.Total) + } + } + } + return Any(producer(unit, format), wcc...) +} + +// CurrentNoUnit is a wrapper around Current with no unit param. +func CurrentNoUnit(format string, wcc ...WC) Decorator { + return Current(0, format, wcc...) +} + +// CurrentKibiByte is a wrapper around Current with predefined unit +// UnitKiB (bytes/1024). +func CurrentKibiByte(format string, wcc ...WC) Decorator { + return Current(UnitKiB, format, wcc...) +} + +// CurrentKiloByte is a wrapper around Current with predefined unit +// UnitKB (bytes/1000). +func CurrentKiloByte(format string, wcc ...WC) Decorator { + return Current(UnitKB, format, wcc...) +} + +// Current decorator with dynamic unit measure adjustment. +// +// `unit` one of [0|UnitKiB|UnitKB] zero for no unit +// +// `format` printf compatible verb for Current +// +// `wcc` optional WC config +// +// format example if unit=UnitKiB: +// +// format="%.1f" output: "12.0MiB" +// format="% .1f" output: "12.0 MiB" +// format="%d" output: "12MiB" +// format="% d" output: "12 MiB" +// +func Current(unit int, format string, wcc ...WC) Decorator { + producer := func(unit int, format string) DecorFunc { + if format == "" { + format = "%d" + } else if strings.Count(format, "%") != 1 { + panic("expected format with exactly 1 verb") + } + + switch unit { + case UnitKiB: + return func(s Statistics) string { + return fmt.Sprintf(format, SizeB1024(s.Current)) + } + case UnitKB: + return func(s Statistics) string { + return fmt.Sprintf(format, SizeB1000(s.Current)) + } + default: + return func(s Statistics) string { + return fmt.Sprintf(format, s.Current) + } + } + } + return Any(producer(unit, format), wcc...) +} + +// InvertedCurrentNoUnit is a wrapper around InvertedCurrent with no unit param. +func InvertedCurrentNoUnit(format string, wcc ...WC) Decorator { + return InvertedCurrent(0, format, wcc...) +} + +// InvertedCurrentKibiByte is a wrapper around InvertedCurrent with predefined unit +// UnitKiB (bytes/1024). +func InvertedCurrentKibiByte(format string, wcc ...WC) Decorator { + return InvertedCurrent(UnitKiB, format, wcc...) +} + +// InvertedCurrentKiloByte is a wrapper around InvertedCurrent with predefined unit +// UnitKB (bytes/1000). +func InvertedCurrentKiloByte(format string, wcc ...WC) Decorator { + return InvertedCurrent(UnitKB, format, wcc...) +} + +// InvertedCurrent decorator with dynamic unit measure adjustment. +// +// `unit` one of [0|UnitKiB|UnitKB] zero for no unit +// +// `format` printf compatible verb for InvertedCurrent +// +// `wcc` optional WC config +// +// format example if unit=UnitKiB: +// +// format="%.1f" output: "12.0MiB" +// format="% .1f" output: "12.0 MiB" +// format="%d" output: "12MiB" +// format="% d" output: "12 MiB" +// +func InvertedCurrent(unit int, format string, wcc ...WC) Decorator { + producer := func(unit int, format string) DecorFunc { + if format == "" { + format = "%d" + } else if strings.Count(format, "%") != 1 { + panic("expected format with exactly 1 verb") + } + + switch unit { + case UnitKiB: + return func(s Statistics) string { + return fmt.Sprintf(format, SizeB1024(s.Total-s.Current)) + } + case UnitKB: + return func(s Statistics) string { + return fmt.Sprintf(format, SizeB1000(s.Total-s.Current)) + } + default: + return func(s Statistics) string { + return fmt.Sprintf(format, s.Total-s.Current) + } + } + } + return Any(producer(unit, format), wcc...) +} diff --git a/vendor/github.com/vbauerster/mpb/v7/decor/decorator.go b/vendor/github.com/vbauerster/mpb/v7/decor/decorator.go new file mode 100644 index 000000000..e81fae367 --- /dev/null +++ b/vendor/github.com/vbauerster/mpb/v7/decor/decorator.go @@ -0,0 +1,191 @@ +package decor + +import ( + "fmt" + "time" + + "github.com/acarl005/stripansi" + "github.com/mattn/go-runewidth" +) + +const ( + // DidentRight bit specifies identation direction. + // |foo |b | With DidentRight + // | foo| b| Without DidentRight + DidentRight = 1 << iota + + // DextraSpace bit adds extra space, makes sense with DSyncWidth only. + // When DidentRight bit set, the space will be added to the right, + // otherwise to the left. + DextraSpace + + // DSyncWidth bit enables same column width synchronization. + // Effective with multiple bars only. + DSyncWidth + + // DSyncWidthR is shortcut for DSyncWidth|DidentRight + DSyncWidthR = DSyncWidth | DidentRight + + // DSyncSpace is shortcut for DSyncWidth|DextraSpace + DSyncSpace = DSyncWidth | DextraSpace + + // DSyncSpaceR is shortcut for DSyncWidth|DextraSpace|DidentRight + DSyncSpaceR = DSyncWidth | DextraSpace | DidentRight +) + +// TimeStyle enum. +type TimeStyle int + +// TimeStyle kinds. +const ( + ET_STYLE_GO TimeStyle = iota + ET_STYLE_HHMMSS + ET_STYLE_HHMM + ET_STYLE_MMSS +) + +// Statistics consists of progress related statistics, that Decorator +// may need. +type Statistics struct { + ID int + AvailableWidth int + Total int64 + Current int64 + Refill int64 + Completed bool +} + +// Decorator interface. +// Most of the time there is no need to implement this interface +// manually, as decor package already provides a wide range of decorators +// which implement this interface. If however built-in decorators don't +// meet your needs, you're free to implement your own one by implementing +// this particular interface. The easy way to go is to convert a +// `DecorFunc` into a `Decorator` interface by using provided +// `func Any(DecorFunc, ...WC) Decorator`. +type Decorator interface { + Configurator + Synchronizer + Decor(Statistics) string +} + +// DecorFunc func type. +// To be used with `func Any`(DecorFunc, ...WC) Decorator`. +type DecorFunc func(Statistics) string + +// Synchronizer interface. +// All decorators implement this interface implicitly. Its Sync +// method exposes width sync channel, if DSyncWidth bit is set. +type Synchronizer interface { + Sync() (chan int, bool) +} + +// Configurator interface. +type Configurator interface { + GetConf() WC + SetConf(WC) +} + +// Wrapper interface. +// If you're implementing custom Decorator by wrapping a built-in one, +// it is necessary to implement this interface to retain functionality +// of built-in Decorator. +type Wrapper interface { + Base() Decorator +} + +// EwmaDecorator interface. +// EWMA based decorators should implement this one. +type EwmaDecorator interface { + EwmaUpdate(int64, time.Duration) +} + +// AverageDecorator interface. +// Average decorators should implement this interface to provide start +// time adjustment facility, for resume-able tasks. +type AverageDecorator interface { + AverageAdjust(time.Time) +} + +// ShutdownListener interface. +// If decorator needs to be notified once upon bar shutdown event, so +// this is the right interface to implement. +type ShutdownListener interface { + Shutdown() +} + +// Global convenience instances of WC with sync width bit set. +// To be used with multiple bars only, i.e. not effective for single bar usage. +var ( + WCSyncWidth = WC{C: DSyncWidth} + WCSyncWidthR = WC{C: DSyncWidthR} + WCSyncSpace = WC{C: DSyncSpace} + WCSyncSpaceR = WC{C: DSyncSpaceR} +) + +// WC is a struct with two public fields W and C, both of int type. +// W represents width and C represents bit set of width related config. +// A decorator should embed WC, to enable width synchronization. +type WC struct { + W int + C int + fill func(s string, w int) string + wsync chan int +} + +// FormatMsg formats final message according to WC.W and WC.C. +// Should be called by any Decorator implementation. +func (wc *WC) FormatMsg(msg string) string { + pureWidth := runewidth.StringWidth(msg) + stripWidth := runewidth.StringWidth(stripansi.Strip(msg)) + maxCell := wc.W + if (wc.C & DSyncWidth) != 0 { + cellCount := stripWidth + if (wc.C & DextraSpace) != 0 { + cellCount++ + } + wc.wsync <- cellCount + maxCell = <-wc.wsync + } + return wc.fill(msg, maxCell+(pureWidth-stripWidth)) +} + +// Init initializes width related config. +func (wc *WC) Init() WC { + wc.fill = runewidth.FillLeft + if (wc.C & DidentRight) != 0 { + wc.fill = runewidth.FillRight + } + if (wc.C & DSyncWidth) != 0 { + // it's deliberate choice to override wsync on each Init() call, + // this way globals like WCSyncSpace can be reused + wc.wsync = make(chan int) + } + return *wc +} + +// Sync is implementation of Synchronizer interface. +func (wc *WC) Sync() (chan int, bool) { + if (wc.C&DSyncWidth) != 0 && wc.wsync == nil { + panic(fmt.Sprintf("%T is not initialized", wc)) + } + return wc.wsync, (wc.C & DSyncWidth) != 0 +} + +// GetConf is implementation of Configurator interface. +func (wc *WC) GetConf() WC { + return *wc +} + +// SetConf is implementation of Configurator interface. +func (wc *WC) SetConf(conf WC) { + *wc = conf.Init() +} + +func initWC(wcc ...WC) WC { + var wc WC + for _, nwc := range wcc { + wc = nwc + } + return wc.Init() +} diff --git a/vendor/github.com/vbauerster/mpb/v7/decor/doc.go b/vendor/github.com/vbauerster/mpb/v7/decor/doc.go new file mode 100644 index 000000000..4e4299307 --- /dev/null +++ b/vendor/github.com/vbauerster/mpb/v7/decor/doc.go @@ -0,0 +1,19 @@ +// Package decor provides common decorators for "github.com/vbauerster/mpb/v7" module. +// +// Some decorators returned by this package might have a closure state. It is ok to use +// decorators concurrently, unless you share the same decorator among multiple +// *mpb.Bar instances. To avoid data races, create new decorator per *mpb.Bar instance. +// +// Don't: +// +// p := mpb.New() +// name := decor.Name("bar") +// p.AddBar(100, mpb.AppendDecorators(name)) +// p.AddBar(100, mpb.AppendDecorators(name)) +// +// Do: +// +// p := mpb.New() +// p.AddBar(100, mpb.AppendDecorators(decor.Name("bar1"))) +// p.AddBar(100, mpb.AppendDecorators(decor.Name("bar2"))) +package decor diff --git a/vendor/github.com/vbauerster/mpb/v7/decor/elapsed.go b/vendor/github.com/vbauerster/mpb/v7/decor/elapsed.go new file mode 100644 index 000000000..e389f1581 --- /dev/null +++ b/vendor/github.com/vbauerster/mpb/v7/decor/elapsed.go @@ -0,0 +1,35 @@ +package decor + +import ( + "time" +) + +// Elapsed decorator. It's wrapper of NewElapsed. +// +// `style` one of [ET_STYLE_GO|ET_STYLE_HHMMSS|ET_STYLE_HHMM|ET_STYLE_MMSS] +// +// `wcc` optional WC config +// +func Elapsed(style TimeStyle, wcc ...WC) Decorator { + return NewElapsed(style, time.Now(), wcc...) +} + +// NewElapsed returns elapsed time decorator. +// +// `style` one of [ET_STYLE_GO|ET_STYLE_HHMMSS|ET_STYLE_HHMM|ET_STYLE_MMSS] +// +// `startTime` start time +// +// `wcc` optional WC config +// +func NewElapsed(style TimeStyle, startTime time.Time, wcc ...WC) Decorator { + var msg string + producer := chooseTimeProducer(style) + fn := func(s Statistics) string { + if !s.Completed { + msg = producer(time.Since(startTime)) + } + return msg + } + return Any(fn, wcc...) +} diff --git a/vendor/github.com/vbauerster/mpb/v7/decor/eta.go b/vendor/github.com/vbauerster/mpb/v7/decor/eta.go new file mode 100644 index 000000000..d03caa735 --- /dev/null +++ b/vendor/github.com/vbauerster/mpb/v7/decor/eta.go @@ -0,0 +1,203 @@ +package decor + +import ( + "fmt" + "math" + "time" + + "github.com/VividCortex/ewma" +) + +// TimeNormalizer interface. Implementors could be passed into +// MovingAverageETA, in order to affect i.e. normalize its output. +type TimeNormalizer interface { + Normalize(time.Duration) time.Duration +} + +// TimeNormalizerFunc is function type adapter to convert function +// into TimeNormalizer. +type TimeNormalizerFunc func(time.Duration) time.Duration + +func (f TimeNormalizerFunc) Normalize(src time.Duration) time.Duration { + return f(src) +} + +// EwmaETA exponential-weighted-moving-average based ETA decorator. +// For this decorator to work correctly you have to measure each +// iteration's duration and pass it to the +// *Bar.DecoratorEwmaUpdate(time.Duration) method after each increment. +func EwmaETA(style TimeStyle, age float64, wcc ...WC) Decorator { + var average ewma.MovingAverage + if age == 0 { + average = ewma.NewMovingAverage() + } else { + average = ewma.NewMovingAverage(age) + } + return MovingAverageETA(style, NewThreadSafeMovingAverage(average), nil, wcc...) +} + +// MovingAverageETA decorator relies on MovingAverage implementation to calculate its average. +// +// `style` one of [ET_STYLE_GO|ET_STYLE_HHMMSS|ET_STYLE_HHMM|ET_STYLE_MMSS] +// +// `average` implementation of MovingAverage interface +// +// `normalizer` available implementations are [FixedIntervalTimeNormalizer|MaxTolerateTimeNormalizer] +// +// `wcc` optional WC config +// +func MovingAverageETA(style TimeStyle, average ewma.MovingAverage, normalizer TimeNormalizer, wcc ...WC) Decorator { + d := &movingAverageETA{ + WC: initWC(wcc...), + average: average, + normalizer: normalizer, + producer: chooseTimeProducer(style), + } + return d +} + +type movingAverageETA struct { + WC + average ewma.MovingAverage + normalizer TimeNormalizer + producer func(time.Duration) string +} + +func (d *movingAverageETA) Decor(s Statistics) string { + v := math.Round(d.average.Value()) + remaining := time.Duration((s.Total - s.Current) * int64(v)) + if d.normalizer != nil { + remaining = d.normalizer.Normalize(remaining) + } + return d.FormatMsg(d.producer(remaining)) +} + +func (d *movingAverageETA) EwmaUpdate(n int64, dur time.Duration) { + durPerItem := float64(dur) / float64(n) + if math.IsInf(durPerItem, 0) || math.IsNaN(durPerItem) { + return + } + d.average.Add(durPerItem) +} + +// AverageETA decorator. It's wrapper of NewAverageETA. +// +// `style` one of [ET_STYLE_GO|ET_STYLE_HHMMSS|ET_STYLE_HHMM|ET_STYLE_MMSS] +// +// `wcc` optional WC config +// +func AverageETA(style TimeStyle, wcc ...WC) Decorator { + return NewAverageETA(style, time.Now(), nil, wcc...) +} + +// NewAverageETA decorator with user provided start time. +// +// `style` one of [ET_STYLE_GO|ET_STYLE_HHMMSS|ET_STYLE_HHMM|ET_STYLE_MMSS] +// +// `startTime` start time +// +// `normalizer` available implementations are [FixedIntervalTimeNormalizer|MaxTolerateTimeNormalizer] +// +// `wcc` optional WC config +// +func NewAverageETA(style TimeStyle, startTime time.Time, normalizer TimeNormalizer, wcc ...WC) Decorator { + d := &averageETA{ + WC: initWC(wcc...), + startTime: startTime, + normalizer: normalizer, + producer: chooseTimeProducer(style), + } + return d +} + +type averageETA struct { + WC + startTime time.Time + normalizer TimeNormalizer + producer func(time.Duration) string +} + +func (d *averageETA) Decor(s Statistics) string { + var remaining time.Duration + if s.Current != 0 { + durPerItem := float64(time.Since(d.startTime)) / float64(s.Current) + durPerItem = math.Round(durPerItem) + remaining = time.Duration((s.Total - s.Current) * int64(durPerItem)) + if d.normalizer != nil { + remaining = d.normalizer.Normalize(remaining) + } + } + return d.FormatMsg(d.producer(remaining)) +} + +func (d *averageETA) AverageAdjust(startTime time.Time) { + d.startTime = startTime +} + +// MaxTolerateTimeNormalizer returns implementation of TimeNormalizer. +func MaxTolerateTimeNormalizer(maxTolerate time.Duration) TimeNormalizer { + var normalized time.Duration + var lastCall time.Time + return TimeNormalizerFunc(func(remaining time.Duration) time.Duration { + if diff := normalized - remaining; diff <= 0 || diff > maxTolerate || remaining < time.Minute { + normalized = remaining + lastCall = time.Now() + return remaining + } + normalized -= time.Since(lastCall) + lastCall = time.Now() + return normalized + }) +} + +// FixedIntervalTimeNormalizer returns implementation of TimeNormalizer. +func FixedIntervalTimeNormalizer(updInterval int) TimeNormalizer { + var normalized time.Duration + var lastCall time.Time + var count int + return TimeNormalizerFunc(func(remaining time.Duration) time.Duration { + if count == 0 || remaining < time.Minute { + count = updInterval + normalized = remaining + lastCall = time.Now() + return remaining + } + count-- + normalized -= time.Since(lastCall) + lastCall = time.Now() + return normalized + }) +} + +func chooseTimeProducer(style TimeStyle) func(time.Duration) string { + switch style { + case ET_STYLE_HHMMSS: + return func(remaining time.Duration) string { + hours := int64(remaining/time.Hour) % 60 + minutes := int64(remaining/time.Minute) % 60 + seconds := int64(remaining/time.Second) % 60 + return fmt.Sprintf("%02d:%02d:%02d", hours, minutes, seconds) + } + case ET_STYLE_HHMM: + return func(remaining time.Duration) string { + hours := int64(remaining/time.Hour) % 60 + minutes := int64(remaining/time.Minute) % 60 + return fmt.Sprintf("%02d:%02d", hours, minutes) + } + case ET_STYLE_MMSS: + return func(remaining time.Duration) string { + hours := int64(remaining/time.Hour) % 60 + minutes := int64(remaining/time.Minute) % 60 + seconds := int64(remaining/time.Second) % 60 + if hours > 0 { + return fmt.Sprintf("%02d:%02d:%02d", hours, minutes, seconds) + } + return fmt.Sprintf("%02d:%02d", minutes, seconds) + } + default: + return func(remaining time.Duration) string { + // strip off nanoseconds + return ((remaining / time.Second) * time.Second).String() + } + } +} diff --git a/vendor/github.com/vbauerster/mpb/v7/decor/merge.go b/vendor/github.com/vbauerster/mpb/v7/decor/merge.go new file mode 100644 index 000000000..e41406a64 --- /dev/null +++ b/vendor/github.com/vbauerster/mpb/v7/decor/merge.go @@ -0,0 +1,107 @@ +package decor + +import ( + "strings" + + "github.com/acarl005/stripansi" + "github.com/mattn/go-runewidth" +) + +// Merge wraps its decorator argument with intention to sync width +// with several decorators of another bar. Visual example: +// +// +----+--------+---------+--------+ +// | B1 | MERGE(D, P1, Pn) | +// +----+--------+---------+--------+ +// | B2 | D0 | D1 | Dn | +// +----+--------+---------+--------+ +// +func Merge(decorator Decorator, placeholders ...WC) Decorator { + if _, ok := decorator.Sync(); !ok || len(placeholders) == 0 { + return decorator + } + md := &mergeDecorator{ + Decorator: decorator, + wc: decorator.GetConf(), + placeHolders: make([]*placeHolderDecorator, len(placeholders)), + } + decorator.SetConf(WC{}) + for i, wc := range placeholders { + if (wc.C & DSyncWidth) == 0 { + return decorator + } + md.placeHolders[i] = &placeHolderDecorator{wc.Init()} + } + return md +} + +type mergeDecorator struct { + Decorator + wc WC + placeHolders []*placeHolderDecorator +} + +func (d *mergeDecorator) GetConf() WC { + return d.wc +} + +func (d *mergeDecorator) SetConf(conf WC) { + d.wc = conf.Init() +} + +func (d *mergeDecorator) MergeUnwrap() []Decorator { + decorators := make([]Decorator, len(d.placeHolders)) + for i, ph := range d.placeHolders { + decorators[i] = ph + } + return decorators +} + +func (d *mergeDecorator) Sync() (chan int, bool) { + return d.wc.Sync() +} + +func (d *mergeDecorator) Base() Decorator { + return d.Decorator +} + +func (d *mergeDecorator) Decor(s Statistics) string { + msg := d.Decorator.Decor(s) + pureWidth := runewidth.StringWidth(msg) + stripWidth := runewidth.StringWidth(stripansi.Strip(msg)) + cellCount := stripWidth + if (d.wc.C & DextraSpace) != 0 { + cellCount++ + } + + total := runewidth.StringWidth(d.placeHolders[0].FormatMsg("")) + pw := (cellCount - total) / len(d.placeHolders) + rem := (cellCount - total) % len(d.placeHolders) + + var diff int + for i := 1; i < len(d.placeHolders); i++ { + ph := d.placeHolders[i] + width := pw - diff + if (ph.WC.C & DextraSpace) != 0 { + width-- + if width < 0 { + width = 0 + } + } + max := runewidth.StringWidth(ph.FormatMsg(strings.Repeat(" ", width))) + total += max + diff = max - pw + } + + d.wc.wsync <- pw + rem + max := <-d.wc.wsync + return d.wc.fill(msg, max+total+(pureWidth-stripWidth)) +} + +type placeHolderDecorator struct { + WC +} + +func (d *placeHolderDecorator) Decor(Statistics) string { + return "" +} diff --git a/vendor/github.com/vbauerster/mpb/v7/decor/moving_average.go b/vendor/github.com/vbauerster/mpb/v7/decor/moving_average.go new file mode 100644 index 000000000..50ac9c393 --- /dev/null +++ b/vendor/github.com/vbauerster/mpb/v7/decor/moving_average.go @@ -0,0 +1,68 @@ +package decor + +import ( + "sort" + "sync" + + "github.com/VividCortex/ewma" +) + +type threadSafeMovingAverage struct { + ewma.MovingAverage + mu sync.Mutex +} + +func (s *threadSafeMovingAverage) Add(value float64) { + s.mu.Lock() + s.MovingAverage.Add(value) + s.mu.Unlock() +} + +func (s *threadSafeMovingAverage) Value() float64 { + s.mu.Lock() + defer s.mu.Unlock() + return s.MovingAverage.Value() +} + +func (s *threadSafeMovingAverage) Set(value float64) { + s.mu.Lock() + s.MovingAverage.Set(value) + s.mu.Unlock() +} + +// NewThreadSafeMovingAverage converts provided ewma.MovingAverage +// into thread safe ewma.MovingAverage. +func NewThreadSafeMovingAverage(average ewma.MovingAverage) ewma.MovingAverage { + if tsma, ok := average.(*threadSafeMovingAverage); ok { + return tsma + } + return &threadSafeMovingAverage{MovingAverage: average} +} + +type medianWindow [3]float64 + +func (s *medianWindow) Len() int { return len(s) } +func (s *medianWindow) Swap(i, j int) { s[i], s[j] = s[j], s[i] } +func (s *medianWindow) Less(i, j int) bool { return s[i] < s[j] } + +func (s *medianWindow) Add(value float64) { + s[0], s[1] = s[1], s[2] + s[2] = value +} + +func (s *medianWindow) Value() float64 { + tmp := *s + sort.Sort(&tmp) + return tmp[1] +} + +func (s *medianWindow) Set(value float64) { + for i := 0; i < len(s); i++ { + s[i] = value + } +} + +// NewMedian is fixed last 3 samples median MovingAverage. +func NewMedian() ewma.MovingAverage { + return NewThreadSafeMovingAverage(new(medianWindow)) +} diff --git a/vendor/github.com/vbauerster/mpb/v7/decor/name.go b/vendor/github.com/vbauerster/mpb/v7/decor/name.go new file mode 100644 index 000000000..3af311254 --- /dev/null +++ b/vendor/github.com/vbauerster/mpb/v7/decor/name.go @@ -0,0 +1,12 @@ +package decor + +// Name decorator displays text that is set once and can't be changed +// during decorator's lifetime. +// +// `str` string to display +// +// `wcc` optional WC config +// +func Name(str string, wcc ...WC) Decorator { + return Any(func(Statistics) string { return str }, wcc...) +} diff --git a/vendor/github.com/vbauerster/mpb/v7/decor/on_complete.go b/vendor/github.com/vbauerster/mpb/v7/decor/on_complete.go new file mode 100644 index 000000000..f46b19aba --- /dev/null +++ b/vendor/github.com/vbauerster/mpb/v7/decor/on_complete.go @@ -0,0 +1,37 @@ +package decor + +// OnComplete returns decorator, which wraps provided decorator, with +// sole purpose to display provided message on complete event. +// +// `decorator` Decorator to wrap +// +// `message` message to display on complete event +// +func OnComplete(decorator Decorator, message string) Decorator { + d := &onCompleteWrapper{ + Decorator: decorator, + msg: message, + } + if md, ok := decorator.(*mergeDecorator); ok { + d.Decorator, md.Decorator = md.Decorator, d + return md + } + return d +} + +type onCompleteWrapper struct { + Decorator + msg string +} + +func (d *onCompleteWrapper) Decor(s Statistics) string { + if s.Completed { + wc := d.GetConf() + return wc.FormatMsg(d.msg) + } + return d.Decorator.Decor(s) +} + +func (d *onCompleteWrapper) Base() Decorator { + return d.Decorator +} diff --git a/vendor/github.com/vbauerster/mpb/v7/decor/percentage.go b/vendor/github.com/vbauerster/mpb/v7/decor/percentage.go new file mode 100644 index 000000000..2b0a7a956 --- /dev/null +++ b/vendor/github.com/vbauerster/mpb/v7/decor/percentage.go @@ -0,0 +1,58 @@ +package decor + +import ( + "fmt" + "io" + "strconv" + + "github.com/vbauerster/mpb/v7/internal" +) + +type percentageType float64 + +func (s percentageType) Format(st fmt.State, verb rune) { + var prec int + switch verb { + case 'd': + case 's': + prec = -1 + default: + if p, ok := st.Precision(); ok { + prec = p + } else { + prec = 6 + } + } + + io.WriteString(st, strconv.FormatFloat(float64(s), 'f', prec, 64)) + + if st.Flag(' ') { + io.WriteString(st, " ") + } + io.WriteString(st, "%") +} + +// Percentage returns percentage decorator. It's a wrapper of NewPercentage. +func Percentage(wcc ...WC) Decorator { + return NewPercentage("% d", wcc...) +} + +// NewPercentage percentage decorator with custom format string. +// +// format examples: +// +// format="%.1f" output: "1.0%" +// format="% .1f" output: "1.0 %" +// format="%d" output: "1%" +// format="% d" output: "1 %" +// +func NewPercentage(format string, wcc ...WC) Decorator { + if format == "" { + format = "% d" + } + f := func(s Statistics) string { + p := internal.Percentage(s.Total, s.Current, 100) + return fmt.Sprintf(format, percentageType(p)) + } + return Any(f, wcc...) +} diff --git a/vendor/github.com/vbauerster/mpb/v7/decor/size_type.go b/vendor/github.com/vbauerster/mpb/v7/decor/size_type.go new file mode 100644 index 000000000..e4b974058 --- /dev/null +++ b/vendor/github.com/vbauerster/mpb/v7/decor/size_type.go @@ -0,0 +1,109 @@ +package decor + +import ( + "fmt" + "io" + "math" + "strconv" +) + +//go:generate stringer -type=SizeB1024 -trimprefix=_i +//go:generate stringer -type=SizeB1000 -trimprefix=_ + +const ( + _ib SizeB1024 = iota + 1 + _iKiB SizeB1024 = 1 << (iota * 10) + _iMiB + _iGiB + _iTiB +) + +// SizeB1024 named type, which implements fmt.Formatter interface. It +// adjusts its value according to byte size multiple by 1024 and appends +// appropriate size marker (KiB, MiB, GiB, TiB). +type SizeB1024 int64 + +func (self SizeB1024) Format(st fmt.State, verb rune) { + var prec int + switch verb { + case 'd': + case 's': + prec = -1 + default: + if p, ok := st.Precision(); ok { + prec = p + } else { + prec = 6 + } + } + + var unit SizeB1024 + switch { + case self < _iKiB: + unit = _ib + case self < _iMiB: + unit = _iKiB + case self < _iGiB: + unit = _iMiB + case self < _iTiB: + unit = _iGiB + case self <= math.MaxInt64: + unit = _iTiB + } + + io.WriteString(st, strconv.FormatFloat(float64(self)/float64(unit), 'f', prec, 64)) + + if st.Flag(' ') { + io.WriteString(st, " ") + } + io.WriteString(st, unit.String()) +} + +const ( + _b SizeB1000 = 1 + _KB SizeB1000 = _b * 1000 + _MB SizeB1000 = _KB * 1000 + _GB SizeB1000 = _MB * 1000 + _TB SizeB1000 = _GB * 1000 +) + +// SizeB1000 named type, which implements fmt.Formatter interface. It +// adjusts its value according to byte size multiple by 1000 and appends +// appropriate size marker (KB, MB, GB, TB). +type SizeB1000 int64 + +func (self SizeB1000) Format(st fmt.State, verb rune) { + var prec int + switch verb { + case 'd': + case 's': + prec = -1 + default: + if p, ok := st.Precision(); ok { + prec = p + } else { + prec = 6 + } + } + + var unit SizeB1000 + switch { + case self < _KB: + unit = _b + case self < _MB: + unit = _KB + case self < _GB: + unit = _MB + case self < _TB: + unit = _GB + case self <= math.MaxInt64: + unit = _TB + } + + io.WriteString(st, strconv.FormatFloat(float64(self)/float64(unit), 'f', prec, 64)) + + if st.Flag(' ') { + io.WriteString(st, " ") + } + io.WriteString(st, unit.String()) +} diff --git a/vendor/github.com/vbauerster/mpb/v7/decor/sizeb1000_string.go b/vendor/github.com/vbauerster/mpb/v7/decor/sizeb1000_string.go new file mode 100644 index 000000000..3f32ef715 --- /dev/null +++ b/vendor/github.com/vbauerster/mpb/v7/decor/sizeb1000_string.go @@ -0,0 +1,41 @@ +// Code generated by "stringer -type=SizeB1000 -trimprefix=_"; DO NOT EDIT. + +package decor + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[_b-1] + _ = x[_KB-1000] + _ = x[_MB-1000000] + _ = x[_GB-1000000000] + _ = x[_TB-1000000000000] +} + +const ( + _SizeB1000_name_0 = "b" + _SizeB1000_name_1 = "KB" + _SizeB1000_name_2 = "MB" + _SizeB1000_name_3 = "GB" + _SizeB1000_name_4 = "TB" +) + +func (i SizeB1000) String() string { + switch { + case i == 1: + return _SizeB1000_name_0 + case i == 1000: + return _SizeB1000_name_1 + case i == 1000000: + return _SizeB1000_name_2 + case i == 1000000000: + return _SizeB1000_name_3 + case i == 1000000000000: + return _SizeB1000_name_4 + default: + return "SizeB1000(" + strconv.FormatInt(int64(i), 10) + ")" + } +} diff --git a/vendor/github.com/vbauerster/mpb/v7/decor/sizeb1024_string.go b/vendor/github.com/vbauerster/mpb/v7/decor/sizeb1024_string.go new file mode 100644 index 000000000..9fca66cc7 --- /dev/null +++ b/vendor/github.com/vbauerster/mpb/v7/decor/sizeb1024_string.go @@ -0,0 +1,41 @@ +// Code generated by "stringer -type=SizeB1024 -trimprefix=_i"; DO NOT EDIT. + +package decor + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[_ib-1] + _ = x[_iKiB-1024] + _ = x[_iMiB-1048576] + _ = x[_iGiB-1073741824] + _ = x[_iTiB-1099511627776] +} + +const ( + _SizeB1024_name_0 = "b" + _SizeB1024_name_1 = "KiB" + _SizeB1024_name_2 = "MiB" + _SizeB1024_name_3 = "GiB" + _SizeB1024_name_4 = "TiB" +) + +func (i SizeB1024) String() string { + switch { + case i == 1: + return _SizeB1024_name_0 + case i == 1024: + return _SizeB1024_name_1 + case i == 1048576: + return _SizeB1024_name_2 + case i == 1073741824: + return _SizeB1024_name_3 + case i == 1099511627776: + return _SizeB1024_name_4 + default: + return "SizeB1024(" + strconv.FormatInt(int64(i), 10) + ")" + } +} diff --git a/vendor/github.com/vbauerster/mpb/v7/decor/speed.go b/vendor/github.com/vbauerster/mpb/v7/decor/speed.go new file mode 100644 index 000000000..634edabfd --- /dev/null +++ b/vendor/github.com/vbauerster/mpb/v7/decor/speed.go @@ -0,0 +1,171 @@ +package decor + +import ( + "fmt" + "io" + "math" + "time" + + "github.com/VividCortex/ewma" +) + +// FmtAsSpeed adds "/s" to the end of the input formatter. To be +// used with SizeB1000 or SizeB1024 types, for example: +// +// fmt.Printf("%.1f", FmtAsSpeed(SizeB1024(2048))) +// +func FmtAsSpeed(input fmt.Formatter) fmt.Formatter { + return &speedFormatter{input} +} + +type speedFormatter struct { + fmt.Formatter +} + +func (self *speedFormatter) Format(st fmt.State, verb rune) { + self.Formatter.Format(st, verb) + io.WriteString(st, "/s") +} + +// EwmaSpeed exponential-weighted-moving-average based speed decorator. +// For this decorator to work correctly you have to measure each +// iteration's duration and pass it to the +// *Bar.DecoratorEwmaUpdate(time.Duration) method after each increment. +func EwmaSpeed(unit int, format string, age float64, wcc ...WC) Decorator { + var average ewma.MovingAverage + if age == 0 { + average = ewma.NewMovingAverage() + } else { + average = ewma.NewMovingAverage(age) + } + return MovingAverageSpeed(unit, format, NewThreadSafeMovingAverage(average), wcc...) +} + +// MovingAverageSpeed decorator relies on MovingAverage implementation +// to calculate its average. +// +// `unit` one of [0|UnitKiB|UnitKB] zero for no unit +// +// `format` printf compatible verb for value, like "%f" or "%d" +// +// `average` MovingAverage implementation +// +// `wcc` optional WC config +// +// format examples: +// +// unit=UnitKiB, format="%.1f" output: "1.0MiB/s" +// unit=UnitKiB, format="% .1f" output: "1.0 MiB/s" +// unit=UnitKB, format="%.1f" output: "1.0MB/s" +// unit=UnitKB, format="% .1f" output: "1.0 MB/s" +// +func MovingAverageSpeed(unit int, format string, average ewma.MovingAverage, wcc ...WC) Decorator { + if format == "" { + format = "%.0f" + } + d := &movingAverageSpeed{ + WC: initWC(wcc...), + average: average, + producer: chooseSpeedProducer(unit, format), + } + return d +} + +type movingAverageSpeed struct { + WC + producer func(float64) string + average ewma.MovingAverage + msg string +} + +func (d *movingAverageSpeed) Decor(s Statistics) string { + if !s.Completed { + var speed float64 + if v := d.average.Value(); v > 0 { + speed = 1 / v + } + d.msg = d.producer(speed * 1e9) + } + return d.FormatMsg(d.msg) +} + +func (d *movingAverageSpeed) EwmaUpdate(n int64, dur time.Duration) { + durPerByte := float64(dur) / float64(n) + if math.IsInf(durPerByte, 0) || math.IsNaN(durPerByte) { + return + } + d.average.Add(durPerByte) +} + +// AverageSpeed decorator with dynamic unit measure adjustment. It's +// a wrapper of NewAverageSpeed. +func AverageSpeed(unit int, format string, wcc ...WC) Decorator { + return NewAverageSpeed(unit, format, time.Now(), wcc...) +} + +// NewAverageSpeed decorator with dynamic unit measure adjustment and +// user provided start time. +// +// `unit` one of [0|UnitKiB|UnitKB] zero for no unit +// +// `format` printf compatible verb for value, like "%f" or "%d" +// +// `startTime` start time +// +// `wcc` optional WC config +// +// format examples: +// +// unit=UnitKiB, format="%.1f" output: "1.0MiB/s" +// unit=UnitKiB, format="% .1f" output: "1.0 MiB/s" +// unit=UnitKB, format="%.1f" output: "1.0MB/s" +// unit=UnitKB, format="% .1f" output: "1.0 MB/s" +// +func NewAverageSpeed(unit int, format string, startTime time.Time, wcc ...WC) Decorator { + if format == "" { + format = "%.0f" + } + d := &averageSpeed{ + WC: initWC(wcc...), + startTime: startTime, + producer: chooseSpeedProducer(unit, format), + } + return d +} + +type averageSpeed struct { + WC + startTime time.Time + producer func(float64) string + msg string +} + +func (d *averageSpeed) Decor(s Statistics) string { + if !s.Completed { + speed := float64(s.Current) / float64(time.Since(d.startTime)) + d.msg = d.producer(speed * 1e9) + } + + return d.FormatMsg(d.msg) +} + +func (d *averageSpeed) AverageAdjust(startTime time.Time) { + d.startTime = startTime +} + +func chooseSpeedProducer(unit int, format string) func(float64) string { + switch unit { + case UnitKiB: + return func(speed float64) string { + return fmt.Sprintf(format, FmtAsSpeed(SizeB1024(math.Round(speed)))) + } + case UnitKB: + return func(speed float64) string { + return fmt.Sprintf(format, FmtAsSpeed(SizeB1000(math.Round(speed)))) + } + default: + return func(speed float64) string { + return fmt.Sprintf(format, speed) + } + } +} diff --git a/vendor/github.com/vbauerster/mpb/v7/decor/spinner.go b/vendor/github.com/vbauerster/mpb/v7/decor/spinner.go new file mode 100644 index 000000000..6871639db --- /dev/null +++ b/vendor/github.com/vbauerster/mpb/v7/decor/spinner.go @@ -0,0 +1,21 @@ +package decor + +var defaultSpinnerStyle = []string{"⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"} + +// Spinner returns spinner decorator. +// +// `frames` spinner frames, if nil or len==0, default is used +// +// `wcc` optional WC config +func Spinner(frames []string, wcc ...WC) Decorator { + if len(frames) == 0 { + frames = defaultSpinnerStyle + } + var count uint + f := func(s Statistics) string { + frame := frames[count%uint(len(frames))] + count++ + return frame + } + return Any(f, wcc...) +} diff --git a/vendor/github.com/vbauerster/mpb/v7/doc.go b/vendor/github.com/vbauerster/mpb/v7/doc.go new file mode 100644 index 000000000..5ada71774 --- /dev/null +++ b/vendor/github.com/vbauerster/mpb/v7/doc.go @@ -0,0 +1,2 @@ +// Package mpb is a library for rendering progress bars in terminal applications. +package mpb diff --git a/vendor/github.com/vbauerster/mpb/v7/go.mod b/vendor/github.com/vbauerster/mpb/v7/go.mod new file mode 100644 index 000000000..ea22e1eda --- /dev/null +++ b/vendor/github.com/vbauerster/mpb/v7/go.mod @@ -0,0 +1,10 @@ +module github.com/vbauerster/mpb/v7 + +require ( + github.com/VividCortex/ewma v1.2.0 + github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d + github.com/mattn/go-runewidth v0.0.13 + golang.org/x/sys v0.0.0-20210603125802-9665404d3644 +) + +go 1.14 diff --git a/vendor/github.com/vbauerster/mpb/v7/go.sum b/vendor/github.com/vbauerster/mpb/v7/go.sum new file mode 100644 index 000000000..0b609b223 --- /dev/null +++ b/vendor/github.com/vbauerster/mpb/v7/go.sum @@ -0,0 +1,10 @@ +github.com/VividCortex/ewma v1.2.0 h1:f58SaIzcDXrSy3kWaHNvuJgJ3Nmz59Zji6XoJR/q1ow= +github.com/VividCortex/ewma v1.2.0/go.mod h1:nz4BbCtbLyFDeC9SUHbtcT5644juEuWfUAUnGx7j5l4= +github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8= +github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo= +github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +golang.org/x/sys v0.0.0-20210603125802-9665404d3644 h1:CA1DEQ4NdKphKeL70tvsWNdT5oFh1lOjihRcEDROi0I= +golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/vendor/github.com/vbauerster/mpb/v7/internal/percentage.go b/vendor/github.com/vbauerster/mpb/v7/internal/percentage.go new file mode 100644 index 000000000..a8ef8be12 --- /dev/null +++ b/vendor/github.com/vbauerster/mpb/v7/internal/percentage.go @@ -0,0 +1,19 @@ +package internal + +import "math" + +// Percentage is a helper function, to calculate percentage. +func Percentage(total, current int64, width int) float64 { + if total <= 0 { + return 0 + } + if current >= total { + return float64(width) + } + return float64(int64(width)*current) / float64(total) +} + +// PercentageRound same as Percentage but with math.Round. +func PercentageRound(total, current int64, width int) float64 { + return math.Round(Percentage(total, current, width)) +} diff --git a/vendor/github.com/vbauerster/mpb/v7/internal/predicate.go b/vendor/github.com/vbauerster/mpb/v7/internal/predicate.go new file mode 100644 index 000000000..1e4dd24d9 --- /dev/null +++ b/vendor/github.com/vbauerster/mpb/v7/internal/predicate.go @@ -0,0 +1,6 @@ +package internal + +// Predicate helper for internal use. +func Predicate(pick bool) func() bool { + return func() bool { return pick } +} diff --git a/vendor/github.com/vbauerster/mpb/v7/internal/width.go b/vendor/github.com/vbauerster/mpb/v7/internal/width.go new file mode 100644 index 000000000..7677e404a --- /dev/null +++ b/vendor/github.com/vbauerster/mpb/v7/internal/width.go @@ -0,0 +1,10 @@ +package internal + +// CheckRequestedWidth checks that requested width doesn't overflow +// available width +func CheckRequestedWidth(requested, available int) int { + if requested < 1 || requested >= available { + return available + } + return requested +} diff --git a/vendor/github.com/vbauerster/mpb/v7/priority_queue.go b/vendor/github.com/vbauerster/mpb/v7/priority_queue.go new file mode 100644 index 000000000..29d9bd5a8 --- /dev/null +++ b/vendor/github.com/vbauerster/mpb/v7/priority_queue.go @@ -0,0 +1,32 @@ +package mpb + +// A priorityQueue implements heap.Interface +type priorityQueue []*Bar + +func (pq priorityQueue) Len() int { return len(pq) } + +func (pq priorityQueue) Less(i, j int) bool { + return pq[i].priority < pq[j].priority +} + +func (pq priorityQueue) Swap(i, j int) { + pq[i], pq[j] = pq[j], pq[i] + pq[i].index = i + pq[j].index = j +} + +func (pq *priorityQueue) Push(x interface{}) { + s := *pq + bar := x.(*Bar) + bar.index = len(s) + s = append(s, bar) + *pq = s +} + +func (pq *priorityQueue) Pop() interface{} { + s := *pq + *pq = s[0 : len(s)-1] + bar := s[len(s)-1] + bar.index = -1 // for safety + return bar +} diff --git a/vendor/github.com/vbauerster/mpb/v7/progress.go b/vendor/github.com/vbauerster/mpb/v7/progress.go new file mode 100644 index 000000000..b2017f3f0 --- /dev/null +++ b/vendor/github.com/vbauerster/mpb/v7/progress.go @@ -0,0 +1,412 @@ +package mpb + +import ( + "bytes" + "container/heap" + "context" + "fmt" + "io" + "io/ioutil" + "log" + "math" + "os" + "sync" + "time" + + "github.com/vbauerster/mpb/v7/cwriter" + "github.com/vbauerster/mpb/v7/decor" +) + +const ( + // default RefreshRate + prr = 120 * time.Millisecond +) + +// Progress represents a container that renders one or more progress +// bars. +type Progress struct { + ctx context.Context + uwg *sync.WaitGroup + cwg *sync.WaitGroup + bwg *sync.WaitGroup + operateState chan func(*pState) + done chan struct{} + refreshCh chan time.Time + once sync.Once + dlogger *log.Logger +} + +// pState holds bars in its priorityQueue. It gets passed to +// *Progress.serve(...) monitor goroutine. +type pState struct { + bHeap priorityQueue + heapUpdated bool + pMatrix map[int][]chan int + aMatrix map[int][]chan int + barShutdownQueue []*Bar + + // following are provided/overrided by user + idCount int + reqWidth int + popCompleted bool + outputDiscarded bool + rr time.Duration + uwg *sync.WaitGroup + externalRefresh <-chan interface{} + renderDelay <-chan struct{} + shutdownNotifier chan struct{} + parkedBars map[*Bar]*Bar + output io.Writer + debugOut io.Writer +} + +// New creates new Progress container instance. It's not possible to +// reuse instance after *Progress.Wait() method has been called. +func New(options ...ContainerOption) *Progress { + return NewWithContext(context.Background(), options...) +} + +// NewWithContext creates new Progress container instance with provided +// context. It's not possible to reuse instance after *Progress.Wait() +// method has been called. +func NewWithContext(ctx context.Context, options ...ContainerOption) *Progress { + s := &pState{ + bHeap: priorityQueue{}, + rr: prr, + parkedBars: make(map[*Bar]*Bar), + output: os.Stdout, + debugOut: ioutil.Discard, + } + + for _, opt := range options { + if opt != nil { + opt(s) + } + } + + p := &Progress{ + ctx: ctx, + uwg: s.uwg, + cwg: new(sync.WaitGroup), + bwg: new(sync.WaitGroup), + operateState: make(chan func(*pState)), + done: make(chan struct{}), + dlogger: log.New(s.debugOut, "[mpb] ", log.Lshortfile), + } + + p.cwg.Add(1) + go p.serve(s, cwriter.New(s.output)) + return p +} + +// AddBar creates a bar with default bar filler. Different filler can +// be chosen and applied via `*Progress.Add(...) *Bar` method. +func (p *Progress) AddBar(total int64, options ...BarOption) *Bar { + return p.Add(total, NewBarFiller(BarStyle()), options...) +} + +// AddSpinner creates a bar with default spinner filler. Different +// filler can be chosen and applied via `*Progress.Add(...) *Bar` +// method. +func (p *Progress) AddSpinner(total int64, options ...BarOption) *Bar { + return p.Add(total, NewBarFiller(SpinnerStyle()), options...) +} + +// Add creates a bar which renders itself by provided filler. +// If `total <= 0` trigger complete event is disabled until reset with *bar.SetTotal(int64, bool). +// Panics if *Progress instance is done, i.e. called after *Progress.Wait(). +func (p *Progress) Add(total int64, filler BarFiller, options ...BarOption) *Bar { + if filler == nil { + filler = BarFillerFunc(func(io.Writer, int, decor.Statistics) {}) + } + p.bwg.Add(1) + result := make(chan *Bar) + select { + case p.operateState <- func(ps *pState) { + bs := ps.makeBarState(total, filler, options...) + bar := newBar(p, bs) + if bs.runningBar != nil { + bs.runningBar.noPop = true + ps.parkedBars[bs.runningBar] = bar + } else { + heap.Push(&ps.bHeap, bar) + ps.heapUpdated = true + } + ps.idCount++ + result <- bar + }: + bar := <-result + bar.subscribeDecorators() + return bar + case <-p.done: + p.bwg.Done() + panic(fmt.Sprintf("%T instance can't be reused after it's done!", p)) + } +} + +func (p *Progress) dropBar(b *Bar) { + select { + case p.operateState <- func(s *pState) { + if b.index < 0 { + return + } + heap.Remove(&s.bHeap, b.index) + s.heapUpdated = true + }: + case <-p.done: + } +} + +func (p *Progress) setBarPriority(b *Bar, priority int) { + select { + case p.operateState <- func(s *pState) { + if b.index < 0 { + return + } + b.priority = priority + heap.Fix(&s.bHeap, b.index) + }: + case <-p.done: + } +} + +// UpdateBarPriority same as *Bar.SetPriority(int). +func (p *Progress) UpdateBarPriority(b *Bar, priority int) { + p.setBarPriority(b, priority) +} + +// BarCount returns bars count. +func (p *Progress) BarCount() int { + result := make(chan int, 1) + select { + case p.operateState <- func(s *pState) { result <- s.bHeap.Len() }: + return <-result + case <-p.done: + return 0 + } +} + +// Wait waits for all bars to complete and finally shutdowns container. +// After this method has been called, there is no way to reuse *Progress +// instance. +func (p *Progress) Wait() { + if p.uwg != nil { + // wait for user wg + p.uwg.Wait() + } + + // wait for bars to quit, if any + p.bwg.Wait() + + p.once.Do(p.shutdown) + + // wait for container to quit + p.cwg.Wait() +} + +func (p *Progress) shutdown() { + close(p.done) +} + +func (p *Progress) serve(s *pState, cw *cwriter.Writer) { + defer p.cwg.Done() + + p.refreshCh = s.newTicker(p.done) + + for { + select { + case op := <-p.operateState: + op(s) + case <-p.refreshCh: + if err := s.render(cw); err != nil { + p.dlogger.Println(err) + } + case <-s.shutdownNotifier: + if s.heapUpdated { + if err := s.render(cw); err != nil { + p.dlogger.Println(err) + } + } + return + } + } +} + +func (s *pState) newTicker(done <-chan struct{}) chan time.Time { + ch := make(chan time.Time) + if s.shutdownNotifier == nil { + s.shutdownNotifier = make(chan struct{}) + } + go func() { + if s.renderDelay != nil { + <-s.renderDelay + } + var internalRefresh <-chan time.Time + if !s.outputDiscarded { + if s.externalRefresh == nil { + ticker := time.NewTicker(s.rr) + defer ticker.Stop() + internalRefresh = ticker.C + } + } else { + s.externalRefresh = nil + } + for { + select { + case t := <-internalRefresh: + ch <- t + case x := <-s.externalRefresh: + if t, ok := x.(time.Time); ok { + ch <- t + } else { + ch <- time.Now() + } + case <-done: + close(s.shutdownNotifier) + return + } + } + }() + return ch +} + +func (s *pState) render(cw *cwriter.Writer) error { + if s.heapUpdated { + s.updateSyncMatrix() + s.heapUpdated = false + } + syncWidth(s.pMatrix) + syncWidth(s.aMatrix) + + tw, err := cw.GetWidth() + if err != nil { + tw = s.reqWidth + } + for i := 0; i < s.bHeap.Len(); i++ { + bar := s.bHeap[i] + go bar.render(tw) + } + + return s.flush(cw) +} + +func (s *pState) flush(cw *cwriter.Writer) error { + var lineCount int + bm := make(map[*Bar]struct{}, s.bHeap.Len()) + for s.bHeap.Len() > 0 { + b := heap.Pop(&s.bHeap).(*Bar) + cw.ReadFrom(<-b.frameCh) + if b.toShutdown { + if b.recoveredPanic != nil { + s.barShutdownQueue = append(s.barShutdownQueue, b) + b.toShutdown = false + } else { + // shutdown at next flush + // this ensures no bar ends up with less than 100% rendered + defer func() { + s.barShutdownQueue = append(s.barShutdownQueue, b) + }() + } + } + lineCount += b.extendedLines + 1 + bm[b] = struct{}{} + } + + for _, b := range s.barShutdownQueue { + if parkedBar := s.parkedBars[b]; parkedBar != nil { + parkedBar.priority = b.priority + heap.Push(&s.bHeap, parkedBar) + delete(s.parkedBars, b) + b.toDrop = true + } + if s.popCompleted && !b.noPop { + lineCount -= b.extendedLines + 1 + b.toDrop = true + } + if b.toDrop { + delete(bm, b) + s.heapUpdated = true + } + b.cancel() + } + s.barShutdownQueue = s.barShutdownQueue[0:0] + + for b := range bm { + heap.Push(&s.bHeap, b) + } + + return cw.Flush(lineCount) +} + +func (s *pState) updateSyncMatrix() { + s.pMatrix = make(map[int][]chan int) + s.aMatrix = make(map[int][]chan int) + for i := 0; i < s.bHeap.Len(); i++ { + bar := s.bHeap[i] + table := bar.wSyncTable() + pRow, aRow := table[0], table[1] + + for i, ch := range pRow { + s.pMatrix[i] = append(s.pMatrix[i], ch) + } + + for i, ch := range aRow { + s.aMatrix[i] = append(s.aMatrix[i], ch) + } + } +} + +func (s *pState) makeBarState(total int64, filler BarFiller, options ...BarOption) *bState { + bs := &bState{ + id: s.idCount, + priority: s.idCount, + reqWidth: s.reqWidth, + total: total, + filler: filler, + extender: func(r io.Reader, _ int, _ decor.Statistics) (io.Reader, int) { return r, 0 }, + debugOut: s.debugOut, + } + + if total > 0 { + bs.triggerComplete = true + } + + for _, opt := range options { + if opt != nil { + opt(bs) + } + } + + if bs.middleware != nil { + bs.filler = bs.middleware(filler) + bs.middleware = nil + } + + if s.popCompleted && !bs.noPop { + bs.priority = -(math.MaxInt32 - s.idCount) + } + + bs.bufP = bytes.NewBuffer(make([]byte, 0, 128)) + bs.bufB = bytes.NewBuffer(make([]byte, 0, 256)) + bs.bufA = bytes.NewBuffer(make([]byte, 0, 128)) + + return bs +} + +func syncWidth(matrix map[int][]chan int) { + for _, column := range matrix { + go maxWidthDistributor(column) + } +} + +var maxWidthDistributor = func(column []chan int) { + var maxWidth int + for _, ch := range column { + if w := <-ch; w > maxWidth { + maxWidth = w + } + } + for _, ch := range column { + ch <- maxWidth + } +} diff --git a/vendor/github.com/vbauerster/mpb/v7/proxyreader.go b/vendor/github.com/vbauerster/mpb/v7/proxyreader.go new file mode 100644 index 000000000..316f438d7 --- /dev/null +++ b/vendor/github.com/vbauerster/mpb/v7/proxyreader.go @@ -0,0 +1,90 @@ +package mpb + +import ( + "io" + "io/ioutil" + "time" +) + +type proxyReader struct { + io.ReadCloser + bar *Bar +} + +func (x *proxyReader) Read(p []byte) (int, error) { + n, err := x.ReadCloser.Read(p) + x.bar.IncrBy(n) + if err == io.EOF { + go x.bar.SetTotal(0, true) + } + return n, err +} + +type proxyWriterTo struct { + io.ReadCloser // *proxyReader + wt io.WriterTo + bar *Bar +} + +func (x *proxyWriterTo) WriteTo(w io.Writer) (int64, error) { + n, err := x.wt.WriteTo(w) + x.bar.IncrInt64(n) + if err == io.EOF { + go x.bar.SetTotal(0, true) + } + return n, err +} + +type ewmaProxyReader struct { + io.ReadCloser // *proxyReader + bar *Bar + iT time.Time +} + +func (x *ewmaProxyReader) Read(p []byte) (int, error) { + n, err := x.ReadCloser.Read(p) + if n > 0 { + x.bar.DecoratorEwmaUpdate(time.Since(x.iT)) + x.iT = time.Now() + } + return n, err +} + +type ewmaProxyWriterTo struct { + io.ReadCloser // *ewmaProxyReader + wt io.WriterTo // *proxyWriterTo + bar *Bar + iT time.Time +} + +func (x *ewmaProxyWriterTo) WriteTo(w io.Writer) (int64, error) { + n, err := x.wt.WriteTo(w) + if n > 0 { + x.bar.DecoratorEwmaUpdate(time.Since(x.iT)) + x.iT = time.Now() + } + return n, err +} + +func newProxyReader(r io.Reader, bar *Bar) io.ReadCloser { + rc := toReadCloser(r) + rc = &proxyReader{rc, bar} + + if wt, isWriterTo := r.(io.WriterTo); bar.hasEwmaDecorators { + now := time.Now() + rc = &ewmaProxyReader{rc, bar, now} + if isWriterTo { + rc = &ewmaProxyWriterTo{rc, wt, bar, now} + } + } else if isWriterTo { + rc = &proxyWriterTo{rc, wt, bar} + } + return rc +} + +func toReadCloser(r io.Reader) io.ReadCloser { + if rc, ok := r.(io.ReadCloser); ok { + return rc + } + return ioutil.NopCloser(r) +} diff --git a/vendor/golang.org/x/sys/unix/README.md b/vendor/golang.org/x/sys/unix/README.md index 579d2d735..474efad0e 100644 --- a/vendor/golang.org/x/sys/unix/README.md +++ b/vendor/golang.org/x/sys/unix/README.md @@ -76,7 +76,7 @@ arguments can be passed to the kernel. The third is for low-level use by the ForkExec wrapper. Unlike the first two, it does not call into the scheduler to let it know that a system call is running. -When porting Go to an new architecture/OS, this file must be implemented for +When porting Go to a new architecture/OS, this file must be implemented for each GOOS/GOARCH pair. ### mksysnum @@ -107,7 +107,7 @@ prototype can be exported (capitalized) or not. Adding a new syscall often just requires adding a new `//sys` function prototype with the desired arguments and a capitalized name so it is exported. However, if you want the interface to the syscall to be different, often one will make an -unexported `//sys` prototype, an then write a custom wrapper in +unexported `//sys` prototype, and then write a custom wrapper in `syscall_${GOOS}.go`. ### types files @@ -137,7 +137,7 @@ some `#if/#elif` macros in your include statements. This script is used to generate the system's various constants. This doesn't just include the error numbers and error strings, but also the signal numbers -an a wide variety of miscellaneous constants. The constants come from the list +and a wide variety of miscellaneous constants. The constants come from the list of include files in the `includes_${uname}` variable. A regex then picks out the desired `#define` statements, and generates the corresponding Go constants. The error numbers and strings are generated from `#include <errno.h>`, and the diff --git a/vendor/golang.org/x/sys/unix/asm_bsd_386.s b/vendor/golang.org/x/sys/unix/asm_bsd_386.s index 7f29275fa..e0fcd9b3d 100644 --- a/vendor/golang.org/x/sys/unix/asm_bsd_386.s +++ b/vendor/golang.org/x/sys/unix/asm_bsd_386.s @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build (darwin || freebsd || netbsd || openbsd) && gc -// +build darwin freebsd netbsd openbsd +//go:build (freebsd || netbsd || openbsd) && gc +// +build freebsd netbsd openbsd // +build gc #include "textflag.h" diff --git a/vendor/golang.org/x/sys/unix/asm_bsd_arm.s b/vendor/golang.org/x/sys/unix/asm_bsd_arm.s index 98ebfad9d..d702d4adc 100644 --- a/vendor/golang.org/x/sys/unix/asm_bsd_arm.s +++ b/vendor/golang.org/x/sys/unix/asm_bsd_arm.s @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build (darwin || freebsd || netbsd || openbsd) && gc -// +build darwin freebsd netbsd openbsd +//go:build (freebsd || netbsd || openbsd) && gc +// +build freebsd netbsd openbsd // +build gc #include "textflag.h" diff --git a/vendor/golang.org/x/sys/unix/mkerrors.sh b/vendor/golang.org/x/sys/unix/mkerrors.sh index 007358af8..3f670faba 100644 --- a/vendor/golang.org/x/sys/unix/mkerrors.sh +++ b/vendor/golang.org/x/sys/unix/mkerrors.sh @@ -239,6 +239,7 @@ struct ltchars { #include <linux/netfilter/nfnetlink.h> #include <linux/netlink.h> #include <linux/net_namespace.h> +#include <linux/nfc.h> #include <linux/nsfs.h> #include <linux/perf_event.h> #include <linux/pps.h> @@ -258,6 +259,7 @@ struct ltchars { #include <linux/watchdog.h> #include <mtd/ubi-user.h> +#include <mtd/mtd-user.h> #include <net/route.h> #if defined(__sparc__) @@ -501,6 +503,9 @@ ccflags="$@" $2 ~ /^LO_(KEY|NAME)_SIZE$/ || $2 ~ /^LOOP_(CLR|CTL|GET|SET)_/ || $2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|TCP|MCAST|EVFILT|NOTE|SHUT|PROT|MAP|MFD|T?PACKET|MSG|SCM|MCL|DT|MADV|PR|LOCAL)_/ || + $2 ~ /^NFC_(GENL|PROTO|COMM|RF|SE|DIRECTION|LLCP|SOCKPROTO)_/ || + $2 ~ /^NFC_.*_(MAX)?SIZE$/ || + $2 ~ /^RAW_PAYLOAD_/ || $2 ~ /^TP_STATUS_/ || $2 ~ /^FALLOC_/ || $2 ~ /^ICMPV?6?_(FILTER|SEC)/ || @@ -593,6 +598,9 @@ ccflags="$@" $2 == "HID_MAX_DESCRIPTOR_SIZE" || $2 ~ /^_?HIDIOC/ || $2 ~ /^BUS_(USB|HIL|BLUETOOTH|VIRTUAL)$/ || + $2 ~ /^MTD/ || + $2 ~ /^OTP/ || + $2 ~ /^MEM/ || $2 ~ /^BLK[A-Z]*(GET$|SET$|BUF$|PART$|SIZE)/ {printf("\t%s = C.%s\n", $2, $2)} $2 ~ /^__WCOREFLAG$/ {next} $2 ~ /^__W[A-Z0-9]+$/ {printf("\t%s = C.%s\n", substr($2,3), $2)} diff --git a/vendor/golang.org/x/sys/unix/syscall_linux.go b/vendor/golang.org/x/sys/unix/syscall_linux.go index 2dd7c8e34..41b91fdfb 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux.go @@ -904,6 +904,46 @@ func (sa *SockaddrIUCV) sockaddr() (unsafe.Pointer, _Socklen, error) { return unsafe.Pointer(&sa.raw), SizeofSockaddrIUCV, nil } +type SockaddrNFC struct { + DeviceIdx uint32 + TargetIdx uint32 + NFCProtocol uint32 + raw RawSockaddrNFC +} + +func (sa *SockaddrNFC) sockaddr() (unsafe.Pointer, _Socklen, error) { + sa.raw.Sa_family = AF_NFC + sa.raw.Dev_idx = sa.DeviceIdx + sa.raw.Target_idx = sa.TargetIdx + sa.raw.Nfc_protocol = sa.NFCProtocol + return unsafe.Pointer(&sa.raw), SizeofSockaddrNFC, nil +} + +type SockaddrNFCLLCP struct { + DeviceIdx uint32 + TargetIdx uint32 + NFCProtocol uint32 + DestinationSAP uint8 + SourceSAP uint8 + ServiceName string + raw RawSockaddrNFCLLCP +} + +func (sa *SockaddrNFCLLCP) sockaddr() (unsafe.Pointer, _Socklen, error) { + sa.raw.Sa_family = AF_NFC + sa.raw.Dev_idx = sa.DeviceIdx + sa.raw.Target_idx = sa.TargetIdx + sa.raw.Nfc_protocol = sa.NFCProtocol + sa.raw.Dsap = sa.DestinationSAP + sa.raw.Ssap = sa.SourceSAP + if len(sa.ServiceName) > len(sa.raw.Service_name) { + return nil, 0, EINVAL + } + copy(sa.raw.Service_name[:], sa.ServiceName) + sa.raw.SetServiceNameLen(len(sa.ServiceName)) + return unsafe.Pointer(&sa.raw), SizeofSockaddrNFCLLCP, nil +} + var socketProtocol = func(fd int) (int, error) { return GetsockoptInt(fd, SOL_SOCKET, SO_PROTOCOL) } @@ -1144,6 +1184,37 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { } return sa, nil } + case AF_NFC: + proto, err := socketProtocol(fd) + if err != nil { + return nil, err + } + switch proto { + case NFC_SOCKPROTO_RAW: + pp := (*RawSockaddrNFC)(unsafe.Pointer(rsa)) + sa := &SockaddrNFC{ + DeviceIdx: pp.Dev_idx, + TargetIdx: pp.Target_idx, + NFCProtocol: pp.Nfc_protocol, + } + return sa, nil + case NFC_SOCKPROTO_LLCP: + pp := (*RawSockaddrNFCLLCP)(unsafe.Pointer(rsa)) + if uint64(pp.Service_name_len) > uint64(len(pp.Service_name)) { + return nil, EINVAL + } + sa := &SockaddrNFCLLCP{ + DeviceIdx: pp.Dev_idx, + TargetIdx: pp.Target_idx, + NFCProtocol: pp.Nfc_protocol, + DestinationSAP: pp.Dsap, + SourceSAP: pp.Ssap, + ServiceName: string(pp.Service_name[:pp.Service_name_len]), + } + return sa, nil + default: + return nil, EINVAL + } } return nil, EAFNOSUPPORT } diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_386.go b/vendor/golang.org/x/sys/unix/syscall_linux_386.go index 7b52e5d8a..b430536c8 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_386.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_386.go @@ -378,6 +378,10 @@ func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } +func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { + rsa.Service_name_len = uint32(length) +} + //sys poll(fds *PollFd, nfds int, timeout int) (n int, err error) func Poll(fds []PollFd, timeout int) (n int, err error) { diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_amd64.go b/vendor/golang.org/x/sys/unix/syscall_linux_amd64.go index 28b764115..85cd97da0 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_amd64.go @@ -172,6 +172,10 @@ func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint64(length) } +func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { + rsa.Service_name_len = uint64(length) +} + //sys poll(fds *PollFd, nfds int, timeout int) (n int, err error) func Poll(fds []PollFd, timeout int) (n int, err error) { diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_arm.go b/vendor/golang.org/x/sys/unix/syscall_linux_arm.go index 68877728e..39a864d4e 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_arm.go @@ -256,6 +256,10 @@ func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } +func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { + rsa.Service_name_len = uint32(length) +} + //sys poll(fds *PollFd, nfds int, timeout int) (n int, err error) func Poll(fds []PollFd, timeout int) (n int, err error) { diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go b/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go index 7ed703476..7f27ebf2f 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go @@ -207,6 +207,10 @@ func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint64(length) } +func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { + rsa.Service_name_len = uint64(length) +} + func InotifyInit() (fd int, err error) { return InotifyInit1(0) } diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go b/vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go index 06dec06fa..27aee81d9 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go @@ -217,6 +217,10 @@ func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint64(length) } +func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { + rsa.Service_name_len = uint64(length) +} + func InotifyInit() (fd int, err error) { return InotifyInit1(0) } diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_mipsx.go b/vendor/golang.org/x/sys/unix/syscall_linux_mipsx.go index 8f0d0a5b5..3a5621e37 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_mipsx.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_mipsx.go @@ -229,6 +229,10 @@ func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } +func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { + rsa.Service_name_len = uint32(length) +} + //sys poll(fds *PollFd, nfds int, timeout int) (n int, err error) func Poll(fds []PollFd, timeout int) (n int, err error) { diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_ppc.go b/vendor/golang.org/x/sys/unix/syscall_linux_ppc.go index 7e65e088d..cf0d36f76 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_ppc.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_ppc.go @@ -215,6 +215,10 @@ func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } +func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { + rsa.Service_name_len = uint32(length) +} + //sysnb pipe(p *[2]_C_int) (err error) func Pipe(p []int) (err error) { diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go b/vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go index 0b1f0d6da..5259a5fea 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go @@ -100,6 +100,10 @@ func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint64(length) } +func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { + rsa.Service_name_len = uint64(length) +} + //sysnb pipe(p *[2]_C_int) (err error) func Pipe(p []int) (err error) { diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go b/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go index ce9bcd317..8ef821e5d 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go @@ -188,6 +188,10 @@ func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint64(length) } +func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { + rsa.Service_name_len = uint64(length) +} + func InotifyInit() (fd int, err error) { return InotifyInit1(0) } diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_s390x.go b/vendor/golang.org/x/sys/unix/syscall_linux_s390x.go index a1e45694b..a1c0574b5 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_s390x.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_s390x.go @@ -129,6 +129,10 @@ func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint64(length) } +func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { + rsa.Service_name_len = uint64(length) +} + // Linux on s390x uses the old mmap interface, which requires arguments to be passed in a struct. // mmap2 also requires arguments to be passed in a struct; it is currently not exposed in <asm/unistd.h>. func mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error) { diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_sparc64.go b/vendor/golang.org/x/sys/unix/syscall_linux_sparc64.go index 49055a3cf..de14b8898 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_sparc64.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_sparc64.go @@ -116,6 +116,10 @@ func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint64(length) } +func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) { + rsa.Service_name_len = uint64(length) +} + //sysnb pipe(p *[2]_C_int) (err error) func Pipe(p []int) (err error) { diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux.go b/vendor/golang.org/x/sys/unix/zerrors_linux.go index 47572aaa6..c3fa22486 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux.go @@ -1406,6 +1406,10 @@ const ( MCAST_LEAVE_SOURCE_GROUP = 0x2f MCAST_MSFILTER = 0x30 MCAST_UNBLOCK_SOURCE = 0x2c + MEMGETREGIONINFO = 0xc0104d08 + MEMREADOOB64 = 0xc0184d16 + MEMWRITE = 0xc0304d18 + MEMWRITEOOB64 = 0xc0184d15 MFD_ALLOW_SEALING = 0x2 MFD_CLOEXEC = 0x1 MFD_HUGETLB = 0x4 @@ -1494,7 +1498,35 @@ const ( MS_SYNCHRONOUS = 0x10 MS_UNBINDABLE = 0x20000 MS_VERBOSE = 0x8000 + MTD_ABSENT = 0x0 + MTD_BIT_WRITEABLE = 0x800 + MTD_CAP_NANDFLASH = 0x400 + MTD_CAP_NORFLASH = 0xc00 + MTD_CAP_NVRAM = 0x1c00 + MTD_CAP_RAM = 0x1c00 + MTD_CAP_ROM = 0x0 + MTD_DATAFLASH = 0x6 MTD_INODE_FS_MAGIC = 0x11307854 + MTD_MAX_ECCPOS_ENTRIES = 0x40 + MTD_MAX_OOBFREE_ENTRIES = 0x8 + MTD_MLCNANDFLASH = 0x8 + MTD_NANDECC_AUTOPLACE = 0x2 + MTD_NANDECC_AUTOPL_USR = 0x4 + MTD_NANDECC_OFF = 0x0 + MTD_NANDECC_PLACE = 0x1 + MTD_NANDECC_PLACEONLY = 0x3 + MTD_NANDFLASH = 0x4 + MTD_NORFLASH = 0x3 + MTD_NO_ERASE = 0x1000 + MTD_OTP_FACTORY = 0x1 + MTD_OTP_OFF = 0x0 + MTD_OTP_USER = 0x2 + MTD_POWERUP_LOCK = 0x2000 + MTD_RAM = 0x1 + MTD_ROM = 0x2 + MTD_SLC_ON_MLC_EMULATION = 0x4000 + MTD_UBIVOLUME = 0x7 + MTD_WRITEABLE = 0x400 NAME_MAX = 0xff NCP_SUPER_MAGIC = 0x564c NETLINK_ADD_MEMBERSHIP = 0x1 @@ -1534,6 +1566,59 @@ const ( NETLINK_XFRM = 0x6 NETNSA_MAX = 0x5 NETNSA_NSID_NOT_ASSIGNED = -0x1 + NFC_ATR_REQ_GB_MAXSIZE = 0x30 + NFC_ATR_REQ_MAXSIZE = 0x40 + NFC_ATR_RES_GB_MAXSIZE = 0x2f + NFC_ATR_RES_MAXSIZE = 0x40 + NFC_COMM_ACTIVE = 0x0 + NFC_COMM_PASSIVE = 0x1 + NFC_DEVICE_NAME_MAXSIZE = 0x8 + NFC_DIRECTION_RX = 0x0 + NFC_DIRECTION_TX = 0x1 + NFC_FIRMWARE_NAME_MAXSIZE = 0x20 + NFC_GB_MAXSIZE = 0x30 + NFC_GENL_MCAST_EVENT_NAME = "events" + NFC_GENL_NAME = "nfc" + NFC_GENL_VERSION = 0x1 + NFC_HEADER_SIZE = 0x1 + NFC_ISO15693_UID_MAXSIZE = 0x8 + NFC_LLCP_MAX_SERVICE_NAME = 0x3f + NFC_LLCP_MIUX = 0x1 + NFC_LLCP_REMOTE_LTO = 0x3 + NFC_LLCP_REMOTE_MIU = 0x2 + NFC_LLCP_REMOTE_RW = 0x4 + NFC_LLCP_RW = 0x0 + NFC_NFCID1_MAXSIZE = 0xa + NFC_NFCID2_MAXSIZE = 0x8 + NFC_NFCID3_MAXSIZE = 0xa + NFC_PROTO_FELICA = 0x3 + NFC_PROTO_FELICA_MASK = 0x8 + NFC_PROTO_ISO14443 = 0x4 + NFC_PROTO_ISO14443_B = 0x6 + NFC_PROTO_ISO14443_B_MASK = 0x40 + NFC_PROTO_ISO14443_MASK = 0x10 + NFC_PROTO_ISO15693 = 0x7 + NFC_PROTO_ISO15693_MASK = 0x80 + NFC_PROTO_JEWEL = 0x1 + NFC_PROTO_JEWEL_MASK = 0x2 + NFC_PROTO_MAX = 0x8 + NFC_PROTO_MIFARE = 0x2 + NFC_PROTO_MIFARE_MASK = 0x4 + NFC_PROTO_NFC_DEP = 0x5 + NFC_PROTO_NFC_DEP_MASK = 0x20 + NFC_RAW_HEADER_SIZE = 0x2 + NFC_RF_INITIATOR = 0x0 + NFC_RF_NONE = 0x2 + NFC_RF_TARGET = 0x1 + NFC_SENSB_RES_MAXSIZE = 0xc + NFC_SENSF_RES_MAXSIZE = 0x12 + NFC_SE_DISABLED = 0x0 + NFC_SE_EMBEDDED = 0x2 + NFC_SE_ENABLED = 0x1 + NFC_SE_UICC = 0x1 + NFC_SOCKPROTO_LLCP = 0x1 + NFC_SOCKPROTO_MAX = 0x2 + NFC_SOCKPROTO_RAW = 0x0 NFNETLINK_V0 = 0x0 NFNLGRP_ACCT_QUOTA = 0x8 NFNLGRP_CONNTRACK_DESTROY = 0x3 @@ -1959,6 +2044,11 @@ const ( QNX4_SUPER_MAGIC = 0x2f QNX6_SUPER_MAGIC = 0x68191122 RAMFS_MAGIC = 0x858458f6 + RAW_PAYLOAD_DIGITAL = 0x3 + RAW_PAYLOAD_HCI = 0x2 + RAW_PAYLOAD_LLCP = 0x0 + RAW_PAYLOAD_NCI = 0x1 + RAW_PAYLOAD_PROPRIETARY = 0x4 RDTGROUP_SUPER_MAGIC = 0x7655821 REISERFS_SUPER_MAGIC = 0x52654973 RENAME_EXCHANGE = 0x2 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_386.go b/vendor/golang.org/x/sys/unix/zerrors_linux_386.go index e91a1a957..09fc559ed 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_386.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_386.go @@ -60,6 +60,8 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + ECCGETLAYOUT = 0x81484d11 + ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 ECHOE = 0x10 ECHOK = 0x20 @@ -123,6 +125,19 @@ const ( MCL_CURRENT = 0x1 MCL_FUTURE = 0x2 MCL_ONFAULT = 0x4 + MEMERASE = 0x40084d02 + MEMERASE64 = 0x40104d14 + MEMGETBADBLOCK = 0x40084d0b + MEMGETINFO = 0x80204d01 + MEMGETOOBSEL = 0x80c84d0a + MEMGETREGIONCOUNT = 0x80044d07 + MEMISLOCKED = 0x80084d17 + MEMLOCK = 0x40084d05 + MEMREADOOB = 0xc00c4d04 + MEMSETBADBLOCK = 0x40084d0c + MEMUNLOCK = 0x40084d06 + MEMWRITEOOB = 0xc00c4d03 + MTDFILEMODE = 0x4d13 NFDBITS = 0x20 NLDLY = 0x100 NOFLSH = 0x80 @@ -132,6 +147,10 @@ const ( NS_GET_USERNS = 0xb701 OLCUC = 0x2 ONLCR = 0x4 + OTPGETREGIONCOUNT = 0x40044d0e + OTPGETREGIONINFO = 0x400c4d0f + OTPLOCK = 0x800c4d10 + OTPSELECT = 0x80044d0d O_APPEND = 0x400 O_ASYNC = 0x2000 O_CLOEXEC = 0x80000 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go index a9cbac644..75730cc22 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go @@ -60,6 +60,8 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + ECCGETLAYOUT = 0x81484d11 + ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 ECHOE = 0x10 ECHOK = 0x20 @@ -123,6 +125,19 @@ const ( MCL_CURRENT = 0x1 MCL_FUTURE = 0x2 MCL_ONFAULT = 0x4 + MEMERASE = 0x40084d02 + MEMERASE64 = 0x40104d14 + MEMGETBADBLOCK = 0x40084d0b + MEMGETINFO = 0x80204d01 + MEMGETOOBSEL = 0x80c84d0a + MEMGETREGIONCOUNT = 0x80044d07 + MEMISLOCKED = 0x80084d17 + MEMLOCK = 0x40084d05 + MEMREADOOB = 0xc0104d04 + MEMSETBADBLOCK = 0x40084d0c + MEMUNLOCK = 0x40084d06 + MEMWRITEOOB = 0xc0104d03 + MTDFILEMODE = 0x4d13 NFDBITS = 0x40 NLDLY = 0x100 NOFLSH = 0x80 @@ -132,6 +147,10 @@ const ( NS_GET_USERNS = 0xb701 OLCUC = 0x2 ONLCR = 0x4 + OTPGETREGIONCOUNT = 0x40044d0e + OTPGETREGIONINFO = 0x400c4d0f + OTPLOCK = 0x800c4d10 + OTPSELECT = 0x80044d0d O_APPEND = 0x400 O_ASYNC = 0x2000 O_CLOEXEC = 0x80000 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go b/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go index d74f3c15a..127cf17ad 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go @@ -60,6 +60,8 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + ECCGETLAYOUT = 0x81484d11 + ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 ECHOE = 0x10 ECHOK = 0x20 @@ -121,6 +123,19 @@ const ( MCL_CURRENT = 0x1 MCL_FUTURE = 0x2 MCL_ONFAULT = 0x4 + MEMERASE = 0x40084d02 + MEMERASE64 = 0x40104d14 + MEMGETBADBLOCK = 0x40084d0b + MEMGETINFO = 0x80204d01 + MEMGETOOBSEL = 0x80c84d0a + MEMGETREGIONCOUNT = 0x80044d07 + MEMISLOCKED = 0x80084d17 + MEMLOCK = 0x40084d05 + MEMREADOOB = 0xc00c4d04 + MEMSETBADBLOCK = 0x40084d0c + MEMUNLOCK = 0x40084d06 + MEMWRITEOOB = 0xc00c4d03 + MTDFILEMODE = 0x4d13 NFDBITS = 0x20 NLDLY = 0x100 NOFLSH = 0x80 @@ -130,6 +145,10 @@ const ( NS_GET_USERNS = 0xb701 OLCUC = 0x2 ONLCR = 0x4 + OTPGETREGIONCOUNT = 0x40044d0e + OTPGETREGIONINFO = 0x400c4d0f + OTPLOCK = 0x800c4d10 + OTPSELECT = 0x80044d0d O_APPEND = 0x400 O_ASYNC = 0x2000 O_CLOEXEC = 0x80000 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go index e1538995b..957ca1ff1 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go @@ -60,6 +60,8 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + ECCGETLAYOUT = 0x81484d11 + ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 ECHOE = 0x10 ECHOK = 0x20 @@ -124,6 +126,19 @@ const ( MCL_CURRENT = 0x1 MCL_FUTURE = 0x2 MCL_ONFAULT = 0x4 + MEMERASE = 0x40084d02 + MEMERASE64 = 0x40104d14 + MEMGETBADBLOCK = 0x40084d0b + MEMGETINFO = 0x80204d01 + MEMGETOOBSEL = 0x80c84d0a + MEMGETREGIONCOUNT = 0x80044d07 + MEMISLOCKED = 0x80084d17 + MEMLOCK = 0x40084d05 + MEMREADOOB = 0xc0104d04 + MEMSETBADBLOCK = 0x40084d0c + MEMUNLOCK = 0x40084d06 + MEMWRITEOOB = 0xc0104d03 + MTDFILEMODE = 0x4d13 NFDBITS = 0x40 NLDLY = 0x100 NOFLSH = 0x80 @@ -133,6 +148,10 @@ const ( NS_GET_USERNS = 0xb701 OLCUC = 0x2 ONLCR = 0x4 + OTPGETREGIONCOUNT = 0x40044d0e + OTPGETREGIONINFO = 0x400c4d0f + OTPLOCK = 0x800c4d10 + OTPSELECT = 0x80044d0d O_APPEND = 0x400 O_ASYNC = 0x2000 O_CLOEXEC = 0x80000 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go index 5e8e71ff8..314a2054f 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go @@ -60,6 +60,8 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + ECCGETLAYOUT = 0x41484d11 + ECCGETSTATS = 0x40104d12 ECHOCTL = 0x200 ECHOE = 0x10 ECHOK = 0x20 @@ -121,6 +123,19 @@ const ( MCL_CURRENT = 0x1 MCL_FUTURE = 0x2 MCL_ONFAULT = 0x4 + MEMERASE = 0x80084d02 + MEMERASE64 = 0x80104d14 + MEMGETBADBLOCK = 0x80084d0b + MEMGETINFO = 0x40204d01 + MEMGETOOBSEL = 0x40c84d0a + MEMGETREGIONCOUNT = 0x40044d07 + MEMISLOCKED = 0x40084d17 + MEMLOCK = 0x80084d05 + MEMREADOOB = 0xc00c4d04 + MEMSETBADBLOCK = 0x80084d0c + MEMUNLOCK = 0x80084d06 + MEMWRITEOOB = 0xc00c4d03 + MTDFILEMODE = 0x20004d13 NFDBITS = 0x20 NLDLY = 0x100 NOFLSH = 0x80 @@ -130,6 +145,10 @@ const ( NS_GET_USERNS = 0x2000b701 OLCUC = 0x2 ONLCR = 0x4 + OTPGETREGIONCOUNT = 0x80044d0e + OTPGETREGIONINFO = 0x800c4d0f + OTPLOCK = 0x400c4d10 + OTPSELECT = 0x40044d0d O_APPEND = 0x8 O_ASYNC = 0x1000 O_CLOEXEC = 0x80000 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go index e670ee148..457e8de97 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go @@ -60,6 +60,8 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + ECCGETLAYOUT = 0x41484d11 + ECCGETSTATS = 0x40104d12 ECHOCTL = 0x200 ECHOE = 0x10 ECHOK = 0x20 @@ -121,6 +123,19 @@ const ( MCL_CURRENT = 0x1 MCL_FUTURE = 0x2 MCL_ONFAULT = 0x4 + MEMERASE = 0x80084d02 + MEMERASE64 = 0x80104d14 + MEMGETBADBLOCK = 0x80084d0b + MEMGETINFO = 0x40204d01 + MEMGETOOBSEL = 0x40c84d0a + MEMGETREGIONCOUNT = 0x40044d07 + MEMISLOCKED = 0x40084d17 + MEMLOCK = 0x80084d05 + MEMREADOOB = 0xc0104d04 + MEMSETBADBLOCK = 0x80084d0c + MEMUNLOCK = 0x80084d06 + MEMWRITEOOB = 0xc0104d03 + MTDFILEMODE = 0x20004d13 NFDBITS = 0x40 NLDLY = 0x100 NOFLSH = 0x80 @@ -130,6 +145,10 @@ const ( NS_GET_USERNS = 0x2000b701 OLCUC = 0x2 ONLCR = 0x4 + OTPGETREGIONCOUNT = 0x80044d0e + OTPGETREGIONINFO = 0x800c4d0f + OTPLOCK = 0x400c4d10 + OTPSELECT = 0x40044d0d O_APPEND = 0x8 O_ASYNC = 0x1000 O_CLOEXEC = 0x80000 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go index dd11eacb8..33cd28f6b 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go @@ -60,6 +60,8 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + ECCGETLAYOUT = 0x41484d11 + ECCGETSTATS = 0x40104d12 ECHOCTL = 0x200 ECHOE = 0x10 ECHOK = 0x20 @@ -121,6 +123,19 @@ const ( MCL_CURRENT = 0x1 MCL_FUTURE = 0x2 MCL_ONFAULT = 0x4 + MEMERASE = 0x80084d02 + MEMERASE64 = 0x80104d14 + MEMGETBADBLOCK = 0x80084d0b + MEMGETINFO = 0x40204d01 + MEMGETOOBSEL = 0x40c84d0a + MEMGETREGIONCOUNT = 0x40044d07 + MEMISLOCKED = 0x40084d17 + MEMLOCK = 0x80084d05 + MEMREADOOB = 0xc0104d04 + MEMSETBADBLOCK = 0x80084d0c + MEMUNLOCK = 0x80084d06 + MEMWRITEOOB = 0xc0104d03 + MTDFILEMODE = 0x20004d13 NFDBITS = 0x40 NLDLY = 0x100 NOFLSH = 0x80 @@ -130,6 +145,10 @@ const ( NS_GET_USERNS = 0x2000b701 OLCUC = 0x2 ONLCR = 0x4 + OTPGETREGIONCOUNT = 0x80044d0e + OTPGETREGIONINFO = 0x800c4d0f + OTPLOCK = 0x400c4d10 + OTPSELECT = 0x40044d0d O_APPEND = 0x8 O_ASYNC = 0x1000 O_CLOEXEC = 0x80000 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go index a0a5b22ae..0e085ba14 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go @@ -60,6 +60,8 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + ECCGETLAYOUT = 0x41484d11 + ECCGETSTATS = 0x40104d12 ECHOCTL = 0x200 ECHOE = 0x10 ECHOK = 0x20 @@ -121,6 +123,19 @@ const ( MCL_CURRENT = 0x1 MCL_FUTURE = 0x2 MCL_ONFAULT = 0x4 + MEMERASE = 0x80084d02 + MEMERASE64 = 0x80104d14 + MEMGETBADBLOCK = 0x80084d0b + MEMGETINFO = 0x40204d01 + MEMGETOOBSEL = 0x40c84d0a + MEMGETREGIONCOUNT = 0x40044d07 + MEMISLOCKED = 0x40084d17 + MEMLOCK = 0x80084d05 + MEMREADOOB = 0xc00c4d04 + MEMSETBADBLOCK = 0x80084d0c + MEMUNLOCK = 0x80084d06 + MEMWRITEOOB = 0xc00c4d03 + MTDFILEMODE = 0x20004d13 NFDBITS = 0x20 NLDLY = 0x100 NOFLSH = 0x80 @@ -130,6 +145,10 @@ const ( NS_GET_USERNS = 0x2000b701 OLCUC = 0x2 ONLCR = 0x4 + OTPGETREGIONCOUNT = 0x80044d0e + OTPGETREGIONINFO = 0x800c4d0f + OTPLOCK = 0x400c4d10 + OTPSELECT = 0x40044d0d O_APPEND = 0x8 O_ASYNC = 0x1000 O_CLOEXEC = 0x80000 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go index d9530e5fb..1b5928cff 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go @@ -60,6 +60,8 @@ const ( CS8 = 0x300 CSIZE = 0x300 CSTOPB = 0x400 + ECCGETLAYOUT = 0x41484d11 + ECCGETSTATS = 0x40104d12 ECHOCTL = 0x40 ECHOE = 0x2 ECHOK = 0x4 @@ -121,6 +123,19 @@ const ( MCL_CURRENT = 0x2000 MCL_FUTURE = 0x4000 MCL_ONFAULT = 0x8000 + MEMERASE = 0x80084d02 + MEMERASE64 = 0x80104d14 + MEMGETBADBLOCK = 0x80084d0b + MEMGETINFO = 0x40204d01 + MEMGETOOBSEL = 0x40c84d0a + MEMGETREGIONCOUNT = 0x40044d07 + MEMISLOCKED = 0x40084d17 + MEMLOCK = 0x80084d05 + MEMREADOOB = 0xc00c4d04 + MEMSETBADBLOCK = 0x80084d0c + MEMUNLOCK = 0x80084d06 + MEMWRITEOOB = 0xc00c4d03 + MTDFILEMODE = 0x20004d13 NFDBITS = 0x20 NL2 = 0x200 NL3 = 0x300 @@ -132,6 +147,10 @@ const ( NS_GET_USERNS = 0x2000b701 OLCUC = 0x4 ONLCR = 0x2 + OTPGETREGIONCOUNT = 0x80044d0e + OTPGETREGIONINFO = 0x800c4d0f + OTPLOCK = 0x400c4d10 + OTPSELECT = 0x40044d0d O_APPEND = 0x400 O_ASYNC = 0x2000 O_CLOEXEC = 0x80000 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go index e60102f6a..f3a41d6ec 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go @@ -60,6 +60,8 @@ const ( CS8 = 0x300 CSIZE = 0x300 CSTOPB = 0x400 + ECCGETLAYOUT = 0x41484d11 + ECCGETSTATS = 0x40104d12 ECHOCTL = 0x40 ECHOE = 0x2 ECHOK = 0x4 @@ -121,6 +123,19 @@ const ( MCL_CURRENT = 0x2000 MCL_FUTURE = 0x4000 MCL_ONFAULT = 0x8000 + MEMERASE = 0x80084d02 + MEMERASE64 = 0x80104d14 + MEMGETBADBLOCK = 0x80084d0b + MEMGETINFO = 0x40204d01 + MEMGETOOBSEL = 0x40c84d0a + MEMGETREGIONCOUNT = 0x40044d07 + MEMISLOCKED = 0x40084d17 + MEMLOCK = 0x80084d05 + MEMREADOOB = 0xc0104d04 + MEMSETBADBLOCK = 0x80084d0c + MEMUNLOCK = 0x80084d06 + MEMWRITEOOB = 0xc0104d03 + MTDFILEMODE = 0x20004d13 NFDBITS = 0x40 NL2 = 0x200 NL3 = 0x300 @@ -132,6 +147,10 @@ const ( NS_GET_USERNS = 0x2000b701 OLCUC = 0x4 ONLCR = 0x2 + OTPGETREGIONCOUNT = 0x80044d0e + OTPGETREGIONINFO = 0x800c4d0f + OTPLOCK = 0x400c4d10 + OTPSELECT = 0x40044d0d O_APPEND = 0x400 O_ASYNC = 0x2000 O_CLOEXEC = 0x80000 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go index 838ff4ea6..6a5a555d5 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go @@ -60,6 +60,8 @@ const ( CS8 = 0x300 CSIZE = 0x300 CSTOPB = 0x400 + ECCGETLAYOUT = 0x41484d11 + ECCGETSTATS = 0x40104d12 ECHOCTL = 0x40 ECHOE = 0x2 ECHOK = 0x4 @@ -121,6 +123,19 @@ const ( MCL_CURRENT = 0x2000 MCL_FUTURE = 0x4000 MCL_ONFAULT = 0x8000 + MEMERASE = 0x80084d02 + MEMERASE64 = 0x80104d14 + MEMGETBADBLOCK = 0x80084d0b + MEMGETINFO = 0x40204d01 + MEMGETOOBSEL = 0x40c84d0a + MEMGETREGIONCOUNT = 0x40044d07 + MEMISLOCKED = 0x40084d17 + MEMLOCK = 0x80084d05 + MEMREADOOB = 0xc0104d04 + MEMSETBADBLOCK = 0x80084d0c + MEMUNLOCK = 0x80084d06 + MEMWRITEOOB = 0xc0104d03 + MTDFILEMODE = 0x20004d13 NFDBITS = 0x40 NL2 = 0x200 NL3 = 0x300 @@ -132,6 +147,10 @@ const ( NS_GET_USERNS = 0x2000b701 OLCUC = 0x4 ONLCR = 0x2 + OTPGETREGIONCOUNT = 0x80044d0e + OTPGETREGIONINFO = 0x800c4d0f + OTPLOCK = 0x400c4d10 + OTPSELECT = 0x40044d0d O_APPEND = 0x400 O_ASYNC = 0x2000 O_CLOEXEC = 0x80000 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go index 7cc98f09c..a4da67edb 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go @@ -60,6 +60,8 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + ECCGETLAYOUT = 0x81484d11 + ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 ECHOE = 0x10 ECHOK = 0x20 @@ -121,6 +123,19 @@ const ( MCL_CURRENT = 0x1 MCL_FUTURE = 0x2 MCL_ONFAULT = 0x4 + MEMERASE = 0x40084d02 + MEMERASE64 = 0x40104d14 + MEMGETBADBLOCK = 0x40084d0b + MEMGETINFO = 0x80204d01 + MEMGETOOBSEL = 0x80c84d0a + MEMGETREGIONCOUNT = 0x80044d07 + MEMISLOCKED = 0x80084d17 + MEMLOCK = 0x40084d05 + MEMREADOOB = 0xc0104d04 + MEMSETBADBLOCK = 0x40084d0c + MEMUNLOCK = 0x40084d06 + MEMWRITEOOB = 0xc0104d03 + MTDFILEMODE = 0x4d13 NFDBITS = 0x40 NLDLY = 0x100 NOFLSH = 0x80 @@ -130,6 +145,10 @@ const ( NS_GET_USERNS = 0xb701 OLCUC = 0x2 ONLCR = 0x4 + OTPGETREGIONCOUNT = 0x40044d0e + OTPGETREGIONINFO = 0x400c4d0f + OTPLOCK = 0x800c4d10 + OTPSELECT = 0x80044d0d O_APPEND = 0x400 O_ASYNC = 0x2000 O_CLOEXEC = 0x80000 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go b/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go index 6d30e6fd8..a7028e0ef 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go @@ -60,6 +60,8 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + ECCGETLAYOUT = 0x81484d11 + ECCGETSTATS = 0x80104d12 ECHOCTL = 0x200 ECHOE = 0x10 ECHOK = 0x20 @@ -121,6 +123,19 @@ const ( MCL_CURRENT = 0x1 MCL_FUTURE = 0x2 MCL_ONFAULT = 0x4 + MEMERASE = 0x40084d02 + MEMERASE64 = 0x40104d14 + MEMGETBADBLOCK = 0x40084d0b + MEMGETINFO = 0x80204d01 + MEMGETOOBSEL = 0x80c84d0a + MEMGETREGIONCOUNT = 0x80044d07 + MEMISLOCKED = 0x80084d17 + MEMLOCK = 0x40084d05 + MEMREADOOB = 0xc0104d04 + MEMSETBADBLOCK = 0x40084d0c + MEMUNLOCK = 0x40084d06 + MEMWRITEOOB = 0xc0104d03 + MTDFILEMODE = 0x4d13 NFDBITS = 0x40 NLDLY = 0x100 NOFLSH = 0x80 @@ -130,6 +145,10 @@ const ( NS_GET_USERNS = 0xb701 OLCUC = 0x2 ONLCR = 0x4 + OTPGETREGIONCOUNT = 0x40044d0e + OTPGETREGIONINFO = 0x400c4d0f + OTPLOCK = 0x800c4d10 + OTPSELECT = 0x80044d0d O_APPEND = 0x400 O_ASYNC = 0x2000 O_CLOEXEC = 0x80000 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go index d5e2dc94f..ed3b3286c 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go @@ -63,6 +63,8 @@ const ( CS8 = 0x30 CSIZE = 0x30 CSTOPB = 0x40 + ECCGETLAYOUT = 0x41484d11 + ECCGETSTATS = 0x40104d12 ECHOCTL = 0x200 ECHOE = 0x10 ECHOK = 0x20 @@ -126,6 +128,19 @@ const ( MCL_CURRENT = 0x2000 MCL_FUTURE = 0x4000 MCL_ONFAULT = 0x8000 + MEMERASE = 0x80084d02 + MEMERASE64 = 0x80104d14 + MEMGETBADBLOCK = 0x80084d0b + MEMGETINFO = 0x40204d01 + MEMGETOOBSEL = 0x40c84d0a + MEMGETREGIONCOUNT = 0x40044d07 + MEMISLOCKED = 0x40084d17 + MEMLOCK = 0x80084d05 + MEMREADOOB = 0xc0104d04 + MEMSETBADBLOCK = 0x80084d0c + MEMUNLOCK = 0x80084d06 + MEMWRITEOOB = 0xc0104d03 + MTDFILEMODE = 0x20004d13 NFDBITS = 0x40 NLDLY = 0x100 NOFLSH = 0x80 @@ -135,6 +150,10 @@ const ( NS_GET_USERNS = 0x2000b701 OLCUC = 0x2 ONLCR = 0x4 + OTPGETREGIONCOUNT = 0x80044d0e + OTPGETREGIONINFO = 0x800c4d0f + OTPLOCK = 0x400c4d10 + OTPSELECT = 0x40044d0d O_APPEND = 0x8 O_ASYNC = 0x40 O_CLOEXEC = 0x400000 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux.go b/vendor/golang.org/x/sys/unix/ztypes_linux.go index 087323591..72887abe5 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux.go @@ -351,6 +351,13 @@ type RawSockaddrIUCV struct { Name [8]int8 } +type RawSockaddrNFC struct { + Sa_family uint16 + Dev_idx uint32 + Target_idx uint32 + Nfc_protocol uint32 +} + type _Socklen uint32 type Linger struct { @@ -464,6 +471,7 @@ const ( SizeofSockaddrL2TPIP = 0x10 SizeofSockaddrL2TPIP6 = 0x20 SizeofSockaddrIUCV = 0x20 + SizeofSockaddrNFC = 0x10 SizeofLinger = 0x8 SizeofIPMreq = 0x8 SizeofIPMreqn = 0xc @@ -3742,3 +3750,158 @@ const ( NLMSGERR_ATTR_OFFS = 0x2 NLMSGERR_ATTR_COOKIE = 0x3 ) + +type ( + EraseInfo struct { + Start uint32 + Length uint32 + } + EraseInfo64 struct { + Start uint64 + Length uint64 + } + MtdOobBuf struct { + Start uint32 + Length uint32 + Ptr *uint8 + } + MtdOobBuf64 struct { + Start uint64 + Pad uint32 + Length uint32 + Ptr uint64 + } + MtdWriteReq struct { + Start uint64 + Len uint64 + Ooblen uint64 + Data uint64 + Oob uint64 + Mode uint8 + _ [7]uint8 + } + MtdInfo struct { + Type uint8 + Flags uint32 + Size uint32 + Erasesize uint32 + Writesize uint32 + Oobsize uint32 + _ uint64 + } + RegionInfo struct { + Offset uint32 + Erasesize uint32 + Numblocks uint32 + Regionindex uint32 + } + OtpInfo struct { + Start uint32 + Length uint32 + Locked uint32 + } + NandOobinfo struct { + Useecc uint32 + Eccbytes uint32 + Oobfree [8][2]uint32 + Eccpos [32]uint32 + } + NandOobfree struct { + Offset uint32 + Length uint32 + } + NandEcclayout struct { + Eccbytes uint32 + Eccpos [64]uint32 + Oobavail uint32 + Oobfree [8]NandOobfree + } + MtdEccStats struct { + Corrected uint32 + Failed uint32 + Badblocks uint32 + Bbtblocks uint32 + } +) + +const ( + MTD_OPS_PLACE_OOB = 0x0 + MTD_OPS_AUTO_OOB = 0x1 + MTD_OPS_RAW = 0x2 +) + +const ( + MTD_FILE_MODE_NORMAL = 0x0 + MTD_FILE_MODE_OTP_FACTORY = 0x1 + MTD_FILE_MODE_OTP_USER = 0x2 + MTD_FILE_MODE_RAW = 0x3 +) + +const ( + NFC_CMD_UNSPEC = 0x0 + NFC_CMD_GET_DEVICE = 0x1 + NFC_CMD_DEV_UP = 0x2 + NFC_CMD_DEV_DOWN = 0x3 + NFC_CMD_DEP_LINK_UP = 0x4 + NFC_CMD_DEP_LINK_DOWN = 0x5 + NFC_CMD_START_POLL = 0x6 + NFC_CMD_STOP_POLL = 0x7 + NFC_CMD_GET_TARGET = 0x8 + NFC_EVENT_TARGETS_FOUND = 0x9 + NFC_EVENT_DEVICE_ADDED = 0xa + NFC_EVENT_DEVICE_REMOVED = 0xb + NFC_EVENT_TARGET_LOST = 0xc + NFC_EVENT_TM_ACTIVATED = 0xd + NFC_EVENT_TM_DEACTIVATED = 0xe + NFC_CMD_LLC_GET_PARAMS = 0xf + NFC_CMD_LLC_SET_PARAMS = 0x10 + NFC_CMD_ENABLE_SE = 0x11 + NFC_CMD_DISABLE_SE = 0x12 + NFC_CMD_LLC_SDREQ = 0x13 + NFC_EVENT_LLC_SDRES = 0x14 + NFC_CMD_FW_DOWNLOAD = 0x15 + NFC_EVENT_SE_ADDED = 0x16 + NFC_EVENT_SE_REMOVED = 0x17 + NFC_EVENT_SE_CONNECTIVITY = 0x18 + NFC_EVENT_SE_TRANSACTION = 0x19 + NFC_CMD_GET_SE = 0x1a + NFC_CMD_SE_IO = 0x1b + NFC_CMD_ACTIVATE_TARGET = 0x1c + NFC_CMD_VENDOR = 0x1d + NFC_CMD_DEACTIVATE_TARGET = 0x1e + NFC_ATTR_UNSPEC = 0x0 + NFC_ATTR_DEVICE_INDEX = 0x1 + NFC_ATTR_DEVICE_NAME = 0x2 + NFC_ATTR_PROTOCOLS = 0x3 + NFC_ATTR_TARGET_INDEX = 0x4 + NFC_ATTR_TARGET_SENS_RES = 0x5 + NFC_ATTR_TARGET_SEL_RES = 0x6 + NFC_ATTR_TARGET_NFCID1 = 0x7 + NFC_ATTR_TARGET_SENSB_RES = 0x8 + NFC_ATTR_TARGET_SENSF_RES = 0x9 + NFC_ATTR_COMM_MODE = 0xa + NFC_ATTR_RF_MODE = 0xb + NFC_ATTR_DEVICE_POWERED = 0xc + NFC_ATTR_IM_PROTOCOLS = 0xd + NFC_ATTR_TM_PROTOCOLS = 0xe + NFC_ATTR_LLC_PARAM_LTO = 0xf + NFC_ATTR_LLC_PARAM_RW = 0x10 + NFC_ATTR_LLC_PARAM_MIUX = 0x11 + NFC_ATTR_SE = 0x12 + NFC_ATTR_LLC_SDP = 0x13 + NFC_ATTR_FIRMWARE_NAME = 0x14 + NFC_ATTR_SE_INDEX = 0x15 + NFC_ATTR_SE_TYPE = 0x16 + NFC_ATTR_SE_AID = 0x17 + NFC_ATTR_FIRMWARE_DOWNLOAD_STATUS = 0x18 + NFC_ATTR_SE_APDU = 0x19 + NFC_ATTR_TARGET_ISO15693_DSFID = 0x1a + NFC_ATTR_TARGET_ISO15693_UID = 0x1b + NFC_ATTR_SE_PARAMS = 0x1c + NFC_ATTR_VENDOR_ID = 0x1d + NFC_ATTR_VENDOR_SUBCMD = 0x1e + NFC_ATTR_VENDOR_DATA = 0x1f + NFC_SDP_ATTR_UNSPEC = 0x0 + NFC_SDP_ATTR_URI = 0x1 + NFC_SDP_ATTR_SAP = 0x2 +) diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_386.go b/vendor/golang.org/x/sys/unix/ztypes_linux_386.go index 4d4d283de..235c62e46 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_386.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_386.go @@ -128,6 +128,17 @@ const ( FADV_NOREUSE = 0x5 ) +type RawSockaddrNFCLLCP struct { + Sa_family uint16 + Dev_idx uint32 + Target_idx uint32 + Nfc_protocol uint32 + Dsap uint8 + Ssap uint8 + Service_name [63]uint8 + Service_name_len uint32 +} + type RawSockaddr struct { Family uint16 Data [14]int8 @@ -160,9 +171,10 @@ type Cmsghdr struct { } const ( - SizeofIovec = 0x8 - SizeofMsghdr = 0x1c - SizeofCmsghdr = 0xc + SizeofSockaddrNFCLLCP = 0x58 + SizeofIovec = 0x8 + SizeofMsghdr = 0x1c + SizeofCmsghdr = 0xc ) const ( diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go index 8a2eed5ec..99b1e5b6a 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go @@ -130,6 +130,17 @@ const ( FADV_NOREUSE = 0x5 ) +type RawSockaddrNFCLLCP struct { + Sa_family uint16 + Dev_idx uint32 + Target_idx uint32 + Nfc_protocol uint32 + Dsap uint8 + Ssap uint8 + Service_name [63]uint8 + Service_name_len uint64 +} + type RawSockaddr struct { Family uint16 Data [14]int8 @@ -163,9 +174,10 @@ type Cmsghdr struct { } const ( - SizeofIovec = 0x10 - SizeofMsghdr = 0x38 - SizeofCmsghdr = 0x10 + SizeofSockaddrNFCLLCP = 0x60 + SizeofIovec = 0x10 + SizeofMsghdr = 0x38 + SizeofCmsghdr = 0x10 ) const ( diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go b/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go index 94b34add6..cc8bba791 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go @@ -134,6 +134,17 @@ const ( FADV_NOREUSE = 0x5 ) +type RawSockaddrNFCLLCP struct { + Sa_family uint16 + Dev_idx uint32 + Target_idx uint32 + Nfc_protocol uint32 + Dsap uint8 + Ssap uint8 + Service_name [63]uint8 + Service_name_len uint32 +} + type RawSockaddr struct { Family uint16 Data [14]uint8 @@ -166,9 +177,10 @@ type Cmsghdr struct { } const ( - SizeofIovec = 0x8 - SizeofMsghdr = 0x1c - SizeofCmsghdr = 0xc + SizeofSockaddrNFCLLCP = 0x58 + SizeofIovec = 0x8 + SizeofMsghdr = 0x1c + SizeofCmsghdr = 0xc ) const ( diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go index 2143de4d5..fa8fe3a75 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go @@ -131,6 +131,17 @@ const ( FADV_NOREUSE = 0x5 ) +type RawSockaddrNFCLLCP struct { + Sa_family uint16 + Dev_idx uint32 + Target_idx uint32 + Nfc_protocol uint32 + Dsap uint8 + Ssap uint8 + Service_name [63]uint8 + Service_name_len uint64 +} + type RawSockaddr struct { Family uint16 Data [14]int8 @@ -164,9 +175,10 @@ type Cmsghdr struct { } const ( - SizeofIovec = 0x10 - SizeofMsghdr = 0x38 - SizeofCmsghdr = 0x10 + SizeofSockaddrNFCLLCP = 0x60 + SizeofIovec = 0x10 + SizeofMsghdr = 0x38 + SizeofCmsghdr = 0x10 ) const ( diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go index a40216eee..e7fb8d9b7 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go @@ -133,6 +133,17 @@ const ( FADV_NOREUSE = 0x5 ) +type RawSockaddrNFCLLCP struct { + Sa_family uint16 + Dev_idx uint32 + Target_idx uint32 + Nfc_protocol uint32 + Dsap uint8 + Ssap uint8 + Service_name [63]uint8 + Service_name_len uint32 +} + type RawSockaddr struct { Family uint16 Data [14]int8 @@ -165,9 +176,10 @@ type Cmsghdr struct { } const ( - SizeofIovec = 0x8 - SizeofMsghdr = 0x1c - SizeofCmsghdr = 0xc + SizeofSockaddrNFCLLCP = 0x58 + SizeofIovec = 0x8 + SizeofMsghdr = 0x1c + SizeofCmsghdr = 0xc ) const ( diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go index e834b069f..2fa61d593 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go @@ -131,6 +131,17 @@ const ( FADV_NOREUSE = 0x5 ) +type RawSockaddrNFCLLCP struct { + Sa_family uint16 + Dev_idx uint32 + Target_idx uint32 + Nfc_protocol uint32 + Dsap uint8 + Ssap uint8 + Service_name [63]uint8 + Service_name_len uint64 +} + type RawSockaddr struct { Family uint16 Data [14]int8 @@ -164,9 +175,10 @@ type Cmsghdr struct { } const ( - SizeofIovec = 0x10 - SizeofMsghdr = 0x38 - SizeofCmsghdr = 0x10 + SizeofSockaddrNFCLLCP = 0x60 + SizeofIovec = 0x10 + SizeofMsghdr = 0x38 + SizeofCmsghdr = 0x10 ) const ( diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go index e31083b04..7f3639933 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go @@ -131,6 +131,17 @@ const ( FADV_NOREUSE = 0x5 ) +type RawSockaddrNFCLLCP struct { + Sa_family uint16 + Dev_idx uint32 + Target_idx uint32 + Nfc_protocol uint32 + Dsap uint8 + Ssap uint8 + Service_name [63]uint8 + Service_name_len uint64 +} + type RawSockaddr struct { Family uint16 Data [14]int8 @@ -164,9 +175,10 @@ type Cmsghdr struct { } const ( - SizeofIovec = 0x10 - SizeofMsghdr = 0x38 - SizeofCmsghdr = 0x10 + SizeofSockaddrNFCLLCP = 0x60 + SizeofIovec = 0x10 + SizeofMsghdr = 0x38 + SizeofCmsghdr = 0x10 ) const ( diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go index 42811f7fb..f3c20cb86 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go @@ -133,6 +133,17 @@ const ( FADV_NOREUSE = 0x5 ) +type RawSockaddrNFCLLCP struct { + Sa_family uint16 + Dev_idx uint32 + Target_idx uint32 + Nfc_protocol uint32 + Dsap uint8 + Ssap uint8 + Service_name [63]uint8 + Service_name_len uint32 +} + type RawSockaddr struct { Family uint16 Data [14]int8 @@ -165,9 +176,10 @@ type Cmsghdr struct { } const ( - SizeofIovec = 0x8 - SizeofMsghdr = 0x1c - SizeofCmsghdr = 0xc + SizeofSockaddrNFCLLCP = 0x58 + SizeofIovec = 0x8 + SizeofMsghdr = 0x1c + SizeofCmsghdr = 0xc ) const ( diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go index af7a72017..885d27950 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go @@ -134,6 +134,17 @@ const ( FADV_NOREUSE = 0x5 ) +type RawSockaddrNFCLLCP struct { + Sa_family uint16 + Dev_idx uint32 + Target_idx uint32 + Nfc_protocol uint32 + Dsap uint8 + Ssap uint8 + Service_name [63]uint8 + Service_name_len uint32 +} + type RawSockaddr struct { Family uint16 Data [14]uint8 @@ -166,9 +177,10 @@ type Cmsghdr struct { } const ( - SizeofIovec = 0x8 - SizeofMsghdr = 0x1c - SizeofCmsghdr = 0xc + SizeofSockaddrNFCLLCP = 0x58 + SizeofIovec = 0x8 + SizeofMsghdr = 0x1c + SizeofCmsghdr = 0xc ) const ( diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go index 2a3afbaef..a94eb8e18 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go @@ -132,6 +132,17 @@ const ( FADV_NOREUSE = 0x5 ) +type RawSockaddrNFCLLCP struct { + Sa_family uint16 + Dev_idx uint32 + Target_idx uint32 + Nfc_protocol uint32 + Dsap uint8 + Ssap uint8 + Service_name [63]uint8 + Service_name_len uint64 +} + type RawSockaddr struct { Family uint16 Data [14]uint8 @@ -165,9 +176,10 @@ type Cmsghdr struct { } const ( - SizeofIovec = 0x10 - SizeofMsghdr = 0x38 - SizeofCmsghdr = 0x10 + SizeofSockaddrNFCLLCP = 0x60 + SizeofIovec = 0x10 + SizeofMsghdr = 0x38 + SizeofCmsghdr = 0x10 ) const ( diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go index c0de30a65..659e32ebd 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go @@ -132,6 +132,17 @@ const ( FADV_NOREUSE = 0x5 ) +type RawSockaddrNFCLLCP struct { + Sa_family uint16 + Dev_idx uint32 + Target_idx uint32 + Nfc_protocol uint32 + Dsap uint8 + Ssap uint8 + Service_name [63]uint8 + Service_name_len uint64 +} + type RawSockaddr struct { Family uint16 Data [14]uint8 @@ -165,9 +176,10 @@ type Cmsghdr struct { } const ( - SizeofIovec = 0x10 - SizeofMsghdr = 0x38 - SizeofCmsghdr = 0x10 + SizeofSockaddrNFCLLCP = 0x60 + SizeofIovec = 0x10 + SizeofMsghdr = 0x38 + SizeofCmsghdr = 0x10 ) const ( diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go index 74faf2e91..ab8ec604f 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go @@ -131,6 +131,17 @@ const ( FADV_NOREUSE = 0x5 ) +type RawSockaddrNFCLLCP struct { + Sa_family uint16 + Dev_idx uint32 + Target_idx uint32 + Nfc_protocol uint32 + Dsap uint8 + Ssap uint8 + Service_name [63]uint8 + Service_name_len uint64 +} + type RawSockaddr struct { Family uint16 Data [14]uint8 @@ -164,9 +175,10 @@ type Cmsghdr struct { } const ( - SizeofIovec = 0x10 - SizeofMsghdr = 0x38 - SizeofCmsghdr = 0x10 + SizeofSockaddrNFCLLCP = 0x60 + SizeofIovec = 0x10 + SizeofMsghdr = 0x38 + SizeofCmsghdr = 0x10 ) const ( diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go b/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go index 9a8f0c2c6..3ec08237f 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go @@ -130,6 +130,17 @@ const ( FADV_NOREUSE = 0x7 ) +type RawSockaddrNFCLLCP struct { + Sa_family uint16 + Dev_idx uint32 + Target_idx uint32 + Nfc_protocol uint32 + Dsap uint8 + Ssap uint8 + Service_name [63]uint8 + Service_name_len uint64 +} + type RawSockaddr struct { Family uint16 Data [14]int8 @@ -163,9 +174,10 @@ type Cmsghdr struct { } const ( - SizeofIovec = 0x10 - SizeofMsghdr = 0x38 - SizeofCmsghdr = 0x10 + SizeofSockaddrNFCLLCP = 0x60 + SizeofIovec = 0x10 + SizeofMsghdr = 0x38 + SizeofCmsghdr = 0x10 ) const ( diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go index 72cdda75b..23d474470 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go @@ -134,6 +134,17 @@ const ( FADV_NOREUSE = 0x5 ) +type RawSockaddrNFCLLCP struct { + Sa_family uint16 + Dev_idx uint32 + Target_idx uint32 + Nfc_protocol uint32 + Dsap uint8 + Ssap uint8 + Service_name [63]uint8 + Service_name_len uint64 +} + type RawSockaddr struct { Family uint16 Data [14]int8 @@ -167,9 +178,10 @@ type Cmsghdr struct { } const ( - SizeofIovec = 0x10 - SizeofMsghdr = 0x38 - SizeofCmsghdr = 0x10 + SizeofSockaddrNFCLLCP = 0x60 + SizeofIovec = 0x10 + SizeofMsghdr = 0x38 + SizeofCmsghdr = 0x10 ) const ( diff --git a/vendor/golang.org/x/sys/windows/exec_windows.go b/vendor/golang.org/x/sys/windows/exec_windows.go index a020caeef..7a11e83b7 100644 --- a/vendor/golang.org/x/sys/windows/exec_windows.go +++ b/vendor/golang.org/x/sys/windows/exec_windows.go @@ -9,6 +9,8 @@ package windows import ( errorspkg "errors" "unsafe" + + "golang.org/x/sys/internal/unsafeheader" ) // EscapeArg rewrites command line argument s as prescribed @@ -135,8 +137,8 @@ func FullPath(name string) (path string, err error) { } } -// NewProcThreadAttributeList allocates a new ProcThreadAttributeList, with the requested maximum number of attributes. -func NewProcThreadAttributeList(maxAttrCount uint32) (*ProcThreadAttributeList, error) { +// NewProcThreadAttributeList allocates a new ProcThreadAttributeListContainer, with the requested maximum number of attributes. +func NewProcThreadAttributeList(maxAttrCount uint32) (*ProcThreadAttributeListContainer, error) { var size uintptr err := initializeProcThreadAttributeList(nil, maxAttrCount, 0, &size) if err != ERROR_INSUFFICIENT_BUFFER { @@ -145,10 +147,9 @@ func NewProcThreadAttributeList(maxAttrCount uint32) (*ProcThreadAttributeList, } return nil, err } - const psize = unsafe.Sizeof(uintptr(0)) // size is guaranteed to be ≥1 by InitializeProcThreadAttributeList. - al := (*ProcThreadAttributeList)(unsafe.Pointer(&make([]unsafe.Pointer, (size+psize-1)/psize)[0])) - err = initializeProcThreadAttributeList(al, maxAttrCount, 0, &size) + al := &ProcThreadAttributeListContainer{data: (*ProcThreadAttributeList)(unsafe.Pointer(&make([]byte, size)[0]))} + err = initializeProcThreadAttributeList(al.data, maxAttrCount, 0, &size) if err != nil { return nil, err } @@ -156,11 +157,39 @@ func NewProcThreadAttributeList(maxAttrCount uint32) (*ProcThreadAttributeList, } // Update modifies the ProcThreadAttributeList using UpdateProcThreadAttribute. -func (al *ProcThreadAttributeList) Update(attribute uintptr, flags uint32, value unsafe.Pointer, size uintptr, prevValue unsafe.Pointer, returnedSize *uintptr) error { - return updateProcThreadAttribute(al, flags, attribute, value, size, prevValue, returnedSize) +// Note that the value passed to this function will be copied into memory +// allocated by LocalAlloc, the contents of which should not contain any +// Go-managed pointers, even if the passed value itself is a Go-managed +// pointer. +func (al *ProcThreadAttributeListContainer) Update(attribute uintptr, value unsafe.Pointer, size uintptr) error { + alloc, err := LocalAlloc(LMEM_FIXED, uint32(size)) + if err != nil { + return err + } + var src, dst []byte + hdr := (*unsafeheader.Slice)(unsafe.Pointer(&src)) + hdr.Data = value + hdr.Cap = int(size) + hdr.Len = int(size) + hdr = (*unsafeheader.Slice)(unsafe.Pointer(&dst)) + hdr.Data = unsafe.Pointer(alloc) + hdr.Cap = int(size) + hdr.Len = int(size) + copy(dst, src) + al.heapAllocations = append(al.heapAllocations, alloc) + return updateProcThreadAttribute(al.data, 0, attribute, unsafe.Pointer(alloc), size, nil, nil) } // Delete frees ProcThreadAttributeList's resources. -func (al *ProcThreadAttributeList) Delete() { - deleteProcThreadAttributeList(al) +func (al *ProcThreadAttributeListContainer) Delete() { + deleteProcThreadAttributeList(al.data) + for i := range al.heapAllocations { + LocalFree(Handle(al.heapAllocations[i])) + } + al.heapAllocations = nil +} + +// List returns the actual ProcThreadAttributeList to be passed to StartupInfoEx. +func (al *ProcThreadAttributeListContainer) List() *ProcThreadAttributeList { + return al.data } diff --git a/vendor/golang.org/x/sys/windows/syscall_windows.go b/vendor/golang.org/x/sys/windows/syscall_windows.go index bb6aaf89e..1215b2ae2 100644 --- a/vendor/golang.org/x/sys/windows/syscall_windows.go +++ b/vendor/golang.org/x/sys/windows/syscall_windows.go @@ -220,6 +220,7 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys CancelIo(s Handle) (err error) //sys CancelIoEx(s Handle, o *Overlapped) (err error) //sys CreateProcess(appName *uint16, commandLine *uint16, procSecurity *SecurityAttributes, threadSecurity *SecurityAttributes, inheritHandles bool, creationFlags uint32, env *uint16, currentDir *uint16, startupInfo *StartupInfo, outProcInfo *ProcessInformation) (err error) = CreateProcessW +//sys CreateProcessAsUser(token Token, appName *uint16, commandLine *uint16, procSecurity *SecurityAttributes, threadSecurity *SecurityAttributes, inheritHandles bool, creationFlags uint32, env *uint16, currentDir *uint16, startupInfo *StartupInfo, outProcInfo *ProcessInformation) (err error) = advapi32.CreateProcessAsUserW //sys initializeProcThreadAttributeList(attrlist *ProcThreadAttributeList, attrcount uint32, flags uint32, size *uintptr) (err error) = InitializeProcThreadAttributeList //sys deleteProcThreadAttributeList(attrlist *ProcThreadAttributeList) = DeleteProcThreadAttributeList //sys updateProcThreadAttribute(attrlist *ProcThreadAttributeList, flags uint32, attr uintptr, value unsafe.Pointer, size uintptr, prevvalue unsafe.Pointer, returnedsize *uintptr) (err error) = UpdateProcThreadAttribute diff --git a/vendor/golang.org/x/sys/windows/types_windows.go b/vendor/golang.org/x/sys/windows/types_windows.go index 23fe18ece..1f733398e 100644 --- a/vendor/golang.org/x/sys/windows/types_windows.go +++ b/vendor/golang.org/x/sys/windows/types_windows.go @@ -909,14 +909,15 @@ type StartupInfoEx struct { // ProcThreadAttributeList is a placeholder type to represent a PROC_THREAD_ATTRIBUTE_LIST. // -// To create a *ProcThreadAttributeList, use NewProcThreadAttributeList, and -// free its memory using ProcThreadAttributeList.Delete. -type ProcThreadAttributeList struct { - // This is of type unsafe.Pointer, not of type byte or uintptr, because - // the contents of it is mostly a list of pointers, and in most cases, - // that's a list of pointers to Go-allocated objects. In order to keep - // the GC from collecting these objects, we declare this as unsafe.Pointer. - _ [1]unsafe.Pointer +// To create a *ProcThreadAttributeList, use NewProcThreadAttributeList, update +// it with ProcThreadAttributeListContainer.Update, free its memory using +// ProcThreadAttributeListContainer.Delete, and access the list itself using +// ProcThreadAttributeListContainer.List. +type ProcThreadAttributeList struct{} + +type ProcThreadAttributeListContainer struct { + data *ProcThreadAttributeList + heapAllocations []uintptr } type ProcessInformation struct { diff --git a/vendor/golang.org/x/sys/windows/zsyscall_windows.go b/vendor/golang.org/x/sys/windows/zsyscall_windows.go index 559bc845c..148de0ffb 100644 --- a/vendor/golang.org/x/sys/windows/zsyscall_windows.go +++ b/vendor/golang.org/x/sys/windows/zsyscall_windows.go @@ -69,6 +69,7 @@ var ( procConvertStringSecurityDescriptorToSecurityDescriptorW = modadvapi32.NewProc("ConvertStringSecurityDescriptorToSecurityDescriptorW") procConvertStringSidToSidW = modadvapi32.NewProc("ConvertStringSidToSidW") procCopySid = modadvapi32.NewProc("CopySid") + procCreateProcessAsUserW = modadvapi32.NewProc("CreateProcessAsUserW") procCreateServiceW = modadvapi32.NewProc("CreateServiceW") procCreateWellKnownSid = modadvapi32.NewProc("CreateWellKnownSid") procCryptAcquireContextW = modadvapi32.NewProc("CryptAcquireContextW") @@ -553,6 +554,18 @@ func CopySid(destSidLen uint32, destSid *SID, srcSid *SID) (err error) { return } +func CreateProcessAsUser(token Token, appName *uint16, commandLine *uint16, procSecurity *SecurityAttributes, threadSecurity *SecurityAttributes, inheritHandles bool, creationFlags uint32, env *uint16, currentDir *uint16, startupInfo *StartupInfo, outProcInfo *ProcessInformation) (err error) { + var _p0 uint32 + if inheritHandles { + _p0 = 1 + } + r1, _, e1 := syscall.Syscall12(procCreateProcessAsUserW.Addr(), 11, uintptr(token), uintptr(unsafe.Pointer(appName)), uintptr(unsafe.Pointer(commandLine)), uintptr(unsafe.Pointer(procSecurity)), uintptr(unsafe.Pointer(threadSecurity)), uintptr(_p0), uintptr(creationFlags), uintptr(unsafe.Pointer(env)), uintptr(unsafe.Pointer(currentDir)), uintptr(unsafe.Pointer(startupInfo)), uintptr(unsafe.Pointer(outProcInfo)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + func CreateService(mgr Handle, serviceName *uint16, displayName *uint16, access uint32, srvType uint32, startType uint32, errCtl uint32, pathName *uint16, loadOrderGroup *uint16, tagId *uint32, dependencies *uint16, serviceStartName *uint16, password *uint16) (handle Handle, err error) { r0, _, e1 := syscall.Syscall15(procCreateServiceW.Addr(), 13, uintptr(mgr), uintptr(unsafe.Pointer(serviceName)), uintptr(unsafe.Pointer(displayName)), uintptr(access), uintptr(srvType), uintptr(startType), uintptr(errCtl), uintptr(unsafe.Pointer(pathName)), uintptr(unsafe.Pointer(loadOrderGroup)), uintptr(unsafe.Pointer(tagId)), uintptr(unsafe.Pointer(dependencies)), uintptr(unsafe.Pointer(serviceStartName)), uintptr(unsafe.Pointer(password)), 0, 0) handle = Handle(r0) diff --git a/vendor/modules.txt b/vendor/modules.txt index a00f1becc..c4cfc0d83 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -93,7 +93,7 @@ github.com/containers/buildah/pkg/overlay github.com/containers/buildah/pkg/parse github.com/containers/buildah/pkg/rusage github.com/containers/buildah/util -# github.com/containers/common v0.39.1-0.20210527140106-e5800a20386a +# github.com/containers/common v0.40.2-0.20210623133759-d13a31743aec github.com/containers/common/libimage github.com/containers/common/libimage/manifests github.com/containers/common/pkg/apparmor @@ -114,6 +114,7 @@ github.com/containers/common/pkg/retry github.com/containers/common/pkg/seccomp github.com/containers/common/pkg/secrets github.com/containers/common/pkg/secrets/filedriver +github.com/containers/common/pkg/secrets/passdriver github.com/containers/common/pkg/signal github.com/containers/common/pkg/subscriptions github.com/containers/common/pkg/supplemented @@ -123,7 +124,7 @@ github.com/containers/common/pkg/umask github.com/containers/common/version # github.com/containers/conmon v2.0.20+incompatible github.com/containers/conmon/runner/config -# github.com/containers/image/v5 v5.12.0 +# github.com/containers/image/v5 v5.13.2 github.com/containers/image/v5/copy github.com/containers/image/v5/directory github.com/containers/image/v5/directory/explicitfilepath @@ -195,7 +196,7 @@ github.com/containers/psgo/internal/dev github.com/containers/psgo/internal/host github.com/containers/psgo/internal/proc github.com/containers/psgo/internal/process -# github.com/containers/storage v1.32.1 +# github.com/containers/storage v1.32.3 github.com/containers/storage github.com/containers/storage/drivers github.com/containers/storage/drivers/aufs @@ -253,7 +254,7 @@ github.com/coreos/stream-metadata-go/fedoracoreos github.com/coreos/stream-metadata-go/fedoracoreos/internals github.com/coreos/stream-metadata-go/stream github.com/coreos/stream-metadata-go/stream/rhcos -# github.com/cri-o/ocicni v0.2.1-0.20210301205850-541cf7c703cf +# github.com/cri-o/ocicni v0.2.1-0.20210621164014-d0acc7862283 github.com/cri-o/ocicni/pkg/ocicni # github.com/cyphar/filepath-securejoin v0.2.2 github.com/cyphar/filepath-securejoin @@ -311,7 +312,7 @@ github.com/docker/docker/pkg/parsers github.com/docker/docker/pkg/pools github.com/docker/docker/pkg/stdcopy github.com/docker/docker/pkg/system -# github.com/docker/docker-credential-helpers v0.6.3 +# github.com/docker/docker-credential-helpers v0.6.4 github.com/docker/docker-credential-helpers/client github.com/docker/docker-credential-helpers/credentials # github.com/docker/go-connections v0.4.0 @@ -384,20 +385,20 @@ github.com/hpcloud/tail/ratelimiter github.com/hpcloud/tail/util github.com/hpcloud/tail/watch github.com/hpcloud/tail/winfile -# github.com/imdario/mergo v0.3.11 +# github.com/imdario/mergo v0.3.12 github.com/imdario/mergo # github.com/inconshreveable/mousetrap v1.0.0 github.com/inconshreveable/mousetrap # github.com/ishidawataru/sctp v0.0.0-20210226210310-f2269e66cdee github.com/ishidawataru/sctp -# github.com/jinzhu/copier v0.3.0 +# github.com/jinzhu/copier v0.3.2 github.com/jinzhu/copier # github.com/json-iterator/go v1.1.11 github.com/json-iterator/go # github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a github.com/juju/ansiterm github.com/juju/ansiterm/tabwriter -# github.com/klauspost/compress v1.12.3 +# github.com/klauspost/compress v1.13.1 github.com/klauspost/compress/flate github.com/klauspost/compress/fse github.com/klauspost/compress/huff0 @@ -415,9 +416,9 @@ github.com/manifoldco/promptui/screenbuf github.com/mattn/go-colorable # github.com/mattn/go-isatty v0.0.12 github.com/mattn/go-isatty -# github.com/mattn/go-runewidth v0.0.12 +# github.com/mattn/go-runewidth v0.0.13 github.com/mattn/go-runewidth -# github.com/mattn/go-shellwords v1.0.11 +# github.com/mattn/go-shellwords v1.0.12 github.com/mattn/go-shellwords # github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 github.com/matttproud/golang_protobuf_extensions/pbutil @@ -605,6 +606,11 @@ github.com/vbauerster/mpb/v6 github.com/vbauerster/mpb/v6/cwriter github.com/vbauerster/mpb/v6/decor github.com/vbauerster/mpb/v6/internal +# github.com/vbauerster/mpb/v7 v7.0.2 +github.com/vbauerster/mpb/v7 +github.com/vbauerster/mpb/v7/cwriter +github.com/vbauerster/mpb/v7/decor +github.com/vbauerster/mpb/v7/internal # github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852 github.com/vishvananda/netlink github.com/vishvananda/netlink/nl @@ -662,7 +668,7 @@ golang.org/x/net/proxy golang.org/x/net/trace # golang.org/x/sync v0.0.0-20201207232520-09787c993a3a golang.org/x/sync/semaphore -# golang.org/x/sys v0.0.0-20210514084401-e8d321eab015 +# golang.org/x/sys v0.0.0-20210603125802-9665404d3644 golang.org/x/sys/cpu golang.org/x/sys/execabs golang.org/x/sys/internal/unsafeheader @@ -782,10 +788,10 @@ gopkg.in/tomb.v1 gopkg.in/yaml.v2 # gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 gopkg.in/yaml.v3 -# k8s.io/api v0.21.1 +# k8s.io/api v0.21.2 k8s.io/api/apps/v1 k8s.io/api/core/v1 -# k8s.io/apimachinery v0.21.1 +# k8s.io/apimachinery v0.21.2 k8s.io/apimachinery/pkg/api/resource k8s.io/apimachinery/pkg/apis/meta/v1 k8s.io/apimachinery/pkg/conversion |