Skip to content

Commit 2287f64

Browse files
committed
Add file watcher for Appnet agent image update
1 parent e11391b commit 2287f64

30 files changed

+2650
-7
lines changed

agent/engine/docker_task_engine.go

+6-1
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,11 @@ const (
111111
stopContainerMaxRetryCount = 5
112112
)
113113

114-
var newExponentialBackoff = retry.NewExponentialBackoff
114+
var (
115+
newExponentialBackoff = retry.NewExponentialBackoff
116+
117+
serviceConnectAppnetAgenTarballDir = "/var/lib/ecs/deps/serviceconnect/"
118+
)
115119

116120
// DockerTaskEngine is a state machine for managing a task and its containers
117121
// in ECS.
@@ -281,6 +285,7 @@ func (engine *DockerTaskEngine) Init(ctx context.Context) error {
281285
go engine.handleDockerEvents(derivedCtx)
282286
engine.initialized = true
283287
go engine.startPeriodicExecAgentsMonitoring(derivedCtx)
288+
go engine.watchAppNetImage(engine.ctx, serviceConnectAppnetAgenTarballDir)
284289
return nil
285290
}
286291

agent/engine/docker_task_engine_linux.go

+80
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,78 @@ 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+
engine.watch(ctx, watcher)
59+
}
60+
61+
func (engine *DockerTaskEngine) watch(ctx context.Context, watcher *fsnotify.Watcher) {
62+
// Start listening for events.
63+
for {
64+
select {
65+
case event, ok := <-watcher.Events:
66+
if !ok {
67+
seelog.Warn("fsnotify watcher event error")
68+
return
69+
}
70+
const writeOrCreateMask = fsnotify.Write | fsnotify.Create
71+
if event.Op&writeOrCreateMask != 0 {
72+
seelog.Debugf("new fsnotify watcher event: %s", event.Name)
73+
// reload the updated Appnet Agent image
74+
if err := engine.reloadAppNetImage(); err != nil {
75+
// restart the internal instance relay task with
76+
// updated Appnet Agent image
77+
engine.restartInstanceTask()
78+
}
79+
}
80+
case err, ok := <-watcher.Errors:
81+
if !ok {
82+
return
83+
}
84+
seelog.Error("fsnotify watcher error: %v", err)
85+
case <-ctx.Done():
86+
return
87+
}
88+
}
89+
}
90+
91+
func (engine *DockerTaskEngine) reloadAppNetImage() error {
92+
_, err := engine.serviceconnectManager.LoadImage(engine.ctx, engine.cfg, engine.client)
93+
if err != nil {
94+
seelog.Errorf("engine: Failed to reload appnet Agent container, error: %v", err)
95+
return err
96+
}
97+
return nil
98+
}
99+
100+
func (engine *DockerTaskEngine) restartInstanceTask() {
101+
if engine.serviceconnectRelay != nil {
102+
serviceconnectRelayTask, err := engine.serviceconnectManager.CreateInstanceTask(engine.cfg)
103+
if err != nil {
104+
seelog.Errorf("Unable to start relay for task in the engine: %v", err)
105+
return
106+
}
107+
// clean up instance relay task
108+
for _, container := range engine.serviceconnectRelay.Containers {
109+
if container.Type == apicontainer.ContainerServiceConnectRelay {
110+
engine.stopContainer(engine.serviceconnectRelay, container)
111+
}
112+
}
113+
engine.serviceconnectRelay.SetDesiredStatus(apitaskstatus.TaskStopped)
114+
engine.sweepTask(engine.serviceconnectRelay)
115+
engine.deleteTask(engine.serviceconnectRelay)
116+
117+
engine.serviceconnectRelay = serviceconnectRelayTask
118+
engine.AddTask(engine.serviceconnectRelay)
119+
seelog.Info("engine: Restarted AppNet Relay task")
120+
}
121+
}

agent/engine/docker_task_engine_linux_test.go

