diff --git a/.pipelines/build.yml b/.pipelines/build.yml index 43063480d..cc659cfce 100644 --- a/.pipelines/build.yml +++ b/.pipelines/build.yml @@ -1,129 +1,57 @@ # This contains common build steps steps: -- script: | - mkdir -p '$(GOBIN)' - mkdir -p '$(GOPATH)/pkg' - mkdir -p '$(modulePath)' - shopt -s extglob - shopt -s dotglob - mv !(gopath) '$(modulePath)' - echo '##vso[task.prependpath]$(GOBIN)' - echo '##vso[task.prependpath]$(GOROOT)/bin' - displayName: 'Set up the Go workspace' - -- script: | - go get -u golang.org/x/lint/golint - golint $(go list ./... | grep -v /vendor/) | tee /tmp/lint.out - if [ -s /tmp/lint.out ]; then - echo -e "\e[101;97m golint FAILED \e[0m"`` - exit 1 - else - echo -e "\e[42;97m golint SUCCEEDED \e[0m" - fi - workingDirectory: '$(modulePath)' - displayName: 'Go lint' - -- script: | - if go vet ./...; then - echo -e "\e[42;97m govet SUCCEEDED \e[0m" - else - echo -e "\e[101;97m govet FAILED \e[0m"`` - exit 1 - fi - - if go vet -tags=unittest ./...; then - echo -e "\e[42;97m govet SUCCEEDED \e[0m" - else - echo -e "\e[101;97m govet FAILED \e[0m"`` - exit 1 - fi - - cd ./scripts/e2e - if go vet -tags=e2e ./...; then - echo -e "\e[42;97m govet SUCCEEDED \e[0m" - else - echo -e "\e[101;97m govet FAILED \e[0m"`` - exit 1 - fi - cd ../.. - workingDirectory: '$(modulePath)' - displayName: 'Go vet' - -- script: | - set -u - go version - echo -e "\e[44;97m Compiling ... \e[0m" - - # set version - ORG_PATH="github.com/Azure" - PROJECT_NAME="application-gateway-kubernetes-ingress" - REPO_PATH="${ORG_PATH}/${PROJECT_NAME}" - VERSION_VAR="${REPO_PATH}/pkg/version.Version" - VERSION=$(git describe --abbrev=0 --tags) - DATE_VAR="${REPO_PATH}/pkg/version.BuildDate" - BUILD_DATE=$(date +%Y-%m-%d-%H:%MT%z) - COMMIT_VAR="${REPO_PATH}/pkg/version.GitCommit" - GIT_HASH=$(git rev-parse --short HEAD) - - echo "VERSION $VERSION_VAR:$VERSION, BUILD_DATE $DATE_VAR:$BUILD_DATE, GIT_HASH $COMMIT_VAR:$GIT_HASH" - if go install -ldflags "-s -X ${VERSION_VAR}=${VERSION} -X ${DATE_VAR}=${BUILD_DATE} -X ${COMMIT_VAR}=${GIT_HASH}" -v ./cmd/appgw-ingress; then - chmod -R 777 $(GOBIN) - $(GOBIN)/appgw-ingress --version - echo -e "\e[42;97m Build SUCCEEDED \e[0m" - else - echo -e "\e[101;97m Build FAILED \e[0m" - exit 1 - fi - workingDirectory: '$(modulePath)' - displayName: 'Get dependencies and build' - -- script: | - go get github.com/jstemmer/go-junit-report - go get github.com/axw/gocov/gocov - go get github.com/AlekSi/gocov-xml - go get github.com/matm/gocov-html - go test -timeout 80s -v -coverprofile=coverage.txt -covermode count -tags unittest ./... > testoutput.txt || { echo "go test returned non-zero"; cat testoutput.txt; exit 1; } - cat testoutput.txt | go-junit-report > report.xml - gocov convert coverage.txt > coverage.json - gocov-xml < coverage.json > coverage.xml - mkdir coverage - gocov-html < coverage.json > coverage/index.html - workingDirectory: '$(modulePath)' - displayName: 'Run unit tests with code coverage' - -- script: | - helm lint ./helm/ingress-azure - workingDirectory: '$(modulePath)' - displayName: 'Helm lint' - -- task: PublishTestResults@2 - continueOnError: true - condition: succeededOrFailed() - inputs: - failTaskOnFailedTests: true - testRunner: JUnit - testResultsFiles: $(System.DefaultWorkingDirectory)/**/report.xml - - -- task: PublishCodeCoverageResults@1 - continueOnError: true - condition: succeededOrFailed() - inputs: - codeCoverageTool: Cobertura - summaryFileLocation: $(modulePath)/coverage.xml - reportDirectory: $(modulePath)/coverage - -- task: CopyFiles@2 - inputs: - contents: | - $(GOBIN)/appgw-ingress - $(modulePath)/dockerfiles/deploy.Dockerfile - $(modulePath)/scripts/** - $(modulePath)/helm/** - targetFolder: $(Build.ArtifactStagingDirectory) - -- task: PublishBuildArtifacts@1 - inputs: - pathtoPublish: $(Build.ArtifactStagingDirectory) - artifactName: drop \ No newline at end of file + - script: | + mkdir -p '$(GOBIN)' + mkdir -p '$(GOPATH)/pkg' + mkdir -p '$(modulePath)' + shopt -s extglob + shopt -s dotglob + mv !(gopath) '$(modulePath)' + echo '##vso[task.prependpath]$(GOBIN)' + echo '##vso[task.prependpath]$(GOROOT)/bin' + displayName: "Set up the Go workspace" + + - script: make lint-all + workingDirectory: "$(modulePath)" + displayName: "Go and Helm lint check" + + - script: make vet-all + workingDirectory: "$(modulePath)" + displayName: "Go vet" + + - script: make build + workingDirectory: "$(modulePath)" + displayName: "Get dependencies and build" + + - script: make unittest + workingDirectory: "$(modulePath)" + displayName: "Run unit tests with code coverage" + + - task: PublishTestResults@2 + continueOnError: true + condition: succeededOrFailed() + inputs: + failTaskOnFailedTests: true + testRunner: JUnit + testResultsFiles: $(System.DefaultWorkingDirectory)/**/report.xml + + - task: PublishCodeCoverageResults@1 + continueOnError: true + condition: succeededOrFailed() + inputs: + codeCoverageTool: Cobertura + summaryFileLocation: $(modulePath)/coverage.xml + reportDirectory: $(modulePath)/coverage + + - task: CopyFiles@2 + inputs: + contents: | + $(modulePath)/scripts/** + $(modulePath)/helm/** + targetFolder: $(Build.ArtifactStagingDirectory) + + - task: PublishBuildArtifacts@1 + inputs: + pathtoPublish: $(Build.ArtifactStagingDirectory) + artifactName: drop diff --git a/.pipelines/nightly-build.yml b/.pipelines/nightly-build.yml index 2c184caa8..f35f848c1 100644 --- a/.pipelines/nightly-build.yml +++ b/.pipelines/nightly-build.yml @@ -22,4 +22,37 @@ variables: GO_PROJ: 'github.com/Azure/$(build.repository.name)' steps: -- template: build.yml \ No newline at end of file + - script: | + mkdir -p '$(GOBIN)' + mkdir -p '$(GOPATH)/pkg' + mkdir -p '$(modulePath)' + shopt -s extglob + shopt -s dotglob + mv !(gopath) '$(modulePath)' + echo '##vso[task.prependpath]$(GOBIN)' + echo '##vso[task.prependpath]$(GOROOT)/bin' + displayName: "Set up the Go workspace" + + - task: Docker@2 + displayName: Login to ACR + inputs: + command: login + containerRegistry: "AGIC Registry" + + - script: | + docker buildx create --use + make build-image-multi-arch BUILD_TAG=$(build.buildid) PUSH_IMAGE=true + workingDirectory: "$(modulePath)" + displayName: "Build nightly image" + + - task: CopyFiles@2 + inputs: + contents: | + $(modulePath)/scripts/** + $(modulePath)/helm/** + targetFolder: $(Build.ArtifactStagingDirectory) + + - task: PublishBuildArtifacts@1 + inputs: + pathtoPublish: $(Build.ArtifactStagingDirectory) + artifactName: drop \ No newline at end of file diff --git a/.pipelines/release-build.yml b/.pipelines/release-build.yml index 35b086bce..eeffe224a 100644 --- a/.pipelines/release-build.yml +++ b/.pipelines/release-build.yml @@ -6,15 +6,48 @@ trigger: pr: none pool: - vmImage: 'ubuntu-latest' + vmImage: "ubuntu-latest" variables: - GOPATH: '$(system.defaultWorkingDirectory)/gopath' - GOBIN: '$(GOPATH)/bin' - modulePath: '$(GOPATH)/src/github.com/$(build.repository.name)' - GOOS: 'linux' - GO111MODULE: 'on' - GO_PROJ: 'github.com/Azure/$(build.repository.name)' + GOPATH: "$(system.defaultWorkingDirectory)/gopath" + GOBIN: "$(GOPATH)/bin" + modulePath: "$(GOPATH)/src/github.com/$(build.repository.name)" + GOOS: "linux" + GO111MODULE: "on" + GO_PROJ: "github.com/Azure/$(build.repository.name)" steps: -- template: build.yml \ No newline at end of file + - script: | + mkdir -p '$(GOBIN)' + mkdir -p '$(GOPATH)/pkg' + mkdir -p '$(modulePath)' + shopt -s extglob + shopt -s dotglob + mv !(gopath) '$(modulePath)' + echo '##vso[task.prependpath]$(GOBIN)' + echo '##vso[task.prependpath]$(GOROOT)/bin' + displayName: "Set up the Go workspace" + + - task: Docker@2 + displayName: Login to ACR + inputs: + command: login + containerRegistry: "AGIC Registry" + + - script: | + docker buildx create --use + make build-image-multi-arch RELEASE_IMAGE=true PUSH_IMAGE=true + workingDirectory: "$(modulePath)" + displayName: "Build release image" + + - task: CopyFiles@2 + inputs: + contents: | + $(modulePath)/scripts/** + $(modulePath)/helm/** + targetFolder: $(Build.ArtifactStagingDirectory) + + - task: PublishBuildArtifacts@1 + inputs: + pathtoPublish: $(Build.ArtifactStagingDirectory) + artifactName: drop diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..f527084e4 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,40 @@ +ARG BUILDPLATFORM=linux/amd64 +ARG BUILD_BASE_IMAGE + +FROM --platform=$BUILDPLATFORM $BUILD_BASE_IMAGE AS build +WORKDIR /azure + +COPY go.mod go.sum /azure/ +RUN go mod download + +RUN apt-get update +RUN apt-get install -y ca-certificates openssl + +ARG TARGETOS +ARG TARGETARCH +ARG BUILD_TAG +ARG BUILD_DATE +ARG GIT_HASH + +COPY cmd cmd +COPY pkg pkg +COPY Makefile Makefile + +RUN make build \ + GOOS=${TARGETOS} \ + GOARCH=${TARGETARCH} \ + BUILD_TAG=${BUILD_TAG} \ + BUILD_DATE=${BUILD_DATE} \ + GIT_HASH=${GIT_HASH} + +#RUN ldd ./bin/appgw-ingress 2>&1 | grep 'not a dynamic executable' + +FROM ubuntu:20.04 AS final +COPY --from=build /azure/bin/appgw-ingress /appgw-ingress +RUN apt-get update +RUN apt-get install -y ca-certificates openssl +RUN useradd appgw-ingress-user +RUN chown appgw-ingress-user /appgw-ingress +USER appgw-ingress-user +RUN chmod +x /appgw-ingress +CMD ["/appgw-ingress"] diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..5ea7a3dd7 --- /dev/null +++ b/Makefile @@ -0,0 +1,126 @@ +ORG_PATH := github.com/Azure +PROJECT_NAME := application-gateway-kubernetes-ingress +REPO_PATH = ${ORG_PATH}/${PROJECT_NAME} + +VERSION_VAR = ${REPO_PATH}/pkg/version.Version +BUILD_TAG ?= $(shell git describe --abbrev=0 --tags) + +DATE_VAR = ${REPO_PATH}/pkg/version.BuildDate +BUILD_DATE ?= $(shell date +%Y-%m-%d-%H:%MT%z) + +COMMIT_VAR = ${REPO_PATH}/pkg/version.GitCommit +GIT_HASH ?= $(shell git rev-parse --short HEAD) + +GO_BINARY_NAME ?= appgw-ingress +GOOS ?= linux +GARCH ?= arm64 + +BUILD_BASE_IMAGE ?= golang:1.17.3 + +REPO ?= appgwreg.azurecr.io +IMAGE_NAME = public/azure-application-gateway/kubernetes-ingress-staging +IMAGE = ${REPO}/${IMAGE_NAME} + +IMAGE_RESULT_FLAG = --output=type=oci,dest=$(shell pwd)/image/ingress-agic-$(VERSION).tar +ifeq ($(PUSH_IMAGE), true) + IMAGE_RESULT_FLAG = --push +endif + +ifeq ($(RELEASE_IMAGE), true) + IMAGE_NAME = public/azure-application-gateway/kubernetes-ingress +endif + +TAG_LATEST ?= false + +ifeq ($(TAG_LATEST), true) + IMAGE_TAGS = \ + --tag $(IMAGE):$(BUILD_TAG) \ + --tag $(IMAGE):latest +else + IMAGE_TAGS = \ + --tag $(IMAGE):$(BUILD_TAG) +endif + +# Platforms to build the multi-arch image for. +IMAGE_PLATFORMS ?= linux/amd64,linux/arm64 + +GO_BUILD_VARS = \ + ${REPO_PATH}/pkg/version.Version=${BUILD_TAG} \ + ${REPO_PATH}/pkg/version.BuildDate=${BUILD_DATE} \ + ${REPO_PATH}/pkg/version.GitCommit=${GIT_HASH} + +GO_LDFLAGS := -s -w $(patsubst %,-X %, $(GO_BUILD_VARS)) + +build-image-multi-arch: + @mkdir -p $(shell pwd)/image + @docker run --rm --privileged linuxkit/binfmt:v0.8 + @docker buildx build $(IMAGE_RESULT_FLAG) \ + --platform $(IMAGE_PLATFORMS) \ + --build-arg "BUILD_BASE_IMAGE=$(BUILD_BASE_IMAGE)" \ + --build-arg "BUILD_TAG=$(BUILD_TAG)" \ + --build-arg "BUILD_DATE=$(BUILD_DATE)" \ + --build-arg "GIT_HASH=$(GIT_HASH)" \ + $(IMAGE_TAGS) \ + $(shell pwd) + +build: + go build -mod=readonly -v -ldflags="$(GO_LDFLAGS)" -v -o ./bin/${GO_BINARY_NAME} ./cmd/appgw-ingress + +lint-all: lint lint-helm + +lint: + @go get -u golang.org/x/lint/golint + @golint $(go list ./... | grep -v /vendor/) | tee /tmp/lint.out + @if [ -s /tmp/lint.out ]; then \ + echo "\e[101;97m golint FAILED \e[0m"; \ + exit 1; \ + fi + @echo "\e[42;97m golint SUCCEEDED \e[0m" + +lint-helm: + helm lint ./helm/ingress-azure + +vet-all: vet vet-unittest vet-e2e + +vet: + @echo "Vetting controller source code" + @if go vet -v ./...; then \ + echo "\e[42;97m govet SUCCEEDED \e[0m"; \ + else \ + echo "\e[101;97m govet FAILED \e[0m"; \ + exit 1; \ + fi + +vet-unittest: + @echo "Vetting test source code" + @if go vet -v -tags=unittest ./...; then \ + echo "\e[42;97m govet SUCCEEDED \e[0m"; \ + else \ + echo "\e[101;97m govet FAILED \e[0m"; \ + exit 1; \ + fi + +vet-e2e: + @echo "Vetting e2e source code" + @cd ./scripts/e2e + @if go vet -v -tags=e2e ./...; then \ + echo "\e[42;97m govet SUCCEEDED \e[0m"; \ + else \ + echo "\e[101;97m govet FAILED \e[0m"; \ + exit 1; \ + fi + @cd ../.. + +test-all: unittest + +unittest: + @go get github.com/jstemmer/go-junit-report + @go get github.com/axw/gocov/gocov + @go get github.com/AlekSi/gocov-xml + @go get github.com/matm/gocov-html + @go test -timeout 80s -v -coverprofile=coverage.txt -covermode count -tags unittest ./... > testoutput.txt || { echo "go test returned non-zero"; cat testoutput.txt; exit 1; } + @cat testoutput.txt | go-junit-report > report.xml + @gocov convert coverage.txt > coverage.json + @gocov-xml < coverage.json > coverage.xml + @mkdir coverage + @gocov-html < coverage.json > coverage/index.html \ No newline at end of file diff --git a/dockerfiles/deploy.Dockerfile b/dockerfiles/deploy.Dockerfile deleted file mode 100644 index fb81ca831..000000000 --- a/dockerfiles/deploy.Dockerfile +++ /dev/null @@ -1,9 +0,0 @@ -FROM ubuntu:20.04 -RUN apt-get update -RUN apt-get install -y ca-certificates openssl -RUN useradd appgw-ingress-user -ADD bin/appgw-ingress / -RUN chown appgw-ingress-user /appgw-ingress -USER appgw-ingress-user -RUN chmod +x /appgw-ingress -CMD ["/appgw-ingress"] diff --git a/dockerfiles/devenv.Dockerfile b/dockerfiles/devenv.Dockerfile deleted file mode 100644 index 194f90e9d..000000000 --- a/dockerfiles/devenv.Dockerfile +++ /dev/null @@ -1,35 +0,0 @@ -# minimal compile environment for project - -FROM buildpack-deps:xenial - -RUN apt-get update && apt-get -y install apt-transport-https curl ca-certificates openssl -RUN curl -o /tmp/helm-v2.13.1-linux-amd64.tar.gz https://storage.googleapis.com/kubernetes-helm/helm-v2.13.1-linux-amd64.tar.gz -RUN tar -C /tmp/ -zxvf /tmp/helm-v2.13.1-linux-amd64.tar.gz \ - && mv /tmp/linux-amd64/helm /usr/local/bin/helm \ - && rm -rf /tmp/* \ - && helm init --client-only - -# install golang -ENV GO_VERSION 1.13 -RUN wget -q https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz \ - && tar -C /usr/local -xzf go${GO_VERSION}.linux-amd64.tar.gz && rm go${GO_VERSION}.linux-amd64.tar.gz - -# create gopath -RUN mkdir -p /gopath/bin - -# configure env for gopath -ENV GOPATH /gopath -ENV PATH "${PATH}:${GOPATH}/bin:/usr/local/go/bin" - -# get ginkgo, gomega -RUN go get github.com/onsi/ginkgo/ginkgo -RUN go get github.com/onsi/gomega/... - -# get golint, goimports -RUN go get -u golang.org/x/lint/golint -RUN go get -u golang.org/x/tools/cmd/goimports - -RUN apt-get clean && apt-get update && apt-get install -y locales -RUN locale-gen en_US.UTF-8 - -WORKDIR /gopath/src/github.com/Azure/application-gateway-kubernetes-ingress diff --git a/scripts/start.sh b/scripts/start.sh index 748a04b7d..48cf19b36 100755 --- a/scripts/start.sh +++ b/scripts/start.sh @@ -20,7 +20,7 @@ BUILD_DATE=$(date +%Y-%m-%d-%H:%MT%z) GIT_HASH=$(git rev-parse --short HEAD) echo -e "Compiling..." -go install -ldflags "-s -X ${VERSION_VAR}=${VERSION} -X ${DATE_VAR}=${BUILD_DATE} -X ${COMMIT_VAR}=${GIT_HASH}" -v ./cmd/appgw-ingress +go build -ldflags "-s -X ${VERSION_VAR}=${VERSION} -X ${DATE_VAR}=${BUILD_DATE} -X ${COMMIT_VAR}=${GIT_HASH}" -o ./bin/appgw-ingress -v ./cmd/appgw-ingress RESULT=$? if [ "$RESULT" -eq "0" ]; then chmod -R 777 bin