Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Unified Cgroups (cgroups v2) (#3127) #3161

Merged
merged 1 commit into from
Apr 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 23 additions & 2 deletions agent/api/task/task_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,34 @@ func (task *Task) initializeCgroupResourceSpec(cgroupPath string, cGroupCPUPerio
}

// BuildCgroupRoot helps build the task cgroup prefix
// Example: /ecs/task-id
// Example v1: /ecs/task-id
// Example v2: ecstasks-$TASKID.slice
func (task *Task) BuildCgroupRoot() (string, error) {
taskID, err := utils.TaskIdFromArn(task.Arn)
if err != nil {
return "", err
}
return filepath.Join(config.DefaultTaskCgroupPrefix, taskID), nil

if config.CgroupV2 {
return buildCgroupV2Root(taskID), nil
}
return buildCgroupV1Root(taskID), nil
}

func buildCgroupV1Root(taskID string) string {
return filepath.Join(config.DefaultTaskCgroupV1Prefix, taskID)
}

// buildCgroupV2Root creates a root cgroup using the systemd driver's special "-"
// character. The "-" specifies a parent slice, so tasks and their containers end up
// looking like this in the cgroup directory:
// /sys/fs/cgroup/ecstasks.slice/
// ├── ecstasks-XXXXf406f70c4c678073ae96944fXXXX.slice
// │ └── docker-XXXX7c6dc81f2e9a8bf1c566dc769733ccba594b3007dd289a0f50ad7923XXXX.scope
// └── ecstasks-XXXX30467358463ab6bbba4e73afXXXX.slice
// └── docker-XXXX7ef4e942552437c96051356859c1df169f16e1cf9a9fc96fd30614e6XXXX.scope
func buildCgroupV2Root(taskID string) string {
return fmt.Sprintf("%s-%s.slice", config.DefaultTaskCgroupV2Prefix, taskID)
}

// BuildLinuxResourceSpec returns a linuxResources object for the task cgroup
Expand Down
10 changes: 10 additions & 0 deletions agent/api/task/task_linux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,16 @@ func TestBuildCgroupRootErrorPath(t *testing.T) {
assert.Empty(t, cgroupRoot)
}

func TestBuildCgroupV1Root(t *testing.T) {
cgroupRoot := buildCgroupV1Root("111mytaskid")
assert.Equal(t, "/ecs/111mytaskid", cgroupRoot)
}

func TestBuildCgroupV2Root(t *testing.T) {
cgroupRoot := buildCgroupV2Root("111mytaskid")
assert.Equal(t, "ecstasks-111mytaskid.slice", cgroupRoot)
}

// TestBuildLinuxResourceSpecCPUMem validates the linux resource spec builder
func TestBuildLinuxResourceSpecCPUMem(t *testing.T) {
taskMemoryLimit := int64(taskMemoryLimit)
Expand Down
3 changes: 3 additions & 0 deletions agent/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,9 @@ var (
// DefaultPauseContainerTag is the tag for the pause container image. The linker's load
// flags are used to populate this value from the Makefile
DefaultPauseContainerTag = ""

// CgroupV2 Specifies whether or not to run in Cgroups V2 mode.
CgroupV2 = false
)

// Merge merges two config files, preferring the ones on the left. Any nil or
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,14 @@
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.

package control
package config

import (
"github.com/aws/amazon-ecs-agent/agent/config"
"github.com/aws/amazon-ecs-agent/agent/logger"

specs "github.com/opencontainers/runtime-spec/specs-go"
"github.com/containerd/cgroups"
)

// Init is used to setup the cgroup root for ecs
func (c *control) Init() error {
logger.Info("Creating root ecs cgroup", logger.Fields{
"cgroup": config.DefaultTaskCgroupPrefix,
})

// Build cgroup spec
cgroupSpec := &Spec{
Root: config.DefaultTaskCgroupPrefix,
Specs: &specs.LinuxResources{},
func init() {
if cgroups.Mode() == cgroups.Unified {
CgroupV2 = true
}
_, err := c.Create(cgroupSpec)
return err
}
9 changes: 7 additions & 2 deletions agent/config/config_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,13 @@ const (
// defaultRuntimeStatsLogFile stores the path where the golang runtime stats are periodically logged
defaultRuntimeStatsLogFile = `/log/agent-runtime-stats.log`

// DefaultTaskCgroupPrefix is default cgroup prefix for ECS tasks
DefaultTaskCgroupPrefix = "/ecs"
// DefaultTaskCgroupV1Prefix is default cgroup v1 prefix for ECS tasks
DefaultTaskCgroupV1Prefix = "/ecs"
// DefaultTaskCgroupV2Prefix is default cgroup v2 prefix for ECS tasks
// ecstasks is used because this creates a systemd "slice", and using just
// ecs would create a confusing name conflict with the ecs systemd service.
// (we would have both ecs.service and ecs.slice in /sys/fs/cgroup).
DefaultTaskCgroupV2Prefix = "ecstasks"

// Default cgroup memory system root path, this is the default used if the
// path has not been configured through ECS_CGROUP_PATH
Expand Down
6 changes: 3 additions & 3 deletions agent/engine/docker_task_engine_linux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ func TestResourceContainerProgression(t *testing.T) {
gomock.InOrder(
// Ensure that the resource is created first
mockControl.EXPECT().Exists(gomock.Any()).Return(false),
mockControl.EXPECT().Create(gomock.Any()).Return(nil, nil),
mockControl.EXPECT().Create(gomock.Any()).Return(nil),
mockIO.EXPECT().WriteFile(cgroupMemoryPath, gomock.Any(), gomock.Any()).Return(nil),
imageManager.EXPECT().AddAllImageStates(gomock.Any()).AnyTimes(),
client.EXPECT().PullImage(gomock.Any(), sleepContainer.Image, nil, gomock.Any()).Return(dockerapi.DockerContainerMetadata{}),
Expand Down Expand Up @@ -263,7 +263,7 @@ func TestResourceContainerProgressionFailure(t *testing.T) {
gomock.InOrder(
// resource creation failure
mockControl.EXPECT().Exists(gomock.Any()).Return(false),
mockControl.EXPECT().Create(gomock.Any()).Return(nil, errors.New("cgroup create error")),
mockControl.EXPECT().Create(gomock.Any()).Return(errors.New("cgroup create error")),
)
mockTime.EXPECT().Now().Return(time.Now()).AnyTimes()

Expand Down Expand Up @@ -345,7 +345,7 @@ func TestTaskCPULimitHappyPath(t *testing.T) {
},
}
mockControl.EXPECT().Exists(gomock.Any()).Return(false)
mockControl.EXPECT().Create(gomock.Any()).Return(nil, nil)
mockControl.EXPECT().Create(gomock.Any()).Return(nil)
mockIO.EXPECT().WriteFile(cgroupMemoryPath, gomock.Any(), gomock.Any()).Return(nil)
}

Expand Down
2 changes: 1 addition & 1 deletion agent/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ require (
github.com/aws/aws-sdk-go v1.36.0
github.com/awslabs/go-config-generator-for-fluentd-and-fluentbit v0.0.0-20190829210224-55d4fd2e6f35
github.com/cihub/seelog v0.0.0-20170130134532-f561c5e57575
github.com/containerd/cgroups v1.0.3
github.com/containerd/cgroups v1.0.4-0.20220221221032-e710ed6ebb1a
github.com/containerd/containerd v1.4.12 // indirect
github.com/containerd/continuity v0.0.0-20181023183536-c220ac4f01b8 // indirect
github.com/containernetworking/cni v0.7.1
Expand Down
10 changes: 10 additions & 0 deletions agent/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,16 @@ github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cihub/seelog v0.0.0-20170130134532-f561c5e57575 h1:kHaBemcxl8o/pQ5VM1c8PVE1PubbNx3mjUr09OqWGCs=
github.com/cihub/seelog v0.0.0-20170130134532-f561c5e57575/go.mod h1:9d6lWj8KzO/fd/NrVaLscBKmPigpZpn5YawRPw+e3Yo=
github.com/cilium/ebpf v0.4.0 h1:QlHdikaxALkqWasW8hAC1mfR0jdmvbfaBdBPFmRSglA=
github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/containerd/cgroups v1.0.3 h1:ADZftAkglvCiD44c77s5YmMqaP2pzVCFZvBmAlBdAP4=
github.com/containerd/cgroups v1.0.3/go.mod h1:/ofk34relqNjSGyqPrmEULrO4Sc8LJhvJmWbUCUKqj8=
github.com/containerd/cgroups v1.0.4-0.20220217190539-cf1b326d3714 h1:jCXPr1wkugK8p7oEQjuP8hBB7Q8Abq3w4ELsSs/0IwU=
github.com/containerd/cgroups v1.0.4-0.20220217190539-cf1b326d3714/go.mod h1:/ofk34relqNjSGyqPrmEULrO4Sc8LJhvJmWbUCUKqj8=
github.com/containerd/cgroups v1.0.4-0.20220221221032-e710ed6ebb1a h1:e956Q1zTD3IIKTQPWb92C20PvU3S2ohP9jWqqD0JJWE=
github.com/containerd/cgroups v1.0.4-0.20220221221032-e710ed6ebb1a/go.mod h1:/ofk34relqNjSGyqPrmEULrO4Sc8LJhvJmWbUCUKqj8=
github.com/containerd/containerd v1.4.12 h1:V+SHzYmhng/iju6M5nFrpTTusrhidoxKTwdwLw+u4c4=
github.com/containerd/containerd v1.4.12/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
github.com/containerd/continuity v0.0.0-20181023183536-c220ac4f01b8 h1:lJeDcldQnYskl7krc3lTppg8NKomoQkmQg1AzOXtQbA=
Expand Down Expand Up @@ -62,6 +67,7 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/frankban/quicktest v1.11.3 h1:8sXhOn0uLys67V8EsXLc6eszDs8VXWxL3iRvebPhedY=
github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
Expand Down Expand Up @@ -102,8 +108,10 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGi
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
Expand Down Expand Up @@ -156,13 +164,15 @@ github.com/vishvananda/netns v0.0.0-20171111001504-be1fbeda1936 h1:J9gO8RJCAFlln
github.com/vishvananda/netns v0.0.0-20171111001504-be1fbeda1936/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI=
go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU=
go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4=
go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA=
go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3 h1:f4/ZD59VsBOaJmWeI2yqtHvJhmRRPzi73C88ZtfhAIk=
golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/net v0.0.0-20191204025024-5ee1b9f4859a h1:+HHJiFUXVOIS9mr1ThqkQD1N8vpFCfCShqADBM12KTc=
golang.org/x/net v0.0.0-20191204025024-5ee1b9f4859a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
Expand Down
14 changes: 11 additions & 3 deletions agent/stats/utils_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package stats
import (
"fmt"

"github.com/aws/amazon-ecs-agent/agent/config"
"github.com/cihub/seelog"
"github.com/docker/docker/api/types"
)
Expand All @@ -39,9 +40,16 @@ func dockerStatsToContainerStats(dockerStats *types.StatsJSON) (*ContainerStats,
}

func validateDockerStats(dockerStats *types.StatsJSON) error {
// The length of PercpuUsage represents the number of cores in an instance.
if len(dockerStats.CPUStats.CPUUsage.PercpuUsage) == 0 || numCores == uint64(0) {
return fmt.Errorf("invalid container statistics reported, no cpu core usage reported")
if config.CgroupV2 {
// PercpuUsage is not available in cgroupv2
if numCores == uint64(0) {
return fmt.Errorf("invalid number of cores returned from runtime.NumCPU, numCores=0")
}
} else {
// The length of PercpuUsage represents the number of cores in an instance.
if len(dockerStats.CPUStats.CPUUsage.PercpuUsage) == 0 || numCores == uint64(0) {
return fmt.Errorf("invalid container statistics reported, no cpu core usage reported")
}
}
return nil
}
Expand Down
7 changes: 4 additions & 3 deletions agent/stats/utils_unix_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,9 @@ func TestDockerStatsToContainerStatsEmptyCpuUsageGeneratesError(t *testing.T) {
jsonBytes, _ := ioutil.ReadFile(inputJsonFile)
dockerStat := &types.StatsJSON{}
json.Unmarshal([]byte(jsonBytes), dockerStat)
// empty the PercpuUsage array
dockerStat.CPUStats.CPUUsage.PercpuUsage = make([]uint64, 0)
prevNumCores := numCores
numCores = uint64(0)
err := validateDockerStats(dockerStat)
assert.Error(t, err, "expected error converting container stats with empty PercpuUsage")
assert.Error(t, err, "expected error converting container stats with numCores=0")
numCores = prevNumCores
}
29 changes: 17 additions & 12 deletions agent/taskresource/cgroup/cgroup.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
apicontainer "github.com/aws/amazon-ecs-agent/agent/api/container"
apicontainerstatus "github.com/aws/amazon-ecs-agent/agent/api/container/status"
"github.com/aws/amazon-ecs-agent/agent/api/task/status"
"github.com/aws/amazon-ecs-agent/agent/config"
"github.com/aws/amazon-ecs-agent/agent/taskresource"
control "github.com/aws/amazon-ecs-agent/agent/taskresource/cgroup/control"
resourcestatus "github.com/aws/amazon-ecs-agent/agent/taskresource/status"
Expand Down Expand Up @@ -71,12 +72,14 @@ type CgroupResource struct {
}

// NewCgroupResource is used to return an object that implements the Resource interface
func NewCgroupResource(taskARN string,
func NewCgroupResource(
taskARN string,
control control.Control,
ioutil ioutilwrapper.IOUtil,
cgroupRoot string,
cgroupMountPath string,
resourceSpec specs.LinuxResources) *CgroupResource {
resourceSpec specs.LinuxResources,
) *CgroupResource {
c := &CgroupResource{
taskARN: taskARN,
control: control,
Expand Down Expand Up @@ -256,18 +259,17 @@ func (cgroup *CgroupResource) GetCreatedAt() time.Time {
func (cgroup *CgroupResource) Create() error {
err := cgroup.setupTaskCgroup()
if err != nil {
seelog.Criticalf("Cgroup resource [%s]: unable to setup cgroup root: %v", cgroup.taskARN, err)
// this error is already formatted in setupTaskCgroup function
return err
}
return nil
}

func (cgroup *CgroupResource) setupTaskCgroup() error {
cgroupRoot := cgroup.cgroupRoot
seelog.Debugf("Cgroup resource [%s]: setting up cgroup at: %s", cgroup.taskARN, cgroupRoot)

if cgroup.control.Exists(cgroupRoot) {
seelog.Debugf("Cgroup resource [%s]: cgroup at %s already exists, skipping creation", cgroup.taskARN, cgroupRoot)
seelog.Debugf("Cgroup already exists, skipping creation taskARN=%s cgroupPath=%s cgroupV2=%v", cgroup.taskARN, cgroupRoot, config.CgroupV2)
return nil
}

Expand All @@ -276,16 +278,19 @@ func (cgroup *CgroupResource) setupTaskCgroup() error {
Specs: &cgroup.resourceSpec,
}

_, err := cgroup.control.Create(&cgroupSpec)
seelog.Infof("Creating task cgroup taskARN=%s cgroupPath=%s cgroupV2=%v", cgroup.taskARN, cgroupRoot, config.CgroupV2)
err := cgroup.control.Create(&cgroupSpec)
if err != nil {
return fmt.Errorf("cgroup resource [%s]: setup cgroup: unable to create cgroup at %s: %w", cgroup.taskARN, cgroupRoot, err)
return fmt.Errorf("cgroup resource: setup cgroup: unable to create cgroup taskARN=%s cgroupPath=%s cgroupV2=%v err=%s", cgroup.taskARN, cgroupRoot, config.CgroupV2, err)
}

// enabling cgroup memory hierarchy by doing 'echo 1 > memory.use_hierarchy'
memoryHierarchyPath := filepath.Join(cgroup.cgroupMountPath, memorySubsystem, cgroupRoot, memoryUseHierarchy)
err = cgroup.ioutil.WriteFile(memoryHierarchyPath, enableMemoryHierarchy, rootReadOnlyPermissions)
if err != nil {
return fmt.Errorf("cgroup resource [%s]: setup cgroup: unable to set use hierarchy flag: %w", cgroup.taskARN, err)
if !config.CgroupV2 {
// enabling cgroup memory hierarchy by doing 'echo 1 > memory.use_hierarchy'
memoryHierarchyPath := filepath.Join(cgroup.cgroupMountPath, memorySubsystem, cgroupRoot, memoryUseHierarchy)
err = cgroup.ioutil.WriteFile(memoryHierarchyPath, enableMemoryHierarchy, rootReadOnlyPermissions)
if err != nil {
return fmt.Errorf("cgroup resource: setup cgroup: unable to set use hierarchy flag taskARN=%s cgroupPath=%s cgroupV2=%v err=%s", cgroup.taskARN, cgroupRoot, config.CgroupV2, err)
}
}

return nil
Expand Down
6 changes: 2 additions & 4 deletions agent/taskresource/cgroup/cgroup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import (
"time"

cgroup "github.com/aws/amazon-ecs-agent/agent/taskresource/cgroup/control"
mock_cgroups "github.com/aws/amazon-ecs-agent/agent/taskresource/cgroup/control/factory/mock"
"github.com/aws/amazon-ecs-agent/agent/taskresource/cgroup/control/mock_control"
resourcestatus "github.com/aws/amazon-ecs-agent/agent/taskresource/status"
mock_ioutilwrapper "github.com/aws/amazon-ecs-agent/agent/utils/ioutilwrapper/mocks"
Expand Down Expand Up @@ -53,7 +52,7 @@ func TestCreateHappyPath(t *testing.T) {

gomock.InOrder(
mockControl.EXPECT().Exists(gomock.Any()).Return(false),
mockControl.EXPECT().Create(gomock.Any()).Return(nil, nil),
mockControl.EXPECT().Create(gomock.Any()).Return(nil),
mockIO.EXPECT().WriteFile(cgroupMemoryPath, gomock.Any(), gomock.Any()).Return(nil),
)
cgroupResource := NewCgroupResource("taskArn", mockControl, mockIO, cgroupRoot, cgroupMountPath, specs.LinuxResources{})
Expand Down Expand Up @@ -83,13 +82,12 @@ func TestCreateCgroupError(t *testing.T) {

mockControl := mock_control.NewMockControl(ctrl)
mockIO := mock_ioutilwrapper.NewMockIOUtil(ctrl)
mockCgroup := mock_cgroups.NewMockCgroup(ctrl)

cgroupRoot := fmt.Sprintf("/ecs/%s", taskID)

gomock.InOrder(
mockControl.EXPECT().Exists(gomock.Any()).Return(false),
mockControl.EXPECT().Create(gomock.Any()).Return(mockCgroup, errors.New("cgroup create error")),
mockControl.EXPECT().Create(gomock.Any()).Return(errors.New("cgroup create error")),
)

cgroupResource := NewCgroupResource("taskArn", mockControl, mockIO, cgroupRoot, cgroupMountPath, specs.LinuxResources{})
Expand Down
Loading