mirror of
https://github.com/containers/podman.git
synced 2025-10-16 18:53:19 +08:00
Merge pull request #26765 from 2004joshua/log_location
feat: added log_path support for configuration files
This commit is contained in:
6
go.mod
6
go.mod
@ -12,7 +12,7 @@ require (
|
||||
github.com/checkpoint-restore/go-criu/v7 v7.2.0
|
||||
github.com/containernetworking/plugins v1.7.1
|
||||
github.com/containers/buildah v1.41.0
|
||||
github.com/containers/common v0.64.0
|
||||
github.com/containers/common v0.64.1-0.20250806164630-57def9601f3b
|
||||
github.com/containers/conmon v2.0.20+incompatible
|
||||
github.com/containers/gvisor-tap-vsock v0.8.6
|
||||
github.com/containers/image/v5 v5.36.1
|
||||
@ -63,7 +63,7 @@ require (
|
||||
github.com/shirou/gopsutil/v4 v4.25.7
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
github.com/spf13/cobra v1.9.1
|
||||
github.com/spf13/pflag v1.0.6
|
||||
github.com/spf13/pflag v1.0.7
|
||||
github.com/stretchr/testify v1.10.0
|
||||
github.com/vbauerster/mpb/v8 v8.10.2
|
||||
github.com/vishvananda/netlink v1.3.1
|
||||
@ -154,7 +154,7 @@ require (
|
||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
|
||||
github.com/proglottis/gpgme v0.1.4 // indirect
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
github.com/seccomp/libseccomp-golang v0.11.0 // indirect
|
||||
github.com/seccomp/libseccomp-golang v0.11.1 // indirect
|
||||
github.com/secure-systems-lab/go-securesystemslib v0.9.0 // indirect
|
||||
github.com/segmentio/ksuid v1.0.4 // indirect
|
||||
github.com/sigstore/fulcio v1.6.6 // indirect
|
||||
|
11
go.sum
11
go.sum
@ -64,8 +64,8 @@ github.com/containernetworking/plugins v1.7.1 h1:CNAR0jviDj6FS5Vg85NTgKWLDzZPfi/
|
||||
github.com/containernetworking/plugins v1.7.1/go.mod h1:xuMdjuio+a1oVQsHKjr/mgzuZ24leAsqUYRnzGoXHy0=
|
||||
github.com/containers/buildah v1.41.0 h1:GU350UeX6BkZrgCE3SB/d1Hu4xBaHUX07ayiJTvJD54=
|
||||
github.com/containers/buildah v1.41.0/go.mod h1:1Ds26B4E4Z3NeLdi3xjjk8S72KVv2/xiFYYpwfFDgXI=
|
||||
github.com/containers/common v0.64.0 h1:Jdjq1e5tqrLov9tcAVc/AfvQCgX4krhcfDBgOXwrSfw=
|
||||
github.com/containers/common v0.64.0/go.mod h1:bq2UIiFP8vUJdgM+WN8E8jkD7wF69SpDRGzU7epJljg=
|
||||
github.com/containers/common v0.64.1-0.20250806164630-57def9601f3b h1:k6Ir7PSGAqDzJyUHREJQYbJG+TN43anXoGcNX2gmLkA=
|
||||
github.com/containers/common v0.64.1-0.20250806164630-57def9601f3b/go.mod h1:XVM+3mWPo2J4KSrGkRFKGDTgd3FwknWaDq+uQ4Dhb6E=
|
||||
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/gvisor-tap-vsock v0.8.6 h1:9SeAXK+K2o36CtrgYk6zRXbU3zrayjvkrI8b7/O6u5A=
|
||||
@ -377,8 +377,8 @@ github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 h1:KRzFb2m7YtdldCEkzs6KqmJw4nqEV
|
||||
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU=
|
||||
github.com/sebdah/goldie/v2 v2.5.5 h1:rx1mwF95RxZ3/83sdS4Yp7t2C5TCokvWP4TBRbAyEWY=
|
||||
github.com/sebdah/goldie/v2 v2.5.5/go.mod h1:oZ9fp0+se1eapSRjfYbsV/0Hqhbuu3bJVvKI/NNtssI=
|
||||
github.com/seccomp/libseccomp-golang v0.11.0 h1:SDkcBRqGLP+sezmMACkxO1EfgbghxIxnRKfd6mHUEis=
|
||||
github.com/seccomp/libseccomp-golang v0.11.0/go.mod h1:5m1Lk8E9OwgZTTVz4bBOer7JuazaBa+xTkM895tDiWc=
|
||||
github.com/seccomp/libseccomp-golang v0.11.1 h1:wuk4ZjSx6kyQII4rj6G6fvVzRHQaSiPvccJazDagu4g=
|
||||
github.com/seccomp/libseccomp-golang v0.11.1/go.mod h1:5m1Lk8E9OwgZTTVz4bBOer7JuazaBa+xTkM895tDiWc=
|
||||
github.com/secure-systems-lab/go-securesystemslib v0.9.0 h1:rf1HIbL64nUpEIZnjLZ3mcNEL9NBPB0iuVjyxvq3LZc=
|
||||
github.com/secure-systems-lab/go-securesystemslib v0.9.0/go.mod h1:DVHKMcZ+V4/woA/peqr+L0joiRXbPpQ042GgJckkFgw=
|
||||
github.com/segmentio/ksuid v1.0.4 h1:sBo2BdShXjmcugAMwjugoGUdUV0pcxY5mW4xKRn3v4c=
|
||||
@ -403,8 +403,9 @@ github.com/smallstep/pkcs7 v0.1.1 h1:x+rPdt2W088V9Vkjho4KtoggyktZJlMduZAtRHm68LU
|
||||
github.com/smallstep/pkcs7 v0.1.1/go.mod h1:dL6j5AIz9GHjVEBTXtW+QliALcgM19RtXaTeyxI+AfA=
|
||||
github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
|
||||
github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
|
||||
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
|
||||
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/pflag v1.0.7 h1:vN6T9TfwStFPFM5XzjsvmzZkLuaLX+HS+0SeFLRgU6M=
|
||||
github.com/spf13/pflag v1.0.7/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/stefanberger/go-pkcs11uri v0.0.0-20230803200340-78284954bff6 h1:pnnLyeX7o/5aX8qUQ69P/mLojDqwda8hFOCBTmP/6hw=
|
||||
github.com/stefanberger/go-pkcs11uri v0.0.0-20230803200340-78284954bff6/go.mod h1:39R/xuhNgVhi+K0/zst4TLrJrVmbm6LVgl4A0+ZFS5M=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
|
@ -6,6 +6,8 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
@ -1041,8 +1043,16 @@ func WithLogPath(path string) CtrCreateOption {
|
||||
if path == "" {
|
||||
return fmt.Errorf("log path must be set: %w", define.ErrInvalidArg)
|
||||
}
|
||||
if isDirectory(path) {
|
||||
containerDir := filepath.Join(path, ctr.ID())
|
||||
if err := os.Mkdir(containerDir, 0755); err != nil {
|
||||
return fmt.Errorf("failed to create container log directory %s: %w", containerDir, err)
|
||||
}
|
||||
|
||||
ctr.config.LogPath = path
|
||||
ctr.config.LogPath = filepath.Join(containerDir, "ctr.log")
|
||||
} else {
|
||||
ctr.config.LogPath = path
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -285,3 +285,11 @@ func evalSymlinksIfExists(toCheck string) (string, error) {
|
||||
}
|
||||
return checkedVal, nil
|
||||
}
|
||||
|
||||
func isDirectory(path string) bool {
|
||||
info, err := os.Stat(path)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return info.IsDir()
|
||||
}
|
||||
|
@ -228,6 +228,10 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener
|
||||
|
||||
s.ImageVolumes = opts.ImageVolumes
|
||||
|
||||
if rtc.Containers.LogPath != "" {
|
||||
s.LogConfiguration.Path = rtc.Containers.LogPath
|
||||
}
|
||||
|
||||
s.LogConfiguration.Options = make(map[string]string)
|
||||
for _, o := range opts.LogOptions {
|
||||
opt, val, hasVal := strings.Cut(o, "=")
|
||||
|
@ -844,6 +844,10 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *entities.ContainerCreateOptions
|
||||
return err
|
||||
}
|
||||
|
||||
if rtc.Containers.LogPath != "" {
|
||||
s.LogConfiguration.Path = rtc.Containers.LogPath
|
||||
}
|
||||
|
||||
logOpts := make(map[string]string)
|
||||
for _, o := range c.LogOptions {
|
||||
key, val, hasVal := strings.Cut(o, "=")
|
||||
@ -865,6 +869,7 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *entities.ContainerCreateOptions
|
||||
logOpts[key] = val
|
||||
}
|
||||
}
|
||||
|
||||
if len(s.LogConfiguration.Options) == 0 || len(c.LogOptions) != 0 {
|
||||
s.LogConfiguration.Options = logOpts
|
||||
}
|
||||
|
@ -6310,4 +6310,85 @@ spec:
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session).Should(ExitWithError(125, "invalid signal: noSuchSignal"))
|
||||
})
|
||||
|
||||
It("test with custom log path from containers.conf", func() {
|
||||
customLogPath := filepath.Join(podmanTest.TempDir, "custom-logs")
|
||||
expectedMessage := "Pod started, checking logs from test"
|
||||
|
||||
conffile := filepath.Join(podmanTest.TempDir, "containers.conf")
|
||||
configContent := fmt.Sprintf(`[containers]
|
||||
log_driver = "k8s-file"
|
||||
log_path = "%s"
|
||||
`, customLogPath)
|
||||
|
||||
err := os.WriteFile(conffile, []byte(configContent), 0644)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
err = os.MkdirAll(customLogPath, 0755)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
os.Setenv("CONTAINERS_CONF_OVERRIDE", conffile)
|
||||
defer os.Unsetenv("CONTAINERS_CONF_OVERRIDE")
|
||||
|
||||
if IsRemote() {
|
||||
podmanTest.RestartRemoteService()
|
||||
}
|
||||
|
||||
kubeYaml := filepath.Join(podmanTest.TempDir, "test-pod.yaml")
|
||||
podYamlContent := fmt.Sprintf(`apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: log-test-pod
|
||||
spec:
|
||||
restartPolicy: Never
|
||||
containers:
|
||||
- name: logger-container
|
||||
image: %s
|
||||
command: ["/bin/sh", "-c", "echo '%s'; sleep 2"]
|
||||
`, CITEST_IMAGE, expectedMessage)
|
||||
|
||||
err = os.WriteFile(kubeYaml, []byte(podYamlContent), 0644)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
podmanTest.PodmanExitCleanly("kube", "play", kubeYaml)
|
||||
|
||||
podmanTest.PodmanExitCleanly("wait", "log-test-pod-logger-container")
|
||||
|
||||
customLogDirs, err := os.ReadDir(customLogPath)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(customLogDirs).To(HaveLen(2), "Should have exactly two container log directories (infra + app container)")
|
||||
|
||||
var appContainerLogDir string
|
||||
var logContent string
|
||||
found := false
|
||||
|
||||
for _, dir := range customLogDirs {
|
||||
if !dir.IsDir() {
|
||||
continue
|
||||
}
|
||||
containerLogDir := dir.Name()
|
||||
logFilePath := filepath.Join(customLogPath, containerLogDir, "ctr.log")
|
||||
|
||||
if _, err := os.Stat(logFilePath); err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
content, err := os.ReadFile(logFilePath)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if strings.Contains(string(content), expectedMessage) {
|
||||
appContainerLogDir = containerLogDir
|
||||
logContent = string(content)
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
Expect(found).To(BeTrue(), "Should find log file with expected message")
|
||||
|
||||
Expect(appContainerLogDir).ToNot(BeEmpty(), "Should have found application container log directory")
|
||||
Expect(logContent).To(ContainSubstring(expectedMessage), "Log file should contain the expected message")
|
||||
})
|
||||
})
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
@ -2456,4 +2457,84 @@ WORKDIR /madethis`, BB)
|
||||
Expect(inspectData[0].Config.Annotations).To(Not(HaveKey(annoName)))
|
||||
Expect(inspectData[0].Config.Annotations).To(Not(HaveKey("testlabel")))
|
||||
})
|
||||
|
||||
It("podman run log-opt overrides containers.conf path", func() {
|
||||
expectedMessage := "CLI override test message"
|
||||
confLogPath := filepath.Join(podmanTest.TempDir, "conf-logs")
|
||||
|
||||
conffile := filepath.Join(podmanTest.TempDir, "containers.conf")
|
||||
configContent := fmt.Sprintf(`[containers]
|
||||
log_driver = "k8s-file"
|
||||
log_path = "%s"
|
||||
`, confLogPath)
|
||||
|
||||
err := os.WriteFile(conffile, []byte(configContent), 0644)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
err = os.MkdirAll(confLogPath, 0755)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
os.Setenv("CONTAINERS_CONF_OVERRIDE", conffile)
|
||||
defer os.Unsetenv("CONTAINERS_CONF_OVERRIDE")
|
||||
|
||||
if IsRemote() {
|
||||
podmanTest.RestartRemoteService()
|
||||
}
|
||||
|
||||
cliLogPath := filepath.Join(podmanTest.TempDir, "cli-override.log")
|
||||
podmanTest.PodmanExitCleanly("run", "--rm", "--log-driver", "k8s-file", "--log-opt", fmt.Sprintf("path=%s", cliLogPath), ALPINE, "echo", expectedMessage)
|
||||
|
||||
confLogDirs, err := os.ReadDir(confLogPath)
|
||||
Expect(err).ToNot(HaveOccurred(), "Should be able to read config log directory that we created")
|
||||
Expect(confLogDirs).To(BeEmpty(), "Config file log path should not be used when CLI overrides")
|
||||
|
||||
content, err := os.ReadFile(cliLogPath)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(string(content)).To(ContainSubstring(expectedMessage))
|
||||
Expect(string(content)).To(MatchRegexp(`\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+.*stdout F ` + regexp.QuoteMeta(expectedMessage)))
|
||||
|
||||
_ = os.Remove(cliLogPath)
|
||||
})
|
||||
|
||||
It("podman run uses containers.conf log_path", func() {
|
||||
expectedMessage := "Config file path test message"
|
||||
confLogPath := filepath.Join(podmanTest.TempDir, "conf-logs")
|
||||
|
||||
conffile := filepath.Join(podmanTest.TempDir, "containers.conf")
|
||||
configContent := fmt.Sprintf(`[containers]
|
||||
log_driver = "k8s-file"
|
||||
log_path = "%s"
|
||||
`, confLogPath)
|
||||
|
||||
err := os.WriteFile(conffile, []byte(configContent), 0644)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
err = os.MkdirAll(confLogPath, 0755)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
os.Setenv("CONTAINERS_CONF_OVERRIDE", conffile)
|
||||
defer os.Unsetenv("CONTAINERS_CONF_OVERRIDE")
|
||||
|
||||
if IsRemote() {
|
||||
podmanTest.RestartRemoteService()
|
||||
}
|
||||
|
||||
containerName := "test-conf-log-container"
|
||||
|
||||
podmanTest.PodmanExitCleanly("run", "--name", containerName, ALPINE, "echo", expectedMessage)
|
||||
session := podmanTest.PodmanExitCleanly("inspect", "--format", "{{.Id}}", containerName)
|
||||
|
||||
containerID := strings.TrimSpace(session.OutputToString())
|
||||
logFilePath := filepath.Join(confLogPath, containerID, "ctr.log")
|
||||
|
||||
inspectSession := podmanTest.PodmanExitCleanly("inspect", "--format", "{{.HostConfig.LogConfig.Path}}", containerName)
|
||||
inspectedPath := strings.TrimSpace(inspectSession.OutputToString())
|
||||
Expect(inspectedPath).To(Equal(logFilePath), "Log path in inspect data should match the path from containers.conf")
|
||||
|
||||
content, err := os.ReadFile(logFilePath)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
Expect(string(content)).To(ContainSubstring(expectedMessage), "Log should contain expected message")
|
||||
Expect(string(content)).To(MatchRegexp(`\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+.*stdout F `+regexp.QuoteMeta(expectedMessage)), "Log should follow k8s-file format")
|
||||
})
|
||||
})
|
||||
|
10
vendor/github.com/containers/common/pkg/config/config.go
generated
vendored
10
vendor/github.com/containers/common/pkg/config/config.go
generated
vendored
@ -172,6 +172,9 @@ type ContainersConfig struct {
|
||||
// LogDriver for the container. For example: k8s-file and journald
|
||||
LogDriver string `toml:"log_driver,omitempty"`
|
||||
|
||||
// LogPath is the path to the container log file.
|
||||
LogPath string `toml:"log_path,omitempty"`
|
||||
|
||||
// LogSizeMax is the maximum number of bytes after which the log file
|
||||
// will be truncated. It can be expressed as a human-friendly string
|
||||
// that is parsed to bytes.
|
||||
@ -847,8 +850,7 @@ func (c *EngineConfig) Validate() error {
|
||||
}
|
||||
// Check if the pullPolicy from containers.conf is valid
|
||||
// if it is invalid returns the error
|
||||
pullPolicy := strings.ToLower(c.PullPolicy)
|
||||
if _, err := ValidatePullPolicy(pullPolicy); err != nil {
|
||||
if _, err := ParsePullPolicy(c.PullPolicy); err != nil {
|
||||
return fmt.Errorf("invalid pull type from containers.conf %q: %w", c.PullPolicy, err)
|
||||
}
|
||||
|
||||
@ -883,6 +885,10 @@ func (c *ContainersConfig) Validate() error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := c.validateLogPath(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if c.LogSizeMax >= 0 && c.LogSizeMax < OCIBufSize {
|
||||
return fmt.Errorf("log size max should be negative or >= %d", OCIBufSize)
|
||||
}
|
||||
|
14
vendor/github.com/containers/common/pkg/config/config_local.go
generated
vendored
14
vendor/github.com/containers/common/pkg/config/config_local.go
generated
vendored
@ -105,6 +105,20 @@ func (c *ContainersConfig) validateUmask() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *ContainersConfig) validateLogPath() error {
|
||||
if c.LogPath == "" {
|
||||
return nil
|
||||
}
|
||||
if !filepath.IsAbs(c.LogPath) {
|
||||
return fmt.Errorf("log_path must be an absolute path - instead got %q", c.LogPath)
|
||||
}
|
||||
if strings.ContainsAny(c.LogPath, "\x00") {
|
||||
return fmt.Errorf("log_path contains null bytes - got %q", c.LogPath)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func isRemote() bool {
|
||||
return false
|
||||
}
|
||||
|
4
vendor/github.com/containers/common/pkg/config/config_remote.go
generated
vendored
4
vendor/github.com/containers/common/pkg/config/config_remote.go
generated
vendored
@ -35,3 +35,7 @@ func (c *ContainersConfig) validateTZ() error {
|
||||
func (c *ContainersConfig) validateUmask() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *ContainersConfig) validateLogPath() error {
|
||||
return nil
|
||||
}
|
||||
|
8
vendor/github.com/containers/common/pkg/config/containers.conf
generated
vendored
8
vendor/github.com/containers/common/pkg/config/containers.conf
generated
vendored
@ -216,6 +216,14 @@ default_sysctls = [
|
||||
#
|
||||
#log_driver = "k8s-file"
|
||||
|
||||
# Default path for container logs to be stored in. When empty, logs will be stored
|
||||
# in the container's default storage and removed when the container is removed.
|
||||
# A subdirectory named with the container ID will be created under the specified
|
||||
# path, and the log file will have the default name `ctr.log` within that directory.
|
||||
# This option can be overridden by the `--log-opt` flag.
|
||||
#
|
||||
#log_path = ""
|
||||
|
||||
# Maximum size allowed for the container log file. Negative numbers indicate
|
||||
# that no size limit is imposed. If positive, it must be >= 8192 to match or
|
||||
# exceed conmon's read buffer. The file is truncated and re-opened so the
|
||||
|
8
vendor/github.com/containers/common/pkg/config/containers.conf-freebsd
generated
vendored
8
vendor/github.com/containers/common/pkg/config/containers.conf-freebsd
generated
vendored
@ -169,6 +169,14 @@ default_sysctls = [
|
||||
#
|
||||
#log_driver = "k8s-file"
|
||||
|
||||
# Default path for container logs to be stored in. When empty, logs will be stored
|
||||
# in the container's default storage and removed when the container is removed.
|
||||
# A subdirectory named with the container ID will be created under the specified
|
||||
# path, and the log file will have the default name `ctr.log` within that directory.
|
||||
# This option can be overridden by the `--log-opt` flag.
|
||||
#
|
||||
#log_path = ""
|
||||
|
||||
# Maximum size allowed for the container log file. Negative numbers indicate
|
||||
# that no size limit is imposed. If positive, it must be >= 8192 to match or
|
||||
# exceed conmon's read buffer. The file is truncated and re-opened so the
|
||||
|
5
vendor/github.com/containers/common/pkg/config/pull_policy.go
generated
vendored
5
vendor/github.com/containers/common/pkg/config/pull_policy.go
generated
vendored
@ -87,8 +87,3 @@ func ParsePullPolicy(s string) (PullPolicy, error) {
|
||||
return PullPolicyUnsupported, fmt.Errorf("unsupported pull policy %q", s)
|
||||
}
|
||||
}
|
||||
|
||||
// Deprecated: please use `ParsePullPolicy` instead.
|
||||
func ValidatePullPolicy(s string) (PullPolicy, error) {
|
||||
return ParsePullPolicy(s)
|
||||
}
|
||||
|
21
vendor/github.com/containers/common/pkg/filters/filters.go
generated
vendored
21
vendor/github.com/containers/common/pkg/filters/filters.go
generated
vendored
@ -93,9 +93,9 @@ func PrepareFilters(r *http.Request) (map[string][]string, error) {
|
||||
}
|
||||
filterMap := map[string][]string{}
|
||||
for _, filter := range filtersList {
|
||||
split := strings.SplitN(filter, "=", 2)
|
||||
if len(split) > 1 {
|
||||
filterMap[split[0]] = append(filterMap[split[0]], split[1])
|
||||
key, val, found := strings.Cut(filter, "=")
|
||||
if found {
|
||||
filterMap[key] = append(filterMap[key], val)
|
||||
}
|
||||
}
|
||||
return filterMap, nil
|
||||
@ -105,7 +105,7 @@ func PrepareFilters(r *http.Request) (map[string][]string, error) {
|
||||
func MatchLabelFilters(filterValues []string, labels map[string]string) bool {
|
||||
outer:
|
||||
for _, filterValue := range filterValues {
|
||||
filterKey, filterValue := splitFilterValue(filterValue)
|
||||
filterKey, filterValue, _ := strings.Cut(filterValue, "=")
|
||||
for labelKey, labelValue := range labels {
|
||||
if filterValue == "" || labelValue == filterValue {
|
||||
if labelKey == filterKey || matchPattern(filterKey, labelKey) {
|
||||
@ -121,7 +121,7 @@ outer:
|
||||
// MatchNegatedLabelFilters matches negated labels and returns true if they are valid
|
||||
func MatchNegatedLabelFilters(filterValues []string, labels map[string]string) bool {
|
||||
for _, filterValue := range filterValues {
|
||||
filterKey, filterValue := splitFilterValue(filterValue)
|
||||
filterKey, filterValue, _ := strings.Cut(filterValue, "=")
|
||||
for labelKey, labelValue := range labels {
|
||||
if filterValue == "" || labelValue == filterValue {
|
||||
if labelKey == filterKey || matchPattern(filterKey, labelKey) {
|
||||
@ -133,17 +133,6 @@ func MatchNegatedLabelFilters(filterValues []string, labels map[string]string) b
|
||||
return true
|
||||
}
|
||||
|
||||
func splitFilterValue(filterValue string) (string, string) {
|
||||
filterArray := strings.SplitN(filterValue, "=", 2)
|
||||
filterKey := filterArray[0]
|
||||
if len(filterArray) > 1 {
|
||||
filterValue = filterArray[1]
|
||||
} else {
|
||||
filterValue = ""
|
||||
}
|
||||
return filterKey, filterValue
|
||||
}
|
||||
|
||||
func matchPattern(pattern string, value string) bool {
|
||||
if strings.Contains(pattern, "*") {
|
||||
filter := fmt.Sprintf("*%s*", pattern)
|
||||
|
8
vendor/github.com/containers/common/pkg/util/util.go
generated
vendored
8
vendor/github.com/containers/common/pkg/util/util.go
generated
vendored
@ -5,7 +5,6 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"slices"
|
||||
"time"
|
||||
|
||||
"github.com/containers/storage/pkg/fileutils"
|
||||
@ -13,13 +12,6 @@ import (
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// StringInSlice determines if a string is in a string slice, returns bool.
|
||||
//
|
||||
// Deprecated: Use [slices.Contains] instead.
|
||||
func StringInSlice(s string, sl []string) bool {
|
||||
return slices.Contains(sl, s)
|
||||
}
|
||||
|
||||
// StringMatchRegexSlice determines if a given string matches one of the given regexes, returns bool
|
||||
func StringMatchRegexSlice(s string, re []string) bool {
|
||||
for _, r := range re {
|
||||
|
2
vendor/github.com/containers/common/version/version.go
generated
vendored
2
vendor/github.com/containers/common/version/version.go
generated
vendored
@ -1,4 +1,4 @@
|
||||
package version
|
||||
|
||||
// Version is the version of the build.
|
||||
const Version = "0.64.0"
|
||||
const Version = "0.65.0-dev"
|
||||
|
3
vendor/github.com/seccomp/libseccomp-golang/CHANGELOG
generated
vendored
3
vendor/github.com/seccomp/libseccomp-golang/CHANGELOG
generated
vendored
@ -2,6 +2,9 @@ libseccomp-golang: Releases
|
||||
===============================================================================
|
||||
https://github.com/seccomp/libseccomp-golang
|
||||
|
||||
* Version 0.11.1 - August 5, 2025
|
||||
- Make GetArchFromString recognize "loong64"
|
||||
|
||||
* Version 0.11.0 - April 23, 2025
|
||||
- Add new architectures (LOONGARCH64, M68K, SH, SHEB)
|
||||
- Add support for SCMP_FLTATR_CTL_WAITKILL (GetWaitKill, SetWaitKill)
|
||||
|
2
vendor/github.com/seccomp/libseccomp-golang/seccomp.go
generated
vendored
2
vendor/github.com/seccomp/libseccomp-golang/seccomp.go
generated
vendored
@ -330,7 +330,7 @@ func GetArchFromString(arch string) (ScmpArch, error) {
|
||||
return ArchPARISC64, nil
|
||||
case "riscv64":
|
||||
return ArchRISCV64, nil
|
||||
case "loongarch64":
|
||||
case "loong64", "loongarch64":
|
||||
return ArchLOONGARCH64, nil
|
||||
case "m68k":
|
||||
return ArchM68K, nil
|
||||
|
27
vendor/github.com/spf13/pflag/README.md
generated
vendored
27
vendor/github.com/spf13/pflag/README.md
generated
vendored
@ -284,6 +284,33 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### Using pflag with go test
|
||||
`pflag` does not parse the shorthand versions of go test's built-in flags (i.e., those starting with `-test.`).
|
||||
For more context, see issues [#63](https://github.com/spf13/pflag/issues/63) and [#238](https://github.com/spf13/pflag/issues/238) for more details.
|
||||
|
||||
For example, if you use pflag in your `TestMain` function and call `pflag.Parse()` after defining your custom flags, running a test like this:
|
||||
```bash
|
||||
go test /your/tests -run ^YourTest -v --your-test-pflags
|
||||
```
|
||||
will result in the `-v` flag being ignored. This happens because of the way pflag handles flag parsing, skipping over go test's built-in shorthand flags.
|
||||
To work around this, you can use the `ParseSkippedFlags` function, which ensures that go test's flags are parsed separately using the standard flag package.
|
||||
|
||||
**Example**: You want to parse go test flags that are otherwise ignore by `pflag.Parse()`
|
||||
```go
|
||||
import (
|
||||
goflag "flag"
|
||||
flag "github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
var ip *int = flag.Int("flagname", 1234, "help message for flagname")
|
||||
|
||||
func main() {
|
||||
flag.CommandLine.AddGoFlagSet(goflag.CommandLine)
|
||||
flag.ParseSkippedFlags(os.Args[1:], goflag.CommandLine)
|
||||
flag.Parse()
|
||||
}
|
||||
```
|
||||
|
||||
## More info
|
||||
|
||||
You can see the full reference documentation of the pflag package
|
||||
|
40
vendor/github.com/spf13/pflag/bool_func.go
generated
vendored
Normal file
40
vendor/github.com/spf13/pflag/bool_func.go
generated
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
package pflag
|
||||
|
||||
// -- func Value
|
||||
type boolfuncValue func(string) error
|
||||
|
||||
func (f boolfuncValue) Set(s string) error { return f(s) }
|
||||
|
||||
func (f boolfuncValue) Type() string { return "boolfunc" }
|
||||
|
||||
func (f boolfuncValue) String() string { return "" } // same behavior as stdlib 'flag' package
|
||||
|
||||
func (f boolfuncValue) IsBoolFlag() bool { return true }
|
||||
|
||||
// BoolFunc defines a func flag with specified name, callback function and usage string.
|
||||
//
|
||||
// The callback function will be called every time "--{name}" (or any form that matches the flag) is parsed
|
||||
// on the command line.
|
||||
func (f *FlagSet) BoolFunc(name string, usage string, fn func(string) error) {
|
||||
f.BoolFuncP(name, "", usage, fn)
|
||||
}
|
||||
|
||||
// BoolFuncP is like BoolFunc, but accepts a shorthand letter that can be used after a single dash.
|
||||
func (f *FlagSet) BoolFuncP(name, shorthand string, usage string, fn func(string) error) {
|
||||
var val Value = boolfuncValue(fn)
|
||||
flag := f.VarPF(val, name, shorthand, usage)
|
||||
flag.NoOptDefVal = "true"
|
||||
}
|
||||
|
||||
// BoolFunc defines a func flag with specified name, callback function and usage string.
|
||||
//
|
||||
// The callback function will be called every time "--{name}" (or any form that matches the flag) is parsed
|
||||
// on the command line.
|
||||
func BoolFunc(name string, usage string, fn func(string) error) {
|
||||
CommandLine.BoolFuncP(name, "", usage, fn)
|
||||
}
|
||||
|
||||
// BoolFuncP is like BoolFunc, but accepts a shorthand letter that can be used after a single dash.
|
||||
func BoolFuncP(name, shorthand string, usage string, fn func(string) error) {
|
||||
CommandLine.BoolFuncP(name, shorthand, usage, fn)
|
||||
}
|
2
vendor/github.com/spf13/pflag/count.go
generated
vendored
2
vendor/github.com/spf13/pflag/count.go
generated
vendored
@ -85,7 +85,7 @@ func (f *FlagSet) CountP(name, shorthand string, usage string) *int {
|
||||
|
||||
// Count defines a count flag with specified name, default value, and usage string.
|
||||
// The return value is the address of an int variable that stores the value of the flag.
|
||||
// A count flag will add 1 to its value evey time it is found on the command line
|
||||
// A count flag will add 1 to its value every time it is found on the command line
|
||||
func Count(name string, usage string) *int {
|
||||
return CommandLine.CountP(name, "", usage)
|
||||
}
|
||||
|
149
vendor/github.com/spf13/pflag/errors.go
generated
vendored
Normal file
149
vendor/github.com/spf13/pflag/errors.go
generated
vendored
Normal file
@ -0,0 +1,149 @@
|
||||
package pflag
|
||||
|
||||
import "fmt"
|
||||
|
||||
// notExistErrorMessageType specifies which flavor of "flag does not exist"
|
||||
// is printed by NotExistError. This allows the related errors to be grouped
|
||||
// under a single NotExistError struct without making a breaking change to
|
||||
// the error message text.
|
||||
type notExistErrorMessageType int
|
||||
|
||||
const (
|
||||
flagNotExistMessage notExistErrorMessageType = iota
|
||||
flagNotDefinedMessage
|
||||
flagNoSuchFlagMessage
|
||||
flagUnknownFlagMessage
|
||||
flagUnknownShorthandFlagMessage
|
||||
)
|
||||
|
||||
// NotExistError is the error returned when trying to access a flag that
|
||||
// does not exist in the FlagSet.
|
||||
type NotExistError struct {
|
||||
name string
|
||||
specifiedShorthands string
|
||||
messageType notExistErrorMessageType
|
||||
}
|
||||
|
||||
// Error implements error.
|
||||
func (e *NotExistError) Error() string {
|
||||
switch e.messageType {
|
||||
case flagNotExistMessage:
|
||||
return fmt.Sprintf("flag %q does not exist", e.name)
|
||||
|
||||
case flagNotDefinedMessage:
|
||||
return fmt.Sprintf("flag accessed but not defined: %s", e.name)
|
||||
|
||||
case flagNoSuchFlagMessage:
|
||||
return fmt.Sprintf("no such flag -%v", e.name)
|
||||
|
||||
case flagUnknownFlagMessage:
|
||||
return fmt.Sprintf("unknown flag: --%s", e.name)
|
||||
|
||||
case flagUnknownShorthandFlagMessage:
|
||||
c := rune(e.name[0])
|
||||
return fmt.Sprintf("unknown shorthand flag: %q in -%s", c, e.specifiedShorthands)
|
||||
}
|
||||
|
||||
panic(fmt.Errorf("unknown flagNotExistErrorMessageType: %v", e.messageType))
|
||||
}
|
||||
|
||||
// GetSpecifiedName returns the name of the flag (without dashes) as it
|
||||
// appeared in the parsed arguments.
|
||||
func (e *NotExistError) GetSpecifiedName() string {
|
||||
return e.name
|
||||
}
|
||||
|
||||
// GetSpecifiedShortnames returns the group of shorthand arguments
|
||||
// (without dashes) that the flag appeared within. If the flag was not in a
|
||||
// shorthand group, this will return an empty string.
|
||||
func (e *NotExistError) GetSpecifiedShortnames() string {
|
||||
return e.specifiedShorthands
|
||||
}
|
||||
|
||||
// ValueRequiredError is the error returned when a flag needs an argument but
|
||||
// no argument was provided.
|
||||
type ValueRequiredError struct {
|
||||
flag *Flag
|
||||
specifiedName string
|
||||
specifiedShorthands string
|
||||
}
|
||||
|
||||
// Error implements error.
|
||||
func (e *ValueRequiredError) Error() string {
|
||||
if len(e.specifiedShorthands) > 0 {
|
||||
c := rune(e.specifiedName[0])
|
||||
return fmt.Sprintf("flag needs an argument: %q in -%s", c, e.specifiedShorthands)
|
||||
}
|
||||
|
||||
return fmt.Sprintf("flag needs an argument: --%s", e.specifiedName)
|
||||
}
|
||||
|
||||
// GetFlag returns the flag for which the error occurred.
|
||||
func (e *ValueRequiredError) GetFlag() *Flag {
|
||||
return e.flag
|
||||
}
|
||||
|
||||
// GetSpecifiedName returns the name of the flag (without dashes) as it
|
||||
// appeared in the parsed arguments.
|
||||
func (e *ValueRequiredError) GetSpecifiedName() string {
|
||||
return e.specifiedName
|
||||
}
|
||||
|
||||
// GetSpecifiedShortnames returns the group of shorthand arguments
|
||||
// (without dashes) that the flag appeared within. If the flag was not in a
|
||||
// shorthand group, this will return an empty string.
|
||||
func (e *ValueRequiredError) GetSpecifiedShortnames() string {
|
||||
return e.specifiedShorthands
|
||||
}
|
||||
|
||||
// InvalidValueError is the error returned when an invalid value is used
|
||||
// for a flag.
|
||||
type InvalidValueError struct {
|
||||
flag *Flag
|
||||
value string
|
||||
cause error
|
||||
}
|
||||
|
||||
// Error implements error.
|
||||
func (e *InvalidValueError) Error() string {
|
||||
flag := e.flag
|
||||
var flagName string
|
||||
if flag.Shorthand != "" && flag.ShorthandDeprecated == "" {
|
||||
flagName = fmt.Sprintf("-%s, --%s", flag.Shorthand, flag.Name)
|
||||
} else {
|
||||
flagName = fmt.Sprintf("--%s", flag.Name)
|
||||
}
|
||||
return fmt.Sprintf("invalid argument %q for %q flag: %v", e.value, flagName, e.cause)
|
||||
}
|
||||
|
||||
// Unwrap implements errors.Unwrap.
|
||||
func (e *InvalidValueError) Unwrap() error {
|
||||
return e.cause
|
||||
}
|
||||
|
||||
// GetFlag returns the flag for which the error occurred.
|
||||
func (e *InvalidValueError) GetFlag() *Flag {
|
||||
return e.flag
|
||||
}
|
||||
|
||||
// GetValue returns the invalid value that was provided.
|
||||
func (e *InvalidValueError) GetValue() string {
|
||||
return e.value
|
||||
}
|
||||
|
||||
// InvalidSyntaxError is the error returned when a bad flag name is passed on
|
||||
// the command line.
|
||||
type InvalidSyntaxError struct {
|
||||
specifiedFlag string
|
||||
}
|
||||
|
||||
// Error implements error.
|
||||
func (e *InvalidSyntaxError) Error() string {
|
||||
return fmt.Sprintf("bad flag syntax: %s", e.specifiedFlag)
|
||||
}
|
||||
|
||||
// GetSpecifiedName returns the exact flag (with dashes) as it
|
||||
// appeared in the parsed arguments.
|
||||
func (e *InvalidSyntaxError) GetSpecifiedFlag() string {
|
||||
return e.specifiedFlag
|
||||
}
|
85
vendor/github.com/spf13/pflag/flag.go
generated
vendored
85
vendor/github.com/spf13/pflag/flag.go
generated
vendored
@ -27,23 +27,32 @@ unaffected.
|
||||
Define flags using flag.String(), Bool(), Int(), etc.
|
||||
|
||||
This declares an integer flag, -flagname, stored in the pointer ip, with type *int.
|
||||
|
||||
var ip = flag.Int("flagname", 1234, "help message for flagname")
|
||||
|
||||
If you like, you can bind the flag to a variable using the Var() functions.
|
||||
|
||||
var flagvar int
|
||||
func init() {
|
||||
flag.IntVar(&flagvar, "flagname", 1234, "help message for flagname")
|
||||
}
|
||||
|
||||
Or you can create custom flags that satisfy the Value interface (with
|
||||
pointer receivers) and couple them to flag parsing by
|
||||
|
||||
flag.Var(&flagVal, "name", "help message for flagname")
|
||||
|
||||
For such flags, the default value is just the initial value of the variable.
|
||||
|
||||
After all flags are defined, call
|
||||
|
||||
flag.Parse()
|
||||
|
||||
to parse the command line into the defined flags.
|
||||
|
||||
Flags may then be used directly. If you're using the flags themselves,
|
||||
they are all pointers; if you bind to variables, they're values.
|
||||
|
||||
fmt.Println("ip has value ", *ip)
|
||||
fmt.Println("flagvar has value ", flagvar)
|
||||
|
||||
@ -54,22 +63,26 @@ The arguments are indexed from 0 through flag.NArg()-1.
|
||||
The pflag package also defines some new functions that are not in flag,
|
||||
that give one-letter shorthands for flags. You can use these by appending
|
||||
'P' to the name of any function that defines a flag.
|
||||
|
||||
var ip = flag.IntP("flagname", "f", 1234, "help message")
|
||||
var flagvar bool
|
||||
func init() {
|
||||
flag.BoolVarP(&flagvar, "boolname", "b", true, "help message")
|
||||
}
|
||||
flag.VarP(&flagval, "varname", "v", "help message")
|
||||
|
||||
Shorthand letters can be used with single dashes on the command line.
|
||||
Boolean shorthand flags can be combined with other shorthand flags.
|
||||
|
||||
Command line flag syntax:
|
||||
|
||||
--flag // boolean flags only
|
||||
--flag=x
|
||||
|
||||
Unlike the flag package, a single dash before an option means something
|
||||
different than a double dash. Single dashes signify a series of shorthand
|
||||
letters for flags. All but the last shorthand letter must be boolean flags.
|
||||
|
||||
// boolean flags
|
||||
-f
|
||||
-abc
|
||||
@ -381,7 +394,7 @@ func (f *FlagSet) lookup(name NormalizedName) *Flag {
|
||||
func (f *FlagSet) getFlagType(name string, ftype string, convFunc func(sval string) (interface{}, error)) (interface{}, error) {
|
||||
flag := f.Lookup(name)
|
||||
if flag == nil {
|
||||
err := fmt.Errorf("flag accessed but not defined: %s", name)
|
||||
err := &NotExistError{name: name, messageType: flagNotDefinedMessage}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@ -411,7 +424,7 @@ func (f *FlagSet) ArgsLenAtDash() int {
|
||||
func (f *FlagSet) MarkDeprecated(name string, usageMessage string) error {
|
||||
flag := f.Lookup(name)
|
||||
if flag == nil {
|
||||
return fmt.Errorf("flag %q does not exist", name)
|
||||
return &NotExistError{name: name, messageType: flagNotExistMessage}
|
||||
}
|
||||
if usageMessage == "" {
|
||||
return fmt.Errorf("deprecated message for flag %q must be set", name)
|
||||
@ -427,7 +440,7 @@ func (f *FlagSet) MarkDeprecated(name string, usageMessage string) error {
|
||||
func (f *FlagSet) MarkShorthandDeprecated(name string, usageMessage string) error {
|
||||
flag := f.Lookup(name)
|
||||
if flag == nil {
|
||||
return fmt.Errorf("flag %q does not exist", name)
|
||||
return &NotExistError{name: name, messageType: flagNotExistMessage}
|
||||
}
|
||||
if usageMessage == "" {
|
||||
return fmt.Errorf("deprecated message for flag %q must be set", name)
|
||||
@ -441,7 +454,7 @@ func (f *FlagSet) MarkShorthandDeprecated(name string, usageMessage string) erro
|
||||
func (f *FlagSet) MarkHidden(name string) error {
|
||||
flag := f.Lookup(name)
|
||||
if flag == nil {
|
||||
return fmt.Errorf("flag %q does not exist", name)
|
||||
return &NotExistError{name: name, messageType: flagNotExistMessage}
|
||||
}
|
||||
flag.Hidden = true
|
||||
return nil
|
||||
@ -464,18 +477,16 @@ func (f *FlagSet) Set(name, value string) error {
|
||||
normalName := f.normalizeFlagName(name)
|
||||
flag, ok := f.formal[normalName]
|
||||
if !ok {
|
||||
return fmt.Errorf("no such flag -%v", name)
|
||||
return &NotExistError{name: name, messageType: flagNoSuchFlagMessage}
|
||||
}
|
||||
|
||||
err := flag.Value.Set(value)
|
||||
if err != nil {
|
||||
var flagName string
|
||||
if flag.Shorthand != "" && flag.ShorthandDeprecated == "" {
|
||||
flagName = fmt.Sprintf("-%s, --%s", flag.Shorthand, flag.Name)
|
||||
} else {
|
||||
flagName = fmt.Sprintf("--%s", flag.Name)
|
||||
return &InvalidValueError{
|
||||
flag: flag,
|
||||
value: value,
|
||||
cause: err,
|
||||
}
|
||||
return fmt.Errorf("invalid argument %q for %q flag: %v", value, flagName, err)
|
||||
}
|
||||
|
||||
if !flag.Changed {
|
||||
@ -501,7 +512,7 @@ func (f *FlagSet) SetAnnotation(name, key string, values []string) error {
|
||||
normalName := f.normalizeFlagName(name)
|
||||
flag, ok := f.formal[normalName]
|
||||
if !ok {
|
||||
return fmt.Errorf("no such flag -%v", name)
|
||||
return &NotExistError{name: name, messageType: flagNoSuchFlagMessage}
|
||||
}
|
||||
if flag.Annotations == nil {
|
||||
flag.Annotations = map[string][]string{}
|
||||
@ -538,7 +549,7 @@ func (f *FlagSet) PrintDefaults() {
|
||||
func (f *Flag) defaultIsZeroValue() bool {
|
||||
switch f.Value.(type) {
|
||||
case boolFlag:
|
||||
return f.DefValue == "false"
|
||||
return f.DefValue == "false" || f.DefValue == ""
|
||||
case *durationValue:
|
||||
// Beginning in Go 1.7, duration zero values are "0s"
|
||||
return f.DefValue == "0" || f.DefValue == "0s"
|
||||
@ -551,7 +562,7 @@ func (f *Flag) defaultIsZeroValue() bool {
|
||||
case *intSliceValue, *stringSliceValue, *stringArrayValue:
|
||||
return f.DefValue == "[]"
|
||||
default:
|
||||
switch f.Value.String() {
|
||||
switch f.DefValue {
|
||||
case "false":
|
||||
return true
|
||||
case "<nil>":
|
||||
@ -588,8 +599,10 @@ func UnquoteUsage(flag *Flag) (name string, usage string) {
|
||||
|
||||
name = flag.Value.Type()
|
||||
switch name {
|
||||
case "bool":
|
||||
case "bool", "boolfunc":
|
||||
name = ""
|
||||
case "func":
|
||||
name = "value"
|
||||
case "float64":
|
||||
name = "float"
|
||||
case "int64":
|
||||
@ -707,7 +720,7 @@ func (f *FlagSet) FlagUsagesWrapped(cols int) string {
|
||||
switch flag.Value.Type() {
|
||||
case "string":
|
||||
line += fmt.Sprintf("[=\"%s\"]", flag.NoOptDefVal)
|
||||
case "bool":
|
||||
case "bool", "boolfunc":
|
||||
if flag.NoOptDefVal != "true" {
|
||||
line += fmt.Sprintf("[=%s]", flag.NoOptDefVal)
|
||||
}
|
||||
@ -911,10 +924,9 @@ func VarP(value Value, name, shorthand, usage string) {
|
||||
CommandLine.VarP(value, name, shorthand, usage)
|
||||
}
|
||||
|
||||
// failf prints to standard error a formatted error and usage message and
|
||||
// fail prints an error message and usage message to standard error and
|
||||
// returns the error.
|
||||
func (f *FlagSet) failf(format string, a ...interface{}) error {
|
||||
err := fmt.Errorf(format, a...)
|
||||
func (f *FlagSet) fail(err error) error {
|
||||
if f.errorHandling != ContinueOnError {
|
||||
fmt.Fprintln(f.Output(), err)
|
||||
f.usage()
|
||||
@ -934,9 +946,9 @@ func (f *FlagSet) usage() {
|
||||
}
|
||||
}
|
||||
|
||||
//--unknown (args will be empty)
|
||||
//--unknown --next-flag ... (args will be --next-flag ...)
|
||||
//--unknown arg ... (args will be arg ...)
|
||||
// --unknown (args will be empty)
|
||||
// --unknown --next-flag ... (args will be --next-flag ...)
|
||||
// --unknown arg ... (args will be arg ...)
|
||||
func stripUnknownFlagValue(args []string) []string {
|
||||
if len(args) == 0 {
|
||||
//--unknown
|
||||
@ -960,7 +972,7 @@ func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []strin
|
||||
a = args
|
||||
name := s[2:]
|
||||
if len(name) == 0 || name[0] == '-' || name[0] == '=' {
|
||||
err = f.failf("bad flag syntax: %s", s)
|
||||
err = f.fail(&InvalidSyntaxError{specifiedFlag: s})
|
||||
return
|
||||
}
|
||||
|
||||
@ -982,7 +994,7 @@ func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []strin
|
||||
|
||||
return stripUnknownFlagValue(a), nil
|
||||
default:
|
||||
err = f.failf("unknown flag: --%s", name)
|
||||
err = f.fail(&NotExistError{name: name, messageType: flagUnknownFlagMessage})
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -1000,13 +1012,16 @@ func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []strin
|
||||
a = a[1:]
|
||||
} else {
|
||||
// '--flag' (arg was required)
|
||||
err = f.failf("flag needs an argument: %s", s)
|
||||
err = f.fail(&ValueRequiredError{
|
||||
flag: flag,
|
||||
specifiedName: name,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
err = fn(flag, value)
|
||||
if err != nil {
|
||||
f.failf(err.Error())
|
||||
f.fail(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -1014,7 +1029,7 @@ func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []strin
|
||||
func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parseFunc) (outShorts string, outArgs []string, err error) {
|
||||
outArgs = args
|
||||
|
||||
if strings.HasPrefix(shorthands, "test.") {
|
||||
if isGotestShorthandFlag(shorthands) {
|
||||
return
|
||||
}
|
||||
|
||||
@ -1039,7 +1054,11 @@ func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parse
|
||||
outArgs = stripUnknownFlagValue(outArgs)
|
||||
return
|
||||
default:
|
||||
err = f.failf("unknown shorthand flag: %q in -%s", c, shorthands)
|
||||
err = f.fail(&NotExistError{
|
||||
name: string(c),
|
||||
specifiedShorthands: shorthands,
|
||||
messageType: flagUnknownShorthandFlagMessage,
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -1062,7 +1081,11 @@ func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parse
|
||||
outArgs = args[1:]
|
||||
} else {
|
||||
// '-f' (arg was required)
|
||||
err = f.failf("flag needs an argument: %q in -%s", c, shorthands)
|
||||
err = f.fail(&ValueRequiredError{
|
||||
flag: flag,
|
||||
specifiedName: string(c),
|
||||
specifiedShorthands: shorthands,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
@ -1072,7 +1095,7 @@ func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parse
|
||||
|
||||
err = fn(flag, value)
|
||||
if err != nil {
|
||||
f.failf(err.Error())
|
||||
f.fail(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -1135,7 +1158,7 @@ func (f *FlagSet) Parse(arguments []string) error {
|
||||
}
|
||||
f.parsed = true
|
||||
|
||||
if len(arguments) < 0 {
|
||||
if len(arguments) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
37
vendor/github.com/spf13/pflag/func.go
generated
vendored
Normal file
37
vendor/github.com/spf13/pflag/func.go
generated
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
package pflag
|
||||
|
||||
// -- func Value
|
||||
type funcValue func(string) error
|
||||
|
||||
func (f funcValue) Set(s string) error { return f(s) }
|
||||
|
||||
func (f funcValue) Type() string { return "func" }
|
||||
|
||||
func (f funcValue) String() string { return "" } // same behavior as stdlib 'flag' package
|
||||
|
||||
// Func defines a func flag with specified name, callback function and usage string.
|
||||
//
|
||||
// The callback function will be called every time "--{name}={value}" (or equivalent) is
|
||||
// parsed on the command line, with "{value}" as an argument.
|
||||
func (f *FlagSet) Func(name string, usage string, fn func(string) error) {
|
||||
f.FuncP(name, "", usage, fn)
|
||||
}
|
||||
|
||||
// FuncP is like Func, but accepts a shorthand letter that can be used after a single dash.
|
||||
func (f *FlagSet) FuncP(name string, shorthand string, usage string, fn func(string) error) {
|
||||
var val Value = funcValue(fn)
|
||||
f.VarP(val, name, shorthand, usage)
|
||||
}
|
||||
|
||||
// Func defines a func flag with specified name, callback function and usage string.
|
||||
//
|
||||
// The callback function will be called every time "--{name}={value}" (or equivalent) is
|
||||
// parsed on the command line, with "{value}" as an argument.
|
||||
func Func(name string, usage string, fn func(string) error) {
|
||||
CommandLine.FuncP(name, "", usage, fn)
|
||||
}
|
||||
|
||||
// FuncP is like Func, but accepts a shorthand letter that can be used after a single dash.
|
||||
func FuncP(name, shorthand string, usage string, fn func(string) error) {
|
||||
CommandLine.FuncP(name, shorthand, usage, fn)
|
||||
}
|
22
vendor/github.com/spf13/pflag/golangflag.go
generated
vendored
22
vendor/github.com/spf13/pflag/golangflag.go
generated
vendored
@ -10,6 +10,15 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// go test flags prefixes
|
||||
func isGotestFlag(flag string) bool {
|
||||
return strings.HasPrefix(flag, "-test.")
|
||||
}
|
||||
|
||||
func isGotestShorthandFlag(flag string) bool {
|
||||
return strings.HasPrefix(flag, "test.")
|
||||
}
|
||||
|
||||
// flagValueWrapper implements pflag.Value around a flag.Value. The main
|
||||
// difference here is the addition of the Type method that returns a string
|
||||
// name of the type. As this is generally unknown, we approximate that with
|
||||
@ -103,3 +112,16 @@ func (f *FlagSet) AddGoFlagSet(newSet *goflag.FlagSet) {
|
||||
}
|
||||
f.addedGoFlagSets = append(f.addedGoFlagSets, newSet)
|
||||
}
|
||||
|
||||
// ParseSkippedFlags explicitly Parses go test flags (i.e. the one starting with '-test.') with goflag.Parse(),
|
||||
// since by default those are skipped by pflag.Parse().
|
||||
// Typical usage example: `ParseGoTestFlags(os.Args[1:], goflag.CommandLine)`
|
||||
func ParseSkippedFlags(osArgs []string, goFlagSet *goflag.FlagSet) error {
|
||||
var skippedFlags []string
|
||||
for _, f := range osArgs {
|
||||
if isGotestFlag(f) {
|
||||
skippedFlags = append(skippedFlags, f)
|
||||
}
|
||||
}
|
||||
return goFlagSet.Parse(skippedFlags)
|
||||
}
|
||||
|
2
vendor/github.com/spf13/pflag/ipnet_slice.go
generated
vendored
2
vendor/github.com/spf13/pflag/ipnet_slice.go
generated
vendored
@ -73,7 +73,7 @@ func (s *ipNetSliceValue) String() string {
|
||||
|
||||
func ipNetSliceConv(val string) (interface{}, error) {
|
||||
val = strings.Trim(val, "[]")
|
||||
// Emtpy string would cause a slice with one (empty) entry
|
||||
// Empty string would cause a slice with one (empty) entry
|
||||
if len(val) == 0 {
|
||||
return []net.IPNet{}, nil
|
||||
}
|
||||
|
81
vendor/github.com/spf13/pflag/text.go
generated
vendored
Normal file
81
vendor/github.com/spf13/pflag/text.go
generated
vendored
Normal file
@ -0,0 +1,81 @@
|
||||
package pflag
|
||||
|
||||
import (
|
||||
"encoding"
|
||||
"fmt"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// following is copied from go 1.23.4 flag.go
|
||||
type textValue struct{ p encoding.TextUnmarshaler }
|
||||
|
||||
func newTextValue(val encoding.TextMarshaler, p encoding.TextUnmarshaler) textValue {
|
||||
ptrVal := reflect.ValueOf(p)
|
||||
if ptrVal.Kind() != reflect.Ptr {
|
||||
panic("variable value type must be a pointer")
|
||||
}
|
||||
defVal := reflect.ValueOf(val)
|
||||
if defVal.Kind() == reflect.Ptr {
|
||||
defVal = defVal.Elem()
|
||||
}
|
||||
if defVal.Type() != ptrVal.Type().Elem() {
|
||||
panic(fmt.Sprintf("default type does not match variable type: %v != %v", defVal.Type(), ptrVal.Type().Elem()))
|
||||
}
|
||||
ptrVal.Elem().Set(defVal)
|
||||
return textValue{p}
|
||||
}
|
||||
|
||||
func (v textValue) Set(s string) error {
|
||||
return v.p.UnmarshalText([]byte(s))
|
||||
}
|
||||
|
||||
func (v textValue) Get() interface{} {
|
||||
return v.p
|
||||
}
|
||||
|
||||
func (v textValue) String() string {
|
||||
if m, ok := v.p.(encoding.TextMarshaler); ok {
|
||||
if b, err := m.MarshalText(); err == nil {
|
||||
return string(b)
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
//end of copy
|
||||
|
||||
func (v textValue) Type() string {
|
||||
return reflect.ValueOf(v.p).Type().Name()
|
||||
}
|
||||
|
||||
// GetText set out, which implements encoding.UnmarshalText, to the value of a flag with given name
|
||||
func (f *FlagSet) GetText(name string, out encoding.TextUnmarshaler) error {
|
||||
flag := f.Lookup(name)
|
||||
if flag == nil {
|
||||
return fmt.Errorf("flag accessed but not defined: %s", name)
|
||||
}
|
||||
if flag.Value.Type() != reflect.TypeOf(out).Name() {
|
||||
return fmt.Errorf("trying to get %s value of flag of type %s", reflect.TypeOf(out).Name(), flag.Value.Type())
|
||||
}
|
||||
return out.UnmarshalText([]byte(flag.Value.String()))
|
||||
}
|
||||
|
||||
// TextVar defines a flag with a specified name, default value, and usage string. The argument p must be a pointer to a variable that will hold the value of the flag, and p must implement encoding.TextUnmarshaler. If the flag is used, the flag value will be passed to p's UnmarshalText method. The type of the default value must be the same as the type of p.
|
||||
func (f *FlagSet) TextVar(p encoding.TextUnmarshaler, name string, value encoding.TextMarshaler, usage string) {
|
||||
f.VarP(newTextValue(value, p), name, "", usage)
|
||||
}
|
||||
|
||||
// TextVarP is like TextVar, but accepts a shorthand letter that can be used after a single dash.
|
||||
func (f *FlagSet) TextVarP(p encoding.TextUnmarshaler, name, shorthand string, value encoding.TextMarshaler, usage string) {
|
||||
f.VarP(newTextValue(value, p), name, shorthand, usage)
|
||||
}
|
||||
|
||||
// TextVar defines a flag with a specified name, default value, and usage string. The argument p must be a pointer to a variable that will hold the value of the flag, and p must implement encoding.TextUnmarshaler. If the flag is used, the flag value will be passed to p's UnmarshalText method. The type of the default value must be the same as the type of p.
|
||||
func TextVar(p encoding.TextUnmarshaler, name string, value encoding.TextMarshaler, usage string) {
|
||||
CommandLine.VarP(newTextValue(value, p), name, "", usage)
|
||||
}
|
||||
|
||||
// TextVarP is like TextVar, but accepts a shorthand letter that can be used after a single dash.
|
||||
func TextVarP(p encoding.TextUnmarshaler, name, shorthand string, value encoding.TextMarshaler, usage string) {
|
||||
CommandLine.VarP(newTextValue(value, p), name, shorthand, usage)
|
||||
}
|
118
vendor/github.com/spf13/pflag/time.go
generated
vendored
Normal file
118
vendor/github.com/spf13/pflag/time.go
generated
vendored
Normal file
@ -0,0 +1,118 @@
|
||||
package pflag
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// TimeValue adapts time.Time for use as a flag.
|
||||
type timeValue struct {
|
||||
*time.Time
|
||||
formats []string
|
||||
}
|
||||
|
||||
func newTimeValue(val time.Time, p *time.Time, formats []string) *timeValue {
|
||||
*p = val
|
||||
return &timeValue{
|
||||
Time: p,
|
||||
formats: formats,
|
||||
}
|
||||
}
|
||||
|
||||
// Set time.Time value from string based on accepted formats.
|
||||
func (d *timeValue) Set(s string) error {
|
||||
s = strings.TrimSpace(s)
|
||||
for _, f := range d.formats {
|
||||
v, err := time.Parse(f, s)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
*d.Time = v
|
||||
return nil
|
||||
}
|
||||
|
||||
formatsString := ""
|
||||
for i, f := range d.formats {
|
||||
if i > 0 {
|
||||
formatsString += ", "
|
||||
}
|
||||
formatsString += fmt.Sprintf("`%s`", f)
|
||||
}
|
||||
|
||||
return fmt.Errorf("invalid time format `%s` must be one of: %s", s, formatsString)
|
||||
}
|
||||
|
||||
// Type name for time.Time flags.
|
||||
func (d *timeValue) Type() string {
|
||||
return "time"
|
||||
}
|
||||
|
||||
func (d *timeValue) String() string { return d.Time.Format(time.RFC3339Nano) }
|
||||
|
||||
// GetTime return the time value of a flag with the given name
|
||||
func (f *FlagSet) GetTime(name string) (time.Time, error) {
|
||||
flag := f.Lookup(name)
|
||||
if flag == nil {
|
||||
err := fmt.Errorf("flag accessed but not defined: %s", name)
|
||||
return time.Time{}, err
|
||||
}
|
||||
|
||||
if flag.Value.Type() != "time" {
|
||||
err := fmt.Errorf("trying to get %s value of flag of type %s", "time", flag.Value.Type())
|
||||
return time.Time{}, err
|
||||
}
|
||||
|
||||
val, ok := flag.Value.(*timeValue)
|
||||
if !ok {
|
||||
return time.Time{}, fmt.Errorf("value %s is not a time", flag.Value)
|
||||
}
|
||||
|
||||
return *val.Time, nil
|
||||
}
|
||||
|
||||
// TimeVar defines a time.Time flag with specified name, default value, and usage string.
|
||||
// The argument p points to a time.Time variable in which to store the value of the flag.
|
||||
func (f *FlagSet) TimeVar(p *time.Time, name string, value time.Time, formats []string, usage string) {
|
||||
f.TimeVarP(p, name, "", value, formats, usage)
|
||||
}
|
||||
|
||||
// TimeVarP is like TimeVar, but accepts a shorthand letter that can be used after a single dash.
|
||||
func (f *FlagSet) TimeVarP(p *time.Time, name, shorthand string, value time.Time, formats []string, usage string) {
|
||||
f.VarP(newTimeValue(value, p, formats), name, shorthand, usage)
|
||||
}
|
||||
|
||||
// TimeVar defines a time.Time flag with specified name, default value, and usage string.
|
||||
// The argument p points to a time.Time variable in which to store the value of the flag.
|
||||
func TimeVar(p *time.Time, name string, value time.Time, formats []string, usage string) {
|
||||
CommandLine.TimeVarP(p, name, "", value, formats, usage)
|
||||
}
|
||||
|
||||
// TimeVarP is like TimeVar, but accepts a shorthand letter that can be used after a single dash.
|
||||
func TimeVarP(p *time.Time, name, shorthand string, value time.Time, formats []string, usage string) {
|
||||
CommandLine.VarP(newTimeValue(value, p, formats), name, shorthand, usage)
|
||||
}
|
||||
|
||||
// Time defines a time.Time flag with specified name, default value, and usage string.
|
||||
// The return value is the address of a time.Time variable that stores the value of the flag.
|
||||
func (f *FlagSet) Time(name string, value time.Time, formats []string, usage string) *time.Time {
|
||||
return f.TimeP(name, "", value, formats, usage)
|
||||
}
|
||||
|
||||
// TimeP is like Time, but accepts a shorthand letter that can be used after a single dash.
|
||||
func (f *FlagSet) TimeP(name, shorthand string, value time.Time, formats []string, usage string) *time.Time {
|
||||
p := new(time.Time)
|
||||
f.TimeVarP(p, name, shorthand, value, formats, usage)
|
||||
return p
|
||||
}
|
||||
|
||||
// Time defines a time.Time flag with specified name, default value, and usage string.
|
||||
// The return value is the address of a time.Time variable that stores the value of the flag.
|
||||
func Time(name string, value time.Time, formats []string, usage string) *time.Time {
|
||||
return CommandLine.TimeP(name, "", value, formats, usage)
|
||||
}
|
||||
|
||||
// TimeP is like Time, but accepts a shorthand letter that can be used after a single dash.
|
||||
func TimeP(name, shorthand string, value time.Time, formats []string, usage string) *time.Time {
|
||||
return CommandLine.TimeP(name, shorthand, value, formats, usage)
|
||||
}
|
6
vendor/modules.txt
vendored
6
vendor/modules.txt
vendored
@ -141,7 +141,7 @@ github.com/containers/buildah/pkg/sshagent
|
||||
github.com/containers/buildah/pkg/util
|
||||
github.com/containers/buildah/pkg/volumes
|
||||
github.com/containers/buildah/util
|
||||
# github.com/containers/common v0.64.0
|
||||
# github.com/containers/common v0.64.1-0.20250806164630-57def9601f3b
|
||||
## explicit; go 1.23.3
|
||||
github.com/containers/common/internal
|
||||
github.com/containers/common/internal/attributedstring
|
||||
@ -821,7 +821,7 @@ github.com/rootless-containers/rootlesskit/v2/pkg/port/builtin/parent/tcp
|
||||
github.com/rootless-containers/rootlesskit/v2/pkg/port/builtin/parent/udp
|
||||
github.com/rootless-containers/rootlesskit/v2/pkg/port/builtin/parent/udp/udpproxy
|
||||
github.com/rootless-containers/rootlesskit/v2/pkg/port/portutil
|
||||
# github.com/seccomp/libseccomp-golang v0.11.0
|
||||
# github.com/seccomp/libseccomp-golang v0.11.1
|
||||
## explicit; go 1.19
|
||||
github.com/seccomp/libseccomp-golang
|
||||
# github.com/secure-systems-lab/go-securesystemslib v0.9.0
|
||||
@ -870,7 +870,7 @@ github.com/smallstep/pkcs7/internal/legacy/x509
|
||||
# github.com/spf13/cobra v1.9.1
|
||||
## explicit; go 1.15
|
||||
github.com/spf13/cobra
|
||||
# github.com/spf13/pflag v1.0.6
|
||||
# github.com/spf13/pflag v1.0.7
|
||||
## explicit; go 1.12
|
||||
github.com/spf13/pflag
|
||||
# github.com/stefanberger/go-pkcs11uri v0.0.0-20230803200340-78284954bff6
|
||||
|
Reference in New Issue
Block a user