From 0c95c72e0a48f6ccfe4b4f790a8a4239fd27b05c Mon Sep 17 00:00:00 2001 From: titigmr Date: Sat, 17 Aug 2024 21:15:05 +0200 Subject: [PATCH] chore: :zap: add stack for dev locally --- Makefile | 117 +++++++++ README.md | 63 ++++- contribute/Makefile | 31 --- contribute/README.md | 38 +++ .../kind/kind-config.yaml | 4 +- .../kind/traefik-values.yaml | 10 +- contribute/midaas-ws/main.py | 45 ++-- .../ressources/external-dns-values.yaml | 35 +-- .../ressources/ingress.yaml | 4 +- kind/README.md | 37 --- kind/docker-compose.yml | 7 - kind/run.sh | 245 ------------------ 12 files changed, 271 insertions(+), 365 deletions(-) create mode 100644 Makefile delete mode 100644 contribute/Makefile create mode 100644 contribute/README.md rename kind/configs/kind-config.yml => contribute/kind/kind-config.yaml (91%) rename kind/configs/traefik-values.yml => contribute/kind/traefik-values.yaml (57%) rename kind/resources/external-dns-values.yml => contribute/ressources/external-dns-values.yaml (57%) rename kind/resources/ingress.yml => contribute/ressources/ingress.yaml (80%) delete mode 100644 kind/README.md delete mode 100644 kind/docker-compose.yml delete mode 100755 kind/run.sh diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..dde1fa2 --- /dev/null +++ b/Makefile @@ -0,0 +1,117 @@ +SHELL := /bin/bash +DOCKER := $(shell type -p docker) +KIND := $(shell type -p kind) +HELM := $(shell type -p helm) +KUBECTL := $(shell type -p helm) + +WEBHOOK_IMAGE := external-dns-midaas-webhook:dev +WEBHOOK_FOLDER := ./ + +MIDAAS_IMAGE := api-midaas:dev +MIDAAS_FOLDER := ./contribute/midaas-ws/ + +export MIDAAS_WS_URL ?= http://midaas.default:8080/ws/ +export MIDAAS_DEV_SUFFIX ?= dev.local +export MIDAAS_ENV_KEYNAME ?= d1 +export MIDAAS_ENV_KEYVALUE ?= test +export MIDAAS_ENV_ZONES ?= $(MIDAAS_ENV_KEYNAME).$(MIDAAS_DEV_SUFFIX) + +KIND_CLUSTER_NAME ?= midaas +KIND_INGRESS_CONTROLLER = NGINX + +# Commons targets + +all: deploy-MIDAAS deploy-WEBHOOK create-test-ingress + +clean: delete-cluster delete-image-MIDAAS delete-image-WEBHOOK + +create-test-ingress: create-cluster check-prerequisites-kubectl + @kubectl apply -f ./contribute/ressources/ingress.yaml + +logs-%: + @kubectl logs -f deployments/external-dns -c $* + +midaas-get-zone: + @kubectl exec midaas cat /tmp/$(MIDAAS_ENV_KEYNAME).$(MIDAAS_DEV_SUFFIX) | jq + +# Check prerequisites + +check-prerequisites-docker: +ifeq ("$(wildcard ${DOCKER})","") + @echo "docker not found" ; exit 1 +endif +check-prerequisites-kind: +ifeq ("$(wildcard ${KIND})","") + @echo "'kind' not found" ; exit 1 +endif +check-prerequisites-kubectl: +ifeq ("$(wildcard ${KUBECTL})","") + @echo "'kubectl' not found" ; exit 1 +endif +check-prerequisites-helm: +ifeq ("$(wildcard ${HELM})","") + @echo "'helm' not found" ; exit 1 +endif + +# Kind targets + +create-cluster: check-prerequisites-kind +ifeq ($(shell kind get clusters |grep $(KIND_CLUSTER_NAME)), $(KIND_CLUSTER_NAME)) + @echo "Kind cluster '$(KIND_CLUSTER_NAME)' already exists, skipping" +else + @kind create cluster --name $(KIND_CLUSTER_NAME) --config ./contribute/kind/kind-config.yaml + @kubectl config use-context kind-$(KIND_CLUSTER_NAME) +endif + +delete-cluster: check-prerequisites-kind +ifeq ($(shell kind get clusters |grep $(KIND_CLUSTER_NAME)), $(KIND_CLUSTER_NAME)) + @kind delete cluster --name $(KIND_CLUSTER_NAME) +endif + +start-ingress-controller: create-cluster +ifeq ($(KIND_INGRESS_CONTROLLER), NGINX) + @if [ ! -s /tmp/external-dns-nginx.yaml ]; then curl -Ls https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml > /tmp/external-dns-nginx.yaml; fi + @kubectl apply -f /tmp/external-dns-nginx.yaml + @kubectl wait --namespace ingress-nginx \ + --for=condition=ready pod \ + --selector=app.kubernetes.io/component=controller \ + --timeout=90s +else ifeq ($(KIND_INGRESS_CONTROLLER), TRAEFIK) + @echo traefik +endif + +# Docker build and push targets +build-%: check-prerequisites-docker + @if [ $* = WEBHOOK ]; then docker build --target dev ${OPTIONS} -t ${$*_IMAGE} ${$*_FOLDER}; else docker build ${OPTIONS} -t ${$*_IMAGE} ${$*_FOLDER}; fi + +push-%: check-prerequisites-kind + kind load docker-image ${$*_IMAGE} --name $(KIND_CLUSTER_NAME) + +delete-image-%: check-prerequisites-docker + docker rmi ${$*_IMAGE} + +# Midaas deployment targets +delete-MIDAAS: create-cluster check-prerequisites-kubectl + @kubectl delete pod midaas --ignore-not-found + @kubectl delete svc midaas --ignore-not-found + +deploy-MIDAAS: create-cluster check-prerequisites-kubectl build-MIDAAS push-MIDAAS delete-MIDAAS + @kubectl run --image $(MIDAAS_IMAGE) --expose=true --port 8080 \ + --env "MIDAAS_KEYNAME=$(MIDAAS_ENV_KEYNAME)" \ + --env "MIDAAS_KEYVALUE=$(MIDAAS_ENV_KEYVALUE)" \ + --env "MIDAAS_ZONES=$(MIDAAS_ENV_ZONES)" midaas + @echo "Kubernetes midaas service is listening on port 8080" + + +# Webhook deployment targets + +delete-WEBHOOK: create-cluster check-prerequisites-helm + @if [ "external-dns" == "$(shell helm ls -f external-dns -o json |jq -r .[].name)" ]; then helm delete external-dns; else echo "No external-dns release is currently running"; fi + +deploy-WEBHOOK: start-ingress-controller check-prerequisites-helm build-WEBHOOK push-WEBHOOK delete-WEBHOOK + @echo "Adding repository" + @helm repo add external-dns https://kubernetes-sigs.github.io/external-dns/ + @envsubst < ./contribute/ressources/external-dns-values.yaml > /tmp/external-dns-values.yaml + @helm upgrade --force --install external-dns external-dns/external-dns -f /tmp/external-dns-values.yaml + @echo "external DNS is running with webhook in sidecar" + diff --git a/README.md b/README.md index f708454..fbbe582 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,8 @@ helm repo add external-dns https://kubernetes-sigs.github.io/external-dns/ 1. Create the helm values file `external-dns-midaas-values.yaml`: ```yaml +sources: + - ingress # -- How DNS records are synchronized between sources and providers; available values are `sync` & `upsert-only`. policy: sync # -- Specify the registry for storing ownership and labels. @@ -24,7 +26,7 @@ policy: sync # If `noop` midaas manage all records on zone registry: txt # can restrict zone -domainFilters: ["subzone.d1.dev.example.com"] +domainFilters: [] provider: name: webhook webhook: @@ -43,7 +45,7 @@ provider: 2. Create helm deployment: ```sh -helm install external-dns external-dns -f external-dns-midaas-values.yaml +helm install external-dns external-dns/external-dns -f external-dns-midaas-values.yaml ``` ## Parameters references @@ -65,7 +67,62 @@ For example, `TSIG_ZONE_d1` with `PROVIDER_DNS_ZONE_SUFFIX` with `dev.example.co ## Local development -🚧 Work in progress. +### Prerequisite + +Download and install on your local machine: +- `make` in Debian/Ubuntu distrib with +```bash + sudo apt install build-essential +``` +- [docker](https://docs.docker.com/engine/install/) +- [kubectl](https://github.com/kubernetes/kubectl) +- [kind](https://github.com/kubernetes-sigs/kind) +- [helm](https://github.com/helm/helm) + +### Usage + + +You can create a development stack locally with this command: + +```sh +make +``` + +This target do the following target successively: +- `create-cluster` : create a `kind` cluster locally with an ingress controller configured +- `deploy-MIDAAS` : build, push and deploy `midaas` [webservice mock](./contribute/midaas-ws/) in the cluster +- `deploy-WEBHOOK` : build, push and deploy `external-dns` with the midaas webhook in development mode. You can modify the code with hot reload. + +For example, for restarting the webhook: + +```bash +make deploy-WEBHOOK +``` + +Don't forget create an ingress for trigger `external-dns`, an [example](./contribute/ressources/ingress.yaml) can be created with: + +```bash +make create-test-ingress +``` + +You can read the containers logs with: + +```bash +make logs-webhook +``` + +or + +```bash +make logs-external-dns +``` + +To clean all the components + +```sh +make clean +``` + ## Contributions diff --git a/contribute/Makefile b/contribute/Makefile deleted file mode 100644 index 3ed6a9f..0000000 --- a/contribute/Makefile +++ /dev/null @@ -1,31 +0,0 @@ -MIDAAS_IMAGE := api-midaas:v1 -WEBHOOK_IMAGE := webhook:v1 -ENV_MIDAAS_KEYNAME := test -ENV_MIDAAS_KEYVALUE := test -ENV_MIDAAS_ZONES := dev.local -CACHE_CONFIG := /tmp/cluster-name.txt -CLUSTER_NAME := go - -build-midaas: - docker build -t ${MIDAAS_IMAGE} midaas-ws/ - -push-midaas: - kind load docker-image ${MIDAAS_IMAGE} --name ${CLUSTER_NAME} - -delete-midaas: - @kubectl delete pod midaas --ignore-not-found - @kubectl delete svc midaas --ignore-not-found - -deploy-midaas: delete-midaas - @kubectl run --image ${MIDAAS_IMAGE} --expose=true --port 8080 \ - --env "MIDAAS_KEYNAME=${ENV_MIDAAS_KEYNAME}" \ - --env "MIDAAS_KEYVALUE=${ENV_MIDAAS_KEYVALUE}" \ - --env "MIDAAS_ZONES=${ENV_MIDAAS_ZONES}" midaas - @echo "\n\n-------------------" - @echo "Kubernetes midaas service is listening on port 8080" - @echo "Use 'TSIG_${ENV_MIDAAS_KEYNAME}=${ENV_MIDAAS_KEYVALUE}' on environment variable in webhook" - @echo "For manual actions, OpenAPI schema is available at path /docs" - - -start-midaas: build-midaas push-midaas deploy-midaas - diff --git a/contribute/README.md b/contribute/README.md new file mode 100644 index 0000000..81f894b --- /dev/null +++ b/contribute/README.md @@ -0,0 +1,38 @@ +# Run all stack locally with docker + +## Kind cluster + +One single node is deployed but it can be customized in `./kind/kind-config.yml`. The cluster comes with [Traefik](https://doc.traefik.io/traefik/providers/kubernetes-ingress/) or [Nginx](https://kind.sigs.k8s.io/docs/user/ingress/#ingress-nginx) ingress controller installed with port mapping on both ports `8080` and `8443`. + +The node is using `extraMounts` to provide a volume binding between host working directory and `/app` to give the ability to bind mount volumes into containers during development. + + +## Midaas Webservice + +A wrapper of midaas is available for development on folder `./midaas-ws`. Note that tool not really do dns records. It only writes fake domain on container filesystem. + +This webservice is written in python with `Fastapi` framework. The webservice listen on 3 endpoints: +- `GET` - `/ws/{domaine}` : retrieve all domains for a specific zone +- `PUT` - `/ws/{domaine}/{type}/{valeur}` : add or modify a DNS record +You must add this body in the request: +```json +{"ttl": 0, "keyname": "string", "keyvalue": "string"} +``` +- `DELETE` - `/ws/{domaine}/{type}/{valeur}` : add or modify a DNS +You must add this body in the request: +```json +{"keyname": "string", "keyvalue": "string"} +``` + +The midaas webservice can be configured with the following environment variables: + +| Name | Description | Default | +| --------------- | ---------------------- | --------- | +| MIDAAS_KEYNAME | TSIG Keyname | test | +| MIDAAS_KEYVALUE | TSIG Keyvalue | test | +| MIDAAS_ZONE | Zone managed by MiDaas | dev.local | + + +## External-DNS Locally + +:construction: \ No newline at end of file diff --git a/kind/configs/kind-config.yml b/contribute/kind/kind-config.yaml similarity index 91% rename from kind/configs/kind-config.yml rename to contribute/kind/kind-config.yaml index 6c27e25..62fff9a 100644 --- a/kind/configs/kind-config.yml +++ b/contribute/kind/kind-config.yaml @@ -11,10 +11,10 @@ nodes: node-labels: "ingress-ready=true" extraPortMappings: - containerPort: 80 - hostPort: 80 + hostPort: 8080 protocol: TCP - containerPort: 443 - hostPort: 443 + hostPort: 8443 protocol: TCP extraMounts: - hostPath: ./ diff --git a/kind/configs/traefik-values.yml b/contribute/kind/traefik-values.yaml similarity index 57% rename from kind/configs/traefik-values.yml rename to contribute/kind/traefik-values.yaml index a028b87..6fae1b7 100644 --- a/kind/configs/traefik-values.yml +++ b/contribute/kind/traefik-values.yaml @@ -1,9 +1,7 @@ --- providers: kubernetesCRD: - namespaces: - - default - - ingress-traefik + enabled: false kubernetesIngress: namespaces: - default @@ -11,9 +9,9 @@ providers: ports: web: - nodePort: 80 + hostPort: 80 websecure: - nodePort: 443 + hostPort: 443 service: - type: NodePort + type: ClusterIP \ No newline at end of file diff --git a/contribute/midaas-ws/main.py b/contribute/midaas-ws/main.py index c6acf89..3e3734a 100644 --- a/contribute/midaas-ws/main.py +++ b/contribute/midaas-ws/main.py @@ -3,20 +3,15 @@ import json from fastapi import FastAPI, Response, Request, Body from pydantic import BaseModel +import logging +logger = logging.getLogger('uvicorn.error') -KEYNAME = os.environ.get("MIDAAS_KEYNAME", "test") +KEYNAME = "ddns-key." + os.environ.get("MIDAAS_KEYNAME", "d1") KEYVALUE = os.environ.get("MIDAAS_KEYVALUE", "test") -ZONES = os.environ.get("MIDAAS_ZONE", "dev.local,test.local") +ZONES = os.environ.get("MIDAAS_ZONES", "d1.dev.local") ALL_ZONES = ZONES.split(",") -INFO = f""" -Informations about current midaas instance: -- keyname: {KEYNAME} - (MIDAAS_KEYNAME env var) -- keyvalue: {KEYVALUE} - (MIDAAS_KEYVALUE env var) - -Availables zones are comma separated: {ZONES} (MIDAAS_ZONE env var) -""" app = FastAPI() @@ -32,11 +27,16 @@ class TTLCreate(BaseModel): def check_TSIG(keyname, keyvalue): - return keyname == KEYNAME and KEYVALUE == keyvalue + if not keyname == KEYNAME and KEYVALUE == keyvalue: + logger.info(f"Keyname or Keyvalue not match") + logger.info(f"Keyname: {keyname} with {KEYNAME}") + logger.info(f"Keyvalue: {keyname} with {KEYNAME}") + return False + return True def create_zone(file): - print(f"Creating zone on {file}") + logger.info(f"Creating zone on {file}") with open(file, "w+") as f: json.dump({}, f) @@ -61,12 +61,14 @@ def read_zone(file): @app.get("/ws/{domaine}") async def list_domain(request: Request, domaine): + logger.info(f"GET on url: {request.url}") records = {} for zone in ALL_ZONES: if zone in domaine.strip().lower(): file = f"/tmp/{zone}" create_zone_if_not_exist(file) records = read_zone(file) + logger.info(f"Zone content : {records}") return records return records @@ -78,6 +80,7 @@ async def health(): @app.put("/ws/{domaine}/{type}/{valeur}") def create(response: Response, request: Request, domaine: str, type: str, valeur: str, TTL: TTLCreate) -> dict: + logger.info(f"PUT on url: {request.url}") if not check_TSIG(keyname=TTL.keyname, keyvalue=TTL.keyvalue): return {"status": "ERROR", "message": "wrong credentials"} @@ -87,16 +90,21 @@ def create(response: Response, request: Request, domaine: str, type: str, valeur create_zone_if_not_exist(file=file) data = read_zone(file=file) with open(file, "w+") as f: - updated_data = data | {domaine: {"type": type, - "valeur": valeur, - "ttl": TTL.ttl}} + if type == "CNAME": + valeur += "." + key = f"{domaine}./{type}/{valeur}" + updated_data = data | {key: {"type": type, + "valeur": valeur, + "ttl": TTL.ttl}} json.dump(updated_data, f) + logger.info(f"Zone content : {updated_data}") return {"status": "OK"} return {"status": "ERROR", "message": "zone not available"} @app.delete("/ws/{domaine}/{type}/{valeur}") def delete(response: Response, request: Request, domaine: str, type: str, valeur: str, TTL: TTLDelete) -> dict: + logger.info(f"DELETE on url: {request.url}") if not check_TSIG(keyname=TTL.keyname, keyvalue=TTL.keyvalue): return {"status": "ERROR", "message": "wrong credentials"} @@ -105,10 +113,13 @@ def delete(response: Response, request: Request, domaine: str, type: str, valeur file = f"/tmp/{zone}" create_zone_if_not_exist(file=file) data = read_zone(file=file) - print(domaine, data) with open(file, "w") as f: - if domaine in data: - data.pop(domaine) + if type == "CNAME": + valeur += "." + key = f"{domaine}./{type}/{valeur}" + if key in data: + data.pop(key) json.dump(data, f) + logger.info(f"Zone content : {data}") return {"status": "OK"} return {"status": "ERROR", "message": "no domain"} diff --git a/kind/resources/external-dns-values.yml b/contribute/ressources/external-dns-values.yaml similarity index 57% rename from kind/resources/external-dns-values.yml rename to contribute/ressources/external-dns-values.yaml index 2475b02..287bd60 100644 --- a/kind/resources/external-dns-values.yml +++ b/contribute/ressources/external-dns-values.yaml @@ -3,35 +3,40 @@ policy: sync # -- Specify the registry for storing ownership and labels. # Valid values are `txt`, `aws-sd`, `dynamodb` & `noop`. # If `noop` midaas manage all records on zone -registry: txt +registry: noop # can restrict zone -provider: +provider: name: webhook webhook: image: repository: external-dns-midaas-webhook tag: dev - pullPolicy: Never + pullPolicy: Always env: - - name: TSIG_ZONE_foo - value: bar + - name: GOFLAGS + value: -buildvcs=false + - name: TSIG_ZONE_${MIDAAS_ENV_KEYNAME} + value: ${MIDAAS_ENV_KEYVALUE} - name: API_LOG_LEVEL value: DEBUG - - name: PROVIDER_SKIP_TLS_VERIFY - value: "true" + - name: PROVIDER_DNS_ZONE_SUFFIX + value: ${MIDAAS_DEV_SUFFIX} + - name: PROVIDER_WS_URL + value: ${MIDAAS_WS_URL} + - name: https_proxy + value: ${https_proxy} + - name: no_proxy + value: .default,{no_proxy} extraVolumeMounts: - name: dev-workspace mountPath: /go/src/app - env: - - name: PROVIDER_DNS_ZONE_SUFFIX - value: "dev.example.com" - - name: PROVIDER_WS_URL - value: https://midaas.example.com/midaas/ws" - - name: TSIG_ZONE_foo - value: bar podSecurityContext: runAsNonRoot: false extraVolumes: - name: dev-workspace hostPath: - path: /app \ No newline at end of file + path: /app + +sources: + - ingress +logLevel: debug \ No newline at end of file diff --git a/kind/resources/ingress.yml b/contribute/ressources/ingress.yaml similarity index 80% rename from kind/resources/ingress.yml rename to contribute/ressources/ingress.yaml index 0149d34..5637007 100644 --- a/kind/resources/ingress.yml +++ b/contribute/ressources/ingress.yaml @@ -5,13 +5,13 @@ metadata: name: test spec: rules: - - host: test.foo.dev.example.com + - host: test.d1.dev.local http: paths: - path: / pathType: Prefix backend: service: - name: test + name: midaas port: number: 8080 \ No newline at end of file diff --git a/kind/README.md b/kind/README.md deleted file mode 100644 index eb48093..0000000 --- a/kind/README.md +++ /dev/null @@ -1,37 +0,0 @@ -# Run kubernetes locally with docker - -## Prerequisite - -Download & install on your local machine : -- [kind](https://github.com/kubernetes-sigs/kind) -- [kubectl](https://github.com/kubernetes/kubectl) -- [helm](https://github.com/helm/helm) - -Declare your images into the `./docker-compose.yml` file, it is used for parralel build and load images into Kind nodes. - -## Commands - -Put this directory in your git project, then start using the script : - -```sh -# Start kind cluster -sh ./run.sh -c create - -# Build and load docker-compose images into the cluster -sh ./run.sh -c build - -# Stop kind cluster -sh ./run.sh -c delete - -# Start kind cluster, build and load images and deploy app -sh ./run.sh -c dev -``` - -> [!TIP] -> See script helper by running `sh ./run.hs -h` - -## Cluster - -One single node is deployed but it can be customized in `./configs/kind-config.yml`. The cluster comes with [Traefik](https://doc.traefik.io/traefik/providers/kubernetes-ingress/) or [Nginx](https://kind.sigs.k8s.io/docs/user/ingress/#ingress-nginx) ingress controller installed with port mapping on both ports `80` and `443`. - -The node is using `extraMounts` to provide a volume binding between host working directory and `/app` to give the ability to bind mount volumes into containers during development. diff --git a/kind/docker-compose.yml b/kind/docker-compose.yml deleted file mode 100644 index 82eb3f3..0000000 --- a/kind/docker-compose.yml +++ /dev/null @@ -1,7 +0,0 @@ -services: - server: - image: external-dns-midaas-webhook:dev - build: - context: .. - dockerfile: ./Dockerfile - target: dev diff --git a/kind/run.sh b/kind/run.sh deleted file mode 100755 index 2ef7cc1..0000000 --- a/kind/run.sh +++ /dev/null @@ -1,245 +0,0 @@ -#!/bin/bash - -set -e -set -o pipefail - -# Colorize terminal -red='\e[0;31m' -no_color='\033[0m' - -# Get versions -DOCKER_VERSION="$(docker --version)" - -# Default -PROJECT_DIR="$(git rev-parse --show-toplevel)" -SCRIPT_PATH="$(cd -- "$(dirname "$0")" >/dev/null 2>&1; pwd -P)" -INGRESS_CONTROLLER="nginx" -COMPOSE_FILE="$SCRIPT_PATH/docker-compose.yml" - -# Declare script helper -TEXT_HELPER="\nThis script aims to manage a local kubernetes cluster using Kind also known as Kubernetes in Docker. -Following flags are available: - - -c Command tu run. Multiple commands can be provided as a comma separated list. - Available commands are : - create - Create kind cluster. - clean - Delete images in kind cluster (keep only infra resources and ingress controller). - delete - Delete kind cluster. - build - Build and load docker images from compose file into cluster nodes. - load - Load docker images from compose file into cluster nodes. - dev - Run application in development mode. - prod - Run application in production mode. - - -d Domains to add in /etc/hosts for local services resolution. - Comma separated list, this will require sudo. - - -f Path to the docker-compose file that will be used with Kind (default to '$COMPOSE_FILE'). - - -i Ingress controller to install (available values are 'nginx' or 'traefik', default to '$INGRESS_CONTROLLER'). - - -t Tag used to deploy application images. - If the 'CI' environment variable is set to 'true', it will use the - '$PROJECT_DIR/$HELM_DIR/values.yaml' images instead of local ones. - - -h Print script help.\n\n" - -print_help() { - printf "$TEXT_HELPER" -} - -# Parse options -while getopts hc:d:f:i:t: flag; do - case "${flag}" in - c) - COMMAND=${OPTARG};; - d) - DOMAINS=${OPTARG};; - f) - COMPOSE_FILE=${OPTARG};; - i) - INGRESS_CONTROLLER=${OPTARG};; - t) - TAG=${OPTARG};; - h | *) - print_help - exit 0;; - esac -done - - -# Functions -install_kind() { - printf "\n\n${red}[kind wrapper].${no_color} Install kind...\n\n" - if [ "$(uname)" = "Linux" ]; then - OS="linux" - elif [ "$(uname)" = "Darwin" ]; then - OS="darwin" - else - printf "\n\nNo installation available for your system, plese refer to the installation guide\n\n" - exit 0 - fi - - if [ "$(uname -m)" = "x86_64" ]; then - ARCH="amd64" - elif [ "$(uname -m)" = "arm64" ] || [ "$(uname -m)" = "aarch64" ]; then - ARCH="arm64" - fi - - KIND_VERSION="0.23.0" - curl -Lo ./kind "https://kind.sigs.k8s.io/dl/v${VERSION}/kind-${OS}-${ARCH}" - chmod +x ./kind - mv ./kind /usr/local/bin/kind - - printf "\n\n$(kind --version) installed\n\n" -} - -create () { - if [ -z "$(kind get clusters | grep 'kind')" ]; then - printf "\n\n${red}[kind wrapper].${no_color} Create Kind cluster\n\n" - kind create cluster --config $SCRIPT_PATH/configs/kind-config.yml - if [ "$INGRESS_CONTROLLER" = "nginx" ]; then - printf "\n\n${red}[kind wrapper].${no_color} Install Nginx ingress controller\n\n" - kubectl --context kind-kind apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml - sleep 20 - kubectl --context kind-kind wait --namespace ingress-nginx \ - --for=condition=ready pod \ - --selector=app.kubernetes.io/component=controller \ - --timeout=90s - elif [ "$INGRESS_CONTROLLER" = "traefik" ]; then - printf "\n\n${red}[kind wrapper].${no_color} Install traefik ingress controller\n\n" - helm --kube-context kind-kind repo add traefik https://traefik.github.io/charts && helm repo update - helm --kube-context kind-kind upgrade \ - --install \ - --wait \ - --namespace ingress-traefik \ - --create-namespace \ - --values $SCRIPTPATH/configs/traefik-values.yml \ - traefik traefik/traefik - fi - fi -} - -build () { - printf "\n\n${red}[kind wrapper].${no_color} Build images into cluster node\n\n" - cd $(dirname "$COMPOSE_FILE") && docker buildx bake --file $(basename "$COMPOSE_FILE") --load && cd - -} - -load () { - printf "\n\n${red}[kind wrapper].${no_color} Load images into cluster node\n\n" - kind load docker-image $(cat "$COMPOSE_FILE" | docker run -i --rm mikefarah/yq -o t '.services | map(select(.build) | .image)') -} - -clean () { - printf "\n\n${red}[kind wrapper].${no_color} Clean Kind cluster\n\n" - kubectl delete ingress test - helm uninstall external-dns -} - -delete () { - printf "\n\n${red}[kind wrapper].${no_color} Delete Kind cluster\n\n" - kind delete cluster -} - -deploy () { - printf "\n\n${red}[kind wrapper].${no_color} Deploy application in development mode\n\n" - helm repo add external-dns https://kubernetes-sigs.github.io/external-dns - helm upgrade --install external-dns external-dns/external-dns -f "$SCRIPT_PATH/resources/external-dns-values.yml" - kubectl apply -f "$SCRIPT_PATH/resources/ingress.yml" -} - - -# Script condition -if [ -z "$(kind --version)" ]; then - while true; do - read -p "\nYou need kind to run this script. Do you wish to install kind?\n" yn - case $yn in - [Yy]*) - install_kind;; - [Nn]*) - exit 1;; - *) - echo "\nPlease answer yes or no.\n";; - esac - done -fi - -if [[ "$COMMAND" =~ "build" ]] || [[ "$COMMAND" =~ "load" ]] && [ ! -f "$(readlink -f $COMPOSE_FILE)" ]; then - echo "\nDocker compose file $COMPOSE_FILE does not exist.\n" - print_help - exit 1 -fi - - -# Add local services to /etc/hosts -if [ ! -z "$DOMAINS" ]; then - printf "\n\n${red}[kind wrapper].${no_color} Add services local domains to /etc/hosts\n\n" - FORMATED_DOMAINS="$(echo "$DOMAINS" | sed 's/,/\ /g')" - if [ "$(grep -c "$FORMATED_DOMAINS" /etc/hosts)" -ge 1 ]; then - printf "\n\n${red}[kind wrapper].${no_color} Services local domains already added to /etc/hosts\n\n" - else - sudo sh -c "echo $'\n\n# Kind\n127.0.0.1 $FORMATED_DOMAINS' >> /etc/hosts" - printf "\n\n${red}[kind wrapper].${no_color} Services local domains successfully added to /etc/hosts\n\n" - fi -fi - - -# Deploy cluster with trefik ingress controller -if [[ "$COMMAND" =~ "create" ]]; then - create & - JOB_ID_CREATE="$!" -fi - - -# Build and load images into cluster nodes -if [[ "$COMMAND" =~ "build" ]]; then - build & - JOB_ID_BUILD="$!" - [ ! -z $JOB_ID_CREATE ] && wait $JOB_ID_CREATE - wait $JOB_ID_BUILD - load & - JOB_ID_LOAD="$!" -fi - - -# Load images into cluster nodes -if [[ "$COMMAND" =~ "load" ]]; then - [ ! -z $JOB_ID_CREATE ] && wait $JOB_ID_CREATE - load & - JOB_ID_LOAD="$!" -fi - - -# Clean cluster application resources -if [ "$COMMAND" = "clean" ]; then - clean -fi - - -# Delete cluster -if [ "$COMMAND" = "delete" ]; then - delete -fi - - -# Deploy application in dev or test mode -if [[ "$COMMAND" =~ "deploy" ]]; then - [ ! -z $JOB_ID_CREATE ] && wait $JOB_ID_CREATE - [ ! -z $JOB_ID_BUILD ] && wait $JOB_ID_BUILD - [ ! -z $JOB_ID_LOAD ] && wait $JOB_ID_LOAD - deploy -fi - - -# Deploy application in dev or test mode -if [[ "$COMMAND" =~ "dev" ]]; then - create & - JOB_ID_CREATE="$!" - build & - JOB_ID_BUILD="$!" - wait $JOB_ID_CREATE - wait $JOB_ID_BUILD - load & - JOB_ID_LOAD="$!" - wait $JOB_ID_LOAD - deploy -fi