Skip to content

Commit 3a1a09d

Browse files
committed
Introduce ECS_PAUSE_LABELS env var to apply labels to pause container (#4427)
1 parent a94a6db commit 3a1a09d

File tree

3 files changed

+127
-3
lines changed

3 files changed

+127
-3
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,7 @@ Additionally, the following environment variable(s) can be used to configure the
267267
| `ECS_ALLOW_OFFHOST_INTROSPECTION_ACCESS` | <true | false> | By default, the ecs-init service adds an iptable rule to block access to ECS Agent's introspection port from off-host (or containers in awsvpc network mode), and removes the rule upon stop. If `ECS_ALLOW_OFFHOST_INTROSPECTION_ACCESS` is set to true, this rule will not be added/removed. | false |
268268
| `ECS_OFFHOST_INTROSPECTION_INTERFACE_NAME` | `eth0` | Primary network interface name to be used for blocking offhost agent introspection port access. By default, this value is `eth0` | `eth0` |
269269
| `ECS_AGENT_LABELS` | `{"test.label.1":"value1","test.label.2":"value2"}` | The labels to add to the ECS Agent container. | |
270+
| `ECS_PAUSE_LABELS` | `{"test.pause.label.1":"value1","test.pause.label.2":"value2"}` | The labels to add to the pause container. | |
270271
| `ECS_AGENT_APPARMOR_PROFILE` | `unconfined` | Specifies the name of the AppArmor profile to run the ecs-agent container under. This only applies to AppArmor-enabled systems, such as Ubuntu, Debian, and SUSE. If unset, defaults to the profile written out by ecs-init (ecs-agent-default). | `ecs-agent-default` |
271272
| `ECS_AGENT_PID_NAMESPACE_HOST` | <true | false> | By default, the ECS agent container runs with its own PID namespace. If ECS_AGENT_PID_NAMESPACE_HOST is set to true, ecs-init will start the ECS agent container with the host's PID namespace. This is particularly useful when running on SELinux-enforcing hosts with Docker's SELinux option enabled. | false |
272273

agent/api/task/task.go

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"context"
1818
"encoding/json"
1919
"fmt"
20+
"os"
2021
"path/filepath"
2122
"reflect"
2223
"strconv"
@@ -55,6 +56,7 @@ import (
5556
"github.com/aws/amazon-ecs-agent/ecs-agent/utils/arn"
5657
"github.com/aws/amazon-ecs-agent/ecs-agent/utils/ttime"
5758
ecstypes "github.com/aws/aws-sdk-go-v2/service/ecs/types"
59+
log "github.com/cihub/seelog"
5860

5961
"github.com/aws/aws-sdk-go-v2/aws"
6062
"github.com/docker/docker/api/types"
@@ -163,6 +165,8 @@ const (
163165
serviceConnectAttachmentType = "serviceconnectdetail"
164166

165167
ipv6LoopbackAddress = "::1"
168+
169+
PAUSE_LABELS_ENV_VAR = "ECS_PAUSE_LABELS"
166170
)
167171

168172
// TaskOverrides are the overrides applied to a task
@@ -1811,14 +1815,41 @@ func (task *Task) dockerConfig(container *apicontainer.Container, apiVersion doc
18111815
containerConfig.Labels = make(map[string]string)
18121816
}
18131817

1814-
if container.Type == apicontainer.ContainerCNIPause && task.IsNetworkModeAWSVPC() {
1815-
// apply hostname to pause container's docker config
1816-
return task.applyENIHostname(containerConfig), nil
1818+
if container.Type == apicontainer.ContainerCNIPause {
1819+
if pauseLabels := os.Getenv(PAUSE_LABELS_ENV_VAR); pauseLabels != "" {
1820+
// Set labels to pause container if it's provieded as env var.
1821+
setLabelsFromJsonString(containerConfig, pauseLabels)
1822+
}
1823+
1824+
if task.IsNetworkModeAWSVPC() {
1825+
// apply hostname to pause container's docker config
1826+
return task.applyENIHostname(containerConfig), nil
1827+
}
18171828
}
18181829

18191830
return containerConfig, nil
18201831
}
18211832

1833+
// Parse label string and set them to the given container configuration.
1834+
func setLabelsFromJsonString(config *dockercontainer.Config, labelsString string) {
1835+
if len(labelsString) > 0 {
1836+
labels, err := toLabelMap(labelsString)
1837+
if err != nil {
1838+
log.Errorf("Skipped setting labels because of failed to decode. Error: %s", err)
1839+
return
1840+
}
1841+
if len(labels) > 0 {
1842+
config.Labels = labels
1843+
}
1844+
}
1845+
}
1846+
1847+
func toLabelMap(jsonBlock string) (map[string]string, error) {
1848+
out := map[string]string{}
1849+
err := json.Unmarshal([]byte(jsonBlock), &out)
1850+
return out, err
1851+
}
1852+
18221853
// dockerExposedPorts returns the container ports that need to be exposed for a container
18231854
// 1. For bridge-mode ServiceConnect-enabled tasks:
18241855
// 1a. Pause containers need to expose the port(s) for their associated task container. In particular, SC pause container

agent/api/task/task_test.go

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5924,3 +5924,95 @@ func TestGenerateENIExtraHosts(t *testing.T) {
59245924
})
59255925
}
59265926
}
5927+
5928+
func TestDockerConfigPauseContainerLabelsWithoutEnvVar_ECS_PAUSE_LABELS(t *testing.T) {
5929+
testTask := &Task{
5930+
Arn: "arn:aws:ecs:us-east-1:012345678910:task/c09f0188-7f87-4b0f-bfc3-16296622b6fe",
5931+
Family: "myFamily",
5932+
Version: "1",
5933+
Containers: []*apicontainer.Container{
5934+
{
5935+
Name: "pause",
5936+
Type: apicontainer.ContainerCNIPause,
5937+
},
5938+
},
5939+
}
5940+
5941+
config, configErr := testTask.DockerConfig(testTask.Containers[0], defaultDockerClientAPIVersion)
5942+
if configErr != nil {
5943+
t.Fatal(configErr)
5944+
}
5945+
5946+
assert.Equal(t, 0, len(config.Labels))
5947+
}
5948+
5949+
func TestDockerConfigPauseContainerLabelsWithEnvVar_ECS_PAUSE_LABELS(t *testing.T) {
5950+
testTask := &Task{
5951+
Arn: "arn:aws:ecs:us-east-1:012345678910:task/c09f0188-7f87-4b0f-bfc3-16296622b6fe",
5952+
Family: "myFamily",
5953+
Version: "1",
5954+
Containers: []*apicontainer.Container{
5955+
{
5956+
Name: "pause",
5957+
Type: apicontainer.ContainerCNIPause,
5958+
},
5959+
},
5960+
}
5961+
labelsString := "{\"test.label.1\":\"test_a\",\"test.label.2\":\"test_b\"}"
5962+
t.Setenv("ECS_PAUSE_LABELS", labelsString)
5963+
5964+
config, configErr := testTask.DockerConfig(testTask.Containers[0], defaultDockerClientAPIVersion)
5965+
if configErr != nil {
5966+
t.Fatal(configErr)
5967+
}
5968+
5969+
assert.Equal(t, 2, len(config.Labels))
5970+
assert.Equal(t, "test_a", config.Labels["test.label.1"])
5971+
assert.Equal(t, "test_b", config.Labels["test.label.2"])
5972+
}
5973+
5974+
func TestDockerConfigPauseContainerLabelsWithInvalidEnvVar_ECS_PAUSE_LABELS(t *testing.T) {
5975+
testTask := &Task{
5976+
Arn: "arn:aws:ecs:us-east-1:012345678910:task/c09f0188-7f87-4b0f-bfc3-16296622b6fe",
5977+
Family: "myFamily",
5978+
Version: "1",
5979+
Containers: []*apicontainer.Container{
5980+
{
5981+
Name: "pause",
5982+
Type: apicontainer.ContainerCNIPause,
5983+
},
5984+
},
5985+
}
5986+
// Invalid format.
5987+
labelsString := "{\"test.label\":\"test\""
5988+
t.Setenv("ECS_PAUSE_LABELS", labelsString)
5989+
5990+
config, configErr := testTask.DockerConfig(testTask.Containers[0], defaultDockerClientAPIVersion)
5991+
if configErr != nil {
5992+
t.Fatal(configErr)
5993+
}
5994+
5995+
assert.Equal(t, 0, len(config.Labels))
5996+
}
5997+
5998+
func TestDockerConfigContainerLabelsWithEnvVar_ECS_PAUSE_LABELS(t *testing.T) {
5999+
testTask := &Task{
6000+
Arn: "arn:aws:ecs:us-east-1:012345678910:task/c09f0188-7f87-4b0f-bfc3-16296622b6fe",
6001+
Family: "myFamily",
6002+
Version: "1",
6003+
Containers: []*apicontainer.Container{
6004+
{
6005+
Name: "c1",
6006+
CPU: uint(10),
6007+
Memory: uint(256),
6008+
},
6009+
},
6010+
}
6011+
6012+
config, configErr := testTask.DockerConfig(testTask.Containers[0], defaultDockerClientAPIVersion)
6013+
if configErr != nil {
6014+
t.Fatal(configErr)
6015+
}
6016+
6017+
assert.Equal(t, 0, len(config.Labels))
6018+
}

0 commit comments

Comments
 (0)