Skip to content

Commit 82fdc27

Browse files
authored
chore: adds worker service to manifest (#2587)
Adds worker service file. Adds worker service tests. Adds worker service testdata to manifest. Adds worker service type to svc.go. Adds worker service case to workload.go Addresses #2550 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 539d7fa commit 82fdc27

File tree

10 files changed

+988
-22
lines changed

10 files changed

+988
-22
lines changed

internal/pkg/manifest/backend_svc.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@ func (s *BackendService) MarshalBinary() ([]byte, error) {
6060
content, err := s.parser.Parse(backendSvcManifestPath, *s, template.WithFuncs(map[string]interface{}{
6161
"fmtSlice": template.FmtSliceFunc,
6262
"quoteSlice": template.QuoteSliceFunc,
63-
"dirName": tplDirName,
6463
}))
6564
if err != nil {
6665
return nil, err

internal/pkg/manifest/lb_web_svc.go

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ package manifest
55

66
import (
77
"errors"
8-
"path/filepath"
98
"time"
109

1110
"github.com/aws/aws-sdk-go/aws"
@@ -124,19 +123,13 @@ func newDefaultLoadBalancedWebService() *LoadBalancedWebService {
124123
// MarshalBinary serializes the manifest object into a binary YAML document.
125124
// Implements the encoding.BinaryMarshaler interface.
126125
func (s *LoadBalancedWebService) MarshalBinary() ([]byte, error) {
127-
content, err := s.parser.Parse(lbWebSvcManifestPath, *s, template.WithFuncs(map[string]interface{}{
128-
"dirName": tplDirName,
129-
}))
126+
content, err := s.parser.Parse(lbWebSvcManifestPath, *s)
130127
if err != nil {
131128
return nil, err
132129
}
133130
return content.Bytes(), nil
134131
}
135132

136-
func tplDirName(s string) string {
137-
return filepath.Dir(s)
138-
}
139-
140133
// BuildRequired returns if the service requires building from the local Dockerfile.
141134
func (s *LoadBalancedWebService) BuildRequired() (bool, error) {
142135
return requiresBuild(s.ImageConfig.Image)

internal/pkg/manifest/rd_web_svc.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,7 @@ func newDefaultRequestDrivenWebService() *RequestDrivenWebService {
7777
// MarshalBinary serializes the manifest object into a binary YAML document.
7878
// Implements the encoding.BinaryMarshaler interface.
7979
func (s *RequestDrivenWebService) MarshalBinary() ([]byte, error) {
80-
content, err := s.parser.Parse(requestDrivenWebSvcManifestPath, *s, template.WithFuncs(map[string]interface{}{
81-
"dirName": tplDirName,
82-
}))
80+
content, err := s.parser.Parse(requestDrivenWebSvcManifestPath, *s)
8381
if err != nil {
8482
return nil, err
8583
}

internal/pkg/manifest/svc.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ const (
2121
RequestDrivenWebServiceType = "Request-Driven Web Service"
2222
// BackendServiceType is a service that cannot be accessed from the internet but can be reached from other services.
2323
BackendServiceType = "Backend Service"
24+
// WorkerServiceType is a worker service that manages the consumption of messages.
25+
WorkerServiceType = "Worker Service"
2426
)
2527

2628
// ServiceTypes are the supported service manifest types.
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# The manifest for the "testers" service.
2+
# Read the full specification for the "Worker Service" type at:
3+
# https://aws.github.io/copilot-cli/docs/manifest/worker-service/
4+
5+
# Your service name will be used in naming your resources like log groups, ECS services, etc.
6+
name: testers
7+
type: Worker Service
8+
9+
# Configuration for your containers and service.
10+
image:
11+
# Docker build arguments.
12+
build: ./testers/Dockerfile
13+
14+
cpu: 256 # Number of CPU units for the task.
15+
memory: 512 # Amount of memory in MiB used by the task.
16+
count: 1 # Number of tasks that should be running in your service.
17+
exec: true # Enable running commands in your container.
18+
# You can register to topics from other services.
19+
# The events will be available in an SQS queue via the env var $COPILOT_SQS_QUEUE_ARN
20+
# subscribe:
21+
# topics:
22+
# - name: topic-from-another-service
23+
# service: another-service
24+
25+
# Optional fields for more advanced use-cases.
26+
#
27+
#variables: # Pass environment variables as key value pairs.
28+
# LOG_LEVEL: info
29+
30+
#secrets: # Pass secrets from AWS Systems Manager (SSM) Parameter Store.
31+
# GITHUB_TOKEN: GITHUB_TOKEN # The key is the name of the environment variable, the value is the name of the SSM parameter.
32+
33+
# You can override any of the values defined above by environment.
34+
#environments:
35+
# test:
36+
# count: 2 # Number of tasks to run for the "test" environment.
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# The manifest for the "testers" service.
2+
# Read the full specification for the "Worker Service" type at:
3+
# https://aws.github.io/copilot-cli/docs/manifest/worker-service/
4+
5+
# Your service name will be used in naming your resources like log groups, ECS services, etc.
6+
name: testers
7+
type: Worker Service
8+
9+
# Configuration for your containers and service.
10+
image:
11+
# Docker build arguments.
12+
build: ./testers/Dockerfile
13+
14+
cpu: 256 # Number of CPU units for the task.
15+
memory: 512 # Amount of memory in MiB used by the task.
16+
count: 1 # Number of tasks that should be running in your service.
17+
exec: true # Enable running commands in your container.
18+
# The events will be available in an SQS queue via the env var $COPILOT_SQS_QUEUE_ARN
19+
subscribe:
20+
topics:
21+
- name: testTopic
22+
service: service4TestTopic
23+
- name: testTopic2
24+
service: service4TestTopic2
25+
26+
# Optional fields for more advanced use-cases.
27+
#
28+
#variables: # Pass environment variables as key value pairs.
29+
# LOG_LEVEL: info
30+
31+
#secrets: # Pass secrets from AWS Systems Manager (SSM) Parameter Store.
32+
# GITHUB_TOKEN: GITHUB_TOKEN # The key is the name of the environment variable, the value is the name of the SSM parameter.
33+
34+
# You can override any of the values defined above by environment.
35+
#environments:
36+
# test:
37+
# count: 2 # Number of tasks to run for the "test" environment.

internal/pkg/manifest/worker_svc.go

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package manifest
5+
6+
import (
7+
"github.com/aws/aws-sdk-go/aws"
8+
"github.com/aws/copilot-cli/internal/pkg/template"
9+
"github.com/imdario/mergo"
10+
)
11+
12+
const (
13+
workerSvcManifestPath = "workloads/services/worker/manifest.yml"
14+
)
15+
16+
// WorkerService holds the configuration to create a worker service.
17+
type WorkerService struct {
18+
Workload `yaml:",inline"`
19+
WorkerServiceConfig `yaml:",inline"`
20+
// Use *WorkerServiceConfig because of https://github.com/imdario/mergo/issues/146
21+
Environments map[string]*WorkerServiceConfig `yaml:",flow"`
22+
23+
parser template.Parser
24+
}
25+
26+
// WorkerServiceConfig holds the configuration that can be overridden per environments.
27+
type WorkerServiceConfig struct {
28+
ImageConfig ImageWithHealthcheck `yaml:"image,flow"`
29+
ImageOverride `yaml:",inline"`
30+
TaskConfig `yaml:",inline"`
31+
*Logging `yaml:"logging,flow"`
32+
Sidecars map[string]*SidecarConfig `yaml:"sidecars"`
33+
Subscribe *SubscribeConfig `yaml:"subscribe"`
34+
Network *NetworkConfig `yaml:"network"`
35+
}
36+
37+
// WorkerServiceProps represents the configuration needed to create a worker service.
38+
type WorkerServiceProps struct {
39+
WorkloadProps
40+
HealthCheck *ContainerHealthCheck // Optional healthcheck configuration.
41+
Topics *[]TopicSubscription // Optional topics for subscriptions
42+
}
43+
44+
// SubscribeConfig represents the configurable options for setting up subscriptions.
45+
type SubscribeConfig struct {
46+
Topics *[]TopicSubscription `yaml:"topics"`
47+
}
48+
49+
// TopicSubscription represents the configurable options for setting up a SNS Topic Subscription.
50+
type TopicSubscription struct {
51+
Name string `yaml:"name"`
52+
Service string `yaml:"service"`
53+
}
54+
55+
// NewWorkerService applies the props to a default Worker service configuration with
56+
// minimal cpu/memory thresholds, single replica, no healthcheck, and then returns it.
57+
func NewWorkerService(props WorkerServiceProps) *WorkerService {
58+
svc := newDefaultWorkerService()
59+
// Apply overrides.
60+
svc.Name = stringP(props.Name)
61+
svc.WorkerServiceConfig.ImageConfig.Image.Location = stringP(props.Image)
62+
svc.WorkerServiceConfig.ImageConfig.Build.BuildArgs.Dockerfile = stringP(props.Dockerfile)
63+
svc.WorkerServiceConfig.ImageConfig.HealthCheck = props.HealthCheck
64+
svc.WorkerServiceConfig.Subscribe.Topics = props.Topics
65+
svc.parser = template.New()
66+
return svc
67+
}
68+
69+
// newDefaultWorkerService returns a Worker service with minimal task sizes and a single replica.
70+
func newDefaultWorkerService() *WorkerService {
71+
return &WorkerService{
72+
Workload: Workload{
73+
Type: aws.String(WorkerServiceType),
74+
},
75+
WorkerServiceConfig: WorkerServiceConfig{
76+
ImageConfig: ImageWithHealthcheck{},
77+
Subscribe: &SubscribeConfig{},
78+
TaskConfig: TaskConfig{
79+
CPU: aws.Int(256),
80+
Memory: aws.Int(512),
81+
Count: Count{
82+
Value: aws.Int(1),
83+
},
84+
ExecuteCommand: ExecuteCommand{
85+
Enable: aws.Bool(false),
86+
},
87+
},
88+
Network: &NetworkConfig{
89+
VPC: &vpcConfig{
90+
Placement: aws.String(PublicSubnetPlacement),
91+
},
92+
},
93+
},
94+
}
95+
}
96+
97+
// MarshalBinary serializes the manifest object into a binary YAML document.
98+
// Implements the encoding.BinaryMarshaler interface.
99+
func (s *WorkerService) MarshalBinary() ([]byte, error) {
100+
content, err := s.parser.Parse(workerSvcManifestPath, *s, template.WithFuncs(map[string]interface{}{
101+
"fmtSlice": template.FmtSliceFunc,
102+
"quoteSlice": template.QuoteSliceFunc,
103+
}))
104+
if err != nil {
105+
return nil, err
106+
}
107+
return content.Bytes(), nil
108+
}
109+
110+
// BuildRequired returns if the service requires building from the local Dockerfile.
111+
func (s *WorkerService) BuildRequired() (bool, error) {
112+
return requiresBuild(s.ImageConfig.Image)
113+
}
114+
115+
// BuildArgs returns a docker.BuildArguments object for the service given a workspace root directory
116+
func (s *WorkerService) BuildArgs(wsRoot string) *DockerBuildArgs {
117+
return s.ImageConfig.BuildConfig(wsRoot)
118+
}
119+
120+
// ApplyEnv returns the service manifest with environment overrides.
121+
// If the environment passed in does not have any overrides then it returns itself.
122+
func (s WorkerService) ApplyEnv(envName string) (WorkloadManifest, error) {
123+
overrideConfig, ok := s.Environments[envName]
124+
if !ok {
125+
return &s, nil
126+
}
127+
128+
if overrideConfig == nil {
129+
return &s, nil
130+
}
131+
132+
envCount := overrideConfig.TaskConfig.Count
133+
if !envCount.IsEmpty() {
134+
s.TaskConfig.Count = envCount
135+
}
136+
137+
// Apply overrides to the original service s.
138+
err := mergo.Merge(&s, WorkerService{
139+
WorkerServiceConfig: *overrideConfig,
140+
}, mergo.WithOverride, mergo.WithOverwriteWithEmptyValue, mergo.WithTransformers(workloadTransformer{}))
141+
142+
if err != nil {
143+
return nil, err
144+
}
145+
s.Environments = nil
146+
return &s, nil
147+
}

0 commit comments

Comments
 (0)