Skip to content

Commit 73f3325

Browse files
authored
fix: redirect AppRunner services on ARM architectures to AMD (#2955)
Previously, ARM -> AMD redirection was failing because we don't surface the `platform` field in RDWS manifests. Now we hard code `linux/amd64` for empty `platform` fields. Fixes #2640. 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 4a8f9cd commit 73f3325

13 files changed

Lines changed: 309 additions & 277 deletions

internal/pkg/cli/svc_deploy.go

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -396,28 +396,24 @@ func (o *deploySvcOpts) dfBuildArgs(svc interface{}) (*dockerengine.BuildArgumen
396396
func buildArgs(name, imageTag, copilotDir string, unmarshaledManifest interface{}) (*dockerengine.BuildArguments, error) {
397397
type dfArgs interface {
398398
BuildArgs(rootDirectory string) *manifest.DockerBuildArgs
399-
TaskPlatform() (*string, error)
399+
ContainerPlatform() string
400400
}
401401
mf, ok := unmarshaledManifest.(dfArgs)
402402
if !ok {
403-
return nil, fmt.Errorf("%s does not have required methods BuildArgs() and TaskPlatform()", name)
403+
return nil, fmt.Errorf("%s does not have required methods BuildArgs() and ContainerPlatform()", name)
404404
}
405405
var tags []string
406406
if imageTag != "" {
407407
tags = append(tags, imageTag)
408408
}
409409
args := mf.BuildArgs(filepath.Dir(copilotDir))
410-
platform, err := mf.TaskPlatform()
411-
if err != nil {
412-
return nil, fmt.Errorf("get platform for service: %w", err)
413-
}
414410
return &dockerengine.BuildArguments{
415411
Dockerfile: *args.Dockerfile,
416412
Context: *args.Context,
417413
Args: args.Args,
418414
CacheFrom: args.CacheFrom,
419415
Target: aws.StringValue(args.Target),
420-
Platform: aws.StringValue(platform),
416+
Platform: mf.ContainerPlatform(),
421417
Tags: tags,
422418
}, nil
423419
}

internal/pkg/cli/svc_deploy_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,7 @@ image:
306306
m.mockInterpolator.EXPECT().Interpolate(string(mockManifestWithBadPlatform)).Return(string(mockManifestWithBadPlatform), nil),
307307
)
308308
},
309-
wantErr: errors.New("validate manifest against environment : validate \"platform\": platform linus/abc123 is invalid; valid platforms are: linux/amd64, linux/x86_64, windows/amd64 and windows/x86_64"),
309+
wantErr: errors.New("validate manifest against environment : validate \"platform\": platform 'linus/abc123' is invalid; valid platforms are: linux/amd64, linux/x86_64, windows/amd64 and windows/x86_64"),
310310
},
311311
"success with valid platform": {
312312
inputSvc: "serviceA",

internal/pkg/cli/svc_init.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -461,7 +461,7 @@ func legitimizePlatform(engine dockerEngine, wkldType string) (manifest.Platform
461461
if redirectedPlatform == "" {
462462
return "", nil
463463
}
464-
if redirectedPlatform != detectedPlatform {
464+
if redirectedPlatform != detectedPlatform && wkldType != manifest.RequestDrivenWebServiceType {
465465
log.Warningf("Your architecture type %s is currently unsupported. Setting platform %s instead.\n", color.HighlightCode(detectedArch), redirectedPlatform)
466466
}
467467
platform := manifest.PlatformString(redirectedPlatform)

internal/pkg/manifest/backend_svc.go

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44
package manifest
55

66
import (
7-
"errors"
8-
97
"github.com/aws/aws-sdk-go/aws"
108
"github.com/aws/copilot-cli/internal/pkg/template"
119
"github.com/imdario/mergo"
@@ -127,24 +125,6 @@ func (s BackendService) ApplyEnv(envName string) (WorkloadManifest, error) {
127125
return &s, nil
128126
}
129127

130-
// windowsCompatibility disallows unsupported services when deploying Windows containers on Fargate.
131-
func (s *BackendService) windowsCompatibility() error {
132-
if !s.IsWindows() {
133-
return nil
134-
}
135-
// Exec is not supported.
136-
if aws.BoolValue(s.ExecuteCommand.Enable) {
137-
return errors.New(`'exec' is not supported when deploying a Windows container`)
138-
}
139-
// EFS is not supported.
140-
for _, volume := range s.Storage.Volumes {
141-
if !volume.EmptyVolume() {
142-
return errors.New(`'EFS' is not supported when deploying a Windows container`)
143-
}
144-
}
145-
return nil
146-
}
147-
148128
// newDefaultBackendService returns a backend service with minimal task sizes and a single replica.
149129
func newDefaultBackendService() *BackendService {
150130
return &BackendService{

internal/pkg/manifest/job.go

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@
55
package manifest
66

77
import (
8-
"errors"
9-
108
"github.com/aws/aws-sdk-go/aws"
119
"github.com/aws/copilot-cli/internal/pkg/template"
1210
"github.com/imdario/mergo"
@@ -123,20 +121,6 @@ func (j ScheduledJob) ApplyEnv(envName string) (WorkloadManifest, error) {
123121
return &j, nil
124122
}
125123

126-
// windowsCompatibility disallows unsupported services when deploying Windows containers on Fargate.
127-
func (j *ScheduledJob) windowsCompatibility() error {
128-
if !j.IsWindows() {
129-
return nil
130-
}
131-
// EFS is not supported.
132-
for _, volume := range j.Storage.Volumes {
133-
if !volume.EmptyVolume() {
134-
return errors.New(`'EFS' is not supported when deploying a Windows container`)
135-
}
136-
}
137-
return nil
138-
}
139-
140124
// Publish returns the list of topics where notifications can be published.
141125
func (j *ScheduledJob) Publish() []Topic {
142126
return j.ScheduledJobConfig.PublishConfig.Topics

internal/pkg/manifest/lb_web_svc.go

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -192,24 +192,6 @@ type RoutingRule struct {
192192
AllowedSourceIps []IPNet `yaml:"allowed_source_ips"`
193193
}
194194

195-
// windowsCompatibility disallows unsupported services when deploying Windows containers on Fargate.
196-
func (s *LoadBalancedWebService) windowsCompatibility() error {
197-
if !s.IsWindows() {
198-
return nil
199-
}
200-
// Exec is not supported.
201-
if aws.BoolValue(s.ExecuteCommand.Enable) {
202-
return errors.New(`'exec' is not supported when deploying a Windows container`)
203-
}
204-
// EFS is not supported.
205-
for _, volume := range s.Storage.Volumes {
206-
if !volume.EmptyVolume() {
207-
return errors.New(`'EFS' is not supported when deploying a Windows container`)
208-
}
209-
}
210-
return nil
211-
}
212-
213195
// IPNet represents an IP network string. For example: 10.1.0.0/16
214196
type IPNet string
215197

internal/pkg/manifest/lb_web_svc_test.go

Lines changed: 0 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
package manifest
55

66
import (
7-
"errors"
87
"fmt"
98
"io/ioutil"
109
"path/filepath"
@@ -1255,92 +1254,6 @@ func TestLoadBalancedWebService_ApplyEnv(t *testing.T) {
12551254
}
12561255
}
12571256

1258-
func TestLoadBalancedWebService_ValidateForWindows(t *testing.T) {
1259-
testCases := map[string]struct {
1260-
in *LoadBalancedWebService
1261-
wantedErr error
1262-
}{
1263-
"returns nil if not windows": {
1264-
in: &LoadBalancedWebService{
1265-
LoadBalancedWebServiceConfig: LoadBalancedWebServiceConfig{
1266-
TaskConfig: TaskConfig{
1267-
Platform: PlatformArgsOrString{
1268-
PlatformString: (*PlatformString)(aws.String("doors/amp64")),
1269-
PlatformArgs: PlatformArgs{
1270-
OSFamily: nil,
1271-
Arch: nil,
1272-
},
1273-
},
1274-
ExecuteCommand: ExecuteCommand{
1275-
Config: ExecuteCommandConfig{
1276-
Enable: aws.Bool(true)},
1277-
},
1278-
},
1279-
},
1280-
},
1281-
wantedErr: nil,
1282-
},
1283-
"throws error when windows and exec both present": {
1284-
in: &LoadBalancedWebService{
1285-
LoadBalancedWebServiceConfig: LoadBalancedWebServiceConfig{
1286-
TaskConfig: TaskConfig{
1287-
Platform: PlatformArgsOrString{
1288-
PlatformString: nil,
1289-
PlatformArgs: PlatformArgs{
1290-
OSFamily: aws.String("Windows-Server-2019-Full"),
1291-
Arch: aws.String("amd64"),
1292-
},
1293-
},
1294-
ExecuteCommand: ExecuteCommand{
1295-
Config: ExecuteCommandConfig{
1296-
Enable: aws.Bool(true)},
1297-
},
1298-
},
1299-
},
1300-
},
1301-
wantedErr: errors.New("'exec' is not supported when deploying a Windows container"),
1302-
},
1303-
"throws error when windows and efs both present": {
1304-
in: &LoadBalancedWebService{
1305-
LoadBalancedWebServiceConfig: LoadBalancedWebServiceConfig{
1306-
TaskConfig: TaskConfig{
1307-
Platform: PlatformArgsOrString{
1308-
PlatformString: (*PlatformString)(aws.String("windows/amd64")),
1309-
},
1310-
Storage: Storage{
1311-
Volumes: map[string]*Volume{
1312-
"myEFSVolume": {
1313-
MountPointOpts: MountPointOpts{
1314-
ContainerPath: aws.String("/path/to/files"),
1315-
ReadOnly: aws.Bool(false),
1316-
},
1317-
EFS: EFSConfigOrBool{
1318-
Advanced: EFSVolumeConfiguration{
1319-
FileSystemID: aws.String("fs-1234"),
1320-
},
1321-
},
1322-
},
1323-
},
1324-
},
1325-
},
1326-
},
1327-
},
1328-
wantedErr: errors.New("'EFS' is not supported when deploying a Windows container"),
1329-
},
1330-
}
1331-
for name, tc := range testCases {
1332-
t.Run(name, func(t *testing.T) {
1333-
// WHEN
1334-
err := tc.in.windowsCompatibility()
1335-
1336-
// THEN
1337-
if err != nil {
1338-
require.EqualError(t, err, tc.wantedErr.Error(), "errors should be returned when disallowed services present")
1339-
}
1340-
})
1341-
}
1342-
}
1343-
13441257
func TestLoadBalancedWebService_Port(t *testing.T) {
13451258
// GIVEN
13461259
mft := LoadBalancedWebService{

internal/pkg/manifest/rd_web_svc.go

Lines changed: 5 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44
package manifest
55

66
import (
7-
"fmt"
8-
97
"github.com/aws/aws-sdk-go/aws"
108
"github.com/aws/copilot-cli/internal/pkg/template"
119
"github.com/imdario/mergo"
@@ -92,12 +90,12 @@ func (s *RequestDrivenWebService) BuildRequired() (bool, error) {
9290
return requiresBuild(s.ImageConfig.Image)
9391
}
9492

95-
// TaskPlatform returns the platform for the service.
96-
func (s *RequestDrivenWebService) TaskPlatform() (*string, error) {
97-
if s.InstanceConfig.Platform.PlatformString == nil {
98-
return nil, nil
93+
// ContainerPlatform returns the platform for the service.
94+
func (s *RequestDrivenWebService) ContainerPlatform() string {
95+
if s.InstanceConfig.Platform.IsEmpty() {
96+
return platformString(OSLinux, ArchAMD64)
9997
}
100-
return aws.String(platformString(s.InstanceConfig.Platform.OS(), s.InstanceConfig.Platform.Arch())), nil
98+
return platformString(s.InstanceConfig.Platform.OS(), s.InstanceConfig.Platform.Arch())
10199
}
102100

103101
// BuildArgs returns a docker.BuildArguments object given a ws root directory.
@@ -126,22 +124,6 @@ func (s RequestDrivenWebService) ApplyEnv(envName string) (WorkloadManifest, err
126124
return &s, nil
127125
}
128126

129-
// WindowsCompatibility disallows unsupported services when deploying Windows containers on Fargate.
130-
// Here, this method is simply satisfying the WorkloadManifest interface.
131-
func (s *RequestDrivenWebService) windowsCompatibility() error {
132-
if s.InstanceConfig.Platform.IsEmpty() {
133-
return nil
134-
}
135-
// Error out if user added Windows as platform in manifest.
136-
if isWindowsPlatform(s.InstanceConfig.Platform) {
137-
return errAppRunnerInvalidPlatformWindows
138-
}
139-
if s.InstanceConfig.Platform.Arch() != ArchAMD64 || s.InstanceConfig.Platform.Arch() != ArchX86 {
140-
return fmt.Errorf("App Runner services can only build on %s and %s architectures", ArchAMD64, ArchX86)
141-
}
142-
return nil
143-
}
144-
145127
// newDefaultRequestDrivenWebService returns an empty RequestDrivenWebService with only the default values set.
146128
func newDefaultRequestDrivenWebService() *RequestDrivenWebService {
147129
return &RequestDrivenWebService{

0 commit comments

Comments
 (0)