Skip to content

Commit c7f664a

Browse files
authored
feat(manifest): add env var interpolation (#2917)
<!-- Provide summary of changes --> Part of #2912. Doc will be added in the next PR. <!-- Issue number, if available. E.g. "Fixes #31", "Addresses #42, 77" --> By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the Apache 2.0 License.
1 parent 7750a96 commit c7f664a

File tree

15 files changed

+296
-132
lines changed

15 files changed

+296
-132
lines changed

internal/pkg/cli/deploy.go

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -71,27 +71,29 @@ func newDeployOpts(vars deployWkldVars) (*deployOpts, error) {
7171
o.deployWkld = &deployJobOpts{
7272
deployWkldVars: o.deployWkldVars,
7373

74-
store: o.store,
75-
ws: o.ws,
76-
unmarshal: manifest.UnmarshalWorkload,
77-
spinner: termprogress.NewSpinner(log.DiagnosticWriter),
78-
sel: selector.NewWorkspaceSelect(o.prompt, o.store, o.ws),
79-
prompt: o.prompt,
80-
cmd: exec.NewCmd(),
81-
sessProvider: sessions.NewProvider(),
74+
store: o.store,
75+
ws: o.ws,
76+
newInterpolator: newManifestInterpolator,
77+
unmarshal: manifest.UnmarshalWorkload,
78+
spinner: termprogress.NewSpinner(log.DiagnosticWriter),
79+
sel: selector.NewWorkspaceSelect(o.prompt, o.store, o.ws),
80+
prompt: o.prompt,
81+
cmd: exec.NewCmd(),
82+
sessProvider: sessions.NewProvider(),
8283
}
8384
case contains(workloadType, manifest.ServiceTypes):
8485
opts := &deploySvcOpts{
8586
deployWkldVars: o.deployWkldVars,
8687

87-
store: o.store,
88-
ws: o.ws,
89-
unmarshal: manifest.UnmarshalWorkload,
90-
spinner: termprogress.NewSpinner(log.DiagnosticWriter),
91-
sel: selector.NewWorkspaceSelect(o.prompt, o.store, o.ws),
92-
prompt: o.prompt,
93-
cmd: exec.NewCmd(),
94-
sessProvider: sessions.NewProvider(),
88+
store: o.store,
89+
ws: o.ws,
90+
newInterpolator: newManifestInterpolator,
91+
unmarshal: manifest.UnmarshalWorkload,
92+
spinner: termprogress.NewSpinner(log.DiagnosticWriter),
93+
sel: selector.NewWorkspaceSelect(o.prompt, o.store, o.ws),
94+
prompt: o.prompt,
95+
cmd: exec.NewCmd(),
96+
sessProvider: sessions.NewProvider(),
9597
newAppVersionGetter: func(appName string) (versionGetter, error) {
9698
return describe.NewAppDescriber(appName)
9799
},

internal/pkg/cli/init.go

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -162,15 +162,16 @@ func newInitOpts(vars initVars) (*initOpts, error) {
162162
appName: vars.appName,
163163
},
164164

165-
store: ssm,
166-
prompt: prompt,
167-
ws: ws,
168-
unmarshal: manifest.UnmarshalWorkload,
169-
sel: sel,
170-
spinner: spin,
171-
cmd: exec.NewCmd(),
172-
sessProvider: sessProvider,
173-
snsTopicGetter: deployStore,
165+
store: ssm,
166+
prompt: prompt,
167+
ws: ws,
168+
newInterpolator: newManifestInterpolator,
169+
unmarshal: manifest.UnmarshalWorkload,
170+
sel: sel,
171+
spinner: spin,
172+
cmd: exec.NewCmd(),
173+
sessProvider: sessProvider,
174+
snsTopicGetter: deployStore,
174175

175176
newAppVersionGetter: func(appName string) (versionGetter, error) {
176177
return describe.NewAppDescriber(appName)
@@ -182,14 +183,15 @@ func newInitOpts(vars initVars) (*initOpts, error) {
182183
imageTag: vars.imageTag,
183184
appName: vars.appName,
184185
},
185-
store: ssm,
186-
prompt: prompt,
187-
ws: ws,
188-
unmarshal: manifest.UnmarshalWorkload,
189-
sel: sel,
190-
spinner: spin,
191-
cmd: exec.NewCmd(),
192-
sessProvider: sessProvider,
186+
store: ssm,
187+
prompt: prompt,
188+
ws: ws,
189+
newInterpolator: newManifestInterpolator,
190+
unmarshal: manifest.UnmarshalWorkload,
191+
sel: sel,
192+
spinner: spin,
193+
cmd: exec.NewCmd(),
194+
sessProvider: sessProvider,
193195
}
194196
fs := &afero.Afero{Fs: afero.NewOsFs()}
195197
cmd := exec.NewCmd()

internal/pkg/cli/interfaces.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -623,3 +623,7 @@ type timeoutError interface {
623623
error
624624
Timeout() bool
625625
}
626+
627+
type interpolator interface {
628+
Interpolate(s string) (string, error)
629+
}

internal/pkg/cli/job_deploy.go

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ type deployJobOpts struct {
4242
store store
4343
ws wsJobDirReader
4444
unmarshal func(in []byte) (manifest.WorkloadManifest, error)
45+
newInterpolator func(app, env string) interpolator
4546
cmd runner
4647
addons templater
4748
appCFN appResourcesGetter
@@ -80,14 +81,15 @@ func newJobDeployOpts(vars deployWkldVars) (*deployJobOpts, error) {
8081
return &deployJobOpts{
8182
deployWkldVars: vars,
8283

83-
store: store,
84-
ws: ws,
85-
unmarshal: manifest.UnmarshalWorkload,
86-
spinner: termprogress.NewSpinner(log.DiagnosticWriter),
87-
sel: selector.NewWorkspaceSelect(prompter, store, ws),
88-
prompt: prompter,
89-
cmd: exec.NewCmd(),
90-
sessProvider: sessions.NewProvider(),
84+
store: store,
85+
ws: ws,
86+
unmarshal: manifest.UnmarshalWorkload,
87+
spinner: termprogress.NewSpinner(log.DiagnosticWriter),
88+
sel: selector.NewWorkspaceSelect(prompter, store, ws),
89+
prompt: prompter,
90+
cmd: exec.NewCmd(),
91+
sessProvider: sessions.NewProvider(),
92+
newInterpolator: newManifestInterpolator,
9193
}, nil
9294
}
9395

@@ -356,7 +358,11 @@ func (o *deployJobOpts) manifest() (interface{}, error) {
356358
if err != nil {
357359
return nil, fmt.Errorf("read job %s manifest: %w", o.name, err)
358360
}
359-
mft, err := o.unmarshal(raw)
361+
interpolated, err := o.newInterpolator(o.appName, o.envName).Interpolate(string(raw))
362+
if err != nil {
363+
return nil, fmt.Errorf("interpolate environment variables for %s manifest: %w", o.name, err)
364+
}
365+
mft, err := o.unmarshal([]byte(interpolated))
360366
if err != nil {
361367
return nil, fmt.Errorf("unmarshal job %s manifest: %w", o.name, err)
362368
}

internal/pkg/cli/job_deploy_test.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
type deployJobMocks struct {
2222
mockWs *mocks.MockwsJobDirReader
2323
mockimageBuilderPusher *mocks.MockimageBuilderPusher
24+
mockInterpolator *mocks.Mockinterpolator
2425
}
2526

2627
func TestJobDeployOpts_Validate(t *testing.T) {
@@ -240,11 +241,22 @@ on:
240241
},
241242
wantErr: fmt.Errorf("read job %s manifest: %w", "mailer", mockError),
242243
},
244+
"should return error if interpolation fail": {
245+
inputSvc: "mailer",
246+
setupMocks: func(m deployJobMocks) {
247+
gomock.InOrder(
248+
m.mockWs.EXPECT().ReadJobManifest(gomock.Any()).Return(mockManifest, nil),
249+
m.mockInterpolator.EXPECT().Interpolate(string(mockManifest)).Return("", mockError),
250+
)
251+
},
252+
wantErr: fmt.Errorf("interpolate environment variables for mailer manifest: %w", mockError),
253+
},
243254
"should return error if workspace methods fail": {
244255
inputSvc: "mailer",
245256
setupMocks: func(m deployJobMocks) {
246257
gomock.InOrder(
247258
m.mockWs.EXPECT().ReadJobManifest(gomock.Any()).Return(mockManifest, nil),
259+
m.mockInterpolator.EXPECT().Interpolate(string(mockManifest)).Return(string(mockManifest), nil),
248260
m.mockWs.EXPECT().CopilotDirPath().Return("", mockError),
249261
)
250262
},
@@ -255,6 +267,7 @@ on:
255267
setupMocks: func(m deployJobMocks) {
256268
gomock.InOrder(
257269
m.mockWs.EXPECT().ReadJobManifest("mailer").Return(mockMftNoBuild, nil),
270+
m.mockInterpolator.EXPECT().Interpolate(string(mockMftNoBuild)).Return(string(mockMftNoBuild), nil),
258271
m.mockWs.EXPECT().CopilotDirPath().Times(0),
259272
m.mockimageBuilderPusher.EXPECT().BuildAndPush(gomock.Any(), gomock.Any()).Times(0),
260273
)
@@ -265,6 +278,7 @@ on:
265278
setupMocks: func(m deployJobMocks) {
266279
gomock.InOrder(
267280
m.mockWs.EXPECT().ReadJobManifest("mailer").Return(mockManifest, nil),
281+
m.mockInterpolator.EXPECT().Interpolate(string(mockManifest)).Return(string(mockManifest), nil),
268282
m.mockWs.EXPECT().CopilotDirPath().Return("/ws/root/copilot", nil),
269283
m.mockimageBuilderPusher.EXPECT().BuildAndPush(gomock.Any(), gomock.Any()).Return("", mockError),
270284
)
@@ -276,6 +290,7 @@ on:
276290
setupMocks: func(m deployJobMocks) {
277291
gomock.InOrder(
278292
m.mockWs.EXPECT().ReadJobManifest("mailer").Return(mockManifest, nil),
293+
m.mockInterpolator.EXPECT().Interpolate(string(mockManifest)).Return(string(mockManifest), nil),
279294
m.mockWs.EXPECT().CopilotDirPath().Return("/ws/root/copilot", nil),
280295
m.mockimageBuilderPusher.EXPECT().BuildAndPush(gomock.Any(), &dockerengine.BuildArguments{
281296
Dockerfile: filepath.Join("/ws", "root", "path", "to", "Dockerfile"),
@@ -290,6 +305,7 @@ on:
290305
setupMocks: func(m deployJobMocks) {
291306
gomock.InOrder(
292307
m.mockWs.EXPECT().ReadJobManifest("mailer").Return(mockMftBuildString, nil),
308+
m.mockInterpolator.EXPECT().Interpolate(string(mockMftBuildString)).Return(string(mockMftBuildString), nil),
293309
m.mockWs.EXPECT().CopilotDirPath().Return("/ws/root/copilot", nil),
294310
m.mockimageBuilderPusher.EXPECT().BuildAndPush(gomock.Any(), &dockerengine.BuildArguments{
295311
Dockerfile: filepath.Join("/ws", "root", "path", "to", "Dockerfile"),
@@ -304,6 +320,7 @@ on:
304320
setupMocks: func(m deployJobMocks) {
305321
gomock.InOrder(
306322
m.mockWs.EXPECT().ReadJobManifest("mailer").Return(mockMftNoContext, nil),
323+
m.mockInterpolator.EXPECT().Interpolate(string(mockMftNoContext)).Return(string(mockMftNoContext), nil),
307324
m.mockWs.EXPECT().CopilotDirPath().Return("/ws/root/copilot", nil),
308325
m.mockimageBuilderPusher.EXPECT().BuildAndPush(gomock.Any(), &dockerengine.BuildArguments{
309326
Dockerfile: filepath.Join("/ws", "root", "path", "to", "Dockerfile"),
@@ -322,9 +339,11 @@ on:
322339

323340
mockWorkspace := mocks.NewMockwsJobDirReader(ctrl)
324341
mockimageBuilderPusher := mocks.NewMockimageBuilderPusher(ctrl)
342+
mockInterpolator := mocks.NewMockinterpolator(ctrl)
325343
mocks := deployJobMocks{
326344
mockWs: mockWorkspace,
327345
mockimageBuilderPusher: mockimageBuilderPusher,
346+
mockInterpolator: mockInterpolator,
328347
}
329348
test.setupMocks(mocks)
330349
opts := deployJobOpts{
@@ -334,6 +353,9 @@ on:
334353
unmarshal: manifest.UnmarshalWorkload,
335354
imageBuilderPusher: mockimageBuilderPusher,
336355
ws: mockWorkspace,
356+
newInterpolator: func(app, env string) interpolator {
357+
return mockInterpolator
358+
},
337359
}
338360

339361
gotErr := opts.configureContainerImage()

internal/pkg/cli/mocks/mock_interfaces.go

Lines changed: 38 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/pkg/cli/svc_deploy.go

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ type deploySvcOpts struct {
7676
ws wsSvcDirReader
7777
imageBuilderPusher imageBuilderPusher
7878
unmarshal func([]byte) (manifest.WorkloadManifest, error)
79+
newInterpolator func(app, env string) interpolator
7980
s3 artifactUploader
8081
cmd runner
8182
addons templater
@@ -139,14 +140,19 @@ func newSvcDeployOpts(vars deployWkldVars) (*deploySvcOpts, error) {
139140
}
140141
return d, nil
141142
},
142-
cmd: exec.NewCmd(),
143-
sessProvider: sessions.NewProvider(),
144-
snsTopicGetter: deployStore,
143+
newInterpolator: newManifestInterpolator,
144+
cmd: exec.NewCmd(),
145+
sessProvider: sessions.NewProvider(),
146+
snsTopicGetter: deployStore,
145147
}
146148
opts.uploadOpts = newUploadCustomResourcesOpts(opts)
147149
return opts, err
148150
}
149151

152+
func newManifestInterpolator(app, env string) interpolator {
153+
return manifest.NewInterpolator(app, env)
154+
}
155+
150156
// Validate returns an error if the user inputs are invalid.
151157
func (o *deploySvcOpts) Validate() error {
152158
if o.appName == "" {
@@ -451,7 +457,11 @@ func (o *deploySvcOpts) manifest() (interface{}, error) {
451457
if err != nil {
452458
return nil, fmt.Errorf("read service %s manifest file: %w", o.name, err)
453459
}
454-
mft, err := o.unmarshal(raw)
460+
interpolated, err := o.newInterpolator(o.appName, o.envName).Interpolate(string(raw))
461+
if err != nil {
462+
return nil, fmt.Errorf("interpolate environment variables for %s manifest: %w", o.name, err)
463+
}
464+
mft, err := o.unmarshal([]byte(interpolated))
455465
if err != nil {
456466
return nil, fmt.Errorf("unmarshal service %s manifest: %w", o.name, err)
457467
}

0 commit comments

Comments
 (0)