forked from aws/copilot-cli
-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add new pattern "Request-Driven Web Service" to init AWS App Ru…
…nner services (aws#2340) By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.
- Loading branch information
1 parent
91a7045
commit 5f8077a
Showing
113 changed files
with
7,341 additions
and
968 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package apprunner_test | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
"time" | ||
|
||
"github.com/aws/copilot-cli/e2e/internal/client" | ||
. "github.com/onsi/ginkgo" | ||
. "github.com/onsi/gomega" | ||
) | ||
|
||
var cli *client.CLI | ||
var appName string | ||
|
||
const svcName = "front-end" | ||
const envName = "test" | ||
|
||
/** | ||
The Init Suite runs through the copilot init workflow for a brand new | ||
application. It creates a single environment, deploys a service to it, and then | ||
tears it down. | ||
*/ | ||
func TestInit(t *testing.T) { | ||
RegisterFailHandler(Fail) | ||
RunSpecs(t, "App Runner Suite") | ||
} | ||
|
||
var _ = BeforeSuite(func() { | ||
var err error | ||
cli, err = client.NewCLI() | ||
Expect(err).NotTo(HaveOccurred()) | ||
Expect(err).NotTo(HaveOccurred()) | ||
appName = fmt.Sprintf("e2e-apprunner-%d", time.Now().Unix()) | ||
}) | ||
|
||
var _ = AfterSuite(func() { | ||
_, err := cli.SvcDelete(svcName) | ||
Expect(err).NotTo(HaveOccurred()) | ||
|
||
_, err = cli.EnvDelete(envName) | ||
Expect(err).NotTo(HaveOccurred()) | ||
|
||
_, err = cli.AppDelete() | ||
Expect(err).NotTo(HaveOccurred()) | ||
}) | ||
|
||
func BeforeAll(fn func()) { | ||
first := true | ||
BeforeEach(func() { | ||
if first { | ||
fn() | ||
first = false | ||
} | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,269 @@ | ||
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package apprunner_test | ||
|
||
import ( | ||
"fmt" | ||
"net/http" | ||
|
||
"github.com/aws/copilot-cli/e2e/internal/client" | ||
. "github.com/onsi/ginkgo" | ||
. "github.com/onsi/gomega" | ||
) | ||
|
||
type countAssertionTracker struct { | ||
expected int | ||
actual int | ||
} | ||
|
||
var _ = Describe("App Runner", func() { | ||
|
||
var ( | ||
initErr error | ||
) | ||
|
||
BeforeAll(func() { | ||
_, initErr = cli.Init(&client.InitRequest{ | ||
AppName: appName, | ||
WorkloadName: svcName, | ||
ImageTag: "gallopinggurdey", | ||
Dockerfile: "./front-end/Dockerfile", | ||
WorkloadType: "Request-Driven Web Service", | ||
Deploy: true, | ||
SvcPort: "80", | ||
}) | ||
}) | ||
|
||
Context("run init with app runner", func() { | ||
It("init does not return an error", func() { | ||
Expect(initErr).NotTo(HaveOccurred()) | ||
}) | ||
}) | ||
|
||
Context("run svc ls to ensure the service was created", func() { | ||
var ( | ||
svcList *client.SvcListOutput | ||
svcListError error | ||
) | ||
|
||
BeforeAll(func() { | ||
svcList, svcListError = cli.SvcList(appName) | ||
}) | ||
|
||
It("should not return an error", func() { | ||
Expect(svcListError).NotTo(HaveOccurred()) | ||
}) | ||
|
||
It("should return one service", func() { | ||
Expect(len(svcList.Services)).To(Equal(1)) | ||
Expect(svcList.Services[0].Name).To(Equal(svcName)) | ||
Expect(svcList.Services[0].AppName).To(Equal(appName)) | ||
Expect(svcList.Services[0].Type).To(Equal("Request-Driven Web Service")) | ||
}) | ||
}) | ||
|
||
Context("run svc status to ensure that the service is healthy", func() { | ||
var ( | ||
svcStatus *client.SvcStatusOutput | ||
svcStatusError error | ||
) | ||
|
||
BeforeAll(func() { | ||
svcStatus, svcStatusError = cli.SvcStatus(&client.SvcStatusRequest{ | ||
Name: svcName, | ||
AppName: appName, | ||
EnvName: envName, | ||
}) | ||
}) | ||
|
||
It("should not return an error", func() { | ||
Expect(svcStatusError).NotTo(HaveOccurred()) | ||
}) | ||
|
||
It("should return app runner service status", func() { | ||
Expect(svcStatus.Service.Status).To(Equal("RUNNING")) | ||
}) | ||
}) | ||
|
||
Context("run storage init and svc deploy to create an S3 bucket", func() { | ||
var ( | ||
storageInitErr error | ||
deployErr error | ||
) | ||
|
||
BeforeAll(func() { | ||
_, storageInitErr = cli.StorageInit(&client.StorageInitRequest{ | ||
StorageName: "s3storage", | ||
StorageType: "S3", | ||
WorkloadName: svcName, | ||
}) | ||
_, deployErr = cli.SvcDeploy(&client.SvcDeployInput{ | ||
EnvName: envName, | ||
Name: svcName, | ||
}) | ||
}) | ||
|
||
It("should not return an error", func() { | ||
Expect(storageInitErr).NotTo(HaveOccurred()) | ||
Expect(deployErr).NotTo(HaveOccurred()) | ||
}) | ||
}) | ||
|
||
Context("run svc show to retrieve the service configuration, resources, and endpoint, then query the service", func() { | ||
var ( | ||
svc *client.SvcShowOutput | ||
svcShowError error | ||
) | ||
|
||
BeforeAll(func() { | ||
svc, svcShowError = cli.SvcShow(&client.SvcShowRequest{ | ||
Name: svcName, | ||
AppName: appName, | ||
Resources: true, | ||
}) | ||
}) | ||
|
||
It("should not return an error", func() { | ||
Expect(svcShowError).NotTo(HaveOccurred()) | ||
}) | ||
|
||
It("should return correct configuration", func() { | ||
Expect(svc.SvcName).To(Equal(svcName)) | ||
Expect(svc.AppName).To(Equal(appName)) | ||
Expect(len(svc.Configs)).To(Equal(1)) | ||
Expect(svc.Configs[0].Environment).To(Equal(envName)) | ||
Expect(svc.Configs[0].CPU).To(Equal("1024")) | ||
Expect(svc.Configs[0].Memory).To(Equal("2048")) | ||
Expect(svc.Configs[0].Port).To(Equal("80")) | ||
}) | ||
|
||
It("should return correct environment variables", func() { | ||
fmt.Printf("\n\nenvironment variables: %+v\n\n", svc.Variables) | ||
Expect(len(svc.Variables)).To(Equal(4)) | ||
expectedVars := map[string]string{ | ||
"COPILOT_APPLICATION_NAME": appName, | ||
"COPILOT_ENVIRONMENT_NAME": envName, | ||
"COPILOT_SERVICE_NAME": svcName, | ||
"S3STORAGE_NAME": fmt.Sprintf("%s-%s-%s-s3storage", appName, envName, svcName), | ||
} | ||
for _, variable := range svc.Variables { | ||
Expect(variable.Value).To(Equal(expectedVars[variable.Name])) | ||
} | ||
}) | ||
|
||
It("should return the correct resources", func() { | ||
Expect(len(svc.Resources)).To(Equal(1)) | ||
Expect(svc.Resources[envName]).NotTo(BeNil()) | ||
Expect(len(svc.Resources[envName])).To(Equal(4)) | ||
expectedTypes := map[string]*countAssertionTracker{ | ||
"AWS::IAM::Role": {2, 0}, | ||
"AWS::CloudFormation::Stack": {1, 0}, | ||
"AWS::AppRunner::Service": {1, 0}, | ||
} | ||
|
||
for _, r := range svc.Resources[envName] { | ||
if expectedTypes[r.Type] == nil { | ||
expectedTypes[r.Type] = &countAssertionTracker{0, 0} | ||
} | ||
expectedTypes[r.Type].actual++ | ||
} | ||
|
||
for t, v := range expectedTypes { | ||
Expect(v.actual).To( | ||
Equal(v.expected), | ||
fmt.Sprintf("Expected %v resources of type %v, received %v", v.expected, t, v.actual)) | ||
} | ||
}) | ||
|
||
It("should return svc endpoints", func() { | ||
Expect(len(svc.Routes)).To(Equal(1)) | ||
Expect(svc.Routes[0].Environment).To(Equal(envName)) | ||
Expect(svc.Routes[0].URL).NotTo(BeEmpty()) | ||
Eventually(func() (int, error) { | ||
resp, fetchErr := http.Get(svc.Routes[0].URL) | ||
return resp.StatusCode, fetchErr | ||
}, "30s", "1s").Should(Equal(200)) | ||
}) | ||
}) | ||
|
||
Context("run svc logs to troubleshoot", func() { | ||
var ( | ||
svcLogs []client.SvcLogsOutput | ||
svcLogsErr error | ||
) | ||
|
||
BeforeAll(func() { | ||
svcLogs, svcLogsErr = cli.SvcLogs(&client.SvcLogsRequest{ | ||
AppName: appName, | ||
Name: svcName, | ||
EnvName: "test", | ||
Since: "1h", | ||
}) | ||
}) | ||
|
||
It("should not return an error", func() { | ||
Expect(svcLogsErr).NotTo(HaveOccurred()) | ||
}) | ||
|
||
It("should return valid log lines", func() { | ||
Expect(len(svcLogs)).To(BeNumerically(">", 0)) | ||
for _, logLine := range svcLogs { | ||
Expect(logLine.Message).NotTo(Equal("")) | ||
Expect(logLine.LogStreamName).NotTo(Equal("")) | ||
Expect(logLine.Timestamp).NotTo(Equal(0)) | ||
Expect(logLine.IngestionTime).NotTo(Equal(0)) | ||
} | ||
}) | ||
}) | ||
|
||
Context("run pause and then resume the service", func() { | ||
var ( | ||
svcPauseError error | ||
pausedSvcStatus *client.SvcStatusOutput | ||
pausedSvcStatusError error | ||
svcResumeError error | ||
resumedSvcStatus *client.SvcStatusOutput | ||
resumedSvcStatusError error | ||
) | ||
|
||
BeforeAll(func() { | ||
_, svcPauseError = cli.SvcPause(&client.SvcPauseRequest{ | ||
AppName: appName, | ||
EnvName: envName, | ||
Name: svcName, | ||
}) | ||
pausedSvcStatus, pausedSvcStatusError = cli.SvcStatus(&client.SvcStatusRequest{ | ||
Name: svcName, | ||
AppName: appName, | ||
EnvName: envName, | ||
}) | ||
_, svcResumeError = cli.SvcResume(&client.SvcResumeRequest{ | ||
AppName: appName, | ||
EnvName: envName, | ||
Name: svcName, | ||
}) | ||
resumedSvcStatus, resumedSvcStatusError = cli.SvcStatus(&client.SvcStatusRequest{ | ||
Name: svcName, | ||
AppName: appName, | ||
EnvName: envName, | ||
}) | ||
}) | ||
|
||
It("should not an return error", func() { | ||
Expect(svcPauseError).NotTo(HaveOccurred()) | ||
Expect(pausedSvcStatusError).NotTo(HaveOccurred()) | ||
Expect(svcResumeError).NotTo(HaveOccurred()) | ||
Expect(resumedSvcStatusError).NotTo(HaveOccurred()) | ||
}) | ||
|
||
It("should successfully pause service", func() { | ||
Expect(pausedSvcStatus.Service.Status).To(Equal("PAUSED")) | ||
}) | ||
|
||
It("should successfully resume service", func() { | ||
Expect(resumedSvcStatus.Service.Status).To(Equal("RUNNING")) | ||
}) | ||
}) | ||
|
||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
FROM nginx | ||
|
||
RUN mkdir -p /www/data/ | ||
COPY index.html /www/data/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
<meta http-equiv="X-UA-Compatible" content="ie=edge"> | ||
<title>AWS Copilot CLI</title> | ||
</head> | ||
<body style="background-color:rgb(35, 47, 62);"> | ||
<div style='vertical-align: middle; margin:auto; width:50%; padding-top:200px; text-align: center;'> | ||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="141px" height="171px" viewBox="-0.5 -0.5 81 101"><defs><linearGradient x1="0%" y1="0%" x2="0%" y2="100%" id="mx-gradient-232f3e-100-232f3e-100-s-0"><stop offset="0%" style="stop-color:#232F3E"/><stop offset="100%" style="stop-color:#232F3E"/></linearGradient></defs><g><path d="M 0 0 L 80 0 L 80 100 L 0 100 Z" fill="#ffffff" stroke="none" pointer-events="all"/><path d="M 1 1 L 79 1 L 79 79 L 1 79 Z" fill="url(#mx-gradient-232f3e-100-232f3e-100-s-0)" stroke="none" pointer-events="all"/><path d="M 38.07 13.01 C 37.9 13.01 37.73 13.06 37.57 13.15 L 16.61 25.24 C 16.28 25.43 16.08 25.79 16.08 26.17 L 16.08 52.54 C 16.09 52.92 16.29 53.26 16.61 53.45 L 39.42 66.81 C 39.75 67.01 40.16 67.01 40.49 66.81 L 61.42 54.63 C 61.75 54.44 61.95 54.09 61.95 53.71 C 61.95 53.33 61.74 52.98 61.41 52.79 L 51.36 47.12 C 51.03 46.94 50.63 46.94 50.31 47.13 L 40.07 53.14 L 28.12 46.26 L 28.12 32.5 L 38.63 26.49 C 38.96 26.3 39.16 25.95 39.16 25.57 L 39.16 14.07 C 39.16 13.78 39.04 13.51 38.84 13.31 C 38.64 13.11 38.36 13 38.07 13.01 Z M 42.08 13.05 C 41.79 13.04 41.51 13.15 41.31 13.35 C 41.1 13.55 40.98 13.82 40.98 14.11 L 40.98 25.62 C 40.99 26 41.19 26.35 41.52 26.54 L 51.84 32.55 L 51.84 44.59 C 51.84 44.96 52.04 45.31 52.37 45.5 L 62.32 51.28 C 62.65 51.47 63.05 51.47 63.38 51.28 C 63.71 51.09 63.92 50.74 63.92 50.36 L 63.92 26.19 C 63.91 25.81 63.71 25.46 63.38 25.28 L 42.58 13.2 C 42.43 13.11 42.25 13.06 42.08 13.05 Z M 37.05 15.91 L 37.05 24.96 L 26.54 30.97 C 26.21 31.16 26 31.51 26 31.89 L 26 46.87 C 26 47.25 26.2 47.6 26.54 47.79 L 39.54 55.28 C 39.87 55.47 40.28 55.47 40.6 55.28 L 50.85 49.27 L 58.76 53.73 L 39.96 64.67 L 18.2 51.92 L 18.2 26.77 Z M 43.11 15.95 L 61.8 26.8 L 61.8 48.52 L 53.96 43.97 L 53.96 31.94 C 53.96 31.56 53.76 31.21 53.43 31.02 L 43.11 25.01 Z" fill="#ffffff" stroke="none" pointer-events="all"/><g transform="translate(8.5,84.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="62" height="10" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 10px; font-family: Helvetica; color: rgb(35, 47, 62); line-height: 1.2; vertical-align: top; width: 63px; white-space: nowrap; overflow-wrap: normal; font-weight: bold; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;white-space:normal;">Amazon ECS</div></div></foreignObject><text x="31" y="10" fill="#232F3E" text-anchor="middle" font-size="10px" font-family="Helvetica" font-weight="bold">Amazon ECS</text></switch></g></g></svg> | ||
</div> | ||
</body> | ||
</html> |
Oops, something went wrong.