Skip to content

Commit d5cba31

Browse files
authored
refactor(stack): move transformers from manifest to stack package (#1903)
<!-- Provide summary of changes --> To avoid a circular dependency and remove `manifest`'s de facto responsibility for the way its structs are used elsewhere, this PR moves all methods of the form: ```go package manifest func (s *ManifestStruct) Converter() template.Struct ``` to the form ```golang package stack func converter(s manifest.ManifestStruct) template.Struct ``` This makes `stack` responsible for the conversion logic and housing default values for fields that can be left unspecified in the manifest. <!-- 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 terms of your choice.
1 parent 085652d commit d5cba31

16 files changed

+487
-441
lines changed

internal/pkg/deploy/cloudformation/stack/backend_svc.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,11 +75,11 @@ func (s *BackendService) Template() (string, error) {
7575
if err != nil {
7676
return "", err
7777
}
78-
sidecars, err := s.manifest.Sidecar.Options()
78+
sidecars, err := convertSidecar(s.manifest.Sidecars)
7979
if err != nil {
8080
return "", fmt.Errorf("convert the sidecar configuration for service %s: %w", s.name, err)
8181
}
82-
autoscaling, err := s.manifest.Count.Autoscaling.Options()
82+
autoscaling, err := convertAutoscaling(&s.manifest.Count.Autoscaling)
8383
if err != nil {
8484
return "", fmt.Errorf("convert the Auto Scaling configuration for service %s: %w", s.name, err)
8585
}
@@ -90,7 +90,7 @@ func (s *BackendService) Template() (string, error) {
9090
Sidecars: sidecars,
9191
Autoscaling: autoscaling,
9292
HealthCheck: s.manifest.BackendServiceConfig.ImageConfig.HealthCheckOpts(),
93-
LogConfig: s.manifest.LogConfigOpts(),
93+
LogConfig: convertLogging(s.manifest.Logging),
9494
DesiredCountLambda: desiredCountLambda.String(),
9595
})
9696
if err != nil {

internal/pkg/deploy/cloudformation/stack/backend_svc_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,11 @@ func TestBackendService_Template(t *testing.T) {
5353
Port: 8080,
5454
}
5555
testBackendSvcManifestWithBadSidecar := manifest.NewBackendService(baseProps)
56-
testBackendSvcManifestWithBadSidecar.Sidecar = manifest.Sidecar{Sidecars: map[string]*manifest.SidecarConfig{
56+
testBackendSvcManifestWithBadSidecar.Sidecars = map[string]*manifest.SidecarConfig{
5757
"xray": {
5858
Port: aws.String("80/80/80"),
5959
},
60-
}}
60+
}
6161
badRange := manifest.Range("badRange")
6262
testBackendSvcManifestWithBadAutoScaling := manifest.NewBackendService(baseProps)
6363
testBackendSvcManifestWithBadAutoScaling.Count.Autoscaling = manifest.Autoscaling{

internal/pkg/deploy/cloudformation/stack/lb_web_svc.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,11 +104,11 @@ func (s *LoadBalancedWebService) Template() (string, error) {
104104
if err != nil {
105105
return "", err
106106
}
107-
sidecars, err := s.manifest.Sidecar.Options()
107+
sidecars, err := convertSidecar(s.manifest.Sidecars)
108108
if err != nil {
109109
return "", fmt.Errorf("convert the sidecar configuration for service %s: %w", s.name, err)
110110
}
111-
autoscaling, err := s.manifest.Count.Autoscaling.Options()
111+
autoscaling, err := convertAutoscaling(&s.manifest.Count.Autoscaling)
112112
if err != nil {
113113
return "", fmt.Errorf("convert the Auto Scaling configuration for service %s: %w", s.name, err)
114114
}
@@ -117,9 +117,9 @@ func (s *LoadBalancedWebService) Template() (string, error) {
117117
Secrets: s.manifest.Secrets,
118118
NestedStack: outputs,
119119
Sidecars: sidecars,
120-
LogConfig: s.manifest.LogConfigOpts(),
120+
LogConfig: convertLogging(s.manifest.Logging),
121121
Autoscaling: autoscaling,
122-
HTTPHealthCheck: s.manifest.HealthCheck.HTTPHealthCheckOpts(),
122+
HTTPHealthCheck: convertHTTPHealthCheck(&s.manifest.HealthCheck),
123123
AllowedSourceIps: s.manifest.AllowedSourceIps,
124124
RulePriorityLambda: rulePriorityLambda.String(),
125125
DesiredCountLambda: desiredCountLambda.String(),

internal/pkg/deploy/cloudformation/stack/lb_web_svc_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -308,11 +308,11 @@ func TestLoadBalancedWebService_Parameters(t *testing.T) {
308308
},
309309
}
310310
testLBWebServiceManifestWithSidecar.TargetContainer = aws.String("xray")
311-
testLBWebServiceManifestWithSidecar.Sidecar = manifest.Sidecar{Sidecars: map[string]*manifest.SidecarConfig{
311+
testLBWebServiceManifestWithSidecar.Sidecars = map[string]*manifest.SidecarConfig{
312312
"xray": {
313313
Port: aws.String("5000"),
314314
},
315-
}}
315+
}
316316
testLBWebServiceManifestWithStickiness := manifest.NewLoadBalancedWebService(baseProps)
317317
testLBWebServiceManifestWithStickinessRange := manifest.Range("2-100")
318318
testLBWebServiceManifestWithStickiness.Count = manifest.Count{

internal/pkg/deploy/cloudformation/stack/scheduled_job.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ func (j *ScheduledJob) Template() (string, error) {
122122
return "", err
123123
}
124124

125-
sidecars, err := j.manifest.Sidecar.Options()
125+
sidecars, err := convertSidecar(j.manifest.Sidecars)
126126
if err != nil {
127127
return "", fmt.Errorf("convert the sidecar configuration for job %s: %w", j.name, err)
128128
}
@@ -144,7 +144,7 @@ func (j *ScheduledJob) Template() (string, error) {
144144
Sidecars: sidecars,
145145
ScheduleExpression: schedule,
146146
StateMachine: stateMachine,
147-
LogConfig: j.manifest.LogConfigOpts(),
147+
LogConfig: convertLogging(j.manifest.Logging),
148148
})
149149
if err != nil {
150150
return "", fmt.Errorf("parse scheduled job template: %w", err)
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package stack
5+
6+
import (
7+
"fmt"
8+
"strings"
9+
"time"
10+
11+
"github.com/aws/aws-sdk-go/aws"
12+
"github.com/aws/copilot-cli/internal/pkg/manifest"
13+
"github.com/aws/copilot-cli/internal/pkg/template"
14+
)
15+
16+
const (
17+
defaultSidecarPort = "80"
18+
)
19+
20+
// convertSidecar converts the manifest sidecar configuration into a format parsable by the templates pkg.
21+
func convertSidecar(s map[string]*manifest.SidecarConfig) ([]*template.SidecarOpts, error) {
22+
if s == nil {
23+
return nil, nil
24+
}
25+
var sidecars []*template.SidecarOpts
26+
for name, config := range s {
27+
port, protocol, err := parsePortMapping(config.Port)
28+
if err != nil {
29+
return nil, err
30+
}
31+
sidecars = append(sidecars, &template.SidecarOpts{
32+
Name: aws.String(name),
33+
Image: config.Image,
34+
Port: port,
35+
Protocol: protocol,
36+
CredsParam: config.CredsParam,
37+
Secrets: config.Secrets,
38+
Variables: config.Variables,
39+
})
40+
}
41+
return sidecars, nil
42+
}
43+
44+
// Valid sidecar portMapping example: 2000/udp, or 2000 (default to be tcp).
45+
func parsePortMapping(s *string) (port *string, protocol *string, err error) {
46+
if s == nil {
47+
// default port for sidecar container to be 80.
48+
return aws.String(defaultSidecarPort), nil, nil
49+
}
50+
portProtocol := strings.Split(*s, "/")
51+
switch len(portProtocol) {
52+
case 1:
53+
return aws.String(portProtocol[0]), nil, nil
54+
case 2:
55+
return aws.String(portProtocol[0]), aws.String(portProtocol[1]), nil
56+
default:
57+
return nil, nil, fmt.Errorf("cannot parse port mapping from %s", *s)
58+
}
59+
}
60+
61+
// convertAutoscaling converts the service's Auto Scaling configuration into a format parsable
62+
// by the templates pkg.
63+
func convertAutoscaling(a *manifest.Autoscaling) (*template.AutoscalingOpts, error) {
64+
if a.IsEmpty() {
65+
return nil, nil
66+
}
67+
min, max, err := a.Range.Parse()
68+
if err != nil {
69+
return nil, err
70+
}
71+
autoscalingOpts := template.AutoscalingOpts{
72+
MinCapacity: &min,
73+
MaxCapacity: &max,
74+
}
75+
if a.CPU != nil {
76+
autoscalingOpts.CPU = aws.Float64(float64(*a.CPU))
77+
}
78+
if a.Memory != nil {
79+
autoscalingOpts.Memory = aws.Float64(float64(*a.Memory))
80+
}
81+
if a.Requests != nil {
82+
autoscalingOpts.Requests = aws.Float64(float64(*a.Requests))
83+
}
84+
if a.ResponseTime != nil {
85+
responseTime := float64(*a.ResponseTime) / float64(time.Second)
86+
autoscalingOpts.ResponseTime = aws.Float64(responseTime)
87+
}
88+
return &autoscalingOpts, nil
89+
}
90+
91+
// convertHTTPHealthCheck converts the ALB health check configuration into a format parsable by the templates pkg.
92+
func convertHTTPHealthCheck(hc *manifest.HealthCheckArgsOrString) template.HTTPHealthCheckOpts {
93+
opts := template.HTTPHealthCheckOpts{
94+
HealthCheckPath: manifest.DefaultHealthCheckPath,
95+
HealthyThreshold: hc.HealthCheckArgs.HealthyThreshold,
96+
UnhealthyThreshold: hc.HealthCheckArgs.UnhealthyThreshold,
97+
}
98+
if hc.HealthCheckArgs.Path != nil {
99+
opts.HealthCheckPath = *hc.HealthCheckArgs.Path
100+
} else if hc.HealthCheckPath != nil {
101+
opts.HealthCheckPath = *hc.HealthCheckPath
102+
}
103+
if hc.HealthCheckArgs.Interval != nil {
104+
opts.Interval = aws.Int64(int64(hc.HealthCheckArgs.Interval.Seconds()))
105+
}
106+
if hc.HealthCheckArgs.Timeout != nil {
107+
opts.Timeout = aws.Int64(int64(hc.HealthCheckArgs.Timeout.Seconds()))
108+
}
109+
return opts
110+
}
111+
112+
func convertLogging(lc *manifest.Logging) *template.LogConfigOpts {
113+
if lc == nil {
114+
return nil
115+
}
116+
return logConfigOpts(lc)
117+
}
118+
func logConfigOpts(lc *manifest.Logging) *template.LogConfigOpts {
119+
return &template.LogConfigOpts{
120+
Image: lc.LogImage(),
121+
ConfigFile: lc.ConfigFile,
122+
EnableMetadata: lc.GetEnableMetadata(),
123+
Destination: lc.Destination,
124+
SecretOptions: lc.SecretOptions,
125+
}
126+
}

0 commit comments

Comments
 (0)