Skip to content

Commit 3c212fb

Browse files
authored
docs: add environment storage into v1.26.0 blog post (#4511)
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 c1187e7 commit 3c212fb

2 files changed

Lines changed: 100 additions & 4 deletions

File tree

internal/pkg/cli/storage_init.go

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,7 @@ var validLifecycleOptions = []string{lifecycleWorkloadLevel, lifecycleEnvironmen
6666

6767
// General-purpose prompts, collected for all storage resources.
6868
var (
69-
fmtStorageInitTypePrompt = "What " + color.Emphasize("type") + " of storage would you like to associate with %s?"
70-
storageInitTypeHelp = `The type of storage you'd like to add to your workload.
69+
storageInitTypeHelp = `The type of storage you'd like to add to your workload.
7170
DynamoDB is a key-value and document database that delivers single-digit millisecond performance at any scale.
7271
S3 is a web object store built to store and retrieve any amount of data from anywhere on the Internet.
7372
Aurora Serverless is an on-demand autoscaling configuration for Amazon Aurora, a MySQL and PostgreSQL-compatible relational database.
@@ -343,8 +342,7 @@ func (o *initStorageOpts) validateOrAskStorageType() error {
343342
Hint: "SQL",
344343
},
345344
}
346-
result, err := o.prompt.SelectOption(fmt.Sprintf(
347-
fmtStorageInitTypePrompt, color.HighlightUserInput(o.workloadName)),
345+
result, err := o.prompt.SelectOption(o.storageTypePrompt(),
348346
storageInitTypeHelp,
349347
options,
350348
prompt.WithFinalMessage("Storage type:"))
@@ -355,6 +353,13 @@ func (o *initStorageOpts) validateOrAskStorageType() error {
355353
return o.validateStorageType()
356354
}
357355

356+
func (o *initStorageOpts) storageTypePrompt() string {
357+
if o.workloadName == "" {
358+
return "What " + color.Emphasize("type") + " of storage would you like to create?"
359+
}
360+
return fmt.Sprintf("What "+color.Emphasize("type")+" of storage would you like to associate with %s?", color.HighlightUserInput(o.workloadName))
361+
}
362+
358363
func (o *initStorageOpts) validateStorageType() error {
359364
if err := validateStorageType(o.storageType, validateStorageTypeOpts{
360365
ws: o.ws,

site/content/blogs/release-v126.en.md

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,97 @@ With rollback alarms configured in your service manifest, each time you run `svc
6767

6868
## `storage init` for environment addons
6969

70+
Previously, `copilot storage init` only supported storage addons attached to workloads: you need to run
71+
`copilot svc deploy` in order to deploy the storage, and the storage is deleted along with the service
72+
when you run `copilot svc delete`.
73+
74+
Now, you have the option to create environment storage addons: the storage is deployed when you run `copilot env deploy`,
75+
and isn't deleted until you delete the environment by running `copilot env delete`.
76+
77+
Similar to the workload storage, the environment storage is, under the hood, just another [environment addon](../docs/developing/addons/environment.en.md)!
78+
79+
### [Database-Per-Service](https://docs.aws.amazon.com/prescriptive-guidance/latest/modernization-data-persistence/database-per-service.html) By Default
80+
In the microservice world, it is generally recommended to set up data storage resources that are each private to a microservice,
81+
instead of monolith storages that are shared by multiple services.
82+
This pattern preserves the core characteristics of microservices - loose coupling.
83+
Copilot encourages you to follow this database-per-service pattern. By default, a storage resource that Copilot generates
84+
is assumed to be accessed by one service or job.
85+
86+
!!!note ""
87+
However, each user has its own unique situation. If you do need your data storage to be shared among multiple service,
88+
you can modify the Copilot-generated CloudFormation template in order to achieve your goal.
89+
90+
91+
Here is an example of prompts that you might see.
92+
!!! info ""
93+
94+
```term
95+
$ copilot storage init
96+
What type of storage would you like to create?
97+
> DynamoDB (NoSQL)
98+
S3 (Objects)
99+
Aurora Serverless (SQL)
100+
101+
Which workload needs access to the storage?
102+
> api
103+
backend
104+
105+
What would you like to name this DynamoDB Table? movies
106+
107+
Do you want the storage to be created and deleted with the api service?
108+
Yes, the storage should be created and deleted at the same time as api
109+
> No, the storage should be created and deleted at the environment level
110+
```
111+
You can skip the prompts using the flags. The following command is equivalent to the prompts above:
112+
```console
113+
copilot storage init \
114+
--storage-type "DynamoDB" \
115+
--workload "api" \
116+
--name "movies" \
117+
--lifecycle "environment"
118+
```
119+
120+
121+
After you've answered all the prompts or skipped them by using flags, Copilot will generate the CloudFormation template that defines the DynamoDB storage resource
122+
under your `copilot/environments` directory. In addition, it will generate the necessary access policy; here is one that grants "api" service
123+
access to the "movies" storage. The access policy is created as a workload addon, meaning that it is deployed and
124+
deleted at the same time as the "api" service.
125+
!!! info ""
126+
```
127+
copilot/
128+
├── environments/
129+
│ ├── addons/
130+
│ │ └── movies.yml # <- The CloudFormation template that defines the "movies" DynamoDB storage.
131+
│ └── test/
132+
│ └── manifest.yml
133+
└── api
134+
├── addons/
135+
│ └── movies-access-policy.yml # <- The CloudFormation template that defines the access policy.
136+
└─── manifest.yml
137+
```
138+
139+
Depending on the storage type, and the type of the workload that is fronting the storage, Copilot may generate different
140+
CloudFormation files.
141+
142+
???- note "Sample files generated for an Aurora Serverless fronted by a Request-Driven Web Service"
143+
```
144+
# Example: an Aurora Serverless v2 storage whose lifecycle is at the environment-level, faced by a Request-Driven Web Service.
145+
copilot/
146+
├── environments/
147+
│ └── addons/
148+
│ ├── addons.parameters.yml # The extra parameters required by the Aurora Serverless v2 storage.
149+
│ └── user.yml # An Aurora Serverless v2 storage
150+
└── api # "api" is a Request-Driven Web Service
151+
└── addons/
152+
├── addons.parameters.yml # The extra parameters required by the ingress resource.
153+
└── user-ingress.yml # A security group ingress that grants "api" access to the "api" storage"
154+
```
155+
156+
157+
158+
Also check out our [storage page](../docs/developing/storage.en.md) for more information!
159+
160+
70161
## Request-Driven Web Service secrets support
71162
You can now add your secrets (from SSM Parameter Store or AWS Secrets Manager) to your App Runner service as environment variables using Copilot.
72163

0 commit comments

Comments
 (0)