Skip to content
This repository was archived by the owner on Sep 13, 2024. It is now read-only.

Commit faa986d

Browse files
committed
Remove update-cache in favor of reload-cache
1 parent 12e3d65 commit faa986d

File tree

9 files changed

+46
-173
lines changed

9 files changed

+46
-173
lines changed

README.md

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,12 @@ The upstart script installed by the Amazon EC2 Container Service RPM can be star
1818
* `sudo stop ecs`
1919

2020
### Updates
21-
A naive update method exists to pull tarballs from S3. Updating at present is very manual, and requires the following
22-
steps:
21+
Updates to the Amazon ECS Container Agent should be performed through the Amazon ECS Container Agent. In the case where
22+
an update failed and the Amazon ECS Container Agent is no longer functional, a rollback can be initiated as follows:
2323

2424
1. `sudo stop ecs`
25-
2. `sudo /usr/libexec/amazon-ecs-init update-cache`
26-
3. `docker rm ecs-agent`
27-
4. `docker rmi amazon/amazon-ecs-agent:latest`
28-
5. `sudo start ecs`
25+
2. `sudo /usr/libexec/amazon-ecs-init reload-cache`
26+
3. `sudo start ecs`
2927

3028
## License
3129

ecs-init.spec

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ rm -rf $RPM_BUILD_ROOT
7777
- Re-start Agent on non-terminal exit codes
7878
- Enable Agent self-updates
7979
- Cache Agent version 1.0.0
80+
- Added rollback to cached Agent version for failed updates
8081
* Mon Mar 16 2015 Samuel Karp <skarp@amazon.com> - 0.3-0
8182
- Migrate to statically-compiled Go binary
8283
* Tue Feb 17 2015 Eric Nordlund <ericn@amazon.com> - 0.2-3

ecs-init/cache/cache.go

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -53,38 +53,6 @@ func (d *Downloader) IsAgentCached() bool {
5353
return true
5454
}
5555

56-
// IsAgentLatest checks whether the cached copy of the Agent has the same MD5
57-
// sum as the published MD5 sum
58-
func (d *Downloader) IsAgentLatest() bool {
59-
file, err := d.fs.Open(config.AgentTarball())
60-
if err != nil {
61-
return false
62-
}
63-
defer file.Close()
64-
65-
md5hash := md5.New()
66-
_, err = d.fs.Copy(md5hash, file)
67-
if err != nil {
68-
log.Error("Could not calculate md5sum", err)
69-
return false
70-
}
71-
72-
publishedMd5Sum, err := d.getPublishedMd5Sum()
73-
if err != nil {
74-
return false
75-
}
76-
77-
calculatedMd5Sum := md5hash.Sum(nil)
78-
calculatedMd5SumString := fmt.Sprintf("%x", calculatedMd5Sum)
79-
log.Debugf("Expected %s", publishedMd5Sum)
80-
log.Debugf("Calculated %s", calculatedMd5SumString)
81-
if publishedMd5Sum != calculatedMd5SumString {
82-
log.Info("Cached Amazon EC2 Container Service Agent does not match latest at %s", config.AgentRemoteTarball())
83-
return false
84-
}
85-
return true
86-
}
87-
8856
// DownloadAgent downloads a fresh copy of the Agent and performs an
8957
// integrity check on the downloaded image
9058
func (d *Downloader) DownloadAgent() error {

ecs-init/cache/cache_test.go

Lines changed: 0 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -62,100 +62,6 @@ func TestIsAgentCachedTrue(t *testing.T) {
6262
}
6363
}
6464

