diff --git a/e2e/apprunner/back-end/Dockerfile b/e2e/apprunner/back-end/Dockerfile index 02429bdb926..6efeda25764 100644 --- a/e2e/apprunner/back-end/Dockerfile +++ b/e2e/apprunner/back-end/Dockerfile @@ -1,33 +1,15 @@ -# We specify the base image we need for our -# go application -FROM golang:1.14 AS builder -# We create an /app directory within our -# image that will hold our application source -# files -RUN mkdir /app -# We copy everything in the root directory -# into our /app directory -ADD . /app -# We specify that we now wish to execute -# any further commands inside our /app -# directory -WORKDIR /app -# Avoid the GoProxy +FROM public.ecr.aws/docker/library/golang:1.19 as builder + ENV GOPROXY=direct -# we run go build to compile the binary -# executable of our Go program -RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o e2e-service ./ +WORKDIR /go/src/app + +COPY . . + +RUN go mod download +RUN CGO_ENABLED=0 go build -o /go/bin/app ./ -# To make our images smaller, use alpine and copy in the service binary. -FROM alpine:latest -# Install certs -RUN apk --no-cache add ca-certificates -# Copy the binary from the builder image -COPY --from=builder /app ./ -# Make the binary executable -RUN chmod +x ./e2e-service +FROM gcr.io/distroless/static -# Start the service -ENTRYPOINT ["./e2e-service"] -# The service runs on port 80 +COPY --from=builder /go/bin/app / EXPOSE 80 +ENTRYPOINT ["/app"] \ No newline at end of file diff --git a/e2e/apprunner/back-end/go.mod b/e2e/apprunner/back-end/go.mod index f477f35065f..fceae6aab61 100644 --- a/e2e/apprunner/back-end/go.mod +++ b/e2e/apprunner/back-end/go.mod @@ -1,5 +1,3 @@ module github.com/aws/copilot-cli/e2e/appprunner/back-end -go 1.14 - -require github.com/julienschmidt/httprouter v1.3.0 // indirect +go 1.19 diff --git a/e2e/apprunner/back-end/go.sum b/e2e/apprunner/back-end/go.sum index 096c54e6309..e69de29bb2d 100644 --- a/e2e/apprunner/back-end/go.sum +++ b/e2e/apprunner/back-end/go.sum @@ -1,2 +0,0 @@ -github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= diff --git a/e2e/apprunner/back-end/main.go b/e2e/apprunner/back-end/main.go index 279a6f6e0e3..65571639e4e 100644 --- a/e2e/apprunner/back-end/main.go +++ b/e2e/apprunner/back-end/main.go @@ -4,33 +4,32 @@ package main import ( + "errors" "log" "net/http" - - "github.com/julienschmidt/httprouter" ) var message = "hello world" // HealthCheck just returns true if the service is up. -func HealthCheck(w http.ResponseWriter, req *http.Request, ps httprouter.Params) { +func HealthCheck(w http.ResponseWriter, req *http.Request) { log.Println("🚑 healthcheck ok!") w.WriteHeader(http.StatusOK) } // ServiceDiscoveryGet just returns true no matter what -func ServiceDiscoveryGet(w http.ResponseWriter, req *http.Request, ps httprouter.Params) { +func ServiceDiscoveryGet(w http.ResponseWriter, req *http.Request) { log.Printf("Get on ServiceDiscovery endpoint Succeeded with message %s\n", message) w.WriteHeader(http.StatusOK) w.Write([]byte(message)) } func main() { - router := httprouter.New() - router.GET("/service-discovery/", ServiceDiscoveryGet) - - // Health Check - router.GET("/", HealthCheck) + http.Handle("/", http.HandlerFunc(HealthCheck)) + http.Handle("/service-discovery", http.HandlerFunc(ServiceDiscoveryGet)) - log.Fatal(http.ListenAndServe(":80", router)) + err := http.ListenAndServe(":80", nil) + if !errors.Is(err, http.ErrServerClosed) { + log.Fatalf("listen and serve: %s", err) + } } diff --git a/e2e/apprunner/front-end/Dockerfile b/e2e/apprunner/front-end/Dockerfile index 02429bdb926..6efeda25764 100644 --- a/e2e/apprunner/front-end/Dockerfile +++ b/e2e/apprunner/front-end/Dockerfile @@ -1,33 +1,15 @@ -# We specify the base image we need for our -# go application -FROM golang:1.14 AS builder -# We create an /app directory within our -# image that will hold our application source -# files -RUN mkdir /app -# We copy everything in the root directory -# into our /app directory -ADD . /app -# We specify that we now wish to execute -# any further commands inside our /app -# directory -WORKDIR /app -# Avoid the GoProxy +FROM public.ecr.aws/docker/library/golang:1.19 as builder + ENV GOPROXY=direct -# we run go build to compile the binary -# executable of our Go program -RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o e2e-service ./ +WORKDIR /go/src/app + +COPY . . + +RUN go mod download +RUN CGO_ENABLED=0 go build -o /go/bin/app ./ -# To make our images smaller, use alpine and copy in the service binary. -FROM alpine:latest -# Install certs -RUN apk --no-cache add ca-certificates -# Copy the binary from the builder image -COPY --from=builder /app ./ -# Make the binary executable -RUN chmod +x ./e2e-service +FROM gcr.io/distroless/static -# Start the service -ENTRYPOINT ["./e2e-service"] -# The service runs on port 80 +COPY --from=builder /go/bin/app / EXPOSE 80 +ENTRYPOINT ["/app"] \ No newline at end of file diff --git a/e2e/apprunner/front-end/go.mod b/e2e/apprunner/front-end/go.mod index 6e8c75a4840..fb69e0b1cec 100644 --- a/e2e/apprunner/front-end/go.mod +++ b/e2e/apprunner/front-end/go.mod @@ -1,9 +1,23 @@ module github.com/aws/copilot-cli/e2e/apprunner/front-end -go 1.14 +go 1.19 require ( - github.com/aws/aws-sdk-go v1.43.6 - github.com/julienschmidt/httprouter v1.3.0 + github.com/aws/aws-sdk-go-v2 v1.16.16 + github.com/aws/aws-sdk-go-v2/config v1.17.8 + github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.16.2 github.com/lib/pq v1.10.4 ) + +require ( + github.com/aws/aws-sdk-go-v2/credentials v1.12.21 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.17 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.23 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.17 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.3.24 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.17 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.11.23 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.6 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.16.19 // indirect + github.com/aws/smithy-go v1.13.3 // indirect +) diff --git a/e2e/apprunner/front-end/go.sum b/e2e/apprunner/front-end/go.sum index c1f8c44d873..2ace2e1ac00 100644 --- a/e2e/apprunner/front-end/go.sum +++ b/e2e/apprunner/front-end/go.sum @@ -1,28 +1,37 @@ -github.com/aws/aws-sdk-go v1.43.6 h1:FkwmndZR4LjnT2fiKaD18bnqfQ188E8A1IMNI5rcv00= -github.com/aws/aws-sdk-go v1.43.6/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= -github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/aws/aws-sdk-go-v2 v1.16.16 h1:M1fj4FE2lB4NzRb9Y0xdWsn2P0+2UHVxwKyOa4YJNjk= +github.com/aws/aws-sdk-go-v2 v1.16.16/go.mod h1:SwiyXi/1zTUZ6KIAmLK5V5ll8SiURNUYOqTerZPaF9k= +github.com/aws/aws-sdk-go-v2/config v1.17.8 h1:b9LGqNnOdg9vR4Q43tBTVWk4J6F+W774MSchvKJsqnE= +github.com/aws/aws-sdk-go-v2/config v1.17.8/go.mod h1:UkCI3kb0sCdvtjiXYiU4Zx5h07BOpgBTtkPu/49r+kA= +github.com/aws/aws-sdk-go-v2/credentials v1.12.21 h1:4tjlyCD0hRGNQivh5dN8hbP30qQhMLBE/FgQR1vHHWM= +github.com/aws/aws-sdk-go-v2/credentials v1.12.21/go.mod h1:O+4XyAt4e+oBAoIwNUYkRg3CVMscaIJdmZBOcPgJ8D8= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.17 h1:r08j4sbZu/RVi+BNxkBJwPMUYY3P8mgSDuKkZ/ZN1lE= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.17/go.mod h1:yIkQcCDYNsZfXpd5UX2Cy+sWA1jPgIhGTw9cOBzfVnQ= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.23 h1:s4g/wnzMf+qepSNgTvaQQHNxyMLKSawNhKCPNy++2xY= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.23/go.mod h1:2DFxAQ9pfIRy0imBCJv+vZ2X6RKxves6fbnEuSry6b4= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.17 h1:/K482T5A3623WJgWT8w1yRAFK4RzGzEl7y39yhtn9eA= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.17/go.mod h1:pRwaTYCJemADaqCbUAxltMoHKata7hmB5PjEXeu0kfg= +github.com/aws/aws-sdk-go-v2/internal/ini v1.3.24 h1:wj5Rwc05hvUSvKuOF29IYb9QrCLjU+rHAy/x/o0DK2c= +github.com/aws/aws-sdk-go-v2/internal/ini v1.3.24/go.mod h1:jULHjqqjDlbyTa7pfM7WICATnOv+iOhjletM3N0Xbu8= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.17 h1:Jrd/oMh0PKQc6+BowB+pLEwLIgaQF29eYbe7E1Av9Ug= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.17/go.mod h1:4nYOrY41Lrbk2170/BGkcJKBhws9Pfn8MG3aGqjjeFI= +github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.16.2 h1:3x1Qilin49XQ1rK6pDNAfG+DmCFPfB7Rrpl+FUDAR/0= +github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.16.2/go.mod h1:HEBBc70BYi5eUvxBqC3xXjU/04NO96X/XNUe5qhC7Bc= +github.com/aws/aws-sdk-go-v2/service/sso v1.11.23 h1:pwvCchFUEnlceKIgPUouBJwK81aCkQ8UDMORfeFtW10= +github.com/aws/aws-sdk-go-v2/service/sso v1.11.23/go.mod h1:/w0eg9IhFGjGyyncHIQrXtU8wvNsTJOP0R6PPj0wf80= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.6 h1:OwhhKc1P9ElfWbMKPIbMMZBV6hzJlL2JKD76wNNVzgQ= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.6/go.mod h1:csZuQY65DAdFBt1oIjO5hhBR49kQqop4+lcuCjf2arA= +github.com/aws/aws-sdk-go-v2/service/sts v1.16.19 h1:9pPi0PsFNAGILFfPCk8Y0iyEBGc6lu6OQ97U7hmdesg= +github.com/aws/aws-sdk-go-v2/service/sts v1.16.19/go.mod h1:h4J3oPZQbxLhzGnk+j9dfYHi5qIOVJ5kczZd658/ydM= +github.com/aws/smithy-go v1.13.3 h1:l7LYxGuzK6/K+NzJ2mC+VvLUbae0sL3bXU//04MkmnA= +github.com/aws/smithy-go v1.13.3/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= +github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= -github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= -github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/lib/pq v1.10.4 h1:SO9z7FRPzA03QhHKJrH5BXA6HU1rS4V2nIVrrNC1iYk= github.com/lib/pq v1.10.4/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/e2e/apprunner/front-end/main.go b/e2e/apprunner/front-end/main.go index c2d75123ccb..5d86bb48858 100644 --- a/e2e/apprunner/front-end/main.go +++ b/e2e/apprunner/front-end/main.go @@ -4,8 +4,10 @@ package main import ( + "context" "database/sql" "encoding/json" + "errors" "fmt" "io/ioutil" "log" @@ -13,11 +15,10 @@ import ( "os" "time" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/session" - "github.com/aws/aws-sdk-go/service/secretsmanager" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/config" + "github.com/aws/aws-sdk-go-v2/service/secretsmanager" - "github.com/julienschmidt/httprouter" _ "github.com/lib/pq" // https://www.calhoun.io/why-we-import-sql-drivers-with-the-blank-identifier/ ) @@ -29,7 +30,7 @@ const ( ) // SimpleGet just returns true no matter what -func SimpleGet(w http.ResponseWriter, req *http.Request, ps httprouter.Params) { +func SimpleGet(w http.ResponseWriter, req *http.Request) { log.Println("Get Succeeded") w.WriteHeader(http.StatusOK) w.Write([]byte(os.Getenv("COPILOT_APPLICATION_NAME") + "-" + os.Getenv("COPILOT_ENVIRONMENT_NAME") + "-" + os.Getenv("COPILOT_SERVICE_NAME"))) @@ -40,11 +41,11 @@ func SimpleGet(w http.ResponseWriter, req *http.Request, ps httprouter.Params) { // This test assumes the backend app is called "back-end". The 'service-discovery' endpoint // of the back-end service is unreachable from the LB, so the only way to get it is // through service discovery. The response should be `back-end-service-discovery` -func ServiceDiscoveryGet(w http.ResponseWriter, req *http.Request, ps httprouter.Params) { +func ServiceDiscoveryGet(w http.ResponseWriter, req *http.Request) { endpoint := fmt.Sprintf("http://back-end.%s/service-discovery/", os.Getenv("COPILOT_SERVICE_DISCOVERY_ENDPOINT")) resp, err := http.Get(endpoint) if err != nil { - log.Printf("🚨 could call service discovery endpoint: err=%s\n", err) + log.Printf("🚨 could call service discovery endpoint: err=%s", err) http.Error(w, err.Error(), http.StatusInternalServerError) return } @@ -64,17 +65,21 @@ type Secret struct { } // DBGet calls an aurora DB and returns a timestamp from the database. -func DBGet(w http.ResponseWriter, req *http.Request, ps httprouter.Params) { - sess, err := session.NewSession(&aws.Config{ - Region: aws.String(os.Getenv("AWS_DEFAULT_REGION")), - }) +func DBGet(w http.ResponseWriter, req *http.Request) { + ctx, cancel := context.WithTimeout(req.Context(), 20*time.Second) + defer cancel() + + cfg, err := config.LoadDefaultConfig(ctx, + config.WithRegion(os.Getenv("AWS_DEFAULT_REGION")), + ) if err != nil { - log.Printf("🚨 initial new aws session: err=%s\n", err) + log.Printf("🚨 load aws config: %s", err) http.Error(w, err.Error(), http.StatusInternalServerError) return } - ssm := secretsmanager.New(sess) - out, err := ssm.GetSecretValue(&secretsmanager.GetSecretValueInput{ + + mgr := secretsmanager.NewFromConfig(cfg) + out, err := mgr.GetSecretValue(ctx, &secretsmanager.GetSecretValueInput{ SecretId: aws.String(os.Getenv("FRONTENDCLUSTER_SECRET_ARN")), }) if err != nil { @@ -82,18 +87,21 @@ func DBGet(w http.ResponseWriter, req *http.Request, ps httprouter.Params) { http.Error(w, err.Error(), http.StatusInternalServerError) return } - secretValue := aws.StringValue(out.SecretString) + + secretValue := aws.ToString(out.SecretString) if secretValue == "" { log.Print("🚨 empty aurora secret value\n") http.Error(w, err.Error(), http.StatusInternalServerError) return } + secret := Secret{} if err := json.Unmarshal([]byte(secretValue), &secret); err != nil { log.Printf("🚨 unmarshal rds secret: err=%s\n", err) http.Error(w, err.Error(), http.StatusInternalServerError) return } + source := fmt.Sprintf("host=%s port=%d user=%s "+ "password=%s dbname=%s", secret.Host, secret.Port, secret.Username, secret.Password, secret.DBName) @@ -103,29 +111,26 @@ func DBGet(w http.ResponseWriter, req *http.Request, ps httprouter.Params) { http.Error(w, err.Error(), http.StatusInternalServerError) return } - err = db.Ping() // Force open a connection to the database. - if err != nil { + defer db.Close() + + // Force open a connection to the database. + if err := db.Ping(); err != nil { log.Printf("🚨 ping: err=%s\n", err) http.Error(w, err.Error(), http.StatusInternalServerError) return } - close := func() error { - err := db.Close() - if err != nil { - return fmt.Errorf("close db: %w", err) - } - return nil - } - defer close() + w.WriteHeader(http.StatusOK) w.Write([]byte(fmt.Sprint(time.Now()))) } func main() { - router := httprouter.New() - router.GET("/", SimpleGet) - router.GET("/service-discovery-test", ServiceDiscoveryGet) - router.GET("/db", DBGet) + http.Handle("/", http.HandlerFunc(SimpleGet)) + http.Handle("/service-discovery-test", http.HandlerFunc(ServiceDiscoveryGet)) + http.Handle("/db", http.HandlerFunc(DBGet)) - log.Fatal(http.ListenAndServe(":80", router)) + err := http.ListenAndServe(":80", nil) + if !errors.Is(err, http.ErrServerClosed) { + log.Fatalf("listen and serve: %s", err) + } }