This repository has been archived by the owner on May 30, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 59
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #102 from turkenh/local-dev-tooling
Add Local Development Targets
- Loading branch information
Showing
10 changed files
with
530 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
SELF_DIR := $(dir $(lastword $(MAKEFILE_LIST))) | ||
SCRIPTS_DIR := $(SELF_DIR)/../scripts | ||
|
||
KIND_CLUSTER_NAME ?= local-dev | ||
|
||
DEPLOY_LOCAL_DIR ?= $(ROOT_DIR)/cluster/local | ||
DEPLOY_LOCAL_WORKDIR := $(WORK_DIR)/local/localdev | ||
DEPLOY_LOCAL_CONFIG_DIR := $(DEPLOY_LOCAL_WORKDIR)/config | ||
DEPLOY_LOCAL_KUBECONFIG := $(DEPLOY_LOCAL_WORKDIR)/kubeconfig | ||
KIND_CONFIG_FILE := $(DEPLOY_LOCAL_WORKDIR)/kind.yaml | ||
KUBECONFIG ?= $(HOME)/.kube/config | ||
|
||
LOCAL_BUILD ?= true | ||
|
||
export KIND | ||
export KUBECTL | ||
export HELM | ||
export GOMPLATE | ||
export BUILD_REGISTRY | ||
export ROOT_DIR | ||
export SCRIPTS_DIR | ||
export KIND_CLUSTER_NAME | ||
export WORK_DIR | ||
export LOCALDEV_INTEGRATION_CONFIG_REPO | ||
export DEPLOY_LOCAL_DIR | ||
export DEPLOY_LOCAL_WORKDIR | ||
export DEPLOY_LOCAL_CONFIG_DIR | ||
export DEPLOY_LOCAL_KUBECONFIG | ||
export KIND_CONFIG_FILE | ||
export KUBECONFIG | ||
export LOCAL_BUILD | ||
export HELM_OUTPUT_DIR | ||
export BUILD_HELM_CHART_VERSION=$(HELM_CHART_VERSION) | ||
export BUILD_HELM_CHARTS_LIST=$(HELM_CHARTS) | ||
export BUILD_REGISTRIES=$(REGISTRIES) | ||
export BUILD_IMAGES=$(IMAGES) | ||
export BUILD_IMAGE_ARCHS=$(subst linux_,,$(filter linux_%,$(BUILD_PLATFORMS))) | ||
|
||
# Install gomplate | ||
GOMPLATE_VERSION := 3.7.0 | ||
GOMPLATE := $(TOOLS_HOST_DIR)/gomplate-$(GOMPLATE_VERSION) | ||
|
||
gomplate.buildvars: | ||
@echo GOMPLATE=$(GOMPLATE) | ||
|
||
build.vars: gomplate.buildvars | ||
|
||
$(GOMPLATE): | ||
@$(INFO) installing gomplate $(HOSTOS)-$(HOSTARCH) | ||
@curl -fsSLo $(GOMPLATE) https://github.com/hairyhenderson/gomplate/releases/download/v$(GOMPLATE_VERSION)/gomplate_$(HOSTOS)-$(HOSTARCH) || $(FAIL) | ||
@chmod +x $(GOMPLATE) | ||
@$(OK) installing gomplate $(HOSTOS)-$(HOSTARCH) | ||
|
||
kind.up: $(KIND) | ||
@$(INFO) kind up | ||
@$(KIND) get kubeconfig --name $(KIND_CLUSTER_NAME) >/dev/null 2>&1 || $(KIND) create cluster --name=$(KIND_CLUSTER_NAME) --config="$(KIND_CONFIG_FILE)" --kubeconfig="$(KUBECONFIG)" | ||
@$(KIND) get kubeconfig --name $(KIND_CLUSTER_NAME) > $(DEPLOY_LOCAL_KUBECONFIG) | ||
@$(OK) kind up | ||
|
||
kind.down: $(KIND) | ||
@$(INFO) kind down | ||
@$(KIND) delete cluster --name=$(KIND_CLUSTER_NAME) | ||
@$(OK) kind down | ||
|
||
kind.setcontext: $(KUBECTL) | ||
@$(KUBECTL) --kubeconfig $(KUBECONFIG) config use-context kind-$(KIND_CLUSTER_NAME) | ||
|
||
kind.buildvars: | ||
@echo DEPLOY_LOCAL_KUBECONFIG=$(DEPLOY_LOCAL_KUBECONFIG) | ||
|
||
build.vars: kind.buildvars | ||
clean: local.down | ||
|
||
.PHONY: kind.up kind.down kind.setcontext kind.buildvars | ||
|
||
local.helminit: $(KUBECTL) $(HELM) kind.setcontext | ||
@$(INFO) helm init | ||
@docker pull gcr.io/kubernetes-helm/tiller:$(HELM_VERSION) | ||
@$(KIND) load docker-image gcr.io/kubernetes-helm/tiller:$(HELM_VERSION) --name=$(KIND_CLUSTER_NAME) | ||
@$(KUBECTL) --kubeconfig $(KUBECONFIG) --namespace kube-system get serviceaccount tiller > /dev/null 2>&1 || $(KUBECTL) --kubeconfig $(KUBECONFIG) --namespace kube-system create serviceaccount tiller | ||
@$(KUBECTL) --kubeconfig $(KUBECONFIG) get clusterrolebinding tiller-cluster-rule > /dev/null 2>&1 || $(KUBECTL) --kubeconfig $(KUBECONFIG) create clusterrolebinding tiller-cluster-rule --clusterrole=cluster-admin --serviceaccount=kube-system:tiller | ||
@$(HELM) ls > /dev/null 2>&1 || $(HELM) init --kubeconfig $(KUBECONFIG) --service-account tiller --upgrade --wait | ||
@$(HELM) repo update | ||
@$(OK) helm init | ||
|
||
local.prepare: | ||
@$(INFO) preparing local dev workdir | ||
@$(SCRIPTS_DIR)/localdev-prepare.sh || $(FAIL) | ||
@$(OK) preparing local dev workdir | ||
|
||
local.clean: | ||
@$(INFO) cleaning local dev workdir | ||
@rm -rf $(WORK_DIR)/local || $(FAIL) | ||
@$(OK) cleaning local dev workdir | ||
|
||
local.up: local.prepare kind.up local.helminit | ||
|
||
local.down: local.clean kind.down | ||
|
||
local.deploy.%: $(KUBECTL) $(HELM) $(HELM_HOME) $(GOMPLATE) kind.setcontext | ||
@$(INFO) localdev deploy component: $* | ||
@$(eval PLATFORMS=$(BUILD_PLATFORMS)) | ||
@$(SCRIPTS_DIR)/localdev-deploy-component.sh $* || $(FAIL) | ||
@$(OK) localdev deploy component: $* | ||
|
||
local.remove.%: $(KUBECTL) $(HELM) $(HELM_HOME) $(GOMPLATE) kind.setcontext | ||
@$(INFO) localdev remove component: $* | ||
@$(SCRIPTS_DIR)/localdev-remove-component.sh $* || $(FAIL) | ||
@$(OK) localdev remove component: $* | ||
|
||
local.scaffold: | ||
@$(INFO) localdev scaffold config | ||
@$(SCRIPTS_DIR)/localdev-scaffold.sh || $(FAIL) | ||
@$(OK) localdev scaffold config | ||
|
||
.PHONY: local.helminit local.up local.deploy.% local.remove.% local.scaffold | ||
|
||
# ==================================================================================== | ||
# Special Targets | ||
|
||
fmt: go.imports | ||
fmt.simplify: go.fmt.simplify | ||
imports: go.imports | ||
imports.fix: go.imports.fix | ||
vendor: go.vendor | ||
vendor.check: go.vendor.check | ||
vendor.update: go.vendor.update | ||
vet: go.vet | ||
generate codegen: go.generate | ||
|
||
define LOCAL_HELPTEXT | ||
Local Targets: | ||
local.scaffold scaffold a local development configuration | ||
local.up stand up of a local development cluster with kind | ||
local.down tear down local development cluster | ||
local.deploy.% install/upgrade a local/external component, for example, local.deploy.crossplane | ||
local.remove.% removes component, for example, local.remove.crossplane | ||
|
||
endef | ||
export LOCAL_HELPTEXT | ||
|
||
local.help: | ||
@echo "$$LOCAL_HELPTEXT" | ||
|
||
help-special: local.help | ||
|
||
### |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
COMPONENT=$1 | ||
|
||
# REQUIRED_IMAGES is the array of images that the COMPONENT needs. | ||
# These images will be pulled (if not exists) and loaded into the kind cluster before deployment. | ||
# If an image has tags, it will be used. | ||
# If an image does not have a tag, "v${HELM_CHART_VERSION}" will be used as a tag. | ||
REQUIRED_IMAGES=() | ||
|
||
# HELM_CHART_NAME is the name of the helm chart to deploy. If not set, defaults to COMPONENT | ||
HELM_CHART_NAME="" | ||
# HELM_CHART_VERSION is the version of the helm chart to deploy. | ||
# If LOCAL_BUILD=true, HELM_CHART_VERSION will be set the version in build system. | ||
# If LOCAL_BUILD=false, HELM_CHART_VERSION defaults to latest version in the HELM_REPOSITORY | ||
HELM_CHART_VERSION="" | ||
# HELM_REPOSITORY_NAME is the name of the helm repository. | ||
# This will only be used if LOCAL_BUILD=false or HELM_CHART_NAME is not a local chart (e.g. not in HELM_CHARTS array) | ||
HELM_REPOSITORY_NAME="" | ||
# HELM_REPOSITORY_NAME is the url of the helm repository. | ||
HELM_REPOSITORY_URL="" | ||
# HELM_REPOSITORY_FORCE_UPDATE controls whether always update helm repositories or not. | ||
# If false, "helm repo update" will only be called if repo does not exist already. | ||
HELM_REPOSITORY_FORCE_UPDATE="false" | ||
# HELM_RELEASE_NAME is the name of the helm release. If not set, defaults to COMPONENT | ||
HELM_RELEASE_NAME="" | ||
# HELM_RELEASE_NAMESPACE is the namespace for the helm release. | ||
HELM_RELEASE_NAMESPACE="default" | ||
# HELM_DELETE_ON_FAILURE controls whether to delete/rollback a failed install/upgrade. | ||
HELM_DELETE_ON_FAILURE="true" | ||
|
||
# COMPONENT_SKIP_DEPLOY controls whether (conditionally) skip deployment of a component or not. | ||
COMPONENT_SKIP_DEPLOY="false" | ||
|
||
MAIN_CONFIG_FILE="${DEPLOY_LOCAL_CONFIG_DIR}/config.env" | ||
COMPONENT_CONFIG_DIR="${DEPLOY_LOCAL_CONFIG_DIR}/${COMPONENT}" | ||
COMPONENT_CONFIG_FILE="${COMPONENT_CONFIG_DIR}/config.env" | ||
|
||
if [[ ! -d "${COMPONENT_CONFIG_DIR}" ]]; then | ||
echo_error "Component config dir \"${COMPONENT_CONFIG_DIR}\" does not exist (or is not a directory), did you run make local.prepare ?" | ||
fi | ||
|
||
if [[ -f "${MAIN_CONFIG_FILE}" ]]; then | ||
source "${MAIN_CONFIG_FILE}" | ||
fi | ||
if [[ -f "${COMPONENT_CONFIG_FILE}" ]]; then | ||
source "${COMPONENT_CONFIG_FILE}" | ||
fi |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
#!/usr/bin/env bash | ||
set -aeuo pipefail | ||
|
||
COMPONENT=$1 | ||
|
||
# Source utility functions | ||
source "${SCRIPTS_DIR}/utils.sh" | ||
# sourcing load-configs.sh: | ||
# - initializes configuration variables with default values | ||
# - loads top level configuration | ||
# - loads component level configuration | ||
source "${SCRIPTS_DIR}/load-configs.sh" "${COMPONENT}" | ||
|
||
# Skip deployment of this component if COMPONENT_SKIP_DEPLOY is set to true | ||
if [ "${COMPONENT_SKIP_DEPLOY}" == "true" ]; then | ||
echo "COMPONENT_SKIP_DEPLOY set to true, skipping deployment of ${COMPONENT}" | ||
exit 0 | ||
fi | ||
|
||
# if HELM_CHART_NAME is not set, default to component name | ||
if [ -z "${HELM_CHART_NAME}" ]; then | ||
HELM_CHART_NAME="${COMPONENT}" | ||
fi | ||
|
||
registries_arr=($BUILD_REGISTRIES) | ||
images_arr=($BUILD_IMAGES) | ||
image_archs_arr=($BUILD_IMAGE_ARCHS) | ||
charts_arr=($BUILD_HELM_CHARTS_LIST) | ||
|
||
if [ "${LOCAL_BUILD}" == "true" ] && containsElement "${HELM_CHART_NAME}" "${charts_arr[@]}"; then | ||
# If local build is set and helm chart is from this repository, use locally build helm chart tgz file. | ||
echo "Deploying locally built artifacts..." | ||
HELM_CHART_VERSION=${BUILD_HELM_CHART_VERSION} | ||
HELM_CHART_REF="${HELM_OUTPUT_DIR}/${COMPONENT}-${HELM_CHART_VERSION}.tgz" | ||
[ -f "${HELM_CHART_REF}" ] || echo_error "Local chart ${HELM_CHART_REF} not found. Did you run \"make build\" ? " | ||
|
||
# If local build, tag "required" local images, so that they can be load into kind cluster at a later step. | ||
for r in "${registries_arr[@]}"; do | ||
for i in "${images_arr[@]}"; do | ||
for a in "${image_archs_arr[@]}"; do | ||
if containsElement "${r}/${i}" "${REQUIRED_IMAGES[@]}"; then | ||
echo "Tagging locally built image as ${r}/${i}:${VERSION}" | ||
docker tag "${BUILD_REGISTRY}/${i}-${a}" "${r}/${i}:${VERSION}" | ||
fi | ||
done | ||
done | ||
done | ||
else | ||
# If local build is NOT set or helm chart is NOT from this repository, deploy chart from a remote repository. | ||
echo "Deploying latest artifacts in chart repo \"${HELM_REPOSITORY_NAME}\"..." | ||
if [ -z ${HELM_REPOSITORY_NAME} ] || [ -z ${HELM_CHART_NAME} ]; then | ||
echo_error "HELM_REPOSITORY_NAME and/or HELM_CHART_NAME is not set for component ${COMPONENT}!" | ||
fi | ||
HELM_CHART_REF="${HELM_REPOSITORY_NAME}/${HELM_CHART_NAME}" | ||
# Add helm repo and update repositories, if repo is not added already or force update is set. | ||
if [ "${HELM_REPOSITORY_FORCE_UPDATE}" == "true" ] || ! "${HELM}" repo list -o yaml |grep "Name:\s*${HELM_REPOSITORY_NAME}\s*$" >/dev/null; then | ||
"${HELM}" repo add "${HELM_REPOSITORY_NAME}" "${HELM_REPOSITORY_URL}" | ||
"${HELM}" repo update | ||
fi | ||
if [ -z "${HELM_CHART_VERSION}" ]; then | ||
# if no HELM_CHART_VERSION provided, then get the latest version from repo which will be used to load required images for chart. | ||
HELM_CHART_VERSION=$("${HELM}" search -l ${HELM_CHART_REF} --devel |awk 'NR==2{print $2}') | ||
echo "Latest version found in repo: ${HELM_CHART_VERSION}" | ||
fi | ||
if [ -z "${HELM_CHART_VERSION}" ]; then | ||
echo_error "No version found in repo for chart ${HELM_CHART_REF}" | ||
fi | ||
fi | ||
|
||
# shellcheck disable=SC2068 | ||
for i in ${REQUIRED_IMAGES[@]+"${REQUIRED_IMAGES[@]}"}; do | ||
# check if image has a tag, if not, append tag for the chart | ||
if ! echo "${i}" | grep ":"; then | ||
i="${i}:v${HELM_CHART_VERSION}" | ||
fi | ||
# Pull the image: | ||
# - if has a tag "master" or "latest" | ||
# - or does not exist already. | ||
if echo "${i}" | grep ":master\s*$" >/dev/null || echo "${i}" | grep ":latest\s*$" >/dev/null || ! docker inspect --type=image "${i}" >/dev/null 2>&1; then | ||
docker pull "${i}" | ||
fi | ||
"${KIND}" load docker-image "${i}" --name="${KIND_CLUSTER_NAME}" | ||
done | ||
|
||
|
||
PREDEPLOY_SCRIPT="${DEPLOY_LOCAL_CONFIG_DIR}/${COMPONENT}/pre-deploy.sh" | ||
POSTDEPLOY_SCRIPT="${DEPLOY_LOCAL_CONFIG_DIR}/${COMPONENT}/post-deploy.sh" | ||
|
||
# Run config.validate.sh if exists. | ||
test -f "${DEPLOY_LOCAL_CONFIG_DIR}/config.validate.sh" && source "${DEPLOY_LOCAL_CONFIG_DIR}/config.validate.sh" | ||
|
||
# Create the HELM_RELEASE_NAMESPACE if not exist already. | ||
"${KUBECTL}" --kubeconfig "${KUBECONFIG}" get ns "${HELM_RELEASE_NAMESPACE}" >/dev/null 2>&1 || ${KUBECTL} \ | ||
--kubeconfig "${KUBECONFIG}" create ns "${HELM_RELEASE_NAMESPACE}" | ||
|
||
# Run pre-deploy script, if exists. | ||
if [ -f "${PREDEPLOY_SCRIPT}" ]; then | ||
source "${PREDEPLOY_SCRIPT}" | ||
fi | ||
|
||
# With all configuration sourced as environment variables, render value-overrides.yaml file with gomplate. | ||
"${GOMPLATE}" -f "${DEPLOY_LOCAL_CONFIG_DIR}/${COMPONENT}/value-overrides.yaml.tmpl" \ | ||
-o "${DEPLOY_LOCAL_CONFIG_DIR}/${COMPONENT}/value-overrides.yaml" | ||
|
||
helm_chart_version_flag="--devel" | ||
if [ -n "${HELM_CHART_VERSION}" ]; then | ||
helm_chart_version_flag="--version ${HELM_CHART_VERSION}" | ||
fi | ||
|
||
helm_wait_atomic_flag="--wait" | ||
if [ "${HELM_DELETE_ON_FAILURE}" == "true" ]; then | ||
helm_wait_atomic_flag="--atomic" | ||
fi | ||
|
||
# if HELM_RELEASE_NAME is not set, default to component name | ||
if [ -z "${HELM_RELEASE_NAME}" ]; then | ||
HELM_RELEASE_NAME=${COMPONENT} | ||
fi | ||
|
||
# Run helm upgrade --install with computed parameters. | ||
# shellcheck disable=SC2086 | ||
set -x | ||
"${HELM}" upgrade --install "${HELM_RELEASE_NAME}" --namespace "${HELM_RELEASE_NAMESPACE}" --kubeconfig "${KUBECONFIG}" \ | ||
"${HELM_CHART_REF}" ${helm_chart_version_flag:-} -f "${DEPLOY_LOCAL_CONFIG_DIR}/${COMPONENT}/value-overrides.yaml" \ | ||
${helm_wait_atomic_flag:-} --force | ||
{ set +x; } 2>/dev/null | ||
|
||
# Run post-deploy script, if exists. | ||
if [ -f "${POSTDEPLOY_SCRIPT}" ]; then | ||
source "${POSTDEPLOY_SCRIPT}" | ||
fi |
Oops, something went wrong.