Skip to content

Commit

Permalink
ecs_client/model, functional_tests: devices and init support
Browse files Browse the repository at this point in the history
This commit contains the model changes and functional tests for the new Task Definition fields-devices and initProcessEnabled.

This addresses the following issues:
* aws#433
* aws#852
  • Loading branch information
sharanyad committed Oct 6, 2017
1 parent a50aad7 commit 8cd474c
Show file tree
Hide file tree
Showing 7 changed files with 264 additions and 1 deletion.
29 changes: 28 additions & 1 deletion agent/ecs_client/model/api/api-2.json
Original file line number Diff line number Diff line change
Expand Up @@ -565,6 +565,18 @@
"type":"integer",
"box":true
},
"DeviceCgroupPermission":{
"type":"string",
"enum":[
"read",
"write",
"mknod"
]
},
"DeviceCgroupPermissions":{
"type":"list",
"member":{"shape":"DeviceCgroupPermission"}
},
"ClientException":{
"type":"structure",
"members":{
Expand Down Expand Up @@ -942,6 +954,19 @@
"STOPPED"
]
},
"Device":{
"type":"structure",
"required":["hostPath"],
"members":{
"hostPath":{"shape":"String"},
"containerPath":{"shape":"String"},
"permissions":{"shape":"DeviceCgroupPermissions"}
}
},
"DevicesList":{
"type":"list",
"member":{"shape":"Device"}
},
"DiscoverPollEndpointRequest":{
"type":"structure",
"members":{
Expand Down Expand Up @@ -1022,7 +1047,9 @@
"LinuxParameters":{
"type":"structure",
"members":{
"capabilities":{"shape":"KernelCapabilities"}
"capabilities":{"shape":"KernelCapabilities"},
"devices":{"shape":"DevicesList"},
"initProcessEnabled":{"shape":"BoxedBoolean"}
}
},
"ListAttributesRequest":{
Expand Down
104 changes: 104 additions & 0 deletions agent/ecs_client/model/ecs/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -4262,6 +4262,11 @@ func (s *ContainerDefinition) Validate() error {
}
}
}
if s.LinuxParameters != nil {
if err := s.LinuxParameters.Validate(); err != nil {
invalidParams.AddNested("LinuxParameters", err.(request.ErrInvalidParams))
}
}
if s.LogConfiguration != nil {
if err := s.LogConfiguration.Validate(); err != nil {
invalidParams.AddNested("LogConfiguration", err.(request.ErrInvalidParams))
Expand Down Expand Up @@ -5926,6 +5931,58 @@ func (s *DescribeTasksOutput) SetTasks(v []*Task) *DescribeTasksOutput {
return s
}

type Device struct {
_ struct{} `type:"structure"`

ContainerPath *string `locationName:"containerPath" type:"string"`

// HostPath is a required field
HostPath *string `locationName:"hostPath" type:"string" required:"true"`

Permissions []*string `locationName:"permissions" type:"list"`
}

// String returns the string representation
func (s Device) String() string {
return awsutil.Prettify(s)
}

// GoString returns the string representation
func (s Device) GoString() string {
return s.String()
}

// Validate inspects the fields of the type to determine if they are valid.
func (s *Device) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "Device"}
if s.HostPath == nil {
invalidParams.Add(request.NewErrParamRequired("HostPath"))
}

if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}

// SetContainerPath sets the ContainerPath field's value.
func (s *Device) SetContainerPath(v string) *Device {
s.ContainerPath = &v
return s
}

// SetHostPath sets the HostPath field's value.
func (s *Device) SetHostPath(v string) *Device {
s.HostPath = &v
return s
}

// SetPermissions sets the Permissions field's value.
func (s *Device) SetPermissions(v []*string) *Device {
s.Permissions = v
return s
}

type DiscoverPollEndpointInput struct {
_ struct{} `type:"structure"`

Expand Down Expand Up @@ -6219,6 +6276,10 @@ type LinuxParameters struct {
// The Linux capabilities for the container that are added to or dropped from
// the default configuration provided by Docker.
Capabilities *KernelCapabilities `locationName:"capabilities" type:"structure"`

Devices []*Device `locationName:"devices" type:"list"`

InitProcessEnabled *bool `locationName:"initProcessEnabled" type:"boolean"`
}

// String returns the string representation
Expand All @@ -6231,12 +6292,44 @@ func (s LinuxParameters) GoString() string {
return s.String()
}

// Validate inspects the fields of the type to determine if they are valid.
func (s *LinuxParameters) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "LinuxParameters"}
if s.Devices != nil {
for i, v := range s.Devices {
if v == nil {
continue
}
if err := v.Validate(); err != nil {
invalidParams.AddNested(fmt.Sprintf("%s[%v]", "Devices", i), err.(request.ErrInvalidParams))
}
}
}

if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}

// SetCapabilities sets the Capabilities field's value.
func (s *LinuxParameters) SetCapabilities(v *KernelCapabilities) *LinuxParameters {
s.Capabilities = v
return s
}

// SetDevices sets the Devices field's value.
func (s *LinuxParameters) SetDevices(v []*Device) *LinuxParameters {
s.Devices = v
return s
}

// SetInitProcessEnabled sets the InitProcessEnabled field's value.
func (s *LinuxParameters) SetInitProcessEnabled(v bool) *LinuxParameters {
s.InitProcessEnabled = &v
return s
}

