diff options
387 files changed, 4585 insertions, 1880 deletions
diff --git a/.cirrus.yml b/.cirrus.yml index 7e523c4ae..ae5463427 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -429,7 +429,7 @@ apiv2_test_task: compose_test_task: - name: "compose test on $DISTRO_NV ($PRIV_NAME)" + name: "$TEST_FLAVOR test on $DISTRO_NV ($PRIV_NAME)" alias: compose_test only_if: *not_build skip: *tags @@ -438,11 +438,18 @@ compose_test_task: gce_instance: *standardvm env: <<: *stdenvars - TEST_FLAVOR: compose matrix: - env: + TEST_FLAVOR: compose PRIV_NAME: root - env: + TEST_FLAVOR: compose + PRIV_NAME: rootless + - env: + TEST_FLAVOR: compose_v2 + PRIV_NAME: root + - env: + TEST_FLAVOR: compose_v2 PRIV_NAME: rootless clone_script: *noop # Comes from cache gopath_cache: *ro_gopath_cache @@ -800,7 +807,59 @@ success_task: CTR_FQIN: ${FEDORA_CONTAINER_FQIN} TEST_ENVIRON: container clone_script: *noop - script: /bin/true + script: *noop + + +artifacts_task: + name: "Artifacts" + alias: artifacts + only_if: *not_docs + depends_on: + - success + # This task is a secondary/convenience for downstream consumers, don't + # block development progress if there is a failure in a PR, only break + # when running on branches or tags. + allow_failures: $CIRRUS_PR != '' + container: *smallcontainer + env: + CTR_FQIN: ${FEDORA_CONTAINER_FQIN} + TEST_ENVIRON: container + CURL: "curl --fail --location -O https://api.cirrus-ci.com/v1/artifact/build/${CIRRUS_BUILD_ID}" + # In order to keep the download URL and Cirrus-CI artifact.zip contents + # simple, nothing should exist in $CIRRUS_WORKING_DIR except for artifacts. + clone_script: *noop + script: + # Assume the latest Fedora release build is most useful + - $CURL/Build%20for%20$FEDORA_NAME/binary/bin/podman + - $CURL/Build%20for%20$FEDORA_NAME/binary/bin/podman-remote + - $CURL/Build%20for%20$FEDORA_NAME/binary/bin/rootlessport + - chmod +x podman* rootlessport + # Architecture in filename & can't use wildcards in a URL + - mkdir -p /tmp/alt + - cd /tmp/alt + - $CURL/Alt%20Arch.%20Cross/gosrc.zip + - unzip gosrc.zip + - cd $CIRRUS_WORKING_DIR + - mv /tmp/alt/*.tar.gz ./ + # Windows MSI filename has version number + - mkdir -p /tmp/win + - cd /tmp/win + - $CURL/Windows%20Cross/gosrc.zip + - unzip gosrc.zip + - cd $CIRRUS_WORKING_DIR + - mv /tmp/win/podman-remote*.zip /tmp/win/*.msi ./ + # OSX + - $CURL/OSX%20Cross/gosrc/podman-remote-release-darwin_amd64.zip + - $CURL/OSX%20Cross/gosrc/podman-remote-release-darwin_arm64.zip + # Always show contents to assist in debugging + always: + contents_script: ls -1 $CIRRUS_WORKING_DIR + # Produce downloadable files and an automatic zip-file accessible + # by a consistent URL, based on contents of $CIRRUS_WORKING_DIR + # Ref: https://cirrus-ci.org/guide/writing-tasks/#latest-build-artifacts + binary_artifacts: + path: ./* + type: application/octet-stream # When a new tag is pushed, confirm that the code and commits diff --git a/.golangci.yml b/.golangci.yml index f3338b9ae..956e528ef 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -13,7 +13,8 @@ linters: enable-all: true disable: # All these break for one reason or another - - nolintlint + - nolintlint # some linter must be disabled (see `nolint` in the code) + - tagliatelle # too many JSON keys cannot be changed due to compat - gocognit - testpackage - goerr113 @@ -38,7 +39,6 @@ linters: - gofumpt - gci - godot - - makezero - dupl - funlen - gochecknoglobals @@ -51,6 +51,17 @@ linters: - gocritic - gosec - maligned + - gomoddirectives + - revive + - containedctx + - contextcheck + - cyclop + - errname + - forcetypeassert + - ireturn + - varnamelen + - maintidx + - nilnil linters-settings: errcheck: check-blank: false @@ -292,7 +292,7 @@ validate: gofmt lint .gitvalidation validate.completions man-page-check swagger- .PHONY: build-all-new-commits build-all-new-commits: # Validate that all the commits build on top of $(GIT_BASE_BRANCH) - git rebase $(GIT_BASE_BRANCH) -x make + git rebase $(GIT_BASE_BRANCH) -x "$(MAKE)" .PHONY: vendor vendor: @@ -336,7 +336,10 @@ $(SRCBINDIR)/podman$(BINSFX): $(SRCBINDIR) .gopathok $(SOURCES) go.mod go.sum -o $@ ./cmd/podman $(SRCBINDIR)/podman-remote-static: $(SRCBINDIR) .gopathok $(SOURCES) go.mod go.sum - $(GOCMD) build \ + CGO_ENABLED=0 \ + GOOS=$(GOOS) \ + GOARCH=$(GOARCH) \ + $(GO) build \ $(BUILDFLAGS) \ $(GO_LDFLAGS) '$(LDFLAGS_PODMAN_STATIC)' \ -tags "${REMOTETAGS}" \ @@ -432,22 +435,6 @@ local-cross: $(CROSS_BUILD_TARGETS) ## Cross compile podman binary for multiple .PHONY: cross cross: local-cross -# Update nix/nixpkgs.json its latest stable commit -.PHONY: nixpkgs -nixpkgs: - @nix run \ - -f channel:nixos-21.05 nix-prefetch-git \ - -c nix-prefetch-git \ - --no-deepClone \ - https://github.com/nixos/nixpkgs refs/heads/nixos-21.05 > nix/nixpkgs.json - -# Build statically linked binary -.PHONY: static -static: - @nix build -f nix/ - mkdir -p ./bin - cp -rfp ./result/bin/* ./bin/ - .PHONY: build-no-cgo build-no-cgo: BUILDTAGS="containers_image_openpgp exclude_graphdriver_btrfs \ @@ -882,7 +869,7 @@ install.tools: .install.goimports .install.gitvalidation .install.md2man .instal .PHONY: .install.golangci-lint .install.golangci-lint: .gopathok - VERSION=1.36.0 GOBIN=$(GOBIN) ./hack/install_golangci.sh + VERSION=1.45.0 GOBIN=$(GOBIN) ./hack/install_golangci.sh .PHONY: .install.bats .install.bats: .gopathok diff --git a/cmd/podman/common/create.go b/cmd/podman/common/create.go index f3e2e4d6d..afaa1942e 100644 --- a/cmd/podman/common/create.go +++ b/cmd/podman/common/create.go @@ -394,14 +394,6 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions, ) _ = cmd.RegisterFlagCompletionFunc(platformFlagName, completion.AutocompleteNone) - podFlagName := "pod" - createFlags.StringVar( - &cf.Pod, - podFlagName, "", - "Run container in an existing pod", - ) - _ = cmd.RegisterFlagCompletionFunc(podFlagName, AutocompletePods) - podIDFileFlagName := "pod-id-file" createFlags.StringVar( &cf.PodIDFile, @@ -721,7 +713,7 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions, "Optional parent cgroup for the container", ) _ = cmd.RegisterFlagCompletionFunc(cgroupParentFlagName, completion.AutocompleteDefault) - conmonPidfileFlagName := "" + var conmonPidfileFlagName string if !isInfra { conmonPidfileFlagName = "conmon-pidfile" } else { @@ -734,7 +726,7 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions, ) _ = cmd.RegisterFlagCompletionFunc(conmonPidfileFlagName, completion.AutocompleteDefault) - entrypointFlagName := "" + var entrypointFlagName string if !isInfra { entrypointFlagName = "entrypoint" } else { @@ -837,6 +829,14 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions, ) _ = cmd.RegisterFlagCompletionFunc(nameFlagName, completion.AutocompleteNone) + podFlagName := "pod" + createFlags.StringVar( + &cf.Pod, + podFlagName, "", + "Run container in an existing pod", + ) + _ = cmd.RegisterFlagCompletionFunc(podFlagName, AutocompletePods) + cpuPeriodFlagName := "cpu-period" createFlags.Uint64Var( &cf.CPUPeriod, diff --git a/cmd/podman/common/create_opts.go b/cmd/podman/common/create_opts.go index b110b3d85..e5a2a0da3 100644 --- a/cmd/podman/common/create_opts.go +++ b/cmd/podman/common/create_opts.go @@ -97,12 +97,21 @@ func ContainerCreateToContainerCLIOpts(cc handlers.CreateContainerConfig, rtc *c } // mounts type=tmpfs/bind,source=...,target=...=,opt=val + volSources := make(map[string]bool) + volDestinations := make(map[string]bool) mounts := make([]string, 0, len(cc.HostConfig.Mounts)) var builder strings.Builder for _, m := range cc.HostConfig.Mounts { addField(&builder, "type", string(m.Type)) addField(&builder, "source", m.Source) addField(&builder, "target", m.Target) + + // Store source/dest so we don't add duplicates if a volume is + // also mentioned in cc.Volumes. + // Which Docker Compose v2.0 does, for unclear reasons... + volSources[m.Source] = true + volDestinations[m.Target] = true + if m.ReadOnly { addField(&builder, "ro", "true") } @@ -328,8 +337,6 @@ func ContainerCreateToContainerCLIOpts(cc handlers.CreateContainerConfig, rtc *c } // volumes - volSources := make(map[string]bool) - volDestinations := make(map[string]bool) for _, vol := range cc.HostConfig.Binds { cliOpts.Volume = append(cliOpts.Volume, vol) // Extract the destination so we don't add duplicate mounts in @@ -348,6 +355,8 @@ func ContainerCreateToContainerCLIOpts(cc handlers.CreateContainerConfig, rtc *c // format of `-v` so we can just append them in there. // Unfortunately, these may be duplicates of existing mounts in Binds. // So... We need to catch that. + // This also handles volumes duplicated between cc.HostConfig.Mounts and + // cc.Volumes, as seen in compose v2.0. for vol := range cc.Volumes { if _, ok := volDestinations[filepath.Clean(vol)]; ok { continue diff --git a/cmd/podman/containers/clone.go b/cmd/podman/containers/clone.go index d095d24ba..8a1473608 100644 --- a/cmd/podman/containers/clone.go +++ b/cmd/podman/containers/clone.go @@ -58,9 +58,8 @@ func clone(cmd *cobra.Command, args []string) error { case 3: ctrClone.CreateOpts.Name = args[1] ctrClone.Image = args[2] - rawImageName := "" if !cliVals.RootFS { - rawImageName = args[0] + rawImageName := args[0] name, err := PullImage(ctrClone.Image, ctrClone.CreateOpts) if err != nil { return err diff --git a/cmd/podman/containers/cp.go b/cmd/podman/containers/cp.go index 7ac28b799..eb18dfce4 100644 --- a/cmd/podman/containers/cp.go +++ b/cmd/podman/containers/cp.go @@ -449,7 +449,7 @@ func resolvePathOnDestinationContainer(container string, containerPath string, i containerInfo, err = registry.ContainerEngine().ContainerStat(registry.GetContext(), container, containerPath) if err == nil { baseName = filepath.Base(containerInfo.LinkTarget) - return + return // nolint: nilerr } if strings.HasSuffix(containerPath, "/") { diff --git a/cmd/podman/containers/start.go b/cmd/podman/containers/start.go index a7731a0a1..b70e975b7 100644 --- a/cmd/podman/containers/start.go +++ b/cmd/podman/containers/start.go @@ -122,7 +122,7 @@ func start(cmd *cobra.Command, args []string) error { startOptions.Stdout = os.Stdout } - var containers []string = args + containers := args if len(filters) > 0 { for _, f := range filters { split := strings.SplitN(f, "=", 2) diff --git a/cmd/podman/early_init_unsupported.go b/cmd/podman/early_init_unsupported.go index 4e748559f..55bb0906f 100644 --- a/cmd/podman/early_init_unsupported.go +++ b/cmd/podman/early_init_unsupported.go @@ -1,3 +1,4 @@ +//go:build !linux // +build !linux package main diff --git a/cmd/podman/images/build.go b/cmd/podman/images/build.go index 729951a31..1f9e7ea9e 100644 --- a/cmd/podman/images/build.go +++ b/cmd/podman/images/build.go @@ -375,7 +375,7 @@ func buildFlagsWrapperToOptions(c *cobra.Command, contextDir string, flags *buil } } - cleanTmpFile := false + var cleanTmpFile bool flags.Authfile, cleanTmpFile = buildahUtil.MirrorToTempFileIfPathIsDescriptor(flags.Authfile) if cleanTmpFile { defer os.Remove(flags.Authfile) @@ -474,7 +474,7 @@ func buildFlagsWrapperToOptions(c *cobra.Command, contextDir string, flags *buil return nil, err } - format := "" + var format string flags.Format = strings.ToLower(flags.Format) switch { case strings.HasPrefix(flags.Format, buildahDefine.OCI): diff --git a/cmd/podman/images/import.go b/cmd/podman/images/import.go index a7416e298..47f2a798d 100644 --- a/cmd/podman/images/import.go +++ b/cmd/podman/images/import.go @@ -76,6 +76,18 @@ func importFlags(cmd *cobra.Command) { flags.StringVarP(&importOpts.Message, messageFlagName, "m", "", "Set commit message for imported image") _ = cmd.RegisterFlagCompletionFunc(messageFlagName, completion.AutocompleteNone) + osFlagName := "os" + flags.StringVar(&importOpts.OS, osFlagName, "", "Set the OS of the imported image") + _ = cmd.RegisterFlagCompletionFunc(osFlagName, completion.AutocompleteNone) + + archFlagName := "arch" + flags.StringVar(&importOpts.Architecture, archFlagName, "", "Set the architecture of the imported image") + _ = cmd.RegisterFlagCompletionFunc(archFlagName, completion.AutocompleteNone) + + variantFlagName := "variant" + flags.StringVar(&importOpts.Variant, variantFlagName, "", "Set the variant of the imported image") + _ = cmd.RegisterFlagCompletionFunc(variantFlagName, completion.AutocompleteNone) + flags.BoolVarP(&importOpts.Quiet, "quiet", "q", false, "Suppress output") if !registry.IsRemote() { flags.StringVar(&importOpts.SignaturePolicy, "signature-policy", "", "Path to a signature-policy file") diff --git a/cmd/podman/images/rm.go b/cmd/podman/images/rm.go index dd138d410..13dab62d4 100644 --- a/cmd/podman/images/rm.go +++ b/cmd/podman/images/rm.go @@ -56,6 +56,7 @@ func init() { func imageRemoveFlagSet(flags *pflag.FlagSet) { flags.BoolVarP(&imageOpts.All, "all", "a", false, "Remove all images") + flags.BoolVarP(&imageOpts.Ignore, "ignore", "i", false, "Ignore errors if a specified image does not exist") flags.BoolVarP(&imageOpts.Force, "force", "f", false, "Force Removal of the image") } diff --git a/cmd/podman/images/scp.go b/cmd/podman/images/scp.go index d07a5d99d..152275c68 100644 --- a/cmd/podman/images/scp.go +++ b/cmd/podman/images/scp.go @@ -105,7 +105,7 @@ func scp(cmd *cobra.Command, args []string) (finalErr error) { } locations := []*entities.ImageScpOptions{} cliConnections := []string{} - flipConnections := false + var flipConnections bool for _, arg := range args { loc, connect, err := parseImageSCPArg(arg) if err != nil { @@ -233,7 +233,7 @@ func loadToRemote(localFile string, tag string, url *urlP.URL, iden string) (str errOut := strconv.Itoa(int(n)) + " Bytes copied before error" return " ", errors.Wrapf(err, errOut) } - run := "" + var run string if tag != "" { return "", errors.Wrapf(define.ErrInvalidArg, "Renaming of an image is currently not supported") } @@ -264,10 +264,12 @@ func saveToRemote(image, localFile string, tag string, uri *urlP.URL, iden strin run := podman + " image save " + image + " --format=oci-archive --output=" + remoteFile // run ssh image load of the file copied via scp. Files are reverse in this case... _, err = connection.ExecRemoteCommand(dial, run) if err != nil { - return nil + return err } n, err := scpD.CopyFrom(dial, remoteFile, localFile) - connection.ExecRemoteCommand(dial, "rm "+remoteFile) + if _, conErr := connection.ExecRemoteCommand(dial, "rm "+remoteFile); conErr != nil { + logrus.Errorf("Error removing file on endpoint: %v", conErr) + } if err != nil { errOut := strconv.Itoa(int(n)) + " Bytes copied before error" return errors.Wrapf(err, errOut) diff --git a/cmd/podman/images/search.go b/cmd/podman/images/search.go index 292a1d060..aa11cf254 100644 --- a/cmd/podman/images/search.go +++ b/cmd/podman/images/search.go @@ -105,7 +105,7 @@ func searchFlags(cmd *cobra.Command) { // imageSearch implements the command for searching images. func imageSearch(cmd *cobra.Command, args []string) error { - searchTerm := "" + var searchTerm string switch len(args) { case 1: searchTerm = args[0] diff --git a/cmd/podman/images/utils_unsupported.go b/cmd/podman/images/utils_unsupported.go index 69d1df786..7d4a19ded 100644 --- a/cmd/podman/images/utils_unsupported.go +++ b/cmd/podman/images/utils_unsupported.go @@ -1,3 +1,4 @@ +//go:build !linux // +build !linux package images diff --git a/cmd/podman/machine/init.go b/cmd/podman/machine/init.go index ab13d8651..e07b6fbfa 100644 --- a/cmd/podman/machine/init.go +++ b/cmd/podman/machine/init.go @@ -1,3 +1,4 @@ +//go:build amd64 || arm64 // +build amd64 arm64 package machine @@ -82,7 +83,7 @@ func init() { "reexec", false, "process was rexeced", ) - flags.MarkHidden("reexec") + _ = flags.MarkHidden("reexec") ImagePathFlagName := "image-path" flags.StringVar(&initOpts.ImagePath, ImagePathFlagName, cfg.Machine.Image, "Path to qcow image") diff --git a/cmd/podman/machine/machine.go b/cmd/podman/machine/machine.go index 4937fcbda..d3775f022 100644 --- a/cmd/podman/machine/machine.go +++ b/cmd/podman/machine/machine.go @@ -1,3 +1,4 @@ +//go:build amd64 || arm64 // +build amd64 arm64 package machine diff --git a/cmd/podman/machine/machine_unsupported.go b/cmd/podman/machine/machine_unsupported.go index 2f4189446..e11049888 100644 --- a/cmd/podman/machine/machine_unsupported.go +++ b/cmd/podman/machine/machine_unsupported.go @@ -1,3 +1,4 @@ +//go:build !amd64 && !arm64 // +build !amd64,!arm64 package machine diff --git a/cmd/podman/machine/platform.go b/cmd/podman/machine/platform.go index bbcf06c85..77fec083e 100644 --- a/cmd/podman/machine/platform.go +++ b/cmd/podman/machine/platform.go @@ -1,3 +1,4 @@ +//go:build (amd64 && !windows) || (arm64 && !windows) // +build amd64,!windows arm64,!windows package machine diff --git a/cmd/podman/machine/rm.go b/cmd/podman/machine/rm.go index 3e5d5fb0b..617a70a76 100644 --- a/cmd/podman/machine/rm.go +++ b/cmd/podman/machine/rm.go @@ -1,3 +1,4 @@ +//go:build amd64 || arm64 // +build amd64 arm64 package machine @@ -26,7 +27,7 @@ var ( ) var ( - destoryOptions machine.RemoveOptions + destroyOptions machine.RemoveOptions ) func init() { @@ -37,16 +38,16 @@ func init() { flags := rmCmd.Flags() formatFlagName := "force" - flags.BoolVarP(&destoryOptions.Force, formatFlagName, "f", false, "Stop and do not prompt before rming") + flags.BoolVarP(&destroyOptions.Force, formatFlagName, "f", false, "Stop and do not prompt before rming") keysFlagName := "save-keys" - flags.BoolVar(&destoryOptions.SaveKeys, keysFlagName, false, "Do not delete SSH keys") + flags.BoolVar(&destroyOptions.SaveKeys, keysFlagName, false, "Do not delete SSH keys") ignitionFlagName := "save-ignition" - flags.BoolVar(&destoryOptions.SaveIgnition, ignitionFlagName, false, "Do not delete ignition file") + flags.BoolVar(&destroyOptions.SaveIgnition, ignitionFlagName, false, "Do not delete ignition file") imageFlagName := "save-image" - flags.BoolVar(&destoryOptions.SaveImage, imageFlagName, false, "Do not delete the image file") + flags.BoolVar(&destroyOptions.SaveImage, imageFlagName, false, "Do not delete the image file") } func rm(cmd *cobra.Command, args []string) error { @@ -64,12 +65,12 @@ func rm(cmd *cobra.Command, args []string) error { if err != nil { return err } - confirmationMessage, remove, err := vm.Remove(vmName, destoryOptions) + confirmationMessage, remove, err := vm.Remove(vmName, destroyOptions) if err != nil { return err } - if !destoryOptions.Force { + if !destroyOptions.Force { // Warn user fmt.Println(confirmationMessage) reader := bufio.NewReader(os.Stdin) diff --git a/cmd/podman/machine/set.go b/cmd/podman/machine/set.go index c978206f0..4c15f1de1 100644 --- a/cmd/podman/machine/set.go +++ b/cmd/podman/machine/set.go @@ -1,3 +1,4 @@ +//go:build amd64 || arm64 // +build amd64 arm64 package machine @@ -16,7 +17,7 @@ var ( Long: "Sets an updatable virtual machine setting", RunE: setMachine, Args: cobra.MaximumNArgs(1), - Example: `podman machine set --root=false`, + Example: `podman machine set --rootful=false`, ValidArgsFunction: completion.AutocompleteNone, } ) diff --git a/cmd/podman/machine/ssh.go b/cmd/podman/machine/ssh.go index ba37f7ba4..e1175d632 100644 --- a/cmd/podman/machine/ssh.go +++ b/cmd/podman/machine/ssh.go @@ -1,3 +1,4 @@ +//go:build amd64 || arm64 // +build amd64 arm64 package machine diff --git a/cmd/podman/machine/start.go b/cmd/podman/machine/start.go index 16faa25ef..56acb09cb 100644 --- a/cmd/podman/machine/start.go +++ b/cmd/podman/machine/start.go @@ -57,10 +57,6 @@ func start(cmd *cobra.Command, args []string) error { } return errors.Wrapf(machine.ErrMultipleActiveVM, "cannot start VM %s. VM %s is currently running", vmName, activeName) } - vm, err = provider.LoadVMByName(vmName) - if err != nil { - return err - } fmt.Printf("Starting machine %q\n", vmName) if err := vm.Start(vmName, machine.StartOptions{}); err != nil { return err diff --git a/cmd/podman/networks/create.go b/cmd/podman/networks/create.go index 3dd393c46..8cf9bcada 100644 --- a/cmd/podman/networks/create.go +++ b/cmd/podman/networks/create.go @@ -60,7 +60,7 @@ func networkCreateFlags(cmd *cobra.Command) { macvlanFlagName := "macvlan" flags.StringVar(&networkCreateOptions.MacVLAN, macvlanFlagName, "", "create a Macvlan connection based on this device") // This option is deprecated - flags.MarkHidden(macvlanFlagName) + _ = flags.MarkHidden(macvlanFlagName) labelFlagName := "label" flags.StringArrayVar(&labels, labelFlagName, nil, "set metadata on a network") diff --git a/cmd/podman/parse/json.go b/cmd/podman/parse/json.go index d7486d0b1..85572a057 100644 --- a/cmd/podman/parse/json.go +++ b/cmd/podman/parse/json.go @@ -4,7 +4,7 @@ import "regexp" var jsonFormatRegex = regexp.MustCompile(`^\s*(json|{{\s*json\s*(\.)?\s*}})\s*$`) -// MatchesJSONFormat test CLI --format string to be a JSON request +// MatchesJSONFormat test CLI --format string to be a JSON request. func MatchesJSONFormat(s string) bool { return jsonFormatRegex.Match([]byte(s)) } diff --git a/cmd/podman/play/kube.go b/cmd/podman/play/kube.go index 3067f0d54..e92516eb4 100644 --- a/cmd/podman/play/kube.go +++ b/cmd/podman/play/kube.go @@ -209,10 +209,15 @@ func teardown(yamlfile string) error { podRmErrors utils.OutputErrors ) options := new(entities.PlayKubeDownOptions) - reports, err := registry.ContainerEngine().PlayKubeDown(registry.GetContext(), yamlfile, *options) + f, err := os.Open(yamlfile) if err != nil { return err } + defer f.Close() + reports, err := registry.ContainerEngine().PlayKubeDown(registry.GetContext(), f, *options) + if err != nil { + return errors.Wrap(err, yamlfile) + } // Output stopped pods fmt.Println("Pods stopped:") @@ -242,10 +247,15 @@ func teardown(yamlfile string) error { } func playkube(yamlfile string) error { - report, err := registry.ContainerEngine().PlayKube(registry.GetContext(), yamlfile, kubeOptions.PlayKubeOptions) + f, err := os.Open(yamlfile) if err != nil { return err } + defer f.Close() + report, err := registry.ContainerEngine().PlayKube(registry.GetContext(), f, kubeOptions.PlayKubeOptions) + if err != nil { + return errors.Wrap(err, yamlfile) + } // Print volumes report for i, volume := range report.Volumes { if i == 0 { diff --git a/cmd/podman/registry/config_abi.go b/cmd/podman/registry/config_abi.go index 4a909c17e..7babfa169 100644 --- a/cmd/podman/registry/config_abi.go +++ b/cmd/podman/registry/config_abi.go @@ -1,3 +1,4 @@ +//go:build !remote // +build !remote package registry diff --git a/cmd/podman/registry/config_tunnel.go b/cmd/podman/registry/config_tunnel.go index bb3da947e..dfdbab8f8 100644 --- a/cmd/podman/registry/config_tunnel.go +++ b/cmd/podman/registry/config_tunnel.go @@ -1,3 +1,4 @@ +//go:build remote // +build remote package registry diff --git a/cmd/podman/root.go b/cmd/podman/root.go index 6d768c2e6..500a475bd 100644 --- a/cmd/podman/root.go +++ b/cmd/podman/root.go @@ -402,7 +402,7 @@ func rootFlags(cmd *cobra.Command, opts *entities.PodmanConfig) { networkBackendFlagName := "network-backend" pFlags.StringVar(&cfg.Network.NetworkBackend, networkBackendFlagName, cfg.Network.NetworkBackend, `Network backend to use ("cni"|"netavark")`) _ = cmd.RegisterFlagCompletionFunc(networkBackendFlagName, common.AutocompleteNetworkBackend) - pFlags.MarkHidden(networkBackendFlagName) + _ = pFlags.MarkHidden(networkBackendFlagName) rootFlagName := "root" pFlags.StringVar(&cfg.Engine.StaticDir, rootFlagName, "", "Path to the root directory in which data, including images, is stored") diff --git a/cmd/podman/syslog_unsupported.go b/cmd/podman/syslog_unsupported.go index 3765d96b9..42a7851ab 100644 --- a/cmd/podman/syslog_unsupported.go +++ b/cmd/podman/syslog_unsupported.go @@ -1,3 +1,4 @@ +//go:build !linux // +build !linux package main diff --git a/cmd/podman/system/connection/add.go b/cmd/podman/system/connection/add.go index 324e02db4..db575a689 100644 --- a/cmd/podman/system/connection/add.go +++ b/cmd/podman/system/connection/add.go @@ -244,7 +244,7 @@ func getUDS(cmd *cobra.Command, uri *url.URL, iden string) (string, error) { // ValidateAndConfigure will take a ssh url and an identity key (rsa and the like) and ensure the information given is valid // iden iden can be blank to mean no identity key -// once the function validates the information it creates and returns an ssh.ClientConfig +// once the function validates the information it creates and returns an ssh.ClientConfig. func ValidateAndConfigure(uri *url.URL, iden string) (*ssh.ClientConfig, error) { var signers []ssh.Signer passwd, passwdSet := uri.User.Password() diff --git a/cmd/podman/system/connection/default.go b/cmd/podman/system/connection/default.go index c59ff36af..81866df55 100644 --- a/cmd/podman/system/connection/default.go +++ b/cmd/podman/system/connection/default.go @@ -11,7 +11,7 @@ import ( ) var ( - // Skip creating engines since this command will obtain connection information to said engines + // Skip creating engines since this command will obtain connection information to said engines. dfltCmd = &cobra.Command{ Use: "default NAME", Args: cobra.ExactArgs(1), diff --git a/cmd/podman/system/connection/remove.go b/cmd/podman/system/connection/remove.go index 84ec3e2ee..463eae9fa 100644 --- a/cmd/podman/system/connection/remove.go +++ b/cmd/podman/system/connection/remove.go @@ -10,7 +10,7 @@ import ( ) var ( - // Skip creating engines since this command will obtain connection information to said engines + // Skip creating engines since this command will obtain connection information to said engines. rmCmd = &cobra.Command{ Use: "remove [options] NAME", Aliases: []string{"rm"}, diff --git a/cmd/podman/system/df.go b/cmd/podman/system/df.go index b2325507a..dad14df6b 100644 --- a/cmd/podman/system/df.go +++ b/cmd/podman/system/df.go @@ -2,6 +2,7 @@ package system import ( "fmt" + "math" "os" "strings" "time" @@ -170,7 +171,7 @@ func printVerbose(cmd *cobra.Command, reports *entities.SystemDfReport) error { return err } if err := writeTemplate(rpt, hdrs, dfImages); err != nil { - return nil + return err } fmt.Fprint(rpt.Writer(), "\nContainers space usage:\n\n") @@ -190,7 +191,7 @@ func printVerbose(cmd *cobra.Command, reports *entities.SystemDfReport) error { return err } if err := writeTemplate(rpt, hdrs, dfContainers); err != nil { - return nil + return err } fmt.Fprint(rpt.Writer(), "\nLocal Volumes space usage:\n\n") @@ -288,6 +289,10 @@ func (d *dfSummary) Size() string { } func (d *dfSummary) Reclaimable() string { - percent := int(float64(d.reclaimable)/float64(d.size)) * 100 + percent := 0 + // make sure to check this to prevent div by zero problems + if d.size > 0 { + percent = int(math.Round(float64(d.reclaimable) / float64(d.size) * float64(100))) + } return fmt.Sprintf("%s (%d%%)", units.HumanSize(float64(d.reclaimable)), percent) } diff --git a/cmd/podman/system/migrate.go b/cmd/podman/system/migrate.go index c6b6546e7..5d7b31314 100644 --- a/cmd/podman/system/migrate.go +++ b/cmd/podman/system/migrate.go @@ -1,3 +1,4 @@ +//go:build !remote // +build !remote package system diff --git a/cmd/podman/system/renumber.go b/cmd/podman/system/renumber.go index b310dc607..f24488822 100644 --- a/cmd/podman/system/renumber.go +++ b/cmd/podman/system/renumber.go @@ -1,3 +1,4 @@ +//go:build !remote // +build !remote package system diff --git a/cmd/podman/system/reset.go b/cmd/podman/system/reset.go index 07904faaa..e8cf127b7 100644 --- a/cmd/podman/system/reset.go +++ b/cmd/podman/system/reset.go @@ -1,3 +1,4 @@ +//go:build !remote // +build !remote package system diff --git a/cmd/podman/system/service.go b/cmd/podman/system/service.go index daf252401..1a93b3137 100644 --- a/cmd/podman/system/service.go +++ b/cmd/podman/system/service.go @@ -1,3 +1,4 @@ +//go:build linux && !remote // +build linux,!remote package system @@ -66,7 +67,7 @@ func init() { flags.StringVarP(&srvArgs.PProfAddr, "pprof-address", "", "", "Binding network address for pprof profile endpoints, default: do not expose endpoints") - flags.MarkHidden("pprof-address") + _ = flags.MarkHidden("pprof-address") } func aliasTimeoutFlag(_ *pflag.FlagSet, name string) pflag.NormalizedName { diff --git a/cmd/podman/system/service_abi.go b/cmd/podman/system/service_abi.go index 560cce847..d6b42ed29 100644 --- a/cmd/podman/system/service_abi.go +++ b/cmd/podman/system/service_abi.go @@ -1,3 +1,4 @@ +//go:build linux && !remote // +build linux,!remote package system diff --git a/cmd/podman/utils/signals_linux.go b/cmd/podman/utils/signals_linux.go index f0a14aff0..dd0507c0e 100644 --- a/cmd/podman/utils/signals_linux.go +++ b/cmd/podman/utils/signals_linux.go @@ -1,3 +1,4 @@ +//go:build !windows // +build !windows package utils diff --git a/cmd/podman/utils/signals_windows.go b/cmd/podman/utils/signals_windows.go index 30b058cb9..e6fcc1b32 100644 --- a/cmd/podman/utils/signals_windows.go +++ b/cmd/podman/utils/signals_windows.go @@ -1,3 +1,4 @@ +//go:build windows // +build windows package utils diff --git a/cmd/podman/validate/args.go b/cmd/podman/validate/args.go index 1642e2280..743ee1837 100644 --- a/cmd/podman/validate/args.go +++ b/cmd/podman/validate/args.go @@ -27,7 +27,7 @@ func SubCommandExists(cmd *cobra.Command, args []string) error { } return errors.Errorf("unrecognized command `%[1]s %[2]s`\n\nDid you mean this?\n\t%[3]s\n\nTry '%[1]s --help' for more information.", cmd.CommandPath(), args[0], strings.Join(suggestions, "\n\t")) } - cmd.Help() + cmd.Help() // nolint: errcheck return errors.Errorf("missing command '%[1]s COMMAND'", cmd.CommandPath()) } diff --git a/cmd/rootlessport/main.go b/cmd/rootlessport/main.go index 37e91fca8..e9ab8b076 100644 --- a/cmd/rootlessport/main.go +++ b/cmd/rootlessport/main.go @@ -253,9 +253,9 @@ func serve(listener net.Listener, pm rkport.Manager) { ctx := context.TODO() err = handler(ctx, conn, pm) if err != nil { - conn.Write([]byte(err.Error())) + _, _ = conn.Write([]byte(err.Error())) } else { - conn.Write([]byte("OK")) + _, _ = conn.Write([]byte("OK")) } conn.Close() } diff --git a/contrib/cirrus/cirrus_yaml_test.py b/contrib/cirrus/cirrus_yaml_test.py index 39de0c7b7..b424c3ee6 100755 --- a/contrib/cirrus/cirrus_yaml_test.py +++ b/contrib/cirrus/cirrus_yaml_test.py @@ -26,7 +26,7 @@ class TestCaseBase(unittest.TestCase): class TestDependsOn(TestCaseBase): ALL_TASK_NAMES = None - SUCCESS_DEPS_EXCLUDE = set(['success', 'release', 'release_test']) + SUCCESS_DEPS_EXCLUDE = set(['success', 'artifacts', 'release', 'release_test']) def setUp(self): super().setUp() diff --git a/contrib/cirrus/logformatter b/contrib/cirrus/logformatter index 43173eaa6..3ec839aa8 100755 --- a/contrib/cirrus/logformatter +++ b/contrib/cirrus/logformatter @@ -307,10 +307,18 @@ END_HTML elsif ($line =~ /^#\s#\|\s/) { $css = 'log-esm' } elsif ($line =~ /^#\s/) { $css = 'log' } + # Link to source file. This is ugly: we have to hardcode 'podman' + # and 'test/system' because there's no way to get them from log. + # + # 1 2 2 13 4 43 5 + $line =~ s{(in(\stest)?\s+file\s+\S+/)(\S+\.(bats|bash)),\s+line\s+(\d+)}{$1<a class="codelink" href="https://github.com/containers/podman/blob/$git_commit/test/system/$3#L$5">$3, line $5</a>}; + if ($css) { # Make it linkable, e.g. foo.html#t--00001 - if ($line =~ /^(not\s+)?ok\s+(\d+)/) { + if ($line =~ /^(not\s+)?ok\s+(\d+)\s+(.*)/) { $line = sprintf("<a name='t--%05d'>%s</a>", $2, $line); + + push @{$bats_count{__fail_list}}, [ $2, $3 ] if $1; } $line = "<span class='bats-$css'>$line</span>"; @@ -393,7 +401,7 @@ END_HTML # Highlight the important (non-boilerplate) podman command. $line =~ s/\s+--remote\s+/ /g; # --remote takes no args # Strip out the global podman options, but show them on hover - $line =~ s{(\S+\/podman(-remote)?)((\s+--(root|runroot|runtime|tmpdir|storage-opt|conmon|cgroup-manager|network-config-dir|storage-driver|events-backend|url) \S+)*)(.*)}{ + $line =~ s{(\S+\/podman(-remote)?)((\s+--(root|runroot|runtime|tmpdir|storage-opt|conmon|cgroup-manager|network-backend|network-config-dir|storage-driver|events-backend|url) \S+)*)(.*)}{ my ($full_path, $remote, $options, $args) = ($1, $2||'', $3, $6); $options =~ s/^\s+//; @@ -515,6 +523,15 @@ END_HTML } } + # Grumble. Github only shows the last N lines of the log... which is + # anti-helpful when you want a quick synopsis of what failed. Write a + # summary at the tail, to make it easier for humans to see what went wrong. + if (my $fails = $bats_count{__fail_list}) { + print "\n"; + printf "Failed tests (%d):\n", scalar(@$fails); + printf " - %d %s\n", @$_ for @$fails; + } + # If Cirrus magic envariables are available, write a link to results. # FIXME: it'd be so nice to make this a clickable live link. # diff --git a/contrib/cirrus/logformatter.t b/contrib/cirrus/logformatter.t index df8154cb9..2c191769c 100755 --- a/contrib/cirrus/logformatter.t +++ b/contrib/cirrus/logformatter.t @@ -91,6 +91,9 @@ __END__ ok 1 hi ok 2 bye # skip no reason not ok 3 fail +# (from function `assert' in file ./helpers.bash, line 343, +# from function `expect_output' in file ./helpers.bash, line 370, +# in test file ./run.bats, line 786) # $ /path/to/podman foo -bar # #| FAIL: exit code is 123; expected 321 ok 4 blah @@ -99,6 +102,9 @@ ok 4 blah <span class='bats-passed'><a name='t--00001'>ok 1 hi</a></span> <span class='bats-skipped'><a name='t--00002'>ok 2 bye # skip no reason</a></span> <span class='bats-failed'><a name='t--00003'>not ok 3 fail</a></span> +<span class='bats-log'># (from function `assert' in file ./<a class="codelink" href="https://github.com/containers/podman/blob/ceci-nest-pas-une-sha/test/system/helpers.bash#L343">helpers.bash, line 343</a>,</span> +<span class='bats-log'># from function `expect_output' in file ./<a class="codelink" href="https://github.com/containers/podman/blob/ceci-nest-pas-une-sha/test/system/helpers.bash#L370">helpers.bash, line 370</a>,</span> +<span class='bats-log'># in test file ./<a class="codelink" href="https://github.com/containers/podman/blob/ceci-nest-pas-une-sha/test/system/run.bats#L786">run.bats, line 786</a>)</span> <span class='bats-log'># $ <b><span title="/path/to/podman">podman</span> foo -bar</b></span> <span class='bats-log-esm'># #| FAIL: exit code is 123; expected 321</span> <span class='bats-passed'><a name='t--00004'>ok 4 blah</a></span> @@ -125,7 +131,7 @@ $SCRIPT_BASE/integration_test.sh |& ${TIMESTAMP} [+0103s] /var/tmp/go/src/github.com/containers/podman/test/e2e/pod_restart_test.go:18 [+0103s] [It] podman pod restart single empty pod [+0103s] /var/tmp/go/src/github.com/containers/podman/test/e2e/pod_restart_test.go:41 -[+0103s] Running: /var/tmp/go/src/github.com/containers/podman/bin/podman --storage-opt vfs.imagestore=/tmp/podman/imagecachedir --root /tmp/podman_test553496330/crio --runroot /tmp/podman_test553496330/crio-run --runtime /usr/bin/runc --conmon /usr/bin/conmon --network-config-dir /etc/cni/net.d --cgroup-manager systemd --tmpdir /tmp/podman_test553496330 --events-backend file --storage-driver vfs pod create --infra=false --share +[+0103s] Running: /var/tmp/go/src/github.com/containers/podman/bin/podman --network-backend netavark --storage-opt vfs.imagestore=/tmp/podman/imagecachedir --root /tmp/podman_test553496330/crio --runroot /tmp/podman_test553496330/crio-run --runtime /usr/bin/runc --conmon /usr/bin/conmon --network-config-dir /etc/cni/net.d --cgroup-manager systemd --tmpdir /tmp/podman_test553496330 --events-backend file --storage-driver vfs pod create --infra=false --share [+0103s] 4810be0cfbd42241e349dbe7d50fbc54405cd320a6637c65fd5323f34d64af89 [+0103s] output: 4810be0cfbd42241e349dbe7d50fbc54405cd320a6637c65fd5323f34d64af89 [+0103s] Running: /var/tmp/go/src/github.com/containers/podman/bin/podman --storage-opt vfs.imagestore=/tmp/podman/imagecachedir --root /tmp/podman_test553496330/crio --runroot /tmp/podman_test553496330/crio-run --runtime /usr/bin/runc --conmon /usr/bin/conmon --network-config-dir /etc/cni/net.d --cgroup-manager systemd --tmpdir /tmp/podman_test553496330 --events-backend file --storage-driver vfs pod restart 4810be0cfbd42241e349dbe7d50fbc54405cd320a6637c65fd5323f34d64af89 @@ -181,7 +187,8 @@ $SCRIPT_BASE/integration_test.sh |& ${TIMESTAMP} <span class="timestamp"> </span> /var/tmp/go/src/github.com<a class="codelink" href='https://github.com/containers/podman/blob/40f5d8b1becd381c4e8283ed3940d09193e4fe06/test/e2e/pod_restart_test.go#L18'>/containers/podman/test/e2e/pod_restart_test.go:18</a> <span class="timestamp"> </span><span class="testname">[It] podman pod restart single empty pod</span> <span class="timestamp"> </span> /var/tmp/go/src/github.com<a class="codelink" href='https://github.com/containers/podman/blob/40f5d8b1becd381c4e8283ed3940d09193e4fe06/test/e2e/pod_restart_test.go#L41'>/containers/podman/test/e2e/pod_restart_test.go:41</a> -<span class="timestamp"> </span><span class="boring">#</span> <span title="/var/tmp/go/src/github.com/containers/podman/bin/podman"><b>podman</b></span> <span class="boring" title="--storage-opt vfs.imagestore=/tmp/podman/imagecachedir +<span class="timestamp"> </span><span class="boring">#</span> <span title="/var/tmp/go/src/github.com/containers/podman/bin/podman"><b>podman</b></span> <span class="boring" title="--network-backend netavark +--storage-opt vfs.imagestore=/tmp/podman/imagecachedir --root /tmp/podman_test553496330/crio --runroot /tmp/podman_test553496330/crio-run --runtime /usr/bin/runc diff --git a/contrib/cirrus/runner.sh b/contrib/cirrus/runner.sh index d1d87ad04..f33c6af29 100755 --- a/contrib/cirrus/runner.sh +++ b/contrib/cirrus/runner.sh @@ -63,6 +63,10 @@ function _run_compose() { ./test/compose/test-compose |& logformatter } +function _run_compose_v2() { + ./test/compose/test-compose |& logformatter +} + function _run_int() { dotest integration } @@ -224,7 +228,17 @@ function _run_altbuild() { case "$ALT_NAME" in *Each*) git fetch origin - make build-all-new-commits GIT_BASE_BRANCH=origin/$DEST_BRANCH + # The check-size script, introduced 2022-03-22 in #13518, + # runs 'make' (the original purpose of this check) against + # each commit, then checks image sizes to make sure that + # none have grown beyond a given limit. That of course + # requires a baseline, which is why we use '^' to start + # with the *parent* commit of this PR, not the first commit. + context_dir=$(mktemp -d --tmpdir make-size-check.XXXXXXX) + make build-all-new-commits \ + GIT_BASE_BRANCH=origin/"${DEST_BRANCH}^" \ + MAKE="hack/make-and-check-size $context_dir" + rm -rf $context_dir ;; *Windows*) make podman-remote-release-windows_amd64.zip diff --git a/contrib/cirrus/setup_environment.sh b/contrib/cirrus/setup_environment.sh index 696560166..864c78484 100755 --- a/contrib/cirrus/setup_environment.sh +++ b/contrib/cirrus/setup_environment.sh @@ -272,6 +272,11 @@ case "$TEST_FLAVOR" in ;; build) make clean ;; unit) ;; + compose_v2) + dnf -y remove docker-compose + curl -SL https://github.com/docker/compose/releases/download/v2.2.3/docker-compose-linux-x86_64 -o /usr/local/bin/docker-compose + chmod +x /usr/local/bin/docker-compose + ;& # Continue with next item apiv2) msg "Installing previously downloaded/cached packages" dnf install -y $PACKAGE_DOWNLOAD_DIR/python3*.rpm diff --git a/contrib/msi/podman.wxs b/contrib/msi/podman.wxs index c4ba623c0..786465589 100644 --- a/contrib/msi/podman.wxs +++ b/contrib/msi/podman.wxs @@ -13,6 +13,8 @@ <Package Id="*" Keywords="Installer" Description="Red Hat's Podman $(var.VERSION) Installer" Comments="Apache 2.0 License" Manufacturer="Red Hat Inc." InstallScope="perMachine" InstallerVersion="200" Compressed="yes"/> <Media Id="1" Cabinet="Podman.cab" EmbedCab="yes"/> + <!-- Switch to AllowDowngrades="yes" when msitools is released with commit dde7dd2f --> + <MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed. Uninstall first to downgrade."/> <Property Id="DiskPrompt" Value="Red Hat's Podman $(var.VERSION) Installation"/> <Directory Id="TARGETDIR" Name="SourceDir"> diff --git a/dependencies/dependencies.go b/dependencies/dependencies.go index b1b0aee08..adc074d93 100644 --- a/dependencies/dependencies.go +++ b/dependencies/dependencies.go @@ -1,3 +1,4 @@ +//go:build !linter // +build !linter package dependencies diff --git a/docs/source/markdown/podman-build.1.md b/docs/source/markdown/podman-build.1.md index b9542fec5..c8707521f 100644 --- a/docs/source/markdown/podman-build.1.md +++ b/docs/source/markdown/podman-build.1.md @@ -312,7 +312,7 @@ environment variable. `export BUILDAH_FORMAT=docker` Overrides the first `FROM` instruction within the Containerfile. If there are multiple FROM instructions in a Containerfile, only the first is changed. -**-h**, **--help** +#### **--help**, **-h** Print usage statement @@ -320,15 +320,15 @@ Print usage statement Pass through HTTP Proxy environment variables. +#### **--ignorefile** + +Path to an alternative .containerignore file. + #### **--iidfile**=*ImageIDfile* Write the built image's ID to the file. When `--platform` is specified more than once, attempting to use this option will trigger an error. -#### **--ignorefile** - -Path to an alternative .containerignore file. - #### **--ipc**=*how* Sets the configuration for IPC namespaces when handling `RUN` instructions. @@ -643,47 +643,62 @@ the user namespace in which `podman` itself is being run should be reused, or it can be the path to a user namespace which is already in use by another process. -#### **--userns-uid-map**=*mapping* +#### **--userns-gid-map**=*mapping* -Directly specifies a UID mapping which should be used to set ownership, at the +Directly specifies a GID mapping which should be used to set ownership, at the filesystem level, on the working container's contents. Commands run when handling `RUN` instructions will default to being run in their own user namespaces, configured using the UID and GID maps. Entries in this map take the form of one or more triples of a starting -in-container UID, a corresponding starting host-level UID, and the number of +in-container GID, a corresponding starting host-level GID, and the number of consecutive IDs which the map entry represents. -This option overrides the *remap-uids* setting in the *options* section of +This option overrides the *remap-gids* setting in the *options* section of /etc/containers/storage.conf. -If this option is not specified, but a global --userns-uid-map setting is +If this option is not specified, but a global --userns-gid-map setting is supplied, settings from the global option will be used. -If none of --userns-uid-map-user, --userns-gid-map-group, or --userns-uid-map -are specified, but --userns-gid-map is specified, the UID map will be set to -use the same numeric values as the GID map. +If none of --userns-uid-map-user, --userns-gid-map-group, or --userns-gid-map +are specified, but --userns-uid-map is specified, the GID map will be set to +use the same numeric values as the UID map. -#### **--userns-gid-map**=*mapping* +#### **--userns-gid-map-group**=*group* -Directly specifies a GID mapping which should be used to set ownership, at the +Specifies that a GID mapping which should be used to set ownership, at the +filesystem level, on the working container's contents, can be found in entries +in the `/etc/subgid` file which correspond to the specified group. +Commands run when handling `RUN` instructions will default to being run in +their own user namespaces, configured using the UID and GID maps. +If --userns-uid-map-user is specified, but --userns-gid-map-group is not +specified, `podman` will assume that the specified user name is also a +suitable group name to use as the default setting for this option. + +**NOTE:** When this option is specified by a rootless user, the specified +mappings are relative to the rootless user namespace in the container, rather +than being relative to the host as it would be when run rootfull. + +#### **--userns-uid-map**=*mapping* + +Directly specifies a UID mapping which should be used to set ownership, at the filesystem level, on the working container's contents. Commands run when handling `RUN` instructions will default to being run in their own user namespaces, configured using the UID and GID maps. Entries in this map take the form of one or more triples of a starting -in-container GID, a corresponding starting host-level GID, and the number of +in-container UID, a corresponding starting host-level UID, and the number of consecutive IDs which the map entry represents. -This option overrides the *remap-gids* setting in the *options* section of +This option overrides the *remap-uids* setting in the *options* section of /etc/containers/storage.conf. -If this option is not specified, but a global --userns-gid-map setting is +If this option is not specified, but a global --userns-uid-map setting is supplied, settings from the global option will be used. -If none of --userns-uid-map-user, --userns-gid-map-group, or --userns-gid-map -are specified, but --userns-uid-map is specified, the GID map will be set to -use the same numeric values as the UID map. +If none of --userns-uid-map-user, --userns-gid-map-group, or --userns-uid-map +are specified, but --userns-gid-map is specified, the UID map will be set to +use the same numeric values as the GID map. #### **--userns-uid-map-user**=*user* @@ -700,21 +715,6 @@ suitable user name to use as the default setting for this option. mappings are relative to the rootless user namespace in the container, rather than being relative to the host as it would be when run rootfull. -#### **--userns-gid-map-group**=*group* - -Specifies that a GID mapping which should be used to set ownership, at the -filesystem level, on the working container's contents, can be found in entries -in the `/etc/subgid` file which correspond to the specified group. -Commands run when handling `RUN` instructions will default to being run in -their own user namespaces, configured using the UID and GID maps. -If --userns-uid-map-user is specified, but --userns-gid-map-group is not -specified, `podman` will assume that the specified user name is also a -suitable group name to use as the default setting for this option. - -**NOTE:** When this option is specified by a rootless user, the specified -mappings are relative to the rootless user namespace in the container, rather -than being relative to the host as it would be when run rootfull. - #### **--uts**=*how* Sets the configuration for UTS namespaces when handling `RUN` instructions. @@ -1010,7 +1010,7 @@ Exclude all doc files except Help.doc from the image. This functionality is compatible with the handling of .containerignore files described here: -https://github.com/containers/buildah/blob/main/docs/containerignore.5.md +https://github.com/containers/common/blob/main/docs/containerignore.5.md **registries.conf** (`/etc/containers/registries.conf`) @@ -1032,7 +1032,7 @@ If you are using `useradd` within your build script, you should pass the useradd to stop creating the lastlog file. ## SEE ALSO -**[podman(1)](podman.1.md)**, **[buildah(1)](https://github.com/containers/buildah/blob/main/docs/buildah.1.md)**, **[containers-certs.d(5)](https://github.com/containers/image/blob/main/docs/containers-certs.d.5.md)**, **[containers-registries.conf(5)](https://github.com/containers/image/blob/main/docs/containers-registries.conf.5.md)**, **[crun(1)](https://github.com/containers/crun/blob/main/crun.1.md)**, **[runc(8)](https://github.com/opencontainers/runc/blob/master/man/runc.8.md)**, **[useradd(8)](https://www.unix.com/man-page/redhat/8/useradd)**, **[podman-ps(1)](podman-ps.1.md)**, **[podman-rm(1)](podman-rm.1.md)**, **[Containerfile(5)](https://github.com/containers/buildah/blob/main/docs/Containerfile.5.md)**, **[containerignore(5)](https://github.com/containers/buildah/blob/main/docs/containerignore.5.md)** +**[podman(1)](podman.1.md)**, **[buildah(1)](https://github.com/containers/buildah/blob/main/docs/buildah.1.md)**, **[containers-certs.d(5)](https://github.com/containers/image/blob/main/docs/containers-certs.d.5.md)**, **[containers-registries.conf(5)](https://github.com/containers/image/blob/main/docs/containers-registries.conf.5.md)**, **[crun(1)](https://github.com/containers/crun/blob/main/crun.1.md)**, **[runc(8)](https://github.com/opencontainers/runc/blob/master/man/runc.8.md)**, **[useradd(8)](https://www.unix.com/man-page/redhat/8/useradd)**, **[podman-ps(1)](podman-ps.1.md)**, **[podman-rm(1)](podman-rm.1.md)**, **[Containerfile(5)](https://github.com/containers/common/blob/main/docs/Containerfile.5.md)**, **[containerignore(5)](https://github.com/containers/common/blob/main/docs/containerignore.5.md)** ## HISTORY Aug 2020, Additional options and .containerignore added by Dan Walsh `<dwalsh@redhat.com>` diff --git a/docs/source/markdown/podman-commit.1.md b/docs/source/markdown/podman-commit.1.md index df3c38711..3df931254 100644 --- a/docs/source/markdown/podman-commit.1.md +++ b/docs/source/markdown/podman-commit.1.md @@ -60,14 +60,14 @@ Set commit message for committed image.\ Pause the container when creating an image.\ The default is **false**. -#### **--squash**, **-s** +#### **--quiet**, **-q** -Squash newly built layers into a single new layer.\ +Suppresses output.\ The default is **false**. -#### **--quiet**, **-q** +#### **--squash**, **-s** -Suppresses output.\ +Squash newly built layers into a single new layer.\ The default is **false**. ## EXAMPLES diff --git a/docs/source/markdown/podman-container-checkpoint.1.md b/docs/source/markdown/podman-container-checkpoint.1.md index fcb3cfd0c..5c07cd975 100644 --- a/docs/source/markdown/podman-container-checkpoint.1.md +++ b/docs/source/markdown/podman-container-checkpoint.1.md @@ -35,6 +35,14 @@ 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**. +#### **--file-locks** + +Checkpoint a *container* with file locks. If an application running in the container +is using file locks, this OPTION is required during checkpoint and restore. Otherwise +checkpointing *containers* with file locks is expected to fail. If file locks are not +used, this option is ignored.\ +The default is **false**. + #### **--ignore-rootfs** 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.\ @@ -119,14 +127,6 @@ restore. Defaults to not checkpointing *containers* with established TCP connections.\ The default is **false**. -#### **--file-locks** - -Checkpoint a *container* with file locks. If an application running in the container -is using file locks, this OPTION is required during checkpoint and restore. Otherwise -checkpointing *containers* with file locks is expected to fail. If file locks are not -used, this option is ignored.\ -The default is **false**. - #### **--with-previous** Check out the *container* with previous criu image files in pre-dump. It only works on `runc 1.0-rc3` or `higher`.\ diff --git a/docs/source/markdown/podman-container-clone.1.md b/docs/source/markdown/podman-container-clone.1.md index 52fa023f3..eaf330373 100644 --- a/docs/source/markdown/podman-container-clone.1.md +++ b/docs/source/markdown/podman-container-clone.1.md @@ -11,25 +11,6 @@ podman\-container\-clone - Creates a copy of an existing container ## OPTIONS -#### **--name** - -Set a custom name for the cloned container. The default if not specified is of the syntax: **<ORIGINAL_NAME>-clone** - -#### **--destroy** - -Remove the original container that we are cloning once used to mimic the configuration. - -#### **--cpus** - -Set a number of CPUs for the container that overrides the original containers CPU limits. If none are specified, the original container's Nano CPUs are used. - -This is shorthand -for **--cpu-period** and **--cpu-quota**, so only **--cpus** or either both the **--cpu-period** and **--cpu-quota** options can be set. - -#### **--cpuset-cpus** - -CPUs in which to allow execution (0-3, 0,1). If none are specified, the original container's CPUset is used. - #### **--cpu-period**=*limit* Set the CPU period for the Completely Fair Scheduler (CFS), which is a @@ -43,6 +24,43 @@ https://github.com/containers/podman/blob/master/troubleshooting.md#26-running-c If none is specified, the original container's cpu period is used +#### **--cpu-quota**=*limit* + +Limit the CPU Completely Fair Scheduler (CFS) quota. + +Limit the container's CPU usage. By default, containers run with the full +CPU resource. The limit is a number in microseconds. If a number is provided, +the container will be allowed to use that much CPU time until the CPU period +ends (controllable via **--cpu-period**). + +On some systems, changing the CPU limits may not be allowed for non-root +users. For more details, see +https://github.com/containers/podman/blob/master/troubleshooting.md#26-running-containers-with-cpu-limits-fails-with-a-permissions-error + +If none is specified, the original container's CPU quota are used. + +#### **--cpu-rt-period**=*microseconds* + +Limit the CPU real-time period in microseconds + +Limit the container's Real Time CPU usage. This option tells the kernel to restrict the container's Real Time CPU usage to the period specified. + +This option is not supported on cgroups V2 systems. + +If none is specified, the original container's CPU runtime period is used. + + +#### **--cpu-rt-runtime**=*microseconds* + +Limit the CPU real-time runtime in microseconds. + +Limit the containers Real Time CPU usage. This option tells the kernel to limit the amount of time in a given CPU period Real Time tasks may consume. Ex: +Period of 1,000,000us and Runtime of 950,000us means that this container could consume 95% of available CPU and leave the remaining 5% to normal priority tasks. + +The sum of all runtimes across containers cannot exceed the amount allotted to the parent cgroup. + +This option is not supported on cgroup V2 systems. + #### **--cpu-shares**=*shares* CPU shares (relative weight) @@ -82,6 +100,17 @@ PID container CPU CPU share If none are specified, the original container's CPU shares are used. +#### **--cpus** + +Set a number of CPUs for the container that overrides the original containers CPU limits. If none are specified, the original container's Nano CPUs are used. + +This is shorthand +for **--cpu-period** and **--cpu-quota**, so only **--cpus** or either both the **--cpu-period** and **--cpu-quota** options can be set. + +#### **--cpuset-cpus** + +CPUs in which to allow execution (0-3, 0,1). If none are specified, the original container's CPUset is used. + #### **--cpuset-mems**=*nodes* Memory nodes (MEMs) in which to allow execution (0-3, 0,1). Only effective on NUMA systems. @@ -92,42 +121,9 @@ two memory nodes. If none are specified, the original container's CPU memory nodes are used. -#### **--cpu-quota**=*limit* - -Limit the CPU Completely Fair Scheduler (CFS) quota. - -Limit the container's CPU usage. By default, containers run with the full -CPU resource. The limit is a number in microseconds. If a number is provided, -the container will be allowed to use that much CPU time until the CPU period -ends (controllable via **--cpu-period**). - -On some systems, changing the CPU limits may not be allowed for non-root -users. For more details, see -https://github.com/containers/podman/blob/master/troubleshooting.md#26-running-containers-with-cpu-limits-fails-with-a-permissions-error - -If none is specified, the original container's CPU quota are used. - -#### **--cpu-rt-period**=*microseconds* - -Limit the CPU real-time period in microseconds - -Limit the container's Real Time CPU usage. This option tells the kernel to restrict the container's Real Time CPU usage to the period specified. - -This option is not supported on cgroups V2 systems. - -If none is specified, the original container's CPU runtime period is used. - - -#### **--cpu-rt-runtime**=*microseconds* - -Limit the CPU real-time runtime in microseconds. - -Limit the containers Real Time CPU usage. This option tells the kernel to limit the amount of time in a given CPU period Real Time tasks may consume. Ex: -Period of 1,000,000us and Runtime of 950,000us means that this container could consume 95% of available CPU and leave the remaining 5% to normal priority tasks. - -The sum of all runtimes across containers cannot exceed the amount allotted to the parent cgroup. +#### **--destroy** -This option is not supported on cgroup V2 systems. +Remove the original container that we are cloning once used to mimic the configuration. #### **--memory**, **-m**=*limit* @@ -141,6 +137,16 @@ system's page size (the value would be very large, that's millions of trillions) If no memory limits are specified, the original container's will be used. +#### **--name** + +Set a custom name for the cloned container. The default if not specified is of the syntax: **<ORIGINAL_NAME>-clone** + +#### **--pod**=*name* + +Clone the container in an existing pod. It is helpful to move a container to an +existing pod. The container will join the pod shared namespaces, losing its configuration +that conflicts with the shared namespaces. + #### **--run** When set to true, this flag runs the newly created container after the diff --git a/docs/source/markdown/podman-container-restore.1.md b/docs/source/markdown/podman-container-restore.1.md index 4016eb1cb..5b1bf82c5 100644 --- a/docs/source/markdown/podman-container-restore.1.md +++ b/docs/source/markdown/podman-container-restore.1.md @@ -16,25 +16,14 @@ Restore all checkpointed *containers*.\ The default is **false**.\ *IMPORTANT: This OPTION does not need a container name or ID as input argument.* -#### **--keep**, **-k** +#### **--file-locks** -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 **--keep**, **-k** option the checkpoint will be consumed and cannot be used again.\ +Restore a *container* with file locks. This option is required to +restore file locks from a checkpoint image. If the checkpoint image +does not contain file locks, this option is ignored. Defaults to not +restoring file locks.\ The default is **false**. -#### **--latest**, **-l** - -Instead of providing the *container ID* or *name*, use the last created *container*. If other tools than Podman are used to run *containers* such as `CRI-O`, the last started *container* could be from either tool.\ -The default is **false**.\ -*IMPORTANT: This OPTION is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines. This OPTION does not need a container name or ID as input argument.* - #### **--ignore-rootfs** 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*.\ @@ -89,6 +78,25 @@ 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`. *IMPORTANT: This OPTION is not supported on the remote client, including Mac and Windows (excluding WSL2) machines.* +#### **--keep**, **-k** + +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 **--keep**, **-k** option the checkpoint will be consumed and cannot be used again.\ +The default is **false**. + +#### **--latest**, **-l** + +Instead of providing the *container ID* or *name*, use the last created *container*. If other tools than Podman are used to run *containers* such as `CRI-O`, the last started *container* could be from either tool.\ +The default is **false**.\ +*IMPORTANT: This OPTION is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines. This OPTION does not need a container name or ID as input argument.* + #### **--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 @@ -149,14 +157,6 @@ option is ignored. Defaults to not restoring *containers* with established TCP connections.\ The default is **false**. -#### **--file-locks** - -Restore a *container* with file locks. This option is required to -restore file locks from a checkpoint image. If the checkpoint image -does not contain file locks, this option is ignored. Defaults to not -restoring file locks.\ -The default is **false**. - ## EXAMPLE Restores the container "mywebserver". ``` diff --git a/docs/source/markdown/podman-container-runlabel.1.md b/docs/source/markdown/podman-container-runlabel.1.md index ac34b232c..40e5392ce 100644 --- a/docs/source/markdown/podman-container-runlabel.1.md +++ b/docs/source/markdown/podman-container-runlabel.1.md @@ -35,10 +35,6 @@ Path of the containers-auth.json(5) file. Default is ${XDG\_RUNTIME\_DIR}/contai 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` -#### **--display** - -Display the label's value of the image having populated its environment variables. The runlabel command will not execute if --display is specified. - #### **--cert-dir**=*path* Use certificates at *path* (\*.crt, \*.cert, \*.key) to connect to the registry. (Default: /etc/containers/certs.d) @@ -48,6 +44,10 @@ Please refer to containers-certs.d(5) for details. (This option is not available The [username[:password]] to use to authenticate with the registry if required. If one or both values are not supplied, a command line prompt will appear and the value can be entered. The password is entered without echo. +#### **--display** + +Display the label's value of the image having populated its environment variables. The runlabel command will not execute if --display is specified. + #### **--help**, **-h** Print usage statement diff --git a/docs/source/markdown/podman-create.1.md b/docs/source/markdown/podman-create.1.md index 506f575fe..a85ad9200 100644 --- a/docs/source/markdown/podman-create.1.md +++ b/docs/source/markdown/podman-create.1.md @@ -65,6 +65,7 @@ and specified with a _tag_. $ podman create oci-archive:/tmp/fedora echo hello ## OPTIONS + #### **--add-host**=*host* Add a custom host-to-IP mapping (host:ip) @@ -114,6 +115,14 @@ Add Linux capabilities Drop Linux capabilities +#### **--cgroup-conf**=*KEY=VALUE* + +When running on cgroup v2, specify the cgroup file to write to and its value. For example **--cgroup-conf=memory.high=1073741824** sets the memory.high limit to 1GB. + +#### **--cgroup-parent**=*path* + +Path to cgroups under which the cgroup for the container will be created. If the path is not absolute, the path is considered to be relative to the cgroups path of the init process. Cgroups will be created if they do not already exist. + #### **--cgroupns**=*mode* Set the cgroup namespace mode for the container. @@ -134,13 +143,11 @@ The *disabled* option will force the container to not create CGroups, and thus c The *no-conmon* option disables a new CGroup only for the conmon process. The *split* option splits the current cgroup in two sub-cgroups: one for conmon and one for the container payload. It is not possible to set *--cgroup-parent* with *split*. -#### **--cgroup-parent**=*path* - -Path to cgroups under which the cgroup for the container will be created. If the path is not absolute, the path is considered to be relative to the cgroups path of the init process. Cgroups will be created if they do not already exist. - -#### **--cgroup-conf**=*KEY=VALUE* +#### **--chrootdirs**=*path* -When running on cgroup v2, specify the cgroup file to write to and its value. For example **--cgroup-conf=memory.high=1073741824** sets the memory.high limit to 1GB. +Path to a directory inside the container that should be treated as a `chroot` directory. +Any Podman managed file (e.g., /etc/resolv.conf, /etc/hosts, etc/hostname) that is mounted into the root directory will be mounted into that location as well. +Multiple directories should be separated with a comma. #### **--cidfile**=*id* @@ -346,14 +353,14 @@ This option allows arbitrary environment variables that are available for the pr See [**Environment**](#environment) note below for precedence and examples. -#### **--env-host** - -Use host environment inside of the container. See **Environment** note below for precedence. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) - #### **--env-file**=*file* Read in a line delimited file of environment variables. See **Environment** note below for precedence. +#### **--env-host** + +Use host environment inside of the container. See **Environment** note below for precedence. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) + #### **--expose**=*port* Expose a port, or a range of ports (e.g. --expose=3300-3310) to set up port redirection @@ -406,6 +413,10 @@ The initialization time needed for a container to bootstrap. The value can be ex The maximum time allowed to complete the healthcheck before an interval is considered failed. Like start-period, the value can be expressed in a time format such as `1m22s`. The default value is `30s`. +#### **--help** + +Print usage statement + #### **--hostname**=*name*, **-h** Container host name @@ -417,10 +428,6 @@ Sets the container host name that is available inside the container. Can only be Add a user account to /etc/passwd from the host to the container. The Username or UID must exist on the host system. -#### **--help** - -Print usage statement - #### **--http-proxy** By default proxy environment variables are passed into the container if set @@ -761,6 +768,16 @@ Default is to create a private PID namespace for the container - `ns`: join the specified PID namespace - `private`: create a new namespace for the container (default) +#### **--pidfile**=*path* + +When the pidfile location is specified, the container process' PID will be written to the pidfile. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) +If the pidfile option is not specified, the container process' PID will be written to /run/containers/storage/${storage-driver}-containers/$CID/userdata/pidfile. + +After the container is started, the location for the pidfile can be discovered with the following `podman inspect` command: + + $ podman inspect --format '{{ .PidFile }}' $CID + /run/containers/storage/${storage-driver}-containers/$CID/userdata/pidfile + #### **--pids-limit**=*limit* Tune the container's pids limit. Set `-1` to have unlimited pids for the container. (default "4096" on systems that support PIDS cgroups). @@ -1020,15 +1037,20 @@ Run container in systemd mode. The default is *true*. The value *always* enforces the systemd mode is enforced without looking at the executable name. Otherwise, if set to true and the -command you are running inside the container is systemd, /usr/sbin/init, -/sbin/init or /usr/local/sbin/init. +command you are running inside the container is **systemd**, **/usr/sbin/init**, +**/sbin/init** or **/usr/local/sbin/init**. -If the command you are running inside of the container is systemd, -Podman will setup tmpfs mount points in the following directories: +Running the container in systemd mode causes the following changes: -/run, /run/lock, /tmp, /sys/fs/cgroup/systemd, /var/lib/journal - -It will also set the default stop signal to SIGRTMIN+3. +* Podman mounts tmpfs file systems on the following directories + * _/run_ + * _/run/lock_ + * _/tmp_ + * _/sys/fs/cgroup/systemd_ + * _/var/lib/journal_ +* Podman sets the default stop signal to **SIGRTMIN+3**. +* Podman sets **container_uuid** environment variable in the container to the +first 32 characters of the container id. This allows systemd to run in a confined container without any modifications. @@ -1077,23 +1099,6 @@ standard input. Set timezone in container. This flag takes area-based timezones, GMT time, as well as `local`, which sets the timezone in the container to match the host machine. See `/usr/share/zoneinfo/` for valid timezones. Remote connections use local containers.conf for defaults -#### **--umask**=*umask* - -Set the umask inside the container. Defaults to `0022`. -Remote connections use local containers.conf for defaults - -#### **--unsetenv**=*env* - -Unset default environment variables for the container. Default environment -variables include variables provided natively by Podman, environment variables -configured by the image, and environment variables from containers.conf. - -#### **--unsetenv-all**=*true|false* - -Unset all default environment variables for the container. Default environment -variables include variables provided natively by Podman, environment variables -configured by the image, and environment variables from containers.conf. - #### **--uidmap**=*container_uid*:*from_uid*:*amount* Run the container in a new user namespace using the supplied mapping. This @@ -1178,6 +1183,23 @@ Ulimit options You can pass `host` to copy the current configuration from the host. +#### **--umask**=*umask* + +Set the umask inside the container. Defaults to `0022`. +Remote connections use local containers.conf for defaults + +#### **--unsetenv**=*env* + +Unset default environment variables for the container. Default environment +variables include variables provided natively by Podman, environment variables +configured by the image, and environment variables from containers.conf. + +#### **--unsetenv-all**=*true|false* + +Unset all default environment variables for the container. Default environment +variables include variables provided natively by Podman, environment variables +configured by the image, and environment variables from containers.conf. + #### **--user**, **-u**=*user* Sets the username or UID used and optionally the groupname or GID for the specified command. @@ -1443,22 +1465,6 @@ The default working directory for running binaries within a container is the roo The image developer can set a different default with the WORKDIR instruction. The operator can override the working directory by using the **-w** option. -#### **--pidfile**=*path* - -When the pidfile location is specified, the container process' PID will be written to the pidfile. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) -If the pidfile option is not specified, the container process' PID will be written to /run/containers/storage/${storage-driver}-containers/$CID/userdata/pidfile. - -After the container is started, the location for the pidfile can be discovered with the following `podman inspect` command: - - $ podman inspect --format '{{ .PidFile }}' $CID - /run/containers/storage/${storage-driver}-containers/$CID/userdata/pidfile - -#### **--chrootdirs**=*path* - -Path to a directory inside the container that should be treated as a `chroot` directory. -Any Podman managed file (e.g., /etc/resolv.conf, /etc/hosts, etc/hostname) that is mounted into the root directory will be mounted into that location as well. -Multiple directories should be separated with a comma. - ## EXAMPLES ### Create a container using a local image diff --git a/docs/source/markdown/podman-events.1.md b/docs/source/markdown/podman-events.1.md index 7ca52e3e9..741aca3a5 100644 --- a/docs/source/markdown/podman-events.1.md +++ b/docs/source/markdown/podman-events.1.md @@ -70,15 +70,6 @@ The *volume* type will report the following statuses: ## OPTIONS -#### **--help** - -Print usage statement. - -#### **--format** - -Format the output to JSON Lines or using the given Go template. - - #### **--filter**=*filter* Filter events that are displayed. They must be in the format of "filter=value". The following @@ -93,6 +84,14 @@ filters are supported: In the case where an ID is used, the ID may be in its full or shortened form. +#### **--format** + +Format the output to JSON Lines or using the given Go template. + +#### **--help** + +Print usage statement. + #### **--no-trunc** Do not truncate the output (default *true*). diff --git a/docs/source/markdown/podman-export.1.md b/docs/source/markdown/podman-export.1.md index b2ad4e907..53d7e425e 100644 --- a/docs/source/markdown/podman-export.1.md +++ b/docs/source/markdown/podman-export.1.md @@ -24,14 +24,14 @@ Note: `:` is a restricted character and cannot be part of the file name. ## OPTIONS -#### **--output**, **-o** - -Write to a file, default is STDOUT - #### **--help**, **-h** Print usage statement +#### **--output**, **-o** + +Write to a file, default is STDOUT + ## EXAMPLES ``` diff --git a/docs/source/markdown/podman-generate-systemd.1.md b/docs/source/markdown/podman-generate-systemd.1.md index b2b5ee2ca..32d5d2bc4 100644 --- a/docs/source/markdown/podman-generate-systemd.1.md +++ b/docs/source/markdown/podman-generate-systemd.1.md @@ -16,6 +16,16 @@ _Note: If you use this command with the remote client, including Mac and Windows ## OPTIONS +#### **--after**=*dependency_name* + +Add the systemd unit after (`After=`) option, that ordering dependencies between the list of dependencies and this service. This option may be specified more than once. + +User-defined dependencies will be appended to the generated unit file, but any existing options such as needed or defined by default (e.g. `online.target`) will **not** be removed or overridden. + +#### **--container-prefix**=*prefix* + +Set the systemd unit name prefix for containers. The default is *container*. + #### **--files**, **-f** Generate files instead of printing to stdout. The generated files are named {container,pod}-{ID,name}.service and will be placed in the current working directory. @@ -40,13 +50,13 @@ Note that `--new` only works on containers and pods created directly via Podman Do not generate the header including meta data such as the Podman version and the timestamp. -#### **--start-timeout** =*value* +#### **--pod-prefix**=*prefix* -Override the default start timeout for the container with the given value in seconds. +Set the systemd unit name prefix for pods. The default is *pod*. -#### **--stop-timeout** =*value* +#### **--requires**=*dependency_name* -Override the default stop timeout for the container with the given value in seconds. +Set the systemd unit requires (`Requires=`) option. Similar to wants, but declares a stronger requirement dependency. #### **--restart-policy**=*policy* @@ -58,33 +68,17 @@ Set the systemd restart policy. The restart-policy must be one of: "no", "on-su Set the systemd service restartsec value. Configures the time to sleep before restarting a service (as configured with restart-policy). Takes a value in seconds. -#### **--container-prefix**=*prefix* - -Set the systemd unit name prefix for containers. The default is *container*. - -#### **--pod-prefix**=*prefix* - -Set the systemd unit name prefix for pods. The default is *pod*. - #### **--separator**=*separator* Set the systemd unit name separator between the name/id of a container/pod and the prefix. The default is *-*. -#### **--wants**=*dependency_name* - -Add the systemd unit wants (`Wants=`) option, that this service is (weak) dependent on. This option may be specified more than once. This option does not influence the order in which services are started or stopped. - -User-defined dependencies will be appended to the generated unit file, but any existing options such as needed or defined by default (e.g. `online.target`) will **not** be removed or overridden. - -#### **--after**=*dependency_name* - -Add the systemd unit after (`After=`) option, that ordering dependencies between the list of dependencies and this service. This option may be specified more than once. +#### **--start-timeout** =*value* -User-defined dependencies will be appended to the generated unit file, but any existing options such as needed or defined by default (e.g. `online.target`) will **not** be removed or overridden. +Override the default start timeout for the container with the given value in seconds. -#### **--requires**=*dependency_name* +#### **--stop-timeout** =*value* -Set the systemd unit requires (`Requires=`) option. Similar to wants, but declares a stronger requirement dependency. +Override the default stop timeout for the container with the given value in seconds. #### **--template** @@ -92,6 +86,12 @@ Add template specifiers to run multiple services from the systemd unit file. Note that if `--new` was not set to true, it is set to true by default. However, if `--new` is set to `false` explicitly the command will fail. +#### **--wants**=*dependency_name* + +Add the systemd unit wants (`Wants=`) option, that this service is (weak) dependent on. This option may be specified more than once. This option does not influence the order in which services are started or stopped. + +User-defined dependencies will be appended to the generated unit file, but any existing options such as needed or defined by default (e.g. `online.target`) will **not** be removed or overridden. + ## EXAMPLES ### Generate and print a systemd unit file for a container diff --git a/docs/source/markdown/podman-history.1.md b/docs/source/markdown/podman-history.1.md index 4ab2547ea..af35814c2 100644 --- a/docs/source/markdown/podman-history.1.md +++ b/docs/source/markdown/podman-history.1.md @@ -29,6 +29,15 @@ Valid placeholders for the Go template are listed below: ## OPTIONS +Print the numeric IDs only (default *false*). +#### **--format**=*format* + +Alter the output for a format like 'json' or a Go template. + +#### **--help**, **-h** + +Print usage statement + #### **--human**, **-H** Display sizes and dates in human readable format (default *true*). @@ -39,15 +48,6 @@ Do not truncate the output (default *false*). #### **--quiet**, **-q** -Print the numeric IDs only (default *false*). -#### **--format**=*format* - -Alter the output for a format like 'json' or a Go template. - -#### **--help**, **-h** - -Print usage statement - ## EXAMPLES ``` diff --git a/docs/source/markdown/podman-image-scp.1.md b/docs/source/markdown/podman-image-scp.1.md index e08d5b465..1d902da91 100644 --- a/docs/source/markdown/podman-image-scp.1.md +++ b/docs/source/markdown/podman-image-scp.1.md @@ -20,14 +20,14 @@ Note: `::` is used to specify the image name depending on if you are saving or l ## OPTIONS -#### **--quiet**, **-q** - -Suppress the output - #### **--help**, **-h** Print usage statement +#### **--quiet**, **-q** + +Suppress the output + ## EXAMPLES diff --git a/docs/source/markdown/podman-image-sign.1.md b/docs/source/markdown/podman-image-sign.1.md index 7e483a3b2..035e10743 100644 --- a/docs/source/markdown/podman-image-sign.1.md +++ b/docs/source/markdown/podman-image-sign.1.md @@ -15,10 +15,6 @@ By default, the signature will be written into `/var/lib/containers/sigstore` fo ## OPTIONS -#### **--help**, **-h** - -Print usage statement. - #### **--all**, **-a** Sign all the manifests of the multi-architecture image (default false). @@ -39,6 +35,10 @@ Please refer to containers-certs.d(5) for details. (This option is not available Store the signatures in the specified directory. Default: /var/lib/containers/sigstore +#### **--help**, **-h** + +Print usage statement. + #### **--sign-by**=*identity* Override the default identity of the signature. diff --git a/docs/source/markdown/podman-images.1.md b/docs/source/markdown/podman-images.1.md index f1d9d4816..f81ea5a20 100644 --- a/docs/source/markdown/podman-images.1.md +++ b/docs/source/markdown/podman-images.1.md @@ -73,14 +73,14 @@ Valid placeholders for the Go template are listed below: Display the history of image names. If an image gets re-tagged or untagged, then the image name history gets prepended (latest image first). This is especially useful when undoing a tag operation or an image does not contain any name because it has been untagged. -#### **--noheading**, **-n** - -Omit the table headings from the listing of images. - #### **--no-trunc** Do not truncate the output (default *false*). +#### **--noheading**, **-n** + +Omit the table headings from the listing of images. + #### **--quiet**, **-q** Lists only the image IDs. diff --git a/docs/source/markdown/podman-import.1.md b/docs/source/markdown/podman-import.1.md index 462e9eacf..bfe0291de 100644 --- a/docs/source/markdown/podman-import.1.md +++ b/docs/source/markdown/podman-import.1.md @@ -19,6 +19,10 @@ Note: `:` is a restricted character and cannot be part of the file name. ## OPTIONS +#### **--arch** + +Set architecture of the imported image. + #### **--change**=*instruction*, **-c** Apply the following possible instructions to the created image: @@ -26,21 +30,29 @@ Apply the following possible instructions to the created image: Can be set multiple times +#### **--help**, **-h** + +Print usage statement + #### **--message**, **-m**=*message* Set commit message for imported image +#### **--os** + +Set OS of the imported image. + #### **--quiet**, **-q** Shows progress on the import -**--verbose** +#### **--variant** -Print additional debugging information +Set variant of the imported image. -#### **--help**, **-h** +**--verbose** -Print usage statement +Print additional debugging information ## EXAMPLES diff --git a/docs/source/markdown/podman-inspect.1.md b/docs/source/markdown/podman-inspect.1.md index 9eafb7460..a67604ab5 100644 --- a/docs/source/markdown/podman-inspect.1.md +++ b/docs/source/markdown/podman-inspect.1.md @@ -22,11 +22,6 @@ For more inspection options, see also ## OPTIONS -#### **--type**, **-t**=*type* - -Return JSON for the specified type. Type can be 'container', 'image', 'volume', 'network', 'pod', or 'all' (default: all) -(Only meaningful when invoked as *podman inspect*) - #### **--format**, **-f**=*format* Format the output using the given Go template. @@ -43,6 +38,10 @@ This option can be used to inspect the latest pod created when used with --type In addition to normal output, display the total file size if the type is a container. +#### **--type**, **-t**=*type* + +Return JSON for the specified type. Type can be 'container', 'image', 'volume', 'network', 'pod', or 'all' (default: all) +(Only meaningful when invoked as *podman inspect*) ## EXAMPLE diff --git a/docs/source/markdown/podman-load.1.md b/docs/source/markdown/podman-load.1.md index 30e8e82ea..ad32df854 100644 --- a/docs/source/markdown/podman-load.1.md +++ b/docs/source/markdown/podman-load.1.md @@ -26,6 +26,10 @@ Note: `:` is a restricted character and cannot be part of the file name. ## OPTIONS +#### **--help**, **-h** + +Print usage statement + #### **--input**, **-i**=*input* Load the specified input file instead of from stdin. The file can be on the local file system or on a server (e.g., https://server.com/archive.tar) @@ -38,10 +42,6 @@ NOTE: Use the environment variable `TMPDIR` to change the temporary storage loca Suppress the progress output -#### **--help**, **-h** - -Print usage statement - ## EXAMPLES ``` diff --git a/docs/source/markdown/podman-logout.1.md b/docs/source/markdown/podman-logout.1.md index e34c80e95..96ac98f35 100644 --- a/docs/source/markdown/podman-logout.1.md +++ b/docs/source/markdown/podman-logout.1.md @@ -21,6 +21,10 @@ All the cached credentials can be removed by setting the **all** flag. ## OPTIONS +#### **--all**, **-a** + +Remove the cached credentials for all registries in the auth file + #### **--authfile**=*path* Path of the authentication file. Default is ${XDG\_RUNTIME\_DIR}/containers/auth.json. @@ -28,10 +32,6 @@ 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` -#### **--all**, **-a** - -Remove the cached credentials for all registries in the auth file - #### **--help**, **-h** Print usage statement diff --git a/docs/source/markdown/podman-logs.1.md b/docs/source/markdown/podman-logs.1.md index f62a66c81..e12042030 100644 --- a/docs/source/markdown/podman-logs.1.md +++ b/docs/source/markdown/podman-logs.1.md @@ -39,14 +39,6 @@ strings (e.g. 10m, 1h30m) computed relative to the client machine's time. Suppor time stamps include RFC3339Nano, RFC3339, 2006-01-02T15:04:05, 2006-01-02T15:04:05.999999999, 2006-01-02Z07:00, and 2006-01-02. -#### **--until**=*TIMESTAMP* - -Show logs until TIMESTAMP. The --until option can be Unix timestamps, date formatted timestamps, or Go duration -strings (e.g. 10m, 1h30m) computed relative to the client machine's time. Supported formats for date formatted -time stamps include RFC3339Nano, RFC3339, 2006-01-02T15:04:05, 2006-01-02T15:04:05.999999999, 2006-01-02Z07:00, -and 2006-01-02. - - #### **--tail**=*LINES* Output the specified number of LINES at the end of the logs. LINES must be an integer. Defaults to -1, @@ -56,6 +48,13 @@ which prints all lines Show timestamps in the log outputs. The default is false +#### **--until**=*TIMESTAMP* + +Show logs until TIMESTAMP. The --until option can be Unix timestamps, date formatted timestamps, or Go duration +strings (e.g. 10m, 1h30m) computed relative to the client machine's time. Supported formats for date formatted +time stamps include RFC3339Nano, RFC3339, 2006-01-02T15:04:05, 2006-01-02T15:04:05.999999999, 2006-01-02Z07:00, +and 2006-01-02. + ## EXAMPLE To view a container's logs: diff --git a/docs/source/markdown/podman-machine-init.1.md b/docs/source/markdown/podman-machine-init.1.md index 36db5b1cd..ac258eaae 100644 --- a/docs/source/markdown/podman-machine-init.1.md +++ b/docs/source/markdown/podman-machine-init.1.md @@ -32,6 +32,10 @@ Number of CPUs. Size of the disk for the guest VM in GB. +#### **--help** + +Print usage statement. + #### **--ignition-path** Fully qualified path of the ignition file. @@ -83,10 +87,6 @@ so mounts must be created under the /mnt directory. Driver to use for mounting volumes from the host, such as `virtfs`. -#### **--help** - -Print usage statement. - ## EXAMPLES ``` diff --git a/docs/source/markdown/podman-machine-rm.1.md b/docs/source/markdown/podman-machine-rm.1.md index 4eea1d2e4..4a2c59173 100644 --- a/docs/source/markdown/podman-machine-rm.1.md +++ b/docs/source/markdown/podman-machine-rm.1.md @@ -19,21 +19,21 @@ is used. ## OPTIONS -#### **--help** +#### **--force**, **-f** -Print usage statement. +Stop and delete without confirmation. -#### **--force**, **-f** +#### **--help** -Stop and delete without confirmation +Print usage statement. #### **--save-ignition** -Do not delete the generated ignition file +Do not delete the generated ignition file. #### **--save-image** -Do not delete the VM image +Do not delete the VM image. #### **--save-keys** @@ -42,7 +42,7 @@ deleted. ## EXAMPLES -Remove a VM named "test1" +Remove a VM named "test1": ``` $ podman machine rm test1 diff --git a/docs/source/markdown/podman-machine-set.1.md b/docs/source/markdown/podman-machine-set.1.md index e69779564..a4918eacf 100644 --- a/docs/source/markdown/podman-machine-set.1.md +++ b/docs/source/markdown/podman-machine-set.1.md @@ -15,6 +15,10 @@ subset can be changed after machine initialization. ## OPTIONS +#### **--help** + +Print usage statement. + #### **--rootful**=*true|false* Whether this machine should prefer rootful (`true`) or rootless (`false`) @@ -22,11 +26,9 @@ container execution. This option will also update the current podman remote connection default if it is currently pointing at the specified machine name (or `podman-machine-default` if no name is specified). -API forwarding, if available, will follow this setting. - -#### **--help** - -Print usage statement. +Unlike [**podman system connection default**](podman-system-connection-default.1.md) +this option will also make the API socket, if available, forward to the rootful/rootless +socket in the VM. ## EXAMPLES diff --git a/docs/source/markdown/podman-manifest-push.1.md b/docs/source/markdown/podman-manifest-push.1.md index a0011cea8..22e8cae9a 100644 --- a/docs/source/markdown/podman-manifest-push.1.md +++ b/docs/source/markdown/podman-manifest-push.1.md @@ -50,14 +50,14 @@ Manifest list type (oci or v2s2) to use when pushing the list (default is oci). When writing the manifest, suppress progress output -#### **--rm** - -Delete the manifest list or image index from local storage if pushing succeeds. - #### **--remove-signatures** Don't copy signatures when pushing images. +#### **--rm** + +Delete the manifest list or image index from local storage if pushing succeeds. + #### **--sign-by**=*fingerprint* Sign the pushed images using the GPG key that matches the specified fingerprint. diff --git a/docs/source/markdown/podman-network-create.1.md b/docs/source/markdown/podman-network-create.1.md index 5a3224501..479c36318 100644 --- a/docs/source/markdown/podman-network-create.1.md +++ b/docs/source/markdown/podman-network-create.1.md @@ -32,21 +32,6 @@ Special considerations for the *netavark* backend: - The `macvlan` driver requires the `--subnet` option, DHCP is currently not supported. - The `ipvlan` driver is not currently supported. -#### **--opt**=*option*, **-o** - -Set driver specific options. - -All drivers accept the `mtu` option. The `mtu` option sets the Maximum Transmission Unit (MTU) and takes an integer value. - -Additionally the `bridge` driver supports the following option: -- `vlan`: This option assign VLAN tag and enables vlan\_filtering. Defaults to none. - -The `macvlan` and `ipvlan` driver support the following options: -- `parent`: The host device which should be used for the macvlan interface. Defaults to the default route interface. -- `mode`: This option sets the specified ip/macvlan mode on the interface. - - Supported values for `macvlan` are `bridge`, `private`, `vepa`, `passthru`. Defaults to `bridge`. - - Supported values for `ipvlan` are `l2`, `l3`, `l3s`. Defaults to `l2`. - #### **--gateway** Define a gateway for the subnet. If you want to provide a gateway address, you must also provide a @@ -64,20 +49,35 @@ Allocate container IP from a range. The range must be a complete subnet and in must be used with a *subnet* option. Can be specified multiple times. The argument order of the **--subnet**, **--gateway** and **--ip-range** options must match. +#### **--ipv6** + +Enable IPv6 (Dual Stack) networking. If not subnets are given it will allocate a ipv4 and ipv6 subnet. + #### **--label** Set metadata for a network (e.g., --label mykey=value). +#### **--opt**=*option*, **-o** + +Set driver specific options. + +All drivers accept the `mtu` option. The `mtu` option sets the Maximum Transmission Unit (MTU) and takes an integer value. + +Additionally the `bridge` driver supports the following option: +- `vlan`: This option assign VLAN tag and enables vlan\_filtering. Defaults to none. + +The `macvlan` and `ipvlan` driver support the following options: +- `parent`: The host device which should be used for the macvlan interface. Defaults to the default route interface. +- `mode`: This option sets the specified ip/macvlan mode on the interface. + - Supported values for `macvlan` are `bridge`, `private`, `vepa`, `passthru`. Defaults to `bridge`. + - Supported values for `ipvlan` are `l2`, `l3`, `l3s`. Defaults to `l2`. + #### **--subnet** The subnet in CIDR notation. Can be specified multiple times to allocate more than one subnet for this network. The argument order of the **--subnet**, **--gateway** and **--ip-range** options must match. This is useful to set a static ipv4 and ipv6 subnet. -#### **--ipv6** - -Enable IPv6 (Dual Stack) networking. If not subnets are given it will allocate a ipv4 and ipv6 subnet. - ## EXAMPLE Create a network with no options. diff --git a/docs/source/markdown/podman-network-ls.1.md b/docs/source/markdown/podman-network-ls.1.md index d5bdb6a39..b341083f9 100644 --- a/docs/source/markdown/podman-network-ls.1.md +++ b/docs/source/markdown/podman-network-ls.1.md @@ -54,14 +54,14 @@ Valid placeholders for the Go template are listed below: | .NetworkInterface | Name of the network interface on the host | | .Subnets | List of subnets on this network | -#### **--noheading** - -Omit the table headings from the listing of networks. - #### **--no-trunc** Do not truncate the network ID. +#### **--noheading** + +Omit the table headings from the listing of networks. + #### **--quiet**, **-q** The `quiet` option will restrict the output to only the network names. diff --git a/docs/source/markdown/podman-network-prune.1.md b/docs/source/markdown/podman-network-prune.1.md index a1dc5d85c..2c8cf13db 100644 --- a/docs/source/markdown/podman-network-prune.1.md +++ b/docs/source/markdown/podman-network-prune.1.md @@ -12,9 +12,6 @@ has no containers connected or configured to connect to it. It will not remove the so-called default network which goes by the name of *podman*. ## OPTIONS -#### **--force**, **-f** - -Do not prompt for confirmation #### **--filter** @@ -33,6 +30,10 @@ The `label` *filter* accepts two formats. One is the `label`=*key* or `label`=*k 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. +#### **--force**, **-f** + +Do not prompt for confirmation + ## EXAMPLE Prune networks diff --git a/docs/source/markdown/podman-play-kube.1.md b/docs/source/markdown/podman-play-kube.1.md index 310bade34..ad3bd421d 100644 --- a/docs/source/markdown/podman-play-kube.1.md +++ b/docs/source/markdown/podman-play-kube.1.md @@ -148,6 +148,10 @@ value can be entered. The password is entered without echo. Tears down the pods that were created by a previous run of `play kube`. The pods are stopped and then removed. Any volumes created are left intact. +#### **--help**, **-h** + +Print usage statement + #### **--ip**=*IP address* Assign a static ip address to the pod. This option can be specified several times when play kube creates more than one pod. @@ -236,10 +240,6 @@ 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** - -Print usage statement - ## EXAMPLES Recreate the pod and containers as described in a file called `demo.yml` diff --git a/docs/source/markdown/podman-pod-create.1.md b/docs/source/markdown/podman-pod-create.1.md index 8088e1d62..2ae4453c9 100644 --- a/docs/source/markdown/podman-pod-create.1.md +++ b/docs/source/markdown/podman-pod-create.1.md @@ -75,21 +75,6 @@ Set custom DNS search domains in the /etc/resolv.conf file that will be shared b GID map for the user namespace. Using this flag will run the container with user namespace enabled. It conflicts with the `--userns` and `--subgidname` flags. -#### **--uidmap**=*container_uid*:*from_uid*:*amount* - -Run the container in a new user namespace using the supplied mapping. This -option conflicts with the **--userns** and **--subuidname** options. This -option provides a way to map host UIDs to container UIDs. It can be passed -several times to map different ranges. - -#### **--subgidname**=*name* - -Name for GID map from the `/etc/subgid` file. Using this flag will run the container with user namespace enabled. This flag conflicts with `--userns` and `--gidmap`. - -#### **--subuidname**=*name* - -Name for UID map from the `/etc/subuid` file. Using this flag will run the container with user namespace enabled. This flag conflicts with `--userns` and `--uidmap`. - #### **--help**, **-h** Print usage statement. @@ -102,14 +87,14 @@ Set a hostname to the pod Create an infra container and associate it with the pod. An infra container is a lightweight container used to coordinate the shared kernel namespace of a pod. Default: true. -#### **--infra-conmon-pidfile**=*file* - -Write the pid of the infra container's **conmon** process to a file. As **conmon** runs in a separate process than Podman, this is necessary when using systemd to manage Podman containers and pods. - #### **--infra-command**=*command* The command that will be run to start the infra container. Default: "/pause". +#### **--infra-conmon-pidfile**=*file* + +Write the pid of the infra container's **conmon** process to a file. As **conmon** runs in a separate process than Podman, this is necessary when using systemd to manage Podman containers and pods. + #### **--infra-image**=*image* The custom image that will be used for the infra container. Unless specified, Podman builds a custom local image which does not require pulling down an image. @@ -282,6 +267,14 @@ This boolean determines whether or not all containers entering the pod will use Note: This options conflict with **--share=cgroup** since that would set the pod as the cgroup parent but enter the container into the same cgroupNS as the infra container. +#### **--subgidname**=*name* + +Name for GID map from the `/etc/subgid` file. Using this flag will run the container with user namespace enabled. This flag conflicts with `--userns` and `--gidmap`. + +#### **--subuidname**=*name* + +Name for UID map from the `/etc/subuid` file. Using this flag will run the container with user namespace enabled. This flag conflicts with `--userns` and `--uidmap`. + #### **--sysctl**=_name_=_value_ Configure namespace kernel parameters for all containers in the pod. @@ -304,6 +297,13 @@ For the network namespace, only sysctls beginning with net.\* are allowed. Note: if the network namespace is not shared within the pod, these sysctls are not allowed. +#### **--uidmap**=*container_uid*:*from_uid*:*amount* + +Run the container in a new user namespace using the supplied mapping. This +option conflicts with the **--userns** and **--subuidname** options. This +option provides a way to map host UIDs to container UIDs. It can be passed +several times to map different ranges. + #### **--userns**=*mode* Set the user namespace mode for all the containers in a pod. It defaults to the **PODMAN_USERNS** environment variable. An empty value ("") means user namespaces are disabled. diff --git a/docs/source/markdown/podman-pod-inspect.1.md b/docs/source/markdown/podman-pod-inspect.1.md index 75b422306..3105ebaab 100644 --- a/docs/source/markdown/podman-pod-inspect.1.md +++ b/docs/source/markdown/podman-pod-inspect.1.md @@ -11,10 +11,6 @@ Displays configuration and state information about a given pod. It also display that belong to the pod. ## OPTIONS -#### **--latest**, **-l** - -Instead of providing the pod name or ID, use the last created pod. If you use methods other than Podman -to run pods such as CRI-O, the last started pod could be from either of those methods. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) #### **--format**=*format*, **-f** @@ -39,6 +35,11 @@ Valid placeholders for the Go template are listed below: | .NumContainers | Number of containers in the pod | | .Containers | Pod containers | +#### **--latest**, **-l** + +Instead of providing the pod name or ID, use the last created pod. If you use methods other than Podman +to run pods such as CRI-O, the last started pod could be from either of those methods. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) + ## EXAMPLE ``` # podman pod inspect foobar diff --git a/docs/source/markdown/podman-pod-logs.1.md b/docs/source/markdown/podman-pod-logs.1.md index 880853000..5ef667504 100644 --- a/docs/source/markdown/podman-pod-logs.1.md +++ b/docs/source/markdown/podman-pod-logs.1.md @@ -39,14 +39,6 @@ strings (e.g. 10m, 1h30m) computed relative to the client machine's time. Suppor time stamps include RFC3339Nano, RFC3339, 2006-01-02T15:04:05, 2006-01-02T15:04:05.999999999, 2006-01-02Z07:00, and 2006-01-02. -#### **--until**=*TIMESTAMP* - -Show logs until TIMESTAMP. The --until option can be Unix timestamps, date formatted timestamps, or Go duration -strings (e.g. 10m, 1h30m) computed relative to the client machine's time. Supported formats for date formatted -time stamps include RFC3339Nano, RFC3339, 2006-01-02T15:04:05, 2006-01-02T15:04:05.999999999, 2006-01-02Z07:00, -and 2006-01-02. - - #### **--tail**=*LINES* Output the specified number of LINES at the end of the logs. LINES must be an integer. Defaults to -1, @@ -56,6 +48,13 @@ which prints all lines Show timestamps in the log outputs. The default is false +#### **--until**=*TIMESTAMP* + +Show logs until TIMESTAMP. The --until option can be Unix timestamps, date formatted timestamps, or Go duration +strings (e.g. 10m, 1h30m) computed relative to the client machine's time. Supported formats for date formatted +time stamps include RFC3339Nano, RFC3339, 2006-01-02T15:04:05, 2006-01-02T15:04:05.999999999, 2006-01-02Z07:00, +and 2006-01-02. + ## EXAMPLE To view a pod's logs: diff --git a/docs/source/markdown/podman-pod-ps.1.md b/docs/source/markdown/podman-pod-ps.1.md index 8a9c3f7cc..34f49173a 100644 --- a/docs/source/markdown/podman-pod-ps.1.md +++ b/docs/source/markdown/podman-pod-ps.1.md @@ -28,37 +28,48 @@ By default it lists: ## OPTIONS -#### **--ctr-names** - -Display the container names - #### **--ctr-ids** Display the container IDs +#### **--ctr-names** + +Display the container names + #### **--ctr-status** Display the container statuses -#### **--latest**, **-l** +#### **--filter**, **-f**=*filter* -Show the latest pod created (all states) (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) +Provide filter values. -#### **--noheading** +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*. -Omit the table headings from the listing of pods. +Supported filters: -#### **--no-trunc** +| Filter | Description | +| ---------- | -------------------------------------------------------------------------------------------------- | +| *ctr-ids* | Filter by container ID within the pod. | +| *ctr-names* | Filter by container name within the pod. | +| *ctr-number*| Filter by number of containers in the pod. | +| *ctr-status*| Filter by container status within the pod. | +| *id* | Filter by pod ID. | +| *label* | Filter by container with (or without, in the case of label!=[...] is used) the specified labels. | +| *name* | Filter by pod name. | +| *network* | Filter by network name or full ID of network. | +| *status* | Filter by pod status. | +| *until* | Filter by pods created before given timestamp. | -Do not truncate the output (default *false*). +The `ctr-ids`, `ctr-names`, `id`, `name` filters accept `regex` format. -#### **--ns** +The `ctr-status` filter accepts values: `created`, `running`, `paused`, `stopped`, `exited`, `unknown`. -Display namespace information of the pod +The `label` *filter* accepts two formats. One is the `label`=*key* or `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. -#### **--quiet**, **-q** +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. -Print the numeric IDs of the pods only +The `status` filter accepts values: `stopped`, `running`, `paused`, `exited`, `dead`, `created`, `degraded`. #### **--format**=*format* @@ -78,47 +89,35 @@ Valid placeholders for the Go template are listed below: | .InfraID | Pod infra container ID | | .Networks | Show all networks connected to the infra container | -#### **--sort** - -Sort by created, ID, name, status, or number of containers +#### **--help**, **-h** -Default: created +Print usage statement -#### **--filter**, **-f**=*filter* +#### **--latest**, **-l** -Provide filter values. +Show the latest pod created (all states) (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) -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*. +#### **--no-trunc** -Supported filters: +Do not truncate the output (default *false*). -| Filter | Description | -| ---------- | -------------------------------------------------------------------------------------------------- | -| *ctr-ids* | Filter by container ID within the pod. | -| *ctr-names* | Filter by container name within the pod. | -| *ctr-number*| Filter by number of containers in the pod. | -| *ctr-status*| Filter by container status within the pod. | -| *id* | Filter by pod ID. | -| *label* | Filter by container with (or without, in the case of label!=[...] is used) the specified labels. | -| *name* | Filter by pod name. | -| *network* | Filter by network name or full ID of network. | -| *status* | Filter by pod status. | -| *until* | Filter by pods created before given timestamp. | +#### **--noheading** -The `ctr-ids`, `ctr-names`, `id`, `name` filters accept `regex` format. +Omit the table headings from the listing of pods. -The `ctr-status` filter accepts values: `created`, `running`, `paused`, `stopped`, `exited`, `unknown`. +#### **--ns** -The `label` *filter* accepts two formats. One is the `label`=*key* or `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. +Display namespace information of the pod -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. +#### **--quiet**, **-q** -The `status` filter accepts values: `stopped`, `running`, `paused`, `exited`, `dead`, `created`, `degraded`. +Print the numeric IDs of the pods only +#### **--sort** -#### **--help**, **-h** +Sort by created, ID, name, status, or number of containers -Print usage statement +Default: created ## EXAMPLES diff --git a/docs/source/markdown/podman-pod-rm.1.md b/docs/source/markdown/podman-pod-rm.1.md index ed33c5e57..75a44c6d4 100644 --- a/docs/source/markdown/podman-pod-rm.1.md +++ b/docs/source/markdown/podman-pod-rm.1.md @@ -15,6 +15,10 @@ podman\-pod\-rm - Remove one or more stopped pods and containers Remove all pods. Can be used in conjunction with \-f as well. +#### **--force**, **-f** + +Stop running containers and delete all stopped containers before removal of pod. + #### **--ignore**, **-i** Ignore errors when specified pods are not in the container store. A user might @@ -25,10 +29,6 @@ ExecStop directive of a systemd service referencing that pod. Instead of providing the pod name or ID, remove the last created pod. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) -#### **--force**, **-f** - -Stop running containers and delete all stopped containers before removal of pod. - #### **--pod-id-file** Read pod ID from the specified file and remove the pod. Can be specified multiple times. diff --git a/docs/source/markdown/podman-pod-stats.1.md b/docs/source/markdown/podman-pod-stats.1.md index 460571add..389540fdf 100644 --- a/docs/source/markdown/podman-pod-stats.1.md +++ b/docs/source/markdown/podman-pod-stats.1.md @@ -15,18 +15,6 @@ Display a live stream of containers in one or more pods resource usage statistic Show all containers. Only running containers are shown by default -#### **--latest**, **-l** - -Instead of providing the pod name or ID, use the last created pod. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) - -#### **--no-reset** - -Do not clear the terminal/screen in between reporting intervals - -#### **--no-stream** - -Disable streaming pod stats and only pull the first result, default setting is false - #### **--format**=*template* Pretty-print container statistics to JSON or using a Go template @@ -47,6 +35,19 @@ Valid placeholders for the Go template are listed below: | .PIDS | Number of PIDs | When using a GO template, you may precede the format with `table` to print headers. + +#### **--latest**, **-l** + +Instead of providing the pod name or ID, use the last created pod. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) + +#### **--no-reset** + +Do not clear the terminal/screen in between reporting intervals + +#### **--no-stream** + +Disable streaming pod stats and only pull the first result, default setting is false + ## EXAMPLE ``` diff --git a/docs/source/markdown/podman-pod-stop.1.md b/docs/source/markdown/podman-pod-stop.1.md index 13d86d1db..bded0ba7d 100644 --- a/docs/source/markdown/podman-pod-stop.1.md +++ b/docs/source/markdown/podman-pod-stop.1.md @@ -25,14 +25,14 @@ ExecStop directive of a systemd service referencing that pod. Instead of providing the pod name or ID, stop the last created pod. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) -#### **--time**, **-t**=*seconds* - -Seconds to wait before forcibly stopping the containers in the pod. - #### **--pod-id-file** Read pod ID from the specified file and stop the pod. Can be specified multiple times. +#### **--time**, **-t**=*seconds* + +Seconds to wait before forcibly stopping the containers in the pod. + ## EXAMPLE Stop a pod called *mywebserverpod* diff --git a/docs/source/markdown/podman-ps.1.md b/docs/source/markdown/podman-ps.1.md index 5b142d283..6e2a8616c 100644 --- a/docs/source/markdown/podman-ps.1.md +++ b/docs/source/markdown/podman-ps.1.md @@ -100,14 +100,14 @@ Show the latest container created (all states) (This option is not available wit Display namespace information -#### **--noheading** - -Omit the table headings from the listing of containers. - #### **--no-trunc** Do not truncate the output (default *false*). +#### **--noheading** + +Omit the table headings from the listing of containers. + #### **--pod**, **-p** Display the pods the containers are associated with @@ -116,15 +116,15 @@ Display the pods the containers are associated with Print the numeric IDs of the containers only +#### **--size**, **-s** + +Display the total file size + #### **--sort**=*created* Sort by command, created, id, image, names, runningfor, size, or status", Note: Choosing size will sort by size of rootFs, not alphabetically like the rest of the options -#### **--size**, **-s** - -Display the total file size - #### **--sync** Force a sync of container state with the OCI runtime. diff --git a/docs/source/markdown/podman-push.1.md b/docs/source/markdown/podman-push.1.md index c71eecfd2..74555c11b 100644 --- a/docs/source/markdown/podman-push.1.md +++ b/docs/source/markdown/podman-push.1.md @@ -55,12 +55,6 @@ If the authorization state is not found there, $HOME/.docker/config.json is chec 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` -#### **--creds**=*[username[:password]]* - -The [username[:password]] to use to authenticate with the registry if required. -If one or both values are not supplied, a command line prompt will appear and the -value can be entered. The password is entered without echo. - #### **--cert-dir**=*path* Use certificates at *path* (\*.crt, \*.cert, \*.key) to connect to the registry. (Default: /etc/containers/certs.d) @@ -75,6 +69,12 @@ Note: This flag can only be set when using the **dir** transport Specifies the compression format to use. Supported values are: `gzip`, `zstd` and `zstd:chunked`. The default is `gzip`. +#### **--creds**=*[username[:password]]* + +The [username[:password]] to use to authenticate with the registry if required. +If one or both values are not supplied, a command line prompt will appear and the +value can be entered. The password is entered without echo. + #### **--digestfile** *Digestfile* After copying the image, write the digest of the resulting image to the file. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) diff --git a/docs/source/markdown/podman-rm.1.md b/docs/source/markdown/podman-rm.1.md index 23944270c..1fac3aa34 100644 --- a/docs/source/markdown/podman-rm.1.md +++ b/docs/source/markdown/podman-rm.1.md @@ -18,14 +18,14 @@ Running or unusable containers will not be removed without the **-f** option. Remove all containers. Can be used in conjunction with **-f** as well. -#### **--depend** - -Remove selected container and recursively remove all containers that depend on it. - #### **--cidfile** Read container ID from the specified file and remove the container. Can be specified multiple times. +#### **--depend** + +Remove selected container and recursively remove all containers that depend on it. + #### **--force**, **-f** Force the removal of running and paused containers. Forcing a container removal also diff --git a/docs/source/markdown/podman-rmi.1.md b/docs/source/markdown/podman-rmi.1.md index 5fe0efa18..8d0e5e500 100644 --- a/docs/source/markdown/podman-rmi.1.md +++ b/docs/source/markdown/podman-rmi.1.md @@ -24,6 +24,10 @@ Remove all images in the local storage. This option will cause podman to remove all containers that are using the image before removing the image from the system. +#### **--ignore**, **-i** + +If a specified image does not exist in the local storage, ignore it and do not throw an error. + Remove an image by its short ID ``` @@ -43,6 +47,16 @@ Remove all images and containers. ``` $ podman rmi -a -f ``` + +Remove an absent image with and without the `--ignore` flag. +``` +$ podman rmi --ignore nothing +$ podman rmi nothing +Error: nothing: image not known + +``` + + ## Exit Status **0** All specified images removed diff --git a/docs/source/markdown/podman-run.1.md b/docs/source/markdown/podman-run.1.md index 7fa7bda30..616635c69 100644 --- a/docs/source/markdown/podman-run.1.md +++ b/docs/source/markdown/podman-run.1.md @@ -130,6 +130,14 @@ Add Linux capabilities. Drop Linux capabilities. +#### **--cgroup-conf**=*KEY=VALUE* + +When running on cgroup v2, specify the cgroup file to write to and its value. For example **--cgroup-conf=memory.high=1073741824** sets the memory.high limit to 1GB. + +#### **--cgroup-parent**=*path* + +Path to cgroups under which the cgroup for the container will be created. If the path is not absolute, the path is considered to be relative to the cgroups path of the init process. Cgroups will be created if they do not already exist. + #### **--cgroupns**=*mode* Set the cgroup namespace mode for the container. @@ -152,13 +160,11 @@ The **disabled** option will force the container to not create CGroups, and thus The **no-conmon** option disables a new CGroup only for the **conmon** process. The **split** option splits the current CGroup in two sub-cgroups: one for conmon and one for the container payload. It is not possible to set **--cgroup-parent** with **split**. -#### **--cgroup-parent**=*path* - -Path to cgroups under which the cgroup for the container will be created. If the path is not absolute, the path is considered to be relative to the cgroups path of the init process. Cgroups will be created if they do not already exist. - -#### **--cgroup-conf**=*KEY=VALUE* +#### **--chrootdirs**=*path* -When running on cgroup v2, specify the cgroup file to write to and its value. For example **--cgroup-conf=memory.high=1073741824** sets the memory.high limit to 1GB. +Path to a directory inside the container that should be treated as a `chroot` directory. +Any Podman managed file (e.g., /etc/resolv.conf, /etc/hosts, etc/hostname) that is mounted into the root directory will be mounted into that location as well. +Multiple directories should be separated with a comma. #### **--cidfile**=*file* @@ -381,14 +387,14 @@ This option allows arbitrary environment variables that are available for the pr See [**Environment**](#environment) note below for precedence and examples. -#### **--env-host** - -Use host environment inside of the container. See **Environment** note below for precedence. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) - #### **--env-file**=*file* Read in a line delimited file of environment variables. See **Environment** note below for precedence. +#### **--env-host** + +Use host environment inside of the container. See **Environment** note below for precedence. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) + #### **--expose**=*port* Expose a port, or a range of ports (e.g. **--expose=3300-3310**) to set up port redirection @@ -448,11 +454,6 @@ The initialization time needed for a container to bootstrap. The value can be ex The maximum time allowed to complete the healthcheck before an interval is considered failed. Like start-period, the value can be expressed in a time format such as **1m22s**. The default value is **30s**. -#### **--hostuser**=*name* - -Add a user account to /etc/passwd from the host to the container. The Username -or UID must exist on the host system. - #### **--help** Print usage statement @@ -463,6 +464,11 @@ Container host name Sets the container host name that is available inside the container. Can only be used with a private UTS namespace `--uts=private` (default). If `--pod` is specified and the pod shares the UTS namespace (default) the pod's hostname will be used. +#### **--hostuser**=*name* + +Add a user account to /etc/passwd from the host to the container. The Username +or UID must exist on the host system. + #### **--http-proxy** By default proxy environment variables are passed into the container if set @@ -795,6 +801,16 @@ The default is to create a private PID namespace for the container. - **private**: create a new namespace for the container (default) - **ns:**_path_: join the specified PID namespace. +#### **--pidfile**=*path* + +When the pidfile location is specified, the container process' PID will be written to the pidfile. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) +If the pidfile option is not specified, the container process' PID will be written to /run/containers/storage/${storage-driver}-containers/$CID/userdata/pidfile. + +After the container is started, the location for the pidfile can be discovered with the following `podman inspect` command: + + $ podman inspect --format '{{ .PidFile }}' $CID + /run/containers/storage/${storage-driver}-containers/$CID/userdata/pidfile + #### **--pids-limit**=*limit* Tune the container's pids limit. Set to **-1** to have unlimited pids for the container. The default is **4096** on systems that support "pids" cgroup controller. @@ -1082,20 +1098,21 @@ Note: if you use the **--network=host** option, these sysctls will not be allowe Run container in systemd mode. The default is **true**. The value *always* enforces the systemd mode is enforced without -looking at the executable name. Otherwise, if set to **true** and the -command you are running inside the container is systemd, _/usr/sbin/init_, -_/sbin/init_ or _/usr/local/sbin/init_. - -If the command you are running inside of the container is systemd -Podman will setup tmpfs mount points in the following directories: - -- _/run_ -- _/run/lock_ -- _/tmp_ -- _/sys/fs/cgroup/systemd_ -- _/var/lib/journal_ - -It will also set the default stop signal to **SIGRTMIN+3**. +looking at the executable name. Otherwise, if set to true and the +command you are running inside the container is **systemd**, **/usr/sbin/init**, +**/sbin/init** or **/usr/local/sbin/init**. + +Running the container in systemd mode causes the following changes: + +* Podman mounts tmpfs file systems on the following directories + * _/run_ + * _/run/lock_ + * _/tmp_ + * _/sys/fs/cgroup/systemd_ + * _/var/lib/journal_ +* Podman sets the default stop signal to **SIGRTMIN+3**. +* Podman sets **container_uuid** environment variable in the container to the +first 32 characters of the container id. This allows systemd to run in a confined container without any modifications. @@ -1150,23 +1167,6 @@ echo "asdf" | podman run --rm -i someimage /bin/cat Set timezone in container. This flag takes area-based timezones, GMT time, as well as `local`, which sets the timezone in the container to match the host machine. See `/usr/share/zoneinfo/` for valid timezones. Remote connections use local containers.conf for defaults -#### **--umask**=*umask* - -Set the umask inside the container. Defaults to `0022`. -Remote connections use local containers.conf for defaults - -#### **--unsetenv**=*env* - -Unset default environment variables for the container. Default environment -variables include variables provided natively by Podman, environment variables -configured by the image, and environment variables from containers.conf. - -#### **--unsetenv-all**=*true|false* - -Unset all default environment variables for the container. Default environment -variables include variables provided natively by Podman, environment variables -configured by the image, and environment variables from containers.conf. - #### **--uidmap**=*container_uid*:*from_uid*:*amount* Run the container in a new user namespace using the supplied mapping. This @@ -1251,6 +1251,23 @@ Note: the **--uidmap** flag cannot be called in conjunction with the **--pod** f Ulimit options. You can use **host** to copy the current configuration from the host. +#### **--umask**=*umask* + +Set the umask inside the container. Defaults to `0022`. +Remote connections use local containers.conf for defaults + +#### **--unsetenv**=*env* + +Unset default environment variables for the container. Default environment +variables include variables provided natively by Podman, environment variables +configured by the image, and environment variables from containers.conf. + +#### **--unsetenv-all**=*true|false* + +Unset all default environment variables for the container. Default environment +variables include variables provided natively by Podman, environment variables +configured by the image, and environment variables from containers.conf. + #### **--user**, **-u**=[_user_ | _user_:_group_ | _uid_ | _uid_:_gid_ | _user_:_gid_ | _uid_:_group_ ] Sets the username or UID used and optionally the groupname or GID for the specified command. @@ -1519,22 +1536,6 @@ The default working directory for running binaries within a container is the roo The image developer can set a different default with the WORKDIR instruction. The operator can override the working directory by using the **-w** option. -#### **--pidfile**=*path* - -When the pidfile location is specified, the container process' PID will be written to the pidfile. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) -If the pidfile option is not specified, the container process' PID will be written to /run/containers/storage/${storage-driver}-containers/$CID/userdata/pidfile. - -After the container is started, the location for the pidfile can be discovered with the following `podman inspect` command: - - $ podman inspect --format '{{ .PidFile }}' $CID - /run/containers/storage/${storage-driver}-containers/$CID/userdata/pidfile - -#### **--chrootdirs**=*path* - -Path to a directory inside the container that should be treated as a `chroot` directory. -Any Podman managed file (e.g., /etc/resolv.conf, /etc/hosts, etc/hostname) that is mounted into the root directory will be mounted into that location as well. -Multiple directories should be separated with a comma. - ## Exit Status The exit code from **podman run** gives information about why the container diff --git a/docs/source/markdown/podman-save.1.md b/docs/source/markdown/podman-save.1.md index 0de64e518..aa4900e25 100644 --- a/docs/source/markdown/podman-save.1.md +++ b/docs/source/markdown/podman-save.1.md @@ -29,14 +29,6 @@ Note: `:` is a restricted character and cannot be part of the file name. Compress tarball image layers when pushing to a directory using the 'dir' transport. (default is same compression type, compressed or uncompressed, as source) Note: This flag can only be set with **--format=docker-dir**. -#### **--uncompressed** - -Accept uncompressed layers when using one of the OCI formats. - -#### **--output**, **-o**=*file* - -Write to a file, default is STDOUT - #### **--format**=*format* An image format to produce, one of: @@ -48,18 +40,26 @@ An image format to produce, one of: | **oci-dir** | A directory using the OCI Image Format | | **docker-dir** | **dir** transport (see **containers-transports(5)**) with v2s2 manifest type | +#### **--help**, **-h** + +Print usage statement + #### **--multi-image-archive**, **-m** Allow for creating archives with more than one image. Additional names will be interpreted as images instead of tags. Only supported for **--format=docker-archive**. The default for this option can be modified via the `multi_image_archive="true"|"false"` flag in containers.conf. +#### **--output**, **-o**=*file* + +Write to a file, default is STDOUT + #### **--quiet**, **-q** Suppress the output -#### **--help**, **-h** +#### **--uncompressed** -Print usage statement +Accept uncompressed layers when using one of the OCI formats. ## EXAMPLES diff --git a/docs/source/markdown/podman-search.1.md b/docs/source/markdown/podman-search.1.md index 9c075a1e0..81a67d762 100644 --- a/docs/source/markdown/podman-search.1.md +++ b/docs/source/markdown/podman-search.1.md @@ -70,6 +70,10 @@ Valid placeholders for the Go template are listed below: Note: use .Tag only if the --list-tags is set. +#### **--help**, **-h** + +Print usage statement + #### **--limit**=*limit* Limit the number of results (default 25). @@ -95,10 +99,6 @@ then TLS verification will be used. If set to false, then TLS verification will default registries will be searched through (in /etc/containers/registries.conf), and TLS will be skipped if a default registry is listed in the insecure registries. -#### **--help**, **-h** - -Print usage statement - ## EXAMPLES ``` diff --git a/docs/source/markdown/podman-secret-create.1.md b/docs/source/markdown/podman-secret-create.1.md index 2d504c0ad..e08afb388 100644 --- a/docs/source/markdown/podman-secret-create.1.md +++ b/docs/source/markdown/podman-secret-create.1.md @@ -20,10 +20,6 @@ Secrets will not be committed to an image with `podman commit`, and will not be ## OPTIONS -#### **--env**=*false* - -Read secret data from environment variable - #### **--driver**=*driver* Specify the secret driver (default **file**, which is unencrypted). @@ -32,6 +28,10 @@ Specify the secret driver (default **file**, which is unencrypted). Specify driver specific options +#### **--env**=*false* + +Read secret data from environment variable + #### **--help** Print usage statement. diff --git a/docs/source/markdown/podman-secret-ls.1.md b/docs/source/markdown/podman-secret-ls.1.md index f33ccf41b..3b8535b5d 100644 --- a/docs/source/markdown/podman-secret-ls.1.md +++ b/docs/source/markdown/podman-secret-ls.1.md @@ -12,14 +12,6 @@ Lists all the secrets that exist. The output can be formatted to a Go template u ## OPTIONS -#### **--format**=*format* - -Format secret output using Go template. - -#### **--noheading** - -Omit the table headings from the listing of secrets. . - #### **--filter**, **-f**=*filter=value* Filter output based on conditions given. @@ -32,6 +24,14 @@ Valid filters are listed below: | name | [Name] Secret name (accepts regex) | | id | [ID] Full or partial secret ID | +#### **--format**=*format* + +Format secret output using Go template. + +#### **--noheading** + +Omit the table headings from the listing of secrets. . + ## EXAMPLES ``` diff --git a/docs/source/markdown/podman-start.1.md b/docs/source/markdown/podman-start.1.md index 793f27aa4..6b0433483 100644 --- a/docs/source/markdown/podman-start.1.md +++ b/docs/source/markdown/podman-start.1.md @@ -16,6 +16,10 @@ attach to the container. ## OPTIONS +#### **--all** + +Start all the containers created by Podman, default is only running containers. + #### **--attach**, **-a** Attach container's STDOUT and STDERR. The default is false. This option cannot be used when @@ -25,23 +29,6 @@ starting multiple containers. 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*. -#### **--interactive**, **-i** - -Attach container's STDIN. The default is false. - -#### **--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, including Mac and Windows (excluding WSL2) machines) - -#### **--sig-proxy** - -Proxy received signals to the process (non-TTY mode only). SIGCHLD, SIGSTOP, and SIGKILL are not proxied. The default is *true* when attaching, *false* otherwise. - -#### **--all** - -Start all the containers created by Podman, default is only running containers. - #### **--filter**, **-f** Filter what containers are going to be started from the given arguments. @@ -66,6 +53,18 @@ Valid filters are listed below: | pod | [Pod] name or full or partial ID of pod | | network | [Network] name or full ID of network | +#### **--interactive**, **-i** + +Attach container's STDIN. The default is false. + +#### **--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, including Mac and Windows (excluding WSL2) machines) + +#### **--sig-proxy** + +Proxy received signals to the process (non-TTY mode only). SIGCHLD, SIGSTOP, and SIGKILL are not proxied. The default is *true* when attaching, *false* otherwise. ## EXAMPLE diff --git a/docs/source/markdown/podman-stats.1.md b/docs/source/markdown/podman-stats.1.md index a1a156b10..472cbfbcf 100644 --- a/docs/source/markdown/podman-stats.1.md +++ b/docs/source/markdown/podman-stats.1.md @@ -24,23 +24,6 @@ about their networking usage. Show all containers. Only running containers are shown by default -#### **--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, including Mac and Windows (excluding WSL2) machines) - -#### **--no-reset** - -Do not clear the terminal/screen in between reporting intervals - -#### **--no-stream** - -Disable streaming stats and only pull the first result, default setting is false - -#### **--interval**=*seconds*, **-i**=*seconds* - -Time in seconds between stats reports, defaults to 5 seconds. - #### **--format**=*template* Pretty-print container statistics to JSON or using a Go template @@ -61,6 +44,23 @@ Valid placeholders for the Go template are listed below: When using a GO template, you may precede the format with `table` to print headers. +#### **--interval**=*seconds*, **-i**=*seconds* + +Time in seconds between stats reports, defaults to 5 seconds. + +#### **--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, including Mac and Windows (excluding WSL2) machines) + +#### **--no-reset** + +Do not clear the terminal/screen in between reporting intervals + +#### **--no-stream** + +Disable streaming stats and only pull the first result, default setting is false + ## EXAMPLE ``` diff --git a/docs/source/markdown/podman-system-service.1.md b/docs/source/markdown/podman-system-service.1.md index 3bc4fc7f1..678f08a20 100644 --- a/docs/source/markdown/podman-system-service.1.md +++ b/docs/source/markdown/podman-system-service.1.md @@ -15,7 +15,7 @@ example *unix:///run/user/1000/podman/podman.sock*) To access the API service inside a container: - mount the socket as a volume -- run the container with `--security-opt label:disable` +- run the container with `--security-opt label=disable` The REST API provided by **podman system service** is split into two parts: a compatibility layer offering support for the Docker v1.40 API, and a Podman-native Libpod layer. Documentation for the latter is available at *https://docs.podman.io/en/latest/_static/api.html*. @@ -25,14 +25,6 @@ Note: The default systemd unit files (system and user) change the log-level opti ## OPTIONS -#### **--time**, **-t** - -The time until the session expires in _seconds_. The default is 5 -seconds. A value of `0` means no timeout, therefore the session will not expire. - -The default timeout can be changed via the `service_timeout=VALUE` field in containers.conf. -See **[containers.conf(5)](https://github.com/containers/common/blob/master/docs/containers.conf.5.md)** for more information. - #### **--cors** CORS headers to inject to the HTTP response. The default value is empty string which disables CORS headers. @@ -41,6 +33,14 @@ CORS headers to inject to the HTTP response. The default value is empty string w Print usage statement. +#### **--time**, **-t** + +The time until the session expires in _seconds_. The default is 5 +seconds. A value of `0` means no timeout, therefore the session will not expire. + +The default timeout can be changed via the `service_timeout=VALUE` field in containers.conf. +See **[containers.conf(5)](https://github.com/containers/common/blob/master/docs/containers.conf.5.md)** for more information. + ## EXAMPLES Run an API listening for 5 seconds using the default socket. diff --git a/docs/source/markdown/podman-unshare.1.md b/docs/source/markdown/podman-unshare.1.md index 01393a862..db1bc5387 100644 --- a/docs/source/markdown/podman-unshare.1.md +++ b/docs/source/markdown/podman-unshare.1.md @@ -4,7 +4,7 @@ podman\-unshare - Run a command inside of a modified user namespace ## SYNOPSIS -**podman unshare** [*--*] [*command*] +**podman unshare** [*options*] [*command*] ## DESCRIPTION Launches a process (by default, *$SHELL*) in a new user namespace. The user @@ -24,6 +24,8 @@ The unshare session defines two environment variables: - **CONTAINERS_GRAPHROOT**: the path to the persistent container's data. - **CONTAINERS_RUNROOT**: the path to the volatile container's data. +*IMPORTANT: This command is not available with the remote Podman client.* + ## OPTIONS #### **--help**, **-h** diff --git a/docs/source/markdown/podman-version.1.md b/docs/source/markdown/podman-version.1.md index 809ce64a6..94fa0fb21 100644 --- a/docs/source/markdown/podman-version.1.md +++ b/docs/source/markdown/podman-version.1.md @@ -12,10 +12,6 @@ OS, and Architecture. ## OPTIONS -#### **--help**, **-h** - -Print usage statement - #### **--format**, **-f**=*format* Change output format to "json" or a Go template. @@ -39,6 +35,10 @@ $ podman version --format '{{.Client.Version}}' 2.0.0 ``` +#### **--help**, **-h** + +Print usage statement + ## SEE ALSO **[podman(1)](podman.1.md)** diff --git a/docs/source/markdown/podman-volume-export.1.md b/docs/source/markdown/podman-volume-export.1.md index ed73e86d0..57b707ae5 100644 --- a/docs/source/markdown/podman-volume-export.1.md +++ b/docs/source/markdown/podman-volume-export.1.md @@ -18,14 +18,13 @@ Note: Following command is not supported by podman-remote. ## OPTIONS -#### **--output**, **-o**=*file* - -Write to a file, default is STDOUT - #### **--help** Print usage statement +#### **--output**, **-o**=*file* + +Write to a file, default is STDOUT ## EXAMPLES diff --git a/docs/source/markdown/podman-volume-prune.1.md b/docs/source/markdown/podman-volume-prune.1.md index 2028e42f2..0127cc12a 100644 --- a/docs/source/markdown/podman-volume-prune.1.md +++ b/docs/source/markdown/podman-volume-prune.1.md @@ -15,10 +15,6 @@ unused volumes. To bypass the confirmation, use the **--force** flag. ## OPTIONS -#### **--force**, **-f** - -Do not prompt for confirmation. - #### **--filter** Provide filter values. @@ -36,6 +32,10 @@ The `label` *filter* accepts two formats. One is the `label`=*key* or `label`=*k 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. +#### **--force**, **-f** + +Do not prompt for confirmation. + #### **--help** Print usage statement diff --git a/docs/source/markdown/podman.1.md b/docs/source/markdown/podman.1.md index 4d3e92dd2..aad12c584 100644 --- a/docs/source/markdown/podman.1.md +++ b/docs/source/markdown/podman.1.md @@ -32,22 +32,14 @@ The CGroup manager to use for container cgroups. Supported values are cgroupfs o Note: Setting this flag can cause certain commands to break when called on containers previously created by the other CGroup manager type. Note: CGroup manager is not supported in rootless mode when using CGroups Version V1. -#### **--network-config-dir**=*directory* - -Path to the directory where network configuration files are located. -For the CNI backend the default is "/etc/cni/net.d" as root -and "$HOME/.config/cni/net.d" as rootless. -For the netavark backend "/etc/containers/networks" is used as root -and "$graphroot/networks" as rootless. +#### **--conmon** +Path of the conmon binary (Default path is configured in `containers.conf`) #### **--connection**, **-c** Connection to use for remote podman, including Mac and Windows (excluding WSL2) machines, (Default connection is configured in `containers.conf`) Setting this option will switch the **--remote** option to true. Remote connections use local containers.conf for default. -#### **--conmon** -Path of the conmon binary (Default path is configured in `containers.conf`) - #### **--events-backend**=*type* Backend to use for storing events. Allowed values are **file**, **journald**, and @@ -98,6 +90,14 @@ When namespace is set, created containers and pods will join the given namespace #### **--network-cmd-path**=*path* Path to the command binary to use for setting up a network. It is currently only used for setting up a slirp4netns network. If "" is used then the binary is looked up using the $PATH environment variable. +#### **--network-config-dir**=*directory* + +Path to the directory where network configuration files are located. +For the CNI backend the default is "/etc/cni/net.d" as root +and "$HOME/.config/cni/net.d" as rootless. +For the netavark backend "/etc/containers/networks" is used as root +and "$graphroot/networks" as rootless. + #### **--noout** Redirect stdout to /dev/null. This command will prevent all stdout from the Podman command. The **--noout** option will not block stderr or stdout from containers. @@ -107,39 +107,6 @@ When true, access to the Podman service will be remote. Defaults to false. Settings can be modified in the containers.conf file. If the CONTAINER_HOST environment variable is set, the **--remote** option defaults to true. -#### **--url**=*value* -URL to access Podman service (default from `containers.conf`, rootless `unix://run/user/$UID/podman/podman.sock` or as root `unix://run/podman/podman.sock`). -Setting this option will switch the **--remote** option to true. - - - `CONTAINER_HOST` is of the format `<schema>://[<user[:<password>]@]<host>[:<port>][<path>]` - -Details: - - `schema` is one of: - * `ssh` (default): a local unix(7) socket on the named `host` and `port`, reachable via SSH - * `tcp`: an unencrypted, unauthenticated TCP connection to the named `host` and `port` - * `unix`: a local unix(7) socket at the specified `path`, or the default for the user - - `user` will default to either `root` or the current running user (`ssh` only) - - `password` has no default (`ssh` only) - - `host` must be provided and is either the IP or name of the machine hosting the Podman service (`ssh` and `tcp`) - - `port` defaults to 22 (`ssh` and `tcp`) - - `path` defaults to either `/run/podman/podman.sock`, or `/run/user/$UID/podman/podman.sock` if running rootless (`unix`), or must be explicitly specified (`ssh`) - -URL value resolution precedence: - - command line value - - environment variable `CONTAINER_HOST` - - `containers.conf` `service_destinations` table - - `unix://run/podman/podman.sock` - -Remote connections use local containers.conf for default. - -Some example URL values in valid formats: - - unix://run/podman/podman.sock - - unix://run/user/$UID/podman/podman.sock - - ssh://notroot@localhost:22/run/user/$UID/podman/podman.sock - - ssh://root@localhost:22/run/podman/podman.sock - - tcp://localhost:34451 - - tcp://127.0.0.1:34451 - #### **--root**=*value* Storage root dir in which data, including images, is stored (default: "/var/lib/containers/storage" for UID 0, "$HOME/.local/share/containers/storage" for other users). @@ -189,6 +156,39 @@ Path to the tmp directory, for libpod runtime content. NOTE --tmpdir is not used for the temporary storage of downloaded images. Use the environment variable `TMPDIR` to change the temporary storage location of downloaded container images. Podman defaults to use `/var/tmp`. +#### **--url**=*value* +URL to access Podman service (default from `containers.conf`, rootless `unix://run/user/$UID/podman/podman.sock` or as root `unix://run/podman/podman.sock`). +Setting this option will switch the **--remote** option to true. + + - `CONTAINER_HOST` is of the format `<schema>://[<user[:<password>]@]<host>[:<port>][<path>]` + +Details: + - `schema` is one of: + * `ssh` (default): a local unix(7) socket on the named `host` and `port`, reachable via SSH + * `tcp`: an unencrypted, unauthenticated TCP connection to the named `host` and `port` + * `unix`: a local unix(7) socket at the specified `path`, or the default for the user + - `user` will default to either `root` or the current running user (`ssh` only) + - `password` has no default (`ssh` only) + - `host` must be provided and is either the IP or name of the machine hosting the Podman service (`ssh` and `tcp`) + - `port` defaults to 22 (`ssh` and `tcp`) + - `path` defaults to either `/run/podman/podman.sock`, or `/run/user/$UID/podman/podman.sock` if running rootless (`unix`), or must be explicitly specified (`ssh`) + +URL value resolution precedence: + - command line value + - environment variable `CONTAINER_HOST` + - `containers.conf` `service_destinations` table + - `unix://run/podman/podman.sock` + +Remote connections use local containers.conf for default. + +Some example URL values in valid formats: + - unix://run/podman/podman.sock + - unix://run/user/$UID/podman/podman.sock + - ssh://notroot@localhost:22/run/user/$UID/podman/podman.sock + - ssh://root@localhost:22/run/podman/podman.sock + - tcp://localhost:34451 + - tcp://127.0.0.1:34451 + #### **--version**, **-v** Print the version @@ -12,12 +12,12 @@ require ( github.com/containernetworking/cni v1.0.1 github.com/containernetworking/plugins v1.1.1 github.com/containers/buildah v1.24.3-0.20220310160415-5ec70bf01ea5 - github.com/containers/common v0.47.5-0.20220228211119-9880eb424fde + github.com/containers/common v0.47.5-0.20220318125043-0ededd18a1f9 github.com/containers/conmon v2.0.20+incompatible github.com/containers/image/v5 v5.20.1-0.20220310094651-0d8056ee346f - github.com/containers/ocicrypt v1.1.2 + github.com/containers/ocicrypt v1.1.3 github.com/containers/psgo v1.7.2 - github.com/containers/storage v1.38.3-0.20220308085612-93ce26691863 + github.com/containers/storage v1.38.3-0.20220321121613-8e565392dd91 github.com/coreos/go-systemd/v22 v22.3.2 github.com/coreos/stream-metadata-go v0.0.0-20210225230131-70edb9eb47b3 github.com/cyphar/filepath-securejoin v0.2.3 @@ -54,11 +54,12 @@ require ( github.com/opencontainers/selinux v1.10.0 github.com/pkg/errors v0.9.1 github.com/pmezard/go-difflib v1.0.0 + github.com/prometheus/client_golang v1.11.1 // indirect github.com/rootless-containers/rootlesskit v0.14.6 github.com/sirupsen/logrus v1.8.1 github.com/spf13/cobra v1.4.0 github.com/spf13/pflag v1.0.5 - github.com/stretchr/testify v1.7.0 + github.com/stretchr/testify v1.7.1 github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 github.com/uber/jaeger-client-go v2.30.0+incompatible github.com/ulikunitz/xz v0.5.10 @@ -285,7 +285,6 @@ github.com/containerd/containerd v1.5.1/go.mod h1:0DOxVqwDy2iZvrZp2JUx/E+hS0UNTV github.com/containerd/containerd v1.5.7/go.mod h1:gyvv6+ugqY25TiXxcZC3L5yOeYgEw0QMhscqVp1AR9c= github.com/containerd/containerd v1.5.8/go.mod h1:YdFSv5bTFLpG2HIYmfqDpSYYTDX+mc5qtSuYx1YUb/s= github.com/containerd/containerd v1.5.9/go.mod h1:fvQqCfadDGga5HZyn3j4+dx56qj2I9YwBrlSdalvJYQ= -github.com/containerd/containerd v1.6.0/go.mod h1:1nJz5xCZPusx6jJU8Frfct988y0NpumIq9ODB0kLtoE= github.com/containerd/containerd v1.6.1 h1:oa2uY0/0G+JX4X7hpGCYvkp9FjUancz56kSNnb1sG3o= github.com/containerd/containerd v1.6.1/go.mod h1:1nJz5xCZPusx6jJU8Frfct988y0NpumIq9ODB0kLtoE= github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= @@ -325,8 +324,9 @@ github.com/containerd/stargz-snapshotter/estargz v0.9.0/go.mod h1:aE5PCyhFMwR8sb github.com/containerd/stargz-snapshotter/estargz v0.10.1/go.mod h1:aE5PCyhFMwR8sbrErO5eM2GcvkyXTTJremG883D4qF0= github.com/containerd/stargz-snapshotter/estargz v0.11.0/go.mod h1:/KsZXsJRllMbTKFfG0miFQWViQKdI9+9aSXs+HN0+ac= github.com/containerd/stargz-snapshotter/estargz v0.11.1/go.mod h1:6VoPcf4M1wvnogWxqc4TqBWWErCS+R+ucnPZId2VbpQ= -github.com/containerd/stargz-snapshotter/estargz v0.11.2 h1:0P0vWmfrEeTtZ4BBRrpuyu/HxR9HPBLfeljGOra5f6g= github.com/containerd/stargz-snapshotter/estargz v0.11.2/go.mod h1:rjbdAXaytDSIrAy2WAy2kUrJ4ehzDS0eUQLlIb5UCY0= +github.com/containerd/stargz-snapshotter/estargz v0.11.3 h1:k2kN16Px6LYuv++qFqK+JTcYqc8bEVxzGpf8/gFBL5M= +github.com/containerd/stargz-snapshotter/estargz v0.11.3/go.mod h1:7vRJIcImfY8bpifnMjt+HTJoQxASq7T28MYbP15/Nf0= github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= github.com/containerd/ttrpc v0.0.0-20191028202541-4f1b8fe65a5c/go.mod h1:LPm1u0xBw8r8NOKoOdNMeVHSawSsltak+Ihv+etqsE8= @@ -350,14 +350,13 @@ github.com/containernetworking/cni v1.0.1/go.mod h1:AKuhXbN5EzmD4yTNtfSsX3tPcmtr github.com/containernetworking/plugins v0.8.6/go.mod h1:qnw5mN19D8fIwkqW7oHHYDHVlzhJpcY6TQxn/fUyDDM= github.com/containernetworking/plugins v0.9.1/go.mod h1:xP/idU2ldlzN6m4p5LmGiwRDjeJr6FLK6vuiUwoH7P8= github.com/containernetworking/plugins v1.0.1/go.mod h1:QHCfGpaTwYTbbH+nZXKVTxNBDZcxSOplJT5ico8/FLE= -github.com/containernetworking/plugins v1.1.0/go.mod h1:Sr5TH/eBsGLXK/h71HeLfX19sZPp3ry5uHSkI4LPxV8= github.com/containernetworking/plugins v1.1.1 h1:+AGfFigZ5TiQH00vhR8qPeSatj53eNGz0C1d3wVYlHE= github.com/containernetworking/plugins v1.1.1/go.mod h1:Sr5TH/eBsGLXK/h71HeLfX19sZPp3ry5uHSkI4LPxV8= github.com/containers/buildah v1.24.3-0.20220310160415-5ec70bf01ea5 h1:RMJG1wCPQqZX7o9xGzpmR0U7NppgquSQunTi8qmP9Do= github.com/containers/buildah v1.24.3-0.20220310160415-5ec70bf01ea5/go.mod h1:C5+kt1nmYVf1N+/pk4WepycLD+m4lEIRgJQ0eXqhADo= github.com/containers/common v0.47.4/go.mod h1:HgX0mFXyB0Tbe2REEIp9x9CxET6iSzmHfwR6S/t2LZc= -github.com/containers/common v0.47.5-0.20220228211119-9880eb424fde h1:zLBqM8I+wiIgzmQhJ+n2zrB+cpxdGmzA/HkCxJbmGok= -github.com/containers/common v0.47.5-0.20220228211119-9880eb424fde/go.mod h1:pksCYxGMnUwntsUMdsq/eClGsASoDsdDOZz+YxDxAJY= +github.com/containers/common v0.47.5-0.20220318125043-0ededd18a1f9 h1:+uNhZTl7nBm4GLCKb4Np8BDhw2uMmC8+D/KuH8nIjGA= +github.com/containers/common v0.47.5-0.20220318125043-0ededd18a1f9/go.mod h1:j1nTHtSRoBgVqAoV6X13EGIrTU5jP1GYyEsE4N9DXng= 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.19.1/go.mod h1:ewoo3u+TpJvGmsz64XgzbyTHwHtM94q7mgK/pX+v2SE= @@ -371,16 +370,18 @@ github.com/containers/libtrust v0.0.0-20200511145503-9c3a6c22cd9a/go.mod h1:9rfv github.com/containers/ocicrypt v1.0.1/go.mod h1:MeJDzk1RJHv89LjsH0Sp5KTY3ZYkjXO/C+bKAeWFIrc= github.com/containers/ocicrypt v1.1.0/go.mod h1:b8AOe0YR67uU8OqfVNcznfFpAzu3rdgUV4GP9qXPfu4= github.com/containers/ocicrypt v1.1.1/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY= -github.com/containers/ocicrypt v1.1.2 h1:Ez+GAMP/4GLix5Ywo/fL7O0nY771gsBIigiqUm1aXz0= github.com/containers/ocicrypt v1.1.2/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY= +github.com/containers/ocicrypt v1.1.3 h1:uMxn2wTb4nDR7GqG3rnZSfpJXqWURfzZ7nKydzIeKpA= +github.com/containers/ocicrypt v1.1.3/go.mod h1:xpdkbVAuaH3WzbEabUd5yDsl9SwJA5pABH85425Es2g= github.com/containers/psgo v1.7.2 h1:WbCvsY9w+nCv3j4der0mbD3PSRUv/W8l+G0YrZrdSDc= github.com/containers/psgo v1.7.2/go.mod h1:SLpqxsPOHtTqRygjutCPXmeU2PoEFzV3gzJplN4BMx0= github.com/containers/storage v1.37.0/go.mod h1:kqeJeS0b7DO2ZT1nVWs0XufrmPFbgV3c+Q/45RlH6r4= github.com/containers/storage v1.38.0/go.mod h1:lBzt28gAk5ADZuRtwdndRJyqX22vnRaXmlF+7ktfMYc= github.com/containers/storage v1.38.2/go.mod h1:INP0RPLHWBxx+pTsO5uiHlDUGHDFvWZPWprAbAlQWPQ= github.com/containers/storage v1.38.3-0.20220301151551-d06b0f81c0aa/go.mod h1:LkkL34WRi4dI4jt9Cp+ImdZi/P5i36glSHimT5CP5zM= -github.com/containers/storage v1.38.3-0.20220308085612-93ce26691863 h1:10k6Dl+Bm9zgsxP7qv0mnrhd7+XlCmgQWKgkydwZ7vQ= github.com/containers/storage v1.38.3-0.20220308085612-93ce26691863/go.mod h1:uhf9mPUP+uYajC2/S0A9NaCVa2JJ6+1C254ue4Edv2g= +github.com/containers/storage v1.38.3-0.20220321121613-8e565392dd91 h1:gEbkqcBM3XFbIz6L9bpJyUEcuDd8vi8jzyrneVS8At4= +github.com/containers/storage v1.38.3-0.20220321121613-8e565392dd91/go.mod h1:UAD0cKLouN4BOQRgZut/nMjrh/EnTCjSNPgp4ZuGWMs= 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= @@ -878,8 +879,9 @@ github.com/klauspost/compress v1.14.1/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47e github.com/klauspost/compress v1.14.2/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.14.3/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.14.4/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/klauspost/compress v1.15.0 h1:xqfchp4whNFxn5A4XFyyYtitiWI8Hy5EW59jEwcyL6U= github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/klauspost/compress v1.15.1 h1:y9FcTHGyrebwfP0ZZqFiaxTaiDnUrGkJkI+f583BL1A= +github.com/klauspost/compress v1.15.1/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= 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= @@ -974,8 +976,9 @@ github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKju github.com/miekg/dns v1.1.35/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= github.com/miekg/pkcs11 v1.0.2/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= -github.com/miekg/pkcs11 v1.0.3 h1:iMwmD7I5225wv84WxIG/bmxz9AXjWvTWIbM/TYHvWtw= github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= +github.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU= +github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible h1:aKW/4cBs+yK6gpqU3K/oIwk9Q/XICqd3zOX/UFuvqmk= github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= @@ -1152,8 +1155,9 @@ github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5Fsn github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_golang v1.11.1 h1:+4eQaD7vAZ6DsfsxB15hbE0odUjGI5ARs9yskGu1v4s= +github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -1300,8 +1304,9 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/sylabs/release-tools v0.1.0/go.mod h1:pqP/z/11/rYMQ0OM/Nn7TxGijw7KfZwW9UolD/J1TUo= github.com/sylabs/sif/v2 v2.3.1/go.mod h1:NnvveH62GiibimL00MrI6YYcZfb7DnZMcRo/40giY+0= diff --git a/hack/make-and-check-size b/hack/make-and-check-size new file mode 100755 index 000000000..71b382b44 --- /dev/null +++ b/hack/make-and-check-size @@ -0,0 +1,133 @@ +#!/bin/bash +# +# make-and-check-size - wrapper around 'make' that also checks binary growth +# +# This script is intended to be run via 'git rebase -x', in a form such as: +# +# context_dir=$(mktemp -d --tmpdir make-size-check.XXXXXXX) +# git rebase ${GIT_BASE_BRANCH}^ -x "hack/make-and-check-size $context_dir" +# rm -rf $context_dir +# +# (Carefully note the '^' next to GIT_BASE_BRANCH!) +# +# A 'git rebase -x' has long been a part of our usual CI; it guarantees +# that each commit (whether in a single- or multi-commit PR) can be +# compiled individually. +# +# By adding the '^' to GIT_BASE_BRANCH we establish a baseline and store +# the binary sizes of each file (podman, podman-remote) prior to our PR. +# +# context_dir is a temporary directory used to store the original sizes +# of each binary file under bin/ +# +# *IMPORTANT NOTE*: this script will leave the git checkout in a funky state! +# (because we rebase onto a nonterminal commit). I believe this is OK, since +# this script is only invoked in CI from runner.sh and only in a scratch VM. +# Running this in a development environment would yield unpredictable results +# anyway, by rebasing onto origin/main by default and by leaving an aborted +# rebase on failure. +# +ME=$(basename $0) + +############################################################################### +# BEGIN end-user-customizable settings + +# Maximum allowable size, in bytes +MAX_BIN_GROWTH=$((50 * 1024)) + +# Github label which allows overriding this check +OVERRIDE_LABEL=bloat_approved + +# END end-user-customizable settings +############################################################################### + +# +# Helper function: queries github for labels on this PR +# +function bloat_approved() { + # Argument is the actual size increase in this build. + # FIXME: 2022-03-21: this is not actually used atm, but Ed hopes some day + # to implement a more robust size-override mechanism, such as by + # requiring a MAX_BIN_GROWTH=nnn statement in github comments. + local actual_growth="$1" + + if [[ -z "$CIRRUS_PR" ]]; then + echo "$ME: cannot query github: \$CIRRUS_PR is undefined" >&2 + return 1 + fi + if [[ -z "$CIRRUS_REPO_CLONE_TOKEN" ]]; then + echo "$ME: cannot query github: \$CIRRUS_REPO_CLONE_TOKEN is undefined" >&2 + return 1 + fi + + query="{ + \"query\": \"query { + repository(owner: \\\"containers\\\", name: \\\"podman\\\") { + pullRequest(number: $CIRRUS_PR) { + labels(first: 100) { + nodes { + name + } + } + } + } +}\" +}" + + result=$(curl -s -H "Authorization: bearer $CIRRUS_REPO_CLONE_TOKEN" -H "Accept: application/vnd.github.antiope-preview+json" -H "Content-Type: application/json" -X POST --data @- https://api.github.com/graphql <<<"$query") + + labels=$(jq -r '.data.repository.pullRequest.labels.nodes[].name' <<<"$result") + + grep -q -w "$OVERRIDE_LABEL" <<<"$labels" +} + +# ACTUAL CODE BEGINS HERE +set -e + +# Must be invoked with one argument, an existing context directory +context_dir=${1?Missing CONTEXT-DIR argument} +if [[ ! -d $context_dir ]]; then + echo "$ME: directory '$context_dir' does not exist" + exit 1 +fi + +# This is the original (and primary) purpose of this check: if 'make' fails, +# there is no point in continuing +echo +echo "Building: $(git rev-parse HEAD)" +make + +# Determine size of each built file. +# - If this is our first time through, preserve that size in a tmpfile +# - On all subsequent runs, compare built size to initial size +for bin in bin/*;do + size=$(stat -c %s $bin) + + saved_size_file=$context_dir/$(basename $bin) + if [[ -e $saved_size_file ]]; then + # Not the first time through: compare to original size + size_orig=$(< $saved_size_file) + delta_size=$(( size - size_orig )) + + if [[ $delta_size -gt $MAX_BIN_GROWTH ]]; then + separator=$(printf "%.0s*" {1..75}) # row of stars, for highlight + echo "$separator" + echo "* $bin grew by $delta_size bytes; max allowed is $MAX_BIN_GROWTH." + echo "*" + if bloat_approved $delta_size; then + echo "* Continuing due to '$OVERRIDE_LABEL' label" + echo "*" + echo "$separator" + else + echo "* Please investigate, and fix if possible." + echo "*" + echo "* A repo admin can override by setting the $OVERRIDE_LABEL label" + echo "$separator" + exit 1 + fi + fi + else + # First time through: preserve original file size + echo $size >$saved_size_file + fi +done diff --git a/hack/xref-helpmsgs-manpages b/hack/xref-helpmsgs-manpages index a447f4da1..33ba43e9b 100755 --- a/hack/xref-helpmsgs-manpages +++ b/hack/xref-helpmsgs-manpages @@ -287,6 +287,7 @@ sub podman_man { my $section = ''; my @most_recent_flags; my $previous_subcmd = ''; + my $previous_flag = ''; while (my $line = <$fh>) { chomp $line; next unless $line; # skip empty lines @@ -294,6 +295,12 @@ sub podman_man { # .md files designate sections with leading double hash if ($line =~ /^##\s*(GLOBAL\s+)?OPTIONS/) { $section = 'flags'; + $previous_flag = ''; + } + elsif ($line =~ /^###\s+\w+\s+OPTIONS/) { + # poaman image trust has sections for set & show + $section = 'flags'; + $previous_flag = ''; } elsif ($line =~ /^\#\#\s+(SUB)?COMMANDS/) { $section = 'commands'; @@ -320,7 +327,7 @@ sub podman_man { # $1 will be changed by recursion _*BEFORE*_ left-hand assignment my $subcmd = $1; if ($previous_subcmd gt $subcmd) { - warn "$ME: $subpath: '$previous_subcmd' and '$subcmd' are out of order\n"; + warn "$ME: $subpath:$.: '$previous_subcmd' and '$subcmd' are out of order\n"; ++$Errs; } $previous_subcmd = $subcmd; @@ -342,9 +349,20 @@ sub podman_man { # If option has long and short form, long must come first. # This is a while-loop because there may be multiple long # option names, e.g. --net/--network + my $is_first = 1; while ($line =~ s/^\*\*(--[a-z0-9-]+)\*\*(=\*[a-zA-Z0-9-]+\*)?(,\s+)?//g) { - $man{$1} = 1; - push @most_recent_flags, $1; + my $flag = $1; + $man{$flag} = 1; + if ($flag lt $previous_flag && $is_first) { + warn "$ME: $subpath:$.: $flag should precede $previous_flag\n"; + ++$Errs; + } + $previous_flag = $flag if $is_first; + push @most_recent_flags, $flag; + + # Further iterations of /g are allowed to be out of order, + # e.g., it's OK for "--namespace, -ns" to precede --nohead + $is_first = 0; } # Short form if ($line =~ s/^\*\*(-[a-zA-Z0-9])\*\*(=\*[a-zA-Z0-9-]+\*)?//g) { diff --git a/libpod/boltdb_state.go b/libpod/boltdb_state.go index 6389431ab..9745121c7 100644 --- a/libpod/boltdb_state.go +++ b/libpod/boltdb_state.go @@ -366,7 +366,7 @@ func (s *BoltState) GetDBConfig() (*DBConfig, error) { err = db.View(func(tx *bolt.Tx) error { configBucket, err := getRuntimeConfigBucket(tx) if err != nil { - return nil + return err } // Some of these may be nil diff --git a/libpod/boltdb_state_linux.go b/libpod/boltdb_state_linux.go index 63ce9784e..8bb10fb63 100644 --- a/libpod/boltdb_state_linux.go +++ b/libpod/boltdb_state_linux.go @@ -1,3 +1,4 @@ +//go:build linux // +build linux package libpod diff --git a/libpod/common/common.go b/libpod/common/common.go index 93a736af2..34cabeadc 100644 --- a/libpod/common/common.go +++ b/libpod/common/common.go @@ -1,16 +1,16 @@ package common -// IsTrue determines whether the given string equals "true" +// IsTrue determines whether the given string equals "true". func IsTrue(str string) bool { return str == "true" } -// IsFalse determines whether the given string equals "false" +// IsFalse determines whether the given string equals "false". func IsFalse(str string) bool { return str == "false" } -// IsValidBool determines whether the given string equals "true" or "false" +// IsValidBool determines whether the given string equals "true" or "false". func IsValidBool(str string) bool { return IsTrue(str) || IsFalse(str) } diff --git a/libpod/container_api.go b/libpod/container_api.go index 03b3dcc04..0b6139335 100644 --- a/libpod/container_api.go +++ b/libpod/container_api.go @@ -921,7 +921,11 @@ func (c *Container) Stat(ctx context.Context, containerPath string) (*define.Fil if err != nil { return nil, err } - defer c.unmount(false) + defer func() { + if err := c.unmount(false); err != nil { + logrus.Errorf("Unmounting container %s: %v", c.ID(), err) + } + }() } info, _, _, err := c.stat(ctx, mountPoint, containerPath) diff --git a/libpod/container_copy_linux.go b/libpod/container_copy_linux.go index d16d635b7..38927d691 100644 --- a/libpod/container_copy_linux.go +++ b/libpod/container_copy_linux.go @@ -1,3 +1,4 @@ +//go:build linux // +build linux package libpod diff --git a/libpod/container_exec.go b/libpod/container_exec.go index d1c190905..140267f28 100644 --- a/libpod/container_exec.go +++ b/libpod/container_exec.go @@ -341,22 +341,60 @@ func (c *Container) ExecStartAndAttach(sessionID string, streams *define.AttachS } lastErr = tmpErr - exitCode, err := c.readExecExitCode(session.ID()) - if err != nil { + exitCode, exitCodeErr := c.readExecExitCode(session.ID()) + + // Lock again. + // Important: we must lock and sync *before* the above error is handled. + // We need info from the database to handle the error. + if !c.batched { + c.lock.Lock() + } + // We can't reuse the old exec session (things may have changed from + // other use, the container was unlocked). + // So re-sync and get a fresh copy. + // If we can't do this, no point in continuing, any attempt to save + // would write garbage to the DB. + if err := c.syncContainer(); err != nil { + if errors.Is(err, define.ErrNoSuchCtr) || errors.Is(err, define.ErrCtrRemoved) { + // We can't save status, but since the container has + // been entirely removed, we don't have to; exit cleanly + return lastErr + } if lastErr != nil { logrus.Errorf("Container %s exec session %s error: %v", c.ID(), session.ID(), lastErr) } - lastErr = err - } + return errors.Wrapf(err, "error syncing container %s state to update exec session %s", c.ID(), sessionID) + } + + // Now handle the error from readExecExitCode above. + if exitCodeErr != nil { + newSess, ok := c.state.ExecSessions[sessionID] + if !ok { + // The exec session was removed entirely, probably by + // the cleanup process. When it did so, it should have + // written an event with the exit code. + // Given that, there's nothing more we can do. + logrus.Infof("Container %s exec session %s already removed", c.ID(), session.ID()) + return lastErr + } - logrus.Debugf("Container %s exec session %s completed with exit code %d", c.ID(), session.ID(), exitCode) + if newSess.State == define.ExecStateStopped { + // Exec session already cleaned up. + // Exit code should be recorded, so it's OK if we were + // not able to read it. + logrus.Infof("Container %s exec session %s already cleaned up", c.ID(), session.ID()) + return lastErr + } - // Lock again - if !c.batched { - c.lock.Lock() + if lastErr != nil { + logrus.Errorf("Container %s exec session %s error: %v", c.ID(), session.ID(), lastErr) + } + lastErr = exitCodeErr } - if err := writeExecExitCode(c, session.ID(), exitCode); err != nil { + logrus.Debugf("Container %s exec session %s completed with exit code %d", c.ID(), session.ID(), exitCode) + + if err := justWriteExecExitCode(c, session.ID(), exitCode); err != nil { if lastErr != nil { logrus.Errorf("Container %s exec session %s error: %v", c.ID(), session.ID(), lastErr) } diff --git a/libpod/container_internal.go b/libpod/container_internal.go index 3c21cade8..b7362e7fb 100644 --- a/libpod/container_internal.go +++ b/libpod/container_internal.go @@ -1087,13 +1087,6 @@ func (c *Container) init(ctx context.Context, retainRetries bool) error { // With the spec complete, do an OCI create if _, err = c.ociRuntime.CreateContainer(c, nil); err != nil { - // Fedora 31 is carrying a patch to display improved error - // messages to better handle the V2 transition. This is NOT - // upstream in any OCI runtime. - // TODO: Remove once runc supports cgroupsv2 - if strings.Contains(err.Error(), "this version of runc doesn't work on cgroups v2") { - logrus.Errorf("Oci runtime %q does not support Cgroups V2: use system migrate to mitigate", c.ociRuntime.Name()) - } return err } @@ -1268,7 +1261,10 @@ func (c *Container) start() error { } } - if c.config.HealthCheckConfig != nil { + // Check if healthcheck is not nil and --no-healthcheck option is not set. + // If --no-healthcheck is set Test will be always set to `[NONE]` so no need + // to update status in such case. + if c.config.HealthCheckConfig != nil && !(len(c.config.HealthCheckConfig.Test) == 1 && c.config.HealthCheckConfig.Test[0] == "NONE") { if err := c.updateHealthStatus(define.HealthCheckStarting); err != nil { logrus.Error(err) } diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go index 75250b9b1..11ca169ca 100644 --- a/libpod/container_internal_linux.go +++ b/libpod/container_internal_linux.go @@ -968,6 +968,16 @@ func (c *Container) mountNotifySocket(g generate.Generator) error { // systemd expects to have /run, /run/lock and /tmp on tmpfs // It also expects to be able to write to /sys/fs/cgroup/systemd and /var/log/journal func (c *Container) setupSystemd(mounts []spec.Mount, g generate.Generator) error { + var containerUUIDSet bool + for _, s := range c.config.Spec.Process.Env { + if strings.HasPrefix(s, "container_uuid=") { + containerUUIDSet = true + break + } + } + if !containerUUIDSet { + g.AddProcessEnv("container_uuid", c.ID()[:32]) + } options := []string{"rw", "rprivate", "nosuid", "nodev"} for _, dest := range []string{"/run", "/run/lock"} { if MountExists(mounts, dest) { @@ -2587,7 +2597,7 @@ func (c *Container) generateUserGroupEntry(addedGID int) (string, int, error) { gid, err := strconv.ParseUint(group, 10, 32) if err != nil { - return "", 0, nil + return "", 0, nil // nolint: nilerr } if addedGID != 0 && addedGID == int(gid) { @@ -2740,7 +2750,7 @@ func (c *Container) generateUserPasswdEntry(addedUID int) (string, int, int, err // If a non numeric User, then don't generate passwd uid, err := strconv.ParseUint(userspec, 10, 32) if err != nil { - return "", 0, 0, nil + return "", 0, 0, nil // nolint: nilerr } if addedUID != 0 && int(uid) == addedUID { diff --git a/libpod/container_linux.go b/libpod/container_linux.go index c445fb8af..8b517e69f 100644 --- a/libpod/container_linux.go +++ b/libpod/container_linux.go @@ -1,3 +1,4 @@ +//go:build linux // +build linux package libpod diff --git a/libpod/container_log_unsupported.go b/libpod/container_log_unsupported.go index f9ca26966..4f50f9f4c 100644 --- a/libpod/container_log_unsupported.go +++ b/libpod/container_log_unsupported.go @@ -1,4 +1,5 @@ -//+build !linux !systemd +//go:build !linux || !systemd +// +build !linux !systemd package libpod diff --git a/libpod/container_path_resolution.go b/libpod/container_path_resolution.go index 7db23b783..80a3749f5 100644 --- a/libpod/container_path_resolution.go +++ b/libpod/container_path_resolution.go @@ -1,4 +1,3 @@ -// +linux package libpod import ( diff --git a/libpod/container_stat_linux.go b/libpod/container_stat_linux.go index d90684197..84ab984e0 100644 --- a/libpod/container_stat_linux.go +++ b/libpod/container_stat_linux.go @@ -1,3 +1,4 @@ +//go:build linux // +build linux package libpod diff --git a/libpod/container_top_linux.go b/libpod/container_top_linux.go index 41300a708..9b3dbc873 100644 --- a/libpod/container_top_linux.go +++ b/libpod/container_top_linux.go @@ -1,3 +1,4 @@ +//go:build linux // +build linux package libpod diff --git a/libpod/define/containerstate.go b/libpod/define/containerstate.go index 23ba1f451..9ad3aec08 100644 --- a/libpod/define/containerstate.go +++ b/libpod/define/containerstate.go @@ -138,7 +138,6 @@ type ContainerStats struct { CPU float64 CPUNano uint64 CPUSystemNano uint64 - DataPoints int64 SystemNano uint64 MemUsage uint64 MemLimit uint64 diff --git a/libpod/doc.go b/libpod/doc.go new file mode 100644 index 000000000..948153181 --- /dev/null +++ b/libpod/doc.go @@ -0,0 +1,11 @@ +// The libpod library is not stable and we do not support use cases outside of +// this repository. The API can change at any time even with patch releases. +// +// If you need a stable interface Podman provides a HTTP API which follows semver, +// please see https://docs.podman.io/en/latest/markdown/podman-system-service.1.html +// to start the api service and https://docs.podman.io/en/latest/_static/api.html +// for the API reference. +// +// We also provide stable go bindings to talk to the api service from another go +// program, see the pkg/bindings directory. +package libpod diff --git a/libpod/events/events_unsupported.go b/libpod/events/events_unsupported.go index 5b32a1b4b..25c175524 100644 --- a/libpod/events/events_unsupported.go +++ b/libpod/events/events_unsupported.go @@ -1,3 +1,4 @@ +//go:build !linux // +build !linux package events diff --git a/libpod/events/journal_linux.go b/libpod/events/journal_linux.go index cc63df120..866042a4c 100644 --- a/libpod/events/journal_linux.go +++ b/libpod/events/journal_linux.go @@ -1,3 +1,4 @@ +//go:build systemd // +build systemd package events diff --git a/libpod/events/journal_unsupported.go b/libpod/events/journal_unsupported.go index 004efdab2..6ed39792b 100644 --- a/libpod/events/journal_unsupported.go +++ b/libpod/events/journal_unsupported.go @@ -1,3 +1,4 @@ +//go:build !systemd // +build !systemd package events diff --git a/libpod/events/logfile.go b/libpod/events/logfile.go index be2aaacca..76173cde9 100644 --- a/libpod/events/logfile.go +++ b/libpod/events/logfile.go @@ -9,6 +9,7 @@ import ( "github.com/containers/podman/v4/pkg/util" "github.com/containers/storage/pkg/lockfile" "github.com/pkg/errors" + "github.com/sirupsen/logrus" ) // EventLogFile is the structure for event writing to a logfile. It contains the eventer @@ -59,7 +60,9 @@ func (e EventLogFile) Read(ctx context.Context, options ReadOptions) error { } go func() { time.Sleep(time.Until(untilTime)) - t.Stop() + if err := t.Stop(); err != nil { + logrus.Errorf("Stopping logger: %v", err) + } }() } funcDone := make(chan bool) diff --git a/libpod/linkmode/linkmode_dynamic.go b/libpod/linkmode/linkmode_dynamic.go index 6d51d60e0..f020fa53e 100644 --- a/libpod/linkmode/linkmode_dynamic.go +++ b/libpod/linkmode/linkmode_dynamic.go @@ -1,3 +1,4 @@ +//go:build !static // +build !static package linkmode diff --git a/libpod/linkmode/linkmode_static.go b/libpod/linkmode/linkmode_static.go index 2db083f4a..b181ad285 100644 --- a/libpod/linkmode/linkmode_static.go +++ b/libpod/linkmode/linkmode_static.go @@ -1,3 +1,4 @@ +//go:build static // +build static package linkmode diff --git a/libpod/lock/shm/shm_lock.go b/libpod/lock/shm/shm_lock.go index fea02a619..c7f4d1bc5 100644 --- a/libpod/lock/shm/shm_lock.go +++ b/libpod/lock/shm/shm_lock.go @@ -1,3 +1,4 @@ +//go:build linux && cgo // +build linux,cgo package shm diff --git a/libpod/lock/shm/shm_lock_nocgo.go b/libpod/lock/shm/shm_lock_nocgo.go index 627344d9c..31fc02223 100644 --- a/libpod/lock/shm/shm_lock_nocgo.go +++ b/libpod/lock/shm/shm_lock_nocgo.go @@ -1,3 +1,4 @@ +//go:build linux && !cgo // +build linux,!cgo package shm diff --git a/libpod/lock/shm/shm_lock_test.go b/libpod/lock/shm/shm_lock_test.go index cb83c7c2c..8dfc849d6 100644 --- a/libpod/lock/shm/shm_lock_test.go +++ b/libpod/lock/shm/shm_lock_test.go @@ -1,3 +1,4 @@ +//go:build linux // +build linux package shm diff --git a/libpod/lock/shm_lock_manager_linux.go b/libpod/lock/shm_lock_manager_linux.go index 8f3b6df7f..3076cd864 100644 --- a/libpod/lock/shm_lock_manager_linux.go +++ b/libpod/lock/shm_lock_manager_linux.go @@ -1,3 +1,4 @@ +//go:build linux // +build linux package lock diff --git a/libpod/lock/shm_lock_manager_unsupported.go b/libpod/lock/shm_lock_manager_unsupported.go index 1d6e3fcbd..d578359ab 100644 --- a/libpod/lock/shm_lock_manager_unsupported.go +++ b/libpod/lock/shm_lock_manager_unsupported.go @@ -1,3 +1,4 @@ +//go:build !linux // +build !linux package lock diff --git a/libpod/mounts_linux.go b/libpod/mounts_linux.go index e6aa09eac..f6945b3a3 100644 --- a/libpod/mounts_linux.go +++ b/libpod/mounts_linux.go @@ -1,3 +1,4 @@ +//go:build linux // +build linux package libpod diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go index 7fd80927b..20c8059a5 100644 --- a/libpod/networking_linux.go +++ b/libpod/networking_linux.go @@ -1,3 +1,4 @@ +//go:build linux // +build linux package libpod @@ -1148,7 +1149,7 @@ func (c *Container) inspectJoinedNetworkNS(networkns string) (q types.StatusBloc // result func resultToBasicNetworkConfig(result types.StatusBlock) (define.InspectBasicNetworkConfig, error) { config := define.InspectBasicNetworkConfig{} - interfaceNames := make([]string, len(result.Interfaces)) + interfaceNames := make([]string, 0, len(result.Interfaces)) for interfaceName := range result.Interfaces { interfaceNames = append(interfaceNames, interfaceName) } diff --git a/libpod/networking_machine.go b/libpod/networking_machine.go index ca759b893..d2a6b7cfa 100644 --- a/libpod/networking_machine.go +++ b/libpod/networking_machine.go @@ -11,6 +11,7 @@ import ( "net/http" "strconv" "strings" + "time" "github.com/containers/common/libnetwork/types" "github.com/sirupsen/logrus" @@ -36,7 +37,18 @@ func requestMachinePorts(expose bool, ports []types.PortMapping) error { url = url + "unexpose" } ctx := context.Background() - client := &http.Client{} + client := &http.Client{ + Transport: &http.Transport{ + // make sure to not set a proxy here so explicitly ignore the proxy + // since we want to talk directly to gvproxy + // https://github.com/containers/podman/issues/13628 + Proxy: nil, + MaxIdleConns: 50, + IdleConnTimeout: 30 * time.Second, + TLSHandshakeTimeout: 10 * time.Second, + ExpectContinueTimeout: 1 * time.Second, + }, + } buf := new(bytes.Buffer) for num, port := range ports { protocols := strings.Split(port.Protocol, ",") @@ -78,7 +90,6 @@ func requestMachinePorts(expose bool, ports []types.PortMapping) error { } func makeMachineRequest(ctx context.Context, client *http.Client, url string, buf io.Reader) error { - //var buf io.ReadWriter req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, buf) if err != nil { return err diff --git a/libpod/networking_slirp4netns.go b/libpod/networking_slirp4netns.go index cc44f78f7..a7a002657 100644 --- a/libpod/networking_slirp4netns.go +++ b/libpod/networking_slirp4netns.go @@ -1,3 +1,4 @@ +//go:build linux // +build linux package libpod diff --git a/libpod/oci_attach_linux.go b/libpod/oci_attach_linux.go index 1ee664e81..b5eabec1f 100644 --- a/libpod/oci_attach_linux.go +++ b/libpod/oci_attach_linux.go @@ -1,4 +1,5 @@ -//+build linux +//go:build linux +// +build linux package libpod diff --git a/libpod/oci_conmon_exec_linux.go b/libpod/oci_conmon_exec_linux.go index aa970bbde..65123b37e 100644 --- a/libpod/oci_conmon_exec_linux.go +++ b/libpod/oci_conmon_exec_linux.go @@ -758,11 +758,14 @@ func prepareProcessExec(c *Container, options *ExecOptions, env []string, sessio } else { pspec.Capabilities.Bounding = ctrSpec.Process.Capabilities.Bounding } + + // Always unset the inheritable capabilities similarly to what the Linux kernel does + // They are used only when using capabilities with uid != 0. + pspec.Capabilities.Inheritable = []string{} + if execUser.Uid == 0 { pspec.Capabilities.Effective = pspec.Capabilities.Bounding - pspec.Capabilities.Inheritable = pspec.Capabilities.Bounding pspec.Capabilities.Permitted = pspec.Capabilities.Bounding - pspec.Capabilities.Ambient = pspec.Capabilities.Bounding } else { if user == c.config.User { pspec.Capabilities.Effective = ctrSpec.Process.Capabilities.Effective diff --git a/libpod/oci_conmon_linux.go b/libpod/oci_conmon_linux.go index a328f7621..38bf85834 100644 --- a/libpod/oci_conmon_linux.go +++ b/libpod/oci_conmon_linux.go @@ -1,3 +1,4 @@ +//go:build linux // +build linux package libpod @@ -749,7 +750,7 @@ func openControlFile(ctr *Container, parentDir string) (*os.File, error) { for i := 0; i < 600; i++ { controlFile, err := os.OpenFile(controlPath, unix.O_WRONLY|unix.O_NONBLOCK, 0) if err == nil { - return controlFile, err + return controlFile, nil } if !isRetryable(err) { return nil, errors.Wrapf(err, "could not open ctl file for terminal resize for container %s", ctr.ID()) @@ -1014,7 +1015,8 @@ func (r *ConmonOCIRuntime) getLogTag(ctr *Container) (string, error) { } data, err := ctr.inspectLocked(false) if err != nil { - return "", nil + // FIXME: this error should probably be returned + return "", nil // nolint: nilerr } tmpl, err := template.New("container").Parse(logTag) if err != nil { @@ -1199,7 +1201,7 @@ func (r *ConmonOCIRuntime) createOCIContainer(ctr *Container, restoreOptions *Co cmd.ExtraFiles = append(cmd.ExtraFiles, childSyncPipe, childStartPipe) if r.reservePorts && !rootless.IsRootless() && !ctr.config.NetMode.IsSlirp4netns() { - ports, err := bindPorts(ctr.config.PortMappings) + ports, err := bindPorts(ctr.convertPortMappings()) if err != nil { return 0, err } @@ -1370,7 +1372,7 @@ func (r *ConmonOCIRuntime) sharedConmonArgs(ctr *Container, cuuid, bundlePath, p case define.JSONLogging: fallthrough //lint:ignore ST1015 the default case has to be here - default: //nolint-stylecheck + default: //nolint:stylecheck // No case here should happen except JSONLogging, but keep this here in case the options are extended logrus.Errorf("%s logging specified but not supported. Choosing k8s-file logging instead", ctr.LogDriver()) fallthrough @@ -1585,17 +1587,19 @@ func readConmonPipeData(runtimeName string, pipe *os.File, ociLog string) (int, var si *syncInfo rdr := bufio.NewReader(pipe) b, err := rdr.ReadBytes('\n') - if err != nil { + // ignore EOF here, error is returned even when data was read + // if it is no valid json unmarshal will fail below + if err != nil && !errors.Is(err, io.EOF) { ch <- syncStruct{err: err} } if err := json.Unmarshal(b, &si); err != nil { - ch <- syncStruct{err: err} + ch <- syncStruct{err: fmt.Errorf("conmon bytes %q: %w", string(b), err)} return } ch <- syncStruct{si: si} }() - data := -1 + data := -1 //nolint: wastedassign select { case ss := <-ch: if ss.err != nil { diff --git a/libpod/pod.go b/libpod/pod.go index 6273ff247..ed2d97b37 100644 --- a/libpod/pod.go +++ b/libpod/pod.go @@ -422,10 +422,6 @@ type PodContainerStats struct { // GetPodStats returns the stats for each of its containers func (p *Pod) GetPodStats(previousContainerStats map[string]*define.ContainerStats) (map[string]*define.ContainerStats, error) { - var ( - ok bool - prevStat *define.ContainerStats - ) p.lock.Lock() defer p.lock.Unlock() @@ -438,10 +434,7 @@ func (p *Pod) GetPodStats(previousContainerStats map[string]*define.ContainerSta } newContainerStats := make(map[string]*define.ContainerStats) for _, c := range containers { - if prevStat, ok = previousContainerStats[c.ID()]; !ok { - prevStat = &define.ContainerStats{} - } - newStats, err := c.GetContainerStats(prevStat) + newStats, err := c.GetContainerStats(previousContainerStats[c.ID()]) // If the container wasn't running, don't include it // but also suppress the error if err != nil && errors.Cause(err) != define.ErrCtrStateInvalid { diff --git a/libpod/pod_top_linux.go b/libpod/pod_top_linux.go index 43823a106..83a070807 100644 --- a/libpod/pod_top_linux.go +++ b/libpod/pod_top_linux.go @@ -1,3 +1,4 @@ +//go:build linux // +build linux package libpod diff --git a/libpod/runtime_migrate.go b/libpod/runtime_migrate.go index 32fdc7b5d..fccd5bdee 100644 --- a/libpod/runtime_migrate.go +++ b/libpod/runtime_migrate.go @@ -1,3 +1,4 @@ +//go:build linux // +build linux package libpod diff --git a/libpod/runtime_pod_linux.go b/libpod/runtime_pod_linux.go index 230491c1a..2bbccfdf6 100644 --- a/libpod/runtime_pod_linux.go +++ b/libpod/runtime_pod_linux.go @@ -6,6 +6,7 @@ package libpod import ( "context" "fmt" + "os" "path" "path/filepath" "strings" @@ -239,7 +240,7 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool, // Don't try if we failed to retrieve the cgroup if err == nil { - if err := conmonCgroup.Update(resLimits); err != nil { + if err := conmonCgroup.Update(resLimits); err != nil && !os.IsNotExist(err) { logrus.Warnf("Error updating pod %s conmon cgroup PID limit: %v", p.ID(), err) } } diff --git a/libpod/runtime_volume_linux.go b/libpod/runtime_volume_linux.go index c4fe3db90..3d585fa7a 100644 --- a/libpod/runtime_volume_linux.go +++ b/libpod/runtime_volume_linux.go @@ -1,3 +1,4 @@ +//go:build linux // +build linux package libpod diff --git a/libpod/stats.go b/libpod/stats.go index dbb10a27e..25baa378d 100644 --- a/libpod/stats.go +++ b/libpod/stats.go @@ -1,3 +1,4 @@ +//go:build linux // +build linux package libpod @@ -13,7 +14,9 @@ import ( "github.com/pkg/errors" ) -// GetContainerStats gets the running stats for a given container +// GetContainerStats gets the running stats for a given container. +// The previousStats is used to correctly calculate cpu percentages. You +// should pass nil if there is no previous stat for this container. func (c *Container) GetContainerStats(previousStats *define.ContainerStats) (*define.ContainerStats, error) { stats := new(define.ContainerStats) stats.ContainerID = c.ID() @@ -35,6 +38,14 @@ func (c *Container) GetContainerStats(previousStats *define.ContainerStats) (*de return stats, define.ErrCtrStateInvalid } + if previousStats == nil { + previousStats = &define.ContainerStats{ + // if we have no prev stats use the container start time as prev time + // otherwise we cannot correctly calculate the CPU percentage + SystemNano: uint64(c.state.StartedTime.UnixNano()), + } + } + cgroupPath, err := c.cGroupPath() if err != nil { return nil, err @@ -66,8 +77,8 @@ func (c *Container) GetContainerStats(previousStats *define.ContainerStats) (*de 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 + // calc the average cpu usage for the time the container is running + stats.AvgCPU = calculateCPUPercent(cgroupStats, 0, now, uint64(c.state.StartedTime.UnixNano())) stats.MemUsage = cgroupStats.Memory.Usage.Usage stats.MemLimit = c.getMemLimit() stats.MemPerc = (float64(stats.MemUsage) / float64(stats.MemLimit)) * 100 @@ -145,9 +156,3 @@ 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/util_linux.go b/libpod/util_linux.go index dd115c7fb..fe98056dc 100644 --- a/libpod/util_linux.go +++ b/libpod/util_linux.go @@ -1,3 +1,4 @@ +//go:build linux // +build linux package libpod diff --git a/nix/default-arm64.nix b/nix/default-arm64.nix deleted file mode 100644 index fa076f27d..000000000 --- a/nix/default-arm64.nix +++ /dev/null @@ -1,90 +0,0 @@ -let - pkgs = (import ./nixpkgs.nix { - crossSystem = { - config = "aarch64-unknown-linux-gnu"; - }; - config = { - packageOverrides = pkg: { - gpgme = (static pkg.gpgme); - libassuan = (static pkg.libassuan); - libgpgerror = (static pkg.libgpgerror); - libseccomp = (static pkg.libseccomp); - glib = (static pkg.glib).overrideAttrs (x: { - outputs = [ "bin" "out" "dev" ]; - mesonFlags = [ - "-Ddefault_library=static" - "-Ddevbindir=${placeholder ''dev''}/bin" - "-Dgtk_doc=false" - "-Dnls=disabled" - ]; - postInstall = '' - moveToOutput "share/glib-2.0" "$dev" - substituteInPlace "$dev/bin/gdbus-codegen" --replace "$out" "$dev" - sed -i "$dev/bin/glib-gettextize" -e "s|^gettext_dir=.*|gettext_dir=$dev/share/glib-2.0/gettext|" - sed '1i#line 1 "${x.pname}-${x.version}/include/glib-2.0/gobject/gobjectnotifyqueue.c"' \ - -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" - "--disable-libudev" - "--disable-libusb" - ]; - buildInputs = [ pkgs.python3 pkgs.dbus ]; - }); - systemd = (static pkg.systemd).overrideAttrs (x: { - outputs = [ "out" "dev" ]; - mesonFlags = x.mesonFlags ++ [ - "-Dglib=false" - "-Dstatic-libsystemd=true" - ]; - }); - }; - }; - }); - - static = pkg: pkg.overrideAttrs (x: { - doCheck = false; - configureFlags = (x.configureFlags or [ ]) ++ [ - "--without-shared" - "--disable-shared" - ]; - dontDisableStatic = true; - enableSharedExecutables = false; - enableStatic = true; - }); - - self = with pkgs; buildGoModule rec { - name = "podman"; - src = builtins.filterSource - (path: type: !(type == "directory" && baseNameOf path == "bin")) ./..; - vendorSha256 = null; - doCheck = false; - enableParallelBuilding = true; - outputs = [ "out" ]; - 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' - export EXTRA_LDFLAGS='-s -w -linkmode external -extldflags "-static -lm"' - export BUILDTAGS='static netgo osusergo exclude_graphdriver_btrfs exclude_graphdriver_devicemapper seccomp apparmor selinux' - export CGO_ENABLED=1 - ''; - buildPhase = '' - patchShebangs . - make bin/podman - make bin/podman-remote - make bin/rootlessport - ''; - installPhase = '' - install -Dm755 bin/podman $out/bin/podman - install -Dm755 bin/podman-remote $out/bin/podman-remote - install -Dm755 bin/rootlessport $out/libexec/podman/rootlessport - ''; - }; -in -self diff --git a/nix/default.nix b/nix/default.nix deleted file mode 100644 index 30ae21503..000000000 --- a/nix/default.nix +++ /dev/null @@ -1,88 +0,0 @@ -{ system ? builtins.currentSystem }: -let - pkgs = (import ./nixpkgs.nix { - config = { - packageOverrides = pkg: { - gpgme = (static pkg.gpgme); - libassuan = (static pkg.libassuan); - libgpgerror = (static pkg.libgpgerror); - libseccomp = (static pkg.libseccomp); - glib = (static pkg.glib).overrideAttrs (x: { - outputs = [ "bin" "out" "dev" ]; - mesonFlags = [ - "-Ddefault_library=static" - "-Ddevbindir=${placeholder ''dev''}/bin" - "-Dgtk_doc=false" - "-Dnls=disabled" - ]; - postInstall = '' - moveToOutput "share/glib-2.0" "$dev" - substituteInPlace "$dev/bin/gdbus-codegen" --replace "$out" "$dev" - sed -i "$dev/bin/glib-gettextize" -e "s|^gettext_dir=.*|gettext_dir=$dev/share/glib-2.0/gettext|" - sed '1i#line 1 "${x.pname}-${x.version}/include/glib-2.0/gobject/gobjectnotifyqueue.c"' \ - -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" - "--disable-libudev" - "--disable-libusb" - ]; - buildInputs = [ pkgs.python3 pkgs.dbus ]; - }); - systemd = (static pkg.systemd).overrideAttrs (x: { - outputs = [ "out" "dev" ]; - mesonFlags = x.mesonFlags ++ [ - "-Dglib=false" - "-Dstatic-libsystemd=true" - ]; - }); - }; - }; - }); - - static = pkg: pkg.overrideAttrs (x: { - doCheck = false; - configureFlags = (x.configureFlags or [ ]) ++ [ - "--without-shared" - "--disable-shared" - ]; - dontDisableStatic = true; - enableSharedExecutables = false; - enableStatic = true; - }); - - self = with pkgs; buildGoModule rec { - name = "podman"; - src = builtins.filterSource - (path: type: !(type == "directory" && baseNameOf path == "bin")) ./..; - vendorSha256 = null; - doCheck = false; - enableParallelBuilding = true; - outputs = [ "out" ]; - 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' - export EXTRA_LDFLAGS='-s -w -linkmode external -extldflags "-static -lm"' - export BUILDTAGS='static netgo osusergo exclude_graphdriver_btrfs exclude_graphdriver_devicemapper seccomp apparmor selinux' - export CGO_ENABLED=1 - ''; - buildPhase = '' - patchShebangs . - make bin/podman - make bin/podman-remote - make bin/rootlessport - ''; - installPhase = '' - install -Dm755 bin/podman $out/bin/podman - install -Dm755 bin/podman-remote $out/bin/podman-remote - install -Dm755 bin/rootlessport $out/libexec/podman/rootlessport - ''; - }; -in -self diff --git a/nix/nixpkgs.json b/nix/nixpkgs.json deleted file mode 100644 index efcfe202e..000000000 --- a/nix/nixpkgs.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "url": "https://github.com/nixos/nixpkgs", - "rev": "2a96414d7e350160a33ed0978449c9ff5b5a6eb3", - "date": "2021-07-13T18:21:47+02:00", - "path": "/nix/store/2ai9q8ac6vxb2rrngdz82y8jxnk15cvm-nixpkgs", - "sha256": "1dzrfqdjq3yq5jjskiqflzy58l2xx6059gay9p1k07zrlm1wigy5", - "fetchSubmodules": false, - "deepClone": false, - "leaveDotGit": false -} diff --git a/nix/nixpkgs.nix b/nix/nixpkgs.nix deleted file mode 100644 index 11c20380a..000000000 --- a/nix/nixpkgs.nix +++ /dev/null @@ -1,9 +0,0 @@ -let - json = builtins.fromJSON (builtins.readFile ./nixpkgs.json); - nixpkgs = import (builtins.fetchTarball { - name = "nixos-unstable"; - url = "${json.url}/archive/${json.rev}.tar.gz"; - inherit (json) sha256; - }); -in -nixpkgs diff --git a/pkg/annotations/annotations.go b/pkg/annotations/annotations.go index 8badab20d..a22222f10 100644 --- a/pkg/annotations/annotations.go +++ b/pkg/annotations/annotations.go @@ -1,122 +1,122 @@ package annotations const ( - // Annotations carries the received Kubelet annotations + // Annotations carries the received Kubelet annotations. Annotations = "io.kubernetes.cri-o.Annotations" - // ContainerID is the container ID annotation + // ContainerID is the container ID annotation. ContainerID = "io.kubernetes.cri-o.ContainerID" - // ContainerName is the container name annotation + // ContainerName is the container name annotation. ContainerName = "io.kubernetes.cri-o.ContainerName" - // ContainerType is the container type (sandbox or container) annotation + // ContainerType is the container type (sandbox or container) annotation. ContainerType = "io.kubernetes.cri-o.ContainerType" - // Created is the container creation time annotation + // Created is the container creation time annotation. Created = "io.kubernetes.cri-o.Created" - // HostName is the container host name annotation + // HostName is the container host name annotation. HostName = "io.kubernetes.cri-o.HostName" - // CgroupParent is the sandbox cgroup parent + // CgroupParent is the sandbox cgroup parent. CgroupParent = "io.kubernetes.cri-o.CgroupParent" - // IP is the container ipv4 or ipv6 address + // IP is the container ipv4 or ipv6 address. IP = "io.kubernetes.cri-o.IP" - // NamespaceOptions store the options for namespaces + // NamespaceOptions store the options for namespaces. NamespaceOptions = "io.kubernetes.cri-o.NamespaceOptions" - // SeccompProfilePath is the node seccomp profile path + // SeccompProfilePath is the node seccomp profile path. SeccompProfilePath = "io.kubernetes.cri-o.SeccompProfilePath" - // Image is the container image ID annotation + // Image is the container image ID annotation. Image = "io.kubernetes.cri-o.Image" - // ImageName is the container image name annotation + // ImageName is the container image name annotation. ImageName = "io.kubernetes.cri-o.ImageName" - // ImageRef is the container image ref annotation + // ImageRef is the container image ref annotation. ImageRef = "io.kubernetes.cri-o.ImageRef" - // KubeName is the kubernetes name annotation + // KubeName is the kubernetes name annotation. KubeName = "io.kubernetes.cri-o.KubeName" - // PortMappings holds the port mappings for the sandbox + // PortMappings holds the port mappings for the sandbox. PortMappings = "io.kubernetes.cri-o.PortMappings" - // Labels are the kubernetes labels annotation + // Labels are the kubernetes labels annotation. Labels = "io.kubernetes.cri-o.Labels" - // LogPath is the container logging path annotation + // LogPath is the container logging path annotation. LogPath = "io.kubernetes.cri-o.LogPath" - // Metadata is the container metadata annotation + // Metadata is the container metadata annotation. Metadata = "io.kubernetes.cri-o.Metadata" - // Name is the pod name annotation + // Name is the pod name annotation. Name = "io.kubernetes.cri-o.Name" - // Namespace is the pod namespace annotation + // Namespace is the pod namespace annotation. Namespace = "io.kubernetes.cri-o.Namespace" - // PrivilegedRuntime is the annotation for the privileged runtime path + // PrivilegedRuntime is the annotation for the privileged runtime path. PrivilegedRuntime = "io.kubernetes.cri-o.PrivilegedRuntime" - // ResolvPath is the resolver configuration path annotation + // ResolvPath is the resolver configuration path annotation. ResolvPath = "io.kubernetes.cri-o.ResolvPath" - // HostnamePath is the path to /etc/hostname to bind mount annotation + // HostnamePath is the path to /etc/hostname to bind mount annotation. HostnamePath = "io.kubernetes.cri-o.HostnamePath" - // SandboxID is the sandbox ID annotation + // SandboxID is the sandbox ID annotation. SandboxID = "io.kubernetes.cri-o.SandboxID" - // SandboxName is the sandbox name annotation + // SandboxName is the sandbox name annotation. SandboxName = "io.kubernetes.cri-o.SandboxName" - // ShmPath is the shared memory path annotation + // ShmPath is the shared memory path annotation. ShmPath = "io.kubernetes.cri-o.ShmPath" - // MountPoint is the mount point of the container rootfs + // MountPoint is the mount point of the container rootfs. MountPoint = "io.kubernetes.cri-o.MountPoint" - // RuntimeHandler is the annotation for runtime handler + // RuntimeHandler is the annotation for runtime handler. RuntimeHandler = "io.kubernetes.cri-o.RuntimeHandler" - // TTY is the terminal path annotation + // TTY is the terminal path annotation. TTY = "io.kubernetes.cri-o.TTY" - // Stdin is the stdin annotation + // Stdin is the stdin annotation. Stdin = "io.kubernetes.cri-o.Stdin" - // StdinOnce is the stdin_once annotation + // StdinOnce is the stdin_once annotation. StdinOnce = "io.kubernetes.cri-o.StdinOnce" - // Volumes is the volumes annotation + // Volumes is the volumes annotation. Volumes = "io.kubernetes.cri-o.Volumes" - // HostNetwork indicates whether the host network namespace is used or not + // HostNetwork indicates whether the host network namespace is used or not. HostNetwork = "io.kubernetes.cri-o.HostNetwork" - // CNIResult is the JSON string representation of the Result from CNI + // CNIResult is the JSON string representation of the Result from CNI. CNIResult = "io.kubernetes.cri-o.CNIResult" // ContainerManager is the annotation key for indicating the creator and - // manager of the container + // manager of the container. ContainerManager = "io.container.manager" ) // ContainerType values const ( - // ContainerTypeSandbox represents a pod sandbox container + // ContainerTypeSandbox represents a pod sandbox container. ContainerTypeSandbox = "sandbox" - // ContainerTypeContainer represents a container running within a pod + // ContainerTypeContainer represents a container running within a pod. ContainerTypeContainer = "container" ) // ContainerManagerLibpod indicates that libpod created and manages the -// container +// container. const ContainerManagerLibpod = "libpod" diff --git a/pkg/api/handlers/compat/containers_stats.go b/pkg/api/handlers/compat/containers_stats.go index 99f14d02f..77b16b03e 100644 --- a/pkg/api/handlers/compat/containers_stats.go +++ b/pkg/api/handlers/compat/containers_stats.go @@ -56,7 +56,7 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) { return } - stats, err := ctnr.GetContainerStats(&define.ContainerStats{}) + stats, err := ctnr.GetContainerStats(nil) if err != nil { utils.InternalServerError(w, errors.Wrapf(err, "failed to obtain Container %s stats", name)) return diff --git a/pkg/api/handlers/compat/images_prune.go b/pkg/api/handlers/compat/images_prune.go index 88776dc49..c0be9da7d 100644 --- a/pkg/api/handlers/compat/images_prune.go +++ b/pkg/api/handlers/compat/images_prune.go @@ -43,7 +43,7 @@ func PruneImages(w http.ResponseWriter, r *http.Request) { return } - idr := make([]types.ImageDeleteResponseItem, len(imagePruneReports)) + idr := make([]types.ImageDeleteResponseItem, 0, len(imagePruneReports)) var reclaimedSpace uint64 var errorMsg bytes.Buffer for _, p := range imagePruneReports { diff --git a/pkg/api/handlers/compat/networks.go b/pkg/api/handlers/compat/networks.go index eb1a5d59c..89d914e0a 100644 --- a/pkg/api/handlers/compat/networks.go +++ b/pkg/api/handlers/compat/networks.go @@ -242,7 +242,7 @@ func CreateNetwork(w http.ResponseWriter, r *http.Request) { body := struct { ID string `json:"Id"` - Warning []string + Warning string }{ ID: newNetwork.ID, } diff --git a/pkg/api/handlers/libpod/images.go b/pkg/api/handlers/libpod/images.go index eb9fb12a6..cddf4c205 100644 --- a/pkg/api/handlers/libpod/images.go +++ b/pkg/api/handlers/libpod/images.go @@ -367,10 +367,13 @@ func ImagesImport(w http.ResponseWriter, r *http.Request) { runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime) decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder) query := struct { - Changes []string `schema:"changes"` - Message string `schema:"message"` - Reference string `schema:"reference"` - URL string `schema:"URL"` + Changes []string `schema:"changes"` + Message string `schema:"message"` + Reference string `schema:"reference"` + URL string `schema:"URL"` + OS string `schema:"OS"` + Architecture string `schema:"Architecture"` + Variant string `schema:"Variant"` }{ // Add defaults here once needed. } @@ -402,10 +405,13 @@ func ImagesImport(w http.ResponseWriter, r *http.Request) { imageEngine := abi.ImageEngine{Libpod: runtime} importOptions := entities.ImageImportOptions{ - Changes: query.Changes, - Message: query.Message, - Reference: query.Reference, - Source: source, + Changes: query.Changes, + Message: query.Message, + Reference: query.Reference, + OS: query.OS, + Architecture: query.Architecture, + Variant: query.Variant, + Source: source, } report, err := imageEngine.Import(r.Context(), importOptions) if err != nil { @@ -613,6 +619,7 @@ func ImagesBatchRemove(w http.ResponseWriter, r *http.Request) { query := struct { All bool `schema:"all"` Force bool `schema:"force"` + Ignore bool `schema:"ignore"` Images []string `schema:"images"` }{} @@ -621,7 +628,7 @@ func ImagesBatchRemove(w http.ResponseWriter, r *http.Request) { return } - opts := entities.ImageRemoveOptions{All: query.All, Force: query.Force} + opts := entities.ImageRemoveOptions{All: query.All, Force: query.Force, Ignore: query.Ignore} imageEngine := abi.ImageEngine{Libpod: runtime} rmReport, rmErrors := imageEngine.Remove(r.Context(), query.Images, opts) strErrs := errorhandling.ErrorsToStrings(rmErrors) diff --git a/pkg/api/handlers/libpod/manifests.go b/pkg/api/handlers/libpod/manifests.go index 250736579..ad662f32c 100644 --- a/pkg/api/handlers/libpod/manifests.go +++ b/pkg/api/handlers/libpod/manifests.go @@ -401,7 +401,7 @@ func ManifestModify(w http.ResponseWriter, r *http.Request) { case len(report.Errors) > 0 && len(report.Images) > 0: statusCode = http.StatusConflict case len(report.Errors) > 0: - statusCode = http.StatusInternalServerError + statusCode = http.StatusBadRequest } utils.WriteResponse(w, statusCode, report) } diff --git a/pkg/api/handlers/libpod/play.go b/pkg/api/handlers/libpod/play.go index aed889298..ca9ada761 100644 --- a/pkg/api/handlers/libpod/play.go +++ b/pkg/api/handlers/libpod/play.go @@ -1,11 +1,8 @@ package libpod import ( - "io" - "io/ioutil" "net" "net/http" - "os" "github.com/containers/image/v5/types" "github.com/containers/podman/v4/libpod" @@ -16,7 +13,6 @@ import ( "github.com/containers/podman/v4/pkg/domain/infra/abi" "github.com/gorilla/schema" "github.com/pkg/errors" - "github.com/sirupsen/logrus" ) func PlayKube(w http.ResponseWriter, r *http.Request) { @@ -62,28 +58,6 @@ func PlayKube(w http.ResponseWriter, r *http.Request) { staticMACs = append(staticMACs, mac) } - // Fetch the K8s YAML file from the body, and copy it to a temp file. - tmpfile, err := ioutil.TempFile("", "libpod-play-kube.yml") - if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to create tempfile")) - return - } - defer func() { - if err := os.Remove(tmpfile.Name()); err != nil { - logrus.Warn(err) - } - }() - if _, err := io.Copy(tmpfile, r.Body); err != nil && err != io.EOF { - if err := tmpfile.Close(); err != nil { - logrus.Warn(err) - } - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to write archive to temporary file")) - return - } - if err := tmpfile.Close(); err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "error closing temporary file")) - return - } authConf, authfile, err := auth.GetCredentials(r) if err != nil { utils.Error(w, http.StatusBadRequest, err) @@ -116,7 +90,8 @@ func PlayKube(w http.ResponseWriter, r *http.Request) { if _, found := r.URL.Query()["start"]; found { options.Start = types.NewOptionalBool(query.Start) } - report, err := containerEngine.PlayKube(r.Context(), tmpfile.Name(), options) + report, err := containerEngine.PlayKube(r.Context(), r.Body, options) + _ = r.Body.Close() if err != nil { utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "error playing YAML file")) return @@ -126,30 +101,10 @@ func PlayKube(w http.ResponseWriter, r *http.Request) { func PlayKubeDown(w http.ResponseWriter, r *http.Request) { runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime) - tmpfile, err := ioutil.TempFile("", "libpod-play-kube.yml") - if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to create tempfile")) - return - } - defer func() { - if err := os.Remove(tmpfile.Name()); err != nil { - logrus.Warn(err) - } - }() - if _, err := io.Copy(tmpfile, r.Body); err != nil && err != io.EOF { - if err := tmpfile.Close(); err != nil { - logrus.Warn(err) - } - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to write archive to temporary file")) - return - } - if err := tmpfile.Close(); err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "error closing temporary file")) - return - } containerEngine := abi.ContainerEngine{Libpod: runtime} options := new(entities.PlayKubeDownOptions) - report, err := containerEngine.PlayKubeDown(r.Context(), tmpfile.Name(), *options) + report, err := containerEngine.PlayKubeDown(r.Context(), r.Body, *options) + _ = r.Body.Close() if err != nil { utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "error tearing down YAML file")) return diff --git a/pkg/api/handlers/utils/images.go b/pkg/api/handlers/utils/images.go index 15b16bc43..7154f5616 100644 --- a/pkg/api/handlers/utils/images.go +++ b/pkg/api/handlers/utils/images.go @@ -63,7 +63,7 @@ func IsRegistryReference(name string) error { imageRef, err := alltransports.ParseImageName(name) if err != nil { // No supported transport -> assume a docker-stype reference. - return nil + return nil // nolint: nilerr } if imageRef.Transport().Name() == docker.Transport.Name() { return nil diff --git a/pkg/api/server/register_exec.go b/pkg/api/server/register_exec.go index c19ca7859..90136463d 100644 --- a/pkg/api/server/register_exec.go +++ b/pkg/api/server/register_exec.go @@ -169,7 +169,7 @@ func (s *APIServer) registerExecHandlers(r *mux.Router) error { // - application/json // responses: // 200: - // description: no error + // $ref: "#/responses/InspectExecSession" // 404: // $ref: "#/responses/NoSuchExecInstance" // 500: diff --git a/pkg/api/server/register_images.go b/pkg/api/server/register_images.go index 017310f12..89f808e7d 100644 --- a/pkg/api/server/register_images.go +++ b/pkg/api/server/register_images.go @@ -944,6 +944,10 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // name: force // description: Force image removal (including containers using the images). // type: boolean + // - in: query + // name: ignore + // description: Ignore if a specified image does not exist and do not throw an error. + // type: boolean // produces: // - application/json // responses: diff --git a/pkg/api/server/register_networks.go b/pkg/api/server/register_networks.go index 4466c938f..b900aa953 100644 --- a/pkg/api/server/register_networks.go +++ b/pkg/api/server/register_networks.go @@ -105,8 +105,15 @@ func (s *APIServer) registerNetworkHandlers(r *mux.Router) error { // schema: // $ref: "#/definitions/NetworkCreateRequest" // responses: - // 200: - // $ref: "#/responses/CompatNetworkCreate" + // 201: + // description: network created + // schema: + // type: object + // properties: + // Id: + // type: string + // Warning: + // type: string // 400: // $ref: "#/responses/BadParamError" // 500: diff --git a/pkg/api/server/swagger.go b/pkg/api/server/swagger.go index 9b652be87..6cf89581a 100644 --- a/pkg/api/server/swagger.go +++ b/pkg/api/server/swagger.go @@ -235,3 +235,12 @@ type swagSystemAuthResponse struct { entities.AuthReport } } + +// Inspect response +// swagger:response InspectExecSession +type swagInspectExecSession struct { + // in:body + Body struct { + define.InspectExecSession + } +} diff --git a/pkg/bindings/containers/attach.go b/pkg/bindings/containers/attach.go index f410606e4..0c6ebdd2f 100644 --- a/pkg/bindings/containers/attach.go +++ b/pkg/bindings/containers/attach.go @@ -279,7 +279,7 @@ func DemuxFrame(r io.Reader, buffer []byte, length int) (frame []byte, err error n, err := io.ReadFull(r, buffer[0:length]) if err != nil { - return nil, nil + return nil, err } if n < length { err = io.ErrUnexpectedEOF diff --git a/pkg/bindings/generator/generator.go b/pkg/bindings/generator/generator.go index a224013ea..e69973be1 100644 --- a/pkg/bindings/generator/generator.go +++ b/pkg/bindings/generator/generator.go @@ -1,3 +1,4 @@ +//go:build ignore // +build ignore package main diff --git a/pkg/bindings/images/build_unix.go b/pkg/bindings/images/build_unix.go index 0afb1deb6..67a5e2998 100644 --- a/pkg/bindings/images/build_unix.go +++ b/pkg/bindings/images/build_unix.go @@ -1,3 +1,4 @@ +//go:build !windows // +build !windows package images diff --git a/pkg/bindings/images/types.go b/pkg/bindings/images/types.go index a44a3527f..75cb38a0a 100644 --- a/pkg/bindings/images/types.go +++ b/pkg/bindings/images/types.go @@ -11,6 +11,8 @@ type RemoveOptions struct { All *bool // Forces removes all containers based on the image Force *bool + // Ignore if a specified image does not exist and do not throw an error. + Ignore *bool } //go:generate go run ../generator/generator.go DiffOptions @@ -101,6 +103,12 @@ type ImportOptions struct { Reference *string // Url to option image to import. Cannot be used with the reader URL *string + // OS for the imported image + OS *string + // Architecture for the imported image + Architecture *string + // Variant for the imported image + Variant *string } //go:generate go run ../generator/generator.go PushOptions diff --git a/pkg/bindings/images/types_import_options.go b/pkg/bindings/images/types_import_options.go index ea66fa312..f958fe8b4 100644 --- a/pkg/bindings/images/types_import_options.go +++ b/pkg/bindings/images/types_import_options.go @@ -76,3 +76,48 @@ func (o *ImportOptions) GetURL() string { } return *o.URL } + +// WithOS set field OS to given value +func (o *ImportOptions) WithOS(value string) *ImportOptions { + o.OS = &value + return o +} + +// GetOS returns value of field OS +func (o *ImportOptions) GetOS() string { + if o.OS == nil { + var z string + return z + } + return *o.OS +} + +// WithArchitecture set field Architecture to given value +func (o *ImportOptions) WithArchitecture(value string) *ImportOptions { + o.Architecture = &value + return o +} + +// GetArchitecture returns value of field Architecture +func (o *ImportOptions) GetArchitecture() string { + if o.Architecture == nil { + var z string + return z + } + return *o.Architecture +} + +// WithVariant set field Variant to given value +func (o *ImportOptions) WithVariant(value string) *ImportOptions { + o.Variant = &value + return o +} + +// GetVariant returns value of field Variant +func (o *ImportOptions) GetVariant() string { + if o.Variant == nil { + var z string + return z + } + return *o.Variant +} diff --git a/pkg/bindings/images/types_remove_options.go b/pkg/bindings/images/types_remove_options.go index 1fbe5f4ea..613a33183 100644 --- a/pkg/bindings/images/types_remove_options.go +++ b/pkg/bindings/images/types_remove_options.go @@ -46,3 +46,18 @@ func (o *RemoveOptions) GetForce() bool { } return *o.Force } + +// WithIgnore set field Ignore to given value +func (o *RemoveOptions) WithIgnore(value bool) *RemoveOptions { + o.Ignore = &value + return o +} + +// GetIgnore returns value of field Ignore +func (o *RemoveOptions) GetIgnore() bool { + if o.Ignore == nil { + var z bool + return z + } + return *o.Ignore +} diff --git a/pkg/bindings/manifests/manifests.go b/pkg/bindings/manifests/manifests.go index 458cb913a..f7cd0d262 100644 --- a/pkg/bindings/manifests/manifests.go +++ b/pkg/bindings/manifests/manifests.go @@ -2,10 +2,9 @@ package manifests import ( "context" - "errors" "fmt" + "io/ioutil" "net/http" - "net/url" "strconv" "strings" @@ -14,8 +13,11 @@ import ( "github.com/containers/podman/v4/pkg/api/handlers" "github.com/containers/podman/v4/pkg/bindings" "github.com/containers/podman/v4/pkg/bindings/images" + "github.com/containers/podman/v4/pkg/domain/entities" + "github.com/containers/podman/v4/pkg/errorhandling" "github.com/containers/podman/v4/version" jsoniter "github.com/json-iterator/go" + "github.com/pkg/errors" ) // Create creates a manifest for the given name. Optional images to be associated with @@ -135,30 +137,8 @@ func Add(ctx context.Context, name string, options *AddOptions) (string, error) // Remove deletes a manifest entry from a manifest list. Both name and the digest to be // removed are mandatory inputs. The ID of the new manifest list is returned as a string. func Remove(ctx context.Context, name, digest string, _ *RemoveOptions) (string, error) { - if bindings.ServiceVersion(ctx).GTE(semver.MustParse("4.0.0")) { - optionsv4 := new(ModifyOptions).WithOperation("remove") - return Modify(ctx, name, []string{digest}, optionsv4) - } - - // API Version < 4.0.0 - conn, err := bindings.GetClient(ctx) - if err != nil { - return "", err - } - - headers := http.Header{} - headers.Add("API-Version", "3.4.0") - - params := url.Values{} - params.Set("digest", digest) - response, err := conn.DoRequest(ctx, nil, http.MethodDelete, "/manifests/%s", params, headers, name) - if err != nil { - return "", err - } - defer response.Body.Close() - - var idr handlers.IDResponse - return idr.ID, response.Process(&idr) + optionsv4 := new(ModifyOptions).WithOperation("remove") + return Modify(ctx, name, []string{digest}, optionsv4) } // Push takes a manifest list and pushes to a destination. If the destination is not specified, @@ -229,8 +209,36 @@ func Modify(ctx context.Context, name string, images []string, options *ModifyOp } defer response.Body.Close() - var idr handlers.IDResponse - return idr.ID, response.Process(&idr) + data, err := ioutil.ReadAll(response.Body) + if err != nil { + return "", errors.Wrap(err, "unable to process API response") + } + + if response.IsSuccess() || response.IsRedirection() { + var report entities.ManifestModifyReport + if err = jsoniter.Unmarshal(data, &report); err != nil { + return "", errors.Wrap(err, "unable to decode API response") + } + + err = errorhandling.JoinErrors(report.Errors) + if err != nil { + errModel := errorhandling.ErrorModel{ + Because: (errors.Cause(err)).Error(), + Message: err.Error(), + ResponseCode: response.StatusCode, + } + return report.ID, &errModel + } + return report.ID, nil + } + + errModel := errorhandling.ErrorModel{ + ResponseCode: response.StatusCode, + } + if err = jsoniter.Unmarshal(data, &errModel); err != nil { + return "", errors.Wrap(err, "unable to decode API response") + } + return "", &errModel } // Annotate modifies the given manifest list using options and the optional list of images diff --git a/pkg/bindings/play/play.go b/pkg/bindings/play/play.go index d4018b6b3..8058a8514 100644 --- a/pkg/bindings/play/play.go +++ b/pkg/bindings/play/play.go @@ -2,6 +2,7 @@ package play import ( "context" + "io" "net/http" "os" "strconv" @@ -14,20 +15,25 @@ import ( ) func Kube(ctx context.Context, path string, options *KubeOptions) (*entities.PlayKubeReport, error) { + f, err := os.Open(path) + if err != nil { + return nil, err + } + defer f.Close() + + return KubeWithBody(ctx, f, options) +} + +func KubeWithBody(ctx context.Context, body io.Reader, options *KubeOptions) (*entities.PlayKubeReport, error) { var report entities.PlayKubeReport if options == nil { options = new(KubeOptions) } - conn, err := bindings.GetClient(ctx) - if err != nil { - return nil, err - } - f, err := os.Open(path) + conn, err := bindings.GetClient(ctx) if err != nil { return nil, err } - defer f.Close() params, err := options.ToParams() if err != nil { @@ -46,7 +52,7 @@ func Kube(ctx context.Context, path string, options *KubeOptions) (*entities.Pla return nil, err } - response, err := conn.DoRequest(ctx, f, http.MethodPost, "/play/kube", params, header) + response, err := conn.DoRequest(ctx, body, http.MethodPost, "/play/kube", params, header) if err != nil { return nil, err } @@ -60,12 +66,6 @@ func Kube(ctx context.Context, path string, options *KubeOptions) (*entities.Pla } func KubeDown(ctx context.Context, path string) (*entities.PlayKubeReport, error) { - var report entities.PlayKubeReport - conn, err := bindings.GetClient(ctx) - if err != nil { - return nil, err - } - f, err := os.Open(path) if err != nil { return nil, err @@ -75,7 +75,18 @@ func KubeDown(ctx context.Context, path string) (*entities.PlayKubeReport, error logrus.Warn(err) } }() - response, err := conn.DoRequest(ctx, f, http.MethodDelete, "/play/kube", nil, nil) + + return KubeDownWithBody(ctx, f) +} + +func KubeDownWithBody(ctx context.Context, body io.Reader) (*entities.PlayKubeReport, error) { + var report entities.PlayKubeReport + conn, err := bindings.GetClient(ctx) + if err != nil { + return nil, err + } + + response, err := conn.DoRequest(ctx, body, http.MethodDelete, "/play/kube", nil, nil) if err != nil { return nil, err } diff --git a/pkg/bindings/test/attach_test.go b/pkg/bindings/test/attach_test.go index 670566882..dcebe0809 100644 --- a/pkg/bindings/test/attach_test.go +++ b/pkg/bindings/test/attach_test.go @@ -44,7 +44,8 @@ var _ = Describe("Podman containers attach", func() { timeout := uint(5) err := containers.Stop(bt.conn, id, new(containers.StopOptions).WithTimeout(timeout)) if err != nil { - GinkgoWriter.Write([]byte(err.Error())) + _, writeErr := GinkgoWriter.Write([]byte(err.Error())) + Expect(writeErr).ShouldNot(HaveOccurred()) } }() diff --git a/pkg/bindings/test/auth_test.go b/pkg/bindings/test/auth_test.go index b421f0797..c4c4b16d8 100644 --- a/pkg/bindings/test/auth_test.go +++ b/pkg/bindings/test/auth_test.go @@ -40,7 +40,8 @@ var _ = Describe("Podman images", func() { AfterEach(func() { s.Kill() bt.cleanup() - registry.Stop() + err := registry.Stop() + Expect(err).To(BeNil()) }) // Test using credentials. diff --git a/pkg/bindings/test/common_test.go b/pkg/bindings/test/common_test.go index f51e5f404..f2602967b 100644 --- a/pkg/bindings/test/common_test.go +++ b/pkg/bindings/test/common_test.go @@ -211,7 +211,7 @@ func (b *bindingTest) RunTopContainer(containerName *string, podName *string) (s } ctr, err := containers.CreateWithSpec(b.conn, s, nil) if err != nil { - return "", nil + return "", err } err = containers.Start(b.conn, ctr.ID, nil) if err != nil { diff --git a/pkg/bindings/test/containers_test.go b/pkg/bindings/test/containers_test.go index 9411d8a5f..bf627fdba 100644 --- a/pkg/bindings/test/containers_test.go +++ b/pkg/bindings/test/containers_test.go @@ -322,7 +322,8 @@ var _ = Describe("Podman containers ", func() { // a container that has no healthcheck should be a 409 var name = "top" - bt.RunTopContainer(&name, nil) + _, err = bt.RunTopContainer(&name, nil) + Expect(err).To(BeNil()) _, err = containers.RunHealthCheck(bt.conn, name, nil) Expect(err).ToNot(BeNil()) code, _ = bindings.CheckResponseCode(err) diff --git a/pkg/checkpoint/crutils/checkpoint_restore_utils.go b/pkg/checkpoint/crutils/checkpoint_restore_utils.go index 2765d18e8..6a8a7894a 100644 --- a/pkg/checkpoint/crutils/checkpoint_restore_utils.go +++ b/pkg/checkpoint/crutils/checkpoint_restore_utils.go @@ -99,13 +99,12 @@ func CRRemoveDeletedFiles(id, baseDirectory, containerRootDirectory string) erro // root file system changes on top of containerRootDirectory func CRApplyRootFsDiffTar(baseDirectory, containerRootDirectory string) error { rootfsDiffPath := filepath.Join(baseDirectory, metadata.RootFsDiffTar) - if _, err := os.Stat(rootfsDiffPath); err != nil { - // Only do this if a rootfs-diff.tar actually exists - return nil - } - + // Only do this if a rootfs-diff.tar actually exists rootfsDiffFile, err := os.Open(rootfsDiffPath) if err != nil { + if errors.Is(err, os.ErrNotExist) { + return nil + } return errors.Wrap(err, "failed to open root file-system diff file") } defer rootfsDiffFile.Close() diff --git a/pkg/criu/criu.go b/pkg/criu/criu.go index 967da0dca..b54870abc 100644 --- a/pkg/criu/criu.go +++ b/pkg/criu/criu.go @@ -1,3 +1,4 @@ +//go:build linux // +build linux package criu diff --git a/pkg/criu/criu_unsupported.go b/pkg/criu/criu_unsupported.go index 51cd0c1fd..3e3ed9c6c 100644 --- a/pkg/criu/criu_unsupported.go +++ b/pkg/criu/criu_unsupported.go @@ -1,3 +1,4 @@ +//go:build !linux // +build !linux package criu diff --git a/pkg/ctime/ctime_linux.go b/pkg/ctime/ctime_linux.go index 113693e87..7eb3caa6d 100644 --- a/pkg/ctime/ctime_linux.go +++ b/pkg/ctime/ctime_linux.go @@ -1,3 +1,4 @@ +//go:build linux // +build linux package ctime diff --git a/pkg/ctime/ctime_unsupported.go b/pkg/ctime/ctime_unsupported.go index 325731353..afee56027 100644 --- a/pkg/ctime/ctime_unsupported.go +++ b/pkg/ctime/ctime_unsupported.go @@ -1,3 +1,4 @@ +//go:build !linux // +build !linux package ctime diff --git a/pkg/domain/entities/engine_container.go b/pkg/domain/entities/engine_container.go index 7cf7ca17f..6b70a3452 100644 --- a/pkg/domain/entities/engine_container.go +++ b/pkg/domain/entities/engine_container.go @@ -68,8 +68,8 @@ type ContainerEngine interface { NetworkPrune(ctx context.Context, options NetworkPruneOptions) ([]*NetworkPruneReport, error) NetworkReload(ctx context.Context, names []string, options NetworkReloadOptions) ([]*NetworkReloadReport, error) NetworkRm(ctx context.Context, namesOrIds []string, options NetworkRmOptions) ([]*NetworkRmReport, error) - PlayKube(ctx context.Context, path string, opts PlayKubeOptions) (*PlayKubeReport, error) - PlayKubeDown(ctx context.Context, path string, opts PlayKubeDownOptions) (*PlayKubeReport, error) + PlayKube(ctx context.Context, body io.Reader, opts PlayKubeOptions) (*PlayKubeReport, error) + PlayKubeDown(ctx context.Context, body io.Reader, opts PlayKubeDownOptions) (*PlayKubeReport, error) PodCreate(ctx context.Context, specg PodSpec) (*PodCreateReport, error) PodExists(ctx context.Context, nameOrID string) (*BoolReport, error) PodInspect(ctx context.Context, options PodInspectOptions) (*PodInspectReport, error) diff --git a/pkg/domain/entities/images.go b/pkg/domain/entities/images.go index 2ac21cfeb..7081c5d25 100644 --- a/pkg/domain/entities/images.go +++ b/pkg/domain/entities/images.go @@ -90,6 +90,8 @@ type ImageRemoveOptions struct { All bool // Foce will force image removal including containers using the images. Force bool + // Ignore if a specified image does not exist and do not throw an error. + Ignore bool // Confirms if given name is a manifest list and removes it, otherwise returns error. LookupManifest bool } @@ -277,6 +279,7 @@ type ImageLoadReport struct { type ImageImportOptions struct { Architecture string + Variant string Changes []string Message string OS string diff --git a/pkg/domain/entities/types.go b/pkg/domain/entities/types.go index 4d9ced900..bed3183e9 100644 --- a/pkg/domain/entities/types.go +++ b/pkg/domain/entities/types.go @@ -20,7 +20,7 @@ type Volume struct { } type Report struct { - Id []string //nolint + Id []string // nolint Err map[string]error } @@ -98,8 +98,10 @@ type EventsOptions struct { // ContainerCreateResponse is the response struct for creating a container type ContainerCreateResponse struct { // ID of the container created + // required: true ID string `json:"Id"` // Warnings during container creation + // required: true Warnings []string `json:"Warnings"` } diff --git a/pkg/domain/filters/containers.go b/pkg/domain/filters/containers.go index 85ba4f84f..4c6964a00 100644 --- a/pkg/domain/filters/containers.go +++ b/pkg/domain/filters/containers.go @@ -213,8 +213,10 @@ func GenerateContainerFilterFuncs(filter string, filterValues []string, r *libpo for _, val := range filterValues { net, err := r.Network().NetworkInspect(val) if err != nil { - // ignore not found errors - break + if errors.Is(err, define.ErrNoSuchNetwork) { + continue + } + return nil, err } inputNetNames = append(inputNetNames, net.Name) } diff --git a/pkg/domain/filters/pods.go b/pkg/domain/filters/pods.go index 2f9442dff..e22480006 100644 --- a/pkg/domain/filters/pods.go +++ b/pkg/domain/filters/pods.go @@ -131,8 +131,10 @@ func GeneratePodFilterFunc(filter string, filterValues []string, r *libpod.Runti for _, val := range filterValues { net, err := r.Network().NetworkInspect(val) if err != nil { - // ignore not found errors - break + if errors.Is(err, define.ErrNoSuchNetwork) { + continue + } + return nil, err } inputNetNames = append(inputNetNames, net.Name) } diff --git a/pkg/domain/infra/abi/containers.go b/pkg/domain/infra/abi/containers.go index e6feb7c82..f45bdeba5 100644 --- a/pkg/domain/infra/abi/containers.go +++ b/pkg/domain/infra/abi/containers.go @@ -1431,12 +1431,7 @@ func (ic *ContainerEngine) ContainerStats(ctx context.Context, namesOrIds []stri reportStats := []define.ContainerStats{} for _, ctr := range containers { - prev, ok := containerStats[ctr.ID()] - if !ok { - prev = &define.ContainerStats{} - } - - stats, err := ctr.GetContainerStats(prev) + stats, err := ctr.GetContainerStats(containerStats[ctr.ID()]) if err != nil { cause := errors.Cause(err) if queryAll && (cause == define.ErrCtrRemoved || cause == define.ErrNoSuchCtr || cause == define.ErrCtrStateInvalid) { @@ -1501,6 +1496,35 @@ func (ic *ContainerEngine) ContainerClone(ctx context.Context, ctrCloneOpts enti return nil, err } + if ctrCloneOpts.CreateOpts.Pod != "" { + pod, err := ic.Libpod.LookupPod(ctrCloneOpts.CreateOpts.Pod) + if err != nil { + return nil, err + } + + allNamespaces := []struct { + isShared bool + value *specgen.Namespace + }{ + {pod.SharesPID(), &spec.PidNS}, + {pod.SharesNet(), &spec.NetNS}, + {pod.SharesCgroup(), &spec.CgroupNS}, + {pod.SharesIPC(), &spec.IpcNS}, + {pod.SharesUTS(), &spec.UtsNS}, + } + + printWarning := false + for _, n := range allNamespaces { + if n.isShared && !n.value.IsDefault() { + *n.value = specgen.Namespace{NSMode: specgen.Default} + printWarning = true + } + } + if printWarning { + logrus.Warning("At least one namespace was reset to the default configuration") + } + } + err = specgenutil.FillOutSpecGen(spec, &ctrCloneOpts.CreateOpts, []string{}) if err != nil { return nil, err diff --git a/pkg/domain/infra/abi/images.go b/pkg/domain/infra/abi/images.go index 0b1281aac..74478b26d 100644 --- a/pkg/domain/infra/abi/images.go +++ b/pkg/domain/infra/abi/images.go @@ -445,7 +445,8 @@ func (ir *ImageEngine) Import(ctx context.Context, options entities.ImageImportO importOptions.Tag = options.Reference importOptions.SignaturePolicyPath = options.SignaturePolicy importOptions.OS = options.OS - importOptions.Architecture = options.Architecture + importOptions.Arch = options.Architecture + importOptions.Variant = options.Variant if !options.Quiet { importOptions.Writer = os.Stderr @@ -578,6 +579,7 @@ func (ir *ImageEngine) Remove(ctx context.Context, images []string, opts entitie libimageOptions := &libimage.RemoveImagesOptions{} libimageOptions.Filters = []string{"readonly=false"} libimageOptions.Force = opts.Force + libimageOptions.Ignore = opts.Ignore libimageOptions.LookupManifest = opts.LookupManifest if !opts.All { libimageOptions.Filters = append(libimageOptions.Filters, "intermediate=false") @@ -847,13 +849,12 @@ func execPodman(execUser *user.User, command []string) error { if err != nil { return err } - defer func() error { - err := cmdLogin.Process.Kill() - if err != nil { - return err - } - return cmdLogin.Wait() + + defer func() { + _ = cmdLogin.Process.Kill() + _ = cmdLogin.Wait() }() + cmd := exec.Command(command[0], command[1:]...) cmd.Env = []string{"PATH=" + os.Getenv("PATH"), "TERM=" + os.Getenv("TERM")} cmd.Stderr = os.Stderr diff --git a/pkg/domain/infra/abi/play.go b/pkg/domain/infra/abi/play.go index 4d8c5a381..1423ab06e 100644 --- a/pkg/domain/infra/abi/play.go +++ b/pkg/domain/infra/abi/play.go @@ -33,12 +33,12 @@ import ( yamlv2 "gopkg.in/yaml.v2" ) -func (ic *ContainerEngine) PlayKube(ctx context.Context, path string, options entities.PlayKubeOptions) (*entities.PlayKubeReport, error) { +func (ic *ContainerEngine) PlayKube(ctx context.Context, body io.Reader, options entities.PlayKubeOptions) (*entities.PlayKubeReport, error) { report := &entities.PlayKubeReport{} validKinds := 0 // read yaml document - content, err := ioutil.ReadFile(path) + content, err := ioutil.ReadAll(body) if err != nil { return nil, err } @@ -52,7 +52,7 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, path string, options en // sort kube kinds documentList, err = sortKubeKinds(documentList) if err != nil { - return nil, errors.Wrapf(err, "unable to sort kube kinds in %q", path) + return nil, errors.Wrap(err, "unable to sort kube kinds") } ipIndex := 0 @@ -64,7 +64,7 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, path string, options en for _, document := range documentList { kind, err := getKubeKind(document) if err != nil { - return nil, errors.Wrapf(err, "unable to read %q as kube YAML", path) + return nil, errors.Wrap(err, "unable to read kube YAML") } switch kind { @@ -73,7 +73,7 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, path string, options en var podTemplateSpec v1.PodTemplateSpec if err := yaml.Unmarshal(document, &podYAML); err != nil { - return nil, errors.Wrapf(err, "unable to read YAML %q as Kube Pod", path) + return nil, errors.Wrap(err, "unable to read YAML as Kube Pod") } podTemplateSpec.ObjectMeta = podYAML.ObjectMeta @@ -97,7 +97,7 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, path string, options en var deploymentYAML v1apps.Deployment if err := yaml.Unmarshal(document, &deploymentYAML); err != nil { - return nil, errors.Wrapf(err, "unable to read YAML %q as Kube Deployment", path) + return nil, errors.Wrap(err, "unable to read YAML as Kube Deployment") } r, err := ic.playKubeDeployment(ctx, &deploymentYAML, options, &ipIndex, configMaps) @@ -111,7 +111,7 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, path string, options en var pvcYAML v1.PersistentVolumeClaim if err := yaml.Unmarshal(document, &pvcYAML); err != nil { - return nil, errors.Wrapf(err, "unable to read YAML %q as Kube PersistentVolumeClaim", path) + return nil, errors.Wrap(err, "unable to read YAML as Kube PersistentVolumeClaim") } r, err := ic.playKubePVC(ctx, &pvcYAML, options) @@ -125,7 +125,7 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, path string, options en var configMap v1.ConfigMap if err := yaml.Unmarshal(document, &configMap); err != nil { - return nil, errors.Wrapf(err, "unable to read YAML %q as Kube ConfigMap", path) + return nil, errors.Wrap(err, "unable to read YAML as Kube ConfigMap") } configMaps = append(configMaps, configMap) default: @@ -215,7 +215,7 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY // FIXME This is very hard to support properly with a good ux if len(options.StaticIPs) > *ipIndex { if !podOpt.Net.Network.IsBridge() { - errors.Wrap(define.ErrInvalidArg, "static ip addresses can only be set when the network mode is bridge") + return nil, errors.Wrap(define.ErrInvalidArg, "static ip addresses can only be set when the network mode is bridge") } if len(podOpt.Net.Networks) != 1 { return nil, errors.Wrap(define.ErrInvalidArg, "cannot set static ip addresses for more than network, use netname:ip=<ip> syntax to specify ips for more than network") @@ -230,7 +230,7 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY } if len(options.StaticMACs) > *ipIndex { if !podOpt.Net.Network.IsBridge() { - errors.Wrap(define.ErrInvalidArg, "static mac address can only be set when the network mode is bridge") + return nil, errors.Wrap(define.ErrInvalidArg, "static mac address can only be set when the network mode is bridge") } if len(podOpt.Net.Networks) != 1 { return nil, errors.Wrap(define.ErrInvalidArg, "cannot set static mac address for more than network, use netname:mac=<mac> syntax to specify mac for more than network") @@ -773,14 +773,14 @@ func getBuildFile(imageName string, cwd string) (string, error) { return "", err } -func (ic *ContainerEngine) PlayKubeDown(ctx context.Context, path string, _ entities.PlayKubeDownOptions) (*entities.PlayKubeReport, error) { +func (ic *ContainerEngine) PlayKubeDown(ctx context.Context, body io.Reader, _ entities.PlayKubeDownOptions) (*entities.PlayKubeReport, error) { var ( podNames []string ) reports := new(entities.PlayKubeReport) // read yaml document - content, err := ioutil.ReadFile(path) + content, err := ioutil.ReadAll(body) if err != nil { return nil, err } @@ -794,27 +794,27 @@ func (ic *ContainerEngine) PlayKubeDown(ctx context.Context, path string, _ enti // sort kube kinds documentList, err = sortKubeKinds(documentList) if err != nil { - return nil, errors.Wrapf(err, "unable to sort kube kinds in %q", path) + return nil, errors.Wrap(err, "unable to sort kube kinds") } for _, document := range documentList { kind, err := getKubeKind(document) if err != nil { - return nil, errors.Wrapf(err, "unable to read %q as kube YAML", path) + return nil, errors.Wrap(err, "unable to read as kube YAML") } switch kind { case "Pod": var podYAML v1.Pod if err := yaml.Unmarshal(document, &podYAML); err != nil { - return nil, errors.Wrapf(err, "unable to read YAML %q as Kube Pod", path) + return nil, errors.Wrap(err, "unable to read YAML as Kube Pod") } podNames = append(podNames, podYAML.ObjectMeta.Name) case "Deployment": var deploymentYAML v1apps.Deployment if err := yaml.Unmarshal(document, &deploymentYAML); err != nil { - return nil, errors.Wrapf(err, "unable to read YAML %q as Kube Deployment", path) + return nil, errors.Wrap(err, "unable to read YAML as Kube Deployment") } var numReplicas int32 = 1 deploymentName := deploymentYAML.ObjectMeta.Name diff --git a/pkg/domain/infra/abi/terminal/sigproxy_linux.go b/pkg/domain/infra/abi/terminal/sigproxy_linux.go index 206ded091..fe2c268c0 100644 --- a/pkg/domain/infra/abi/terminal/sigproxy_linux.go +++ b/pkg/domain/infra/abi/terminal/sigproxy_linux.go @@ -20,7 +20,7 @@ const signalBufferSize = 2048 func ProxySignals(ctr *libpod.Container) { // Stop catching the shutdown signals (SIGINT, SIGTERM) - they're going // to the container now. - shutdown.Stop() + shutdown.Stop() // nolint: errcheck sigBuffer := make(chan os.Signal, signalBufferSize) signal.CatchAll(sigBuffer) diff --git a/pkg/domain/infra/abi/terminal/terminal_linux.go b/pkg/domain/infra/abi/terminal/terminal_linux.go index 78c792d2b..153b19fdb 100644 --- a/pkg/domain/infra/abi/terminal/terminal_linux.go +++ b/pkg/domain/infra/abi/terminal/terminal_linux.go @@ -39,7 +39,7 @@ func ExecAttachCtr(ctx context.Context, ctr *libpod.Container, execConfig *libpo // StartAttachCtr starts and (if required) attaches to a container // if you change the signature of this function from os.File to io.Writer, it will trigger a downstream // error. we may need to just lint disable this one. -func StartAttachCtr(ctx context.Context, ctr *libpod.Container, stdout, stderr, stdin *os.File, detachKeys string, sigProxy bool, startContainer bool) error { //nolint-interfacer +func StartAttachCtr(ctx context.Context, ctr *libpod.Container, stdout, stderr, stdin *os.File, detachKeys string, sigProxy bool, startContainer bool) error { //nolint: interfacer resize := make(chan define.TerminalSize) haveTerminal := terminal.IsTerminal(int(os.Stdin.Fd())) diff --git a/pkg/domain/infra/abi/volumes.go b/pkg/domain/infra/abi/volumes.go index 19fc6d2d3..f59f11e20 100644 --- a/pkg/domain/infra/abi/volumes.go +++ b/pkg/domain/infra/abi/volumes.go @@ -171,7 +171,8 @@ func (ic *ContainerEngine) VolumeMounted(ctx context.Context, nameOrID string) ( } mountCount, err := vol.MountCount() if err != nil { - return &entities.BoolReport{Value: false}, nil + // FIXME: this error should probably be returned + return &entities.BoolReport{Value: false}, nil // nolint: nilerr } if mountCount > 0 { return &entities.BoolReport{Value: true}, nil diff --git a/pkg/domain/infra/runtime_abi.go b/pkg/domain/infra/runtime_abi.go index 5b7b7cf8a..39989c96b 100644 --- a/pkg/domain/infra/runtime_abi.go +++ b/pkg/domain/infra/runtime_abi.go @@ -1,3 +1,4 @@ +//go:build !remote // +build !remote package infra diff --git a/pkg/domain/infra/runtime_abi_unsupported.go b/pkg/domain/infra/runtime_abi_unsupported.go index b4414dc54..9e5bd01eb 100644 --- a/pkg/domain/infra/runtime_abi_unsupported.go +++ b/pkg/domain/infra/runtime_abi_unsupported.go @@ -1,3 +1,4 @@ +//go:build remote // +build remote package infra diff --git a/pkg/domain/infra/runtime_libpod.go b/pkg/domain/infra/runtime_libpod.go index f9ceb9305..dffd90dbe 100644 --- a/pkg/domain/infra/runtime_libpod.go +++ b/pkg/domain/infra/runtime_libpod.go @@ -1,3 +1,4 @@ +//go:build !remote // +build !remote package infra diff --git a/pkg/domain/infra/runtime_proxy.go b/pkg/domain/infra/runtime_proxy.go index a70b61165..e5761d4ab 100644 --- a/pkg/domain/infra/runtime_proxy.go +++ b/pkg/domain/infra/runtime_proxy.go @@ -1,3 +1,4 @@ +//go:build !remote // +build !remote package infra diff --git a/pkg/domain/infra/runtime_tunnel.go b/pkg/domain/infra/runtime_tunnel.go index 68f8b0dac..8a4de032f 100644 --- a/pkg/domain/infra/runtime_tunnel.go +++ b/pkg/domain/infra/runtime_tunnel.go @@ -1,3 +1,4 @@ +//go:build remote // +build remote package infra diff --git a/pkg/domain/infra/tunnel/containers.go b/pkg/domain/infra/tunnel/containers.go index 046c2509d..10bfb3984 100644 --- a/pkg/domain/infra/tunnel/containers.go +++ b/pkg/domain/infra/tunnel/containers.go @@ -840,7 +840,7 @@ func (ic *ContainerEngine) ContainerRun(ctx context.Context, opts entities.Conta if eventsErr != nil || lastEvent == nil { logrus.Errorf("Cannot get exit code: %v", err) report.ExitCode = define.ExecErrorCodeNotFound - return &report, nil // compat with local client + return &report, nil // nolint: nilerr } report.ExitCode = lastEvent.ContainerExitCode @@ -938,7 +938,7 @@ func (ic *ContainerEngine) ContainerStat(ctx context.Context, nameOrID string, p return containers.Stat(ic.ClientCtx, nameOrID, path) } -// Shutdown Libpod engine +// Shutdown Libpod engine. func (ic *ContainerEngine) Shutdown(_ context.Context) { } @@ -949,7 +949,7 @@ func (ic *ContainerEngine) ContainerStats(ctx context.Context, namesOrIds []stri return containers.Stats(ic.ClientCtx, namesOrIds, new(containers.StatsOptions).WithStream(options.Stream).WithInterval(options.Interval)) } -// ShouldRestart reports back whether the container will restart +// ShouldRestart reports back whether the container will restart. func (ic *ContainerEngine) ShouldRestart(_ context.Context, id string) (bool, error) { return containers.ShouldRestart(ic.ClientCtx, id, nil) } diff --git a/pkg/domain/infra/tunnel/events.go b/pkg/domain/infra/tunnel/events.go index 1f27cdff8..b472ad03a 100644 --- a/pkg/domain/infra/tunnel/events.go +++ b/pkg/domain/infra/tunnel/events.go @@ -34,7 +34,7 @@ func (ic *ContainerEngine) Events(ctx context.Context, opts entities.EventsOptio } // GetLastContainerEvent takes a container name or ID and an event status and returns -// the last occurrence of the container event +// the last occurrence of the container event. func (ic *ContainerEngine) GetLastContainerEvent(ctx context.Context, nameOrID string, containerEvent events.Status) (*events.Event, error) { // check to make sure the event.Status is valid if _, err := events.StringToStatus(containerEvent.String()); err != nil { diff --git a/pkg/domain/infra/tunnel/images.go b/pkg/domain/infra/tunnel/images.go index 3ee97d94c..18e10e8dd 100644 --- a/pkg/domain/infra/tunnel/images.go +++ b/pkg/domain/infra/tunnel/images.go @@ -28,7 +28,7 @@ func (ir *ImageEngine) Exists(_ context.Context, nameOrID string) (*entities.Boo } func (ir *ImageEngine) Remove(ctx context.Context, imagesArg []string, opts entities.ImageRemoveOptions) (*entities.ImageRemoveReport, []error) { - options := new(images.RemoveOptions).WithForce(opts.Force).WithAll(opts.All) + options := new(images.RemoveOptions).WithForce(opts.Force).WithIgnore(opts.Ignore).WithAll(opts.All) return images.Remove(ir.ClientCtx, imagesArg, options) } @@ -230,6 +230,7 @@ func (ir *ImageEngine) Import(ctx context.Context, opts entities.ImageImportOpti f *os.File ) options := new(images.ImportOptions).WithChanges(opts.Changes).WithMessage(opts.Message).WithReference(opts.Reference) + options.WithOS(opts.OS).WithArchitecture(opts.Architecture).WithVariant(opts.Variant) if opts.SourceIsURL { options.WithURL(opts.Source) } else { diff --git a/pkg/domain/infra/tunnel/play.go b/pkg/domain/infra/tunnel/play.go index cd51262d0..d9637254a 100644 --- a/pkg/domain/infra/tunnel/play.go +++ b/pkg/domain/infra/tunnel/play.go @@ -2,13 +2,14 @@ package tunnel import ( "context" + "io" "github.com/containers/image/v5/types" "github.com/containers/podman/v4/pkg/bindings/play" "github.com/containers/podman/v4/pkg/domain/entities" ) -func (ic *ContainerEngine) PlayKube(ctx context.Context, path string, opts entities.PlayKubeOptions) (*entities.PlayKubeReport, error) { +func (ic *ContainerEngine) PlayKube(ctx context.Context, body io.Reader, opts entities.PlayKubeOptions) (*entities.PlayKubeReport, error) { options := new(play.KubeOptions).WithAuthfile(opts.Authfile).WithUsername(opts.Username).WithPassword(opts.Password) options.WithCertDir(opts.CertDir).WithQuiet(opts.Quiet).WithSignaturePolicy(opts.SignaturePolicy).WithConfigMaps(opts.ConfigMaps) options.WithLogDriver(opts.LogDriver).WithNetwork(opts.Networks).WithSeccompProfileRoot(opts.SeccompProfileRoot) @@ -26,9 +27,9 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, path string, opts entit if start := opts.Start; start != types.OptionalBoolUndefined { options.WithStart(start == types.OptionalBoolTrue) } - return play.Kube(ic.ClientCtx, path, options) + return play.KubeWithBody(ic.ClientCtx, body, options) } -func (ic *ContainerEngine) PlayKubeDown(ctx context.Context, path string, _ entities.PlayKubeDownOptions) (*entities.PlayKubeReport, error) { - return play.KubeDown(ic.ClientCtx, path) +func (ic *ContainerEngine) PlayKubeDown(ctx context.Context, body io.Reader, _ entities.PlayKubeDownOptions) (*entities.PlayKubeReport, error) { + return play.KubeDownWithBody(ic.ClientCtx, body) } diff --git a/pkg/env/env.go b/pkg/env/env.go index ecd2d62a5..5989d0da5 100644 --- a/pkg/env/env.go +++ b/pkg/env/env.go @@ -26,7 +26,7 @@ func DefaultEnvVariables() map[string]string { // Slice transforms the specified map of environment variables into a // slice. If a value is non-empty, the key and value are joined with '='. func Slice(m map[string]string) []string { - env := make([]string, len(m)) + env := make([]string, 0, len(m)) for k, v := range m { var s string if len(v) > 0 { diff --git a/pkg/env/env_unix.go b/pkg/env/env_unix.go index 16061a700..690078f33 100644 --- a/pkg/env/env_unix.go +++ b/pkg/env/env_unix.go @@ -1,3 +1,4 @@ +//go:build !windows // +build !windows package env diff --git a/pkg/errorhandling/errorhandling.go b/pkg/errorhandling/errorhandling.go index 04110b62a..e33c26032 100644 --- a/pkg/errorhandling/errorhandling.go +++ b/pkg/errorhandling/errorhandling.go @@ -28,7 +28,7 @@ func JoinErrors(errs []error) error { finalErr := multiE.ErrorOrNil() if finalErr == nil { - return finalErr + return nil } return errors.New(strings.TrimSpace(finalErr.Error())) } diff --git a/pkg/inspect/inspect.go b/pkg/inspect/inspect.go index cd26db6b0..767d86daf 100644 --- a/pkg/inspect/inspect.go +++ b/pkg/inspect/inspect.go @@ -9,7 +9,7 @@ import ( v1 "github.com/opencontainers/image-spec/specs-go/v1" ) -// ImageData holds the inspect information of an image +// ImageData holds the inspect information of an image. type ImageData struct { ID string `json:"Id"` Digest digest.Digest `json:"Digest"` @@ -36,13 +36,13 @@ type ImageData struct { HealthCheck *manifest.Schema2HealthConfig `json:"Healthcheck,omitempty"` } -// RootFS holds the root fs information of an image +// RootFS holds the root fs information of an image. type RootFS struct { Type string `json:"Type"` Layers []digest.Digest `json:"Layers"` } -// ImageResult is used for podman images for collection and output +// ImageResult is used for podman images for collection and output. type ImageResult struct { Tag string Repository string diff --git a/pkg/k8s.io/apimachinery/pkg/api/resource/quantity.go b/pkg/k8s.io/apimachinery/pkg/api/resource/quantity.go index fccddc3e0..352cc028f 100644 --- a/pkg/k8s.io/apimachinery/pkg/api/resource/quantity.go +++ b/pkg/k8s.io/apimachinery/pkg/api/resource/quantity.go @@ -579,9 +579,9 @@ func (q Quantity) MarshalJSON() ([]byte, error) { // if CanonicalizeBytes needed more space than our slice provided, we may need to allocate again so use // append result = result[:1] - result = append(result, number...) - result = append(result, suffix...) - result = append(result, '"') + result = append(result, number...) // nolint: makezero + result = append(result, suffix...) // nolint: makezero + result = append(result, '"') // nolint: makezero return result, nil } diff --git a/pkg/k8s.io/apimachinery/pkg/util/intstr/instr_fuzz.go b/pkg/k8s.io/apimachinery/pkg/util/intstr/instr_fuzz.go index 2501d5516..a502b5adb 100644 --- a/pkg/k8s.io/apimachinery/pkg/util/intstr/instr_fuzz.go +++ b/pkg/k8s.io/apimachinery/pkg/util/intstr/instr_fuzz.go @@ -1,3 +1,4 @@ +//go:build !notest // +build !notest /* diff --git a/pkg/lookup/lookup.go b/pkg/lookup/lookup.go index 0b22a1974..0601e829d 100644 --- a/pkg/lookup/lookup.go +++ b/pkg/lookup/lookup.go @@ -14,7 +14,7 @@ const ( etcgroup = "/etc/group" ) -// Overrides allows you to override defaults in GetUserGroupInfo +// Overrides allows you to override defaults in GetUserGroupInfo. type Overrides struct { DefaultUser *user.ExecUser ContainerEtcPasswdPath string diff --git a/pkg/machine/config.go b/pkg/machine/config.go index b3b105150..aaf8da872 100644 --- a/pkg/machine/config.go +++ b/pkg/machine/config.go @@ -36,9 +36,9 @@ type InitOptions struct { type QemuMachineStatus = string const ( - // Running indicates the qemu vm is running + // Running indicates the qemu vm is running. Running QemuMachineStatus = "running" - // Stopped indicates the vm has stopped + // Stopped indicates the vm has stopped. Stopped QemuMachineStatus = "stopped" DefaultMachineName string = "podman-machine-default" ) @@ -147,7 +147,7 @@ func (rc RemoteConnectionType) MakeSSHURL(host, path, port, userName string) url } // GetDataDir returns the filepath where vm images should -// live for podman-machine +// live for podman-machine. func GetDataDir(vmType string) (string, error) { data, err := homedir.GetDataHome() if err != nil { diff --git a/pkg/machine/fcos.go b/pkg/machine/fcos.go index 4d3e2edf4..6215ae08f 100644 --- a/pkg/machine/fcos.go +++ b/pkg/machine/fcos.go @@ -1,3 +1,4 @@ +//go:build amd64 || arm64 // +build amd64 arm64 package machine diff --git a/pkg/machine/fedora.go b/pkg/machine/fedora.go index cd713dde7..bed45c6da 100644 --- a/pkg/machine/fedora.go +++ b/pkg/machine/fedora.go @@ -1,3 +1,4 @@ +//go:build amd64 || arm64 // +build amd64 arm64 package machine @@ -58,7 +59,10 @@ func (f FedoraDownload) Get() *Download { func (f FedoraDownload) HasUsableCache() (bool, error) { info, err := os.Stat(f.LocalPath) if err != nil { - return false, nil + if errors.Is(err, os.ErrNotExist) { + return false, nil + } + return false, err } return info.Size() == f.Size, nil } diff --git a/pkg/machine/ignition_darwin.go b/pkg/machine/ignition_darwin.go index 9ede4b026..b9fbf218d 100644 --- a/pkg/machine/ignition_darwin.go +++ b/pkg/machine/ignition_darwin.go @@ -1,4 +1,5 @@ -//+build darwin +//go:build darwin +// +build darwin package machine diff --git a/pkg/machine/ignition_schema.go b/pkg/machine/ignition_schema.go index 8cfb0d04e..d6b86229c 100644 --- a/pkg/machine/ignition_schema.go +++ b/pkg/machine/ignition_schema.go @@ -1,3 +1,4 @@ +//go:build amd64 || arm64 // +build amd64 arm64 package machine diff --git a/pkg/machine/ignition_windows.go b/pkg/machine/ignition_windows.go index c0de48bd3..0fcc06273 100644 --- a/pkg/machine/ignition_windows.go +++ b/pkg/machine/ignition_windows.go @@ -1,4 +1,5 @@ -//+build windows +//go:build windows +// +build windows package machine diff --git a/pkg/machine/keys.go b/pkg/machine/keys.go index 711b091f0..15c1f73d8 100644 --- a/pkg/machine/keys.go +++ b/pkg/machine/keys.go @@ -1,3 +1,4 @@ +//go:build amd64 || arm64 // +build amd64 arm64 package machine diff --git a/pkg/machine/machine_unsupported.go b/pkg/machine/machine_unsupported.go index da1437984..a12140e16 100644 --- a/pkg/machine/machine_unsupported.go +++ b/pkg/machine/machine_unsupported.go @@ -1,3 +1,4 @@ +//go:build !amd64 && !arm64 // +build !amd64,!arm64 package machine diff --git a/pkg/machine/pull.go b/pkg/machine/pull.go index cf1e708b1..26abedfcd 100644 --- a/pkg/machine/pull.go +++ b/pkg/machine/pull.go @@ -1,3 +1,4 @@ +//go:build amd64 || arm64 // +build amd64 arm64 package machine diff --git a/pkg/machine/qemu/config.go b/pkg/machine/qemu/config.go index b39334be0..211d96ccb 100644 --- a/pkg/machine/qemu/config.go +++ b/pkg/machine/qemu/config.go @@ -61,6 +61,6 @@ type Monitor struct { var ( // defaultQMPTimeout is the timeout duration for the - // qmp monitor interactions + // qmp monitor interactions. defaultQMPTimeout time.Duration = 2 * time.Second ) diff --git a/pkg/machine/qemu/machine.go b/pkg/machine/qemu/machine.go index 3b4548c17..287b93612 100644 --- a/pkg/machine/qemu/machine.go +++ b/pkg/machine/qemu/machine.go @@ -34,7 +34,7 @@ import ( var ( qemuProvider = &Provider{} - // vmtype refers to qemu (vs libvirt, krun, etc) + // vmtype refers to qemu (vs libvirt, krun, etc). vmtype = "qemu" ) @@ -98,7 +98,7 @@ func (p *Provider) NewMachine(opts machine.InitOptions) (machine.VM, error) { return nil, err } - cmd := append([]string{execPath}) + cmd := []string{execPath} // Add memory cmd = append(cmd, []string{"-m", strconv.Itoa(int(vm.Memory))}...) // Add cpus @@ -134,7 +134,7 @@ func (p *Provider) NewMachine(opts machine.InitOptions) (machine.VM, error) { // LoadByName reads a json file that describes a known qemu vm // and returns a vm instance func (p *Provider) LoadVMByName(name string) (machine.VM, error) { - vm := new(MachineVM) + vm := &MachineVM{UID: -1} // posix reserves -1, so use it to signify undefined vmConfigDir, err := machine.GetConfDir(vmtype) if err != nil { return nil, err @@ -278,7 +278,9 @@ func (v *MachineVM) Init(opts machine.InitOptions) (bool, error) { fmt.Println("An ignition path was provided. No SSH connection was added to Podman") } // Write the JSON file - v.writeConfig() + if err := v.writeConfig(); err != nil { + return false, fmt.Errorf("writing JSON file: %w", err) + } // User has provided ignition file so keygen // will be skipped. @@ -370,9 +372,13 @@ func (v *MachineVM) Start(name string, _ machine.StartOptions) error { conn net.Conn err error qemuSocketConn net.Conn - wait time.Duration = time.Millisecond * 500 + wait = time.Millisecond * 500 ) + if v.isIncompatible() { + logrus.Errorf("machine %q is incompatible with this release of podman and needs to be recreated, starting for recovery only", v.Name) + } + forwardSock, forwardState, err := v.startHostNetworking() if err != nil { return errors.Errorf("unable to start host networking: %q", err) @@ -424,13 +430,29 @@ func (v *MachineVM) Start(name string, _ machine.StartOptions) error { // Disable graphic window when not in debug mode // Done in start, so we're not suck with the debug level we used on init - if logrus.GetLevel() != logrus.DebugLevel { + if !logrus.IsLevelEnabled(logrus.DebugLevel) { cmd = append(cmd, "-display", "none") } _, err = os.StartProcess(v.CmdLine[0], cmd, attr) if err != nil { - return err + // check if qemu was not found + if !errors.Is(err, os.ErrNotExist) { + return err + } + // lookup qemu again maybe the path was changed, https://github.com/containers/podman/issues/13394 + cfg, err := config.Default() + if err != nil { + return err + } + cmd[0], err = cfg.FindHelperBinary(QemuCommand, true) + if err != nil { + return err + } + _, err = os.StartProcess(cmd[0], cmd, attr) + if err != nil { + return err + } } fmt.Println("Waiting for VM ...") socketPath, err := getRuntimeDir() @@ -506,7 +528,7 @@ func (v *MachineVM) Start(name string, _ machine.StartOptions) error { } } - waitAPIAndPrintInfo(forwardState, forwardSock, v.Rootful, v.Name) + v.waitAPIAndPrintInfo(forwardState, forwardSock) return nil } @@ -622,7 +644,8 @@ func (v *MachineVM) Stop(name string, _ machine.StopOptions) error { } if err := qmpMonitor.Disconnect(); err != nil { - return nil + // FIXME: this error should probably be returned + return nil // nolint: nilerr } disconnected = true @@ -751,7 +774,8 @@ func (v *MachineVM) isRunning() (bool, error) { // Check if we can dial it monitor, err := qmp.NewSocketMonitor(v.QMPMonitor.Network, v.QMPMonitor.Address, v.QMPMonitor.Timeout) if err != nil { - return false, nil + // FIXME: this error should probably be returned + return false, nil // nolint: nilerr } if err := monitor.Connect(); err != nil { return false, err @@ -774,7 +798,7 @@ func (v *MachineVM) isRunning() (bool, error) { func (v *MachineVM) isListening() bool { // Check if we can dial it - conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", "localhost", v.Port), 10*time.Millisecond) + conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", "127.0.0.1", v.Port), 10*time.Millisecond) if err != nil { return false } @@ -975,7 +999,11 @@ func (v *MachineVM) startHostNetworking() (string, apiForwardingState, error) { // Add the ssh port cmd = append(cmd, []string{"-ssh-port", fmt.Sprintf("%d", v.Port)}...) - cmd, forwardSock, state := v.setupAPIForwarding(cmd) + var forwardSock string + var state apiForwardingState + if !v.isIncompatible() { + cmd, forwardSock, state = v.setupAPIForwarding(cmd) + } if logrus.GetLevel() == logrus.DebugLevel { cmd = append(cmd, "--debug") @@ -1043,6 +1071,10 @@ func (v *MachineVM) setupAPIForwarding(cmd []string) ([]string, string, apiForwa return cmd, dockerSock, dockerGlobal } +func (v *MachineVM) isIncompatible() bool { + return v.UID == -1 +} + func (v *MachineVM) getForwardSocketPath() (string, error) { path, err := machine.GetDataDir(v.Name) if err != nil { @@ -1085,10 +1117,13 @@ func waitAndPingAPI(sock string) { Transport: &http.Transport{ DialContext: func(context.Context, string, string) (net.Conn, error) { con, err := net.DialTimeout("unix", sock, apiUpTimeout) - if err == nil { - con.SetDeadline(time.Now().Add(apiUpTimeout)) + if err != nil { + return nil, err } - return con, err + if err := con.SetDeadline(time.Now().Add(apiUpTimeout)); err != nil { + return nil, err + } + return con, nil }, }, } @@ -1102,46 +1137,66 @@ func waitAndPingAPI(sock string) { } } -func waitAPIAndPrintInfo(forwardState apiForwardingState, forwardSock string, rootFul bool, name string) { - if forwardState != noForwarding { - suffix := "" - if name != machine.DefaultMachineName { - suffix = " " + name - } - waitAndPingAPI(forwardSock) - if !rootFul { - fmt.Printf("\nThis machine is currently configured in rootless mode. If your containers\n") - fmt.Printf("require root permissions (e.g. ports < 1024), or if you run into compatibility\n") - fmt.Printf("issues with non-podman clients, you can switch using the following command: \n") - fmt.Printf("\n\tpodman machine set --rootful%s\n\n", suffix) - } +func (v *MachineVM) waitAPIAndPrintInfo(forwardState apiForwardingState, forwardSock string) { + suffix := "" + if v.Name != machine.DefaultMachineName { + suffix = " " + v.Name + } - fmt.Printf("API forwarding listening on: %s\n", forwardSock) - if forwardState == dockerGlobal { - fmt.Printf("Docker API clients default to this address. You do not need to set DOCKER_HOST.\n\n") - } else { - stillString := "still " - switch forwardState { - case notInstalled: - fmt.Printf("\nThe system helper service is not installed; the default Docker API socket\n") - fmt.Printf("address can't be used by podman. ") - if helper := findClaimHelper(); len(helper) > 0 { - fmt.Printf("If you would like to install it run the\nfollowing commands:\n") - fmt.Printf("\n\tsudo %s install\n", helper) - fmt.Printf("\tpodman machine stop%s; podman machine start%s\n\n", suffix, suffix) - } - case machineLocal: - fmt.Printf("\nAnother process was listening on the default Docker API socket address.\n") - case claimUnsupported: - fallthrough - default: - stillString = "" - } + if v.isIncompatible() { + fmt.Fprintf(os.Stderr, "\n!!! ACTION REQUIRED: INCOMPATIBLE MACHINE !!!\n") - fmt.Printf("You can %sconnect Docker API clients by setting DOCKER_HOST using the\n", stillString) - fmt.Printf("following command in your terminal session:\n") - fmt.Printf("\n\texport DOCKER_HOST='unix://%s'\n\n", forwardSock) + fmt.Fprintf(os.Stderr, "\nThis machine was created by an older podman release that is incompatible\n") + fmt.Fprintf(os.Stderr, "with this release of podman. It has been started in a limited operational\n") + fmt.Fprintf(os.Stderr, "mode to allow you to copy any necessary files before recreating it. This\n") + fmt.Fprintf(os.Stderr, "can be accomplished with the following commands:\n\n") + fmt.Fprintf(os.Stderr, "\t# Login and copy desired files (Optional)\n") + fmt.Fprintf(os.Stderr, "\t# podman machine ssh%s tar cvPf - /path/to/files > backup.tar\n\n", suffix) + fmt.Fprintf(os.Stderr, "\t# Recreate machine (DESTRUCTIVE!) \n") + fmt.Fprintf(os.Stderr, "\tpodman machine stop%s\n", suffix) + fmt.Fprintf(os.Stderr, "\tpodman machine rm -f%s\n", suffix) + fmt.Fprintf(os.Stderr, "\tpodman machine init --now%s\n\n", suffix) + fmt.Fprintf(os.Stderr, "\t# Copy back files (Optional)\n") + fmt.Fprintf(os.Stderr, "\t# cat backup.tar | podman machine ssh%s tar xvPf - \n\n", suffix) + } + + if forwardState == noForwarding { + return + } + + waitAndPingAPI(forwardSock) + if !v.Rootful { + fmt.Printf("\nThis machine is currently configured in rootless mode. If your containers\n") + fmt.Printf("require root permissions (e.g. ports < 1024), or if you run into compatibility\n") + fmt.Printf("issues with non-podman clients, you can switch using the following command: \n") + fmt.Printf("\n\tpodman machine set --rootful%s\n\n", suffix) + } + + fmt.Printf("API forwarding listening on: %s\n", forwardSock) + if forwardState == dockerGlobal { + fmt.Printf("Docker API clients default to this address. You do not need to set DOCKER_HOST.\n\n") + } else { + stillString := "still " + switch forwardState { + case notInstalled: + fmt.Printf("\nThe system helper service is not installed; the default Docker API socket\n") + fmt.Printf("address can't be used by podman. ") + if helper := findClaimHelper(); len(helper) > 0 { + fmt.Printf("If you would like to install it run the\nfollowing commands:\n") + fmt.Printf("\n\tsudo %s install\n", helper) + fmt.Printf("\tpodman machine stop%s; podman machine start%s\n\n", suffix, suffix) + } + case machineLocal: + fmt.Printf("\nAnother process was listening on the default Docker API socket address.\n") + case claimUnsupported: + fallthrough + default: + stillString = "" } + + fmt.Printf("You can %sconnect Docker API clients by setting DOCKER_HOST using the\n", stillString) + fmt.Printf("following command in your terminal session:\n") + fmt.Printf("\n\texport DOCKER_HOST='unix://%s'\n\n", forwardSock) } } diff --git a/pkg/machine/qemu/machine_unsupported.go b/pkg/machine/qemu/machine_unsupported.go index e3ce05e3d..794e710f9 100644 --- a/pkg/machine/qemu/machine_unsupported.go +++ b/pkg/machine/qemu/machine_unsupported.go @@ -1,3 +1,4 @@ +//go:build (!amd64 && !arm64) || windows // +build !amd64,!arm64 windows package qemu diff --git a/pkg/machine/wsl/machine_unsupported.go b/pkg/machine/wsl/machine_unsupported.go index 043c5d729..856f9dd0c 100644 --- a/pkg/machine/wsl/machine_unsupported.go +++ b/pkg/machine/wsl/machine_unsupported.go @@ -1,3 +1,4 @@ +//go:build !windows // +build !windows package wsl diff --git a/pkg/rootless/rootless.go b/pkg/rootless/rootless.go index 93b4e2e9f..13f8078e2 100644 --- a/pkg/rootless/rootless.go +++ b/pkg/rootless/rootless.go @@ -1,6 +1,8 @@ package rootless import ( + "errors" + "fmt" "os" "sort" "sync" @@ -8,7 +10,6 @@ import ( "github.com/containers/storage/pkg/lockfile" "github.com/opencontainers/runc/libcontainer/user" spec "github.com/opencontainers/runtime-spec/specs-go" - "github.com/pkg/errors" ) // TryJoinPauseProcess attempts to join the namespaces of the pause PID via @@ -16,12 +17,15 @@ import ( // file. func TryJoinPauseProcess(pausePidPath string) (bool, int, error) { if _, err := os.Stat(pausePidPath); err != nil { - return false, -1, nil + if errors.Is(err, os.ErrNotExist) { + return false, -1, nil + } + return false, -1, err } became, ret, err := TryJoinFromFilePaths("", false, []string{pausePidPath}) if err == nil { - return became, ret, err + return became, ret, nil } // It could not join the pause process, let's lock the file before trying to delete it. @@ -31,7 +35,7 @@ func TryJoinPauseProcess(pausePidPath string) (bool, int, error) { if os.IsNotExist(err) { return false, -1, nil } - return false, -1, errors.Wrapf(err, "error acquiring lock on %s", pausePidPath) + return false, -1, fmt.Errorf("error acquiring lock on %s: %w", pausePidPath, err) } pidFileLock.Lock() @@ -46,7 +50,7 @@ func TryJoinPauseProcess(pausePidPath string) (bool, int, error) { if err != nil { // It is still failing. We can safely remove it. os.Remove(pausePidPath) - return false, -1, nil + return false, -1, nil // nolint: nilerr } return became, ret, err } diff --git a/pkg/rootless/rootless_linux.go b/pkg/rootless/rootless_linux.go index a0b6edcfb..786e28093 100644 --- a/pkg/rootless/rootless_linux.go +++ b/pkg/rootless/rootless_linux.go @@ -1,3 +1,4 @@ +//go:build linux && cgo // +build linux,cgo package rootless diff --git a/pkg/rootless/rootless_unsupported.go b/pkg/rootless/rootless_unsupported.go index 7dfb4a4b2..fe164e235 100644 --- a/pkg/rootless/rootless_unsupported.go +++ b/pkg/rootless/rootless_unsupported.go @@ -1,3 +1,4 @@ +//go:build !linux || !cgo // +build !linux !cgo package rootless diff --git a/pkg/rootlessport/rootlessport_linux.go b/pkg/rootlessport/rootlessport_linux.go index b89a92d1e..6918a7e8c 100644 --- a/pkg/rootlessport/rootlessport_linux.go +++ b/pkg/rootlessport/rootlessport_linux.go @@ -1,3 +1,4 @@ +//go:build linux // +build linux // Package rootlessport provides reexec for RootlessKit-based port forwarder. diff --git a/pkg/servicereaper/service.go b/pkg/servicereaper/service.go index e105148f0..61445bc19 100644 --- a/pkg/servicereaper/service.go +++ b/pkg/servicereaper/service.go @@ -1,4 +1,5 @@ -//+build linux +//go:build linux +// +build linux package servicereaper diff --git a/pkg/signal/signal_common.go b/pkg/signal/signal_common.go index 8ff4b4dbf..5ea67843a 100644 --- a/pkg/signal/signal_common.go +++ b/pkg/signal/signal_common.go @@ -25,7 +25,7 @@ func ParseSignal(rawSignal string) (syscall.Signal, error) { } // ParseSignalNameOrNumber translates a string to a valid syscall signal. Input -// can be a name or number representation i.e. "KILL" "9" +// can be a name or number representation i.e. "KILL" "9". func ParseSignalNameOrNumber(rawSignal string) (syscall.Signal, error) { basename := strings.TrimPrefix(rawSignal, "-") s, err := ParseSignal(basename) diff --git a/pkg/signal/signal_linux.go b/pkg/signal/signal_linux.go index 305b9d21f..21e09c9fe 100644 --- a/pkg/signal/signal_linux.go +++ b/pkg/signal/signal_linux.go @@ -1,5 +1,5 @@ -// +build linux -// +build !mips,!mipsle,!mips64,!mips64le +//go:build linux && !mips && !mipsle && !mips64 && !mips64le +// +build linux,!mips,!mipsle,!mips64,!mips64le // Signal handling for Linux only. package signal diff --git a/pkg/signal/signal_linux_mipsx.go b/pkg/signal/signal_linux_mipsx.go index 45c9d5af1..52b07aaf4 100644 --- a/pkg/signal/signal_linux_mipsx.go +++ b/pkg/signal/signal_linux_mipsx.go @@ -1,3 +1,4 @@ +//go:build linux && (mips || mipsle || mips64 || mips64le) // +build linux // +build mips mipsle mips64 mips64le diff --git a/pkg/signal/signal_unix.go b/pkg/signal/signal_unix.go index f35abddc1..c0aa62d21 100644 --- a/pkg/signal/signal_unix.go +++ b/pkg/signal/signal_unix.go @@ -1,3 +1,4 @@ +//go:build aix || darwin || dragonfly || freebsd || netbsd || openbsd || solaris || zos // +build aix darwin dragonfly freebsd netbsd openbsd solaris zos // Signal handling for Linux only. diff --git a/pkg/signal/signal_unsupported.go b/pkg/signal/signal_unsupported.go index 45946f142..d8bba7c90 100644 --- a/pkg/signal/signal_unsupported.go +++ b/pkg/signal/signal_unsupported.go @@ -1,3 +1,4 @@ +//go:build !aix && !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd && !solaris && !zos // +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!zos // Signal handling for Linux only. diff --git a/pkg/specgen/config_unsupported.go b/pkg/specgen/config_unsupported.go index 70a60ac47..a6bf77277 100644 --- a/pkg/specgen/config_unsupported.go +++ b/pkg/specgen/config_unsupported.go @@ -1,3 +1,4 @@ +//go:build !linux // +build !linux package specgen diff --git a/pkg/specgen/generate/config_linux.go b/pkg/specgen/generate/config_linux.go index a5772bc6a..35d7f0252 100644 --- a/pkg/specgen/generate/config_linux.go +++ b/pkg/specgen/generate/config_linux.go @@ -262,8 +262,8 @@ func addDevice(g *generate.Generator, device string) error { // ParseDevice parses device mapping string to a src, dest & permissions string func ParseDevice(device string) (string, string, string, error) { //nolint - src := "" - dst := "" + var src string + var dst string permissions := "rwm" arr := strings.Split(device, ":") switch len(arr) { diff --git a/pkg/specgen/generate/config_linux_cgo.go b/pkg/specgen/generate/config_linux_cgo.go index 239655c72..efab6679a 100644 --- a/pkg/specgen/generate/config_linux_cgo.go +++ b/pkg/specgen/generate/config_linux_cgo.go @@ -1,3 +1,4 @@ +//go:build linux && cgo // +build linux,cgo package generate diff --git a/pkg/specgen/generate/config_linux_nocgo.go b/pkg/specgen/generate/config_linux_nocgo.go index 9ead739a7..99b0c4eb2 100644 --- a/pkg/specgen/generate/config_linux_nocgo.go +++ b/pkg/specgen/generate/config_linux_nocgo.go @@ -1,3 +1,4 @@ +//go:build linux && !cgo // +build linux,!cgo package generate diff --git a/pkg/specgen/generate/container.go b/pkg/specgen/generate/container.go index 64669f34d..0e9d33dd8 100644 --- a/pkg/specgen/generate/container.go +++ b/pkg/specgen/generate/container.go @@ -338,8 +338,8 @@ func FinishThrottleDevices(s *specgen.SpecGenerator) error { } // ConfigToSpec takes a completed container config and converts it back into a specgenerator for purposes of cloning an exisiting container -func ConfigToSpec(rt *libpod.Runtime, specg *specgen.SpecGenerator, contaierID string) (*libpod.Container, error) { - c, err := rt.LookupContainer(contaierID) +func ConfigToSpec(rt *libpod.Runtime, specg *specgen.SpecGenerator, containerID string) (*libpod.Container, error) { + c, err := rt.LookupContainer(containerID) if err != nil { return nil, err } diff --git a/pkg/specgen/generate/ports_bench_test.go b/pkg/specgen/generate/ports_bench_test.go index f208a34c5..f65cd2f15 100644 --- a/pkg/specgen/generate/ports_bench_test.go +++ b/pkg/specgen/generate/ports_bench_test.go @@ -9,7 +9,7 @@ import ( func benchmarkParsePortMapping(b *testing.B, ports []types.PortMapping) { for n := 0; n < b.N; n++ { - ParsePortMapping(ports, nil) + _, _ = ParsePortMapping(ports, nil) } } diff --git a/pkg/specgen/generate/security.go b/pkg/specgen/generate/security.go index 9c6709905..988c29832 100644 --- a/pkg/specgen/generate/security.go +++ b/pkg/specgen/generate/security.go @@ -146,6 +146,10 @@ func securityConfigureGenerator(s *specgen.SpecGenerator, g *generate.Generator, configSpec := g.Config configSpec.Process.Capabilities.Ambient = []string{} + + // Always unset the inheritable capabilities similarly to what the Linux kernel does + // They are used only when using capabilities with uid != 0. + configSpec.Process.Capabilities.Inheritable = []string{} configSpec.Process.Capabilities.Bounding = caplist user := strings.Split(s.User, ":")[0] @@ -153,7 +157,6 @@ func securityConfigureGenerator(s *specgen.SpecGenerator, g *generate.Generator, if (user == "" && s.UserNS.NSMode != specgen.KeepID) || user == "root" || user == "0" { configSpec.Process.Capabilities.Effective = caplist configSpec.Process.Capabilities.Permitted = caplist - configSpec.Process.Capabilities.Inheritable = caplist } else { mergedCaps, err := capabilities.MergeCapabilities(nil, s.CapAdd, nil) if err != nil { @@ -175,12 +178,12 @@ func securityConfigureGenerator(s *specgen.SpecGenerator, g *generate.Generator, } configSpec.Process.Capabilities.Effective = userCaps configSpec.Process.Capabilities.Permitted = userCaps - configSpec.Process.Capabilities.Inheritable = userCaps // Ambient capabilities were added to Linux 4.3. Set ambient // capabilities only when the kernel supports them. if supportAmbientCapabilities() { configSpec.Process.Capabilities.Ambient = userCaps + configSpec.Process.Capabilities.Inheritable = userCaps } } diff --git a/pkg/specgenutil/specgen.go b/pkg/specgenutil/specgen.go index b87da61fb..688cc2337 100644 --- a/pkg/specgenutil/specgen.go +++ b/pkg/specgenutil/specgen.go @@ -847,7 +847,8 @@ func makeHealthCheckFromCli(inCmd, interval string, retries uint, timeout, start if len(cmdArr) == 0 { return nil, errors.New("Must define a healthcheck command for all healthchecks") } - concat := "" + + var concat string if cmdArr[0] == "CMD" || cmdArr[0] == "none" { // this is for compat, we are already split properly for most compat cases cmdArr = strings.Fields(inCmd) } else if cmdArr[0] != "CMD-SHELL" { // this is for podman side of things, won't contain the keywords diff --git a/pkg/systemd/dbus.go b/pkg/systemd/dbus.go index 1b1bc8be9..44feb8308 100644 --- a/pkg/systemd/dbus.go +++ b/pkg/systemd/dbus.go @@ -24,7 +24,6 @@ func IsSystemdSessionValid(uid int) bool { if rootless.IsRootless() { conn, err = GetLogindConnection(rootless.GetRootlessUID()) - object = conn.Object(dbusDest, godbus.ObjectPath(dbusPath)) if err != nil { //unable to fetch systemd object for logind logrus.Debugf("systemd-logind: %s", err) diff --git a/pkg/systemd/generate/containers.go b/pkg/systemd/generate/containers.go index c01bb1baf..e11aed771 100644 --- a/pkg/systemd/generate/containers.go +++ b/pkg/systemd/generate/containers.go @@ -362,7 +362,9 @@ func executeContainerTemplate(info *containerInfo, options entities.GenerateSyst fs.StringArrayP("env", "e", nil, "") fs.String("sdnotify", "", "") fs.String("restart", "", "") - fs.Parse(remainingCmd) + if err := fs.Parse(remainingCmd); err != nil { + return "", fmt.Errorf("parsing remaining command-line arguments: %w", err) + } remainingCmd = filterCommonContainerFlags(remainingCmd, fs.NArg()) // If the container is in a pod, make sure that the diff --git a/pkg/systemd/generate/pods.go b/pkg/systemd/generate/pods.go index 78ae6391b..15b598ae8 100644 --- a/pkg/systemd/generate/pods.go +++ b/pkg/systemd/generate/pods.go @@ -335,7 +335,9 @@ func executePodTemplate(info *podInfo, options entities.GenerateSystemdOptions) fs.SetInterspersed(false) fs.String("name", "", "") fs.Bool("replace", false, "") - fs.Parse(podCreateArgs) + if err := fs.Parse(podCreateArgs); err != nil { + return "", fmt.Errorf("parsing remaining command-line arguments: %w", err) + } hasNameParam := fs.Lookup("name").Changed hasReplaceParam, err := fs.GetBool("replace") diff --git a/pkg/terminal/console_unix.go b/pkg/terminal/console_unix.go index 6eee6aa2f..53290be24 100644 --- a/pkg/terminal/console_unix.go +++ b/pkg/terminal/console_unix.go @@ -1,8 +1,9 @@ +//go:build !windows // +build !windows package terminal -// SetConsole for non-windows environments is a no-op +// SetConsole for non-windows environments is a no-op. func SetConsole() error { return nil } diff --git a/pkg/terminal/console_windows.go b/pkg/terminal/console_windows.go index 9a636d681..1a7da3335 100644 --- a/pkg/terminal/console_windows.go +++ b/pkg/terminal/console_windows.go @@ -1,3 +1,4 @@ +//go:build windows // +build windows package terminal diff --git a/pkg/util/camelcase/camelcase.go b/pkg/util/camelcase/camelcase.go index d27ac00d6..eaf7c0178 100644 --- a/pkg/util/camelcase/camelcase.go +++ b/pkg/util/camelcase/camelcase.go @@ -51,10 +51,10 @@ func Split(src string) (entries []string) { } entries = []string{} var runes [][]rune - lastClass := 0 - class := 0 + var lastClass int // split into fields based on class of unicode character for _, r := range src { + var class int switch { case unicode.IsLower(r): class = 1 diff --git a/pkg/util/mountOpts_other.go b/pkg/util/mountOpts_other.go index 6a34942e5..64b4dd1d9 100644 --- a/pkg/util/mountOpts_other.go +++ b/pkg/util/mountOpts_other.go @@ -1,3 +1,4 @@ +//go:build !linux // +build !linux package util diff --git a/pkg/util/utils.go b/pkg/util/utils.go index 925ff9830..1beb3b28e 100644 --- a/pkg/util/utils.go +++ b/pkg/util/utils.go @@ -727,7 +727,7 @@ func SocketPath() (string, error) { func LookupUser(name string) (*user.User, error) { // Assume UID look up first, if it fails lookup by username if u, err := user.LookupId(name); err == nil { - return u, err + return u, nil } return user.Lookup(name) } diff --git a/pkg/util/utils_darwin.go b/pkg/util/utils_darwin.go index 33a46a5d4..66ae85e9c 100644 --- a/pkg/util/utils_darwin.go +++ b/pkg/util/utils_darwin.go @@ -1,4 +1,5 @@ -//+build darwin +//go:build darwin +// +build darwin package util diff --git a/pkg/util/utils_supported.go b/pkg/util/utils_supported.go index 848b35a45..50e4b1b7b 100644 --- a/pkg/util/utils_supported.go +++ b/pkg/util/utils_supported.go @@ -1,3 +1,4 @@ +//go:build !windows // +build !windows package util diff --git a/pkg/util/utils_unsupported.go b/pkg/util/utils_unsupported.go index 62805d7c8..896346493 100644 --- a/pkg/util/utils_unsupported.go +++ b/pkg/util/utils_unsupported.go @@ -1,3 +1,4 @@ +//go:build darwin || windows // +build darwin windows package util diff --git a/pkg/util/utils_windows.go b/pkg/util/utils_windows.go index 46ca5e7f1..2732124f2 100644 --- a/pkg/util/utils_windows.go +++ b/pkg/util/utils_windows.go @@ -1,3 +1,4 @@ +//go:build windows // +build windows package util diff --git a/podman.spec.rpkg b/podman.spec.rpkg index 41385dba6..937253918 100644 --- a/podman.spec.rpkg +++ b/podman.spec.rpkg @@ -144,10 +144,7 @@ Summary: (Experimental) Remote client for managing %{name} containers %description remote Remote client for managing %{name} containers. -This experimental remote client is under heavy development. Please do not -run %{name}-remote in production. - -%{name}-remote uses the version 2 API to connect to a %{name} client to +%{name}-remote uses the libpod REST API to connect to a %{name} client to manage pods, containers and container images. %{name}-remote supports ssh connections as well. diff --git a/test/checkseccomp/checkseccomp.go b/test/checkseccomp/checkseccomp.go index 9046e0955..6c188ec0d 100644 --- a/test/checkseccomp/checkseccomp.go +++ b/test/checkseccomp/checkseccomp.go @@ -1,3 +1,4 @@ +//go:build seccomp // +build seccomp package main diff --git a/test/compose/ipam_set_ip/tests.sh b/test/compose/ipam_set_ip/tests.sh index ecaf3167e..b9e761ea2 100644 --- a/test/compose/ipam_set_ip/tests.sh +++ b/test/compose/ipam_set_ip/tests.sh @@ -1,4 +1,8 @@ # -*- bash -*- -podman container inspect ipam_set_ip_test_1 --format '{{ .NetworkSettings.Networks.ipam_set_ip_net1.IPAddress }}' +ctr_name="ipam_set_ip_test_1" +if [ "$TEST_FLAVOR" = "compose_v2" ]; then + ctr_name="ipam_set_ip-test-1" +fi +podman container inspect "$ctr_name" --format '{{ .NetworkSettings.Networks.ipam_set_ip_net1.IPAddress }}' like "$output" "10.123.0.253" "$testname : ip address is set" diff --git a/test/compose/slirp4netns_opts/tests.sh b/test/compose/slirp4netns_opts/tests.sh index 1efce45c4..2d41311ad 100644 --- a/test/compose/slirp4netns_opts/tests.sh +++ b/test/compose/slirp4netns_opts/tests.sh @@ -1,6 +1,19 @@ # -*- bash -*- -output="$(cat $OUTFILE)" expected="teststring" +# Reading from the nc socket is flaky because docker-compose only starts +# the containers. We cannot know at this point if the container did already +# send the message. Give the container 5 seconds time to send the message +# to prevent flakes. +container_timeout=5 +while [ $container_timeout -gt 0 ]; do + output="$(< $OUTFILE)" + if [ -n "$output" ]; then + break + fi + sleep 1 + container_timeout=$(($container_timeout - 1)) +done + is "$output" "$expected" "$testname : nc received teststring" diff --git a/test/compose/two_networks/tests.sh b/test/compose/two_networks/tests.sh index 1cc88aa5f..af0d1fbe3 100644 --- a/test/compose/two_networks/tests.sh +++ b/test/compose/two_networks/tests.sh @@ -1,7 +1,11 @@ # -*- bash -*- -podman container inspect two_networks_con1_1 --format '{{len .NetworkSettings.Networks}}' +ctr_name="two_networks_con1_1" +if [ "$TEST_FLAVOR" = "compose_v2" ]; then + ctr_name="two_networks-con1-1" +fi +podman container inspect "$ctr_name" --format '{{len .NetworkSettings.Networks}}' is "$output" "2" "$testname : Container is connected to both networks" -podman container inspect two_networks_con1_1 --format '{{.NetworkSettings.Networks}}' +podman container inspect "$ctr_name" --format '{{.NetworkSettings.Networks}}' like "$output" "two_networks_net1" "$testname : First network name exists" like "$output" "two_networks_net2" "$testname : Second network name exists" diff --git a/test/e2e/attach_test.go b/test/e2e/attach_test.go index a7af76529..74e3a619a 100644 --- a/test/e2e/attach_test.go +++ b/test/e2e/attach_test.go @@ -1,7 +1,6 @@ package integration import ( - "os" "syscall" "time" @@ -20,12 +19,11 @@ var _ = Describe("Podman attach", func() { BeforeEach(func() { tempdir, err = CreateTempDirInTempDir() - if err != nil { - os.Exit(1) - } + Expect(err).To(BeNil()) podmanTest = PodmanTestCreate(tempdir) podmanTest.Setup() - podmanTest.SeedImages() + err = podmanTest.SeedImages() + Expect(err).To(BeNil()) }) AfterEach(func() { diff --git a/test/e2e/checkpoint_test.go b/test/e2e/checkpoint_test.go index 5abc672e9..7b2dd89c9 100644 --- a/test/e2e/checkpoint_test.go +++ b/test/e2e/checkpoint_test.go @@ -37,12 +37,12 @@ var _ = Describe("Podman checkpoint", func() { BeforeEach(func() { SkipIfRootless("checkpoint not supported in rootless mode") tempdir, err = CreateTempDirInTempDir() - if err != nil { - os.Exit(1) - } + Expect(err).To(BeNil()) + podmanTest = PodmanTestCreate(tempdir) podmanTest.Setup() - podmanTest.SeedImages() + err = podmanTest.SeedImages() + Expect(err).To(BeNil()) // Check if the runtime implements checkpointing. Currently only // runc's checkpoint/restore implementation is supported. cmd := exec.Command(podmanTest.OCIRuntime, "checkpoint", "--help") diff --git a/test/e2e/commit_test.go b/test/e2e/commit_test.go index 6bcf17bfe..78b607f1e 100644 --- a/test/e2e/commit_test.go +++ b/test/e2e/commit_test.go @@ -21,12 +21,11 @@ var _ = Describe("Podman commit", func() { BeforeEach(func() { tempdir, err = CreateTempDirInTempDir() - if err != nil { - os.Exit(1) - } + Expect(err).To(BeNil()) podmanTest = PodmanTestCreate(tempdir) podmanTest.Setup() - podmanTest.SeedImages() + err = podmanTest.SeedImages() + Expect(err).To(BeNil()) }) AfterEach(func() { diff --git a/test/e2e/common_test.go b/test/e2e/common_test.go index bc6d89fad..cb6574f23 100644 --- a/test/e2e/common_test.go +++ b/test/e2e/common_test.go @@ -809,7 +809,8 @@ func (p *PodmanTestIntegration) RestoreArtifactToCache(image string) error { func populateCache(podman *PodmanTestIntegration) { for _, image := range CACHE_IMAGES { - podman.RestoreArtifactToCache(image) + err := podman.RestoreArtifactToCache(image) + Expect(err).To(BeNil()) } // logformatter uses this to recognize the first test fmt.Printf("-----------------------------\n") diff --git a/test/e2e/container_clone_test.go b/test/e2e/container_clone_test.go index bebc6872b..a327bb8ed 100644 --- a/test/e2e/container_clone_test.go +++ b/test/e2e/container_clone_test.go @@ -184,4 +184,41 @@ var _ = Describe("Podman container clone", func() { Expect(ctrInspect.InspectContainerToJSON()[0].HostConfig.NetworkMode).Should(Equal(runInspect.InspectContainerToJSON()[0].HostConfig.NetworkMode)) }) + It("podman container clone to a pod", func() { + createPod := podmanTest.Podman([]string{"pod", "create", "--share", "uts", "--name", "foo-pod"}) + createPod.WaitWithDefaultTimeout() + Expect(createPod).To(Exit(0)) + + ctr := podmanTest.RunTopContainer("ctr") + ctr.WaitWithDefaultTimeout() + Expect(ctr).Should(Exit(0)) + + clone := podmanTest.Podman([]string{"container", "clone", "--name", "cloned", "--pod", "foo-pod", "ctr"}) + clone.WaitWithDefaultTimeout() + Expect(clone).To(Exit(0)) + + ctrInspect := podmanTest.Podman([]string{"inspect", "cloned"}) + ctrInspect.WaitWithDefaultTimeout() + Expect(ctrInspect).Should(Exit(0)) + + Expect(ctrInspect.InspectContainerToJSON()[0].Pod).Should(Equal(createPod.OutputToString())) + + Expect(ctrInspect.InspectContainerToJSON()[0].HostConfig.NetworkMode).Should(Not(ContainSubstring("container:"))) + + createPod = podmanTest.Podman([]string{"pod", "create", "--share", "uts,net", "--name", "bar-pod"}) + createPod.WaitWithDefaultTimeout() + Expect(createPod).To(Exit(0)) + + clone = podmanTest.Podman([]string{"container", "clone", "--name", "cloned2", "--pod", "bar-pod", "ctr"}) + clone.WaitWithDefaultTimeout() + Expect(clone).To(Exit(0)) + + ctrInspect = podmanTest.Podman([]string{"inspect", "cloned2"}) + ctrInspect.WaitWithDefaultTimeout() + Expect(ctrInspect).Should(Exit(0)) + + Expect(ctrInspect.InspectContainerToJSON()[0].Pod).Should(Equal(createPod.OutputToString())) + + Expect(ctrInspect.InspectContainerToJSON()[0].HostConfig.NetworkMode).Should(ContainSubstring("container:")) + }) }) diff --git a/test/e2e/create_test.go b/test/e2e/create_test.go index 339fa66d8..4c3b5604a 100644 --- a/test/e2e/create_test.go +++ b/test/e2e/create_test.go @@ -24,12 +24,11 @@ var _ = Describe("Podman create", func() { BeforeEach(func() { tempdir, err = CreateTempDirInTempDir() - if err != nil { - os.Exit(1) - } + Expect(err).To(BeNil()) podmanTest = PodmanTestCreate(tempdir) podmanTest.Setup() - podmanTest.SeedImages() + err = podmanTest.SeedImages() + Expect(err).To(BeNil()) }) AfterEach(func() { diff --git a/test/e2e/healthcheck_run_test.go b/test/e2e/healthcheck_run_test.go index 866edbf0e..757eaed20 100644 --- a/test/e2e/healthcheck_run_test.go +++ b/test/e2e/healthcheck_run_test.go @@ -54,6 +54,16 @@ var _ = Describe("Podman healthcheck run", func() { Expect(hc).Should(Exit(125)) }) + It("podman disable healthcheck with --no-healthcheck must not show starting on status", func() { + session := podmanTest.Podman([]string{"run", "-dt", "--no-healthcheck", "--name", "hc", healthcheck}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + hc := podmanTest.Podman([]string{"container", "inspect", "--format", "{{.State.Health.Status}}", "hc"}) + hc.WaitWithDefaultTimeout() + Expect(hc).Should(Exit(0)) + Expect(hc.OutputToString()).To(Not(ContainSubstring("starting"))) + }) + It("podman run healthcheck and logs should contain healthcheck output", func() { session := podmanTest.Podman([]string{"run", "--name", "test-logs", "-dt", "--health-interval", "1s", "--health-cmd", "echo working", "busybox", "sleep", "3600"}) session.WaitWithDefaultTimeout() diff --git a/test/e2e/import_test.go b/test/e2e/import_test.go index 884eae18e..f62df23d9 100644 --- a/test/e2e/import_test.go +++ b/test/e2e/import_test.go @@ -52,6 +52,26 @@ var _ = Describe("Podman import", func() { Expect(results).Should(Exit(0)) }) + It("podman import with custom os, arch and variant", func() { + outfile := filepath.Join(podmanTest.TempDir, "container.tar") + _, ec, cid := podmanTest.RunLsContainer("") + Expect(ec).To(Equal(0)) + + export := podmanTest.Podman([]string{"export", "-o", outfile, cid}) + export.WaitWithDefaultTimeout() + Expect(export).Should(Exit(0)) + + importImage := podmanTest.Podman([]string{"import", "--os", "testos", "--arch", "testarch", outfile, "foobar.com/imported-image:latest"}) + importImage.WaitWithDefaultTimeout() + Expect(importImage).Should(Exit(0)) + + results := podmanTest.Podman([]string{"inspect", "--type", "image", "foobar.com/imported-image:latest"}) + results.WaitWithDefaultTimeout() + Expect(results).Should(Exit(0)) + Expect(results.OutputToString()).To(ContainSubstring("testos")) + Expect(results.OutputToString()).To(ContainSubstring("testarch")) + }) + It("podman import without reference", func() { outfile := filepath.Join(podmanTest.TempDir, "container.tar") _, ec, cid := podmanTest.RunLsContainer("") diff --git a/test/e2e/inspect_test.go b/test/e2e/inspect_test.go index 3943a5e87..bb5a3a6ad 100644 --- a/test/e2e/inspect_test.go +++ b/test/e2e/inspect_test.go @@ -86,6 +86,7 @@ var _ = Describe("Podman inspect", func() { It("podman inspect container with GO format for ConmonPidFile", func() { session, ec, _ := podmanTest.RunLsContainer("test1") + session.WaitWithDefaultTimeout() Expect(ec).To(Equal(0)) session = podmanTest.Podman([]string{"inspect", "--format", "{{.ConmonPidFile}}", "test1"}) @@ -94,7 +95,8 @@ var _ = Describe("Podman inspect", func() { }) It("podman inspect container with size", func() { - _, ec, _ := podmanTest.RunLsContainer("sizetest") + session, ec, _ := podmanTest.RunLsContainer("sizetest") + session.WaitWithDefaultTimeout() Expect(ec).To(Equal(0)) result := podmanTest.Podman([]string{"inspect", "--size", "sizetest"}) @@ -107,6 +109,7 @@ var _ = Describe("Podman inspect", func() { It("podman inspect container and image", func() { ls, ec, _ := podmanTest.RunLsContainer("") + ls.WaitWithDefaultTimeout() Expect(ec).To(Equal(0)) cid := ls.OutputToString() @@ -118,6 +121,7 @@ var _ = Describe("Podman inspect", func() { It("podman inspect container and filter for Image{ID}", func() { ls, ec, _ := podmanTest.RunLsContainer("") + ls.WaitWithDefaultTimeout() Expect(ec).To(Equal(0)) cid := ls.OutputToString() @@ -134,6 +138,7 @@ var _ = Describe("Podman inspect", func() { It("podman inspect container and filter for CreateCommand", func() { ls, ec, _ := podmanTest.RunLsContainer("") + ls.WaitWithDefaultTimeout() Expect(ec).To(Equal(0)) cid := ls.OutputToString() @@ -529,6 +534,7 @@ var _ = Describe("Podman inspect", func() { It("podman inspect container with GO format for PidFile", func() { SkipIfRemote("pidfile not handled by remote") session, ec, _ := podmanTest.RunLsContainer("test1") + session.WaitWithDefaultTimeout() Expect(ec).To(Equal(0)) session = podmanTest.Podman([]string{"inspect", "--format", "{{.PidFile}}", "test1"}) diff --git a/test/e2e/libpod_suite_test.go b/test/e2e/libpod_suite_test.go index ccd7c771e..cf81a0348 100644 --- a/test/e2e/libpod_suite_test.go +++ b/test/e2e/libpod_suite_test.go @@ -1,3 +1,4 @@ +//go:build !remote // +build !remote package integration diff --git a/test/e2e/login_logout_test.go b/test/e2e/login_logout_test.go index 1280b3e83..77549a9a8 100644 --- a/test/e2e/login_logout_test.go +++ b/test/e2e/login_logout_test.go @@ -417,12 +417,12 @@ var _ = Describe("Podman login and logout", func() { Expect(authInfo).NotTo(HaveKey(testRepos[1])) }) - It("podman login with repository invalid arguments", func() { + It("podman login with http{s} prefix", func() { authFile := filepath.Join(podmanTest.TempDir, "auth.json") for _, invalidArg := range []string{ "https://" + server + "/podmantest", - server + "/podmantest/image:latest", + "http://" + server + "/podmantest/image:latest", } { session := podmanTest.Podman([]string{ "login", @@ -432,7 +432,7 @@ var _ = Describe("Podman login and logout", func() { invalidArg, }) session.WaitWithDefaultTimeout() - Expect(session).Should(ExitWithError()) + Expect(session).To(Exit(0)) } }) diff --git a/test/e2e/network_create_test.go b/test/e2e/network_create_test.go index 395759ee6..82b99bd68 100644 --- a/test/e2e/network_create_test.go +++ b/test/e2e/network_create_test.go @@ -416,8 +416,8 @@ var _ = Describe("Podman network create", func() { subnet1 := "10.10.3.0/24" gw1 := "10.10.3.10" range1 := "10.10.3.0/26" - subnet2 := "fd52:2a5a:747e:3acd::/64" - gw2 := "fd52:2a5a:747e:3acd::10" + subnet2 := "fd52:2a5a:747e:3ace::/64" + gw2 := "fd52:2a5a:747e:3ace::10" nc := podmanTest.Podman([]string{"network", "create", "--subnet", subnet1, "--gateway", gw1, "--ip-range", range1, "--subnet", subnet2, "--gateway", gw2, name}) nc.WaitWithDefaultTimeout() defer podmanTest.removeNetwork(name) @@ -440,7 +440,7 @@ var _ = Describe("Podman network create", func() { name := "subnets-" + stringid.GenerateNonCryptoID() subnet1 := "10.10.3.0/24" gw1 := "10.10.3.10" - gw2 := "fd52:2a5a:747e:3acd::10" + gw2 := "fd52:2a5a:747e:3acf::10" nc := podmanTest.Podman([]string{"network", "create", "--subnet", subnet1, "--gateway", gw1, "--gateway", gw2, name}) nc.WaitWithDefaultTimeout() Expect(nc).To(Exit(125)) diff --git a/test/e2e/play_build_test.go b/test/e2e/play_build_test.go index 849ba7162..96785c569 100644 --- a/test/e2e/play_build_test.go +++ b/test/e2e/play_build_test.go @@ -1,3 +1,4 @@ +//go:build !remote // +build !remote // build for play kube is not supported on remote yet. diff --git a/test/e2e/run_apparmor_test.go b/test/e2e/run_apparmor_test.go index e6526217a..64a01deb7 100644 --- a/test/e2e/run_apparmor_test.go +++ b/test/e2e/run_apparmor_test.go @@ -1,3 +1,4 @@ +//go:build !remote // +build !remote package integration diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go index 91a2eddad..f4a6e5733 100644 --- a/test/e2e/run_test.go +++ b/test/e2e/run_test.go @@ -498,7 +498,7 @@ var _ = Describe("Podman run", func() { session = podmanTest.Podman([]string{"run", "--rm", "--user", "root", ALPINE, "grep", "CapInh", "/proc/self/status"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - Expect(session.OutputToString()).To(ContainSubstring("00000000a80425fb")) + Expect(session.OutputToString()).To(ContainSubstring("0000000000000000")) session = podmanTest.Podman([]string{"run", "--rm", ALPINE, "grep", "CapBnd", "/proc/self/status"}) session.WaitWithDefaultTimeout() @@ -533,7 +533,7 @@ var _ = Describe("Podman run", func() { session = podmanTest.Podman([]string{"run", "--user=0:0", "--cap-add=DAC_OVERRIDE", "--rm", ALPINE, "grep", "CapInh", "/proc/self/status"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - Expect(session.OutputToString()).To(ContainSubstring("00000000a80425fb")) + Expect(session.OutputToString()).To(ContainSubstring("0000000000000000")) if os.Geteuid() > 0 { if os.Getenv("SKIP_USERNS") != "" { @@ -550,7 +550,7 @@ var _ = Describe("Podman run", func() { session = podmanTest.Podman([]string{"run", "--userns=keep-id", "--privileged", "--rm", ALPINE, "grep", "CapInh", "/proc/self/status"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - Expect(session.OutputToString()).To(ContainSubstring("0000000000000000")) + Expect(session.OutputToString()).To(ContainSubstring("0000000000000002")) session = podmanTest.Podman([]string{"run", "--userns=keep-id", "--cap-add=DAC_OVERRIDE", "--rm", ALPINE, "grep", "CapInh", "/proc/self/status"}) session.WaitWithDefaultTimeout() diff --git a/test/e2e/system_df_test.go b/test/e2e/system_df_test.go index 2d75316ad..a9fa5f4ac 100644 --- a/test/e2e/system_df_test.go +++ b/test/e2e/system_df_test.go @@ -41,11 +41,17 @@ var _ = Describe("podman system df", func() { session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - session = podmanTest.Podman([]string{"volume", "create", "data"}) + // run two containers with volumes to create something in the volume + session = podmanTest.Podman([]string{"run", "-v", "data1:/data", "--name", "container1", BB, "sh", "-c", "echo test > /data/1"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - session = podmanTest.Podman([]string{"create", "-v", "data:/data", "--name", "container1", BB}) + session = podmanTest.Podman([]string{"run", "-v", "data2:/data", "--name", "container2", BB, "sh", "-c", "echo test > /data/1"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + // remove one container, we keep the volume + session = podmanTest.Podman([]string{"rm", "container2"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) @@ -61,9 +67,10 @@ var _ = Describe("podman system df", func() { images := strings.Fields(session.OutputToStringArray()[1]) containers := strings.Fields(session.OutputToStringArray()[2]) volumes := strings.Fields(session.OutputToStringArray()[3]) - Expect(images[1]).To(Equal(string(totImages))) - Expect(containers[1]).To(Equal("2")) - Expect(volumes[2]).To(Equal("1")) + Expect(images[1]).To(Equal(string(totImages)), "total images expected") + Expect(containers[1]).To(Equal("2"), "total containers expected") + Expect(volumes[2]).To(Equal("2"), "total volumes expected") + Expect(volumes[6]).To(Equal("(50%)"), "percentage usage expected") }) It("podman system df image with no tag", func() { diff --git a/test/system/010-images.bats b/test/system/010-images.bats index dbf4b2828..257508418 100644 --- a/test/system/010-images.bats +++ b/test/system/010-images.bats @@ -303,4 +303,13 @@ Deleted: $pauseID" run_podman image exists $IMAGE } +@test "podman rmi --ignore" { + random_image_name=$(random_string) + random_image_name=${random_image_name,,} # name must be lowercase + run_podman 1 rmi $random_image_name + is "$output" "Error: $random_image_name: image not known.*" + run_podman rmi --ignore $random_image_name + is "$output" "" +} + # vim: filetype=sh diff --git a/test/system/200-pod.bats b/test/system/200-pod.bats index ca931e244..f5fe41924 100644 --- a/test/system/200-pod.bats +++ b/test/system/200-pod.bats @@ -6,7 +6,7 @@ load helpers function teardown() { run_podman pod rm -f -t 0 -a run_podman rm -f -t 0 -a - run_podman ? rmi $(pause_image) + run_podman rmi --ignore $(pause_image) basic_teardown } @@ -317,16 +317,17 @@ EOF @test "podman pod create should fail when infra-name is already in use" { local infra_name="infra_container_$(random_string 10 | tr A-Z a-z)" + local infra_image="k8s.gcr.io/pause:3.5" local pod_name="$(random_string 10 | tr A-Z a-z)" - run_podman --noout pod create --name $pod_name --infra-name "$infra_name" --infra-image "k8s.gcr.io/pause:3.5" - is "$output" "" "output should be empty" + run_podman --noout pod create --name $pod_name --infra-name "$infra_name" --infra-image "$infra_image" + is "$output" "" "output from pod create should be empty" run_podman '?' pod create --infra-name "$infra_name" if [ $status -eq 0 ]; then die "Podman should fail when user try to create two pods with the same infra-name value" fi run_podman pod rm -f $pod_name - run_podman images -a + run_podman rmi $infra_image } @test "podman pod create --share" { diff --git a/test/system/250-systemd.bats b/test/system/250-systemd.bats index 3847d9510..6c72e14e8 100644 --- a/test/system/250-systemd.bats +++ b/test/system/250-systemd.bats @@ -281,6 +281,13 @@ LISTEN_FDNAMES=listen_fdnames" | sort) is "$output" "" "output should be empty" } +@test "podman --systemd sets container_uuid" { + run_podman run --systemd=always --name test $IMAGE printenv container_uuid + container_uuid=$output + run_podman inspect test --format '{{ .ID }}' + is "${container_uuid}" "${output:0:32}" "UUID should be first 32 chars of Container id" +} + # https://github.com/containers/podman/issues/13153 @test "podman rootless-netns slirp4netns process should be in different cgroup" { is_rootless || skip "only meaningful for rootless" diff --git a/test/utils/common_function_test.go b/test/utils/common_function_test.go index 810d9f2a5..6323b44eb 100644 --- a/test/utils/common_function_test.go +++ b/test/utils/common_function_test.go @@ -51,7 +51,8 @@ var _ = Describe("Common functions test", func() { txt := fmt.Sprintf("ID=%s\nVERSION_ID=%s", id, ver) if !empty { f, _ := os.Create(path) - f.WriteString(txt) + _, err := f.WriteString(txt) + Expect(err).To(BeNil(), "Failed to write data.") f.Close() } @@ -102,9 +103,10 @@ var _ = Describe("Common functions test", func() { Item2: []string{"test"}, } - testByte, _ := json.Marshal(testData) - err := WriteJSONFile(testByte, "/tmp/testJSON") + testByte, err := json.Marshal(testData) + Expect(err).To(BeNil(), "Failed to marshal data.") + err = WriteJSONFile(testByte, "/tmp/testJSON") Expect(err).To(BeNil(), "Failed to write JSON to file.") read, err := os.Open("/tmp/testJSON") @@ -135,7 +137,8 @@ var _ = Describe("Common functions test", func() { } if createFile { f, _ := os.Create(path) - f.WriteString(txt) + _, err := f.WriteString(txt) + Expect(err).To(BeNil(), "Failed to write data.") f.Close() } ProcessOneCgroupPath = path diff --git a/test/utils/matchers.go b/test/utils/matchers.go index 288779b63..0c0948e4b 100644 --- a/test/utils/matchers.go +++ b/test/utils/matchers.go @@ -13,7 +13,7 @@ import ( "github.com/onsi/gomega/types" ) -// HaveActiveService verifies the given service is the active service +// HaveActiveService verifies the given service is the active service. func HaveActiveService(name interface{}) OmegaMatcher { return WithTransform( func(cfg *config.Config) string { @@ -86,7 +86,7 @@ type URLMatcher struct { matchers.EqualMatcher } -// VerifyURL matches when actual is a valid URL and matches expected +// VerifyURL matches when actual is a valid URL and matches expected. func VerifyURL(uri interface{}) OmegaMatcher { return &URLMatcher{matchers.EqualMatcher{Expected: uri}} } @@ -129,7 +129,7 @@ func ExitWithError(optionalExitCode ...int) *ExitMatcher { return &ExitMatcher{Expected: exitCode} } -// Match follows gexec.Matcher interface +// Match follows gexec.Matcher interface. func (matcher *ExitMatcher) Match(actual interface{}) (success bool, err error) { exiter, ok := actual.(gexec.Exiter) if !ok { @@ -184,7 +184,7 @@ func (matcher *ValidJSONMatcher) Match(actual interface{}) (success bool, err er var i interface{} if err := json.Unmarshal([]byte(s), &i); err != nil { - return false, nil + return false, err } return true, nil } diff --git a/test/utils/utils.go b/test/utils/utils.go index 8fe45dca0..a6295cd19 100644 --- a/test/utils/utils.go +++ b/test/utils/utils.go @@ -479,7 +479,10 @@ func IsCommandAvailable(command string) bool { func WriteJSONFile(data []byte, filePath string) error { var jsonData map[string]interface{} json.Unmarshal(data, &jsonData) - formatJSON, _ := json.MarshalIndent(jsonData, "", " ") + formatJSON, err := json.MarshalIndent(jsonData, "", " ") + if err != nil { + return err + } return ioutil.WriteFile(filePath, formatJSON, 0644) } diff --git a/troubleshooting.md b/troubleshooting.md index 32f14c1ee..f59963271 100644 --- a/troubleshooting.md +++ b/troubleshooting.md @@ -1177,3 +1177,18 @@ A side-note: Using [__--userns=keep-id__](https://docs.podman.io/en/latest/markd can sometimes be an alternative solution, but it forces the regular user's host UID to be mapped to the same UID inside the container so it provides less flexibility than using __--uidmap__ and __--gidmap__. + +### 35) Images in the additional stores can be deleted even if there are containers using them + +When an image in an additional store is used, it is not locked thus it +can be deleted even if there are containers using it. + +#### Symptom + +WARN[0000] Can't stat lower layer "/var/lib/containers/storage/overlay/l/7HS76F2P5N73FDUKUQAOJA3WI5" because it does not exist. Going through storage to recreate the missing symlinks. + +#### Solution + +It is the user responsibility to make sure images in an additional +store are not deleted while being used by containers in another +store. diff --git a/utils/ports.go b/utils/ports.go index 0a4f67dcc..57a6f8275 100644 --- a/utils/ports.go +++ b/utils/ports.go @@ -7,7 +7,7 @@ import ( "github.com/pkg/errors" ) -// Find a random, open port on the host +// Find a random, open port on the host. func GetRandomPort() (int, error) { l, err := net.Listen("tcp", ":0") if err != nil { diff --git a/utils/utils.go b/utils/utils.go index 22f0cb12f..d0e3dbb46 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -21,7 +21,7 @@ import ( ) // ExecCmd executes a command with args and returns its output as a string along -// with an error, if any +// with an error, if any. func ExecCmd(name string, args ...string) (string, error) { cmd := exec.Command(name, args...) var stdout bytes.Buffer diff --git a/utils/utils_supported.go b/utils/utils_supported.go index 561372607..ab2de2ce1 100644 --- a/utils/utils_supported.go +++ b/utils/utils_supported.go @@ -1,3 +1,4 @@ +//go:build linux || darwin // +build linux darwin package utils diff --git a/utils/utils_windows.go b/utils/utils_windows.go index 1a2196029..2c159ab06 100644 --- a/utils/utils_windows.go +++ b/utils/utils_windows.go @@ -1,3 +1,4 @@ +//go:build windows // +build windows package utils diff --git a/vendor/github.com/containerd/stargz-snapshotter/estargz/go.mod b/vendor/github.com/containerd/stargz-snapshotter/estargz/go.mod index 184421370..895d6645a 100644 --- a/vendor/github.com/containerd/stargz-snapshotter/estargz/go.mod +++ b/vendor/github.com/containerd/stargz-snapshotter/estargz/go.mod @@ -3,7 +3,7 @@ module github.com/containerd/stargz-snapshotter/estargz go 1.16 require ( - github.com/klauspost/compress v1.15.0 + github.com/klauspost/compress v1.15.1 github.com/opencontainers/go-digest v1.0.0 github.com/vbatts/tar-split v0.11.2 golang.org/x/sync v0.0.0-20201207232520-09787c993a3a diff --git a/vendor/github.com/containerd/stargz-snapshotter/estargz/go.sum b/vendor/github.com/containerd/stargz-snapshotter/estargz/go.sum index 0eb0b7a10..8b44342da 100644 --- a/vendor/github.com/containerd/stargz-snapshotter/estargz/go.sum +++ b/vendor/github.com/containerd/stargz-snapshotter/estargz/go.sum @@ -1,8 +1,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/klauspost/compress v1.15.0 h1:xqfchp4whNFxn5A4XFyyYtitiWI8Hy5EW59jEwcyL6U= -github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/klauspost/compress v1.15.1 h1:y9FcTHGyrebwfP0ZZqFiaxTaiDnUrGkJkI+f583BL1A= +github.com/klauspost/compress v1.15.1/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= diff --git a/vendor/github.com/containers/common/libimage/runtime.go b/vendor/github.com/containers/common/libimage/runtime.go index 559a9a6a6..2191e3c4a 100644 --- a/vendor/github.com/containers/common/libimage/runtime.go +++ b/vendor/github.com/containers/common/libimage/runtime.go @@ -592,6 +592,8 @@ type RemoveImagesOptions struct { // containers using a specific image. By default, all containers in // the local containers storage will be removed (if Force is set). RemoveContainerFunc RemoveContainerFunc + // Ignore if a specified image does not exist and do not throw an error. + Ignore bool // IsExternalContainerFunc allows for checking whether the specified // container is an external one (when containers=external filter is // used). The definition of an external container can be set by @@ -677,6 +679,9 @@ func (r *Runtime) RemoveImages(ctx context.Context, names []string, options *Rem for _, name := range names { img, resolvedName, err := r.LookupImage(name, lookupOptions) if err != nil { + if options.Ignore && errors.Is(err, storage.ErrImageUnknown) { + continue + } appendError(err) continue } diff --git a/vendor/github.com/containers/common/libnetwork/cni/cni_conversion.go b/vendor/github.com/containers/common/libnetwork/cni/cni_conversion.go index 5574b2b1c..8c4eeff9d 100644 --- a/vendor/github.com/containers/common/libnetwork/cni/cni_conversion.go +++ b/vendor/github.com/containers/common/libnetwork/cni/cni_conversion.go @@ -1,3 +1,4 @@ +//go:build linux // +build linux package cni @@ -128,15 +129,21 @@ func findPluginByName(plugins []*libcni.NetworkConfig, name string) bool { // It returns an array of subnets and an extra bool if dhcp is configured. func convertIPAMConfToNetwork(network *types.Network, ipam *ipamConfig, confPath string) error { if ipam.PluginType == types.DHCPIPAMDriver { - network.IPAMOptions["driver"] = types.DHCPIPAMDriver + network.IPAMOptions[types.Driver] = types.DHCPIPAMDriver return nil } if ipam.PluginType != types.HostLocalIPAMDriver { - return errors.Errorf("unsupported ipam plugin %s in %s", ipam.PluginType, confPath) + // This is not an error. While we only support certain ipam drivers, we + // cannot make it fail for unsupported ones. CNI is still able to use them, + // just our translation logic cannot convert this into a Network. + // For the same reason this is not warning, it would just be annoying for + // everyone using a unknown ipam driver. + logrus.Infof("unsupported ipam plugin %q in %s", ipam.PluginType, confPath) + return nil } - network.IPAMOptions["driver"] = types.HostLocalIPAMDriver + network.IPAMOptions[types.Driver] = types.HostLocalIPAMDriver for _, r := range ipam.Ranges { for _, ipam := range r { s := types.Subnet{} diff --git a/vendor/github.com/containers/common/libnetwork/cni/cni_exec.go b/vendor/github.com/containers/common/libnetwork/cni/cni_exec.go index c66e7ef5d..6bfa8d63b 100644 --- a/vendor/github.com/containers/common/libnetwork/cni/cni_exec.go +++ b/vendor/github.com/containers/common/libnetwork/cni/cni_exec.go @@ -16,6 +16,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build linux // +build linux package cni diff --git a/vendor/github.com/containers/common/libnetwork/cni/cni_types.go b/vendor/github.com/containers/common/libnetwork/cni/cni_types.go index fbfcd49ad..9ee159886 100644 --- a/vendor/github.com/containers/common/libnetwork/cni/cni_types.go +++ b/vendor/github.com/containers/common/libnetwork/cni/cni_types.go @@ -1,3 +1,4 @@ +//go:build linux // +build linux package cni diff --git a/vendor/github.com/containers/common/libnetwork/cni/config.go b/vendor/github.com/containers/common/libnetwork/cni/config.go index e801e1469..8b300a03b 100644 --- a/vendor/github.com/containers/common/libnetwork/cni/config.go +++ b/vendor/github.com/containers/common/libnetwork/cni/config.go @@ -1,3 +1,4 @@ +//go:build linux // +build linux package cni @@ -197,12 +198,12 @@ func createIPMACVLAN(network *types.Network) error { } } if len(network.Subnets) == 0 { - network.IPAMOptions["driver"] = types.DHCPIPAMDriver + network.IPAMOptions[types.Driver] = types.DHCPIPAMDriver if network.Internal { return errors.New("internal is not supported with macvlan and dhcp ipam driver") } } else { - network.IPAMOptions["driver"] = types.HostLocalIPAMDriver + network.IPAMOptions[types.Driver] = types.HostLocalIPAMDriver } return nil } diff --git a/vendor/github.com/containers/common/libnetwork/cni/network.go b/vendor/github.com/containers/common/libnetwork/cni/network.go index 29866062e..82b9cbd2e 100644 --- a/vendor/github.com/containers/common/libnetwork/cni/network.go +++ b/vendor/github.com/containers/common/libnetwork/cni/network.go @@ -1,3 +1,4 @@ +//go:build linux // +build linux package cni diff --git a/vendor/github.com/containers/common/libnetwork/cni/run.go b/vendor/github.com/containers/common/libnetwork/cni/run.go index af05d9d9d..8bea87893 100644 --- a/vendor/github.com/containers/common/libnetwork/cni/run.go +++ b/vendor/github.com/containers/common/libnetwork/cni/run.go @@ -1,3 +1,4 @@ +//go:build linux // +build linux package cni diff --git a/vendor/github.com/containers/common/libnetwork/internal/util/bridge.go b/vendor/github.com/containers/common/libnetwork/internal/util/bridge.go index d81b78a6f..5a4752e2b 100644 --- a/vendor/github.com/containers/common/libnetwork/internal/util/bridge.go +++ b/vendor/github.com/containers/common/libnetwork/internal/util/bridge.go @@ -27,7 +27,7 @@ func CreateBridge(n NetUtil, network *types.Network, usedNetworks []*net.IPNet, } } - if network.IPAMOptions["driver"] != types.DHCPIPAMDriver { + if network.IPAMOptions[types.Driver] != types.DHCPIPAMDriver { if len(network.Subnets) == 0 { freeSubnet, err := GetFreeIPv4NetworkSubnet(usedNetworks, subnetPools) if err != nil { @@ -63,7 +63,7 @@ func CreateBridge(n NetUtil, network *types.Network, usedNetworks []*net.IPNet, network.Subnets = append(network.Subnets, *freeSubnet) } } - network.IPAMOptions["driver"] = types.HostLocalIPAMDriver + network.IPAMOptions[types.Driver] = types.HostLocalIPAMDriver } return nil } diff --git a/vendor/github.com/containers/common/libnetwork/internal/util/validate.go b/vendor/github.com/containers/common/libnetwork/internal/util/validate.go index ac3934f8d..4dd44110a 100644 --- a/vendor/github.com/containers/common/libnetwork/internal/util/validate.go +++ b/vendor/github.com/containers/common/libnetwork/internal/util/validate.go @@ -109,7 +109,7 @@ func validatePerNetworkOpts(network *types.Network, netOpts *types.PerNetworkOpt if netOpts.InterfaceName == "" { return errors.Errorf("interface name on network %s is empty", network.Name) } - if network.IPAMOptions["driver"] == types.HostLocalIPAMDriver { + if network.IPAMOptions[types.Driver] == types.HostLocalIPAMDriver { outer: for _, ip := range netOpts.StaticIPs { for _, s := range network.Subnets { diff --git a/vendor/github.com/containers/common/libnetwork/netavark/config.go b/vendor/github.com/containers/common/libnetwork/netavark/config.go index d42062927..99b4e0308 100644 --- a/vendor/github.com/containers/common/libnetwork/netavark/config.go +++ b/vendor/github.com/containers/common/libnetwork/netavark/config.go @@ -1,3 +1,4 @@ +//go:build linux // +build linux package netavark @@ -130,6 +131,7 @@ func (n *netavarkNetwork) networkCreate(newNetwork *types.Network, defaultNet bo if err != nil { return nil, err } + defer f.Close() enc := json.NewEncoder(f) enc.SetIndent("", " ") err = enc.Encode(newNetwork) @@ -154,7 +156,7 @@ func createMacvlan(network *types.Network) error { if len(network.Subnets) == 0 { return errors.Errorf("macvlan driver needs at least one subnet specified, DHCP is not supported with netavark") } - network.IPAMOptions["driver"] = types.HostLocalIPAMDriver + network.IPAMOptions[types.Driver] = types.HostLocalIPAMDriver // validate the given options, we do not need them but just check to make sure they are valid for key, value := range network.Options { diff --git a/vendor/github.com/containers/common/libnetwork/netavark/const.go b/vendor/github.com/containers/common/libnetwork/netavark/const.go index 9709315c6..29a7b4f2a 100644 --- a/vendor/github.com/containers/common/libnetwork/netavark/const.go +++ b/vendor/github.com/containers/common/libnetwork/netavark/const.go @@ -1,3 +1,4 @@ +//go:build linux // +build linux package netavark diff --git a/vendor/github.com/containers/common/libnetwork/netavark/exec.go b/vendor/github.com/containers/common/libnetwork/netavark/exec.go index 1812b9084..ac87c5438 100644 --- a/vendor/github.com/containers/common/libnetwork/netavark/exec.go +++ b/vendor/github.com/containers/common/libnetwork/netavark/exec.go @@ -1,3 +1,4 @@ +//go:build linux // +build linux package netavark diff --git a/vendor/github.com/containers/common/libnetwork/netavark/ipam.go b/vendor/github.com/containers/common/libnetwork/netavark/ipam.go index f99d099ca..c0535515a 100644 --- a/vendor/github.com/containers/common/libnetwork/netavark/ipam.go +++ b/vendor/github.com/containers/common/libnetwork/netavark/ipam.go @@ -1,3 +1,4 @@ +//go:build linux // +build linux package netavark @@ -361,7 +362,7 @@ func (n *netavarkNetwork) deallocIPs(opts *types.NetworkOptions) error { // it checks the ipam driver and if subnets are set func requiresIPAMAlloc(network *types.Network) bool { // only do host allocation when driver is set to HostLocalIPAMDriver or unset - switch network.IPAMOptions["driver"] { + switch network.IPAMOptions[types.Driver] { case "", types.HostLocalIPAMDriver: default: return false diff --git a/vendor/github.com/containers/common/libnetwork/netavark/network.go b/vendor/github.com/containers/common/libnetwork/netavark/network.go index d20947cfd..166d5e31a 100644 --- a/vendor/github.com/containers/common/libnetwork/netavark/network.go +++ b/vendor/github.com/containers/common/libnetwork/netavark/network.go @@ -1,3 +1,4 @@ +//go:build linux // +build linux package netavark diff --git a/vendor/github.com/containers/common/libnetwork/netavark/run.go b/vendor/github.com/containers/common/libnetwork/netavark/run.go index 0a9dc3704..c5aa181fd 100644 --- a/vendor/github.com/containers/common/libnetwork/netavark/run.go +++ b/vendor/github.com/containers/common/libnetwork/netavark/run.go @@ -1,3 +1,4 @@ +//go:build linux // +build linux package netavark @@ -44,6 +45,16 @@ func (n *netavarkNetwork) Setup(namespacePath string, options types.SetupOptions return nil, errors.Wrap(err, "failed to convert net opts") } + // Warn users if one or more networks have dns enabled + // but aardvark-dns binary is not configured + for _, network := range netavarkOpts.Networks { + if network != nil && network.DNSEnabled && n.aardvarkBinary == "" { + // this is not a fatal error we can still use container without dns + logrus.Warnf("aardvark-dns binary not found, container dns will not be enabled") + break + } + } + // trace output to get the json if logrus.IsLevelEnabled(logrus.TraceLevel) { b, err := json.Marshal(&netavarkOpts) diff --git a/vendor/github.com/containers/common/libnetwork/network/interface.go b/vendor/github.com/containers/common/libnetwork/network/interface.go index 2c8c59432..9278d7773 100644 --- a/vendor/github.com/containers/common/libnetwork/network/interface.go +++ b/vendor/github.com/containers/common/libnetwork/network/interface.go @@ -1,3 +1,4 @@ +//go:build linux // +build linux package network @@ -61,11 +62,7 @@ func NetworkBackend(store storage.Store, conf *config.Config, syslog bool) (type return "", nil, err } - aardvarkBin, err := conf.FindHelperBinary(aardvarkBinary, false) - if err != nil { - // this is not a fatal error we can still use netavark without dns - logrus.Warnf("%s binary not found, container dns will not be enabled", aardvarkBin) - } + aardvarkBin, _ := conf.FindHelperBinary(aardvarkBinary, false) confDir := conf.Network.NetworkConfigDir if confDir == "" { diff --git a/vendor/github.com/containers/common/libnetwork/types/const.go b/vendor/github.com/containers/common/libnetwork/types/const.go index b2d4a4538..5690a6058 100644 --- a/vendor/github.com/containers/common/libnetwork/types/const.go +++ b/vendor/github.com/containers/common/libnetwork/types/const.go @@ -11,6 +11,7 @@ const ( IPVLANNetworkDriver = "ipvlan" // IPAM drivers + Driver = "driver" // HostLocalIPAMDriver store the ip HostLocalIPAMDriver = "host-local" // DHCPIPAMDriver get subnet and ip from dhcp server diff --git a/vendor/github.com/containers/common/libnetwork/util/filters.go b/vendor/github.com/containers/common/libnetwork/util/filters.go index b27ca1f9a..58d79d25b 100644 --- a/vendor/github.com/containers/common/libnetwork/util/filters.go +++ b/vendor/github.com/containers/common/libnetwork/util/filters.go @@ -29,7 +29,7 @@ func createFilterFuncs(key string, filterValues []string) (types.FilterFunc, err return util.StringMatchRegexSlice(net.Name, filterValues) }, nil - case "driver": + case types.Driver: // matches network driver return func(net types.Network) bool { return util.StringInSlice(net.Driver, filterValues) diff --git a/vendor/github.com/containers/common/pkg/apparmor/apparmor_linux.go b/vendor/github.com/containers/common/pkg/apparmor/apparmor_linux.go index 735d19493..c864a189e 100644 --- a/vendor/github.com/containers/common/pkg/apparmor/apparmor_linux.go +++ b/vendor/github.com/containers/common/pkg/apparmor/apparmor_linux.go @@ -1,3 +1,4 @@ +//go:build linux && apparmor // +build linux,apparmor package apparmor diff --git a/vendor/github.com/containers/common/pkg/apparmor/apparmor_linux_template.go b/vendor/github.com/containers/common/pkg/apparmor/apparmor_linux_template.go index 021e32571..667fa9f26 100644 --- a/vendor/github.com/containers/common/pkg/apparmor/apparmor_linux_template.go +++ b/vendor/github.com/containers/common/pkg/apparmor/apparmor_linux_template.go @@ -1,3 +1,4 @@ +//go:build linux && apparmor // +build linux,apparmor package apparmor diff --git a/vendor/github.com/containers/common/pkg/apparmor/apparmor_unsupported.go b/vendor/github.com/containers/common/pkg/apparmor/apparmor_unsupported.go index 13469f1b6..dacfc2f48 100644 --- a/vendor/github.com/containers/common/pkg/apparmor/apparmor_unsupported.go +++ b/vendor/github.com/containers/common/pkg/apparmor/apparmor_unsupported.go @@ -1,3 +1,4 @@ +//go:build !linux || !apparmor // +build !linux !apparmor package apparmor diff --git a/vendor/github.com/containers/common/pkg/auth/auth.go b/vendor/github.com/containers/common/pkg/auth/auth.go index af3c8f803..6765c9e5b 100644 --- a/vendor/github.com/containers/common/pkg/auth/auth.go +++ b/vendor/github.com/containers/common/pkg/auth/auth.go @@ -4,6 +4,7 @@ import ( "bufio" "context" "fmt" + "net/url" "os" "path/filepath" "strings" @@ -165,20 +166,21 @@ func Login(ctx context.Context, systemContext *types.SystemContext, opts *LoginO // parseCredentialsKey turns the provided argument into a valid credential key // and computes the registry part. func parseCredentialsKey(arg string, acceptRepositories bool) (key, registry string, err error) { - if !acceptRepositories { - registry = getRegistryName(arg) - key = registry - return key, registry, nil + // URL arguments are replaced with their host[:port] parts. + key, err = replaceURLByHostPort(arg) + if err != nil { + return "", "", err } - key = trimScheme(arg) - if key != arg { - return "", "", errors.New("credentials key has https[s]:// prefix") + split := strings.Split(key, "/") + registry = split[0] + + if !acceptRepositories { + return registry, registry, nil } - registry = getRegistryName(key) + // Return early if the key isn't namespaced or uses an http{s} prefix. if registry == key { - // The key is not namespaced return key, registry, nil } @@ -202,24 +204,18 @@ func parseCredentialsKey(arg string, acceptRepositories bool) (key, registry str return key, registry, nil } -// getRegistryName scrubs and parses the input to get the server name -func getRegistryName(server string) string { - // removes 'http://' or 'https://' from the front of the - // server/registry string if either is there. This will be mostly used - // for user input from 'Buildah login' and 'Buildah logout'. - server = trimScheme(server) - // gets the registry from the input. If the input is of the form - // quay.io/myuser/myimage, it will parse it and just return quay.io - split := strings.Split(server, "/") - return split[0] -} - -// trimScheme removes the HTTP(s) scheme from the provided repository. -func trimScheme(repository string) string { - // removes 'http://' or 'https://' from the front of the - // server/registry string if either is there. This will be mostly used - // for user input from 'Buildah login' and 'Buildah logout'. - return strings.TrimPrefix(strings.TrimPrefix(repository, "https://"), "http://") +// If the specified string starts with http{s} it is replaced with it's +// host[:port] parts; everything else is stripped. Otherwise, the string is +// returned as is. +func replaceURLByHostPort(repository string) (string, error) { + if !strings.HasPrefix(repository, "https://") && !strings.HasPrefix(repository, "http://") { + return repository, nil + } + u, err := url.Parse(repository) + if err != nil { + return "", fmt.Errorf("trimming http{s} prefix: %v", err) + } + return u.Host, nil } // getUserAndPass gets the username and password from STDIN if not given diff --git a/vendor/github.com/containers/common/pkg/cgroups/cgroups_supported.go b/vendor/github.com/containers/common/pkg/cgroups/cgroups_supported.go index c1fe194b2..edb28ad18 100644 --- a/vendor/github.com/containers/common/pkg/cgroups/cgroups_supported.go +++ b/vendor/github.com/containers/common/pkg/cgroups/cgroups_supported.go @@ -1,3 +1,4 @@ +//go:build linux // +build linux package cgroups diff --git a/vendor/github.com/containers/common/pkg/cgroups/cgroups_unsupported.go b/vendor/github.com/containers/common/pkg/cgroups/cgroups_unsupported.go index 95d424170..b3dcb2d33 100644 --- a/vendor/github.com/containers/common/pkg/cgroups/cgroups_unsupported.go +++ b/vendor/github.com/containers/common/pkg/cgroups/cgroups_unsupported.go @@ -1,3 +1,4 @@ +//go:build !linux // +build !linux package cgroups diff --git a/vendor/github.com/containers/common/pkg/cgroupv2/cgroups_unsupported.go b/vendor/github.com/containers/common/pkg/cgroupv2/cgroups_unsupported.go index 61b3653e5..f61bd3bb2 100644 --- a/vendor/github.com/containers/common/pkg/cgroupv2/cgroups_unsupported.go +++ b/vendor/github.com/containers/common/pkg/cgroupv2/cgroups_unsupported.go @@ -1,3 +1,4 @@ +//go:build !linux // +build !linux package cgroupv2 diff --git a/vendor/github.com/containers/common/pkg/chown/chown_unix.go b/vendor/github.com/containers/common/pkg/chown/chown_unix.go index 921927de4..ea8f5963e 100644 --- a/vendor/github.com/containers/common/pkg/chown/chown_unix.go +++ b/vendor/github.com/containers/common/pkg/chown/chown_unix.go @@ -1,3 +1,4 @@ +//go:build !windows // +build !windows package chown diff --git a/vendor/github.com/containers/common/pkg/config/config.go b/vendor/github.com/containers/common/pkg/config/config.go index a1d6f259a..8bf62800f 100644 --- a/vendor/github.com/containers/common/pkg/config/config.go +++ b/vendor/github.com/containers/common/pkg/config/config.go @@ -249,6 +249,10 @@ type EngineConfig struct { // EventsLogFilePath is where the events log is stored. EventsLogFilePath string `toml:"events_logfile_path,omitempty"` + // EventsLogFileMaxSize sets the maximum size for the events log. When the limit is exceeded, + // the logfile is rotated and the old one is deleted. + EventsLogFileMaxSize uint64 `toml:"events_logfile_max_size,omitempty"` + // EventsLogger determines where events should be logged. EventsLogger string `toml:"events_logger,omitempty"` diff --git a/vendor/github.com/containers/common/pkg/config/config_local.go b/vendor/github.com/containers/common/pkg/config/config_local.go index 21dab043f..bfb967582 100644 --- a/vendor/github.com/containers/common/pkg/config/config_local.go +++ b/vendor/github.com/containers/common/pkg/config/config_local.go @@ -1,3 +1,4 @@ +//go:build !remote // +build !remote package config diff --git a/vendor/github.com/containers/common/pkg/config/config_remote.go b/vendor/github.com/containers/common/pkg/config/config_remote.go index 7fd9202bb..bff869efa 100644 --- a/vendor/github.com/containers/common/pkg/config/config_remote.go +++ b/vendor/github.com/containers/common/pkg/config/config_remote.go @@ -1,3 +1,4 @@ +//go:build remote // +build remote package config diff --git a/vendor/github.com/containers/common/pkg/config/config_unsupported.go b/vendor/github.com/containers/common/pkg/config/config_unsupported.go index 6563fd317..64e4fcfcd 100644 --- a/vendor/github.com/containers/common/pkg/config/config_unsupported.go +++ b/vendor/github.com/containers/common/pkg/config/config_unsupported.go @@ -1,3 +1,4 @@ +//go:build !linux // +build !linux package config diff --git a/vendor/github.com/containers/common/pkg/config/containers.conf b/vendor/github.com/containers/common/pkg/config/containers.conf index 03de59943..1db2d704a 100644 --- a/vendor/github.com/containers/common/pkg/config/containers.conf +++ b/vendor/github.com/containers/common/pkg/config/containers.conf @@ -371,6 +371,12 @@ default_sysctls = [ # Define where event logs will be stored, when events_logger is "file". #events_logfile_path="" +# Sets the maximum size for events_logfile_path in bytes. When the limit is exceeded, +# the logfile will be rotated and the old one will be deleted. +# If the maximum size is set to 0, then no limit will be applied, +# and the logfile will not be rotated. +#events_logfile_max_size = 0 + # Selects which logging mechanism to use for container engine events. # Valid values are `journald`, `file` and `none`. # diff --git a/vendor/github.com/containers/common/pkg/config/default.go b/vendor/github.com/containers/common/pkg/config/default.go index e4344e8be..3255cff9d 100644 --- a/vendor/github.com/containers/common/pkg/config/default.go +++ b/vendor/github.com/containers/common/pkg/config/default.go @@ -276,7 +276,7 @@ func defaultConfigFromMemory() (*EngineConfig, error) { storeOpts.GraphRoot = _defaultGraphRoot } c.graphRoot = storeOpts.GraphRoot - c.ImageCopyTmpDir = "/var/tmp" + c.ImageCopyTmpDir = getDefaultTmpDir() c.StaticDir = filepath.Join(storeOpts.GraphRoot, "libpod") c.VolumePath = filepath.Join(storeOpts.GraphRoot, "volumes") diff --git a/vendor/github.com/containers/common/pkg/config/default_linux.go b/vendor/github.com/containers/common/pkg/config/default_linux.go index cc2d0fe3e..d6ea4359c 100644 --- a/vendor/github.com/containers/common/pkg/config/default_linux.go +++ b/vendor/github.com/containers/common/pkg/config/default_linux.go @@ -3,6 +3,7 @@ package config import ( "fmt" "io/ioutil" + "os" "strconv" "strings" @@ -48,3 +49,12 @@ func getDefaultProcessLimits() []string { } return defaultLimits } + +// getDefaultTmpDir for linux +func getDefaultTmpDir() string { + // first check the TMPDIR env var + if path, found := os.LookupEnv("TMPDIR"); found { + return path + } + return "/var/tmp" +} diff --git a/vendor/github.com/containers/common/pkg/config/default_unsupported.go b/vendor/github.com/containers/common/pkg/config/default_unsupported.go index 1aa7f6ef3..4be826755 100644 --- a/vendor/github.com/containers/common/pkg/config/default_unsupported.go +++ b/vendor/github.com/containers/common/pkg/config/default_unsupported.go @@ -1,7 +1,10 @@ +//go:build !linux && !windows // +build !linux,!windows package config +import "os" + // getDefaultMachineImage returns the default machine image stream // On Linux/Mac, this returns the FCOS stream func getDefaultMachineImage() string { @@ -22,3 +25,12 @@ func isCgroup2UnifiedMode() (isUnified bool, isUnifiedErr error) { func getDefaultProcessLimits() []string { return []string{} } + +// getDefaultTmpDir for linux +func getDefaultTmpDir() string { + // first check the TMPDIR env var + if path, found := os.LookupEnv("TMPDIR"); found { + return path + } + return "/var/tmp" +} diff --git a/vendor/github.com/containers/common/pkg/config/default_windows.go b/vendor/github.com/containers/common/pkg/config/default_windows.go index 28f102f1c..db230dfb2 100644 --- a/vendor/github.com/containers/common/pkg/config/default_windows.go +++ b/vendor/github.com/containers/common/pkg/config/default_windows.go @@ -1,5 +1,7 @@ package config +import "os" + // getDefaultImage returns the default machine image stream // On Windows this refers to the Fedora major release number func getDefaultMachineImage() string { @@ -20,3 +22,13 @@ func isCgroup2UnifiedMode() (isUnified bool, isUnifiedErr error) { func getDefaultProcessLimits() []string { return []string{} } + +// getDefaultTmpDir for windows +func getDefaultTmpDir() string { + // first check the Temp env var + // https://answers.microsoft.com/en-us/windows/forum/all/where-is-the-temporary-folder/44a039a5-45ba-48dd-84db-fd700e54fd56 + if val, ok := os.LookupEnv("TEMP"); ok { + return val + } + return os.Getenv("LOCALAPPDATA") + "\\Temp" +} diff --git a/vendor/github.com/containers/common/pkg/config/nosystemd.go b/vendor/github.com/containers/common/pkg/config/nosystemd.go index f64b2dfc6..352fddf92 100644 --- a/vendor/github.com/containers/common/pkg/config/nosystemd.go +++ b/vendor/github.com/containers/common/pkg/config/nosystemd.go @@ -1,3 +1,4 @@ +//go:build !systemd || !cgo // +build !systemd !cgo package config diff --git a/vendor/github.com/containers/common/pkg/config/systemd.go b/vendor/github.com/containers/common/pkg/config/systemd.go index 186e8b343..f17a84304 100644 --- a/vendor/github.com/containers/common/pkg/config/systemd.go +++ b/vendor/github.com/containers/common/pkg/config/systemd.go @@ -1,3 +1,4 @@ +//go:build systemd && cgo // +build systemd,cgo package config diff --git a/vendor/github.com/containers/common/pkg/parse/parse_unix.go b/vendor/github.com/containers/common/pkg/parse/parse_unix.go index ce4446a1b..d087c4a02 100644 --- a/vendor/github.com/containers/common/pkg/parse/parse_unix.go +++ b/vendor/github.com/containers/common/pkg/parse/parse_unix.go @@ -1,3 +1,4 @@ +//go:build linux || darwin // +build linux darwin package parse diff --git a/vendor/github.com/containers/common/pkg/retry/retry_unsupported.go b/vendor/github.com/containers/common/pkg/retry/retry_unsupported.go index 676980975..901e28a5d 100644 --- a/vendor/github.com/containers/common/pkg/retry/retry_unsupported.go +++ b/vendor/github.com/containers/common/pkg/retry/retry_unsupported.go @@ -1,3 +1,4 @@ +//go:build !linux // +build !linux package retry 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 d196384f0..fbf10ca31 100644 --- a/vendor/github.com/containers/common/pkg/seccomp/default_linux.go +++ b/vendor/github.com/containers/common/pkg/seccomp/default_linux.go @@ -236,6 +236,7 @@ func DefaultProfile() *Seccomp { "lstat64", "madvise", "mbind", + "membarrier", "memfd_create", "memfd_secret", "mincore", @@ -249,6 +250,7 @@ func DefaultProfile() *Seccomp { "mmap", "mmap2", "mount", + "mount_setattr", "move_mount", "mprotect", "mq_getsetattr", @@ -293,6 +295,7 @@ func DefaultProfile() *Seccomp { "preadv", "preadv2", "prlimit64", + "process_mrelease", "pselect6", "pselect6_time64", "pwrite64", @@ -388,10 +391,15 @@ func DefaultProfile() *Seccomp { "shmdt", "shmget", "shutdown", + "sigaction", "sigaltstack", + "signal", "signalfd", "signalfd4", + "sigpending", + "sigprocmask", "sigreturn", + "sigsuspend", "socketcall", "socketpair", "splice", @@ -405,6 +413,7 @@ func DefaultProfile() *Seccomp { "sync", "sync_file_range", "syncfs", + "syscall", "sysinfo", "syslog", "tee", @@ -417,6 +426,7 @@ func DefaultProfile() *Seccomp { "timer_gettime64", "timer_settime", "timer_settime64", + "timerfd", "timerfd_create", "timerfd_gettime", "timerfd_gettime64", diff --git a/vendor/github.com/containers/common/pkg/seccomp/errno_list.go b/vendor/github.com/containers/common/pkg/seccomp/errno_list.go index a1009012d..87ac2ab77 100644 --- a/vendor/github.com/containers/common/pkg/seccomp/errno_list.go +++ b/vendor/github.com/containers/common/pkg/seccomp/errno_list.go @@ -1,3 +1,4 @@ +//go:build linux && seccomp // +build linux,seccomp package seccomp diff --git a/vendor/github.com/containers/common/pkg/seccomp/filter.go b/vendor/github.com/containers/common/pkg/seccomp/filter.go index 90da99f0a..5c278574c 100644 --- a/vendor/github.com/containers/common/pkg/seccomp/filter.go +++ b/vendor/github.com/containers/common/pkg/seccomp/filter.go @@ -1,3 +1,4 @@ +//go:build seccomp // +build seccomp // NOTE: this package has originally been copied from diff --git a/vendor/github.com/containers/common/pkg/seccomp/seccomp.json b/vendor/github.com/containers/common/pkg/seccomp/seccomp.json index 9314eb3cc..793f9bdac 100644 --- a/vendor/github.com/containers/common/pkg/seccomp/seccomp.json +++ b/vendor/github.com/containers/common/pkg/seccomp/seccomp.json @@ -243,6 +243,7 @@ "lstat64", "madvise", "mbind", + "membarrier", "memfd_create", "memfd_secret", "mincore", @@ -256,6 +257,7 @@ "mmap", "mmap2", "mount", + "mount_setattr", "move_mount", "mprotect", "mq_getsetattr", @@ -300,6 +302,7 @@ "preadv", "preadv2", "prlimit64", + "process_mrelease", "pselect6", "pselect6_time64", "pwrite64", @@ -395,10 +398,15 @@ "shmdt", "shmget", "shutdown", + "sigaction", "sigaltstack", + "signal", "signalfd", "signalfd4", + "sigpending", + "sigprocmask", "sigreturn", + "sigsuspend", "socketcall", "socketpair", "splice", @@ -412,6 +420,7 @@ "sync", "sync_file_range", "syncfs", + "syscall", "sysinfo", "syslog", "tee", @@ -424,6 +433,7 @@ "timer_gettime64", "timer_settime", "timer_settime64", + "timerfd", "timerfd_create", "timerfd_gettime", "timerfd_gettime64", diff --git a/vendor/github.com/containers/common/pkg/seccomp/seccomp_unsupported.go b/vendor/github.com/containers/common/pkg/seccomp/seccomp_unsupported.go index 8b23ee2c0..da5230c56 100644 --- a/vendor/github.com/containers/common/pkg/seccomp/seccomp_unsupported.go +++ b/vendor/github.com/containers/common/pkg/seccomp/seccomp_unsupported.go @@ -1,3 +1,4 @@ +//go:build !linux || !seccomp // +build !linux !seccomp // SPDX-License-Identifier: Apache-2.0 diff --git a/vendor/github.com/containers/common/pkg/seccomp/supported.go b/vendor/github.com/containers/common/pkg/seccomp/supported.go index 86e1b66bb..f8a20e536 100644 --- a/vendor/github.com/containers/common/pkg/seccomp/supported.go +++ b/vendor/github.com/containers/common/pkg/seccomp/supported.go @@ -1,3 +1,4 @@ +//go:build linux && seccomp // +build linux,seccomp package seccomp diff --git a/vendor/github.com/containers/common/pkg/seccomp/validate.go b/vendor/github.com/containers/common/pkg/seccomp/validate.go index 1c5c4edc6..669ab04a2 100644 --- a/vendor/github.com/containers/common/pkg/seccomp/validate.go +++ b/vendor/github.com/containers/common/pkg/seccomp/validate.go @@ -1,3 +1,4 @@ +//go:build seccomp // +build seccomp package seccomp diff --git a/vendor/github.com/containers/common/pkg/signal/signal_linux.go b/vendor/github.com/containers/common/pkg/signal/signal_linux.go index 305b9d21f..21e09c9fe 100644 --- a/vendor/github.com/containers/common/pkg/signal/signal_linux.go +++ b/vendor/github.com/containers/common/pkg/signal/signal_linux.go @@ -1,5 +1,5 @@ -// +build linux -// +build !mips,!mipsle,!mips64,!mips64le +//go:build linux && !mips && !mipsle && !mips64 && !mips64le +// +build linux,!mips,!mipsle,!mips64,!mips64le // Signal handling for Linux only. package signal diff --git a/vendor/github.com/containers/common/pkg/signal/signal_linux_mipsx.go b/vendor/github.com/containers/common/pkg/signal/signal_linux_mipsx.go index 45c9d5af1..52b07aaf4 100644 --- a/vendor/github.com/containers/common/pkg/signal/signal_linux_mipsx.go +++ b/vendor/github.com/containers/common/pkg/signal/signal_linux_mipsx.go @@ -1,3 +1,4 @@ +//go:build linux && (mips || mipsle || mips64 || mips64le) // +build linux // +build mips mipsle mips64 mips64le diff --git a/vendor/github.com/containers/common/pkg/signal/signal_unsupported.go b/vendor/github.com/containers/common/pkg/signal/signal_unsupported.go index 9d1733c02..0e8685a7c 100644 --- a/vendor/github.com/containers/common/pkg/signal/signal_unsupported.go +++ b/vendor/github.com/containers/common/pkg/signal/signal_unsupported.go @@ -1,3 +1,4 @@ +//go:build !linux // +build !linux // Signal handling for Linux only. diff --git a/vendor/github.com/containers/common/pkg/sysinfo/numcpu.go b/vendor/github.com/containers/common/pkg/sysinfo/numcpu.go index aeb1a3a80..d9d8cfb3e 100644 --- a/vendor/github.com/containers/common/pkg/sysinfo/numcpu.go +++ b/vendor/github.com/containers/common/pkg/sysinfo/numcpu.go @@ -1,3 +1,4 @@ +//go:build !linux && !windows // +build !linux,!windows package sysinfo diff --git a/vendor/github.com/containers/common/pkg/sysinfo/numcpu_linux.go b/vendor/github.com/containers/common/pkg/sysinfo/numcpu_linux.go index 2b664c7f8..0adf58358 100644 --- a/vendor/github.com/containers/common/pkg/sysinfo/numcpu_linux.go +++ b/vendor/github.com/containers/common/pkg/sysinfo/numcpu_linux.go @@ -1,3 +1,4 @@ +//go:build linux // +build linux package sysinfo diff --git a/vendor/github.com/containers/common/pkg/sysinfo/numcpu_windows.go b/vendor/github.com/containers/common/pkg/sysinfo/numcpu_windows.go index 1d89dd550..94160ad57 100644 --- a/vendor/github.com/containers/common/pkg/sysinfo/numcpu_windows.go +++ b/vendor/github.com/containers/common/pkg/sysinfo/numcpu_windows.go @@ -1,3 +1,4 @@ +//go:build windows // +build windows package sysinfo diff --git a/vendor/github.com/containers/common/pkg/sysinfo/nummem_linux.go b/vendor/github.com/containers/common/pkg/sysinfo/nummem_linux.go index 1fc4e6d19..859791e36 100644 --- a/vendor/github.com/containers/common/pkg/sysinfo/nummem_linux.go +++ b/vendor/github.com/containers/common/pkg/sysinfo/nummem_linux.go @@ -1,3 +1,4 @@ +//go:build linux // +build linux package sysinfo diff --git a/vendor/github.com/containers/common/pkg/sysinfo/nummem_unsupported.go b/vendor/github.com/containers/common/pkg/sysinfo/nummem_unsupported.go index e3c851fe6..c9e4184aa 100644 --- a/vendor/github.com/containers/common/pkg/sysinfo/nummem_unsupported.go +++ b/vendor/github.com/containers/common/pkg/sysinfo/nummem_unsupported.go @@ -1,4 +1,5 @@ -// +build windows, osx +//go:build (windows && ignore) || osx +// +build windows,ignore osx package sysinfo diff --git a/vendor/github.com/containers/common/pkg/sysinfo/sysinfo_solaris.go b/vendor/github.com/containers/common/pkg/sysinfo/sysinfo_solaris.go index 7463cdd8f..801db8c80 100644 --- a/vendor/github.com/containers/common/pkg/sysinfo/sysinfo_solaris.go +++ b/vendor/github.com/containers/common/pkg/sysinfo/sysinfo_solaris.go @@ -1,3 +1,4 @@ +//go:build solaris && cgo // +build solaris,cgo package sysinfo diff --git a/vendor/github.com/containers/common/pkg/sysinfo/sysinfo_unix.go b/vendor/github.com/containers/common/pkg/sysinfo/sysinfo_unix.go index 45f3ef1c6..4aa9401f6 100644 --- a/vendor/github.com/containers/common/pkg/sysinfo/sysinfo_unix.go +++ b/vendor/github.com/containers/common/pkg/sysinfo/sysinfo_unix.go @@ -1,3 +1,4 @@ +//go:build !linux && !solaris && !windows // +build !linux,!solaris,!windows package sysinfo diff --git a/vendor/github.com/containers/common/pkg/sysinfo/sysinfo_windows.go b/vendor/github.com/containers/common/pkg/sysinfo/sysinfo_windows.go index 4e6255bc5..455a8892f 100644 --- a/vendor/github.com/containers/common/pkg/sysinfo/sysinfo_windows.go +++ b/vendor/github.com/containers/common/pkg/sysinfo/sysinfo_windows.go @@ -1,3 +1,4 @@ +//go:build windows // +build windows package sysinfo diff --git a/vendor/github.com/containers/common/pkg/umask/umask_unix.go b/vendor/github.com/containers/common/pkg/umask/umask_unix.go index bb589f7ac..e59d7bea7 100644 --- a/vendor/github.com/containers/common/pkg/umask/umask_unix.go +++ b/vendor/github.com/containers/common/pkg/umask/umask_unix.go @@ -1,3 +1,4 @@ +//go:build linux || darwin // +build linux darwin package umask diff --git a/vendor/github.com/containers/common/pkg/umask/umask_unsupported.go b/vendor/github.com/containers/common/pkg/umask/umask_unsupported.go index 9041d5f20..cf76ea1d3 100644 --- a/vendor/github.com/containers/common/pkg/umask/umask_unsupported.go +++ b/vendor/github.com/containers/common/pkg/umask/umask_unsupported.go @@ -1,3 +1,4 @@ +//go:build !linux && !darwin // +build !linux,!darwin package umask diff --git a/vendor/github.com/containers/common/pkg/util/util_supported.go b/vendor/github.com/containers/common/pkg/util/util_supported.go index 422e28742..284f3ffdd 100644 --- a/vendor/github.com/containers/common/pkg/util/util_supported.go +++ b/vendor/github.com/containers/common/pkg/util/util_supported.go @@ -1,3 +1,4 @@ +//go:build linux || darwin // +build linux darwin package util @@ -19,6 +20,12 @@ var ( rootlessRuntimeDir string ) +// isWriteableOnlyByOwner checks that the specified permission mask allows write +// access only to the owner. +func isWriteableOnlyByOwner(perm os.FileMode) bool { + return (perm & 0722) == 0700 +} + // GetRuntimeDir returns the runtime directory func GetRuntimeDir() (string, error) { var rootlessRuntimeDirError error @@ -43,7 +50,7 @@ func GetRuntimeDir() (string, error) { logrus.Debugf("unable to make temp dir: %v", err) } st, err := os.Stat(tmpDir) - if err == nil && int(st.Sys().(*syscall.Stat_t).Uid) == os.Geteuid() && st.Mode().Perm() == 0700 { + if err == nil && int(st.Sys().(*syscall.Stat_t).Uid) == os.Geteuid() && isWriteableOnlyByOwner(st.Mode().Perm()) { runtimeDir = tmpDir } } @@ -53,7 +60,7 @@ func GetRuntimeDir() (string, error) { logrus.Debugf("unable to make temp dir %v", err) } st, err := os.Stat(tmpDir) - if err == nil && int(st.Sys().(*syscall.Stat_t).Uid) == os.Geteuid() && st.Mode().Perm() == 0700 { + if err == nil && int(st.Sys().(*syscall.Stat_t).Uid) == os.Geteuid() && isWriteableOnlyByOwner(st.Mode().Perm()) { runtimeDir = tmpDir } } diff --git a/vendor/github.com/containers/common/pkg/util/util_windows.go b/vendor/github.com/containers/common/pkg/util/util_windows.go index 2add712f1..1cffb21fc 100644 --- a/vendor/github.com/containers/common/pkg/util/util_windows.go +++ b/vendor/github.com/containers/common/pkg/util/util_windows.go @@ -1,3 +1,4 @@ +//go:build windows // +build windows package util diff --git a/vendor/github.com/containers/ocicrypt/go.mod b/vendor/github.com/containers/ocicrypt/go.mod index 02be18591..8837d288e 100644 --- a/vendor/github.com/containers/ocicrypt/go.mod +++ b/vendor/github.com/containers/ocicrypt/go.mod @@ -5,9 +5,9 @@ go 1.12 require ( github.com/golang/protobuf v1.4.3 github.com/google/go-cmp v0.5.2 // indirect - github.com/miekg/pkcs11 v1.0.3 + github.com/miekg/pkcs11 v1.1.1 github.com/opencontainers/go-digest v1.0.0 - github.com/opencontainers/image-spec v1.0.1 + github.com/opencontainers/image-spec v1.0.2 github.com/pkg/errors v0.9.1 github.com/sirupsen/logrus v1.7.0 github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980 diff --git a/vendor/github.com/containers/ocicrypt/go.sum b/vendor/github.com/containers/ocicrypt/go.sum index 7153900da..a621a145c 100644 --- a/vendor/github.com/containers/ocicrypt/go.sum +++ b/vendor/github.com/containers/ocicrypt/go.sum @@ -30,12 +30,12 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/miekg/pkcs11 v1.0.3 h1:iMwmD7I5225wv84WxIG/bmxz9AXjWvTWIbM/TYHvWtw= -github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= +github.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU= +github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI= -github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= +github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= diff --git a/vendor/github.com/containers/storage/drivers/overlay/overlay.go b/vendor/github.com/containers/storage/drivers/overlay/overlay.go index 00a3b5e4d..a780ef5da 100644 --- a/vendor/github.com/containers/storage/drivers/overlay/overlay.go +++ b/vendor/github.com/containers/storage/drivers/overlay/overlay.go @@ -292,6 +292,31 @@ func Init(home string, options graphdriver.Options) (graphdriver.Driver, error) backingFs = fsName } + runhome := filepath.Join(options.RunRoot, filepath.Base(home)) + rootUID, rootGID, err := idtools.GetRootUIDGID(options.UIDMaps, options.GIDMaps) + if err != nil { + return nil, err + } + + // Create the driver home dir + if err := idtools.MkdirAllAs(path.Join(home, linkDir), 0700, rootUID, rootGID); err != nil { + return nil, err + } + + if err := idtools.MkdirAllAs(runhome, 0700, rootUID, rootGID); err != nil { + return nil, err + } + + if opts.mountProgram == "" { + if supported, err := SupportsNativeOverlay(home, runhome); err != nil { + return nil, err + } else if !supported { + if path, err := exec.LookPath("fuse-overlayfs"); err == nil { + opts.mountProgram = path + } + } + } + if opts.mountProgram != "" { if unshare.IsRootless() && isNetworkFileSystem(fsMagic) && opts.forceMask == nil { m := os.FileMode(0700) @@ -316,20 +341,6 @@ func Init(home string, options graphdriver.Options) (graphdriver.Driver, error) } } - rootUID, rootGID, err := idtools.GetRootUIDGID(options.UIDMaps, options.GIDMaps) - if err != nil { - return nil, err - } - - // Create the driver home dir - if err := idtools.MkdirAllAs(path.Join(home, linkDir), 0700, rootUID, rootGID); err != nil { - return nil, err - } - runhome := filepath.Join(options.RunRoot, filepath.Base(home)) - if err := idtools.MkdirAllAs(runhome, 0700, rootUID, rootGID); err != nil { - return nil, err - } - var usingMetacopy bool var supportsDType bool var supportsVolatile *bool @@ -569,14 +580,11 @@ func cachedFeatureRecord(runhome, feature string, supported bool, text string) ( return err } -func SupportsNativeOverlay(graphroot, rundir string) (bool, error) { - if os.Geteuid() != 0 || graphroot == "" || rundir == "" { +func SupportsNativeOverlay(home, runhome string) (bool, error) { + if os.Geteuid() != 0 || home == "" || runhome == "" { return false, nil } - home := filepath.Join(graphroot, "overlay") - runhome := filepath.Join(rundir, "overlay") - var contents string flagContent, err := ioutil.ReadFile(getMountProgramFlagFile(home)) if err == nil { diff --git a/vendor/github.com/containers/storage/go.mod b/vendor/github.com/containers/storage/go.mod index 3e8d51f6a..4da8384af 100644 --- a/vendor/github.com/containers/storage/go.mod +++ b/vendor/github.com/containers/storage/go.mod @@ -6,13 +6,13 @@ require ( github.com/BurntSushi/toml v1.0.0 github.com/Microsoft/go-winio v0.5.2 github.com/Microsoft/hcsshim v0.9.2 - github.com/containerd/stargz-snapshotter/estargz v0.11.2 + github.com/containerd/stargz-snapshotter/estargz v0.11.3 github.com/cyphar/filepath-securejoin v0.2.3 github.com/docker/go-units v0.4.0 github.com/google/go-intervals v0.0.2 github.com/hashicorp/go-multierror v1.1.1 github.com/json-iterator/go v1.1.12 - github.com/klauspost/compress v1.15.0 + github.com/klauspost/compress v1.15.1 github.com/klauspost/pgzip v1.2.5 github.com/mattn/go-shellwords v1.0.12 github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible @@ -23,7 +23,7 @@ require ( github.com/opencontainers/selinux v1.10.0 github.com/pkg/errors v0.9.1 github.com/sirupsen/logrus v1.8.1 - github.com/stretchr/testify v1.7.0 + github.com/stretchr/testify v1.7.1 github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 github.com/tchap/go-patricia v2.3.0+incompatible github.com/ulikunitz/xz v0.5.10 diff --git a/vendor/github.com/containers/storage/go.sum b/vendor/github.com/containers/storage/go.sum index ef6b711cf..b995da734 100644 --- a/vendor/github.com/containers/storage/go.sum +++ b/vendor/github.com/containers/storage/go.sum @@ -176,8 +176,8 @@ github.com/containerd/nri v0.0.0-20201007170849-eb1350a75164/go.mod h1:+2wGSDGFY github.com/containerd/nri v0.0.0-20210316161719-dbaa18c31c14/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= github.com/containerd/stargz-snapshotter/estargz v0.4.1/go.mod h1:x7Q9dg9QYb4+ELgxmo4gBUeJB0tl5dqH1Sdz0nJU1QM= -github.com/containerd/stargz-snapshotter/estargz v0.11.2 h1:0P0vWmfrEeTtZ4BBRrpuyu/HxR9HPBLfeljGOra5f6g= -github.com/containerd/stargz-snapshotter/estargz v0.11.2/go.mod h1:rjbdAXaytDSIrAy2WAy2kUrJ4ehzDS0eUQLlIb5UCY0= +github.com/containerd/stargz-snapshotter/estargz v0.11.3 h1:k2kN16Px6LYuv++qFqK+JTcYqc8bEVxzGpf8/gFBL5M= +github.com/containerd/stargz-snapshotter/estargz v0.11.3/go.mod h1:7vRJIcImfY8bpifnMjt+HTJoQxASq7T28MYbP15/Nf0= github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= github.com/containerd/ttrpc v0.0.0-20191028202541-4f1b8fe65a5c/go.mod h1:LPm1u0xBw8r8NOKoOdNMeVHSawSsltak+Ihv+etqsE8= @@ -424,8 +424,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.15.0 h1:xqfchp4whNFxn5A4XFyyYtitiWI8Hy5EW59jEwcyL6U= -github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/klauspost/compress v1.15.1 h1:y9FcTHGyrebwfP0ZZqFiaxTaiDnUrGkJkI+f583BL1A= +github.com/klauspost/compress v1.15.1/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= 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= @@ -622,8 +622,8 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 h1:kdXcSzyDtseVEc4yCz2qF8ZrQvIDBJLl4S1c3GCXmoI= diff --git a/vendor/github.com/containers/storage/types/options.go b/vendor/github.com/containers/storage/types/options.go index 567985b98..a71c6d2ef 100644 --- a/vendor/github.com/containers/storage/types/options.go +++ b/vendor/github.com/containers/storage/types/options.go @@ -3,14 +3,12 @@ package types import ( "fmt" "os" - "os/exec" "path/filepath" "strings" "sync" "time" "github.com/BurntSushi/toml" - "github.com/containers/storage/drivers/overlay" cfg "github.com/containers/storage/pkg/config" "github.com/containers/storage/pkg/idtools" "github.com/sirupsen/logrus" @@ -225,25 +223,11 @@ func getRootlessStorageOpts(rootlessUID int, systemOpts StoreOptions) (StoreOpti opts.GraphDriverName = overlayDriver } - if opts.GraphDriverName == "" || opts.GraphDriverName == overlayDriver { - supported, err := overlay.SupportsNativeOverlay(opts.GraphRoot, rootlessRuntime) - if err != nil { - return opts, err - } - if supported { - opts.GraphDriverName = overlayDriver - } else { - if path, err := exec.LookPath("fuse-overlayfs"); err == nil { - opts.GraphDriverName = overlayDriver - opts.GraphDriverOptions = []string{fmt.Sprintf("overlay.mount_program=%s", path)} - } - } - if opts.GraphDriverName == overlayDriver { - for _, o := range systemOpts.GraphDriverOptions { - if strings.Contains(o, "ignore_chown_errors") { - opts.GraphDriverOptions = append(opts.GraphDriverOptions, o) - break - } + if opts.GraphDriverName == overlayDriver { + for _, o := range systemOpts.GraphDriverOptions { + if strings.Contains(o, "ignore_chown_errors") { + opts.GraphDriverOptions = append(opts.GraphDriverOptions, o) + break } } } diff --git a/vendor/github.com/klauspost/compress/README.md b/vendor/github.com/klauspost/compress/README.md index 9ddf39f6f..0e2dc116a 100644 --- a/vendor/github.com/klauspost/compress/README.md +++ b/vendor/github.com/klauspost/compress/README.md @@ -17,6 +17,23 @@ This package provides various compression algorithms. # changelog
+* Mar 3, 2022 (v1.15.0)
+ * zstd: Refactor decoder by @klauspost in [#498](https://github.com/klauspost/compress/pull/498)
+ * zstd: Add stream encoding without goroutines by @klauspost in [#505](https://github.com/klauspost/compress/pull/505)
+ * huff0: Prevent single blocks exceeding 16 bits by @klauspost in[#507](https://github.com/klauspost/compress/pull/507)
+ * flate: Inline literal emission by @klauspost in [#509](https://github.com/klauspost/compress/pull/509)
+ * gzhttp: Add zstd to transport by @klauspost in [#400](https://github.com/klauspost/compress/pull/400)
+ * gzhttp: Make content-type optional by @klauspost in [#510](https://github.com/klauspost/compress/pull/510)
+
+<details>
+ <summary>See Details</summary>
+Both compression and decompression now supports "synchronous" stream operations. This means that whenever "concurrency" is set to 1, they will operate without spawning goroutines.
+
+Stream decompression is now faster on asynchronous, since the goroutine allocation much more effectively splits the workload. On typical streams this will typically use 2 cores fully for decompression. When a stream has finished decoding no goroutines will be left over, so decoders can now safely be pooled and still be garbage collected.
+
+While the release has been extensively tested, it is recommended to testing when upgrading.
+</details>
+
* Feb 22, 2022 (v1.14.4)
* flate: Fix rare huffman only (-2) corruption. [#503](https://github.com/klauspost/compress/pull/503)
* zip: Update deprecated CreateHeaderRaw to correctly call CreateRaw by @saracen in [#502](https://github.com/klauspost/compress/pull/502)
diff --git a/vendor/github.com/klauspost/compress/huff0/autogen.go b/vendor/github.com/klauspost/compress/huff0/autogen.go new file mode 100644 index 000000000..ff2c69d60 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/autogen.go @@ -0,0 +1,5 @@ +package huff0 + +//go:generate go run generate.go +//go:generate asmfmt -w decompress_amd64.s +//go:generate asmfmt -w decompress_8b_amd64.s diff --git a/vendor/github.com/klauspost/compress/huff0/bitreader.go b/vendor/github.com/klauspost/compress/huff0/bitreader.go index 03562db16..451160edd 100644 --- a/vendor/github.com/klauspost/compress/huff0/bitreader.go +++ b/vendor/github.com/klauspost/compress/huff0/bitreader.go @@ -165,6 +165,11 @@ func (b *bitReaderShifted) peekBitsFast(n uint8) uint16 { return uint16(b.value >> ((64 - n) & 63)) } +// peekTopBits(n) is equvialent to peekBitFast(64 - n) +func (b *bitReaderShifted) peekTopBits(n uint8) uint16 { + return uint16(b.value >> n) +} + func (b *bitReaderShifted) advance(n uint8) { b.bitsRead += n b.value <<= n & 63 diff --git a/vendor/github.com/klauspost/compress/huff0/decompress.go b/vendor/github.com/klauspost/compress/huff0/decompress.go index 3ae7d4677..04f652995 100644 --- a/vendor/github.com/klauspost/compress/huff0/decompress.go +++ b/vendor/github.com/klauspost/compress/huff0/decompress.go @@ -729,189 +729,6 @@ func (d *Decoder) decompress1X8BitExactly(dst, src []byte) ([]byte, error) { // The length of the supplied input must match the end of a block exactly. // The *capacity* of the dst slice must match the destination size of // the uncompressed data exactly. -func (d *Decoder) Decompress4X(dst, src []byte) ([]byte, error) { - if len(d.dt.single) == 0 { - return nil, errors.New("no table loaded") - } - if len(src) < 6+(4*1) { - return nil, errors.New("input too small") - } - if use8BitTables && d.actualTableLog <= 8 { - return d.decompress4X8bit(dst, src) - } - - var br [4]bitReaderShifted - // Decode "jump table" - start := 6 - for i := 0; i < 3; i++ { - length := int(src[i*2]) | (int(src[i*2+1]) << 8) - if start+length >= len(src) { - return nil, errors.New("truncated input (or invalid offset)") - } - err := br[i].init(src[start : start+length]) - if err != nil { - return nil, err - } - start += length - } - err := br[3].init(src[start:]) - if err != nil { - return nil, err - } - - // destination, offset to match first output - dstSize := cap(dst) - dst = dst[:dstSize] - out := dst - dstEvery := (dstSize + 3) / 4 - - const tlSize = 1 << tableLogMax - const tlMask = tlSize - 1 - single := d.dt.single[:tlSize] - - // Use temp table to avoid bound checks/append penalty. - buf := d.buffer() - var off uint8 - var decoded int - - // Decode 2 values from each decoder/loop. - const bufoff = 256 - for { - if br[0].off < 4 || br[1].off < 4 || br[2].off < 4 || br[3].off < 4 { - break - } - - { - const stream = 0 - const stream2 = 1 - br[stream].fillFast() - br[stream2].fillFast() - - val := br[stream].peekBitsFast(d.actualTableLog) - val2 := br[stream2].peekBitsFast(d.actualTableLog) - v := single[val&tlMask] - v2 := single[val2&tlMask] - br[stream].advance(uint8(v.entry)) - br[stream2].advance(uint8(v2.entry)) - buf[stream][off] = uint8(v.entry >> 8) - buf[stream2][off] = uint8(v2.entry >> 8) - - val = br[stream].peekBitsFast(d.actualTableLog) - val2 = br[stream2].peekBitsFast(d.actualTableLog) - v = single[val&tlMask] - v2 = single[val2&tlMask] - br[stream].advance(uint8(v.entry)) - br[stream2].advance(uint8(v2.entry)) - buf[stream][off+1] = uint8(v.entry >> 8) - buf[stream2][off+1] = uint8(v2.entry >> 8) - } - - { - const stream = 2 - const stream2 = 3 - br[stream].fillFast() - br[stream2].fillFast() - - val := br[stream].peekBitsFast(d.actualTableLog) - val2 := br[stream2].peekBitsFast(d.actualTableLog) - v := single[val&tlMask] - v2 := single[val2&tlMask] - br[stream].advance(uint8(v.entry)) - br[stream2].advance(uint8(v2.entry)) - buf[stream][off] = uint8(v.entry >> 8) - buf[stream2][off] = uint8(v2.entry >> 8) - - val = br[stream].peekBitsFast(d.actualTableLog) - val2 = br[stream2].peekBitsFast(d.actualTableLog) - v = single[val&tlMask] - v2 = single[val2&tlMask] - br[stream].advance(uint8(v.entry)) - br[stream2].advance(uint8(v2.entry)) - buf[stream][off+1] = uint8(v.entry >> 8) - buf[stream2][off+1] = uint8(v2.entry >> 8) - } - - off += 2 - - if off == 0 { - if bufoff > dstEvery { - d.bufs.Put(buf) - return nil, errors.New("corruption detected: stream overrun 1") - } - copy(out, buf[0][:]) - copy(out[dstEvery:], buf[1][:]) - copy(out[dstEvery*2:], buf[2][:]) - copy(out[dstEvery*3:], buf[3][:]) - out = out[bufoff:] - decoded += bufoff * 4 - // There must at least be 3 buffers left. - if len(out) < dstEvery*3 { - d.bufs.Put(buf) - return nil, errors.New("corruption detected: stream overrun 2") - } - } - } - if off > 0 { - ioff := int(off) - if len(out) < dstEvery*3+ioff { - d.bufs.Put(buf) - return nil, errors.New("corruption detected: stream overrun 3") - } - copy(out, buf[0][:off]) - copy(out[dstEvery:], buf[1][:off]) - copy(out[dstEvery*2:], buf[2][:off]) - copy(out[dstEvery*3:], buf[3][:off]) - decoded += int(off) * 4 - out = out[off:] - } - - // Decode remaining. - remainBytes := dstEvery - (decoded / 4) - for i := range br { - offset := dstEvery * i - endsAt := offset + remainBytes - if endsAt > len(out) { - endsAt = len(out) - } - br := &br[i] - bitsLeft := br.remaining() - for bitsLeft > 0 { - br.fill() - if offset >= endsAt { - d.bufs.Put(buf) - return nil, errors.New("corruption detected: stream overrun 4") - } - - // Read value and increment offset. - val := br.peekBitsFast(d.actualTableLog) - v := single[val&tlMask].entry - nBits := uint8(v) - br.advance(nBits) - bitsLeft -= uint(nBits) - out[offset] = uint8(v >> 8) - offset++ - } - if offset != endsAt { - d.bufs.Put(buf) - return nil, fmt.Errorf("corruption detected: short output block %d, end %d != %d", i, offset, endsAt) - } - decoded += offset - dstEvery*i - err = br.close() - if err != nil { - return nil, err - } - } - d.bufs.Put(buf) - if dstSize != decoded { - return nil, errors.New("corruption detected: short output block") - } - return dst, nil -} - -// Decompress4X will decompress a 4X encoded stream. -// The length of the supplied input must match the end of a block exactly. -// The *capacity* of the dst slice must match the destination size of -// the uncompressed data exactly. func (d *Decoder) decompress4X8bit(dst, src []byte) ([]byte, error) { if d.actualTableLog == 8 { return d.decompress4X8bitExactly(dst, src) diff --git a/vendor/github.com/klauspost/compress/huff0/decompress_8b_amd64.s b/vendor/github.com/klauspost/compress/huff0/decompress_8b_amd64.s new file mode 100644 index 000000000..0d6cb1a96 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/decompress_8b_amd64.s @@ -0,0 +1,488 @@ +// +build !appengine +// +build gc +// +build !noasm + +#include "textflag.h" +#include "funcdata.h" +#include "go_asm.h" + +#define bufoff 256 // see decompress.go, we're using [4][256]byte table + +// func decompress4x_main_loop_x86(pbr0, pbr1, pbr2, pbr3 *bitReaderShifted, +// peekBits uint8, buf *byte, tbl *dEntrySingle) (int, bool) +TEXT ·decompress4x_8b_loop_x86(SB), NOSPLIT, $8 +#define off R8 +#define buffer DI +#define table SI + +#define br_bits_read R9 +#define br_value R10 +#define br_offset R11 +#define peek_bits R12 +#define exhausted DX + +#define br0 R13 +#define br1 R14 +#define br2 R15 +#define br3 BP + + MOVQ BP, 0(SP) + + XORQ exhausted, exhausted // exhausted = false + XORQ off, off // off = 0 + + MOVBQZX peekBits+32(FP), peek_bits + MOVQ buf+40(FP), buffer + MOVQ tbl+48(FP), table + + MOVQ pbr0+0(FP), br0 + MOVQ pbr1+8(FP), br1 + MOVQ pbr2+16(FP), br2 + MOVQ pbr3+24(FP), br3 + +main_loop: + + // const stream = 0 + // br0.fillFast() + MOVBQZX bitReaderShifted_bitsRead(br0), br_bits_read + MOVQ bitReaderShifted_value(br0), br_value + MOVQ bitReaderShifted_off(br0), br_offset + + // if b.bitsRead >= 32 { + CMPQ br_bits_read, $32 + JB skip_fill0 + + SUBQ $32, br_bits_read // b.bitsRead -= 32 + SUBQ $4, br_offset // b.off -= 4 + + // v := b.in[b.off-4 : b.off] + // v = v[:4] + // low := (uint32(v[0])) | (uint32(v[1]) << 8) | (uint32(v[2]) << 16) | (uint32(v[3]) << 24) + MOVQ bitReaderShifted_in(br0), AX + MOVL 0(br_offset)(AX*1), AX // AX = uint32(b.in[b.off:b.off+4]) + + // b.value |= uint64(low) << (b.bitsRead & 63) + MOVQ br_bits_read, CX + SHLQ CL, AX + ORQ AX, br_value + + // exhausted = exhausted || (br0.off < 4) + CMPQ br_offset, $4 + SETLT DL + ORB DL, DH + + // } +skip_fill0: + + // val0 := br0.peekTopBits(peekBits) + MOVQ br_value, AX + MOVQ peek_bits, CX + SHRQ CL, AX // AX = (value >> peek_bits) & mask + + // v0 := table[val0&mask] + MOVW 0(table)(AX*2), AX // AX - v0 + + // br0.advance(uint8(v0.entry)) + MOVB AH, BL // BL = uint8(v0.entry >> 8) + MOVBQZX AL, CX + SHLQ CL, br_value // value <<= n + ADDQ CX, br_bits_read // bits_read += n + + // val1 := br0.peekTopBits(peekBits) + MOVQ peek_bits, CX + MOVQ br_value, AX + SHRQ CL, AX // AX = (value >> peek_bits) & mask + + // v1 := table[val1&mask] + MOVW 0(table)(AX*2), AX // AX - v1 + + // br0.advance(uint8(v1.entry)) + MOVB AH, BH // BH = uint8(v1.entry >> 8) + MOVBQZX AL, CX + SHLQ CX, br_value // value <<= n + ADDQ CX, br_bits_read // bits_read += n + + // these two writes get coalesced + // buf[stream][off] = uint8(v0.entry >> 8) + // buf[stream][off+1] = uint8(v1.entry >> 8) + MOVW BX, 0(buffer)(off*1) + + // SECOND PART: + // val2 := br0.peekTopBits(peekBits) + MOVQ br_value, AX + MOVQ peek_bits, CX + SHRQ CL, AX // AX = (value >> peek_bits) & mask + + // v2 := table[val0&mask] + MOVW 0(table)(AX*2), AX // AX - v0 + + // br0.advance(uint8(v0.entry)) + MOVB AH, BL // BL = uint8(v0.entry >> 8) + MOVBQZX AL, CX + SHLQ CL, br_value // value <<= n + ADDQ CX, br_bits_read // bits_read += n + + // val3 := br0.peekTopBits(peekBits) + MOVQ peek_bits, CX + MOVQ br_value, AX + SHRQ CL, AX // AX = (value >> peek_bits) & mask + + // v3 := table[val1&mask] + MOVW 0(table)(AX*2), AX // AX - v1 + + // br0.advance(uint8(v1.entry)) + MOVB AH, BH // BH = uint8(v1.entry >> 8) + MOVBQZX AL, CX + SHLQ CX, br_value // value <<= n + ADDQ CX, br_bits_read // bits_read += n + + // these two writes get coalesced + // buf[stream][off+2] = uint8(v2.entry >> 8) + // buf[stream][off+3] = uint8(v3.entry >> 8) + MOVW BX, 0+2(buffer)(off*1) + + // update the bitrader reader structure + MOVB br_bits_read, bitReaderShifted_bitsRead(br0) + MOVQ br_value, bitReaderShifted_value(br0) + MOVQ br_offset, bitReaderShifted_off(br0) + + // const stream = 1 + // br1.fillFast() + MOVBQZX bitReaderShifted_bitsRead(br1), br_bits_read + MOVQ bitReaderShifted_value(br1), br_value + MOVQ bitReaderShifted_off(br1), br_offset + + // if b.bitsRead >= 32 { + CMPQ br_bits_read, $32 + JB skip_fill1 + + SUBQ $32, br_bits_read // b.bitsRead -= 32 + SUBQ $4, br_offset // b.off -= 4 + + // v := b.in[b.off-4 : b.off] + // v = v[:4] + // low := (uint32(v[0])) | (uint32(v[1]) << 8) | (uint32(v[2]) << 16) | (uint32(v[3]) << 24) + MOVQ bitReaderShifted_in(br1), AX + MOVL 0(br_offset)(AX*1), AX // AX = uint32(b.in[b.off:b.off+4]) + + // b.value |= uint64(low) << (b.bitsRead & 63) + MOVQ br_bits_read, CX + SHLQ CL, AX + ORQ AX, br_value + + // exhausted = exhausted || (br1.off < 4) + CMPQ br_offset, $4 + SETLT DL + ORB DL, DH + + // } +skip_fill1: + + // val0 := br1.peekTopBits(peekBits) + MOVQ br_value, AX + MOVQ peek_bits, CX + SHRQ CL, AX // AX = (value >> peek_bits) & mask + + // v0 := table[val0&mask] + MOVW 0(table)(AX*2), AX // AX - v0 + + // br1.advance(uint8(v0.entry)) + MOVB AH, BL // BL = uint8(v0.entry >> 8) + MOVBQZX AL, CX + SHLQ CL, br_value // value <<= n + ADDQ CX, br_bits_read // bits_read += n + + // val1 := br1.peekTopBits(peekBits) + MOVQ peek_bits, CX + MOVQ br_value, AX + SHRQ CL, AX // AX = (value >> peek_bits) & mask + + // v1 := table[val1&mask] + MOVW 0(table)(AX*2), AX // AX - v1 + + // br1.advance(uint8(v1.entry)) + MOVB AH, BH // BH = uint8(v1.entry >> 8) + MOVBQZX AL, CX + SHLQ CX, br_value // value <<= n + ADDQ CX, br_bits_read // bits_read += n + + // these two writes get coalesced + // buf[stream][off] = uint8(v0.entry >> 8) + // buf[stream][off+1] = uint8(v1.entry >> 8) + MOVW BX, 256(buffer)(off*1) + + // SECOND PART: + // val2 := br1.peekTopBits(peekBits) + MOVQ br_value, AX + MOVQ peek_bits, CX + SHRQ CL, AX // AX = (value >> peek_bits) & mask + + // v2 := table[val0&mask] + MOVW 0(table)(AX*2), AX // AX - v0 + + // br1.advance(uint8(v0.entry)) + MOVB AH, BL // BL = uint8(v0.entry >> 8) + MOVBQZX AL, CX + SHLQ CL, br_value // value <<= n + ADDQ CX, br_bits_read // bits_read += n + + // val3 := br1.peekTopBits(peekBits) + MOVQ peek_bits, CX + MOVQ br_value, AX + SHRQ CL, AX // AX = (value >> peek_bits) & mask + + // v3 := table[val1&mask] + MOVW 0(table)(AX*2), AX // AX - v1 + + // br1.advance(uint8(v1.entry)) + MOVB AH, BH // BH = uint8(v1.entry >> 8) + MOVBQZX AL, CX + SHLQ CX, br_value // value <<= n + ADDQ CX, br_bits_read // bits_read += n + + // these two writes get coalesced + // buf[stream][off+2] = uint8(v2.entry >> 8) + // buf[stream][off+3] = uint8(v3.entry >> 8) + MOVW BX, 256+2(buffer)(off*1) + + // update the bitrader reader structure + MOVB br_bits_read, bitReaderShifted_bitsRead(br1) + MOVQ br_value, bitReaderShifted_value(br1) + MOVQ br_offset, bitReaderShifted_off(br1) + + // const stream = 2 + // br2.fillFast() + MOVBQZX bitReaderShifted_bitsRead(br2), br_bits_read + MOVQ bitReaderShifted_value(br2), br_value + MOVQ bitReaderShifted_off(br2), br_offset + + // if b.bitsRead >= 32 { + CMPQ br_bits_read, $32 + JB skip_fill2 + + SUBQ $32, br_bits_read // b.bitsRead -= 32 + SUBQ $4, br_offset // b.off -= 4 + + // v := b.in[b.off-4 : b.off] + // v = v[:4] + // low := (uint32(v[0])) | (uint32(v[1]) << 8) | (uint32(v[2]) << 16) | (uint32(v[3]) << 24) + MOVQ bitReaderShifted_in(br2), AX + MOVL 0(br_offset)(AX*1), AX // AX = uint32(b.in[b.off:b.off+4]) + + // b.value |= uint64(low) << (b.bitsRead & 63) + MOVQ br_bits_read, CX + SHLQ CL, AX + ORQ AX, br_value + + // exhausted = exhausted || (br2.off < 4) + CMPQ br_offset, $4 + SETLT DL + ORB DL, DH + + // } +skip_fill2: + + // val0 := br2.peekTopBits(peekBits) + MOVQ br_value, AX + MOVQ peek_bits, CX + SHRQ CL, AX // AX = (value >> peek_bits) & mask + + // v0 := table[val0&mask] + MOVW 0(table)(AX*2), AX // AX - v0 + + // br2.advance(uint8(v0.entry)) + MOVB AH, BL // BL = uint8(v0.entry >> 8) + MOVBQZX AL, CX + SHLQ CL, br_value // value <<= n + ADDQ CX, br_bits_read // bits_read += n + + // val1 := br2.peekTopBits(peekBits) + MOVQ peek_bits, CX + MOVQ br_value, AX + SHRQ CL, AX // AX = (value >> peek_bits) & mask + + // v1 := table[val1&mask] + MOVW 0(table)(AX*2), AX // AX - v1 + + // br2.advance(uint8(v1.entry)) + MOVB AH, BH // BH = uint8(v1.entry >> 8) + MOVBQZX AL, CX + SHLQ CX, br_value // value <<= n + ADDQ CX, br_bits_read // bits_read += n + + // these two writes get coalesced + // buf[stream][off] = uint8(v0.entry >> 8) + // buf[stream][off+1] = uint8(v1.entry >> 8) + MOVW BX, 512(buffer)(off*1) + + // SECOND PART: + // val2 := br2.peekTopBits(peekBits) + MOVQ br_value, AX + MOVQ peek_bits, CX + SHRQ CL, AX // AX = (value >> peek_bits) & mask + + // v2 := table[val0&mask] + MOVW 0(table)(AX*2), AX // AX - v0 + + // br2.advance(uint8(v0.entry)) + MOVB AH, BL // BL = uint8(v0.entry >> 8) + MOVBQZX AL, CX + SHLQ CL, br_value // value <<= n + ADDQ CX, br_bits_read // bits_read += n + + // val3 := br2.peekTopBits(peekBits) + MOVQ peek_bits, CX + MOVQ br_value, AX + SHRQ CL, AX // AX = (value >> peek_bits) & mask + + // v3 := table[val1&mask] + MOVW 0(table)(AX*2), AX // AX - v1 + + // br2.advance(uint8(v1.entry)) + MOVB AH, BH // BH = uint8(v1.entry >> 8) + MOVBQZX AL, CX + SHLQ CX, br_value // value <<= n + ADDQ CX, br_bits_read // bits_read += n + + // these two writes get coalesced + // buf[stream][off+2] = uint8(v2.entry >> 8) + // buf[stream][off+3] = uint8(v3.entry >> 8) + MOVW BX, 512+2(buffer)(off*1) + + // update the bitrader reader structure + MOVB br_bits_read, bitReaderShifted_bitsRead(br2) + MOVQ br_value, bitReaderShifted_value(br2) + MOVQ br_offset, bitReaderShifted_off(br2) + + // const stream = 3 + // br3.fillFast() + MOVBQZX bitReaderShifted_bitsRead(br3), br_bits_read + MOVQ bitReaderShifted_value(br3), br_value + MOVQ bitReaderShifted_off(br3), br_offset + + // if b.bitsRead >= 32 { + CMPQ br_bits_read, $32 + JB skip_fill3 + + SUBQ $32, br_bits_read // b.bitsRead -= 32 + SUBQ $4, br_offset // b.off -= 4 + + // v := b.in[b.off-4 : b.off] + // v = v[:4] + // low := (uint32(v[0])) | (uint32(v[1]) << 8) | (uint32(v[2]) << 16) | (uint32(v[3]) << 24) + MOVQ bitReaderShifted_in(br3), AX + MOVL 0(br_offset)(AX*1), AX // AX = uint32(b.in[b.off:b.off+4]) + + // b.value |= uint64(low) << (b.bitsRead & 63) + MOVQ br_bits_read, CX + SHLQ CL, AX + ORQ AX, br_value + + // exhausted = exhausted || (br3.off < 4) + CMPQ br_offset, $4 + SETLT DL + ORB DL, DH + + // } +skip_fill3: + + // val0 := br3.peekTopBits(peekBits) + MOVQ br_value, AX + MOVQ peek_bits, CX + SHRQ CL, AX // AX = (value >> peek_bits) & mask + + // v0 := table[val0&mask] + MOVW 0(table)(AX*2), AX // AX - v0 + + // br3.advance(uint8(v0.entry)) + MOVB AH, BL // BL = uint8(v0.entry >> 8) + MOVBQZX AL, CX + SHLQ CL, br_value // value <<= n + ADDQ CX, br_bits_read // bits_read += n + + // val1 := br3.peekTopBits(peekBits) + MOVQ peek_bits, CX + MOVQ br_value, AX + SHRQ CL, AX // AX = (value >> peek_bits) & mask + + // v1 := table[val1&mask] + MOVW 0(table)(AX*2), AX // AX - v1 + + // br3.advance(uint8(v1.entry)) + MOVB AH, BH // BH = uint8(v1.entry >> 8) + MOVBQZX AL, CX + SHLQ CX, br_value // value <<= n + ADDQ CX, br_bits_read // bits_read += n + + // these two writes get coalesced + // buf[stream][off] = uint8(v0.entry >> 8) + // buf[stream][off+1] = uint8(v1.entry >> 8) + MOVW BX, 768(buffer)(off*1) + + // SECOND PART: + // val2 := br3.peekTopBits(peekBits) + MOVQ br_value, AX + MOVQ peek_bits, CX + SHRQ CL, AX // AX = (value >> peek_bits) & mask + + // v2 := table[val0&mask] + MOVW 0(table)(AX*2), AX // AX - v0 + + // br3.advance(uint8(v0.entry)) + MOVB AH, BL // BL = uint8(v0.entry >> 8) + MOVBQZX AL, CX + SHLQ CL, br_value // value <<= n + ADDQ CX, br_bits_read // bits_read += n + + // val3 := br3.peekTopBits(peekBits) + MOVQ peek_bits, CX + MOVQ br_value, AX + SHRQ CL, AX // AX = (value >> peek_bits) & mask + + // v3 := table[val1&mask] + MOVW 0(table)(AX*2), AX // AX - v1 + + // br3.advance(uint8(v1.entry)) + MOVB AH, BH // BH = uint8(v1.entry >> 8) + MOVBQZX AL, CX + SHLQ CX, br_value // value <<= n + ADDQ CX, br_bits_read // bits_read += n + + // these two writes get coalesced + // buf[stream][off+2] = uint8(v2.entry >> 8) + // buf[stream][off+3] = uint8(v3.entry >> 8) + MOVW BX, 768+2(buffer)(off*1) + + // update the bitrader reader structure + MOVB br_bits_read, bitReaderShifted_bitsRead(br3) + MOVQ br_value, bitReaderShifted_value(br3) + MOVQ br_offset, bitReaderShifted_off(br3) + + ADDQ $4, off // off += 2 + + TESTB DH, DH // any br[i].ofs < 4? + JNZ end + + CMPQ off, $bufoff + JL main_loop + +end: + MOVQ 0(SP), BP + + MOVB off, ret+56(FP) + RET + +#undef off +#undef buffer +#undef table + +#undef br_bits_read +#undef br_value +#undef br_offset +#undef peek_bits +#undef exhausted + +#undef br0 +#undef br1 +#undef br2 +#undef br3 diff --git a/vendor/github.com/klauspost/compress/huff0/decompress_8b_amd64.s.in b/vendor/github.com/klauspost/compress/huff0/decompress_8b_amd64.s.in new file mode 100644 index 000000000..6d477a2c1 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/decompress_8b_amd64.s.in @@ -0,0 +1,197 @@ +// +build !appengine +// +build gc +// +build !noasm + +#include "textflag.h" +#include "funcdata.h" +#include "go_asm.h" + + +#define bufoff 256 // see decompress.go, we're using [4][256]byte table + +//func decompress4x_main_loop_x86(pbr0, pbr1, pbr2, pbr3 *bitReaderShifted, +// peekBits uint8, buf *byte, tbl *dEntrySingle) (int, bool) +TEXT ·decompress4x_8b_loop_x86(SB), NOSPLIT, $8 +#define off R8 +#define buffer DI +#define table SI + +#define br_bits_read R9 +#define br_value R10 +#define br_offset R11 +#define peek_bits R12 +#define exhausted DX + +#define br0 R13 +#define br1 R14 +#define br2 R15 +#define br3 BP + + MOVQ BP, 0(SP) + + XORQ exhausted, exhausted // exhausted = false + XORQ off, off // off = 0 + + MOVBQZX peekBits+32(FP), peek_bits + MOVQ buf+40(FP), buffer + MOVQ tbl+48(FP), table + + MOVQ pbr0+0(FP), br0 + MOVQ pbr1+8(FP), br1 + MOVQ pbr2+16(FP), br2 + MOVQ pbr3+24(FP), br3 + +main_loop: +{{ define "decode_2_values_x86" }} + // const stream = {{ var "id" }} + // br{{ var "id"}}.fillFast() + MOVBQZX bitReaderShifted_bitsRead(br{{ var "id" }}), br_bits_read + MOVQ bitReaderShifted_value(br{{ var "id" }}), br_value + MOVQ bitReaderShifted_off(br{{ var "id" }}), br_offset + + // if b.bitsRead >= 32 { + CMPQ br_bits_read, $32 + JB skip_fill{{ var "id" }} + + SUBQ $32, br_bits_read // b.bitsRead -= 32 + SUBQ $4, br_offset // b.off -= 4 + + // v := b.in[b.off-4 : b.off] + // v = v[:4] + // low := (uint32(v[0])) | (uint32(v[1]) << 8) | (uint32(v[2]) << 16) | (uint32(v[3]) << 24) + MOVQ bitReaderShifted_in(br{{ var "id" }}), AX + MOVL 0(br_offset)(AX*1), AX // AX = uint32(b.in[b.off:b.off+4]) + + // b.value |= uint64(low) << (b.bitsRead & 63) + MOVQ br_bits_read, CX + SHLQ CL, AX + ORQ AX, br_value + + // exhausted = exhausted || (br{{ var "id"}}.off < 4) + CMPQ br_offset, $4 + SETLT DL + ORB DL, DH + // } +skip_fill{{ var "id" }}: + + // val0 := br{{ var "id"}}.peekTopBits(peekBits) + MOVQ br_value, AX + MOVQ peek_bits, CX + SHRQ CL, AX // AX = (value >> peek_bits) & mask + + // v0 := table[val0&mask] + MOVW 0(table)(AX*2), AX // AX - v0 + + // br{{ var "id"}}.advance(uint8(v0.entry)) + MOVB AH, BL // BL = uint8(v0.entry >> 8) + MOVBQZX AL, CX + SHLQ CL, br_value // value <<= n + ADDQ CX, br_bits_read // bits_read += n + + // val1 := br{{ var "id"}}.peekTopBits(peekBits) + MOVQ peek_bits, CX + MOVQ br_value, AX + SHRQ CL, AX // AX = (value >> peek_bits) & mask + + // v1 := table[val1&mask] + MOVW 0(table)(AX*2), AX // AX - v1 + + // br{{ var "id"}}.advance(uint8(v1.entry)) + MOVB AH, BH // BH = uint8(v1.entry >> 8) + MOVBQZX AL, CX + SHLQ CX, br_value // value <<= n + ADDQ CX, br_bits_read // bits_read += n + + + // these two writes get coalesced + // buf[stream][off] = uint8(v0.entry >> 8) + // buf[stream][off+1] = uint8(v1.entry >> 8) + MOVW BX, {{ var "bufofs" }}(buffer)(off*1) + + // SECOND PART: + // val2 := br{{ var "id"}}.peekTopBits(peekBits) + MOVQ br_value, AX + MOVQ peek_bits, CX + SHRQ CL, AX // AX = (value >> peek_bits) & mask + + // v2 := table[val0&mask] + MOVW 0(table)(AX*2), AX // AX - v0 + + // br{{ var "id"}}.advance(uint8(v0.entry)) + MOVB AH, BL // BL = uint8(v0.entry >> 8) + MOVBQZX AL, CX + SHLQ CL, br_value // value <<= n + ADDQ CX, br_bits_read // bits_read += n + + // val3 := br{{ var "id"}}.peekTopBits(peekBits) + MOVQ peek_bits, CX + MOVQ br_value, AX + SHRQ CL, AX // AX = (value >> peek_bits) & mask + + // v3 := table[val1&mask] + MOVW 0(table)(AX*2), AX // AX - v1 + + // br{{ var "id"}}.advance(uint8(v1.entry)) + MOVB AH, BH // BH = uint8(v1.entry >> 8) + MOVBQZX AL, CX + SHLQ CX, br_value // value <<= n + ADDQ CX, br_bits_read // bits_read += n + + + // these two writes get coalesced + // buf[stream][off+2] = uint8(v2.entry >> 8) + // buf[stream][off+3] = uint8(v3.entry >> 8) + MOVW BX, {{ var "bufofs" }}+2(buffer)(off*1) + + // update the bitrader reader structure + MOVB br_bits_read, bitReaderShifted_bitsRead(br{{ var "id" }}) + MOVQ br_value, bitReaderShifted_value(br{{ var "id" }}) + MOVQ br_offset, bitReaderShifted_off(br{{ var "id" }}) +{{ end }} + + {{ set "id" "0" }} + {{ set "ofs" "0" }} + {{ set "bufofs" "0" }} {{/* id * bufoff */}} + {{ template "decode_2_values_x86" . }} + + {{ set "id" "1" }} + {{ set "ofs" "8" }} + {{ set "bufofs" "256" }} + {{ template "decode_2_values_x86" . }} + + {{ set "id" "2" }} + {{ set "ofs" "16" }} + {{ set "bufofs" "512" }} + {{ template "decode_2_values_x86" . }} + + {{ set "id" "3" }} + {{ set "ofs" "24" }} + {{ set "bufofs" "768" }} + {{ template "decode_2_values_x86" . }} + + ADDQ $4, off // off += 2 + + TESTB DH, DH // any br[i].ofs < 4? + JNZ end + + CMPQ off, $bufoff + JL main_loop +end: + MOVQ 0(SP), BP + + MOVB off, ret+56(FP) + RET +#undef off +#undef buffer +#undef table + +#undef br_bits_read +#undef br_value +#undef br_offset +#undef peek_bits +#undef exhausted + +#undef br0 +#undef br1 +#undef br2 +#undef br3 diff --git a/vendor/github.com/klauspost/compress/huff0/decompress_amd64.go b/vendor/github.com/klauspost/compress/huff0/decompress_amd64.go new file mode 100644 index 000000000..d47f6644f --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/decompress_amd64.go @@ -0,0 +1,181 @@ +//go:build amd64 && !appengine && !noasm && gc +// +build amd64,!appengine,!noasm,gc + +// This file contains the specialisation of Decoder.Decompress4X +// that uses an asm implementation of its main loop. +package huff0 + +import ( + "errors" + "fmt" +) + +// decompress4x_main_loop_x86 is an x86 assembler implementation +// of Decompress4X when tablelog > 8. +// go:noescape +func decompress4x_main_loop_x86(pbr0, pbr1, pbr2, pbr3 *bitReaderShifted, + peekBits uint8, buf *byte, tbl *dEntrySingle) uint8 + +// decompress4x_8b_loop_x86 is an x86 assembler implementation +// of Decompress4X when tablelog <= 8 which decodes 4 entries +// per loop. +// go:noescape +func decompress4x_8b_loop_x86(pbr0, pbr1, pbr2, pbr3 *bitReaderShifted, + peekBits uint8, buf *byte, tbl *dEntrySingle) uint8 + +// fallback8BitSize is the size where using Go version is faster. +const fallback8BitSize = 800 + +// Decompress4X will decompress a 4X encoded stream. +// The length of the supplied input must match the end of a block exactly. +// The *capacity* of the dst slice must match the destination size of +// the uncompressed data exactly. +func (d *Decoder) Decompress4X(dst, src []byte) ([]byte, error) { + if len(d.dt.single) == 0 { + return nil, errors.New("no table loaded") + } + if len(src) < 6+(4*1) { + return nil, errors.New("input too small") + } + + use8BitTables := d.actualTableLog <= 8 + if cap(dst) < fallback8BitSize && use8BitTables { + return d.decompress4X8bit(dst, src) + } + var br [4]bitReaderShifted + // Decode "jump table" + start := 6 + for i := 0; i < 3; i++ { + length := int(src[i*2]) | (int(src[i*2+1]) << 8) + if start+length >= len(src) { + return nil, errors.New("truncated input (or invalid offset)") + } + err := br[i].init(src[start : start+length]) + if err != nil { + return nil, err + } + start += length + } + err := br[3].init(src[start:]) + if err != nil { + return nil, err + } + + // destination, offset to match first output + dstSize := cap(dst) + dst = dst[:dstSize] + out := dst + dstEvery := (dstSize + 3) / 4 + + const tlSize = 1 << tableLogMax + const tlMask = tlSize - 1 + single := d.dt.single[:tlSize] + + // Use temp table to avoid bound checks/append penalty. + buf := d.buffer() + var off uint8 + var decoded int + + const debug = false + + // see: bitReaderShifted.peekBitsFast() + peekBits := uint8((64 - d.actualTableLog) & 63) + + // Decode 2 values from each decoder/loop. + const bufoff = 256 + for { + if br[0].off < 4 || br[1].off < 4 || br[2].off < 4 || br[3].off < 4 { + break + } + + if use8BitTables { + off = decompress4x_8b_loop_x86(&br[0], &br[1], &br[2], &br[3], peekBits, &buf[0][0], &single[0]) + } else { + off = decompress4x_main_loop_x86(&br[0], &br[1], &br[2], &br[3], peekBits, &buf[0][0], &single[0]) + } + if debug { + fmt.Print("DEBUG: ") + fmt.Printf("off=%d,", off) + for i := 0; i < 4; i++ { + fmt.Printf(" br[%d]={bitsRead=%d, value=%x, off=%d}", + i, br[i].bitsRead, br[i].value, br[i].off) + } + fmt.Println("") + } + + if off != 0 { + break + } + + if bufoff > dstEvery { + d.bufs.Put(buf) + return nil, errors.New("corruption detected: stream overrun 1") + } + copy(out, buf[0][:]) + copy(out[dstEvery:], buf[1][:]) + copy(out[dstEvery*2:], buf[2][:]) + copy(out[dstEvery*3:], buf[3][:]) + out = out[bufoff:] + decoded += bufoff * 4 + // There must at least be 3 buffers left. + if len(out) < dstEvery*3 { + d.bufs.Put(buf) + return nil, errors.New("corruption detected: stream overrun 2") + } + } + if off > 0 { + ioff := int(off) + if len(out) < dstEvery*3+ioff { + d.bufs.Put(buf) + return nil, errors.New("corruption detected: stream overrun 3") + } + copy(out, buf[0][:off]) + copy(out[dstEvery:], buf[1][:off]) + copy(out[dstEvery*2:], buf[2][:off]) + copy(out[dstEvery*3:], buf[3][:off]) + decoded += int(off) * 4 + out = out[off:] + } + + // Decode remaining. + remainBytes := dstEvery - (decoded / 4) + for i := range br { + offset := dstEvery * i + endsAt := offset + remainBytes + if endsAt > len(out) { + endsAt = len(out) + } + br := &br[i] + bitsLeft := br.remaining() + for bitsLeft > 0 { + br.fill() + if offset >= endsAt { + d.bufs.Put(buf) + return nil, errors.New("corruption detected: stream overrun 4") + } + + // Read value and increment offset. + val := br.peekBitsFast(d.actualTableLog) + v := single[val&tlMask].entry + nBits := uint8(v) + br.advance(nBits) + bitsLeft -= uint(nBits) + out[offset] = uint8(v >> 8) + offset++ + } + if offset != endsAt { + d.bufs.Put(buf) + return nil, fmt.Errorf("corruption detected: short output block %d, end %d != %d", i, offset, endsAt) + } + decoded += offset - dstEvery*i + err = br.close() + if err != nil { + return nil, err + } + } + d.bufs.Put(buf) + if dstSize != decoded { + return nil, errors.New("corruption detected: short output block") + } + return dst, nil +} diff --git a/vendor/github.com/klauspost/compress/huff0/decompress_amd64.s b/vendor/github.com/klauspost/compress/huff0/decompress_amd64.s new file mode 100644 index 000000000..2edad3ea5 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/decompress_amd64.s @@ -0,0 +1,506 @@ +// +build !appengine +// +build gc +// +build !noasm + +#include "textflag.h" +#include "funcdata.h" +#include "go_asm.h" + +#ifdef GOAMD64_v4 +#ifndef GOAMD64_v3 +#define GOAMD64_v3 +#endif +#endif + +#define bufoff 256 // see decompress.go, we're using [4][256]byte table + +// func decompress4x_main_loop_x86(pbr0, pbr1, pbr2, pbr3 *bitReaderShifted, +// peekBits uint8, buf *byte, tbl *dEntrySingle) (int, bool) +TEXT ·decompress4x_main_loop_x86(SB), NOSPLIT, $8 +#define off R8 +#define buffer DI +#define table SI + +#define br_bits_read R9 +#define br_value R10 +#define br_offset R11 +#define peek_bits R12 +#define exhausted DX + +#define br0 R13 +#define br1 R14 +#define br2 R15 +#define br3 BP + + MOVQ BP, 0(SP) + + XORQ exhausted, exhausted // exhausted = false + XORQ off, off // off = 0 + + MOVBQZX peekBits+32(FP), peek_bits + MOVQ buf+40(FP), buffer + MOVQ tbl+48(FP), table + + MOVQ pbr0+0(FP), br0 + MOVQ pbr1+8(FP), br1 + MOVQ pbr2+16(FP), br2 + MOVQ pbr3+24(FP), br3 + +main_loop: + + // const stream = 0 + // br0.fillFast() + MOVBQZX bitReaderShifted_bitsRead(br0), br_bits_read + MOVQ bitReaderShifted_value(br0), br_value + MOVQ bitReaderShifted_off(br0), br_offset + + // We must have at least 2 * max tablelog left + CMPQ br_bits_read, $64-22 + JBE skip_fill0 + + SUBQ $32, br_bits_read // b.bitsRead -= 32 + SUBQ $4, br_offset // b.off -= 4 + + // v := b.in[b.off-4 : b.off] + // v = v[:4] + // low := (uint32(v[0])) | (uint32(v[1]) << 8) | (uint32(v[2]) << 16) | (uint32(v[3]) << 24) + MOVQ bitReaderShifted_in(br0), AX + + // b.value |= uint64(low) << (b.bitsRead & 63) +#ifdef GOAMD64_v3 + SHLXQ br_bits_read, 0(br_offset)(AX*1), AX // AX = uint32(b.in[b.off:b.off+4]) << (b.bitsRead & 63) + +#else + MOVL 0(br_offset)(AX*1), AX // AX = uint32(b.in[b.off:b.off+4]) + MOVQ br_bits_read, CX + SHLQ CL, AX + +#endif + + ORQ AX, br_value + + // exhausted = exhausted || (br0.off < 4) + CMPQ br_offset, $4 + SETLT DL + ORB DL, DH + + // } +skip_fill0: + + // val0 := br0.peekTopBits(peekBits) +#ifdef GOAMD64_v3 + SHRXQ peek_bits, br_value, AX // AX = (value >> peek_bits) & mask + +#else + MOVQ br_value, AX + MOVQ peek_bits, CX + SHRQ CL, AX // AX = (value >> peek_bits) & mask + +#endif + + // v0 := table[val0&mask] + MOVW 0(table)(AX*2), AX // AX - v0 + + // br0.advance(uint8(v0.entry)) + MOVB AH, BL // BL = uint8(v0.entry >> 8) + +#ifdef GOAMD64_v3 + MOVBQZX AL, CX + SHLXQ AX, br_value, br_value // value <<= n + +#else + MOVBQZX AL, CX + SHLQ CL, br_value // value <<= n + +#endif + + ADDQ CX, br_bits_read // bits_read += n + +#ifdef GOAMD64_v3 + SHRXQ peek_bits, br_value, AX // AX = (value >> peek_bits) & mask + +#else + // val1 := br0.peekTopBits(peekBits) + MOVQ peek_bits, CX + MOVQ br_value, AX + SHRQ CL, AX // AX = (value >> peek_bits) & mask + +#endif + + // v1 := table[val1&mask] + MOVW 0(table)(AX*2), AX // AX - v1 + + // br0.advance(uint8(v1.entry)) + MOVB AH, BH // BH = uint8(v1.entry >> 8) + +#ifdef GOAMD64_v3 + MOVBQZX AL, CX + SHLXQ AX, br_value, br_value // value <<= n + +#else + MOVBQZX AL, CX + SHLQ CL, br_value // value <<= n + +#endif + + ADDQ CX, br_bits_read // bits_read += n + + // these two writes get coalesced + // buf[stream][off] = uint8(v0.entry >> 8) + // buf[stream][off+1] = uint8(v1.entry >> 8) + MOVW BX, 0(buffer)(off*1) + + // update the bitrader reader structure + MOVB br_bits_read, bitReaderShifted_bitsRead(br0) + MOVQ br_value, bitReaderShifted_value(br0) + MOVQ br_offset, bitReaderShifted_off(br0) + + // const stream = 1 + // br1.fillFast() + MOVBQZX bitReaderShifted_bitsRead(br1), br_bits_read + MOVQ bitReaderShifted_value(br1), br_value + MOVQ bitReaderShifted_off(br1), br_offset + + // We must have at least 2 * max tablelog left + CMPQ br_bits_read, $64-22 + JBE skip_fill1 + + SUBQ $32, br_bits_read // b.bitsRead -= 32 + SUBQ $4, br_offset // b.off -= 4 + + // v := b.in[b.off-4 : b.off] + // v = v[:4] + // low := (uint32(v[0])) | (uint32(v[1]) << 8) | (uint32(v[2]) << 16) | (uint32(v[3]) << 24) + MOVQ bitReaderShifted_in(br1), AX + + // b.value |= uint64(low) << (b.bitsRead & 63) +#ifdef GOAMD64_v3 + SHLXQ br_bits_read, 0(br_offset)(AX*1), AX // AX = uint32(b.in[b.off:b.off+4]) << (b.bitsRead & 63) + +#else + MOVL 0(br_offset)(AX*1), AX // AX = uint32(b.in[b.off:b.off+4]) + MOVQ br_bits_read, CX + SHLQ CL, AX + +#endif + + ORQ AX, br_value + + // exhausted = exhausted || (br1.off < 4) + CMPQ br_offset, $4 + SETLT DL + ORB DL, DH + + // } +skip_fill1: + + // val0 := br1.peekTopBits(peekBits) +#ifdef GOAMD64_v3 + SHRXQ peek_bits, br_value, AX // AX = (value >> peek_bits) & mask + +#else + MOVQ br_value, AX + MOVQ peek_bits, CX + SHRQ CL, AX // AX = (value >> peek_bits) & mask + +#endif + + // v0 := table[val0&mask] + MOVW 0(table)(AX*2), AX // AX - v0 + + // br1.advance(uint8(v0.entry)) + MOVB AH, BL // BL = uint8(v0.entry >> 8) + +#ifdef GOAMD64_v3 + MOVBQZX AL, CX + SHLXQ AX, br_value, br_value // value <<= n + +#else + MOVBQZX AL, CX + SHLQ CL, br_value // value <<= n + +#endif + + ADDQ CX, br_bits_read // bits_read += n + +#ifdef GOAMD64_v3 + SHRXQ peek_bits, br_value, AX // AX = (value >> peek_bits) & mask + +#else + // val1 := br1.peekTopBits(peekBits) + MOVQ peek_bits, CX + MOVQ br_value, AX + SHRQ CL, AX // AX = (value >> peek_bits) & mask + +#endif + + // v1 := table[val1&mask] + MOVW 0(table)(AX*2), AX // AX - v1 + + // br1.advance(uint8(v1.entry)) + MOVB AH, BH // BH = uint8(v1.entry >> 8) + +#ifdef GOAMD64_v3 + MOVBQZX AL, CX + SHLXQ AX, br_value, br_value // value <<= n + +#else + MOVBQZX AL, CX + SHLQ CL, br_value // value <<= n + +#endif + + ADDQ CX, br_bits_read // bits_read += n + + // these two writes get coalesced + // buf[stream][off] = uint8(v0.entry >> 8) + // buf[stream][off+1] = uint8(v1.entry >> 8) + MOVW BX, 256(buffer)(off*1) + + // update the bitrader reader structure + MOVB br_bits_read, bitReaderShifted_bitsRead(br1) + MOVQ br_value, bitReaderShifted_value(br1) + MOVQ br_offset, bitReaderShifted_off(br1) + + // const stream = 2 + // br2.fillFast() + MOVBQZX bitReaderShifted_bitsRead(br2), br_bits_read + MOVQ bitReaderShifted_value(br2), br_value + MOVQ bitReaderShifted_off(br2), br_offset + + // We must have at least 2 * max tablelog left + CMPQ br_bits_read, $64-22 + JBE skip_fill2 + + SUBQ $32, br_bits_read // b.bitsRead -= 32 + SUBQ $4, br_offset // b.off -= 4 + + // v := b.in[b.off-4 : b.off] + // v = v[:4] + // low := (uint32(v[0])) | (uint32(v[1]) << 8) | (uint32(v[2]) << 16) | (uint32(v[3]) << 24) + MOVQ bitReaderShifted_in(br2), AX + + // b.value |= uint64(low) << (b.bitsRead & 63) +#ifdef GOAMD64_v3 + SHLXQ br_bits_read, 0(br_offset)(AX*1), AX // AX = uint32(b.in[b.off:b.off+4]) << (b.bitsRead & 63) + +#else + MOVL 0(br_offset)(AX*1), AX // AX = uint32(b.in[b.off:b.off+4]) + MOVQ br_bits_read, CX + SHLQ CL, AX + +#endif + + ORQ AX, br_value + + // exhausted = exhausted || (br2.off < 4) + CMPQ br_offset, $4 + SETLT DL + ORB DL, DH + + // } +skip_fill2: + + // val0 := br2.peekTopBits(peekBits) +#ifdef GOAMD64_v3 + SHRXQ peek_bits, br_value, AX // AX = (value >> peek_bits) & mask + +#else + MOVQ br_value, AX + MOVQ peek_bits, CX + SHRQ CL, AX // AX = (value >> peek_bits) & mask + +#endif + + // v0 := table[val0&mask] + MOVW 0(table)(AX*2), AX // AX - v0 + + // br2.advance(uint8(v0.entry)) + MOVB AH, BL // BL = uint8(v0.entry >> 8) + +#ifdef GOAMD64_v3 + MOVBQZX AL, CX + SHLXQ AX, br_value, br_value // value <<= n + +#else + MOVBQZX AL, CX + SHLQ CL, br_value // value <<= n + +#endif + + ADDQ CX, br_bits_read // bits_read += n + +#ifdef GOAMD64_v3 + SHRXQ peek_bits, br_value, AX // AX = (value >> peek_bits) & mask + +#else + // val1 := br2.peekTopBits(peekBits) + MOVQ peek_bits, CX + MOVQ br_value, AX + SHRQ CL, AX // AX = (value >> peek_bits) & mask + +#endif + + // v1 := table[val1&mask] + MOVW 0(table)(AX*2), AX // AX - v1 + + // br2.advance(uint8(v1.entry)) + MOVB AH, BH // BH = uint8(v1.entry >> 8) + +#ifdef GOAMD64_v3 + MOVBQZX AL, CX + SHLXQ AX, br_value, br_value // value <<= n + +#else + MOVBQZX AL, CX + SHLQ CL, br_value // value <<= n + +#endif + + ADDQ CX, br_bits_read // bits_read += n + + // these two writes get coalesced + // buf[stream][off] = uint8(v0.entry >> 8) + // buf[stream][off+1] = uint8(v1.entry >> 8) + MOVW BX, 512(buffer)(off*1) + + // update the bitrader reader structure + MOVB br_bits_read, bitReaderShifted_bitsRead(br2) + MOVQ br_value, bitReaderShifted_value(br2) + MOVQ br_offset, bitReaderShifted_off(br2) + + // const stream = 3 + // br3.fillFast() + MOVBQZX bitReaderShifted_bitsRead(br3), br_bits_read + MOVQ bitReaderShifted_value(br3), br_value + MOVQ bitReaderShifted_off(br3), br_offset + + // We must have at least 2 * max tablelog left + CMPQ br_bits_read, $64-22 + JBE skip_fill3 + + SUBQ $32, br_bits_read // b.bitsRead -= 32 + SUBQ $4, br_offset // b.off -= 4 + + // v := b.in[b.off-4 : b.off] + // v = v[:4] + // low := (uint32(v[0])) | (uint32(v[1]) << 8) | (uint32(v[2]) << 16) | (uint32(v[3]) << 24) + MOVQ bitReaderShifted_in(br3), AX + + // b.value |= uint64(low) << (b.bitsRead & 63) +#ifdef GOAMD64_v3 + SHLXQ br_bits_read, 0(br_offset)(AX*1), AX // AX = uint32(b.in[b.off:b.off+4]) << (b.bitsRead & 63) + +#else + MOVL 0(br_offset)(AX*1), AX // AX = uint32(b.in[b.off:b.off+4]) + MOVQ br_bits_read, CX + SHLQ CL, AX + +#endif + + ORQ AX, br_value + + // exhausted = exhausted || (br3.off < 4) + CMPQ br_offset, $4 + SETLT DL + ORB DL, DH + + // } +skip_fill3: + + // val0 := br3.peekTopBits(peekBits) +#ifdef GOAMD64_v3 + SHRXQ peek_bits, br_value, AX // AX = (value >> peek_bits) & mask + +#else + MOVQ br_value, AX + MOVQ peek_bits, CX + SHRQ CL, AX // AX = (value >> peek_bits) & mask + +#endif + + // v0 := table[val0&mask] + MOVW 0(table)(AX*2), AX // AX - v0 + + // br3.advance(uint8(v0.entry)) + MOVB AH, BL // BL = uint8(v0.entry >> 8) + +#ifdef GOAMD64_v3 + MOVBQZX AL, CX + SHLXQ AX, br_value, br_value // value <<= n + +#else + MOVBQZX AL, CX + SHLQ CL, br_value // value <<= n + +#endif + + ADDQ CX, br_bits_read // bits_read += n + +#ifdef GOAMD64_v3 + SHRXQ peek_bits, br_value, AX // AX = (value >> peek_bits) & mask + +#else + // val1 := br3.peekTopBits(peekBits) + MOVQ peek_bits, CX + MOVQ br_value, AX + SHRQ CL, AX // AX = (value >> peek_bits) & mask + +#endif + + // v1 := table[val1&mask] + MOVW 0(table)(AX*2), AX // AX - v1 + + // br3.advance(uint8(v1.entry)) + MOVB AH, BH // BH = uint8(v1.entry >> 8) + +#ifdef GOAMD64_v3 + MOVBQZX AL, CX + SHLXQ AX, br_value, br_value // value <<= n + +#else + MOVBQZX AL, CX + SHLQ CL, br_value // value <<= n + +#endif + + ADDQ CX, br_bits_read // bits_read += n + + // these two writes get coalesced + // buf[stream][off] = uint8(v0.entry >> 8) + // buf[stream][off+1] = uint8(v1.entry >> 8) + MOVW BX, 768(buffer)(off*1) + + // update the bitrader reader structure + MOVB br_bits_read, bitReaderShifted_bitsRead(br3) + MOVQ br_value, bitReaderShifted_value(br3) + MOVQ br_offset, bitReaderShifted_off(br3) + + ADDQ $2, off // off += 2 + + TESTB DH, DH // any br[i].ofs < 4? + JNZ end + + CMPQ off, $bufoff + JL main_loop + +end: + MOVQ 0(SP), BP + + MOVB off, ret+56(FP) + RET + +#undef off +#undef buffer +#undef table + +#undef br_bits_read +#undef br_value +#undef br_offset +#undef peek_bits +#undef exhausted + +#undef br0 +#undef br1 +#undef br2 +#undef br3 diff --git a/vendor/github.com/klauspost/compress/huff0/decompress_amd64.s.in b/vendor/github.com/klauspost/compress/huff0/decompress_amd64.s.in new file mode 100644 index 000000000..330d86ae1 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/decompress_amd64.s.in @@ -0,0 +1,195 @@ +// +build !appengine +// +build gc +// +build !noasm + +#include "textflag.h" +#include "funcdata.h" +#include "go_asm.h" + +#ifdef GOAMD64_v4 +#ifndef GOAMD64_v3 +#define GOAMD64_v3 +#endif +#endif + +#define bufoff 256 // see decompress.go, we're using [4][256]byte table + +//func decompress4x_main_loop_x86(pbr0, pbr1, pbr2, pbr3 *bitReaderShifted, +// peekBits uint8, buf *byte, tbl *dEntrySingle) (int, bool) +TEXT ·decompress4x_main_loop_x86(SB), NOSPLIT, $8 +#define off R8 +#define buffer DI +#define table SI + +#define br_bits_read R9 +#define br_value R10 +#define br_offset R11 +#define peek_bits R12 +#define exhausted DX + +#define br0 R13 +#define br1 R14 +#define br2 R15 +#define br3 BP + + MOVQ BP, 0(SP) + + XORQ exhausted, exhausted // exhausted = false + XORQ off, off // off = 0 + + MOVBQZX peekBits+32(FP), peek_bits + MOVQ buf+40(FP), buffer + MOVQ tbl+48(FP), table + + MOVQ pbr0+0(FP), br0 + MOVQ pbr1+8(FP), br1 + MOVQ pbr2+16(FP), br2 + MOVQ pbr3+24(FP), br3 + +main_loop: +{{ define "decode_2_values_x86" }} + // const stream = {{ var "id" }} + // br{{ var "id"}}.fillFast() + MOVBQZX bitReaderShifted_bitsRead(br{{ var "id" }}), br_bits_read + MOVQ bitReaderShifted_value(br{{ var "id" }}), br_value + MOVQ bitReaderShifted_off(br{{ var "id" }}), br_offset + + // We must have at least 2 * max tablelog left + CMPQ br_bits_read, $64-22 + JBE skip_fill{{ var "id" }} + + SUBQ $32, br_bits_read // b.bitsRead -= 32 + SUBQ $4, br_offset // b.off -= 4 + + // v := b.in[b.off-4 : b.off] + // v = v[:4] + // low := (uint32(v[0])) | (uint32(v[1]) << 8) | (uint32(v[2]) << 16) | (uint32(v[3]) << 24) + MOVQ bitReaderShifted_in(br{{ var "id" }}), AX + + // b.value |= uint64(low) << (b.bitsRead & 63) +#ifdef GOAMD64_v3 + SHLXQ br_bits_read, 0(br_offset)(AX*1), AX // AX = uint32(b.in[b.off:b.off+4]) << (b.bitsRead & 63) +#else + MOVL 0(br_offset)(AX*1), AX // AX = uint32(b.in[b.off:b.off+4]) + MOVQ br_bits_read, CX + SHLQ CL, AX +#endif + + ORQ AX, br_value + + // exhausted = exhausted || (br{{ var "id"}}.off < 4) + CMPQ br_offset, $4 + SETLT DL + ORB DL, DH + // } +skip_fill{{ var "id" }}: + + // val0 := br{{ var "id"}}.peekTopBits(peekBits) +#ifdef GOAMD64_v3 + SHRXQ peek_bits, br_value, AX // AX = (value >> peek_bits) & mask +#else + MOVQ br_value, AX + MOVQ peek_bits, CX + SHRQ CL, AX // AX = (value >> peek_bits) & mask +#endif + + // v0 := table[val0&mask] + MOVW 0(table)(AX*2), AX // AX - v0 + + // br{{ var "id"}}.advance(uint8(v0.entry)) + MOVB AH, BL // BL = uint8(v0.entry >> 8) + +#ifdef GOAMD64_v3 + MOVBQZX AL, CX + SHLXQ AX, br_value, br_value // value <<= n +#else + MOVBQZX AL, CX + SHLQ CL, br_value // value <<= n +#endif + + ADDQ CX, br_bits_read // bits_read += n + + +#ifdef GOAMD64_v3 + SHRXQ peek_bits, br_value, AX // AX = (value >> peek_bits) & mask +#else + // val1 := br{{ var "id"}}.peekTopBits(peekBits) + MOVQ peek_bits, CX + MOVQ br_value, AX + SHRQ CL, AX // AX = (value >> peek_bits) & mask +#endif + + // v1 := table[val1&mask] + MOVW 0(table)(AX*2), AX // AX - v1 + + // br{{ var "id"}}.advance(uint8(v1.entry)) + MOVB AH, BH // BH = uint8(v1.entry >> 8) + +#ifdef GOAMD64_v3 + MOVBQZX AL, CX + SHLXQ AX, br_value, br_value // value <<= n +#else + MOVBQZX AL, CX + SHLQ CL, br_value // value <<= n +#endif + + ADDQ CX, br_bits_read // bits_read += n + + + // these two writes get coalesced + // buf[stream][off] = uint8(v0.entry >> 8) + // buf[stream][off+1] = uint8(v1.entry >> 8) + MOVW BX, {{ var "bufofs" }}(buffer)(off*1) + + // update the bitrader reader structure + MOVB br_bits_read, bitReaderShifted_bitsRead(br{{ var "id" }}) + MOVQ br_value, bitReaderShifted_value(br{{ var "id" }}) + MOVQ br_offset, bitReaderShifted_off(br{{ var "id" }}) +{{ end }} + + {{ set "id" "0" }} + {{ set "ofs" "0" }} + {{ set "bufofs" "0" }} {{/* id * bufoff */}} + {{ template "decode_2_values_x86" . }} + + {{ set "id" "1" }} + {{ set "ofs" "8" }} + {{ set "bufofs" "256" }} + {{ template "decode_2_values_x86" . }} + + {{ set "id" "2" }} + {{ set "ofs" "16" }} + {{ set "bufofs" "512" }} + {{ template "decode_2_values_x86" . }} + + {{ set "id" "3" }} + {{ set "ofs" "24" }} + {{ set "bufofs" "768" }} + {{ template "decode_2_values_x86" . }} + + ADDQ $2, off // off += 2 + + TESTB DH, DH // any br[i].ofs < 4? + JNZ end + + CMPQ off, $bufoff + JL main_loop +end: + MOVQ 0(SP), BP + + MOVB off, ret+56(FP) + RET +#undef off +#undef buffer +#undef table + +#undef br_bits_read +#undef br_value +#undef br_offset +#undef peek_bits +#undef exhausted + +#undef br0 +#undef br1 +#undef br2 +#undef br3 diff --git a/vendor/github.com/klauspost/compress/huff0/decompress_generic.go b/vendor/github.com/klauspost/compress/huff0/decompress_generic.go new file mode 100644 index 000000000..126b4d68a --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/decompress_generic.go @@ -0,0 +1,193 @@ +//go:build !amd64 || appengine || !gc || noasm +// +build !amd64 appengine !gc noasm + +// This file contains a generic implementation of Decoder.Decompress4X. +package huff0 + +import ( + "errors" + "fmt" +) + +// Decompress4X will decompress a 4X encoded stream. +// The length of the supplied input must match the end of a block exactly. +// The *capacity* of the dst slice must match the destination size of +// the uncompressed data exactly. +func (d *Decoder) Decompress4X(dst, src []byte) ([]byte, error) { + if len(d.dt.single) == 0 { + return nil, errors.New("no table loaded") + } + if len(src) < 6+(4*1) { + return nil, errors.New("input too small") + } + if use8BitTables && d.actualTableLog <= 8 { + return d.decompress4X8bit(dst, src) + } + + var br [4]bitReaderShifted + // Decode "jump table" + start := 6 + for i := 0; i < 3; i++ { + length := int(src[i*2]) | (int(src[i*2+1]) << 8) + if start+length >= len(src) { + return nil, errors.New("truncated input (or invalid offset)") + } + err := br[i].init(src[start : start+length]) + if err != nil { + return nil, err + } + start += length + } + err := br[3].init(src[start:]) + if err != nil { + return nil, err + } + + // destination, offset to match first output + dstSize := cap(dst) + dst = dst[:dstSize] + out := dst + dstEvery := (dstSize + 3) / 4 + + const tlSize = 1 << tableLogMax + const tlMask = tlSize - 1 + single := d.dt.single[:tlSize] + + // Use temp table to avoid bound checks/append penalty. + buf := d.buffer() + var off uint8 + var decoded int + + // Decode 2 values from each decoder/loop. + const bufoff = 256 + for { + if br[0].off < 4 || br[1].off < 4 || br[2].off < 4 || br[3].off < 4 { + break + } + + { + const stream = 0 + const stream2 = 1 + br[stream].fillFast() + br[stream2].fillFast() + + val := br[stream].peekBitsFast(d.actualTableLog) + val2 := br[stream2].peekBitsFast(d.actualTableLog) + v := single[val&tlMask] + v2 := single[val2&tlMask] + br[stream].advance(uint8(v.entry)) + br[stream2].advance(uint8(v2.entry)) + buf[stream][off] = uint8(v.entry >> 8) + buf[stream2][off] = uint8(v2.entry >> 8) + + val = br[stream].peekBitsFast(d.actualTableLog) + val2 = br[stream2].peekBitsFast(d.actualTableLog) + v = single[val&tlMask] + v2 = single[val2&tlMask] + br[stream].advance(uint8(v.entry)) + br[stream2].advance(uint8(v2.entry)) + buf[stream][off+1] = uint8(v.entry >> 8) + buf[stream2][off+1] = uint8(v2.entry >> 8) + } + + { + const stream = 2 + const stream2 = 3 + br[stream].fillFast() + br[stream2].fillFast() + + val := br[stream].peekBitsFast(d.actualTableLog) + val2 := br[stream2].peekBitsFast(d.actualTableLog) + v := single[val&tlMask] + v2 := single[val2&tlMask] + br[stream].advance(uint8(v.entry)) + br[stream2].advance(uint8(v2.entry)) + buf[stream][off] = uint8(v.entry >> 8) + buf[stream2][off] = uint8(v2.entry >> 8) + + val = br[stream].peekBitsFast(d.actualTableLog) + val2 = br[stream2].peekBitsFast(d.actualTableLog) + v = single[val&tlMask] + v2 = single[val2&tlMask] + br[stream].advance(uint8(v.entry)) + br[stream2].advance(uint8(v2.entry)) + buf[stream][off+1] = uint8(v.entry >> 8) + buf[stream2][off+1] = uint8(v2.entry >> 8) + } + + off += 2 + + if off == 0 { + if bufoff > dstEvery { + d.bufs.Put(buf) + return nil, errors.New("corruption detected: stream overrun 1") + } + copy(out, buf[0][:]) + copy(out[dstEvery:], buf[1][:]) + copy(out[dstEvery*2:], buf[2][:]) + copy(out[dstEvery*3:], buf[3][:]) + out = out[bufoff:] + decoded += bufoff * 4 + // There must at least be 3 buffers left. + if len(out) < dstEvery*3 { + d.bufs.Put(buf) + return nil, errors.New("corruption detected: stream overrun 2") + } + } + } + if off > 0 { + ioff := int(off) + if len(out) < dstEvery*3+ioff { + d.bufs.Put(buf) + return nil, errors.New("corruption detected: stream overrun 3") + } + copy(out, buf[0][:off]) + copy(out[dstEvery:], buf[1][:off]) + copy(out[dstEvery*2:], buf[2][:off]) + copy(out[dstEvery*3:], buf[3][:off]) + decoded += int(off) * 4 + out = out[off:] + } + + // Decode remaining. + remainBytes := dstEvery - (decoded / 4) + for i := range br { + offset := dstEvery * i + endsAt := offset + remainBytes + if endsAt > len(out) { + endsAt = len(out) + } + br := &br[i] + bitsLeft := br.remaining() + for bitsLeft > 0 { + br.fill() + if offset >= endsAt { + d.bufs.Put(buf) + return nil, errors.New("corruption detected: stream overrun 4") + } + + // Read value and increment offset. + val := br.peekBitsFast(d.actualTableLog) + v := single[val&tlMask].entry + nBits := uint8(v) + br.advance(nBits) + bitsLeft -= uint(nBits) + out[offset] = uint8(v >> 8) + offset++ + } + if offset != endsAt { + d.bufs.Put(buf) + return nil, fmt.Errorf("corruption detected: short output block %d, end %d != %d", i, offset, endsAt) + } + decoded += offset - dstEvery*i + err = br.close() + if err != nil { + return nil, err + } + } + d.bufs.Put(buf) + if dstSize != decoded { + return nil, errors.New("corruption detected: short output block") + } + return dst, nil +} diff --git a/vendor/github.com/klauspost/compress/zstd/README.md b/vendor/github.com/klauspost/compress/zstd/README.md index c876c591a..e3445ac19 100644 --- a/vendor/github.com/klauspost/compress/zstd/README.md +++ b/vendor/github.com/klauspost/compress/zstd/README.md @@ -153,10 +153,10 @@ http://sun.aei.polsl.pl/~sdeor/corpus/silesia.zip This package: file out level insize outsize millis mb/s -silesia.tar zskp 1 211947520 73101992 643 313.87 -silesia.tar zskp 2 211947520 67504318 969 208.38 -silesia.tar zskp 3 211947520 64595893 2007 100.68 -silesia.tar zskp 4 211947520 60995370 8825 22.90 +silesia.tar zskp 1 211947520 73821326 634 318.47 +silesia.tar zskp 2 211947520 67655404 1508 133.96 +silesia.tar zskp 3 211947520 64746933 3000 67.37 +silesia.tar zskp 4 211947520 60073508 16926 11.94 cgo zstd: silesia.tar zstd 1 211947520 73605392 543 371.56 @@ -165,94 +165,94 @@ silesia.tar zstd 6 211947520 62916450 1913 105.66 silesia.tar zstd 9 211947520 60212393 5063 39.92 gzip, stdlib/this package: -silesia.tar gzstd 1 211947520 80007735 1654 122.21 -silesia.tar gzkp 1 211947520 80136201 1152 175.45 +silesia.tar gzstd 1 211947520 80007735 1498 134.87 +silesia.tar gzkp 1 211947520 80088272 1009 200.31 GOB stream of binary data. Highly compressible. https://files.klauspost.com/compress/gob-stream.7z file out level insize outsize millis mb/s -gob-stream zskp 1 1911399616 235022249 3088 590.30 -gob-stream zskp 2 1911399616 205669791 3786 481.34 -gob-stream zskp 3 1911399616 175034659 9636 189.17 -gob-stream zskp 4 1911399616 165609838 50369 36.19 +gob-stream zskp 1 1911399616 233948096 3230 564.34 +gob-stream zskp 2 1911399616 203997694 4997 364.73 +gob-stream zskp 3 1911399616 173526523 13435 135.68 +gob-stream zskp 4 1911399616 162195235 47559 38.33 gob-stream zstd 1 1911399616 249810424 2637 691.26 gob-stream zstd 3 1911399616 208192146 3490 522.31 gob-stream zstd 6 1911399616 193632038 6687 272.56 gob-stream zstd 9 1911399616 177620386 16175 112.70 -gob-stream gzstd 1 1911399616 357382641 10251 177.82 -gob-stream gzkp 1 1911399616 359753026 5438 335.20 +gob-stream gzstd 1 1911399616 357382013 9046 201.49 +gob-stream gzkp 1 1911399616 359136669 4885 373.08 The test data for the Large Text Compression Benchmark is the first 10^9 bytes of the English Wikipedia dump on Mar. 3, 2006. http://mattmahoney.net/dc/textdata.html file out level insize outsize millis mb/s -enwik9 zskp 1 1000000000 343848582 3609 264.18 -enwik9 zskp 2 1000000000 317276632 5746 165.97 -enwik9 zskp 3 1000000000 292243069 12162 78.41 -enwik9 zskp 4 1000000000 262183768 82837 11.51 +enwik9 zskp 1 1000000000 343833605 3687 258.64 +enwik9 zskp 2 1000000000 317001237 7672 124.29 +enwik9 zskp 3 1000000000 291915823 15923 59.89 +enwik9 zskp 4 1000000000 261710291 77697 12.27 enwik9 zstd 1 1000000000 358072021 3110 306.65 enwik9 zstd 3 1000000000 313734672 4784 199.35 enwik9 zstd 6 1000000000 295138875 10290 92.68 enwik9 zstd 9 1000000000 278348700 28549 33.40 -enwik9 gzstd 1 1000000000 382578136 9604 99.30 -enwik9 gzkp 1 1000000000 383825945 6544 145.73 +enwik9 gzstd 1 1000000000 382578136 8608 110.78 +enwik9 gzkp 1 1000000000 382781160 5628 169.45 Highly compressible JSON file. https://files.klauspost.com/compress/github-june-2days-2019.json.zst file out level insize outsize millis mb/s -github-june-2days-2019.json zskp 1 6273951764 699045015 10620 563.40 -github-june-2days-2019.json zskp 2 6273951764 617881763 11687 511.96 -github-june-2days-2019.json zskp 3 6273951764 524340691 34043 175.75 -github-june-2days-2019.json zskp 4 6273951764 470320075 170190 35.16 +github-june-2days-2019.json zskp 1 6273951764 697439532 9789 611.17 +github-june-2days-2019.json zskp 2 6273951764 610876538 18553 322.49 +github-june-2days-2019.json zskp 3 6273951764 517662858 44186 135.41 +github-june-2days-2019.json zskp 4 6273951764 464617114 165373 36.18 github-june-2days-2019.json zstd 1 6273951764 766284037 8450 708.00 github-june-2days-2019.json zstd 3 6273951764 661889476 10927 547.57 github-june-2days-2019.json zstd 6 6273951764 642756859 22996 260.18 github-june-2days-2019.json zstd 9 6273951764 601974523 52413 114.16 -github-june-2days-2019.json gzstd 1 6273951764 1164400847 29948 199.79 -github-june-2days-2019.json gzkp 1 6273951764 1125417694 21788 274.61 +github-june-2days-2019.json gzstd 1 6273951764 1164397768 26793 223.32 +github-june-2days-2019.json gzkp 1 6273951764 1120631856 17693 338.16 VM Image, Linux mint with a few installed applications: https://files.klauspost.com/compress/rawstudio-mint14.7z file out level insize outsize millis mb/s -rawstudio-mint14.tar zskp 1 8558382592 3667489370 20210 403.84 -rawstudio-mint14.tar zskp 2 8558382592 3364592300 31873 256.07 -rawstudio-mint14.tar zskp 3 8558382592 3158085214 77675 105.08 -rawstudio-mint14.tar zskp 4 8558382592 2965110639 857750 9.52 +rawstudio-mint14.tar zskp 1 8558382592 3718400221 18206 448.29 +rawstudio-mint14.tar zskp 2 8558382592 3326118337 37074 220.15 +rawstudio-mint14.tar zskp 3 8558382592 3163842361 87306 93.49 +rawstudio-mint14.tar zskp 4 8558382592 2970480650 783862 10.41 rawstudio-mint14.tar zstd 1 8558382592 3609250104 17136 476.27 rawstudio-mint14.tar zstd 3 8558382592 3341679997 29262 278.92 rawstudio-mint14.tar zstd 6 8558382592 3235846406 77904 104.77 rawstudio-mint14.tar zstd 9 8558382592 3160778861 140946 57.91 -rawstudio-mint14.tar gzstd 1 8558382592 3926257486 57722 141.40 -rawstudio-mint14.tar gzkp 1 8558382592 3962605659 45113 180.92 +rawstudio-mint14.tar gzstd 1 8558382592 3926234992 51345 158.96 +rawstudio-mint14.tar gzkp 1 8558382592 3960117298 36722 222.26 CSV data: https://files.klauspost.com/compress/nyc-taxi-data-10M.csv.zst file out level insize outsize millis mb/s -nyc-taxi-data-10M.csv zskp 1 3325605752 641339945 8925 355.35 -nyc-taxi-data-10M.csv zskp 2 3325605752 591748091 11268 281.44 -nyc-taxi-data-10M.csv zskp 3 3325605752 530289687 25239 125.66 -nyc-taxi-data-10M.csv zskp 4 3325605752 476268884 135958 23.33 +nyc-taxi-data-10M.csv zskp 1 3325605752 641319332 9462 335.17 +nyc-taxi-data-10M.csv zskp 2 3325605752 588976126 17570 180.50 +nyc-taxi-data-10M.csv zskp 3 3325605752 529329260 32432 97.79 +nyc-taxi-data-10M.csv zskp 4 3325605752 474949772 138025 22.98 nyc-taxi-data-10M.csv zstd 1 3325605752 687399637 8233 385.18 nyc-taxi-data-10M.csv zstd 3 3325605752 598514411 10065 315.07 nyc-taxi-data-10M.csv zstd 6 3325605752 570522953 20038 158.27 nyc-taxi-data-10M.csv zstd 9 3325605752 517554797 64565 49.12 -nyc-taxi-data-10M.csv gzstd 1 3325605752 928656485 23876 132.83 -nyc-taxi-data-10M.csv gzkp 1 3325605752 922257165 16780 189.00 +nyc-taxi-data-10M.csv gzstd 1 3325605752 928654908 21270 149.11 +nyc-taxi-data-10M.csv gzkp 1 3325605752 922273214 13929 227.68 ``` ## Decompressor diff --git a/vendor/github.com/klauspost/compress/zstd/blockdec.go b/vendor/github.com/klauspost/compress/zstd/blockdec.go index 607b62ee3..7d567a54a 100644 --- a/vendor/github.com/klauspost/compress/zstd/blockdec.go +++ b/vendor/github.com/klauspost/compress/zstd/blockdec.go @@ -167,6 +167,11 @@ func (b *blockDec) reset(br byteBuffer, windowSize uint64) error { } return ErrCompressedSizeTooBig } + // Empty compressed blocks must at least be 2 bytes + // for Literals_Block_Type and one for Sequences_Section_Header. + if cSize < 2 { + return ErrBlockTooSmall + } case blockTypeRaw: if cSize > maxCompressedBlockSize || cSize > int(b.WindowSize) { if debugDecoder { @@ -491,6 +496,9 @@ func (b *blockDec) decodeCompressed(hist *history) error { } func (b *blockDec) prepareSequences(in []byte, hist *history) (err error) { + if debugDecoder { + printf("prepareSequences: %d byte(s) input\n", len(in)) + } // Decode Sequences // https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md#sequences-section if len(in) < 1 { @@ -499,8 +507,6 @@ func (b *blockDec) prepareSequences(in []byte, hist *history) (err error) { var nSeqs int seqHeader := in[0] switch { - case seqHeader == 0: - in = in[1:] case seqHeader < 128: nSeqs = int(seqHeader) in = in[1:] @@ -517,6 +523,13 @@ func (b *blockDec) prepareSequences(in []byte, hist *history) (err error) { nSeqs = 0x7f00 + int(in[1]) + (int(in[2]) << 8) in = in[3:] } + if nSeqs == 0 && len(in) != 0 { + // When no sequences, there should not be any more data... + if debugDecoder { + printf("prepareSequences: 0 sequences, but %d byte(s) left on stream\n", len(in)) + } + return ErrUnexpectedBlockSize + } var seqs = &hist.decoders seqs.nSeqs = nSeqs @@ -635,6 +648,7 @@ func (b *blockDec) decodeSequences(hist *history) error { hist.decoders.seqSize = len(hist.decoders.literals) return nil } + hist.decoders.windowSize = hist.windowSize hist.decoders.prevOffset = hist.recentOffsets err := hist.decoders.decode(b.sequence) hist.recentOffsets = hist.decoders.prevOffset diff --git a/vendor/github.com/klauspost/compress/zstd/decoder.go b/vendor/github.com/klauspost/compress/zstd/decoder.go index a93dfaf10..9fcdaac1d 100644 --- a/vendor/github.com/klauspost/compress/zstd/decoder.go +++ b/vendor/github.com/klauspost/compress/zstd/decoder.go @@ -348,10 +348,10 @@ func (d *Decoder) DecodeAll(input, dst []byte) ([]byte, error) { frame.history.setDict(&dict) } - if frame.FrameContentSize > d.o.maxDecodedSize-uint64(len(dst)) { + if frame.FrameContentSize != fcsUnknown && frame.FrameContentSize > d.o.maxDecodedSize-uint64(len(dst)) { return dst, ErrDecoderSizeExceeded } - if frame.FrameContentSize > 0 && frame.FrameContentSize < 1<<30 { + if frame.FrameContentSize < 1<<30 { // Never preallocate more than 1 GB up front. if cap(dst)-len(dst) < int(frame.FrameContentSize) { dst2 := make([]byte, len(dst), len(dst)+int(frame.FrameContentSize)) @@ -514,7 +514,7 @@ func (d *Decoder) nextBlockSync() (ok bool) { // Check frame size (before CRC) d.syncStream.decodedFrame += uint64(len(d.current.b)) - if d.frame.FrameContentSize > 0 && d.syncStream.decodedFrame > d.frame.FrameContentSize { + if d.syncStream.decodedFrame > d.frame.FrameContentSize { if debugDecoder { printf("DecodedFrame (%d) > FrameContentSize (%d)\n", d.syncStream.decodedFrame, d.frame.FrameContentSize) } @@ -523,7 +523,7 @@ func (d *Decoder) nextBlockSync() (ok bool) { } // Check FCS - if d.current.d.Last && d.frame.FrameContentSize > 0 && d.syncStream.decodedFrame != d.frame.FrameContentSize { + if d.current.d.Last && d.frame.FrameContentSize != fcsUnknown && d.syncStream.decodedFrame != d.frame.FrameContentSize { if debugDecoder { printf("DecodedFrame (%d) != FrameContentSize (%d)\n", d.syncStream.decodedFrame, d.frame.FrameContentSize) } @@ -700,6 +700,7 @@ func (d *Decoder) startStreamDecoder(ctx context.Context, r io.Reader, output ch } hist.decoders = block.async.newHist.decoders hist.recentOffsets = block.async.newHist.recentOffsets + hist.windowSize = block.async.newHist.windowSize if block.async.newHist.dict != nil { hist.setDict(block.async.newHist.dict) } @@ -811,11 +812,11 @@ func (d *Decoder) startStreamDecoder(ctx context.Context, r io.Reader, output ch } if !hasErr { decodedFrame += uint64(len(do.b)) - if fcs > 0 && decodedFrame > fcs { + if decodedFrame > fcs { println("fcs exceeded", block.Last, fcs, decodedFrame) do.err = ErrFrameSizeExceeded hasErr = true - } else if block.Last && fcs > 0 && decodedFrame != fcs { + } else if block.Last && fcs != fcsUnknown && decodedFrame != fcs { do.err = ErrFrameSizeMismatch hasErr = true } else { diff --git a/vendor/github.com/klauspost/compress/zstd/framedec.go b/vendor/github.com/klauspost/compress/zstd/framedec.go index 29c3176b0..11089d223 100644 --- a/vendor/github.com/klauspost/compress/zstd/framedec.go +++ b/vendor/github.com/klauspost/compress/zstd/framedec.go @@ -197,7 +197,7 @@ func (d *frameDec) reset(br byteBuffer) error { default: fcsSize = 1 << v } - d.FrameContentSize = 0 + d.FrameContentSize = fcsUnknown if fcsSize > 0 { b, err := br.readSmall(fcsSize) if err != nil { @@ -343,12 +343,7 @@ func (d *frameDec) runDecoder(dst []byte, dec *blockDec) ([]byte, error) { err = ErrDecoderSizeExceeded break } - if d.SingleSegment && uint64(len(d.history.b)) > d.o.maxDecodedSize { - println("runDecoder: single segment and", uint64(len(d.history.b)), ">", d.o.maxDecodedSize) - err = ErrFrameSizeExceeded - break - } - if d.FrameContentSize > 0 && uint64(len(d.history.b)-crcStart) > d.FrameContentSize { + if uint64(len(d.history.b)-crcStart) > d.FrameContentSize { println("runDecoder: FrameContentSize exceeded", uint64(len(d.history.b)-crcStart), ">", d.FrameContentSize) err = ErrFrameSizeExceeded break @@ -356,13 +351,13 @@ func (d *frameDec) runDecoder(dst []byte, dec *blockDec) ([]byte, error) { if dec.Last { break } - if debugDecoder && d.FrameContentSize > 0 { + if debugDecoder { println("runDecoder: FrameContentSize", uint64(len(d.history.b)-crcStart), "<=", d.FrameContentSize) } } dst = d.history.b if err == nil { - if d.FrameContentSize > 0 && uint64(len(d.history.b)-crcStart) != d.FrameContentSize { + if d.FrameContentSize != fcsUnknown && uint64(len(d.history.b)-crcStart) != d.FrameContentSize { err = ErrFrameSizeMismatch } else if d.HasCheckSum { var n int diff --git a/vendor/github.com/klauspost/compress/zstd/fuzz.go b/vendor/github.com/klauspost/compress/zstd/fuzz.go index fda8a7422..7f2210e05 100644 --- a/vendor/github.com/klauspost/compress/zstd/fuzz.go +++ b/vendor/github.com/klauspost/compress/zstd/fuzz.go @@ -1,5 +1,5 @@ -//go:build gofuzz -// +build gofuzz +//go:build ignorecrc +// +build ignorecrc // Copyright 2019+ Klaus Post. All rights reserved. // License information can be found in the LICENSE file. diff --git a/vendor/github.com/klauspost/compress/zstd/fuzz_none.go b/vendor/github.com/klauspost/compress/zstd/fuzz_none.go index 0515b201c..6811c68a8 100644 --- a/vendor/github.com/klauspost/compress/zstd/fuzz_none.go +++ b/vendor/github.com/klauspost/compress/zstd/fuzz_none.go @@ -1,5 +1,5 @@ -//go:build !gofuzz -// +build !gofuzz +//go:build !ignorecrc +// +build !ignorecrc // Copyright 2019+ Klaus Post. All rights reserved. // License information can be found in the LICENSE file. diff --git a/vendor/github.com/klauspost/compress/zstd/seqdec.go b/vendor/github.com/klauspost/compress/zstd/seqdec.go index 213736ad7..819f1461b 100644 --- a/vendor/github.com/klauspost/compress/zstd/seqdec.go +++ b/vendor/github.com/klauspost/compress/zstd/seqdec.go @@ -107,7 +107,10 @@ func (s *sequenceDecs) decode(seqs []seqVals) error { llState, mlState, ofState := s.litLengths.state.state, s.matchLengths.state.state, s.offsets.state.state s.seqSize = 0 litRemain := len(s.literals) - + maxBlockSize := maxCompressedBlockSize + if s.windowSize < maxBlockSize { + maxBlockSize = s.windowSize + } for i := range seqs { var ll, mo, ml int if br.off > 4+((maxOffsetBits+16+16)>>3) { @@ -192,7 +195,7 @@ func (s *sequenceDecs) decode(seqs []seqVals) error { } s.seqSize += ll + ml if s.seqSize > maxBlockSize { - return fmt.Errorf("output (%d) bigger than max block size", s.seqSize) + return fmt.Errorf("output (%d) bigger than max block size (%d)", s.seqSize, maxBlockSize) } litRemain -= ll if litRemain < 0 { @@ -230,7 +233,7 @@ func (s *sequenceDecs) decode(seqs []seqVals) error { } s.seqSize += litRemain if s.seqSize > maxBlockSize { - return fmt.Errorf("output (%d) bigger than max block size", s.seqSize) + return fmt.Errorf("output (%d) bigger than max block size (%d)", s.seqSize, maxBlockSize) } err := br.close() if err != nil { @@ -347,6 +350,10 @@ func (s *sequenceDecs) decodeSync(history *history) error { llState, mlState, ofState := s.litLengths.state.state, s.matchLengths.state.state, s.offsets.state.state hist := history.b[history.ignoreBuffer:] out := s.out + maxBlockSize := maxCompressedBlockSize + if s.windowSize < maxBlockSize { + maxBlockSize = s.windowSize + } for i := seqs - 1; i >= 0; i-- { if br.overread() { @@ -426,7 +433,7 @@ func (s *sequenceDecs) decodeSync(history *history) error { } size := ll + ml + len(out) if size-startSize > maxBlockSize { - return fmt.Errorf("output (%d) bigger than max block size", size) + return fmt.Errorf("output (%d) bigger than max block size (%d)", size, maxBlockSize) } if size > cap(out) { // Not enough size, which can happen under high volume block streaming conditions @@ -535,6 +542,11 @@ func (s *sequenceDecs) decodeSync(history *history) error { } } + // Check if space for literals + if len(s.literals)+len(s.out)-startSize > maxBlockSize { + return fmt.Errorf("output (%d) bigger than max block size (%d)", len(s.out), maxBlockSize) + } + // Add final literals s.out = append(out, s.literals...) return br.close() diff --git a/vendor/github.com/klauspost/compress/zstd/zip.go b/vendor/github.com/klauspost/compress/zstd/zip.go index 967f29b31..ffffcbc25 100644 --- a/vendor/github.com/klauspost/compress/zstd/zip.go +++ b/vendor/github.com/klauspost/compress/zstd/zip.go @@ -20,7 +20,7 @@ const ZipMethodPKWare = 20 var zipReaderPool sync.Pool -// newZipReader cannot be used since we would leak goroutines... +// newZipReader creates a pooled zip decompressor. func newZipReader(r io.Reader) io.ReadCloser { dec, ok := zipReaderPool.Get().(*Decoder) if ok { @@ -44,10 +44,14 @@ func (r *pooledZipReader) Read(p []byte) (n int, err error) { r.mu.Lock() defer r.mu.Unlock() if r.dec == nil { - return 0, errors.New("Read after Close") + return 0, errors.New("read after close or EOF") } dec, err := r.dec.Read(p) - + if err == io.EOF { + err = r.dec.Reset(nil) + zipReaderPool.Put(r.dec) + r.dec = nil + } return dec, err } @@ -112,11 +116,5 @@ func ZipCompressor(opts ...EOption) func(w io.Writer) (io.WriteCloser, error) { // ZipDecompressor returns a decompressor that can be registered with zip libraries. // See ZipCompressor for example. func ZipDecompressor() func(r io.Reader) io.ReadCloser { - return func(r io.Reader) io.ReadCloser { - d, err := NewReader(r, WithDecoderConcurrency(1), WithDecoderLowmem(true)) - if err != nil { - panic(err) - } - return d.IOReadCloser() - } + return newZipReader } diff --git a/vendor/github.com/klauspost/compress/zstd/zstd.go b/vendor/github.com/klauspost/compress/zstd/zstd.go index 0b0c2571d..c1c90b4a0 100644 --- a/vendor/github.com/klauspost/compress/zstd/zstd.go +++ b/vendor/github.com/klauspost/compress/zstd/zstd.go @@ -39,6 +39,9 @@ const zstdMinMatch = 3 // Reset the buffer offset when reaching this. const bufferReset = math.MaxInt32 - MaxWindowSize +// fcsUnknown is used for unknown frame content size. +const fcsUnknown = math.MaxUint64 + var ( // ErrReservedBlockType is returned when a reserved block type is found. // Typically this indicates wrong or corrupted input. @@ -52,6 +55,10 @@ var ( // Typically returned on invalid input. ErrBlockTooSmall = errors.New("block too small") + // ErrUnexpectedBlockSize is returned when a block has unexpected size. + // Typically returned on invalid input. + ErrUnexpectedBlockSize = errors.New("unexpected block size") + // ErrMagicMismatch is returned when a "magic" number isn't what is expected. // Typically this indicates wrong or corrupted input. ErrMagicMismatch = errors.New("invalid input: magic number mismatch") diff --git a/vendor/github.com/miekg/pkcs11/.travis.yml b/vendor/github.com/miekg/pkcs11/.travis.yml deleted file mode 100644 index 687044d83..000000000 --- a/vendor/github.com/miekg/pkcs11/.travis.yml +++ /dev/null @@ -1,14 +0,0 @@ -language: go -sudo: required -dist: trusty - -go: - - 1.9 - - tip - -script: - - go test -v ./... - -before_script: - - sudo apt-get update - - sudo apt-get -y install libsofthsm diff --git a/vendor/github.com/miekg/pkcs11/README.md b/vendor/github.com/miekg/pkcs11/README.md index 0a5c1b7b6..18a361a99 100644 --- a/vendor/github.com/miekg/pkcs11/README.md +++ b/vendor/github.com/miekg/pkcs11/README.md @@ -1,6 +1,6 @@ -# PKCS#11 [![Build Status](https://travis-ci.org/miekg/pkcs11.png?branch=master)](https://travis-ci.org/miekg/pkcs11) [![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](http://godoc.org/github.com/miekg/pkcs11) +# PKCS#11 -This is a Go implementation of the PKCS#11 API. It wraps the library closely, but uses Go idiom were +This is a Go implementation of the PKCS#11 API. It wraps the library closely, but uses Go idiom where it makes sense. It has been tested with SoftHSM. ## SoftHSM @@ -13,10 +13,10 @@ it makes sense. It has been tested with SoftHSM. softhsm --init-token --slot 0 --label test --pin 1234 ~~~ - * Then use `libsofthsm.so` as the pkcs11 module: + * Then use `libsofthsm2.so` as the pkcs11 module: ~~~ go - p := pkcs11.New("/usr/lib/softhsm/libsofthsm.so") + p := pkcs11.New("/usr/lib/softhsm/libsofthsm2.so") ~~~ ## Examples @@ -24,7 +24,7 @@ it makes sense. It has been tested with SoftHSM. A skeleton program would look somewhat like this (yes, pkcs#11 is verbose): ~~~ go -p := pkcs11.New("/usr/lib/softhsm/libsofthsm.so") +p := pkcs11.New("/usr/lib/softhsm/libsofthsm2.so") err := p.Initialize() if err != nil { panic(err) diff --git a/vendor/github.com/miekg/pkcs11/pkcs11.go b/vendor/github.com/miekg/pkcs11/pkcs11.go index e21d23b73..e1b5824ec 100644 --- a/vendor/github.com/miekg/pkcs11/pkcs11.go +++ b/vendor/github.com/miekg/pkcs11/pkcs11.go @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:generate go run const_generate.go + // Package pkcs11 is a wrapper around the PKCS#11 cryptographic library. package pkcs11 @@ -14,7 +16,7 @@ package pkcs11 #cgo windows CFLAGS: -DPACKED_STRUCTURES #cgo linux LDFLAGS: -ldl #cgo darwin LDFLAGS: -ldl -#cgo openbsd LDFLAGS: -ldl +#cgo openbsd LDFLAGS: #cgo freebsd LDFLAGS: -ldl #include <stdlib.h> @@ -770,9 +772,10 @@ static inline CK_VOID_PTR getAttributePval(CK_ATTRIBUTE_PTR a) */ import "C" -import "strings" - -import "unsafe" +import ( + "strings" + "unsafe" +) // Ctx contains the current pkcs11 context. type Ctx struct { diff --git a/vendor/github.com/miekg/pkcs11/release.go b/vendor/github.com/miekg/pkcs11/release.go index 4380f374d..d8b99f147 100644 --- a/vendor/github.com/miekg/pkcs11/release.go +++ b/vendor/github.com/miekg/pkcs11/release.go @@ -1,3 +1,4 @@ +//go:build release // +build release package pkcs11 @@ -5,7 +6,7 @@ package pkcs11 import "fmt" // Release is current version of the pkcs11 library. -var Release = R{1, 0, 3} +var Release = R{1, 1, 1} // R holds the version of this library. type R struct { diff --git a/vendor/github.com/miekg/pkcs11/types.go b/vendor/github.com/miekg/pkcs11/types.go index 970db9061..60eadcb71 100644 --- a/vendor/github.com/miekg/pkcs11/types.go +++ b/vendor/github.com/miekg/pkcs11/types.go @@ -182,8 +182,20 @@ func NewAttribute(typ uint, x interface{}) *Attribute { } case int: a.Value = uintToBytes(uint64(v)) + case int16: + a.Value = uintToBytes(uint64(v)) + case int32: + a.Value = uintToBytes(uint64(v)) + case int64: + a.Value = uintToBytes(uint64(v)) case uint: a.Value = uintToBytes(uint64(v)) + case uint16: + a.Value = uintToBytes(uint64(v)) + case uint32: + a.Value = uintToBytes(uint64(v)) + case uint64: + a.Value = uintToBytes(uint64(v)) case string: a.Value = []byte(v) case []byte: diff --git a/vendor/github.com/miekg/pkcs11/const.go b/vendor/github.com/miekg/pkcs11/zconst.go index 408856146..41df5cfcf 100644 --- a/vendor/github.com/miekg/pkcs11/const.go +++ b/vendor/github.com/miekg/pkcs11/zconst.go @@ -2,48 +2,18 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package pkcs11 - -const ( - CKU_SO uint = 0 - CKU_USER uint = 1 - CKU_CONTEXT_SPECIFIC uint = 2 -) - -const ( - CKO_DATA uint = 0x00000000 - CKO_CERTIFICATE uint = 0x00000001 - CKO_PUBLIC_KEY uint = 0x00000002 - CKO_PRIVATE_KEY uint = 0x00000003 - CKO_SECRET_KEY uint = 0x00000004 - CKO_HW_FEATURE uint = 0x00000005 - CKO_DOMAIN_PARAMETERS uint = 0x00000006 - CKO_MECHANISM uint = 0x00000007 - CKO_OTP_KEY uint = 0x00000008 - CKO_VENDOR_DEFINED uint = 0x80000000 -) - -const ( - CKG_MGF1_SHA1 uint = 0x00000001 - CKG_MGF1_SHA224 uint = 0x00000005 - CKG_MGF1_SHA256 uint = 0x00000002 - CKG_MGF1_SHA384 uint = 0x00000003 - CKG_MGF1_SHA512 uint = 0x00000004 - CKG_MGF1_SHA3_224 uint = 0x00000006 - CKG_MGF1_SHA3_256 uint = 0x00000007 - CKG_MGF1_SHA3_384 uint = 0x00000008 - CKG_MGF1_SHA3_512 uint = 0x00000009 -) - -const ( - CKZ_DATA_SPECIFIED uint = 0x00000001 -) +// Code generated by "go run const_generate.go"; DO NOT EDIT. -// Generated with: awk '/#define CK[AFKMRC]/{ print $2 " = " $3 }' pkcs11t.h | sed -e 's/UL$//g' -e 's/UL)$/)/g' +package pkcs11 -// All the flag (CKF_), attribute (CKA_), error code (CKR_), key type (CKK_), certificate type (CKC_) and -// mechanism (CKM_) constants as defined in PKCS#11. const ( + CK_TRUE = 1 + CK_FALSE = 0 + CK_UNAVAILABLE_INFORMATION = ^uint(0) + CK_EFFECTIVELY_INFINITE = 0 + CK_INVALID_HANDLE = 0 + CKN_SURRENDER = 0 + CKN_OTP_CHANGED = 1 CKF_TOKEN_PRESENT = 0x00000001 CKF_REMOVABLE_DEVICE = 0x00000002 CKF_HW_SLOT = 0x00000004 @@ -66,12 +36,34 @@ const ( CKF_SO_PIN_LOCKED = 0x00400000 CKF_SO_PIN_TO_BE_CHANGED = 0x00800000 CKF_ERROR_STATE = 0x01000000 + CKU_SO = 0 + CKU_USER = 1 + CKU_CONTEXT_SPECIFIC = 2 + CKS_RO_PUBLIC_SESSION = 0 + CKS_RO_USER_FUNCTIONS = 1 + CKS_RW_PUBLIC_SESSION = 2 + CKS_RW_USER_FUNCTIONS = 3 + CKS_RW_SO_FUNCTIONS = 4 CKF_RW_SESSION = 0x00000002 CKF_SERIAL_SESSION = 0x00000004 + CKO_DATA = 0x00000000 + CKO_CERTIFICATE = 0x00000001 + CKO_PUBLIC_KEY = 0x00000002 + CKO_PRIVATE_KEY = 0x00000003 + CKO_SECRET_KEY = 0x00000004 + CKO_HW_FEATURE = 0x00000005 + CKO_DOMAIN_PARAMETERS = 0x00000006 + CKO_MECHANISM = 0x00000007 + CKO_OTP_KEY = 0x00000008 + CKO_VENDOR_DEFINED = 0x80000000 + CKH_MONOTONIC_COUNTER = 0x00000001 + CKH_CLOCK = 0x00000002 + CKH_USER_INTERFACE = 0x00000003 + CKH_VENDOR_DEFINED = 0x80000000 CKK_RSA = 0x00000000 CKK_DSA = 0x00000001 CKK_DH = 0x00000002 - CKK_ECDSA = 0x00000003 + CKK_ECDSA = 0x00000003 // Deprecated CKK_EC = 0x00000003 CKK_X9_42_DH = 0x00000004 CKK_KEA = 0x00000005 @@ -83,7 +75,7 @@ const ( CKK_DES3 = 0x00000015 CKK_CAST = 0x00000016 CKK_CAST3 = 0x00000017 - CKK_CAST5 = 0x00000018 + CKK_CAST5 = 0x00000018 // Deprecated CKK_CAST128 = 0x00000018 CKK_RC5 = 0x00000019 CKK_IDEA = 0x0000001A @@ -99,14 +91,14 @@ const ( CKK_ACTI = 0x00000024 CKK_CAMELLIA = 0x00000025 CKK_ARIA = 0x00000026 - CKK_SHA512_224_HMAC = 0x00000027 - CKK_SHA512_256_HMAC = 0x00000028 - CKK_SHA512_T_HMAC = 0x00000029 + CKK_MD5_HMAC = 0x00000027 CKK_SHA_1_HMAC = 0x00000028 - CKK_SHA224_HMAC = 0x0000002E + CKK_RIPEMD128_HMAC = 0x00000029 + CKK_RIPEMD160_HMAC = 0x0000002A CKK_SHA256_HMAC = 0x0000002B CKK_SHA384_HMAC = 0x0000002C CKK_SHA512_HMAC = 0x0000002D + CKK_SHA224_HMAC = 0x0000002E CKK_SEED = 0x0000002F CKK_GOSTR3410 = 0x00000030 CKK_GOSTR3411 = 0x00000031 @@ -116,11 +108,26 @@ const ( CKK_SHA3_384_HMAC = 0x00000035 CKK_SHA3_512_HMAC = 0x00000036 CKK_VENDOR_DEFINED = 0x80000000 + CK_CERTIFICATE_CATEGORY_UNSPECIFIED = 0 + CK_CERTIFICATE_CATEGORY_TOKEN_USER = 1 + CK_CERTIFICATE_CATEGORY_AUTHORITY = 2 + CK_CERTIFICATE_CATEGORY_OTHER_ENTITY = 3 + CK_SECURITY_DOMAIN_UNSPECIFIED = 0 + CK_SECURITY_DOMAIN_MANUFACTURER = 1 + CK_SECURITY_DOMAIN_OPERATOR = 2 + CK_SECURITY_DOMAIN_THIRD_PARTY = 3 CKC_X_509 = 0x00000000 CKC_X_509_ATTR_CERT = 0x00000001 CKC_WTLS = 0x00000002 CKC_VENDOR_DEFINED = 0x80000000 CKF_ARRAY_ATTRIBUTE = 0x40000000 + CK_OTP_FORMAT_DECIMAL = 0 + CK_OTP_FORMAT_HEXADECIMAL = 1 + CK_OTP_FORMAT_ALPHANUMERIC = 2 + CK_OTP_FORMAT_BINARY = 3 + CK_OTP_PARAM_IGNORED = 0 + CK_OTP_PARAM_OPTIONAL = 1 + CK_OTP_PARAM_MANDATORY = 2 CKA_CLASS = 0x00000000 CKA_TOKEN = 0x00000001 CKA_PRIVATE = 0x00000002 @@ -183,15 +190,16 @@ const ( CKA_MODIFIABLE = 0x00000170 CKA_COPYABLE = 0x00000171 CKA_DESTROYABLE = 0x00000172 - CKA_ECDSA_PARAMS = 0x00000180 + CKA_ECDSA_PARAMS = 0x00000180 // Deprecated CKA_EC_PARAMS = 0x00000180 CKA_EC_POINT = 0x00000181 - CKA_SECONDARY_AUTH = 0x00000200 - CKA_AUTH_PIN_FLAGS = 0x00000201 + CKA_SECONDARY_AUTH = 0x00000200 // Deprecated + CKA_AUTH_PIN_FLAGS = 0x00000201 // Deprecated CKA_ALWAYS_AUTHENTICATE = 0x00000202 CKA_WRAP_WITH_TRUSTED = 0x00000210 - CKA_WRAP_TEMPLATE = CKF_ARRAY_ATTRIBUTE | 0x00000211 - CKA_UNWRAP_TEMPLATE = CKF_ARRAY_ATTRIBUTE | 0x00000212 + CKA_WRAP_TEMPLATE = (CKF_ARRAY_ATTRIBUTE | 0x00000211) + CKA_UNWRAP_TEMPLATE = (CKF_ARRAY_ATTRIBUTE | 0x00000212) + CKA_DERIVE_TEMPLATE = (CKF_ARRAY_ATTRIBUTE | 0x00000213) CKA_OTP_FORMAT = 0x00000220 CKA_OTP_LENGTH = 0x00000221 CKA_OTP_TIME_INTERVAL = 0x00000222 @@ -226,7 +234,7 @@ const ( CKA_REQUIRED_CMS_ATTRIBUTES = 0x00000501 CKA_DEFAULT_CMS_ATTRIBUTES = 0x00000502 CKA_SUPPORTED_CMS_ATTRIBUTES = 0x00000503 - CKA_ALLOWED_MECHANISMS = CKF_ARRAY_ATTRIBUTE | 0x00000600 + CKA_ALLOWED_MECHANISMS = (CKF_ARRAY_ATTRIBUTE | 0x00000600) CKA_VENDOR_DEFINED = 0x80000000 CKM_RSA_PKCS_KEY_PAIR_GEN = 0x00000000 CKM_RSA_PKCS = 0x00000001 @@ -246,11 +254,10 @@ const ( CKM_DSA_KEY_PAIR_GEN = 0x00000010 CKM_DSA = 0x00000011 CKM_DSA_SHA1 = 0x00000012 - CKM_DSA_FIPS_G_GEN = 0x00000013 - CKM_DSA_SHA224 = 0x00000014 - CKM_DSA_SHA256 = 0x00000015 - CKM_DSA_SHA384 = 0x00000016 - CKM_DSA_SHA512 = 0x00000017 + CKM_DSA_SHA224 = 0x00000013 + CKM_DSA_SHA256 = 0x00000014 + CKM_DSA_SHA384 = 0x00000015 + CKM_DSA_SHA512 = 0x00000016 CKM_DSA_SHA3_224 = 0x00000018 CKM_DSA_SHA3_256 = 0x00000019 CKM_DSA_SHA3_384 = 0x0000001A @@ -387,13 +394,13 @@ const ( CKM_CAST128_KEY_GEN = 0x00000320 CKM_CAST5_ECB = 0x00000321 CKM_CAST128_ECB = 0x00000321 - CKM_CAST5_CBC = 0x00000322 + CKM_CAST5_CBC = 0x00000322 // Deprecated CKM_CAST128_CBC = 0x00000322 - CKM_CAST5_MAC = 0x00000323 + CKM_CAST5_MAC = 0x00000323 // Deprecated CKM_CAST128_MAC = 0x00000323 - CKM_CAST5_MAC_GENERAL = 0x00000324 + CKM_CAST5_MAC_GENERAL = 0x00000324 // Deprecated CKM_CAST128_MAC_GENERAL = 0x00000324 - CKM_CAST5_CBC_PAD = 0x00000325 + CKM_CAST5_CBC_PAD = 0x00000325 // Deprecated CKM_CAST128_CBC_PAD = 0x00000325 CKM_RC5_KEY_GEN = 0x00000330 CKM_RC5_ECB = 0x00000331 @@ -441,9 +448,9 @@ const ( CKM_PBE_MD5_DES_CBC = 0x000003A1 CKM_PBE_MD5_CAST_CBC = 0x000003A2 CKM_PBE_MD5_CAST3_CBC = 0x000003A3 - CKM_PBE_MD5_CAST5_CBC = 0x000003A4 + CKM_PBE_MD5_CAST5_CBC = 0x000003A4 // Deprecated CKM_PBE_MD5_CAST128_CBC = 0x000003A4 - CKM_PBE_SHA1_CAST5_CBC = 0x000003A5 + CKM_PBE_SHA1_CAST5_CBC = 0x000003A5 // Deprecated CKM_PBE_SHA1_CAST128_CBC = 0x000003A5 CKM_PBE_SHA1_RC4_128 = 0x000003A6 CKM_PBE_SHA1_RC4_40 = 0x000003A7 @@ -522,7 +529,7 @@ const ( CKM_BATON_COUNTER = 0x00001034 CKM_BATON_SHUFFLE = 0x00001035 CKM_BATON_WRAP = 0x00001036 - CKM_ECDSA_KEY_PAIR_GEN = 0x00001040 + CKM_ECDSA_KEY_PAIR_GEN = 0x00001040 // Deprecated CKM_EC_KEY_PAIR_GEN = 0x00001040 CKM_ECDSA = 0x00001041 CKM_ECDSA_SHA1 = 0x00001042 @@ -551,9 +558,9 @@ const ( CKM_AES_CTR = 0x00001086 CKM_AES_GCM = 0x00001087 CKM_AES_CCM = 0x00001088 - CKM_AES_CMAC_GENERAL = 0x00001089 + CKM_AES_CTS = 0x00001089 CKM_AES_CMAC = 0x0000108A - CKM_AES_CTS = 0x0000108B + CKM_AES_CMAC_GENERAL = 0x0000108B CKM_AES_XCBC_MAC = 0x0000108C CKM_AES_XCBC_MAC_96 = 0x0000108D CKM_AES_GMAC = 0x0000108E @@ -704,33 +711,56 @@ const ( CKR_MUTEX_NOT_LOCKED = 0x000001A1 CKR_NEW_PIN_MODE = 0x000001B0 CKR_NEXT_OTP = 0x000001B1 - CKR_EXCEEDED_MAX_ITERATIONS = 0x000001C0 - CKR_FIPS_SELF_TEST_FAILED = 0x000001C1 - CKR_LIBRARY_LOAD_FAILED = 0x000001C2 - CKR_PIN_TOO_WEAK = 0x000001C3 - CKR_PUBLIC_KEY_INVALID = 0x000001C4 + CKR_EXCEEDED_MAX_ITERATIONS = 0x000001B5 + CKR_FIPS_SELF_TEST_FAILED = 0x000001B6 + CKR_LIBRARY_LOAD_FAILED = 0x000001B7 + CKR_PIN_TOO_WEAK = 0x000001B8 + CKR_PUBLIC_KEY_INVALID = 0x000001B9 CKR_FUNCTION_REJECTED = 0x00000200 CKR_VENDOR_DEFINED = 0x80000000 CKF_LIBRARY_CANT_CREATE_OS_THREADS = 0x00000001 CKF_OS_LOCKING_OK = 0x00000002 CKF_DONT_BLOCK = 1 + CKG_MGF1_SHA1 = 0x00000001 + CKG_MGF1_SHA256 = 0x00000002 + CKG_MGF1_SHA384 = 0x00000003 + CKG_MGF1_SHA512 = 0x00000004 + CKG_MGF1_SHA224 = 0x00000005 + CKZ_DATA_SPECIFIED = 0x00000001 + CKD_NULL = 0x00000001 + CKD_SHA1_KDF = 0x00000002 + CKD_SHA1_KDF_ASN1 = 0x00000003 + CKD_SHA1_KDF_CONCATENATE = 0x00000004 + CKD_SHA224_KDF = 0x00000005 + CKD_SHA256_KDF = 0x00000006 + CKD_SHA384_KDF = 0x00000007 + CKD_SHA512_KDF = 0x00000008 + CKD_CPDIVERSIFY_KDF = 0x00000009 + CKD_SHA3_224_KDF = 0x0000000A + CKD_SHA3_256_KDF = 0x0000000B + CKD_SHA3_384_KDF = 0x0000000C + CKD_SHA3_512_KDF = 0x0000000D + CKP_PKCS5_PBKD2_HMAC_SHA1 = 0x00000001 + CKP_PKCS5_PBKD2_HMAC_GOSTR3411 = 0x00000002 + CKP_PKCS5_PBKD2_HMAC_SHA224 = 0x00000003 + CKP_PKCS5_PBKD2_HMAC_SHA256 = 0x00000004 + CKP_PKCS5_PBKD2_HMAC_SHA384 = 0x00000005 + CKP_PKCS5_PBKD2_HMAC_SHA512 = 0x00000006 + CKP_PKCS5_PBKD2_HMAC_SHA512_224 = 0x00000007 + CKP_PKCS5_PBKD2_HMAC_SHA512_256 = 0x00000008 + CKZ_SALT_SPECIFIED = 0x00000001 + CK_OTP_VALUE = 0 + CK_OTP_PIN = 1 + CK_OTP_CHALLENGE = 2 + CK_OTP_TIME = 3 + CK_OTP_COUNTER = 4 + CK_OTP_FLAGS = 5 + CK_OTP_OUTPUT_LENGTH = 6 + CK_OTP_OUTPUT_FORMAT = 7 CKF_NEXT_OTP = 0x00000001 CKF_EXCLUDE_TIME = 0x00000002 CKF_EXCLUDE_COUNTER = 0x00000004 CKF_EXCLUDE_CHALLENGE = 0x00000008 CKF_EXCLUDE_PIN = 0x00000010 CKF_USER_FRIENDLY_OTP = 0x00000020 - CKD_NULL = 0x00000001 - CKD_SHA1_KDF = 0x00000002 -) - -// Special return values defined in PKCS#11 v2.40 section 3.2. -const ( - // CK_EFFECTIVELY_INFINITE may be returned in the CK_TOKEN_INFO fields ulMaxSessionCount and ulMaxRwSessionCount. - // It indicates there is no practical limit on the number of sessions. - CK_EFFECTIVELY_INFINITE = 0 - - // CK_UNAVAILABLE_INFORMATION may be returned for several fields within CK_TOKEN_INFO. It indicates - // the token is unable or unwilling to provide the requested information. - CK_UNAVAILABLE_INFORMATION = ^uint(0) ) diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client.go index 83c49b66a..861b4d21c 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client.go @@ -49,7 +49,10 @@ func InstrumentRoundTripperInFlight(gauge prometheus.Gauge, next http.RoundTripp // http.RoundTripper to observe the request result with the provided CounterVec. // The CounterVec must have zero, one, or two non-const non-curried labels. For // those, the only allowed label names are "code" and "method". The function -// panics otherwise. Partitioning of the CounterVec happens by HTTP status code +// panics otherwise. For the "method" label a predefined default label value set +// is used to filter given values. Values besides predefined values will count +// as `unknown` method.`WithExtraMethods` can be used to add more +// methods to the set. Partitioning of the CounterVec happens by HTTP status code // and/or HTTP method if the respective instance label names are present in the // CounterVec. For unpartitioned counting, use a CounterVec with zero labels. // @@ -57,13 +60,18 @@ func InstrumentRoundTripperInFlight(gauge prometheus.Gauge, next http.RoundTripp // is not incremented. // // See the example for ExampleInstrumentRoundTripperDuration for example usage. -func InstrumentRoundTripperCounter(counter *prometheus.CounterVec, next http.RoundTripper) RoundTripperFunc { +func InstrumentRoundTripperCounter(counter *prometheus.CounterVec, next http.RoundTripper, opts ...Option) RoundTripperFunc { + rtOpts := &option{} + for _, o := range opts { + o(rtOpts) + } + code, method := checkLabels(counter) return RoundTripperFunc(func(r *http.Request) (*http.Response, error) { resp, err := next.RoundTrip(r) if err == nil { - counter.With(labels(code, method, r.Method, resp.StatusCode)).Inc() + counter.With(labels(code, method, r.Method, resp.StatusCode, rtOpts.extraMethods...)).Inc() } return resp, err }) @@ -73,7 +81,10 @@ func InstrumentRoundTripperCounter(counter *prometheus.CounterVec, next http.Rou // http.RoundTripper to observe the request duration with the provided // ObserverVec. The ObserverVec must have zero, one, or two non-const // non-curried labels. For those, the only allowed label names are "code" and -// "method". The function panics otherwise. The Observe method of the Observer +// "method". The function panics otherwise. For the "method" label a predefined +// default label value set is used to filter given values. Values besides +// predefined values will count as `unknown` method. `WithExtraMethods` +// can be used to add more methods to the set. The Observe method of the Observer // in the ObserverVec is called with the request duration in // seconds. Partitioning happens by HTTP status code and/or HTTP method if the // respective instance label names are present in the ObserverVec. For @@ -85,14 +96,19 @@ func InstrumentRoundTripperCounter(counter *prometheus.CounterVec, next http.Rou // // Note that this method is only guaranteed to never observe negative durations // if used with Go1.9+. -func InstrumentRoundTripperDuration(obs prometheus.ObserverVec, next http.RoundTripper) RoundTripperFunc { +func InstrumentRoundTripperDuration(obs prometheus.ObserverVec, next http.RoundTripper, opts ...Option) RoundTripperFunc { + rtOpts := &option{} + for _, o := range opts { + o(rtOpts) + } + code, method := checkLabels(obs) return RoundTripperFunc(func(r *http.Request) (*http.Response, error) { start := time.Now() resp, err := next.RoundTrip(r) if err == nil { - obs.With(labels(code, method, r.Method, resp.StatusCode)).Observe(time.Since(start).Seconds()) + obs.With(labels(code, method, r.Method, resp.StatusCode, rtOpts.extraMethods...)).Observe(time.Since(start).Seconds()) } return resp, err }) diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server.go index ab037db86..a23f0edc6 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server.go @@ -45,7 +45,10 @@ func InstrumentHandlerInFlight(g prometheus.Gauge, next http.Handler) http.Handl // http.Handler to observe the request duration with the provided ObserverVec. // The ObserverVec must have valid metric and label names and must have zero, // one, or two non-const non-curried labels. For those, the only allowed label -// names are "code" and "method". The function panics otherwise. The Observe +// names are "code" and "method". The function panics otherwise. For the "method" +// label a predefined default label value set is used to filter given values. +// Values besides predefined values will count as `unknown` method. +//`WithExtraMethods` can be used to add more methods to the set. The Observe // method of the Observer in the ObserverVec is called with the request duration // in seconds. Partitioning happens by HTTP status code and/or HTTP method if // the respective instance label names are present in the ObserverVec. For @@ -58,7 +61,12 @@ func InstrumentHandlerInFlight(g prometheus.Gauge, next http.Handler) http.Handl // // Note that this method is only guaranteed to never observe negative durations // if used with Go1.9+. -func InstrumentHandlerDuration(obs prometheus.ObserverVec, next http.Handler) http.HandlerFunc { +func InstrumentHandlerDuration(obs prometheus.ObserverVec, next http.Handler, opts ...Option) http.HandlerFunc { + mwOpts := &option{} + for _, o := range opts { + o(mwOpts) + } + code, method := checkLabels(obs) if code { @@ -67,14 +75,14 @@ func InstrumentHandlerDuration(obs prometheus.ObserverVec, next http.Handler) ht d := newDelegator(w, nil) next.ServeHTTP(d, r) - obs.With(labels(code, method, r.Method, d.Status())).Observe(time.Since(now).Seconds()) + obs.With(labels(code, method, r.Method, d.Status(), mwOpts.extraMethods...)).Observe(time.Since(now).Seconds()) }) } return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { now := time.Now() next.ServeHTTP(w, r) - obs.With(labels(code, method, r.Method, 0)).Observe(time.Since(now).Seconds()) + obs.With(labels(code, method, r.Method, 0, mwOpts.extraMethods...)).Observe(time.Since(now).Seconds()) }) } @@ -82,7 +90,10 @@ func InstrumentHandlerDuration(obs prometheus.ObserverVec, next http.Handler) ht // to observe the request result with the provided CounterVec. The CounterVec // must have valid metric and label names and must have zero, one, or two // non-const non-curried labels. For those, the only allowed label names are -// "code" and "method". The function panics otherwise. Partitioning of the +// "code" and "method". The function panics otherwise. For the "method" +// label a predefined default label value set is used to filter given values. +// Values besides predefined values will count as `unknown` method. +// `WithExtraMethods` can be used to add more methods to the set. Partitioning of the // CounterVec happens by HTTP status code and/or HTTP method if the respective // instance label names are present in the CounterVec. For unpartitioned // counting, use a CounterVec with zero labels. @@ -92,20 +103,25 @@ func InstrumentHandlerDuration(obs prometheus.ObserverVec, next http.Handler) ht // If the wrapped Handler panics, the Counter is not incremented. // // See the example for InstrumentHandlerDuration for example usage. -func InstrumentHandlerCounter(counter *prometheus.CounterVec, next http.Handler) http.HandlerFunc { +func InstrumentHandlerCounter(counter *prometheus.CounterVec, next http.Handler, opts ...Option) http.HandlerFunc { + mwOpts := &option{} + for _, o := range opts { + o(mwOpts) + } + code, method := checkLabels(counter) if code { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { d := newDelegator(w, nil) next.ServeHTTP(d, r) - counter.With(labels(code, method, r.Method, d.Status())).Inc() + counter.With(labels(code, method, r.Method, d.Status(), mwOpts.extraMethods...)).Inc() }) } return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { next.ServeHTTP(w, r) - counter.With(labels(code, method, r.Method, 0)).Inc() + counter.With(labels(code, method, r.Method, 0, mwOpts.extraMethods...)).Inc() }) } @@ -114,7 +130,10 @@ func InstrumentHandlerCounter(counter *prometheus.CounterVec, next http.Handler) // until the response headers are written. The ObserverVec must have valid // metric and label names and must have zero, one, or two non-const non-curried // labels. For those, the only allowed label names are "code" and "method". The -// function panics otherwise. The Observe method of the Observer in the +// function panics otherwise. For the "method" label a predefined default label +// value set is used to filter given values. Values besides predefined values +// will count as `unknown` method.`WithExtraMethods` can be used to add more +// methods to the set. The Observe method of the Observer in the // ObserverVec is called with the request duration in seconds. Partitioning // happens by HTTP status code and/or HTTP method if the respective instance // label names are present in the ObserverVec. For unpartitioned observations, @@ -128,13 +147,18 @@ func InstrumentHandlerCounter(counter *prometheus.CounterVec, next http.Handler) // if used with Go1.9+. // // See the example for InstrumentHandlerDuration for example usage. -func InstrumentHandlerTimeToWriteHeader(obs prometheus.ObserverVec, next http.Handler) http.HandlerFunc { +func InstrumentHandlerTimeToWriteHeader(obs prometheus.ObserverVec, next http.Handler, opts ...Option) http.HandlerFunc { + mwOpts := &option{} + for _, o := range opts { + o(mwOpts) + } + code, method := checkLabels(obs) return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { now := time.Now() d := newDelegator(w, func(status int) { - obs.With(labels(code, method, r.Method, status)).Observe(time.Since(now).Seconds()) + obs.With(labels(code, method, r.Method, status, mwOpts.extraMethods...)).Observe(time.Since(now).Seconds()) }) next.ServeHTTP(d, r) }) @@ -144,8 +168,11 @@ func InstrumentHandlerTimeToWriteHeader(obs prometheus.ObserverVec, next http.Ha // http.Handler to observe the request size with the provided ObserverVec. The // ObserverVec must have valid metric and label names and must have zero, one, // or two non-const non-curried labels. For those, the only allowed label names -// are "code" and "method". The function panics otherwise. The Observe method of -// the Observer in the ObserverVec is called with the request size in +// are "code" and "method". The function panics otherwise. For the "method" +// label a predefined default label value set is used to filter given values. +// Values besides predefined values will count as `unknown` method. +// `WithExtraMethods` can be used to add more methods to the set. The Observe +// method of the Observer in the ObserverVec is called with the request size in // bytes. Partitioning happens by HTTP status code and/or HTTP method if the // respective instance label names are present in the ObserverVec. For // unpartitioned observations, use an ObserverVec with zero labels. Note that @@ -156,7 +183,12 @@ func InstrumentHandlerTimeToWriteHeader(obs prometheus.ObserverVec, next http.Ha // If the wrapped Handler panics, no values are reported. // // See the example for InstrumentHandlerDuration for example usage. -func InstrumentHandlerRequestSize(obs prometheus.ObserverVec, next http.Handler) http.HandlerFunc { +func InstrumentHandlerRequestSize(obs prometheus.ObserverVec, next http.Handler, opts ...Option) http.HandlerFunc { + mwOpts := &option{} + for _, o := range opts { + o(mwOpts) + } + code, method := checkLabels(obs) if code { @@ -164,14 +196,14 @@ func InstrumentHandlerRequestSize(obs prometheus.ObserverVec, next http.Handler) d := newDelegator(w, nil) next.ServeHTTP(d, r) size := computeApproximateRequestSize(r) - obs.With(labels(code, method, r.Method, d.Status())).Observe(float64(size)) + obs.With(labels(code, method, r.Method, d.Status(), mwOpts.extraMethods...)).Observe(float64(size)) }) } return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { next.ServeHTTP(w, r) size := computeApproximateRequestSize(r) - obs.With(labels(code, method, r.Method, 0)).Observe(float64(size)) + obs.With(labels(code, method, r.Method, 0, mwOpts.extraMethods...)).Observe(float64(size)) }) } @@ -179,8 +211,11 @@ func InstrumentHandlerRequestSize(obs prometheus.ObserverVec, next http.Handler) // http.Handler to observe the response size with the provided ObserverVec. The // ObserverVec must have valid metric and label names and must have zero, one, // or two non-const non-curried labels. For those, the only allowed label names -// are "code" and "method". The function panics otherwise. The Observe method of -// the Observer in the ObserverVec is called with the response size in +// are "code" and "method". The function panics otherwise. For the "method" +// label a predefined default label value set is used to filter given values. +// Values besides predefined values will count as `unknown` method. +// `WithExtraMethods` can be used to add more methods to the set. The Observe +// method of the Observer in the ObserverVec is called with the response size in // bytes. Partitioning happens by HTTP status code and/or HTTP method if the // respective instance label names are present in the ObserverVec. For // unpartitioned observations, use an ObserverVec with zero labels. Note that @@ -191,12 +226,18 @@ func InstrumentHandlerRequestSize(obs prometheus.ObserverVec, next http.Handler) // If the wrapped Handler panics, no values are reported. // // See the example for InstrumentHandlerDuration for example usage. -func InstrumentHandlerResponseSize(obs prometheus.ObserverVec, next http.Handler) http.Handler { +func InstrumentHandlerResponseSize(obs prometheus.ObserverVec, next http.Handler, opts ...Option) http.Handler { + mwOpts := &option{} + for _, o := range opts { + o(mwOpts) + } + code, method := checkLabels(obs) + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { d := newDelegator(w, nil) next.ServeHTTP(d, r) - obs.With(labels(code, method, r.Method, d.Status())).Observe(float64(d.Written())) + obs.With(labels(code, method, r.Method, d.Status(), mwOpts.extraMethods...)).Observe(float64(d.Written())) }) } @@ -290,7 +331,7 @@ func isLabelCurried(c prometheus.Collector, label string) bool { // unnecessary allocations on each request. var emptyLabels = prometheus.Labels{} -func labels(code, method bool, reqMethod string, status int) prometheus.Labels { +func labels(code, method bool, reqMethod string, status int, extraMethods ...string) prometheus.Labels { if !(code || method) { return emptyLabels } @@ -300,7 +341,7 @@ func labels(code, method bool, reqMethod string, status int) prometheus.Labels { labels["code"] = sanitizeCode(status) } if method { - labels["method"] = sanitizeMethod(reqMethod) + labels["method"] = sanitizeMethod(reqMethod, extraMethods...) } return labels @@ -330,7 +371,12 @@ func computeApproximateRequestSize(r *http.Request) int { return s } -func sanitizeMethod(m string) string { +// If the wrapped http.Handler has a known method, it will be sanitized and returned. +// Otherwise, "unknown" will be returned. The known method list can be extended +// as needed by using extraMethods parameter. +func sanitizeMethod(m string, extraMethods ...string) string { + // See https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods for + // the methods chosen as default. switch m { case "GET", "get": return "get" @@ -348,15 +394,25 @@ func sanitizeMethod(m string) string { return "options" case "NOTIFY", "notify": return "notify" + case "TRACE", "trace": + return "trace" + case "PATCH", "patch": + return "patch" default: - return strings.ToLower(m) + for _, method := range extraMethods { + if strings.EqualFold(m, method) { + return strings.ToLower(m) + } + } + return "unknown" } } // If the wrapped http.Handler has not set a status code, i.e. the value is -// currently 0, santizeCode will return 200, for consistency with behavior in +// currently 0, sanitizeCode will return 200, for consistency with behavior in // the stdlib. func sanitizeCode(s int) string { + // See for accepted codes https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml switch s { case 100: return "100" @@ -453,6 +509,9 @@ func sanitizeCode(s int) string { return "511" default: - return strconv.Itoa(s) + if s >= 100 && s <= 599 { + return strconv.Itoa(s) + } + return "unknown" } } diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/option.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/option.go new file mode 100644 index 000000000..35e41bd1e --- /dev/null +++ b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/option.go @@ -0,0 +1,31 @@ +// Copyright 2022 The Prometheus Authors +// 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 +// +// 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. +// See the License for the specific language governing permissions and +// limitations under the License. + +package promhttp + +// Option are used to configure a middleware or round tripper.. +type Option func(*option) + +type option struct { + extraMethods []string +} + +// WithExtraMethods adds additional HTTP methods to the list of allowed methods. +// See https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods for the default list. +// +// See the example for ExampleInstrumentHandlerWithExtraMethods for example usage. +func WithExtraMethods(methods ...string) Option { + return func(o *option) { + o.extraMethods = methods + } +} diff --git a/vendor/github.com/stretchr/testify/assert/assertion_compare.go b/vendor/github.com/stretchr/testify/assert/assertion_compare.go index 41649d267..3bb22a971 100644 --- a/vendor/github.com/stretchr/testify/assert/assertion_compare.go +++ b/vendor/github.com/stretchr/testify/assert/assertion_compare.go @@ -3,6 +3,7 @@ package assert import ( "fmt" "reflect" + "time" ) type CompareType int @@ -30,6 +31,8 @@ var ( float64Type = reflect.TypeOf(float64(1)) stringType = reflect.TypeOf("") + + timeType = reflect.TypeOf(time.Time{}) ) func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) { @@ -299,6 +302,27 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) { return compareLess, true } } + // Check for known struct types we can check for compare results. + case reflect.Struct: + { + // All structs enter here. We're not interested in most types. + if !canConvert(obj1Value, timeType) { + break + } + + // time.Time can compared! + timeObj1, ok := obj1.(time.Time) + if !ok { + timeObj1 = obj1Value.Convert(timeType).Interface().(time.Time) + } + + timeObj2, ok := obj2.(time.Time) + if !ok { + timeObj2 = obj2Value.Convert(timeType).Interface().(time.Time) + } + + return compare(timeObj1.UnixNano(), timeObj2.UnixNano(), reflect.Int64) + } } return compareEqual, false @@ -310,7 +334,10 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) { // assert.Greater(t, float64(2), float64(1)) // assert.Greater(t, "b", "a") func Greater(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { - return compareTwoValues(t, e1, e2, []CompareType{compareGreater}, "\"%v\" is not greater than \"%v\"", msgAndArgs) + if h, ok := t.(tHelper); ok { + h.Helper() + } + return compareTwoValues(t, e1, e2, []CompareType{compareGreater}, "\"%v\" is not greater than \"%v\"", msgAndArgs...) } // GreaterOrEqual asserts that the first element is greater than or equal to the second @@ -320,7 +347,10 @@ func Greater(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface // assert.GreaterOrEqual(t, "b", "a") // assert.GreaterOrEqual(t, "b", "b") func GreaterOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { - return compareTwoValues(t, e1, e2, []CompareType{compareGreater, compareEqual}, "\"%v\" is not greater than or equal to \"%v\"", msgAndArgs) + if h, ok := t.(tHelper); ok { + h.Helper() + } + return compareTwoValues(t, e1, e2, []CompareType{compareGreater, compareEqual}, "\"%v\" is not greater than or equal to \"%v\"", msgAndArgs...) } // Less asserts that the first element is less than the second @@ -329,7 +359,10 @@ func GreaterOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...in // assert.Less(t, float64(1), float64(2)) // assert.Less(t, "a", "b") func Less(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { - return compareTwoValues(t, e1, e2, []CompareType{compareLess}, "\"%v\" is not less than \"%v\"", msgAndArgs) + if h, ok := t.(tHelper); ok { + h.Helper() + } + return compareTwoValues(t, e1, e2, []CompareType{compareLess}, "\"%v\" is not less than \"%v\"", msgAndArgs...) } // LessOrEqual asserts that the first element is less than or equal to the second @@ -339,7 +372,10 @@ func Less(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) // assert.LessOrEqual(t, "a", "b") // assert.LessOrEqual(t, "b", "b") func LessOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { - return compareTwoValues(t, e1, e2, []CompareType{compareLess, compareEqual}, "\"%v\" is not less than or equal to \"%v\"", msgAndArgs) + if h, ok := t.(tHelper); ok { + h.Helper() + } + return compareTwoValues(t, e1, e2, []CompareType{compareLess, compareEqual}, "\"%v\" is not less than or equal to \"%v\"", msgAndArgs...) } // Positive asserts that the specified element is positive @@ -347,8 +383,11 @@ func LessOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...inter // assert.Positive(t, 1) // assert.Positive(t, 1.23) func Positive(t TestingT, e interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } zero := reflect.Zero(reflect.TypeOf(e)) - return compareTwoValues(t, e, zero.Interface(), []CompareType{compareGreater}, "\"%v\" is not positive", msgAndArgs) + return compareTwoValues(t, e, zero.Interface(), []CompareType{compareGreater}, "\"%v\" is not positive", msgAndArgs...) } // Negative asserts that the specified element is negative @@ -356,8 +395,11 @@ func Positive(t TestingT, e interface{}, msgAndArgs ...interface{}) bool { // assert.Negative(t, -1) // assert.Negative(t, -1.23) func Negative(t TestingT, e interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } zero := reflect.Zero(reflect.TypeOf(e)) - return compareTwoValues(t, e, zero.Interface(), []CompareType{compareLess}, "\"%v\" is not negative", msgAndArgs) + return compareTwoValues(t, e, zero.Interface(), []CompareType{compareLess}, "\"%v\" is not negative", msgAndArgs...) } func compareTwoValues(t TestingT, e1 interface{}, e2 interface{}, allowedComparesResults []CompareType, failMessage string, msgAndArgs ...interface{}) bool { diff --git a/vendor/github.com/stretchr/testify/assert/assertion_compare_can_convert.go b/vendor/github.com/stretchr/testify/assert/assertion_compare_can_convert.go new file mode 100644 index 000000000..df22c47fc --- /dev/null +++ b/vendor/github.com/stretchr/testify/assert/assertion_compare_can_convert.go @@ -0,0 +1,16 @@ +//go:build go1.17 +// +build go1.17 + +// TODO: once support for Go 1.16 is dropped, this file can be +// merged/removed with assertion_compare_go1.17_test.go and +// assertion_compare_legacy.go + +package assert + +import "reflect" + +// Wrapper around reflect.Value.CanConvert, for compatability +// reasons. +func canConvert(value reflect.Value, to reflect.Type) bool { + return value.CanConvert(to) +} diff --git a/vendor/github.com/stretchr/testify/assert/assertion_compare_legacy.go b/vendor/github.com/stretchr/testify/assert/assertion_compare_legacy.go new file mode 100644 index 000000000..1701af2a3 --- /dev/null +++ b/vendor/github.com/stretchr/testify/assert/assertion_compare_legacy.go @@ -0,0 +1,16 @@ +//go:build !go1.17 +// +build !go1.17 + +// TODO: once support for Go 1.16 is dropped, this file can be +// merged/removed with assertion_compare_go1.17_test.go and +// assertion_compare_can_convert.go + +package assert + +import "reflect" + +// Older versions of Go does not have the reflect.Value.CanConvert +// method. +func canConvert(value reflect.Value, to reflect.Type) bool { + return false +} diff --git a/vendor/github.com/stretchr/testify/assert/assertion_format.go b/vendor/github.com/stretchr/testify/assert/assertion_format.go index 4dfd1229a..27e2420ed 100644 --- a/vendor/github.com/stretchr/testify/assert/assertion_format.go +++ b/vendor/github.com/stretchr/testify/assert/assertion_format.go @@ -123,6 +123,18 @@ func ErrorAsf(t TestingT, err error, target interface{}, msg string, args ...int return ErrorAs(t, err, target, append([]interface{}{msg}, args...)...) } +// ErrorContainsf asserts that a function returned an error (i.e. not `nil`) +// and that the error contains the specified substring. +// +// actualObj, err := SomeFunction() +// assert.ErrorContainsf(t, err, expectedErrorSubString, "error message %s", "formatted") +func ErrorContainsf(t TestingT, theError error, contains string, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return ErrorContains(t, theError, contains, append([]interface{}{msg}, args...)...) +} + // ErrorIsf asserts that at least one of the errors in err's chain matches target. // This is a wrapper for errors.Is. func ErrorIsf(t TestingT, err error, target error, msg string, args ...interface{}) bool { diff --git a/vendor/github.com/stretchr/testify/assert/assertion_forward.go b/vendor/github.com/stretchr/testify/assert/assertion_forward.go index 25337a6f0..d9ea368d0 100644 --- a/vendor/github.com/stretchr/testify/assert/assertion_forward.go +++ b/vendor/github.com/stretchr/testify/assert/assertion_forward.go @@ -222,6 +222,30 @@ func (a *Assertions) ErrorAsf(err error, target interface{}, msg string, args .. return ErrorAsf(a.t, err, target, msg, args...) } +// ErrorContains asserts that a function returned an error (i.e. not `nil`) +// and that the error contains the specified substring. +// +// actualObj, err := SomeFunction() +// a.ErrorContains(err, expectedErrorSubString) +func (a *Assertions) ErrorContains(theError error, contains string, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return ErrorContains(a.t, theError, contains, msgAndArgs...) +} + +// ErrorContainsf asserts that a function returned an error (i.e. not `nil`) +// and that the error contains the specified substring. +// +// actualObj, err := SomeFunction() +// a.ErrorContainsf(err, expectedErrorSubString, "error message %s", "formatted") +func (a *Assertions) ErrorContainsf(theError error, contains string, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return ErrorContainsf(a.t, theError, contains, msg, args...) +} + // ErrorIs asserts that at least one of the errors in err's chain matches target. // This is a wrapper for errors.Is. func (a *Assertions) ErrorIs(err error, target error, msgAndArgs ...interface{}) bool { diff --git a/vendor/github.com/stretchr/testify/assert/assertion_order.go b/vendor/github.com/stretchr/testify/assert/assertion_order.go index 1c3b47182..759448783 100644 --- a/vendor/github.com/stretchr/testify/assert/assertion_order.go +++ b/vendor/github.com/stretchr/testify/assert/assertion_order.go @@ -50,7 +50,7 @@ func isOrdered(t TestingT, object interface{}, allowedComparesResults []CompareT // assert.IsIncreasing(t, []float{1, 2}) // assert.IsIncreasing(t, []string{"a", "b"}) func IsIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { - return isOrdered(t, object, []CompareType{compareLess}, "\"%v\" is not less than \"%v\"", msgAndArgs) + return isOrdered(t, object, []CompareType{compareLess}, "\"%v\" is not less than \"%v\"", msgAndArgs...) } // IsNonIncreasing asserts that the collection is not increasing @@ -59,7 +59,7 @@ func IsIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) boo // assert.IsNonIncreasing(t, []float{2, 1}) // assert.IsNonIncreasing(t, []string{"b", "a"}) func IsNonIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { - return isOrdered(t, object, []CompareType{compareEqual, compareGreater}, "\"%v\" is not greater than or equal to \"%v\"", msgAndArgs) + return isOrdered(t, object, []CompareType{compareEqual, compareGreater}, "\"%v\" is not greater than or equal to \"%v\"", msgAndArgs...) } // IsDecreasing asserts that the collection is decreasing @@ -68,7 +68,7 @@ func IsNonIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) // assert.IsDecreasing(t, []float{2, 1}) // assert.IsDecreasing(t, []string{"b", "a"}) func IsDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { - return isOrdered(t, object, []CompareType{compareGreater}, "\"%v\" is not greater than \"%v\"", msgAndArgs) + return isOrdered(t, object, []CompareType{compareGreater}, "\"%v\" is not greater than \"%v\"", msgAndArgs...) } // IsNonDecreasing asserts that the collection is not decreasing @@ -77,5 +77,5 @@ func IsDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) boo // assert.IsNonDecreasing(t, []float{1, 2}) // assert.IsNonDecreasing(t, []string{"a", "b"}) func IsNonDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { - return isOrdered(t, object, []CompareType{compareLess, compareEqual}, "\"%v\" is not less than or equal to \"%v\"", msgAndArgs) + return isOrdered(t, object, []CompareType{compareLess, compareEqual}, "\"%v\" is not less than or equal to \"%v\"", msgAndArgs...) } diff --git a/vendor/github.com/stretchr/testify/assert/assertions.go b/vendor/github.com/stretchr/testify/assert/assertions.go index bcac4401f..0357b2231 100644 --- a/vendor/github.com/stretchr/testify/assert/assertions.go +++ b/vendor/github.com/stretchr/testify/assert/assertions.go @@ -718,10 +718,14 @@ func NotEqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...inte // return (false, false) if impossible. // return (true, false) if element was not found. // return (true, true) if element was found. -func includeElement(list interface{}, element interface{}) (ok, found bool) { +func containsElement(list interface{}, element interface{}) (ok, found bool) { listValue := reflect.ValueOf(list) - listKind := reflect.TypeOf(list).Kind() + listType := reflect.TypeOf(list) + if listType == nil { + return false, false + } + listKind := listType.Kind() defer func() { if e := recover(); e != nil { ok = false @@ -764,7 +768,7 @@ func Contains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bo h.Helper() } - ok, found := includeElement(s, contains) + ok, found := containsElement(s, contains) if !ok { return Fail(t, fmt.Sprintf("%#v could not be applied builtin len()", s), msgAndArgs...) } @@ -787,7 +791,7 @@ func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) h.Helper() } - ok, found := includeElement(s, contains) + ok, found := containsElement(s, contains) if !ok { return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", s), msgAndArgs...) } @@ -831,7 +835,7 @@ func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok for i := 0; i < subsetValue.Len(); i++ { element := subsetValue.Index(i).Interface() - ok, found := includeElement(list, element) + ok, found := containsElement(list, element) if !ok { return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", list), msgAndArgs...) } @@ -852,7 +856,7 @@ func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) h.Helper() } if subset == nil { - return Fail(t, fmt.Sprintf("nil is the empty set which is a subset of every set"), msgAndArgs...) + return Fail(t, "nil is the empty set which is a subset of every set", msgAndArgs...) } subsetValue := reflect.ValueOf(subset) @@ -875,7 +879,7 @@ func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) for i := 0; i < subsetValue.Len(); i++ { element := subsetValue.Index(i).Interface() - ok, found := includeElement(list, element) + ok, found := containsElement(list, element) if !ok { return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", list), msgAndArgs...) } @@ -1000,27 +1004,21 @@ func Condition(t TestingT, comp Comparison, msgAndArgs ...interface{}) bool { type PanicTestFunc func() // didPanic returns true if the function passed to it panics. Otherwise, it returns false. -func didPanic(f PanicTestFunc) (bool, interface{}, string) { - - didPanic := false - var message interface{} - var stack string - func() { - - defer func() { - if message = recover(); message != nil { - didPanic = true - stack = string(debug.Stack()) - } - }() - - // call the target function - f() +func didPanic(f PanicTestFunc) (didPanic bool, message interface{}, stack string) { + didPanic = true + defer func() { + message = recover() + if didPanic { + stack = string(debug.Stack()) + } }() - return didPanic, message, stack + // call the target function + f() + didPanic = false + return } // Panics asserts that the code inside the specified PanicTestFunc panics. @@ -1161,11 +1159,15 @@ func InDelta(t TestingT, expected, actual interface{}, delta float64, msgAndArgs bf, bok := toFloat(actual) if !aok || !bok { - return Fail(t, fmt.Sprintf("Parameters must be numerical"), msgAndArgs...) + return Fail(t, "Parameters must be numerical", msgAndArgs...) + } + + if math.IsNaN(af) && math.IsNaN(bf) { + return true } if math.IsNaN(af) { - return Fail(t, fmt.Sprintf("Expected must not be NaN"), msgAndArgs...) + return Fail(t, "Expected must not be NaN", msgAndArgs...) } if math.IsNaN(bf) { @@ -1188,7 +1190,7 @@ func InDeltaSlice(t TestingT, expected, actual interface{}, delta float64, msgAn if expected == nil || actual == nil || reflect.TypeOf(actual).Kind() != reflect.Slice || reflect.TypeOf(expected).Kind() != reflect.Slice { - return Fail(t, fmt.Sprintf("Parameters must be slice"), msgAndArgs...) + return Fail(t, "Parameters must be slice", msgAndArgs...) } actualSlice := reflect.ValueOf(actual) @@ -1250,8 +1252,12 @@ func InDeltaMapValues(t TestingT, expected, actual interface{}, delta float64, m func calcRelativeError(expected, actual interface{}) (float64, error) { af, aok := toFloat(expected) - if !aok { - return 0, fmt.Errorf("expected value %q cannot be converted to float", expected) + bf, bok := toFloat(actual) + if !aok || !bok { + return 0, fmt.Errorf("Parameters must be numerical") + } + if math.IsNaN(af) && math.IsNaN(bf) { + return 0, nil } if math.IsNaN(af) { return 0, errors.New("expected value must not be NaN") @@ -1259,10 +1265,6 @@ func calcRelativeError(expected, actual interface{}) (float64, error) { if af == 0 { return 0, fmt.Errorf("expected value must have a value other than zero to calculate the relative error") } - bf, bok := toFloat(actual) - if !bok { - return 0, fmt.Errorf("actual value %q cannot be converted to float", actual) - } if math.IsNaN(bf) { return 0, errors.New("actual value must not be NaN") } @@ -1298,7 +1300,7 @@ func InEpsilonSlice(t TestingT, expected, actual interface{}, epsilon float64, m if expected == nil || actual == nil || reflect.TypeOf(actual).Kind() != reflect.Slice || reflect.TypeOf(expected).Kind() != reflect.Slice { - return Fail(t, fmt.Sprintf("Parameters must be slice"), msgAndArgs...) + return Fail(t, "Parameters must be slice", msgAndArgs...) } actualSlice := reflect.ValueOf(actual) @@ -1375,6 +1377,27 @@ func EqualError(t TestingT, theError error, errString string, msgAndArgs ...inte return true } +// ErrorContains asserts that a function returned an error (i.e. not `nil`) +// and that the error contains the specified substring. +// +// actualObj, err := SomeFunction() +// assert.ErrorContains(t, err, expectedErrorSubString) +func ErrorContains(t TestingT, theError error, contains string, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if !Error(t, theError, msgAndArgs...) { + return false + } + + actual := theError.Error() + if !strings.Contains(actual, contains) { + return Fail(t, fmt.Sprintf("Error %#v does not contain %#v", actual, contains), msgAndArgs...) + } + + return true +} + // matchRegexp return true if a specified regexp matches a string. func matchRegexp(rx interface{}, str interface{}) bool { @@ -1588,12 +1611,17 @@ func diff(expected interface{}, actual interface{}) string { } var e, a string - if et != reflect.TypeOf("") { - e = spewConfig.Sdump(expected) - a = spewConfig.Sdump(actual) - } else { + + switch et { + case reflect.TypeOf(""): e = reflect.ValueOf(expected).String() a = reflect.ValueOf(actual).String() + case reflect.TypeOf(time.Time{}): + e = spewConfigStringerEnabled.Sdump(expected) + a = spewConfigStringerEnabled.Sdump(actual) + default: + e = spewConfig.Sdump(expected) + a = spewConfig.Sdump(actual) } diff, _ := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{ @@ -1625,6 +1653,14 @@ var spewConfig = spew.ConfigState{ MaxDepth: 10, } +var spewConfigStringerEnabled = spew.ConfigState{ + Indent: " ", + DisablePointerAddresses: true, + DisableCapacities: true, + SortKeys: true, + MaxDepth: 10, +} + type tHelper interface { Helper() } diff --git a/vendor/github.com/stretchr/testify/require/require.go b/vendor/github.com/stretchr/testify/require/require.go index 51820df2e..59c48277a 100644 --- a/vendor/github.com/stretchr/testify/require/require.go +++ b/vendor/github.com/stretchr/testify/require/require.go @@ -280,6 +280,36 @@ func ErrorAsf(t TestingT, err error, target interface{}, msg string, args ...int t.FailNow() } +// ErrorContains asserts that a function returned an error (i.e. not `nil`) +// and that the error contains the specified substring. +// +// actualObj, err := SomeFunction() +// assert.ErrorContains(t, err, expectedErrorSubString) +func ErrorContains(t TestingT, theError error, contains string, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.ErrorContains(t, theError, contains, msgAndArgs...) { + return + } + t.FailNow() +} + +// ErrorContainsf asserts that a function returned an error (i.e. not `nil`) +// and that the error contains the specified substring. +// +// actualObj, err := SomeFunction() +// assert.ErrorContainsf(t, err, expectedErrorSubString, "error message %s", "formatted") +func ErrorContainsf(t TestingT, theError error, contains string, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.ErrorContainsf(t, theError, contains, msg, args...) { + return + } + t.FailNow() +} + // ErrorIs asserts that at least one of the errors in err's chain matches target. // This is a wrapper for errors.Is. func ErrorIs(t TestingT, err error, target error, msgAndArgs ...interface{}) { diff --git a/vendor/github.com/stretchr/testify/require/require_forward.go b/vendor/github.com/stretchr/testify/require/require_forward.go index ed54a9d83..5bb07c89c 100644 --- a/vendor/github.com/stretchr/testify/require/require_forward.go +++ b/vendor/github.com/stretchr/testify/require/require_forward.go @@ -223,6 +223,30 @@ func (a *Assertions) ErrorAsf(err error, target interface{}, msg string, args .. ErrorAsf(a.t, err, target, msg, args...) } +// ErrorContains asserts that a function returned an error (i.e. not `nil`) +// and that the error contains the specified substring. +// +// actualObj, err := SomeFunction() +// a.ErrorContains(err, expectedErrorSubString) +func (a *Assertions) ErrorContains(theError error, contains string, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + ErrorContains(a.t, theError, contains, msgAndArgs...) +} + +// ErrorContainsf asserts that a function returned an error (i.e. not `nil`) +// and that the error contains the specified substring. +// +// actualObj, err := SomeFunction() +// a.ErrorContainsf(err, expectedErrorSubString, "error message %s", "formatted") +func (a *Assertions) ErrorContainsf(theError error, contains string, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + ErrorContainsf(a.t, theError, contains, msg, args...) +} + // ErrorIs asserts that at least one of the errors in err's chain matches target. // This is a wrapper for errors.Is. func (a *Assertions) ErrorIs(err error, target error, msgAndArgs ...interface{}) { diff --git a/vendor/modules.txt b/vendor/modules.txt index a224d3da5..62fa45067 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -69,7 +69,7 @@ github.com/containerd/containerd/log github.com/containerd/containerd/pkg/userns github.com/containerd/containerd/platforms github.com/containerd/containerd/sys -# github.com/containerd/stargz-snapshotter/estargz v0.11.2 +# github.com/containerd/stargz-snapshotter/estargz v0.11.3 github.com/containerd/stargz-snapshotter/estargz github.com/containerd/stargz-snapshotter/estargz/errorutil # github.com/containernetworking/cni v1.0.1 @@ -109,7 +109,7 @@ github.com/containers/buildah/pkg/rusage github.com/containers/buildah/pkg/sshagent github.com/containers/buildah/pkg/util github.com/containers/buildah/util -# github.com/containers/common v0.47.5-0.20220228211119-9880eb424fde +# github.com/containers/common v0.47.5-0.20220318125043-0ededd18a1f9 ## explicit github.com/containers/common/libimage github.com/containers/common/libimage/manifests @@ -206,7 +206,7 @@ github.com/containers/image/v5/types github.com/containers/image/v5/version # github.com/containers/libtrust v0.0.0-20200511145503-9c3a6c22cd9a github.com/containers/libtrust -# github.com/containers/ocicrypt v1.1.2 +# github.com/containers/ocicrypt v1.1.3 ## explicit github.com/containers/ocicrypt github.com/containers/ocicrypt/blockcipher @@ -233,7 +233,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.38.3-0.20220308085612-93ce26691863 +# github.com/containers/storage v1.38.3-0.20220321121613-8e565392dd91 ## explicit github.com/containers/storage github.com/containers/storage/drivers @@ -455,7 +455,7 @@ github.com/jinzhu/copier # github.com/json-iterator/go v1.1.12 ## explicit github.com/json-iterator/go -# github.com/klauspost/compress v1.15.0 +# github.com/klauspost/compress v1.15.1 github.com/klauspost/compress github.com/klauspost/compress/flate github.com/klauspost/compress/fse @@ -478,7 +478,7 @@ github.com/mattn/go-runewidth github.com/mattn/go-shellwords # github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 github.com/matttproud/golang_protobuf_extensions/pbutil -# github.com/miekg/pkcs11 v1.0.3 +# github.com/miekg/pkcs11 v1.1.1 github.com/miekg/pkcs11 # github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible github.com/mistifyio/go-zfs @@ -603,7 +603,8 @@ github.com/pkg/errors github.com/pmezard/go-difflib/difflib # github.com/proglottis/gpgme v0.1.1 github.com/proglottis/gpgme -# github.com/prometheus/client_golang v1.11.0 +# github.com/prometheus/client_golang v1.11.1 +## explicit github.com/prometheus/client_golang/prometheus github.com/prometheus/client_golang/prometheus/internal github.com/prometheus/client_golang/prometheus/promhttp @@ -647,7 +648,7 @@ github.com/spf13/cobra github.com/spf13/pflag # github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980 github.com/stefanberger/go-pkcs11uri -# github.com/stretchr/testify v1.7.0 +# github.com/stretchr/testify v1.7.1 ## explicit github.com/stretchr/testify/assert github.com/stretchr/testify/require |