Secret create - add ignore option to allow noop

Signed-off-by: Ygal Blum <ygal.blum@gmail.com>
This commit is contained in:
Ygal Blum
2025-06-18 16:28:48 -04:00
parent 1f1618fcb0
commit bfc327a08e
16 changed files with 138 additions and 36 deletions

View File

@ -3,9 +3,7 @@
package cgroups
import (
"fmt"
"path/filepath"
"strconv"
"github.com/opencontainers/cgroups"
"github.com/opencontainers/cgroups/fs"
@ -57,31 +55,44 @@ func (c *linuxMemHandler) Stat(ctr *CgroupControl, m *cgroups.Stats) error {
if ctr.cgroup2 {
memoryRoot = filepath.Join(cgroupRoot, ctr.config.Path)
limitFilename = "memory.max"
if memUsage.Usage.Usage, err = readFileByKeyAsUint64(filepath.Join(memoryRoot, "memory.stat"), "anon"); err != nil {
// Read memory.current
current, err := readFileAsUint64(filepath.Join(memoryRoot, "memory.current"))
if err != nil {
return err
}
// Read inactive_file from memory.stat
inactiveFile, err := readFileByKeyAsUint64(filepath.Join(memoryRoot, "memory.stat"), "inactive_file")
if err != nil {
return err
}
// Docker calculation: memory.current - memory.stat['inactive_file']
memUsage.Usage.Usage = 0
if inactiveFile < current {
memUsage.Usage.Usage = current - inactiveFile
}
} else {
memoryRoot = ctr.getCgroupv1Path(Memory)
limitFilename = "memory.limit_in_bytes"
path := filepath.Join(memoryRoot, "memory.stat")
values, err := readCgroupMapPath(path)
// Read memory.usage_in_bytes
usageInBytes, err := readFileAsUint64(filepath.Join(memoryRoot, "memory.usage_in_bytes"))
if err != nil {
return err
}
// cgroup v1 does not have a single "anon" field, but we can calculate it
// from total_active_anon and total_inactive_anon
// Read total_inactive_file from memory.stat
totalInactiveFile, err := readFileByKeyAsUint64(filepath.Join(memoryRoot, "memory.stat"), "total_inactive_file")
if err != nil {
return err
}
// Docker calculation: memory.usage_in_bytes - memory.stat['total_inactive_file']
memUsage.Usage.Usage = 0
for _, key := range []string{"total_active_anon", "total_inactive_anon"} {
if _, found := values[key]; !found {
continue
}
res, err := strconv.ParseUint(values[key][0], 10, 64)
if err != nil {
return fmt.Errorf("parse %s from %s: %w", key, path, err)
}
memUsage.Usage.Usage += res
if totalInactiveFile < usageInBytes {
memUsage.Usage.Usage = usageInBytes - totalInactiveFile
}
}

View File

@ -48,6 +48,9 @@ var errAmbiguous = errors.New("secret is ambiguous")
// errDataSize indicates that the secret data is too large or too small
var errDataSize = errors.New("secret data must be larger than 0 and less than 512000 bytes")
// errIgnoreIfExistsAndReplace indicates that ignoreIfExists and replace cannot be used together.
var errIgnoreIfExistsAndReplace = errors.New("ignoreIfExists and replace cannot be used together")
// secretsFile is the name of the file that the secrets database will be stored in
var secretsFile = "secrets.json"
@ -114,6 +117,8 @@ type StoreOptions struct {
Labels map[string]string
// Replace existing secret
Replace bool
// Ignore if already exists
IgnoreIfExists bool
}
// NewManager creates a new secrets manager
@ -169,6 +174,11 @@ func (s *SecretsManager) Store(name string, data []byte, driverType string, opti
if len(data) == 0 || len(data) >= maxSecretSize {
return "", errDataSize
}
if options.IgnoreIfExists && options.Replace {
return "", errIgnoreIfExistsAndReplace
}
var secr *Secret
s.lockfile.Lock()
defer s.lockfile.Unlock()
@ -179,13 +189,16 @@ func (s *SecretsManager) Store(name string, data []byte, driverType string, opti
}
if exist {
if !options.Replace {
if !options.Replace && !options.IgnoreIfExists {
return "", fmt.Errorf("%s: %w", name, errSecretNameInUse)
}
secr, err = s.lookupSecret(name)
if err != nil {
return "", err
}
if options.IgnoreIfExists {
return secr.ID, nil
}
secr.UpdatedAt = time.Now()
} else {
secr = new(Secret)

View File

@ -29,7 +29,7 @@ type Cgroup struct {
ScopePrefix string `json:"scope_prefix,omitempty"`
// Resources contains various cgroups settings to apply.
*Resources `json:"Resources,omitempty"`
*Resources
// Systemd tells if systemd should be used to manage cgroups.
Systemd bool `json:"Systemd,omitempty"`

View File

@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"io"
"math"
"os"
"path/filepath"
"strconv"
@ -413,16 +414,30 @@ func WriteCgroupProc(dir string, pid int) error {
return err
}
// Since the OCI spec is designed for cgroup v1, in some cases
// there is need to convert from the cgroup v1 configuration to cgroup v2
// the formula for cpuShares is y = (1 + ((x - 2) * 9999) / 262142)
// convert from [2-262144] to [1-10000]
// 262144 comes from Linux kernel definition "#define MAX_SHARES (1UL << 18)"
// ConvertCPUSharesToCgroupV2Value converts CPU shares, used by cgroup v1,
// to CPU weight, used by cgroup v2.
//
// Cgroup v1 CPU shares has a range of [2^1...2^18], i.e. [2...262144],
// and the default value is 1024.
//
// Cgroup v2 CPU weight has a range of [10^0...10^4], i.e. [1...10000],
// and the default value is 100.
func ConvertCPUSharesToCgroupV2Value(cpuShares uint64) uint64 {
// The value of 0 means "unset".
if cpuShares == 0 {
return 0
}
return (1 + ((cpuShares-2)*9999)/262142)
if cpuShares <= 2 {
return 1
}
if cpuShares >= 262144 {
return 10000
}
l := math.Log2(float64(cpuShares))
// Quadratic function which fits min, max, and default.
exponent := (l*l+125*l)/612.0 - 7.0/34.0
return uint64(math.Ceil(math.Pow(10, exponent)))
}
// ConvertMemorySwapToCgroupV2Value converts MemorySwap value from OCI spec