type ListAttributesInput struct {
_ struct{} `type:"structure"`

Expand Down Expand Up @@ -9708,6 +9801,17 @@ const (
DesiredStatusStopped = "STOPPED"
)

const (
// DeviceCgroupPermissionRead is a DeviceCgroupPermission enum value
DeviceCgroupPermissionRead = "read"

// DeviceCgroupPermissionWrite is a DeviceCgroupPermission enum value
DeviceCgroupPermissionWrite = "write"

// DeviceCgroupPermissionMknod is a DeviceCgroupPermission enum value
DeviceCgroupPermissionMknod = "mknod"
)

const (
// LogDriverJsonFile is a LogDriver enum value
LogDriverJsonFile = "json-file"
Expand Down
10 changes: 10 additions & 0 deletions agent/functional_tests/testdata/simpletests_unix/devices.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"Name": "Devices",
"Description": "checks that adding devices works",
"TaskDefinition": "devices",
"Version": ">=1.0.0",
"Timeout": "2m",
"ExitCodes": {
"exit": 42
}
}
10 changes: 10 additions & 0 deletions agent/functional_tests/testdata/simpletests_unix/init-process.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"Name": "InitProcessEnabled",
"Description": "checks that enabling init process works",
"TaskDefinition": "init-process",
"Version": ">=1.14.5",
"Timeout": "2m",
"ExitCodes": {
"exit": 42
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"family": "ecsftest-devices",
"containerDefinitions": [{
"image": "127.0.0.1:51670/ubuntu:latest",
"name": "exit",
"cpu": 10,
"memory": 10,
"linuxParameters": {
"devices":[
{
"hostPath": "/dev/xvda",
"containerPath": "/dev/sda",
"permissions": ["read"]
}
]
},
"command": ["sh", "-c", "if ls /dev/sda && ! fdisk /dev/sda; then exit 42; else exit 1; fi"]
}]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"family": "ecsftest-init-process",
"containerDefinitions": [{
"image": "127.0.0.1:51670/ubuntu:latest",
"name": "exit",
"cpu": 10,
"memory": 10,
"linuxParameters": {
"initProcessEnabled":true
},
"command": ["sh", "-c", "if pidof init == 1; then exit 42; else exit 1; fi"]
}]
}
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,46 @@ func TestDataVolume2(t *testing.T) {

}

// TestDevices checks that adding devices works
func TestDevices(t *testing.T) {

// Parallel is opt in because resource constraints could cause test failures
// on smaller instances
if os.Getenv("ECS_FUNCTIONAL_PARALLEL") != "" {
t.Parallel()
}
agent := RunAgent(t, nil)
defer agent.Cleanup()
agent.RequireVersion(">=1.0.0")

td, err := GetTaskDefinition("devices")
if err != nil {
t.Fatalf("Could not register task definition: %v", err)
}
testTasks, err := agent.StartMultipleTasks(t, td, 1)
if err != nil {
t.Fatalf("Could not start task: %v", err)
}
timeout, err := time.ParseDuration("2m")
if err != nil {
t.Fatalf("Could not parse timeout: %#v", err)
}

for _, testTask := range testTasks {
err = testTask.WaitStopped(timeout)
if err != nil {
t.Fatalf("Timed out waiting for task to reach stopped. Error %#v, task %#v", err, testTask)
}

if exit, ok := testTask.ContainerExitcode("exit"); !ok || exit != 42 {
t.Errorf("Expected exit to exit with 42; actually exited (%v) with %v", ok, exit)
}

defer agent.SweepTask(testTask)
}

}

// TestDisableNetworking Check that disable networking works
func TestDisableNetworking(t *testing.T) {

Expand Down Expand Up @@ -347,6 +387,46 @@ func TestHostname(t *testing.T) {

}

// TestInitProcessEnabled checks that enabling init process works
func TestInitProcessEnabled(t *testing.T) {

// Parallel is opt in because resource constraints could cause test failures
// on smaller instances
if os.Getenv("ECS_FUNCTIONAL_PARALLEL") != "" {
t.Parallel()
}
agent := RunAgent(t, nil)
defer agent.Cleanup()
agent.RequireVersion(">=1.14.5")

td, err := GetTaskDefinition("init-process")
if err != nil {
t.Fatalf("Could not register task definition: %v", err)
}
testTasks, err := agent.StartMultipleTasks(t, td, 1)
if err != nil {
t.Fatalf("Could not start task: %v", err)
}
timeout, err := time.ParseDuration("2m")
if err != nil {
t.Fatalf("Could not parse timeout: %#v", err)
}

for _, testTask := range testTasks {
err = testTask.WaitStopped(timeout)
if err != nil {
t.Fatalf("Timed out waiting for task to reach stopped. Error %#v, task %#v", err, testTask)
}

if exit, ok := testTask.ContainerExitcode("exit"); !ok || exit != 42 {
t.Errorf("Expected exit to exit with 42; actually exited (%v) with %v", ok, exit)
}

defer agent.SweepTask(testTask)
}

}

// TestLinkVolumeDependencies Tests that the dependency graph of task definitions is resolved correctly
func TestLinkVolumeDependencies(t *testing.T) {

Expand Down

0 comments on commit 8cd474c

Please sign in to comment.