65-
func TestIsAgentLatestCannotOpen(t *testing.T) {
66-
mockCtrl := gomock.NewController(t)
67-
defer mockCtrl.Finish()
68-
69-
mockFS := NewMockfileSystem(mockCtrl)
70-
71-
mockFS.EXPECT().Open(config.AgentTarball()).Return(nil, errors.New("test error"))
72-
73-
d := &Downloader{
74-
fs: mockFS,
75-
}
76-
77-
if d.IsAgentLatest() {
78-
t.Error("Expected d.IsAgentLatest() to be false")
79-
}
80-
}
81-
82-
func TestIsAgentLatestDownloadMD5Failure(t *testing.T) {
83-
mockCtrl := gomock.NewController(t)
84-
defer mockCtrl.Finish()
85-
86-
mockFS := NewMockfileSystem(mockCtrl)
87-
mockGetter := NewMockhttpGetter(mockCtrl)
88-
89-
mockFS.EXPECT().Open(config.AgentTarball()).Return(&os.File{}, nil)
90-
mockFS.EXPECT().Copy(gomock.Any(), gomock.Any())
91-
mockGetter.EXPECT().Get(config.AgentRemoteTarballMD5()).Return(nil, errors.New("test error"))
92-
93-
d := &Downloader{
94-
fs: mockFS,
95-
getter: mockGetter,
96-
}
97-
98-
if d.IsAgentLatest() {
99-
t.Error("Expected d.IsAgentLatest() to be false")
100-
}
101-
}
102-
103-
func TestIsAgentLatestMD5Mismatch(t *testing.T) {
104-
mockCtrl := gomock.NewController(t)
105-
defer mockCtrl.Finish()
106-
107-
md5response := &http.Response{}
108-
md5sum := "md5sum"
109-
110-
mockFS := NewMockfileSystem(mockCtrl)
111-
mockGetter := NewMockhttpGetter(mockCtrl)
112-
113-
mockFS.EXPECT().Open(config.AgentTarball()).Return(&os.File{}, nil)
114-
mockGetter.EXPECT().Get(config.AgentRemoteTarballMD5()).Return(md5response, nil)
115-
mockFS.EXPECT().ReadAll(md5response.Body).Return([]byte(md5sum), nil)
116-
mockFS.EXPECT().Copy(gomock.Any(), gomock.Any())
117-
118-
d := &Downloader{
119-
fs: mockFS,
120-
getter: mockGetter,
121-
}
122-
123-
if d.IsAgentLatest() {
124-
t.Error("Expected d.IsAgentLatest() to be false")
125-
}
126-
}
127-
128-
func TestIsAgentLatestTrue(t *testing.T) {
129-
mockCtrl := gomock.NewController(t)
130-
defer mockCtrl.Finish()
131-
132-
agentContent := "agent content"
133-
md5sum := fmt.Sprintf("%x\n", md5.Sum([]byte(agentContent)))
134-
md5response := &http.Response{}
135-
136-
mockFS := NewMockfileSystem(mockCtrl)
137-
mockGetter := NewMockhttpGetter(mockCtrl)
138-
139-
mockFS.EXPECT().Open(config.AgentTarball()).Return(&os.File{}, nil)
140-
mockGetter.EXPECT().Get(config.AgentRemoteTarballMD5()).Return(md5response, nil)
141-
mockFS.EXPECT().ReadAll(md5response.Body).Return([]byte(md5sum), nil)
142-
mockFS.EXPECT().Copy(gomock.Any(), gomock.Any()).Do(func(writer io.Writer, reader io.Reader) {
143-
_, err := io.Copy(writer, bytes.NewBufferString(agentContent))
144-
if err != nil {
145-
t.Fail()
146-
}
147-
})
148-
149-
d := &Downloader{
150-
fs: mockFS,
151-
getter: mockGetter,
152-
}
153-
154-
if !d.IsAgentLatest() {
155-
t.Error("Expected d.IsAgentLatest() to be true")
156-
}
157-
}
158-
15965
func TestDownloadAgentMkdirFailure(t *testing.T) {
16066
mockCtrl := gomock.NewController(t)
16167
defer mockCtrl.Finish()

ecs-init/ecs-init.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,9 @@ func actions(engine *engine.Engine) map[string]action {
7676
function: engine.PreStop,
7777
description: "Stop the ECS Agent",
7878
},
79-
"update-cache": action{
80-
function: engine.UpdateCache,
81-
description: "Update the cached image of the ECS Agent",
79+
"reload-cache": action{
80+
function: engine.ReloadCache,
81+
description: "Reload the cached image of the ECS Agent into Docker",
8282
},
8383
}
8484
}

