diff --git a/.github/workflows/ferry-controller-image.yml b/.github/workflows/ferry-controller-image.yml deleted file mode 100644 index 5f760e0f..00000000 --- a/.github/workflows/ferry-controller-image.yml +++ /dev/null @@ -1,70 +0,0 @@ -name: Ferry Controller Image - -# This workflow uses actions that are not certified by GitHub. -# They are provided by a third-party and are governed by -# separate terms of service, privacy policy, and support -# documentation. - -on: - push: - # Publish semver tags as releases. - tags: [ 'v*.*.*' ] - -env: - # Use docker.io for Docker Hub if empty - REGISTRY: ghcr.io - # github.repository as / - IMAGE_NAME: ${{ github.repository }}/ferry-controller - - -jobs: - build: - - runs-on: ubuntu-latest - permissions: - contents: read - packages: write - # This is used to complete the identity challenge - # with sigstore/fulcio when running outside of PRs. - id-token: write - - steps: - - name: Checkout repository - uses: actions/checkout@v3 - - - name: Set up QEMU - uses: docker/setup-qemu-action@v2 - - - name: Setup Docker buildx - uses: docker/setup-buildx-action@v2 - - # Login against a Docker registry except on PR - # https://github.com/docker/login-action - - name: Log into registry ${{ env.REGISTRY }} - if: github.event_name != 'pull_request' - uses: docker/login-action@v2 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - # Extract metadata (tags, labels) for Docker - # https://github.com/docker/metadata-action - - name: Extract Docker metadata - id: meta - uses: docker/metadata-action@v4 - with: - images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} - - # Build and push Docker image with Buildx (don't push on PR) - # https://github.com/docker/build-push-action - - name: Build and push Docker image - id: build-and-push - uses: docker/build-push-action@v3 - with: - context: . - file: images/ferry-controller/Dockerfile - push: ${{ github.event_name != 'pull_request' }} - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - platforms: linux/amd64,linux/arm64,linux/arm,linux/386 diff --git a/.github/workflows/ferry-tunnel-image.yml b/.github/workflows/ferry-tunnel-image.yml deleted file mode 100644 index fea1854b..00000000 --- a/.github/workflows/ferry-tunnel-image.yml +++ /dev/null @@ -1,70 +0,0 @@ -name: Ferry Tunnel Image - -# This workflow uses actions that are not certified by GitHub. -# They are provided by a third-party and are governed by -# separate terms of service, privacy policy, and support -# documentation. - -on: - push: - # Publish semver tags as releases. - tags: [ 'v*.*.*' ] - -env: - # Use docker.io for Docker Hub if empty - REGISTRY: ghcr.io - # github.repository as / - IMAGE_NAME: ${{ github.repository }}/ferry-tunnel - - -jobs: - build: - - runs-on: ubuntu-latest - permissions: - contents: read - packages: write - # This is used to complete the identity challenge - # with sigstore/fulcio when running outside of PRs. - id-token: write - - steps: - - name: Checkout repository - uses: actions/checkout@v3 - - - name: Set up QEMU - uses: docker/setup-qemu-action@v2 - - - name: Setup Docker buildx - uses: docker/setup-buildx-action@v2 - - # Login against a Docker registry except on PR - # https://github.com/docker/login-action - - name: Log into registry ${{ env.REGISTRY }} - if: github.event_name != 'pull_request' - uses: docker/login-action@v2 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - # Extract metadata (tags, labels) for Docker - # https://github.com/docker/metadata-action - - name: Extract Docker metadata - id: meta - uses: docker/metadata-action@v4 - with: - images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} - - # Build and push Docker image with Buildx (don't push on PR) - # https://github.com/docker/build-push-action - - name: Build and push Docker image - id: build-and-push - uses: docker/build-push-action@v3 - with: - context: . - file: images/ferry-tunnel/Dockerfile - push: ${{ github.event_name != 'pull_request' }} - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - platforms: linux/amd64,linux/arm64,linux/arm,linux/386 diff --git a/.github/workflows/ferryctl-binary.yml b/.github/workflows/ferryctl-binary.yml deleted file mode 100644 index 8d7dea3b..00000000 --- a/.github/workflows/ferryctl-binary.yml +++ /dev/null @@ -1,24 +0,0 @@ -name: Ferryctl Binary - -on: - push: - # Publish semver tags as releases. - tags: [ 'v*.*.*' ] - -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Set up Go - uses: actions/setup-go@v2 - with: - go-version: 1.18 - - name: Build Cross Platform - uses: wzshiming/action-go-build-cross-plantform@v1 - env: - BASENAME: ferryctl - - name: Upload Release Assets - uses: wzshiming/action-upload-release-assets@v1 - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/releases.yaml b/.github/workflows/releases.yaml new file mode 100644 index 00000000..832c96ff --- /dev/null +++ b/.github/workflows/releases.yaml @@ -0,0 +1,43 @@ +name: Releases +on: + push: + tags: + - v* + +env: + PUSH: 'true' + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + +jobs: + releases: + runs-on: ubuntu-latest + if: github.event_name != 'pull_request' + steps: + - uses: actions/checkout@v3 + - name: Set up Go + uses: actions/setup-go@v2 + with: + go-version: 1.18 + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + - name: Log into registry ${{ env.REGISTRY }} + uses: docker/login-action@v2 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Build binary + env: + GH_RELEASE: ${{ github.repository }} + IMAGE_PREFIX: ghcr.io/${{ github.repository }} + run: | + REF=${{ github.ref }} + GIT_TAG="${REF##*/}" make cross-build + - name: Build image + env: + IMAGE_PREFIX: ghcr.io/${{ github.repository }} + run: | + REF=${{ github.ref }} + GIT_TAG="${REF##*/}" make cross-image diff --git a/.github/workflows/test-cloud.yml b/.github/workflows/test-cloud.yml index 5ae24ceb..1eabf8f8 100644 --- a/.github/workflows/test-cloud.yml +++ b/.github/workflows/test-cloud.yml @@ -19,7 +19,8 @@ jobs: go-version: 1.18 - run: | - go build -o ferryctl ./cmd/ferryctl + make build + mv bin/*/*/ferryctl ./ - name: Upload ferryctl uses: actions/upload-artifact@v2 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9ffb864b..6e6187fe 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -7,10 +7,6 @@ on: branches: [ main ] workflow_dispatch: -env: - FERRY_CONTROLLER_IMAGE: ferry-controller:test - FERRY_TUNNEL_IMAGE: ferry-tunnel:test - concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true @@ -44,7 +40,7 @@ jobs: - run: | go test ./pkg/... - build-ferrctl: + build: runs-on: ubuntu-latest needs: - verify @@ -57,45 +53,17 @@ jobs: go-version: 1.18 - run: | - go build -o ferryctl ./cmd/ferryctl - - - name: Upload ferryctl - uses: actions/upload-artifact@v2 - with: - name: ferryctl - path: ferryctl - - build-ferry-controller: - runs-on: ubuntu-latest - needs: - - verify - steps: - - uses: actions/checkout@v3 - - - run: | - docker build -t ${FERRY_CONTROLLER_IMAGE} -f ./images/ferry-controller/Dockerfile . && docker save -o ferry-controller.tar ${FERRY_CONTROLLER_IMAGE} - - - name: Upload ferry - uses: actions/upload-artifact@v2 - with: - name: ferry-controller - path: ferry-controller.tar - - build-ferry-tunnel: - runs-on: ubuntu-latest - needs: - - verify - steps: - - uses: actions/checkout@v3 - - - run: | - docker build -t ${FERRY_TUNNEL_IMAGE} -f ./images/ferry-tunnel/Dockerfile . && docker save -o ferry-tunnel.tar ${FERRY_TUNNEL_IMAGE} + make build image + mv bin/*/*/ferryctl ./ + docker save -o ferry-images.tar $(docker images | grep ghcr.io/ferryproxy/ferry/ | awk '{print $1 ":" $2}') - - name: Upload ferry-tunnel + - name: Upload uses: actions/upload-artifact@v2 with: - name: ferry-tunnel - path: ferry-tunnel.tar + name: artifacts + path: | + ferryctl + ferry-images.tar test-mcs: continue-on-error: true @@ -105,32 +73,19 @@ jobs: - mcs runs-on: ubuntu-latest needs: - - build-ferrctl - - build-ferry-controller - - build-ferry-tunnel + - build steps: - uses: actions/checkout@v3 - - name: Download for ferry-controller - uses: actions/download-artifact@v2 - with: - name: ferry-controller - - - name: Download for ferry-tunnel + - name: Download uses: actions/download-artifact@v2 with: - name: ferry-tunnel - - - name: Download for ferryctl - uses: actions/download-artifact@v2 - with: - name: ferryctl + name: artifacts - name: Setup run: | cp ferryctl /usr/local/bin/ferryctl && chmod +x /usr/local/bin/ferryctl - docker load -i ferry-controller.tar - docker load -i ferry-tunnel.tar + docker load -i ferry-images.tar - name: Start cluster run: | @@ -157,32 +112,19 @@ jobs: - data-plane-unreachable runs-on: ubuntu-latest needs: - - build-ferrctl - - build-ferry-controller - - build-ferry-tunnel + - build steps: - uses: actions/checkout@v3 - - name: Download for ferry-controller - uses: actions/download-artifact@v2 - with: - name: ferry-controller - - - name: Download for ferry-tunnel - uses: actions/download-artifact@v2 - with: - name: ferry-tunnel - - - name: Download for ferryctl + - name: Download uses: actions/download-artifact@v2 with: - name: ferryctl + name: artifacts - name: Setup run: | cp ferryctl /usr/local/bin/ferryctl && chmod +x /usr/local/bin/ferryctl - docker load -i ferry-controller.tar - docker load -i ferry-tunnel.tar + docker load -i ferry-images.tar - name: Start cluster run: | @@ -208,32 +150,19 @@ jobs: - data-plane-unreachable-3-clusters runs-on: ubuntu-latest needs: - - build-ferrctl - - build-ferry-controller - - build-ferry-tunnel + - build steps: - uses: actions/checkout@v3 - - name: Download for ferry-controller - uses: actions/download-artifact@v2 - with: - name: ferry-controller - - - name: Download for ferry-tunnel + - name: Download uses: actions/download-artifact@v2 with: - name: ferry-tunnel - - - name: Download for ferryctl - uses: actions/download-artifact@v2 - with: - name: ferryctl + name: artifacts - name: Setup run: | cp ferryctl /usr/local/bin/ferryctl && chmod +x /usr/local/bin/ferryctl - docker load -i ferry-controller.tar - docker load -i ferry-tunnel.tar + docker load -i ferry-images.tar - name: Start cluster run: | @@ -269,25 +198,19 @@ jobs: - manual runs-on: ubuntu-latest needs: - - build-ferrctl - - build-ferry-tunnel + - build steps: - uses: actions/checkout@v2 - - name: Download for ferry-tunnel - uses: actions/download-artifact@v2 - with: - name: ferry-tunnel - - - name: Download for ferryctl + - name: Download uses: actions/download-artifact@v2 with: - name: ferryctl + name: artifacts - name: Setup run: | cp ferryctl /usr/local/bin/ferryctl && chmod +x /usr/local/bin/ferryctl - docker load -i ferry-tunnel.tar + docker load -i ferry-images.tar - name: Start cluster run: | diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..ba3cd3c3 --- /dev/null +++ b/Makefile @@ -0,0 +1,135 @@ +# Copyright 2022 FerryProxy Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +GO_CMD ?= go + +DRY_RUN ?= +PUSH ?= + +GH_RELEASE ?= + +VERSION ?= $(shell git describe --tags --dirty --always) + +BASE_REF ?= $(shell git rev-parse --abbrev-ref HEAD) + +EXTRA_TAGS ?= + +BINARY ?= ferryctl + +IMAGE_BINARY ?= ferry-controller ferry-tunnel ferry-tunnel-controller + +IMAGE_PREFIX ?= ghcr.io/ferryproxy/ferry + +CONTROLLER_IMAGE ?= $(IMAGE_PREFIX)/ferry-controller + +TUNNEL_IMAGE ?= $(IMAGE_PREFIX)/ferry-tunnel + +IMAGE_PLATFORMS ?= linux/amd64 linux/arm64 + +BINARY_PLATFORMS ?= linux/amd64 linux/arm64 darwin/amd64 darwin/arm64 windows/amd64 windows/arm64 + +DOCKER_CLI_EXPERIMENTAL ?= enabled + +.PHONY: default +default: help + +vendor: + $(GO_CMD) mod vendor + +## unit-test: Run unit tests +.PHONY: unit-test +unit-test: vendor + $(GO_CMD) test ./pkg/... + +## verify: Verify code +.PHONY: verify +verify: + @./hack/verify-all.sh + +## build: Build binary +.PHONY: build +build: vendor + @./hack/releases.sh \ + $(addprefix --bin=, $(BINARY)) \ + $(addprefix --extra-tag=, $(EXTRA_TAGS)) \ + --gh-release=${GH_RELEASE} \ + --image-prefix=${IMAGE_PREFIX} \ + --version=${VERSION} \ + --dry-run=${DRY_RUN} \ + --push=${PUSH} + +## cross-build: Build all supported platforms +.PHONY: cross-build +cross-build: vendor + @./hack/releases.sh \ + $(addprefix --bin=, $(BINARY)) \ + $(addprefix --platform=, $(BINARY_PLATFORMS)) \ + $(addprefix --extra-tag=, $(EXTRA_TAGS)) \ + --gh-release=${GH_RELEASE} \ + --image-prefix=${IMAGE_PREFIX} \ + --version=${VERSION} \ + --dry-run=${DRY_RUN} \ + --push=${PUSH} + +## image: Build image +.PHONY: image +image: + @./hack/releases.sh \ + $(addprefix --bin=, $(IMAGE_BINARY)) \ + --gh-release=${GH_RELEASE} \ + --image-prefix=${IMAGE_PREFIX} \ + --version=${VERSION} \ + --dry-run=${DRY_RUN} + @./images/ferry-controller/build.sh \ + $(addprefix --extra-tag=, $(EXTRA_TAGS)) \ + --image=${CONTROLLER_IMAGE} \ + --version=${VERSION} \ + --dry-run=${DRY_RUN} \ + --push=${PUSH} + @./images/ferry-tunnel/build.sh \ + $(addprefix --extra-tag=, $(EXTRA_TAGS)) \ + --image=${TUNNEL_IMAGE} \ + --version=${VERSION} \ + --dry-run=${DRY_RUN} \ + --push=${PUSH} + +## cross-image: Build images for all supported platforms +.PHONY: cross-image +cross-image: + @./hack/releases.sh \ + $(addprefix --bin=, $(IMAGE_BINARY)) \ + $(addprefix --platform=, $(IMAGE_PLATFORMS)) \ + --gh-release=${GH_RELEASE} \ + --image-prefix=${IMAGE_PREFIX} \ + --version=${VERSION} \ + --dry-run=${DRY_RUN} + @./images/ferry-controller/build.sh \ + $(addprefix --platform=, $(IMAGE_PLATFORMS)) \ + $(addprefix --extra-tag=, $(EXTRA_TAGS)) \ + --image=${CONTROLLER_IMAGE} \ + --version=${VERSION} \ + --dry-run=${DRY_RUN} \ + --push=${PUSH} + @./images/ferry-tunnel/build.sh \ + $(addprefix --platform=, $(IMAGE_PLATFORMS)) \ + $(addprefix --extra-tag=, $(EXTRA_TAGS)) \ + --image=${TUNNEL_IMAGE} \ + --version=${VERSION} \ + --dry-run=${DRY_RUN} \ + --push=${PUSH} + +## help: Show this help message +.PHONY: help +help: + @cat $(MAKEFILE_LIST) | grep -e '^## ' | sed -e 's/^## //' diff --git a/hack/releases.sh b/hack/releases.sh new file mode 100755 index 00000000..7f2ac540 --- /dev/null +++ b/hack/releases.sh @@ -0,0 +1,161 @@ +#!/usr/bin/env bash +# Copyright 2022 FerryProxy Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +DIR="$(dirname "${BASH_SOURCE[0]}")" + +ROOT_DIR="$(realpath "${DIR}/..")" + +GH_RELEASE="" +IMAGE_PREFIX="" +VERSION="" +DRY_RUN=false +PUSH=false +BINS=() +EXTRA_TAGS=() +PLATFORMS=() +LDFLAGS=() + +function usage() { + echo "Usage: ${0} [--help] [--bin ...] [--extra-tag ...] [--platform ...] [--image-prefix ] [--version ] [--push] [--dry-run]" + echo " --bin is binary, is required" + echo " --extra-tag is extra tag" + echo " --platform is multi-platform capable for binary" + echo " --gh-release is github release" + echo " --image-prefix is image prefix" + echo " --version is version of binary" + echo " --push will push binary to gh release" + echo " --dry-run just show what would be done" +} + +function args() { + local arg + while [[ $# -gt 0 ]]; do + arg="$1" + case "${arg}" in + --bin | --bin=*) + [[ "${arg#*=}" != "${arg}" ]] && BINS+=("${arg#*=}") || { BINS+=("${2}") && shift; } + shift + ;; + --extra-tag | --extra-tag=*) + [[ "${arg#*=}" != "${arg}" ]] && EXTRA_TAGS+=("${arg#*=}") || { EXTRA_TAGS+=("${2}") && shift; } + shift + ;; + --platform | --platform=*) + [[ "${arg#*=}" != "${arg}" ]] && PLATFORMS+=("${arg#*=}") || { PLATFORMS+=("${2}") && shift; } + shift + ;; + --gh-release | --gh-release=*) + [[ "${arg#*=}" != "${arg}" ]] && GH_RELEASE="${arg#*=}" || { GH_RELEASE="${2}" && shift; } + shift + ;; + --image-prefix | --image-prefix=*) + [[ "${arg#*=}" != "${arg}" ]] && IMAGE_PREFIX="${arg#*=}" || { IMAGE_PREFIX="${2}" && shift; } + shift + ;; + --version | --version=*) + [[ "${arg#*=}" != "${arg}" ]] && VERSION="${arg#*=}" || { VERSION="${2}" && shift; } + shift + ;; + --push | --push=*) + [[ "${arg#*=}" != "${arg}" ]] && PUSH="${arg#*=}" || PUSH="true" + shift + ;; + --dry-run | --dry-run=*) + [[ "${arg#*=}" != "${arg}" ]] && DRY_RUN="${arg#*=}" || DRY_RUN="true" + shift + ;; + --help) + usage + exit 0 + ;; + *) + echo "Unknown argument: ${arg}" + usage + exit 1 + ;; + esac + done + + if [[ "${#BINS}" -eq 0 ]]; then + echo "--bin is required" + usage + exit 1 + fi + + if [[ "${#PLATFORMS}" -eq 0 ]]; then + PLATFORMS+=( + linux/amd64 + ) + fi +} + +function dry_run() { + echo "${@}" + if [[ "${DRY_RUN}" != "true" ]]; then + eval "${@}" + fi +} + +function main() { + local os + local dist + local src + local bin + local tmp_bin + local extra_args=() + + if [[ "${VERSION}" != "" ]]; then + LDFLAGS+=("-X github.com/ferryproxy/ferry/pkg/consts.Version=${VERSION}") + fi + if [[ "${IMAGE_PREFIX}" != "" ]]; then + LDFLAGS+=("-X github.com/ferryproxy/ferry/pkg/consts.ImagePrefix=${IMAGE_PREFIX}") + fi + + if [[ "${#LDFLAGS}" -gt 0 ]]; then + extra_args+=("-ldflags" "'${LDFLAGS[*]}'") + fi + + for platform in "${PLATFORMS[@]}"; do + os="${platform%%/*}" + for binary in "${BINS[@]}"; do + bin="${binary}" + if [[ "${os}" == "windows" ]]; then + bin="${bin}.exe" + fi + dist="./bin/${platform}/${bin}" + src="./cmd/${binary}" + CGO_ENABLED=0 dry_run GOOS="${platform%%/*}" GOARCH="${platform##*/}" go build "${extra_args[@]}" -o "${dist}" "${src}" + if [[ "${PUSH}" == "true" ]]; then + if [[ "${GH_RELEASE}" != "" ]]; then + tmp_bin="${binary}-${platform%%/*}-${platform##*/}" + if [[ "${os}" == "windows" ]]; then + tmp_bin="${tmp_bin}.exe" + fi + dry_run cp "${dist}" "${tmp_bin}" + dry_run gh -R "${GH_RELEASE}" release upload "${VERSION}" "${tmp_bin}" + if [[ "${#EXTRA_TAGS}" -ne 0 ]]; then + for extra_tag in "${EXTRA_TAGS[@]}"; do + dry_run gh -R "${GH_RELEASE}" release upload "${extra_tag}" "${tmp_bin}" + done + fi + fi + fi + done + done +} + +args "$@" + +cd "${ROOT_DIR}" && main diff --git a/images/ferry-controller/Dockerfile b/images/ferry-controller/Dockerfile index d1179d50..786f60b1 100644 --- a/images/ferry-controller/Dockerfile +++ b/images/ferry-controller/Dockerfile @@ -12,13 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. -FROM docker.io/library/golang:alpine AS builder -WORKDIR /go/src/github.com/ferryproxy/ferry/ -COPY . . -ENV CGO_ENABLED=0 -RUN apk add git -RUN go install ./cmd/ferry-controller +FROM --platform=$TARGETPLATFORM docker.io/library/alpine:3.16 +ARG TARGETPLATFORM +COPY --chmod=0755 bin/$TARGETPLATFORM/ferry-controller /usr/local/bin/ -FROM docker.io/library/alpine -COPY --from=builder /go/bin/ferry-controller /usr/local/bin/ ENTRYPOINT [ "/usr/local/bin/ferry-controller" ] diff --git a/images/ferry-controller/build.sh b/images/ferry-controller/build.sh new file mode 100755 index 00000000..f981711b --- /dev/null +++ b/images/ferry-controller/build.sh @@ -0,0 +1,143 @@ +#!/usr/bin/env bash +# Copyright 2022 FerryProxy Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +DIR="$(dirname "${BASH_SOURCE[0]}")" +DIR="$(realpath "${DIR}")" +ROOT_DIR="$(realpath "${DIR}/../..")" +DOCKERFILE="$(realpath "${DIR}/Dockerfile" --relative-to="${ROOT_DIR}")" + +DRY_RUN=false +PUSH=false +IMAGES=() +EXTRA_TAGS=() +PLATFORMS=() +VERSION="" + +function usage() { + echo "Usage: ${0} [--help] [--version ] [--image ...] [--extra-tag ...] [--platform ...] [--push] [--dry-run]" + echo " --version is version, is required" + echo " --image is image, is required" + echo " --extra-tag is extra tag" + echo " --platform is multi-platform capable for image" + echo " --push will push image to registry" + echo " --dry-run just show what would be done" +} + +function args() { + local arg + while [[ $# -gt 0 ]]; do + arg="$1" + case "${arg}" in + --version | --version=*) + [[ "${arg#*=}" != "${arg}" ]] && VERSION="${arg#*=}" || { VERSION="${2}" && shift; } + shift + ;; + --image | --image=*) + [[ "${arg#*=}" != "${arg}" ]] && IMAGES+=("${arg#*=}") || { IMAGES+=("${2}") && shift; } + shift + ;; + --extra-tag | --extra-tag=*) + [[ "${arg#*=}" != "${arg}" ]] && EXTRA_TAGS+=("${arg#*=}") || { EXTRA_TAGS+=("${2}") && shift; } + shift + ;; + --platform | --platform=*) + [[ "${arg#*=}" != "${arg}" ]] && PLATFORMS+=("${arg#*=}") || { PLATFORMS+=("${2}") && shift; } + shift + ;; + --push | --push=*) + [[ "${arg#*=}" != "${arg}" ]] && PUSH="${arg#*=}" || PUSH="true" + shift + ;; + --dry-run | --dry-run=*) + [[ "${arg#*=}" != "${arg}" ]] && DRY_RUN="${arg#*=}" || DRY_RUN="true" + shift + ;; + --help) + usage + exit 0 + ;; + *) + echo "Unknown argument: ${arg}" + usage + exit 1 + ;; + esac + done + + if [[ "${VERSION}" == "" ]]; then + echo "--version is required" + usage + exit 1 + fi + + if [[ "${#IMAGES}" -eq 0 ]]; then + echo "--image is required" + usage + exit 1 + fi + + if [[ "${#PLATFORMS}" -eq 0 ]]; then + PLATFORMS+=( + linux/amd64 + ) + fi +} + +function dry_run() { + echo "${@}" + if [[ "${DRY_RUN}" != "true" ]]; then + eval "${@}" + fi +} + +function main() { + local extra_args + local tag + + extra_args=() + for image in "${IMAGES[@]}"; do + tag="${VERSION}" + extra_args+=( + "--tag=${image}:${tag}" + ) + if [[ "${#EXTRA_TAGS[@]}" -ne 0 ]]; then + for extra_tag in "${EXTRA_TAGS[@]}"; do + tag="${extra_tag}" + extra_args+=( + "--tag=${image}:${tag}" + ) + done + fi + done + + for platform in "${PLATFORMS[@]}"; do + extra_args+=( + "--platform=${platform}" + ) + done + if [[ "${PUSH}" == "true" ]]; then + extra_args+=("--push") + else + extra_args+=("--load") + fi + dry_run docker buildx build \ + "${extra_args[@]}" \ + -f "${DOCKERFILE}" \ + . +} + +args "$@" + +cd "${ROOT_DIR}" && main diff --git a/images/ferry-tunnel/Dockerfile b/images/ferry-tunnel/Dockerfile index 248db0b0..a7624087 100644 --- a/images/ferry-tunnel/Dockerfile +++ b/images/ferry-tunnel/Dockerfile @@ -12,15 +12,9 @@ # See the License for the specific language governing permissions and # limitations under the License. -FROM docker.io/library/golang:alpine AS builder -WORKDIR /go/src/github.com/ferryproxy/ferry/ -COPY . . -ENV CGO_ENABLED=0 -RUN apk add git -RUN go install ./cmd/ferry-tunnel-controller -RUN go install ./cmd/ferry-tunnel +FROM --platform=$TARGETPLATFORM docker.io/library/alpine:3.16 +ARG TARGETPLATFORM +COPY --chmod=0755 bin/$TARGETPLATFORM/ferry-tunnel-controller /usr/local/bin/ +COPY --chmod=0755 bin/$TARGETPLATFORM/ferry-tunnel /usr/local/bin/ -FROM ghcr.io/wzshiming/bridge/bridge:v0.8.5 -COPY --from=builder /go/bin/ferry-tunnel-controller /usr/local/bin/ -COPY --from=builder /go/bin/ferry-tunnel /usr/local/bin/ ENTRYPOINT [ "/usr/local/bin/ferry-tunnel-controller" ] diff --git a/images/ferry-tunnel/build.sh b/images/ferry-tunnel/build.sh new file mode 100755 index 00000000..f981711b --- /dev/null +++ b/images/ferry-tunnel/build.sh @@ -0,0 +1,143 @@ +#!/usr/bin/env bash +# Copyright 2022 FerryProxy Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +DIR="$(dirname "${BASH_SOURCE[0]}")" +DIR="$(realpath "${DIR}")" +ROOT_DIR="$(realpath "${DIR}/../..")" +DOCKERFILE="$(realpath "${DIR}/Dockerfile" --relative-to="${ROOT_DIR}")" + +DRY_RUN=false +PUSH=false +IMAGES=() +EXTRA_TAGS=() +PLATFORMS=() +VERSION="" + +function usage() { + echo "Usage: ${0} [--help] [--version ] [--image ...] [--extra-tag ...] [--platform ...] [--push] [--dry-run]" + echo " --version is version, is required" + echo " --image is image, is required" + echo " --extra-tag is extra tag" + echo " --platform is multi-platform capable for image" + echo " --push will push image to registry" + echo " --dry-run just show what would be done" +} + +function args() { + local arg + while [[ $# -gt 0 ]]; do + arg="$1" + case "${arg}" in + --version | --version=*) + [[ "${arg#*=}" != "${arg}" ]] && VERSION="${arg#*=}" || { VERSION="${2}" && shift; } + shift + ;; + --image | --image=*) + [[ "${arg#*=}" != "${arg}" ]] && IMAGES+=("${arg#*=}") || { IMAGES+=("${2}") && shift; } + shift + ;; + --extra-tag | --extra-tag=*) + [[ "${arg#*=}" != "${arg}" ]] && EXTRA_TAGS+=("${arg#*=}") || { EXTRA_TAGS+=("${2}") && shift; } + shift + ;; + --platform | --platform=*) + [[ "${arg#*=}" != "${arg}" ]] && PLATFORMS+=("${arg#*=}") || { PLATFORMS+=("${2}") && shift; } + shift + ;; + --push | --push=*) + [[ "${arg#*=}" != "${arg}" ]] && PUSH="${arg#*=}" || PUSH="true" + shift + ;; + --dry-run | --dry-run=*) + [[ "${arg#*=}" != "${arg}" ]] && DRY_RUN="${arg#*=}" || DRY_RUN="true" + shift + ;; + --help) + usage + exit 0 + ;; + *) + echo "Unknown argument: ${arg}" + usage + exit 1 + ;; + esac + done + + if [[ "${VERSION}" == "" ]]; then + echo "--version is required" + usage + exit 1 + fi + + if [[ "${#IMAGES}" -eq 0 ]]; then + echo "--image is required" + usage + exit 1 + fi + + if [[ "${#PLATFORMS}" -eq 0 ]]; then + PLATFORMS+=( + linux/amd64 + ) + fi +} + +function dry_run() { + echo "${@}" + if [[ "${DRY_RUN}" != "true" ]]; then + eval "${@}" + fi +} + +function main() { + local extra_args + local tag + + extra_args=() + for image in "${IMAGES[@]}"; do + tag="${VERSION}" + extra_args+=( + "--tag=${image}:${tag}" + ) + if [[ "${#EXTRA_TAGS[@]}" -ne 0 ]]; then + for extra_tag in "${EXTRA_TAGS[@]}"; do + tag="${extra_tag}" + extra_args+=( + "--tag=${image}:${tag}" + ) + done + fi + done + + for platform in "${PLATFORMS[@]}"; do + extra_args+=( + "--platform=${platform}" + ) + done + if [[ "${PUSH}" == "true" ]]; then + extra_args+=("--push") + else + extra_args+=("--load") + fi + dry_run docker buildx build \ + "${extra_args[@]}" \ + -f "${DOCKERFILE}" \ + . +} + +args "$@" + +cd "${ROOT_DIR}" && main diff --git a/pkg/consts/consts.go b/pkg/consts/consts.go index c4d9dfa6..05373e0e 100644 --- a/pkg/consts/consts.go +++ b/pkg/consts/consts.go @@ -16,6 +16,11 @@ limitations under the License. package consts +var ( + Version = "unknown" + ImagePrefix = "ghcr.io/ferryproxy/ferry" +) + const ( FerryName = "ferry" FerryNamespace = FerryName + "-system" diff --git a/pkg/ferryctl/vars/vars.go b/pkg/ferryctl/vars/vars.go index ef790f87..ac3d0fbe 100644 --- a/pkg/ferryctl/vars/vars.go +++ b/pkg/ferryctl/vars/vars.go @@ -21,6 +21,7 @@ import ( "os" "path/filepath" + "github.com/ferryproxy/ferry/pkg/consts" "github.com/ferryproxy/ferry/pkg/utils/env" ) @@ -30,9 +31,9 @@ var ( KubeconfigPath = env.GetEnv("KUBECONFIG", filepath.Join(home, ".kube/config")) PeerKubeconfigPath = env.GetEnv("FERRY_PEER_KUBECONFIG", "") - FerryImagePrefix = env.GetEnv("FERRY_IMAGE_PREFIX", "ghcr.io/ferryproxy/ferry") + FerryImagePrefix = env.GetEnv("FERRY_IMAGE_PREFIX", consts.ImagePrefix) - FerryVersion = env.GetEnv("FERRY_VERSION", "v0.5.1") + FerryVersion = env.GetEnv("FERRY_VERSION", consts.Version) FerryControllerImage = env.GetEnv("FERRY_CONTROLLER_IMAGE", FerryImagePrefix+"/ferry-controller:"+FerryVersion)