Skip to content

Commit 960ef05

Browse files
authored
Merge pull request #267 from AkihiroSuda/expose-ParseCgroupFileUnified
move ParseCgroupFileUnified from v3/cgroup1 to v3
2 parents ed5fd67 + 7a0d60d commit 960ef05

File tree

4 files changed

+100
-65
lines changed

4 files changed

+100
-65
lines changed

cgroup1/paths_test.go

+3-29
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ import (
2121
"path/filepath"
2222
"strings"
2323
"testing"
24+
25+
"github.com/containerd/cgroups/v3"
2426
)
2527

2628
func TestStaticPath(t *testing.T) {
@@ -89,34 +91,6 @@ func TestRootPath(t *testing.T) {
8991
}
9092
}
9193

92-
func TestEmptySubsystem(t *testing.T) {
93-
const data = `10:devices:/user.slice
94-
9:net_cls,net_prio:/
95-
8:blkio:/
96-
7:freezer:/
97-
6:perf_event:/
98-
5:cpuset:/
99-
4:memory:/
100-
3:pids:/user.slice/user-1000.slice/user@1000.service
101-
2:cpu,cpuacct:/
102-
1:name=systemd:/user.slice/user-1000.slice/user@1000.service/gnome-terminal-server.service
103-
0::/user.slice/user-1000.slice/user@1000.service/gnome-terminal-server.service`
104-
r := strings.NewReader(data)
105-
paths, unified, err := parseCgroupFromReaderUnified(r)
106-
if err != nil {
107-
t.Fatal(err)
108-
}
109-
for subsystem, path := range paths {
110-
if subsystem == "" {
111-
t.Fatalf("empty subsystem for %q", path)
112-
}
113-
}
114-
unifiedExpected := "/user.slice/user-1000.slice/user@1000.service/gnome-terminal-server.service"
115-
if unified != unifiedExpected {
116-
t.Fatalf("expected %q, got %q", unifiedExpected, unified)
117-
}
118-
}
119-
12094
func TestSystemd240(t *testing.T) {
12195
if isUnified {
12296
t.Skipf("requires the system to be running in legacy mode")
@@ -131,7 +105,7 @@ func TestSystemd240(t *testing.T) {
131105
1:name=systemd:/system.slice/docker.service
132106
0::/system.slice/docker.service`
133107
r := strings.NewReader(data)
134-
paths, unified, err := parseCgroupFromReaderUnified(r)
108+
paths, unified, err := cgroups.ParseCgroupFromReaderUnified(r)
135109
if err != nil {
136110
t.Fatal(err)
137111
}

cgroup1/utils.go

+4-36
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ package cgroup1
1919
import (
2020
"bufio"
2121
"fmt"
22-
"io"
2322
"os"
2423
"path/filepath"
2524
"strconv"
@@ -180,49 +179,18 @@ func parseKV(raw string) (string, uint64, error) {
180179
// etc.
181180
//
182181
// The resulting map does not have an element for cgroup v2 unified hierarchy.
183-
// Use ParseCgroupFileUnified to get the unified path.
182+
// Use [cgroups.ParseCgroupFileUnified] to get the unified path.
184183
func ParseCgroupFile(path string) (map[string]string, error) {
185184
x, _, err := ParseCgroupFileUnified(path)
186185
return x, err
187186
}
188187

189188
// ParseCgroupFileUnified returns legacy subsystem paths as the first value,
190189
// and returns the unified path as the second value.
190+
//
191+
// Deprecated: use [cgroups.ParseCgroupFileUnified] instead .
191192
func ParseCgroupFileUnified(path string) (map[string]string, string, error) {
192-
f, err := os.Open(path)
193-
if err != nil {
194-
return nil, "", err
195-
}
196-
defer f.Close()
197-
return parseCgroupFromReaderUnified(f)
198-
}
199-
200-
func parseCgroupFromReaderUnified(r io.Reader) (map[string]string, string, error) {
201-
var (
202-
cgroups = make(map[string]string)
203-
unified = ""
204-
s = bufio.NewScanner(r)
205-
)
206-
for s.Scan() {
207-
var (
208-
text = s.Text()
209-
parts = strings.SplitN(text, ":", 3)
210-
)
211-
if len(parts) < 3 {
212-
return nil, unified, fmt.Errorf("invalid cgroup entry: %q", text)
213-
}
214-
for _, subs := range strings.Split(parts[1], ",") {
215-
if subs == "" {
216-
unified = parts[2]
217-
} else {
218-
cgroups[subs] = parts[2]
219-
}
220-
}
221-
}
222-
if err := s.Err(); err != nil {
223-
return nil, unified, err
224-
}
225-
return cgroups, unified, nil
193+
return cgroups.ParseCgroupFileUnified(path)
226194
}
227195

228196
func getCgroupDestination(subsystem string) (string, error) {

utils.go

+43
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@ package cgroups
1919
import (
2020
"bufio"
2121
"fmt"
22+
"io"
2223
"os"
2324
"path/filepath"
25+
"strings"
2426
"sync"
2527

2628
"golang.org/x/sys/unix"
@@ -105,3 +107,44 @@ func RunningInUserNS() bool {
105107
})
106108
return inUserNS
107109
}
110+
111+
// ParseCgroupFileUnified returns legacy subsystem paths as the first value,
112+
// and returns the unified path as the second value.
113+
func ParseCgroupFileUnified(path string) (map[string]string, string, error) {
114+
f, err := os.Open(path)
115+
if err != nil {
116+
return nil, "", err
117+
}
118+
defer f.Close()
119+
return ParseCgroupFromReaderUnified(f)
120+
}
121+
122+
// ParseCgroupFromReaderUnified returns legacy subsystem paths as the first value,
123+
// and returns the unified path as the second value.
124+
func ParseCgroupFromReaderUnified(r io.Reader) (map[string]string, string, error) {
125+
var (
126+
cgroups = make(map[string]string)
127+
unified = ""
128+
s = bufio.NewScanner(r)
129+
)
130+
for s.Scan() {
131+
var (
132+
text = s.Text()
133+
parts = strings.SplitN(text, ":", 3)
134+
)
135+
if len(parts) < 3 {
136+
return nil, unified, fmt.Errorf("invalid cgroup entry: %q", text)
137+
}
138+
for _, subs := range strings.Split(parts[1], ",") {
139+
if subs == "" {
140+
unified = parts[2]
141+
} else {
142+
cgroups[subs] = parts[2]
143+
}
144+
}
145+
}
146+
if err := s.Err(); err != nil {
147+
return nil, unified, err
148+
}
149+
return cgroups, unified, nil
150+
}

utils_test.go

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
Copyright The containerd Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package cgroups
18+
19+
import (
20+
"strings"
21+
"testing"
22+
)
23+
24+
func TestParseCgroupFromReaderUnified(t *testing.T) {
25+
const data = `10:devices:/user.slice
26+
9:net_cls,net_prio:/
27+
8:blkio:/
28+
7:freezer:/
29+
6:perf_event:/
30+
5:cpuset:/
31+
4:memory:/
32+
3:pids:/user.slice/user-1000.slice/user@1000.service
33+
2:cpu,cpuacct:/
34+
1:name=systemd:/user.slice/user-1000.slice/user@1000.service/gnome-terminal-server.service
35+
0::/user.slice/user-1000.slice/user@1000.service/gnome-terminal-server.service`
36+
r := strings.NewReader(data)
37+
paths, unified, err := ParseCgroupFromReaderUnified(r)
38+
if err != nil {
39+
t.Fatal(err)
40+
}
41+
for subsystem, path := range paths {
42+
if subsystem == "" {
43+
t.Fatalf("empty subsystem for %q", path)
44+
}
45+
}
46+
unifiedExpected := "/user.slice/user-1000.slice/user@1000.service/gnome-terminal-server.service"
47+
if unified != unifiedExpected {
48+
t.Fatalf("expected %q, got %q", unifiedExpected, unified)
49+
}
50+
}

0 commit comments

Comments
 (0)