+28
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ import (
2626
"testing"
2727
"time"
2828

29+
"github.com/fsnotify/fsnotify"
30+
2931
"github.com/aws/amazon-ecs-agent/agent/api/appmesh"
3032
apicontainer "github.com/aws/amazon-ecs-agent/agent/api/container"
3133
apicontainerstatus "github.com/aws/amazon-ecs-agent/agent/api/container/status"
@@ -1364,3 +1366,29 @@ func TestProvisionContainerResourcesBridgeModeWithServiceConnect(t *testing.T) {
13641366
require.Nil(t, taskEngine.(*DockerTaskEngine).provisionContainerResources(testTask, cont).Error)
13651367
}
13661368
}
1369+
1370+
func TestWatchAppNetImage(t *testing.T) {
1371+
ctx, cancel := context.WithCancel(context.TODO())
1372+
defer cancel()
1373+
ctrl, _, _, taskEngine, _, _, _, serviceConnectManager := mocks(t, ctx, &defaultConfig)
1374+
defer ctrl.Finish()
1375+
1376+
// create a fsnotify watcher
1377+
watcher, err := fsnotify.NewWatcher()
1378+
assert.NoError(t, err)
1379+
err = watcher.Add("/tmp/")
1380+
assert.NoError(t, err)
1381+
defer watcher.Close()
1382+
event := fsnotify.Event{
1383+
Name: "/tmp/",
1384+
Op: fsnotify.Create,
1385+
}
1386+
serviceConnectManager.EXPECT().LoadImage(gomock.Any(), gomock.Any(), gomock.Any()).Times(1)
1387+
1388+
watcherCtx, watcherCancel := context.WithTimeout(context.Background(), time.Second)
1389+
defer watcherCancel()
1390+
go taskEngine.(*DockerTaskEngine).watch(watcherCtx, watcher)
1391+
watcher.Events <- event
1392+
1393+
<-watcherCtx.Done()
1394+
}

agent/engine/docker_task_engine_unsupported.go

+20
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,12 @@
1717
package engine
1818

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

2223
apicontainer "github.com/aws/amazon-ecs-agent/agent/api/container"
2324
apitask "github.com/aws/amazon-ecs-agent/agent/api/task"
25+
"github.com/fsnotify/fsnotify"
2426
)
2527

2628
const (
@@ -39,3 +41,21 @@ func (engine *DockerTaskEngine) updateTaskENIDependencies(task *apitask.Task) {
3941
func (engine *DockerTaskEngine) invokePluginsForContainer(task *apitask.Task, container *apicontainer.Container) error {
4042
return nil
4143
}
44+
45+
// watchAppNetImage is a file watcher, if there is any change/update to AppNet image
46+
// we reload the image and restart the relay instance task with updated AppNet image.
47+
func (engine *DockerTaskEngine) watchAppNetImage(ctx context.Context, filepath string) {
48+
}
49+
50+
func (engine *DockerTaskEngine) watch(ctx context.Context, watcher *fsnotify.Watcher) {
51+
}
52+
53+
// reloadAppNetImage reloads the new AppNet image for service connect
54+
func (engine *DockerTaskEngine) reloadAppNetImage() error {
55+
return nil
56+
}
57+
58+
// restartInstanceTask stop the running internal relay task and starts a new one
59+
// with updated AppNet image
60+
func (engine *DockerTaskEngine) restartInstanceTask() {
61+
}

agent/engine/docker_task_engine_windows.go

+16
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,11 @@
1717
package engine
1818

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

23+
"github.com/fsnotify/fsnotify"
24+
2225
apicontainer "github.com/aws/amazon-ecs-agent/agent/api/container"
2326
apitask "github.com/aws/amazon-ecs-agent/agent/api/task"
2427
"github.com/aws/amazon-ecs-agent/agent/logger"
@@ -65,3 +68,16 @@ func (engine *DockerTaskEngine) invokePluginsForContainer(task *apitask.Task, co
6568

6669
return nil
6770
}
71+
72+
func (engine *DockerTaskEngine) watchAppNetImage(ctx context.Context, filepath string) {
73+
}
74+
75+
func (engine *DockerTaskEngine) watch(ctx context.Context, watcher *fsnotify.Watcher) {
76+
}
77+
78+
func (engine *DockerTaskEngine) reloadAppNetImage() error {
79+
return nil
80+
}
81+
82+
func (engine *DockerTaskEngine) restartInstanceTask() {
83+
}

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)