diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4faed60..62fc030 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -20,7 +20,7 @@ jobs: strategy: fail-fast: false matrix: - go-version: [1.23.x, 1.24.x] + go-version: [1.24.x, 1.25.x] race: ["-race", ""] runs-on: ubuntu-24.04 diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index e5ed8b7..1cf7c01 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -11,7 +11,7 @@ on: # Runs at 00:00 UTC every Monday - cron: '0 0 * * 1' env: - GO_VERSION: 1.24 + GO_VERSION: 1.25 permissions: contents: read diff --git a/.golangci-extra.yml b/.golangci-extra.yml index b98dba1..ce687ce 100644 --- a/.golangci-extra.yml +++ b/.golangci-extra.yml @@ -19,3 +19,11 @@ linters: - -QF1008 # https://staticcheck.dev/docs/checks/#QF1008 Omit embedded fields from selector expression. exclusions: generated: strict + rules: + # Legacy names we can't change without breaking compatibility. + - path: stats.go + text: "(type|struct field) (CpuUsage|CpuStats) should be " + - path: config_linux.go + text: "struct field (CpuShares|CpuQuota|CpuBurst|CpuPeriod|CpuRtRuntime|CpuRtPeriod|CpuWeight) should be " + - path: devices/config/device.go + text: "struct field (Uid|Gid) should be " diff --git a/config_linux.go b/config_linux.go index 3d29d93..8b5e505 100644 --- a/config_linux.go +++ b/config_linux.go @@ -16,23 +16,23 @@ const ( // Cgroup holds properties of a cgroup on Linux. type Cgroup struct { // Name specifies the name of the cgroup - Name string `json:"name,omitempty"` + Name string `json:"name,omitzero"` // Parent specifies the name of parent of cgroup or slice - Parent string `json:"parent,omitempty"` + Parent string `json:"parent,omitzero"` // Path specifies the path to cgroups that are created and/or joined by the container. // The path is assumed to be relative to the host system cgroup mountpoint. - Path string `json:"path,omitempty"` + Path string `json:"path,omitzero"` // ScopePrefix describes prefix for the scope name. - ScopePrefix string `json:"scope_prefix,omitempty"` + ScopePrefix string `json:"scope_prefix,omitzero"` // Resources contains various cgroups settings to apply. *Resources // Systemd tells if systemd should be used to manage cgroups. - Systemd bool `json:"Systemd,omitempty"` + Systemd bool `json:"Systemd,omitzero"` // SystemdProps are any additional properties for systemd, // derived from org.systemd.property.xxx annotations. @@ -40,108 +40,108 @@ type Cgroup struct { SystemdProps []systemdDbus.Property `json:"-"` // Rootless tells if rootless cgroups should be used. - Rootless bool `json:"Rootless,omitempty"` + Rootless bool `json:"Rootless,omitzero"` // The host UID that should own the cgroup, or nil to accept // the default ownership. This should only be set when the // cgroupfs is to be mounted read/write. // Not all cgroup manager implementations support changing // the ownership. - OwnerUID *int `json:"owner_uid,omitempty"` + OwnerUID *int `json:"owner_uid,omitzero"` } type Resources struct { // Devices is the set of access rules for devices in the container. - Devices []*devices.Rule `json:"devices,omitempty"` + Devices []*devices.Rule `json:"devices,omitzero"` // Memory limit (in bytes). - Memory int64 `json:"memory,omitempty"` + Memory int64 `json:"memory,omitzero"` // Memory reservation or soft_limit (in bytes). - MemoryReservation int64 `json:"memory_reservation,omitempty"` + MemoryReservation int64 `json:"memory_reservation,omitzero"` // Total memory usage (memory+swap); use -1 for unlimited swap. - MemorySwap int64 `json:"memory_swap,omitempty"` + MemorySwap int64 `json:"memory_swap,omitzero"` // CPU shares (relative weight vs. other containers). - CpuShares uint64 `json:"cpu_shares,omitempty"` //nolint:revive // Suppress "var-naming: struct field CpuShares should be CPUShares". + CpuShares uint64 `json:"cpu_shares,omitzero"` // CPU hardcap limit (in usecs). Allowed cpu time in a given period. - CpuQuota int64 `json:"cpu_quota,omitempty"` //nolint:revive // Suppress "var-naming: struct field CpuQuota should be CPUQuota". + CpuQuota int64 `json:"cpu_quota,omitzero"` // CPU hardcap burst limit (in usecs). Allowed accumulated cpu time additionally for burst in a given period. - CpuBurst *uint64 `json:"cpu_burst,omitempty"` //nolint:revive // Suppress "var-naming: struct field CpuBurst should be CPUBurst". + CpuBurst *uint64 `json:"cpu_burst,omitzero"` // CPU period to be used for hardcapping (in usecs). 0 to use system default. - CpuPeriod uint64 `json:"cpu_period,omitempty"` //nolint:revive // Suppress "var-naming: struct field CpuPeriod should be CPUPeriod". + CpuPeriod uint64 `json:"cpu_period,omitzero"` // How many time CPU will use in realtime scheduling (in usecs). - CpuRtRuntime int64 `json:"cpu_rt_quota,omitempty"` //nolint:revive // Suppress "var-naming: struct field CpuRtRuntime should be CPURtRuntime". + CpuRtRuntime int64 `json:"cpu_rt_quota,omitzero"` // CPU period to be used for realtime scheduling (in usecs). - CpuRtPeriod uint64 `json:"cpu_rt_period,omitempty"` //nolint:revive // Suppress "var-naming: struct field CpuQuota should be CPUQuota". + CpuRtPeriod uint64 `json:"cpu_rt_period,omitzero"` // Cpuset CPUs to use. - CpusetCpus string `json:"cpuset_cpus,omitempty"` + CpusetCpus string `json:"cpuset_cpus,omitzero"` // Cpuset memory nodes to use. - CpusetMems string `json:"cpuset_mems,omitempty"` + CpusetMems string `json:"cpuset_mems,omitzero"` // Cgroup's SCHED_IDLE value. - CPUIdle *int64 `json:"cpu_idle,omitempty"` + CPUIdle *int64 `json:"cpu_idle,omitzero"` // Process limit; set < `0' to disable limit. `nil` means "keep current limit". - PidsLimit *int64 `json:"pids_limit,omitempty"` + PidsLimit *int64 `json:"pids_limit,omitzero"` // Specifies per cgroup weight, range is from 10 to 1000. - BlkioWeight uint16 `json:"blkio_weight,omitempty"` + BlkioWeight uint16 `json:"blkio_weight,omitzero"` // Tasks' weight in the given cgroup while competing with the cgroup's child cgroups, range is from 10 to 1000, cfq scheduler only. - BlkioLeafWeight uint16 `json:"blkio_leaf_weight,omitempty"` + BlkioLeafWeight uint16 `json:"blkio_leaf_weight,omitzero"` // Weight per cgroup per device, can override BlkioWeight. - BlkioWeightDevice []*WeightDevice `json:"blkio_weight_device,omitempty"` + BlkioWeightDevice []*WeightDevice `json:"blkio_weight_device,omitzero"` // IO read rate limit per cgroup per device, bytes per second. - BlkioThrottleReadBpsDevice []*ThrottleDevice `json:"blkio_throttle_read_bps_device,omitempty"` + BlkioThrottleReadBpsDevice []*ThrottleDevice `json:"blkio_throttle_read_bps_device,omitzero"` // IO write rate limit per cgroup per device, bytes per second. - BlkioThrottleWriteBpsDevice []*ThrottleDevice `json:"blkio_throttle_write_bps_device,omitempty"` + BlkioThrottleWriteBpsDevice []*ThrottleDevice `json:"blkio_throttle_write_bps_device,omitzero"` // IO read rate limit per cgroup per device, IO per second. - BlkioThrottleReadIOPSDevice []*ThrottleDevice `json:"blkio_throttle_read_iops_device,omitempty"` + BlkioThrottleReadIOPSDevice []*ThrottleDevice `json:"blkio_throttle_read_iops_device,omitzero"` // IO write rate limit per cgroup per device, IO per second. - BlkioThrottleWriteIOPSDevice []*ThrottleDevice `json:"blkio_throttle_write_iops_device,omitempty"` + BlkioThrottleWriteIOPSDevice []*ThrottleDevice `json:"blkio_throttle_write_iops_device,omitzero"` // Freeze value for the process. - Freezer FreezerState `json:"freezer,omitempty"` + Freezer FreezerState `json:"freezer,omitzero"` // Hugetlb limit (in bytes). - HugetlbLimit []*HugepageLimit `json:"hugetlb_limit,omitempty"` + HugetlbLimit []*HugepageLimit `json:"hugetlb_limit,omitzero"` // Whether to disable OOM killer. - OomKillDisable bool `json:"oom_kill_disable,omitempty"` + OomKillDisable bool `json:"oom_kill_disable,omitzero"` // Tuning swappiness behaviour per cgroup. - MemorySwappiness *uint64 `json:"memory_swappiness,omitempty"` + MemorySwappiness *uint64 `json:"memory_swappiness,omitzero"` // Set priority of network traffic for container. - NetPrioIfpriomap []*IfPrioMap `json:"net_prio_ifpriomap,omitempty"` + NetPrioIfpriomap []*IfPrioMap `json:"net_prio_ifpriomap,omitzero"` // Set class identifier for container's network packets. - NetClsClassid uint32 `json:"net_cls_classid_u,omitempty"` + NetClsClassid uint32 `json:"net_cls_classid_u,omitzero"` // Rdma resource restriction configuration. - Rdma map[string]LinuxRdma `json:"rdma,omitempty"` + Rdma map[string]LinuxRdma `json:"rdma,omitzero"` // Used on cgroups v2: // CpuWeight sets a proportional bandwidth limit. - CpuWeight uint64 `json:"cpu_weight,omitempty"` //nolint:revive // Suppress "var-naming: struct field CpuWeight should be CPUWeight". + CpuWeight uint64 `json:"cpu_weight,omitzero"` // Unified is cgroupv2-only key-value map. - Unified map[string]string `json:"unified,omitempty"` + Unified map[string]string `json:"unified,omitzero"` // SkipDevices allows to skip configuring device permissions. // Used by e.g. kubelet while creating a parent cgroup (kubepods) @@ -165,5 +165,5 @@ type Resources struct { // MemoryCheckBeforeUpdate is a flag for cgroup v2 managers to check // if the new memory limits (Memory and MemorySwap) being set are lower // than the current memory usage, and reject if so. - MemoryCheckBeforeUpdate bool `json:"memory_check_before_update,omitempty"` + MemoryCheckBeforeUpdate bool `json:"memory_check_before_update,omitzero"` } diff --git a/devices/config/device.go b/devices/config/device.go index 295575c..b36a3e8 100644 --- a/devices/config/device.go +++ b/devices/config/device.go @@ -20,10 +20,10 @@ type Device struct { FileMode os.FileMode `json:"file_mode"` // Uid of the device. - Uid uint32 `json:"uid,omitempty"` //nolint:revive // Suppress "var-naming: struct field Uid should be UID". + Uid uint32 `json:"uid,omitzero"` // Gid of the device. - Gid uint32 `json:"gid,omitempty"` //nolint:revive // Suppress "var-naming: struct field Gid should be GID". + Gid uint32 `json:"gid,omitzero"` } // Permissions is a cgroupv1-style string to represent device access. It diff --git a/devices/devicefilter_test.go b/devices/devicefilter_test.go index 4010deb..6df6af2 100644 --- a/devices/devicefilter_test.go +++ b/devices/devicefilter_test.go @@ -9,7 +9,7 @@ import ( func hash(s, comm string) string { var res []string - for _, l := range strings.Split(s, "\n") { + for l := range strings.SplitSeq(s, "\n") { trimmed := strings.TrimSpace(l) if trimmed == "" || strings.HasPrefix(trimmed, comm) { continue diff --git a/devices/devices_emulator_test.go b/devices/devices_emulator_test.go index 24c1d1e..57c245a 100644 --- a/devices/devices_emulator_test.go +++ b/devices/devices_emulator_test.go @@ -202,7 +202,6 @@ c 10:200 rwm`, } for _, test := range tests { - test := test // capture range variable t.Run(test.name, func(t *testing.T) { list := bytes.NewBufferString(test.list) emu, err := emulatorFromList(list) @@ -741,7 +740,6 @@ func testDeviceEmulatorApply(t *testing.T, baseDefaultAllow bool) { } for _, test := range tests { - test := test t.Run(test.name, func(t *testing.T) { err := test.base.Apply(test.rule) if err != nil && test.expected != nil { @@ -1058,7 +1056,6 @@ func testDeviceEmulatorTransition(t *testing.T, sourceDefaultAllow bool) { } for _, test := range tests { - test := test t.Run(test.name, func(t *testing.T) { // If we are in black-list mode, we need to prepend the relevant // clear-all rule (the expected rule lists are written with @@ -1130,7 +1127,7 @@ c 10:200 rwm` var r *deviceRule var err error - for i := 0; i < b.N; i++ { + for b.Loop() { s := bufio.NewScanner(strings.NewReader(list)) for s.Scan() { line := s.Text() diff --git a/devices/systemd_test.go b/devices/systemd_test.go index 2cbb5ca..3c9a8e6 100644 --- a/devices/systemd_test.go +++ b/devices/systemd_test.go @@ -256,7 +256,7 @@ func TestFindDeviceGroup(t *testing.T) { } func BenchmarkFindDeviceGroup(b *testing.B) { - for i := 0; i < b.N; i++ { + for b.Loop() { if err := testFindDeviceGroup(); err != nil { b.Fatal(err) } diff --git a/file_test.go b/file_test.go index 9c3bf18..2183f33 100644 --- a/file_test.go +++ b/file_test.go @@ -82,8 +82,7 @@ func BenchmarkWriteFile(b *testing.B) { "\n\n\n\n\n\n\n\n", } - b.ResetTimer() - for i := 0; i < b.N; i++ { + for b.Loop() { for _, val := range tc { if err := WriteFileByLine(dir, "file", val); err != nil { b.Fatal(err) diff --git a/fs/cpuacct.go b/fs/cpuacct.go index 391a023..48a016d 100644 --- a/fs/cpuacct.go +++ b/fs/cpuacct.go @@ -105,7 +105,7 @@ func getPercpuUsage(path string) ([]uint64, error) { if err != nil { return percpuUsage, err } - for _, value := range strings.Fields(data) { + for value := range strings.FieldsSeq(data) { value, err := strconv.ParseUint(value, 10, 64) if err != nil { return percpuUsage, &parseError{Path: path, File: file, Err: err} diff --git a/fs/cpuacct_test.go b/fs/cpuacct_test.go index c0c9543..73c6152 100644 --- a/fs/cpuacct_test.go +++ b/fs/cpuacct_test.go @@ -102,8 +102,7 @@ func BenchmarkGetCpuUsageBreakdown(b *testing.B) { "cpuacct.stat": cpuAcctStatContents, }) - b.ResetTimer() - for i := 0; i < b.N; i++ { + for b.Loop() { _, _, err := getCpuUsageBreakdown(path) if err != nil { b.Fatal(err) diff --git a/fs/cpuset.go b/fs/cpuset.go index ef6ff7d..f3f96df 100644 --- a/fs/cpuset.go +++ b/fs/cpuset.go @@ -82,7 +82,7 @@ func getCpusetStat(path string, file string) ([]uint16, error) { return extracted, &parseError{Path: path, File: file, Err: errors.New("empty file")} } - for _, s := range strings.Split(fileContent, ",") { + for s := range strings.SplitSeq(fileContent, ",") { fromStr, toStr, ok := strings.Cut(s, "-") if ok { from, err := strconv.ParseUint(fromStr, 10, 16) diff --git a/fs/fs_test.go b/fs/fs_test.go index f9a0935..331e9f1 100644 --- a/fs/fs_test.go +++ b/fs/fs_test.go @@ -36,8 +36,7 @@ func BenchmarkGetStats(b *testing.B) { var st *cgroups.Stats - b.ResetTimer() - for i := 0; i < b.N; i++ { + for b.Loop() { st, err = m.GetStats() if err != nil { b.Fatal(err) diff --git a/fs2/create.go b/fs2/create.go index 565ca88..6be11c2 100644 --- a/fs2/create.go +++ b/fs2/create.go @@ -28,7 +28,7 @@ func needAnyControllers(r *cgroups.Resources) (bool, error) { return false, err } avail := make(map[string]struct{}) - for _, ctr := range strings.Fields(content) { + for ctr := range strings.FieldsSeq(content) { avail[ctr] = struct{}{} } @@ -137,8 +137,7 @@ func CreateCgroupPath(path string, c *cgroups.Cgroup) (Err error) { if i < len(elements)-1 { if err := cgroups.WriteFile(current, cgStCtlFile, res); err != nil { // try write one by one - allCtrs := strings.Split(res, " ") - for _, ctr := range allCtrs { + for ctr := range strings.SplitSeq(res, " ") { _ = cgroups.WriteFile(current, cgStCtlFile, ctr) } } diff --git a/fscommon/utils.go b/fscommon/utils.go index d8f8dfc..a8b32aa 100644 --- a/fscommon/utils.go +++ b/fscommon/utils.go @@ -82,8 +82,7 @@ func GetValueByKey(path, file, key string) (uint64, error) { } key += " " - lines := strings.Split(content, "\n") - for _, line := range lines { + for line := range strings.SplitSeq(content, "\n") { v, ok := strings.CutPrefix(line, key) if ok { val, err := ParseUint(v, 10, 64) diff --git a/getallpids_test.go b/getallpids_test.go index e6b0632..125fa0a 100644 --- a/getallpids_test.go +++ b/getallpids_test.go @@ -6,7 +6,7 @@ import ( func BenchmarkGetAllPids(b *testing.B) { total := 0 - for i := 0; i < b.N; i++ { + for b.Loop() { i, err := GetAllPids("/sys/fs/cgroup") if err != nil { b.Fatal(err) diff --git a/go.mod b/go.mod index 946822e..6a4e266 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/opencontainers/cgroups -go 1.23.0 +go 1.24.0 require ( github.com/cilium/ebpf v0.17.3 diff --git a/stats.go b/stats.go index 0170133..debc2df 100644 --- a/stats.go +++ b/stats.go @@ -2,19 +2,19 @@ package cgroups type ThrottlingData struct { // Number of periods with throttling active - Periods uint64 `json:"periods,omitempty"` + Periods uint64 `json:"periods,omitzero"` // Number of periods when the container hit its throttling limit. - ThrottledPeriods uint64 `json:"throttled_periods,omitempty"` + ThrottledPeriods uint64 `json:"throttled_periods,omitzero"` // Aggregate time the container was throttled for in nanoseconds. - ThrottledTime uint64 `json:"throttled_time,omitempty"` + ThrottledTime uint64 `json:"throttled_time,omitzero"` } type BurstData struct { // Number of periods bandwidth burst occurs - BurstsPeriods uint64 `json:"bursts_periods,omitempty"` + BurstsPeriods uint64 `json:"bursts_periods,omitzero"` // Cumulative wall-time that any cpus has used above quota in respective periods // Units: nanoseconds. - BurstTime uint64 `json:"burst_time,omitempty"` + BurstTime uint64 `json:"burst_time,omitzero"` } // CpuUsage denotes the usage of a CPU. @@ -22,10 +22,10 @@ type BurstData struct { type CpuUsage struct { // Total CPU time consumed. // Units: nanoseconds. - TotalUsage uint64 `json:"total_usage,omitempty"` + TotalUsage uint64 `json:"total_usage,omitzero"` // Total CPU time consumed per core. // Units: nanoseconds. - PercpuUsage []uint64 `json:"percpu_usage,omitempty"` + PercpuUsage []uint64 `json:"percpu_usage,omitzero"` // CPU time consumed per core in kernel mode // Units: nanoseconds. PercpuUsageInKernelmode []uint64 `json:"percpu_usage_in_kernelmode"` @@ -48,26 +48,26 @@ type PSIData struct { } type PSIStats struct { - Some PSIData `json:"some,omitempty"` - Full PSIData `json:"full,omitempty"` + Some PSIData `json:"some,omitzero"` + Full PSIData `json:"full,omitzero"` } type CpuStats struct { - CpuUsage CpuUsage `json:"cpu_usage,omitempty"` - ThrottlingData ThrottlingData `json:"throttling_data,omitempty"` - PSI *PSIStats `json:"psi,omitempty"` - BurstData BurstData `json:"burst_data,omitempty"` + CpuUsage CpuUsage `json:"cpu_usage,omitzero"` + ThrottlingData ThrottlingData `json:"throttling_data,omitzero"` + PSI *PSIStats `json:"psi,omitzero"` + BurstData BurstData `json:"burst_data,omitzero"` } type CPUSetStats struct { // List of the physical numbers of the CPUs on which processes // in that cpuset are allowed to execute - CPUs []uint16 `json:"cpus,omitempty"` + CPUs []uint16 `json:"cpus,omitzero"` // cpu_exclusive flag CPUExclusive uint64 `json:"cpu_exclusive"` // List of memory nodes on which processes in that cpuset // are allowed to allocate memory - Mems []uint16 `json:"mems,omitempty"` + Mems []uint16 `json:"mems,omitzero"` // mem_hardwall flag MemHardwall uint64 `json:"mem_hardwall"` // mem_exclusive flag @@ -87,122 +87,122 @@ type CPUSetStats struct { } type MemoryData struct { - Usage uint64 `json:"usage,omitempty"` - MaxUsage uint64 `json:"max_usage,omitempty"` + Usage uint64 `json:"usage,omitzero"` + MaxUsage uint64 `json:"max_usage,omitzero"` Failcnt uint64 `json:"failcnt"` Limit uint64 `json:"limit"` } type MemoryStats struct { // memory used for cache - Cache uint64 `json:"cache,omitempty"` + Cache uint64 `json:"cache,omitzero"` // usage of memory - Usage MemoryData `json:"usage,omitempty"` + Usage MemoryData `json:"usage,omitzero"` // usage of memory + swap - SwapUsage MemoryData `json:"swap_usage,omitempty"` + SwapUsage MemoryData `json:"swap_usage,omitzero"` // usage of swap only - SwapOnlyUsage MemoryData `json:"swap_only_usage,omitempty"` + SwapOnlyUsage MemoryData `json:"swap_only_usage,omitzero"` // usage of kernel memory - KernelUsage MemoryData `json:"kernel_usage,omitempty"` + KernelUsage MemoryData `json:"kernel_usage,omitzero"` // usage of kernel TCP memory - KernelTCPUsage MemoryData `json:"kernel_tcp_usage,omitempty"` + KernelTCPUsage MemoryData `json:"kernel_tcp_usage,omitzero"` // usage of memory pages by NUMA node // see chapter 5.6 of memory controller documentation - PageUsageByNUMA PageUsageByNUMA `json:"page_usage_by_numa,omitempty"` + PageUsageByNUMA PageUsageByNUMA `json:"page_usage_by_numa,omitzero"` // if true, memory usage is accounted for throughout a hierarchy of cgroups. UseHierarchy bool `json:"use_hierarchy"` - Stats map[string]uint64 `json:"stats,omitempty"` - PSI *PSIStats `json:"psi,omitempty"` + Stats map[string]uint64 `json:"stats,omitzero"` + PSI *PSIStats `json:"psi,omitzero"` } type PageUsageByNUMA struct { // Embedding is used as types can't be recursive. PageUsageByNUMAInner - Hierarchical PageUsageByNUMAInner `json:"hierarchical,omitempty"` + Hierarchical PageUsageByNUMAInner `json:"hierarchical,omitzero"` } type PageUsageByNUMAInner struct { - Total PageStats `json:"total,omitempty"` - File PageStats `json:"file,omitempty"` - Anon PageStats `json:"anon,omitempty"` - Unevictable PageStats `json:"unevictable,omitempty"` + Total PageStats `json:"total,omitzero"` + File PageStats `json:"file,omitzero"` + Anon PageStats `json:"anon,omitzero"` + Unevictable PageStats `json:"unevictable,omitzero"` } type PageStats struct { - Total uint64 `json:"total,omitempty"` - Nodes map[uint8]uint64 `json:"nodes,omitempty"` + Total uint64 `json:"total,omitzero"` + Nodes map[uint8]uint64 `json:"nodes,omitzero"` } type PidsStats struct { // number of pids in the cgroup - Current uint64 `json:"current,omitempty"` + Current uint64 `json:"current,omitzero"` // active pids hard limit - Limit uint64 `json:"limit,omitempty"` + Limit uint64 `json:"limit,omitzero"` } type BlkioStatEntry struct { - Major uint64 `json:"major,omitempty"` - Minor uint64 `json:"minor,omitempty"` - Op string `json:"op,omitempty"` - Value uint64 `json:"value,omitempty"` + Major uint64 `json:"major,omitzero"` + Minor uint64 `json:"minor,omitzero"` + Op string `json:"op,omitzero"` + Value uint64 `json:"value,omitzero"` } type BlkioStats struct { // number of bytes transferred to and from the block device - IoServiceBytesRecursive []BlkioStatEntry `json:"io_service_bytes_recursive,omitempty"` - IoServicedRecursive []BlkioStatEntry `json:"io_serviced_recursive,omitempty"` - IoQueuedRecursive []BlkioStatEntry `json:"io_queue_recursive,omitempty"` - IoServiceTimeRecursive []BlkioStatEntry `json:"io_service_time_recursive,omitempty"` - IoWaitTimeRecursive []BlkioStatEntry `json:"io_wait_time_recursive,omitempty"` - IoMergedRecursive []BlkioStatEntry `json:"io_merged_recursive,omitempty"` - IoTimeRecursive []BlkioStatEntry `json:"io_time_recursive,omitempty"` - SectorsRecursive []BlkioStatEntry `json:"sectors_recursive,omitempty"` - PSI *PSIStats `json:"psi,omitempty"` - IoCostUsage []BlkioStatEntry `json:"io_cost_usage,omitempty"` - IoCostWait []BlkioStatEntry `json:"io_cost_wait,omitempty"` - IoCostIndebt []BlkioStatEntry `json:"io_cost_indebt,omitempty"` - IoCostIndelay []BlkioStatEntry `json:"io_cost_indelay,omitempty"` + IoServiceBytesRecursive []BlkioStatEntry `json:"io_service_bytes_recursive,omitzero"` + IoServicedRecursive []BlkioStatEntry `json:"io_serviced_recursive,omitzero"` + IoQueuedRecursive []BlkioStatEntry `json:"io_queue_recursive,omitzero"` + IoServiceTimeRecursive []BlkioStatEntry `json:"io_service_time_recursive,omitzero"` + IoWaitTimeRecursive []BlkioStatEntry `json:"io_wait_time_recursive,omitzero"` + IoMergedRecursive []BlkioStatEntry `json:"io_merged_recursive,omitzero"` + IoTimeRecursive []BlkioStatEntry `json:"io_time_recursive,omitzero"` + SectorsRecursive []BlkioStatEntry `json:"sectors_recursive,omitzero"` + PSI *PSIStats `json:"psi,omitzero"` + IoCostUsage []BlkioStatEntry `json:"io_cost_usage,omitzero"` + IoCostWait []BlkioStatEntry `json:"io_cost_wait,omitzero"` + IoCostIndebt []BlkioStatEntry `json:"io_cost_indebt,omitzero"` + IoCostIndelay []BlkioStatEntry `json:"io_cost_indelay,omitzero"` } type HugetlbStats struct { // current res_counter usage for hugetlb - Usage uint64 `json:"usage,omitempty"` + Usage uint64 `json:"usage,omitzero"` // maximum usage ever recorded. - MaxUsage uint64 `json:"max_usage,omitempty"` + MaxUsage uint64 `json:"max_usage,omitzero"` // number of times hugetlb usage allocation failure. Failcnt uint64 `json:"failcnt"` } type RdmaEntry struct { - Device string `json:"device,omitempty"` - HcaHandles uint32 `json:"hca_handles,omitempty"` - HcaObjects uint32 `json:"hca_objects,omitempty"` + Device string `json:"device,omitzero"` + HcaHandles uint32 `json:"hca_handles,omitzero"` + HcaObjects uint32 `json:"hca_objects,omitzero"` } type RdmaStats struct { - RdmaLimit []RdmaEntry `json:"rdma_limit,omitempty"` - RdmaCurrent []RdmaEntry `json:"rdma_current,omitempty"` + RdmaLimit []RdmaEntry `json:"rdma_limit,omitzero"` + RdmaCurrent []RdmaEntry `json:"rdma_current,omitzero"` } type MiscStats struct { // current resource usage for a key in misc - Usage uint64 `json:"usage,omitempty"` + Usage uint64 `json:"usage,omitzero"` // number of times the resource usage was about to go over the max boundary - Events uint64 `json:"events,omitempty"` + Events uint64 `json:"events,omitzero"` } type Stats struct { - CpuStats CpuStats `json:"cpu_stats,omitempty"` - CPUSetStats CPUSetStats `json:"cpuset_stats,omitempty"` - MemoryStats MemoryStats `json:"memory_stats,omitempty"` - PidsStats PidsStats `json:"pids_stats,omitempty"` - BlkioStats BlkioStats `json:"blkio_stats,omitempty"` + CpuStats CpuStats `json:"cpu_stats,omitzero"` + CPUSetStats CPUSetStats `json:"cpuset_stats,omitzero"` + MemoryStats MemoryStats `json:"memory_stats,omitzero"` + PidsStats PidsStats `json:"pids_stats,omitzero"` + BlkioStats BlkioStats `json:"blkio_stats,omitzero"` // the map is in the format "size of hugepage: stats of the hugepage" - HugetlbStats map[string]HugetlbStats `json:"hugetlb_stats,omitempty"` - RdmaStats RdmaStats `json:"rdma_stats,omitempty"` + HugetlbStats map[string]HugetlbStats `json:"hugetlb_stats,omitzero"` + RdmaStats RdmaStats `json:"rdma_stats,omitzero"` // the map is in the format "misc resource name: stats of the key" - MiscStats map[string]MiscStats `json:"misc_stats,omitempty"` + MiscStats map[string]MiscStats `json:"misc_stats,omitzero"` } func NewStats() *Stats { diff --git a/systemd/common.go b/systemd/common.go index 537defb..42083d0 100644 --- a/systemd/common.go +++ b/systemd/common.go @@ -77,7 +77,7 @@ func ExpandSlice(slice string) (string, error) { if sliceName == "-" { return "/", nil } - for _, component := range strings.Split(sliceName, "-") { + for component := range strings.SplitSeq(sliceName, "-") { // test--a.slice isn't permitted, nor is -test.slice. if component == "" { return "", fmt.Errorf("invalid slice name: %s", slice) diff --git a/systemd/cpuset.go b/systemd/cpuset.go index c6f5642..f260362 100644 --- a/systemd/cpuset.go +++ b/systemd/cpuset.go @@ -14,7 +14,7 @@ import ( func RangeToBits(str string) ([]byte, error) { bits := new(big.Int) - for _, r := range strings.Split(str, ",") { + for r := range strings.SplitSeq(str, ",") { // allow extra spaces around r = strings.TrimSpace(r) // allow empty elements (extra commas) diff --git a/systemd/freeze_test.go b/systemd/freeze_test.go index 35558a8..0f05137 100644 --- a/systemd/freeze_test.go +++ b/systemd/freeze_test.go @@ -131,7 +131,6 @@ func TestFreezeBeforeSet(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.desc, func(t *testing.T) { m, err := NewLegacyManager(tc.cg, nil) if err != nil { diff --git a/systemd/systemd_test.go b/systemd/systemd_test.go index 60a6c1f..156e55e 100644 --- a/systemd/systemd_test.go +++ b/systemd/systemd_test.go @@ -160,7 +160,6 @@ func TestUnifiedResToSystemdProps(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { if tc.minVer != 0 && systemdVersion(cm) < tc.minVer { t.Skipf("requires systemd >= %d", tc.minVer) diff --git a/utils.go b/utils.go index 95b3310..469475c 100644 --- a/utils.go +++ b/utils.go @@ -207,7 +207,7 @@ func parseCgroupFromReader(r io.Reader) (map[string]string, error) { return nil, fmt.Errorf("invalid cgroup entry: must contain at least two colons: %v", text) } - for _, subs := range strings.Split(parts[1], ",") { + for subs := range strings.SplitSeq(parts[1], ",") { cgroups[subs] = parts[2] } } diff --git a/utils_test.go b/utils_test.go index 79023b7..6de34d3 100644 --- a/utils_test.go +++ b/utils_test.go @@ -323,8 +323,8 @@ func BenchmarkGetCgroupMounts(b *testing.B) { if err != nil { b.Fatal(err) } - b.ResetTimer() - for i := 0; i < b.N; i++ { + + for b.Loop() { if _, err := getCgroupMountsHelper(subsystems, mi, false); err != nil { b.Fatal(err) } @@ -449,7 +449,7 @@ func BenchmarkGetHugePageSizeImpl(b *testing.B) { output []string err error ) - for i := 0; i < b.N; i++ { + for b.Loop() { output, err = getHugePageSizeFromFilenames(input) } if err != nil || len(output) != len(input) { @@ -512,7 +512,6 @@ func TestGetHugePageSizeImpl(t *testing.T) { } for _, c := range testCases { - c := c t.Run(c.doc, func(t *testing.T) { output, err := getHugePageSizeFromFilenames(c.input) t.Log("input:", c.input, "; output:", output, "; err:", err) @@ -639,7 +638,6 @@ func TestConvertMemorySwapToCgroupV2Value(t *testing.T) { } for _, c := range cases { - c := c t.Run(c.descr, func(t *testing.T) { swap, err := ConvertMemorySwapToCgroupV2Value(c.memswap, c.memory) if c.expErr { diff --git a/v1_utils.go b/v1_utils.go index 19b8af1..11025b2 100644 --- a/v1_utils.go +++ b/v1_utils.go @@ -170,7 +170,7 @@ func getCgroupMountsHelper(ss map[string]bool, mounts []*mountinfo.Info, all boo Mountpoint: mi.Mountpoint, Root: mi.Root, } - for _, opt := range strings.Split(mi.VFSOptions, ",") { + for opt := range strings.SplitSeq(mi.VFSOptions, ",") { seen, known := ss[opt] if !known || (!all && seen) { continue