Skip to content

Commit 739c6f5

Browse files
committed
Add file watcher for Appnet agent image update
1 parent b2bed73 commit 739c6f5

30 files changed

+2628
-6
lines changed

agent/engine/docker_task_engine.go

+3
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ const (
109109
stopContainerBackoffJitter = 0.2
110110
stopContainerBackoffMultiplier = 1.3
111111
stopContainerMaxRetryCount = 5
112+
113+
serviceConnectAppnetAgenTarballDir = "/var/lib/ecs/deps/serviceconnect/"
112114
)
113115

114116
var newExponentialBackoff = retry.NewExponentialBackoff
@@ -281,6 +283,7 @@ func (engine *DockerTaskEngine) Init(ctx context.Context) error {
281283
go engine.handleDockerEvents(derivedCtx)
282284
engine.initialized = true
283285
go engine.startPeriodicExecAgentsMonitoring(derivedCtx)
286+
go engine.watchAppNetImage(engine.ctx, serviceConnectAppnetAgenTarballDir)
284287
return nil
285288
}
286289

agent/engine/docker_task_engine_linux.go

+78
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,15 @@
1717
package engine
1818

1919
import (
20+
"context"
2021
"time"
2122

23+
"github.com/cihub/seelog"
24+
"github.com/fsnotify/fsnotify"
25+
2226
apicontainer "github.com/aws/amazon-ecs-agent/agent/api/container"
2327
apitask "github.com/aws/amazon-ecs-agent/agent/api/task"
28+
apitaskstatus "github.com/aws/amazon-ecs-agent/agent/api/task/status"
2429
)
2530

