-
Notifications
You must be signed in to change notification settings - Fork 618
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
Add file watcher for Appnet agent image update #3435
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,10 +17,16 @@ | |
package engine | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"time" | ||
|
||
"github.com/fsnotify/fsnotify" | ||
|
||
apicontainer "github.com/aws/amazon-ecs-agent/agent/api/container" | ||
apitask "github.com/aws/amazon-ecs-agent/agent/api/task" | ||
apitaskstatus "github.com/aws/amazon-ecs-agent/agent/api/task/status" | ||
"github.com/aws/amazon-ecs-agent/agent/logger" | ||
) | ||
|
||
const ( | ||
|
@@ -39,3 +45,78 @@ func (engine *DockerTaskEngine) updateTaskENIDependencies(task *apitask.Task) { | |
func (engine *DockerTaskEngine) invokePluginsForContainer(task *apitask.Task, container *apicontainer.Container) error { | ||
return nil | ||
} | ||
|
||
func (engine *DockerTaskEngine) watchAppNetImage(ctx context.Context) { | ||
watcher, err := fsnotify.NewWatcher() | ||
if err != nil { | ||
logger.Error(fmt.Sprintf("failed to initialize fsnotify NewWatcher, error: %v", err)) | ||
} | ||
appnetContainerTarballDir := engine.serviceconnectManager.GetAppnetContainerTarballDir() | ||
err = watcher.Add(appnetContainerTarballDir) | ||
if err != nil { | ||
logger.Error(fmt.Sprintf("error adding %s to fsnotify watcher, error: %v", appnetContainerTarballDir, err)) | ||
} | ||
defer watcher.Close() | ||
|
||
// Start listening for events. | ||
for { | ||
select { | ||
case event, ok := <-watcher.Events: | ||
if !ok { | ||
logger.Warn("fsnotify event watcher channel is closed") | ||
return | ||
} | ||
// check if the event file operation is write or create | ||
const writeOrCreateMask = fsnotify.Write | fsnotify.Create | ||
if event.Op&writeOrCreateMask != 0 { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should there be a space between event.Op and writeOrCreateMask ? Also, can you explain what this means? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. added space but I think gofmt removes it. Also add a comment to clarify the condition we check:) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks Mythri :) |
||
logger.Debug(fmt.Sprintf("new fsnotify watcher event: %s", event.Name)) | ||
// reload the updated Appnet Agent image | ||
if err := engine.reloadAppNetImage(); err == nil { | ||
// restart the internal instance relay task with | ||
// updated Appnet Agent image | ||
engine.restartInstanceTask() | ||
} | ||
} | ||
case err, ok := <-watcher.Errors: | ||
if !ok { | ||
logger.Warn("fsnotify event watcher channel is closed") | ||
return | ||
yinyic marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
logger.Error(fmt.Sprintf("fsnotify watcher error: %v", err)) | ||
case <-ctx.Done(): | ||
return | ||
} | ||
} | ||
} | ||
|
||
func (engine *DockerTaskEngine) reloadAppNetImage() error { | ||
_, err := engine.serviceconnectManager.LoadImage(engine.ctx, engine.cfg, engine.client) | ||
if err != nil { | ||
logger.Error(fmt.Sprintf("engine: Failed to reload appnet Agent container, error: %v", err)) | ||
return err | ||
} | ||
return nil | ||
} | ||
|
||
func (engine *DockerTaskEngine) restartInstanceTask() { | ||
if engine.serviceconnectRelay != nil { | ||
serviceconnectRelayTask, err := engine.serviceconnectManager.CreateInstanceTask(engine.cfg) | ||
if err != nil { | ||
logger.Error(fmt.Sprintf("Unable to start relay for task in the engine: %v", err)) | ||
return | ||
} | ||
// clean up instance relay task | ||
for _, container := range engine.serviceconnectRelay.Containers { | ||
if container.Type == apicontainer.ContainerServiceConnectRelay { | ||
engine.stopContainer(engine.serviceconnectRelay, container) | ||
} | ||
} | ||
engine.serviceconnectRelay.SetDesiredStatus(apitaskstatus.TaskStopped) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Q. Would we show the task is stopped/started due to AppNet Agent image reload somewhere in ECS Agent log? or Control plane will receive a message from ECS Agent, saying that task state is changed due to image is reloading? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since this an internal task, we don't publish this task status to backend but just log the restart on ECS Agent. |
||
engine.sweepTask(engine.serviceconnectRelay) | ||
engine.deleteTask(engine.serviceconnectRelay) | ||
|
||
engine.serviceconnectRelay = serviceconnectRelayTask | ||
engine.AddTask(engine.serviceconnectRelay) | ||
logger.Info("engine: Restarted AppNet Relay task") | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not blocking. we can use logger fields : )
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oops...will fix it in the next PR!! Thank you:)