ecs-init/engine/dependencies.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import (
2121

2222
type downloader interface {
2323
IsAgentCached() bool
24-
IsAgentLatest() bool
2524
DownloadAgent() error
2625
LoadCachedAgent() (io.ReadCloser, error)
2726
LoadDesiredAgent() (io.ReadCloser, error)

ecs-init/engine/dependencies_mock_test.go

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -53,16 +53,6 @@ func (_mr *_MockdownloaderRecorder) IsAgentCached() *gomock.Call {
5353
return _mr.mock.ctrl.RecordCall(_mr.mock, "IsAgentCached")
5454
}
5555

56-
func (_m *Mockdownloader) IsAgentLatest() bool {
57-
ret := _m.ctrl.Call(_m, "IsAgentLatest")
58-
ret0, _ := ret[0].(bool)
59-
return ret0
60-
}
61-
62-
func (_mr *_MockdownloaderRecorder) IsAgentLatest() *gomock.Call {
63-
return _mr.mock.ctrl.RecordCall(_mr.mock, "IsAgentLatest")
64-
}
65-
6656
func (_m *Mockdownloader) DownloadAgent() error {
6757
ret := _m.ctrl.Call(_m, "DownloadAgent")
6858
ret0, _ := ret[0].(error)

ecs-init/engine/engine.go

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,18 @@ func (e *Engine) PreStart() error {
5959
return nil
6060
}
6161

62+
return e.loadCache()
63+
}
64+
65+
// ReloadCache reloads the cached image of the ECS Agent into Docker
66+
func (e *Engine) ReloadCache() error {
67+
return e.loadCache()
68+
}
69+
70+
func (e *Engine) loadCache() error {
6271
cached := e.downloader.IsAgentCached()
6372
if !cached {
64-
err = e.mustDownloadAgent()
73+
err := e.mustDownloadAgent()
6574
if err != nil {
6675
return err
6776
}
@@ -71,6 +80,15 @@ func (e *Engine) PreStart() error {
7180
return e.load(e.downloader.LoadCachedAgent())
7281
}
7382

83+
func (e *Engine) mustDownloadAgent() error {
84+
log.Info("Downloading Amazon EC2 Container Service Agent")
85+
err := e.downloader.DownloadAgent()
86+
if err != nil {
87+
return engineError("could not download Amazon EC2 Container Serivce Agent", err)
88+
}
89+
return nil
90+
}
91+
7492
func (e *Engine) load(image io.ReadCloser, err error) error {
7593
if err != nil {
7694
return engineError("could not load Amazon EC2 Container Service Agent from cache", err)
@@ -126,25 +144,6 @@ func (e *Engine) PreStop() error {
126144
return nil
127145
}
128146

129-
// UpdateCache updates teh cached image of the ECS Agent
130-
func (e *Engine) UpdateCache() error {
131-
latest := e.downloader.IsAgentLatest()
132-
if !latest {
133-
log.Info("Cached Amazon EC2 Container Service Agent does not match latest published")
134-
return e.mustDownloadAgent()
135-
}
136-
return nil
137-
}
138-
139-
func (e *Engine) mustDownloadAgent() error {
140-
log.Info("Downloading Amazon EC2 Container Service Agent")
141-
err := e.downloader.DownloadAgent()
142-
if err != nil {
143-
return engineError("could not download Amazon EC2 Container Serivce Agent", err)
144-
}
145-
return nil
146-
}
147-
148147
type _engineError struct {
149148
err error
150149
message string

ecs-init/engine/engine_test.go

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -239,31 +239,43 @@ func TestPreStop(t *testing.T) {
239239
engine.PreStop()
240240
}
241241

242-
func TestUpdateCacheIsLatest(t *testing.T) {
242+
func TestReloadCacheNotCached(t *testing.T) {
243243
mockCtrl := gomock.NewController(t)
244244
defer mockCtrl.Finish()
245245

246+
cachedAgentBuffer := ioutil.NopCloser(&bytes.Buffer{})
247+
248+
mockDocker := NewMockdockerClient(mockCtrl)
246249
mockDownloader := NewMockdownloader(mockCtrl)
247250

248-
mockDownloader.EXPECT().IsAgentLatest().Return(true)
251+
mockDownloader.EXPECT().IsAgentCached().Return(false)
252+
mockDownloader.EXPECT().DownloadAgent()
253+
mockDownloader.EXPECT().LoadCachedAgent().Return(cachedAgentBuffer, nil)
254+
mockDocker.EXPECT().LoadImage(cachedAgentBuffer)
249255

250256
engine := &Engine{
257+
docker: mockDocker,
251258
downloader: mockDownloader,
252259
}
253-
engine.UpdateCache()
260+
engine.ReloadCache()
254261
}
255262

256-
func TestUpdateCacheIsNotLatest(t *testing.T) {
263+
func TestReloadCacheCached(t *testing.T) {
257264
mockCtrl := gomock.NewController(t)
258265
defer mockCtrl.Finish()
259266

267+
cachedAgentBuffer := ioutil.NopCloser(&bytes.Buffer{})
268+
269+
mockDocker := NewMockdockerClient(mockCtrl)
260270
mockDownloader := NewMockdownloader(mockCtrl)
261271

262-
mockDownloader.EXPECT().IsAgentLatest().Return(false)
263-
mockDownloader.EXPECT().DownloadAgent()
272+
mockDownloader.EXPECT().IsAgentCached().Return(true)
273+
mockDownloader.EXPECT().LoadCachedAgent().Return(cachedAgentBuffer, nil)
274+
mockDocker.EXPECT().LoadImage(cachedAgentBuffer)
264275

265276
engine := &Engine{
277+
docker: mockDocker,
266278
downloader: mockDownloader,
267279
}
268-
engine.UpdateCache()
280+
engine.ReloadCache()
269281
}

0 commit comments

Comments
 (0)