2631
const (
@@ -39,3 +44,76 @@ func (engine *DockerTaskEngine) updateTaskENIDependencies(task *apitask.Task) {
3944
func (engine *DockerTaskEngine) invokePluginsForContainer(task *apitask.Task, container *apicontainer.Container) error {
4045
return nil
4146
}
47+
48+
func (engine *DockerTaskEngine) watchAppNetImage(ctx context.Context, filepath string) {
49+
watcher, err := fsnotify.NewWatcher()
50+
if err != nil {
51+
seelog.Errorf("error adding %s to fsnotify watcher, error: %v", filepath, err)
52+
}
53+
err = watcher.Add(filepath)
54+
if err != nil {
55+
seelog.Errorf("failed to initialize fsnotify NewWatcher, error: %v", err)
56+
}
57+
defer watcher.Close()
58+
59+
// Start listening for events.
60+
for {
61+
select {
62+
case event, ok := <-watcher.Events:
63+
if !ok {
64+
seelog.Warn("fsnotify event watcher channel is closed")
65+
return
66+
}
67+
const writeOrCreateMask = fsnotify.Write | fsnotify.Create
68+
if event.Op&writeOrCreateMask != 0 {
69+
seelog.Debugf("new fsnotify watcher event: %s", event.Name)
70+
// reload the updated Appnet Agent image
71+
if err := engine.reloadAppNetImage(); err == nil {
72+
// restart the internal instance relay task with
73+
// updated Appnet Agent image
74+
engine.restartInstanceTask()
75+
}
76+
}
77+
case err, ok := <-watcher.Errors:
78+
if !ok {
79+
seelog.Warn("fsnotify event watcher channel is closed")
80+
return
81+
}
82+
seelog.Error("fsnotify watcher error: %v", err)
83+
case <-ctx.Done():
84+
return
85+
}
86+
}
87+
}
88+
89+
func (engine *DockerTaskEngine) reloadAppNetImage() error {
90+
_, err := engine.serviceconnectManager.LoadImage(engine.ctx, engine.cfg, engine.client)
91+
if err != nil {
92+
seelog.Errorf("engine: Failed to reload appnet Agent container, error: %v", err)
93+
return err
94+
}
95+
return nil
96+
}
97+
98+
func (engine *DockerTaskEngine) restartInstanceTask() {
99+
if engine.serviceconnectRelay != nil {
100+
serviceconnectRelayTask, err := engine.serviceconnectManager.CreateInstanceTask(engine.cfg)
101+
if err != nil {
102+
seelog.Errorf("Unable to start relay for task in the engine: %v", err)
103+
return
104+
}
105+
// clean up instance relay task
106+
for _, container := range engine.serviceconnectRelay.Containers {
107+
if container.Type == apicontainer.ContainerServiceConnectRelay {
108+
engine.stopContainer(engine.serviceconnectRelay, container)
109+
}
110+
}
111+
engine.serviceconnectRelay.SetDesiredStatus(apitaskstatus.TaskStopped)
112+
engine.sweepTask(engine.serviceconnectRelay)
113+
engine.deleteTask(engine.serviceconnectRelay)
114+
115+
engine.serviceconnectRelay = serviceconnectRelayTask
116+
engine.AddTask(engine.serviceconnectRelay)
117+
seelog.Info("engine: Restarted AppNet Relay task")
118+
}
119+
}

agent/engine/docker_task_engine_linux_test.go

+20
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"encoding/json"
2121
"errors"
2222
"fmt"
23+
"os"
2324
"strconv"
2425
"strings"
2526
"sync"
@@ -1364,3 +1365,22 @@ func TestProvisionContainerResourcesBridgeModeWithServiceConnect(t *testing.T) {
13641365
require.Nil(t, taskEngine.(*DockerTaskEngine).provisionContainerResources(testTask, cont).Error)
13651366
}
13661367
}
1368+
1369+
func TestWatchAppNetImage(t *testing.T) {
1370+
ctx, cancel := context.WithCancel(context.TODO())
1371+
defer cancel()
1372+
ctrl, _, _, taskEngine, _, _, _, serviceConnectManager := mocks(t, ctx, &defaultConfig)
1373+
defer ctrl.Finish()
1374+
1375+
tempServiceConnectAppnetAgenTarballDir := t.TempDir()
1376+
1377+
serviceConnectManager.EXPECT().LoadImage(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes()
1378+
1379+
watcherCtx, watcherCancel := context.WithTimeout(context.Background(), time.Second)
1380+
defer watcherCancel()
1381+
go taskEngine.(*DockerTaskEngine).watchAppNetImage(watcherCtx, tempServiceConnectAppnetAgenTarballDir)
1382+
_, err := os.CreateTemp(tempServiceConnectAppnetAgenTarballDir, "agent.tar")
1383+
assert.NoError(t, err)
1384+
1385+
<-watcherCtx.Done()
1386+
}

agent/engine/docker_task_engine_unsupported.go

+16
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package engine
1818

1919
import (
20+
"context"
2021
"time"
2122

2223
apicontainer "github.com/aws/amazon-ecs-agent/agent/api/container"
@@ -39,3 +40,18 @@ func (engine *DockerTaskEngine) updateTaskENIDependencies(task *apitask.Task) {
3940
func (engine *DockerTaskEngine) invokePluginsForContainer(task *apitask.Task, container *apicontainer.Container) error {
4041
return nil
4142
}
43+
44+
// watchAppNetImage is a file watcher, if there is any change/update to AppNet image
45+
// we reload the image and restart the relay instance task with updated AppNet image.
46+
func (engine *DockerTaskEngine) watchAppNetImage(ctx context.Context, filepath string) {
47+
}
48+
49+
// reloadAppNetImage reloads the new AppNet image for service connect
50+
func (engine *DockerTaskEngine) reloadAppNetImage() error {
51+
return nil
52+
}
53+
54+
// restartInstanceTask stop the running internal relay task and starts a new one
55+
// with updated AppNet image
56+
func (engine *DockerTaskEngine) restartInstanceTask() {
57+
}

agent/engine/docker_task_engine_windows.go

+11
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package engine
1818

1919
import (
20+
"context"
2021
"time"
2122

2223
apicontainer "github.com/aws/amazon-ecs-agent/agent/api/container"
@@ -65,3 +66,13 @@ func (engine *DockerTaskEngine) invokePluginsForContainer(task *apitask.Task, co
6566

6667
return nil
6768
}
69+
70+
func (engine *DockerTaskEngine) watchAppNetImage(ctx context.Context, filepath string) {
71+
}
72+
73+
func (engine *DockerTaskEngine) reloadAppNetImage() error {
74+
return nil
75+
}
76+
77+
func (engine *DockerTaskEngine) restartInstanceTask() {
78+
}

agent/engine/serviceconnect/manager_linux.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -387,17 +387,17 @@ func (agent *manager) LoadImage(ctx context.Context, _ *config.Config, dockerCli
387387
})
388388
continue
389389
}
390-
logger.Debug(fmt.Sprintf("Loading appnet agent container tarball: %s", agentContainerTarballPath))
390+
logger.Debug(fmt.Sprintf("Loading Appnet agent container tarball: %s", agentContainerTarballPath))
391391
if loadErr = loader.LoadFromFile(ctx, agentContainerTarballPath, dockerClient); loadErr != nil {
392-
logger.Warn(fmt.Sprintf("Unable to load appnet agent container tarball: %s", agentContainerTarballPath),
392+
logger.Warn(fmt.Sprintf("Unable to load Appnet agent container tarball: %s", agentContainerTarballPath),
393393
logger.Fields{
394394
field.Error: loadErr,
395395
})
396396
continue
397397
}
398398
agent.setLoadedAppnetVerion(supportedAppnetInterfaceVersion)
399399
imageName, _ := agent.GetLoadedImageName()
400-
logger.Info(fmt.Sprintf("Successfully loaded appnet agent container tarball: %s", agentContainerTarballPath),
400+
logger.Info(fmt.Sprintf("Successfully loaded Appnet agent container tarball: %s", agentContainerTarballPath),
401401
logger.Fields{
402402
field.Image: imageName,
403403
})

agent/go.mod

+3-2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ require (
1818
github.com/docker/docker v0.0.0-20200531234253-77e06fda0c94
1919
github.com/docker/go-connections v0.4.0
2020
github.com/docker/go-units v0.4.0
21+
github.com/fsnotify/fsnotify v1.5.4
2122
github.com/godbus/dbus/v5 v5.0.6 // indirect
2223
github.com/golang/mock v1.1.1
2324
github.com/google/go-cmp v0.5.6 // indirect
@@ -34,13 +35,13 @@ require (
3435
github.com/pkg/errors v0.9.1
3536
github.com/prometheus/client_golang v0.9.4
3637
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4
37-
github.com/prometheus/procfs v0.6.0 // indirect
3838
github.com/prometheus/common v0.4.1
39+
github.com/prometheus/procfs v0.6.0 // indirect
3940
github.com/stretchr/testify v1.7.0
4041
github.com/vishvananda/netlink v1.1.0
4142
go.etcd.io/bbolt v1.3.6
4243
golang.org/x/net v0.0.0-20210525063256-abc453219eb5
43-
golang.org/x/sys v0.0.0-20210510120138-977fb7262007
44+
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad
4445
golang.org/x/text v0.3.6 // indirect
4546
golang.org/x/time v0.0.0-20170927054726-6dc17368e09b // indirect
4647
golang.org/x/tools v0.1.5

agent/go.sum

+2
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.m
6666
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
6767
github.com/frankban/quicktest v1.11.3 h1:8sXhOn0uLys67V8EsXLc6eszDs8VXWxL3iRvebPhedY=
6868
github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
69+
github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI=
70+
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
6971
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
7072
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
7173
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=

agent/utils/loader/load.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ import (
1818
"fmt"
1919
"os"
2020

21+
"github.com/aws/amazon-ecs-agent/agent/logger/field"
22+
2123
"github.com/aws/amazon-ecs-agent/agent/config"
2224
"github.com/aws/amazon-ecs-agent/agent/dockerclient"
2325
"github.com/aws/amazon-ecs-agent/agent/dockerclient/dockerapi"
@@ -35,7 +37,7 @@ type Loader interface {
3537
// GetContainerImage This function uses the DockerClient to inspect the image with the given name and tag.
3638
func GetContainerImage(imageName string, dockerClient dockerapi.DockerClient) (*types.ImageInspect, error) {
3739
logger.Debug("Inspecting container image: ", logger.Fields{
38-
imageName: imageName,
40+
field.Image: imageName,
3941
})
4042

4143
image, err := dockerClient.InspectImage(imageName)

agent/vendor/github.com/fsnotify/fsnotify/.editorconfig

+12
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

agent/vendor/github.com/fsnotify/fsnotify/.gitattributes

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

agent/vendor/github.com/fsnotify/fsnotify/.gitignore

+6
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

agent/vendor/github.com/fsnotify/fsnotify/.mailmap

+2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

agent/vendor/github.com/fsnotify/fsnotify/AUTHORS

+62
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)