diff --git a/.github/workflows/auto-author-assign.yaml b/.github/workflows/auto-author-assign.yaml new file mode 100644 index 0000000..1eec23b --- /dev/null +++ b/.github/workflows/auto-author-assign.yaml @@ -0,0 +1,14 @@ +name: Auto Author Assign + +on: + pull_request_target: + types: [opened, reopened] + +permissions: + pull-requests: write + +jobs: + assign-author: + runs-on: ubuntu-latest + steps: + - uses: toshimaru/auto-author-assign@v2.1.1 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d390f86..da425f5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -10,14 +10,14 @@ jobs: docker-build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Build the Docker image run: cd app && docker build . -t ${{ secrets.IMAGE_NAME }}:$(date +%s) sonarqube: name: Sonarqube runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up JDK 11 uses: actions/setup-java@v3 with: @@ -39,4 +39,4 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - run: ./gradlew build sonarqube --info \ No newline at end of file + run: ./gradlew build sonarqube --info diff --git a/.github/workflows/pull_request_template.md b/.github/workflows/pull_request_template.md new file mode 100644 index 0000000..eeb19ad --- /dev/null +++ b/.github/workflows/pull_request_template.md @@ -0,0 +1,3 @@ +# Summary + +## Related Issues diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000..14f087b --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,6 @@ +output: + show-stats: true + sort-results: true + sort-order: + - linter + - file diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..0532239 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,9 @@ +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v5.0.0 + hooks: + - id: check-merge-conflict + - id: end-of-file-fixer + - id: trailing-whitespace + - id: check-json + # - id: check-yaml diff --git a/README.md b/README.md index d50da44..239c837 100644 --- a/README.md +++ b/README.md @@ -3,19 +3,18 @@ [![Build](https://github.com/DevSecOpsSamples/gcp-golang-performance-test/actions/workflows/build.yml/badge.svg?branch=master)](https://github.com/DevSecOpsSamples/gcp-golang-performance-test/actions/workflows/build.yml) [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=DevSecOpsSamples_gcp-golang-performance-test&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=DevSecOpsSamples_gcp-golang-performance-test) [![Lines of Code](https://sonarcloud.io/api/project_badges/measure?project=DevSecOpsSamples_gcp-golang-performance-test&metric=ncloc)](https://sonarcloud.io/summary/new_code?id=DevSecOpsSamples_gcp-golang-performance-test) -Performance testing on GKE using the https://echo.labstack.com application. - +Performance testing on GKE using the application. ## Table of Contents - [1. Create a GKE cluster](#1-create-a-gke-cluster) - [2. Deploy two applications for checking the performance per Pod and scaling](#2-deploy-two-applications-for-checking-the-performance-per-pod-and-scaling) - - [2.1. Deploy for performance of one Pod](#21-deploy-for-performance-of-one-pod) - - [2.2. Deploy for Scaling Test](#22-deploy-for-scaling-test) + - [2.1. Deploy for performance of one Pod](#21-deploy-for-performance-of-one-pod) + - [2.2. Deploy for Scaling Test](#22-deploy-for-scaling-test) - [3. Performance Testing](#3-performance-testing) - - [3.1. Install the Taurus](#31-install-the-taurus) - - [3.2. Test for performance of one Pod](#32-test-for-performance-of-one-pod) - - [3.3. Test with auto scaling](#33-test-with-auto-scaling) + - [3.1. Install the Taurus](#31-install-the-taurus) + - [3.2. Test for performance of one Pod](#32-test-for-performance-of-one-pod) + - [3.3. Test with auto scaling](#33-test-with-auto-scaling) - [Cleanup](#6-cleanup) --- @@ -26,7 +25,7 @@ Performance testing on GKE using the https://echo.labstack.com application. - [Install the gcloud CLI](https://cloud.google.com/sdk/docs/install) - [Install kubectl and configure cluster access](https://cloud.google.com/kubernetes-engine/docs/how-to/cluster-access-for-kubectl) -- [Installing and Upgrading for the Taurus ](https://gettaurus.org/install/Installation/) +- [Installing and Upgrading for the Taurus](https://gettaurus.org/install/Installation/) ### Set environment variables @@ -56,21 +55,24 @@ gcloud container clusters get-credentials sample-cluster ## 2. Deploy two applications for checking the performance per Pod and scaling -Build and push to GCR: +Build and push to GAR: ```bash +gcloud auth login +gcloud auth configure-docker us-docker.pkg.dev + cd app docker build -t go-echo-api . --platform linux/amd64 -docker tag go-echo-api:latest gcr.io/${PROJECT_ID}/go-echo-api:latest - -gcloud auth configure-docker -docker push gcr.io/${PROJECT_ID}/go-echo-api:latest +docker tag go-echo-api:latest us-docker.pkg.dev/${PROJECT_ID}/${REPOSITORY}/go-echo-api:latest +docker push us-docker.pkg.dev/${PROJECT_ID}/${REPOSITORY}/go-echo-api:latest ``` +[build-and-push.sh](app/build-and-push.sh) + ```bash -kubectl get namespaces +kubectl get ns -kubectl create namespace echo-test +kubectl create ns echo-test ``` Two deployments may take around 5 minutes to create a load balancer, including health checking. @@ -137,7 +139,7 @@ curl http://${LB_IP_ADDRESS}/ ### 3.1. Install the Taurus -https://gettaurus.org/install/Installation/ + ```bash sudo apt-get update -y @@ -186,11 +188,12 @@ kubectl scale deployment go-echo-api -n echo-test --replicas=0 kubectl delete -f app/go-echo-api-onepod.yaml -n echo-test kubectl delete -f app/go-echo-api.yaml -n echo-test +kubectl delete namespace echo-test ``` ## References -- https://echo.labstack.com +- - [Cloud SDK > Documentation > Reference > gcloud container clusters](https://cloud.google.com/sdk/gcloud/reference/container/clusters) diff --git a/app/Dockerfile b/app/Dockerfile index 8b198da..1cf7c66 100644 --- a/app/Dockerfile +++ b/app/Dockerfile @@ -1,20 +1,20 @@ -FROM golang:1.18 AS builder +FROM golang:1.23-alpine AS builder -RUN mkdir /app - -COPY ./go.mod /app/ -COPY ./go.sum /app/ -COPY ./main.go /app/ WORKDIR /app -RUN go install -RUN go build main.go +COPY go.mod go.sum ./ +RUN go mod download + +COPY . . +RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o server ./ -RUN adduser go -RUN chown go ./main +FROM scratch + +WORKDIR /app -USER go +COPY --from=builder /app/server . +COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ -EXPOSE 8000 +EXPOSE 8080 -CMD ["./main"] \ No newline at end of file +ENTRYPOINT ["/app/server"] diff --git a/app/Makefile b/app/Makefile index fe850e3..d740702 100644 --- a/app/Makefile +++ b/app/Makefile @@ -1,11 +1,30 @@ +.PHONY: install build build-docker test all clean + +all: install build test build-docker + build: go build ./... +build-docker: + docker build --progress=plain -t go-echo-api . + install: - go install -mod=vendor -v ./... + go install -v ./... + +fmt: + go fmt ./... + +lint: fmt + golangci-lint run + +run: fmt + go run ./main.go + +run-docker: + docker run -it -p 8080:8080 go-echo-api:latest test: go test ./... clean: - go clean ./... \ No newline at end of file + go clean ./... diff --git a/app/README.md b/app/README.md new file mode 100644 index 0000000..7bd51d2 --- /dev/null +++ b/app/README.md @@ -0,0 +1,11 @@ +# Build + +```bash +make build +make run +``` + +```bash +make build-docker +make run-docker +``` diff --git a/app/build-and-push.sh b/app/build-and-push.sh new file mode 100755 index 0000000..c1bedff --- /dev/null +++ b/app/build-and-push.sh @@ -0,0 +1,21 @@ +#!/bin/bash +set -e + +# gcloud config set project +PROJECT_ID=$(gcloud config get-value project) +echo "PROJECT_ID: ${PROJECT_ID}" + +# Set your repository name +RESPOSITORY="docker" + +# gcloud artifacts repositories create ${RESPOSITORY} --repository-format=docker --location=us --description="Docker repository for go-echo-api" + +docker build -t go-echo-api . --platform linux/amd64 +docker tag go-echo-api:latest us-docker.pkg.dev/${PROJECT_ID}/${RESPOSITORY}/go-echo-api:latest + +gcloud auth configure-docker us-docker.pkg.dev +docker push us-docker.pkg.dev/${PROJECT_ID}/${RESPOSITORY}/go-echo-api:latest + +# docker run -it -p 8080:8080 go-echo-api:latest + +# docker run -it -p 8080:8080 us-docker.pkg.dev/${PROJECT_ID}/go-echo-api:latest diff --git a/app/build-multi-arch-and-push.sh b/app/build-multi-arch-and-push.sh new file mode 100755 index 0000000..b9f46a6 --- /dev/null +++ b/app/build-multi-arch-and-push.sh @@ -0,0 +1,17 @@ +#!/bin/bash +set -e + +# gcloud config set project +PROJECT_ID=$(gcloud config get-value project) +echo "PROJECT_ID: ${PROJECT_ID}" + +# Set your repository name +RESPOSITORY="docker" + +docker buildx ls + +docker buildx rm builder || true +docker buildx create --name builder --use + +gcloud auth configure-docker us-docker.pkg.dev +time docker buildx build -t us-docker.pkg.dev/${PROJECT_ID}/${RESPOSITORY}/go-echo-api:latest . --platform linux/amd64,linux/arm/v7 --push diff --git a/app/build-multi-arch.sh b/app/build-multi-arch.sh deleted file mode 100755 index d0d97aa..0000000 --- a/app/build-multi-arch.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash -set -e - -echo "PROJECT_ID: ${PROJECT_ID}" - -docker buildx ls -docker buildx create --name builder --use builder -time docker buildx build -t gcr.io/${PROJECT_ID}/go-echo-api:latest . --platform linux/amd64,linux/arm/v7 --push \ No newline at end of file diff --git a/app/build.sh b/app/build.sh deleted file mode 100755 index 6756c17..0000000 --- a/app/build.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash -set -e - -echo "PROJECT_ID: ${PROJECT_ID}" - -docker build -t go-echo-api . --platform linux/amd64 -docker tag go-echo-api:latest gcr.io/${PROJECT_ID}/go-echo-api:latest -docker push gcr.io/${PROJECT_ID}/go-echo-api:latest - -# docker run -it -p 8000:8000 go-echo-api:latest - -# docker run -it -p 8000:8000 gcr.io/${PROJECT_ID}/go-echo-api:latest \ No newline at end of file diff --git a/app/go-echo-api-onepod-template.yaml b/app/go-echo-api-onepod-template.yaml index b913145..8f2ff49 100644 --- a/app/go-echo-api-onepod-template.yaml +++ b/app/go-echo-api-onepod-template.yaml @@ -1,4 +1,3 @@ ---- apiVersion: apps/v1 kind: Deployment metadata: @@ -18,10 +17,10 @@ spec: spec: containers: - name: go-echo-api-onepod - image: gcr.io//go-echo-api:latest + image: us-docker.pkg.dev//go-echo-api:latest imagePullPolicy: Always ports: - - containerPort: 8000 + - containerPort: 8080 resources: requests: cpu: "1" @@ -41,7 +40,7 @@ spec: type: ClusterIP ports: - port: 30000 - targetPort: 8000 + targetPort: 8080 protocol: TCP --- apiVersion: networking.k8s.io/v1 @@ -77,7 +76,7 @@ spec: timeoutSec: 30 healthyThreshold: 1 unhealthyThreshold: 3 - port: 8000 + port: 8080 type: HTTP requestPath: / --- @@ -99,4 +98,4 @@ spec: name: cpu target: type: Utilization - averageUtilization: 90 \ No newline at end of file + averageUtilization: 90 diff --git a/app/go-echo-api-template.yaml b/app/go-echo-api-template.yaml index 431f1f5..194c014 100644 --- a/app/go-echo-api-template.yaml +++ b/app/go-echo-api-template.yaml @@ -1,4 +1,4 @@ ---- + apiVersion: apps/v1 kind: Deployment metadata: @@ -18,10 +18,10 @@ spec: spec: containers: - name: go-echo-api - image: gcr.io//go-echo-api:latest + image: us-docker.pkg.dev//go-echo-api:latest imagePullPolicy: Always ports: - - containerPort: 8000 + - containerPort: 8080 resources: requests: cpu: "1" @@ -41,7 +41,7 @@ spec: type: ClusterIP ports: - port: 30001 - targetPort: 8000 + targetPort: 8080 protocol: TCP --- apiVersion: networking.k8s.io/v1 @@ -77,7 +77,7 @@ spec: timeoutSec: 30 healthyThreshold: 1 unhealthyThreshold: 3 - port: 8000 + port: 8080 type: HTTP requestPath: / --- @@ -99,4 +99,4 @@ spec: name: cpu target: type: Utilization - averageUtilization: 90 \ No newline at end of file + averageUtilization: 90 diff --git a/app/go.mod b/app/go.mod index dd8a0af..c1f3493 100644 --- a/app/go.mod +++ b/app/go.mod @@ -1,9 +1,10 @@ module echo -go 1.18 +go 1.23.0 + +require github.com/labstack/echo/v4 v4.10.0 require ( - github.com/labstack/echo/v4 v4.10.0 // indirect github.com/labstack/gommon v0.4.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.16 // indirect diff --git a/app/go.sum b/app/go.sum index b462108..81189fa 100644 --- a/app/go.sum +++ b/app/go.sum @@ -1,4 +1,5 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/labstack/echo/v4 v4.10.0 h1:5CiyngihEO4HXsz3vVsJn7f8xAlWwRr3aY6Ih280ZKA= github.com/labstack/echo/v4 v4.10.0/go.mod h1:S/T/5fy/GigaXnHTkh0ZGe4LpkkQysvRjFMSUTkDRNQ= @@ -10,9 +11,12 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +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= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= @@ -33,3 +37,5 @@ golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/workflows/auto-author-assign.yaml b/workflows/auto-author-assign.yaml new file mode 100644 index 0000000..1eec23b --- /dev/null +++ b/workflows/auto-author-assign.yaml @@ -0,0 +1,14 @@ +name: Auto Author Assign + +on: + pull_request_target: + types: [opened, reopened] + +permissions: + pull-requests: write + +jobs: + assign-author: + runs-on: ubuntu-latest + steps: + - uses: toshimaru/auto-author-assign@v2.1.1 diff --git a/workflows/build.yml b/workflows/build.yml new file mode 100644 index 0000000..8f8b409 --- /dev/null +++ b/workflows/build.yml @@ -0,0 +1,42 @@ +name: Build +on: + push: + branches: + - master + - develop + pull_request: + types: [opened, synchronize, reopened] +jobs: + docker-build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Build the Docker image + run: cd app && docker build . -t ${{ secrets.IMAGE_NAME }}:$(date +%s) + sonarqube: + name: Sonarqube + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Set up JDK 11 + uses: actions/setup-java@v3 + with: + distribution: 'temurin' + java-version: 11 + - name: Cache SonarCloud packages + uses: actions/cache@v3 + with: + path: ~/.sonar/cache + key: ${{ runner.os }}-sonar + restore-keys: ${{ runner.os }}-sonar + - name: Cache Gradle packages + uses: actions/cache@v3 + with: + path: ~/.gradle/caches + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} + restore-keys: ${{ runner.os }}-gradle + - name: Build and analyze + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + run: ./gradlew build sonarqube --info diff --git a/workflows/pull_request_template.md b/workflows/pull_request_template.md new file mode 100644 index 0000000..eeb19ad --- /dev/null +++ b/workflows/pull_request_template.md @@ -0,0 +1,3 @@ +# Summary + +## Related Issues diff --git a/wrapper/gradle-wrapper.properties b/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..f398c33 --- /dev/null +++ b/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip +networkTimeout=10000 +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists