NAME ?= $(shell basename "`pwd`") ifneq ($(origin TARGET_SITE), undefined) TARGET_SITE_OPT=--set main.clusterGroupName=$(TARGET_SITE) endif # This variable can be set in order to pass additional helm arguments from the # the command line. I.e. we can set things without having to tweak values files EXTRA_HELM_OPTS ?= # This variable can be set in order to pass additional ansible-playbook arguments from the # the command line. I.e. we can set -vvv for more verbose logging EXTRA_PLAYBOOK_OPTS ?= # INDEX_IMAGES=registry-proxy.engineering.redhat.com/rh-osbs/iib:394248 # or # INDEX_IMAGES=registry-proxy.engineering.redhat.com/rh-osbs/iib:394248,registry-proxy.engineering.redhat.com/rh-osbs/iib:394249 INDEX_IMAGES ?= TARGET_ORIGIN ?= origin # This is to ensure that whether we start with a git@ or https:// URL, we end up with an https:// URL # This is because we expect to use tokens for repo authentication as opposed to SSH keys TARGET_REPO=$(shell git ls-remote --get-url --symref $(TARGET_ORIGIN) | sed -e 's/.*URL:[[:space:]]*//' -e 's%^git@%%' -e 's%^https://%%' -e 's%:%/%' -e 's%^%https://%') # git branch --show-current is also available as of git 2.22, but we will use this for compatibility TARGET_BRANCH ?= $(shell git rev-parse --abbrev-ref HEAD) UUID_FILE ?= ~/.config/validated-patterns/pattern-uuid UUID_HELM_OPTS ?= # --set values always take precedence over the contents of -f ifneq ("$(wildcard $(UUID_FILE))","") UUID := $(shell cat $(UUID_FILE)) UUID_HELM_OPTS := --set main.analyticsUUID=$(UUID) endif # Set the secret name *and* its namespace when deploying from private repositories # The format of said secret is documented here: https://argo-cd.readthedocs.io/en/stable/operator-manual/declarative-setup/#repositories TOKEN_SECRET ?= TOKEN_NAMESPACE ?= ifeq ($(TOKEN_SECRET),) HELM_OPTS=-f values-global.yaml --set main.git.repoURL="$(TARGET_REPO)" --set main.git.revision=$(TARGET_BRANCH) $(TARGET_SITE_OPT) $(UUID_HELM_OPTS) $(EXTRA_HELM_OPTS) else # When we are working with a private repository we do not escape the git URL as it might be using an ssh secret which does not use https:// TARGET_CLEAN_REPO=$(shell git ls-remote --get-url --symref $(TARGET_ORIGIN)) HELM_OPTS=-f values-global.yaml --set main.tokenSecret=$(TOKEN_SECRET) --set main.tokenSecretNamespace=$(TOKEN_NAMESPACE) --set main.git.repoURL="$(TARGET_CLEAN_REPO)" --set main.git.revision=$(TARGET_BRANCH) $(TARGET_SITE_OPT) $(UUID_HELM_OPTS) $(EXTRA_HELM_OPTS) endif # Helm does the right thing and fetches all the tags and detects the newest one PATTERN_INSTALL_CHART ?= oci://quay.io/hybridcloudpatterns/pattern-install ##@ Pattern Common Tasks .PHONY: help help: ## This help message @echo "Pattern: $(NAME)" @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^(\s|[a-zA-Z_0-9-])+:.*?##/ { printf " \033[36m%-35s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) # Makefiles in the individual patterns should call these targets explicitly # e.g. from industrial-edge: make -f common/Makefile show .PHONY: show show: ## show the starting template without installing it helm template $(PATTERN_INSTALL_CHART) --name-template $(NAME) $(HELM_OPTS) preview-all: ## (EXPERIMENTAL) Previews all applications on hub and managed clusters @echo "NOTE: This is just a tentative approximation of rendering all hub and managed clusters templates" @common/scripts/preview-all.sh $(TARGET_REPO) $(TARGET_BRANCH) preview-%: $(eval CLUSTERGROUP ?= $(shell yq ".main.clusterGroupName" values-global.yaml)) @common/scripts/preview.sh $(CLUSTERGROUP) $* $(TARGET_REPO) $(TARGET_BRANCH) .PHONY: operator-deploy operator-deploy operator-upgrade: validate-prereq validate-origin validate-cluster ## runs helm install @common/scripts/deploy-pattern.sh $(NAME) $(PATTERN_INSTALL_CHART) $(HELM_OPTS) .PHONY: uninstall uninstall: ## runs helm uninstall $(eval CSV := $(shell oc get subscriptions -n openshift-operators openshift-gitops-operator -ojsonpath={.status.currentCSV})) helm uninstall $(NAME) @oc delete csv -n openshift-operators $(CSV) .PHONY: load-secrets load-secrets: ## loads the secrets into the backend determined by values-global setting common/scripts/process-secrets.sh $(NAME) .PHONY: legacy-load-secrets legacy-load-secrets: ## loads the secrets into vault (only) common/scripts/vault-utils.sh push_secrets $(NAME) .PHONY: secrets-backend-vault secrets-backend-vault: ## Edits values files to use default Vault+ESO secrets config common/scripts/set-secret-backend.sh vault common/scripts/manage-secret-app.sh vault present common/scripts/manage-secret-app.sh golang-external-secrets present common/scripts/manage-secret-namespace.sh validated-patterns-secrets absent @git diff --exit-code || echo "Secrets backend set to vault, please review changes, commit, and push to activate in the pattern" .PHONY: secrets-backend-kubernetes secrets-backend-kubernetes: ## Edits values file to use Kubernetes+ESO secrets config common/scripts/set-secret-backend.sh kubernetes common/scripts/manage-secret-namespace.sh validated-patterns-secrets present common/scripts/manage-secret-app.sh vault absent common/scripts/manage-secret-app.sh golang-external-secrets present @git diff --exit-code || echo "Secrets backend set to kubernetes, please review changes, commit, and push to activate in the pattern" .PHONY: secrets-backend-none secrets-backend-none: ## Edits values files to remove secrets manager + ESO common/scripts/set-secret-backend.sh none common/scripts/manage-secret-app.sh vault absent common/scripts/manage-secret-app.sh golang-external-secrets absent common/scripts/manage-secret-namespace.sh validated-patterns-secrets absent @git diff --exit-code || echo "Secrets backend set to none, please review changes, commit, and push to activate in the pattern" .PHONY: load-iib load-iib: ## CI target to install Index Image Bundles @set -e; if [ x$(INDEX_IMAGES) != x ]; then \ ansible-playbook $(EXTRA_PLAYBOOK_OPTS) rhvp.cluster_utils.iib_ci; \ else \ echo "No INDEX_IMAGES defined. Bailing out"; \ exit 1; \ fi .PHONY: token-kubeconfig token-kubeconfig: ## Create a local ~/.kube/config with password (not usually needed) common/scripts/write-token-kubeconfig.sh ##@ Validation Tasks # We only check the remote ssh git branch's existance if we're not running inside a container # as getting ssh auth working inside a container seems a bit brittle # If the main repoUpstreamURL field is set, then we need to check against # that and not target_repo .PHONY: validate-origin validate-origin: ## verify the git origin is available @echo "Checking repository:" $(eval UPSTREAMURL := $(shell yq -r '.main.git.repoUpstreamURL // (.main.git.repoUpstreamURL = "")' values-global.yaml)) @if [ -z "$(UPSTREAMURL)" ]; then\ echo -n " $(TARGET_REPO) - branch '$(TARGET_BRANCH)': ";\ git ls-remote --exit-code --heads $(TARGET_REPO) $(TARGET_BRANCH) >/dev/null &&\ echo "OK" || (echo "NOT FOUND"; exit 1);\ else\ echo "Upstream URL set to: $(UPSTREAMURL)";\ echo -n " $(UPSTREAMURL) - branch '$(TARGET_BRANCH)': ";\ git ls-remote --exit-code --heads $(UPSTREAMURL) $(TARGET_BRANCH) >/dev/null &&\ echo "OK" || (echo "NOT FOUND"; exit 1);\ fi .PHONY: validate-cluster validate-cluster: ## Do some cluster validations before installing @echo "Checking cluster:" @echo -n " cluster-info: " @oc cluster-info >/dev/null && echo "OK" || (echo "Error"; exit 1) @echo -n " storageclass: " @if [ `oc get storageclass -o go-template='{{printf "%d\n" (len .items)}}'` -eq 0 ]; then\ echo "WARNING: No storageclass found";\ else\ echo "OK";\ fi .PHONY: validate-schema validate-schema: ## validates values files against schema in common/clustergroup $(eval VAL_PARAMS := $(shell for i in ./values-*.yaml; do echo -n "$${i} "; done)) @echo -n "Validating clustergroup schema of: " @set -e; for i in $(VAL_PARAMS); do echo -n " $$i"; helm template oci://quay.io/hybridcloudpatterns/clustergroup $(HELM_OPTS) -f "$${i}" >/dev/null; done @echo .PHONY: validate-prereq validate-prereq: ## verify pre-requisites $(eval GLOBAL_PATTERN := $(shell yq -r .global.pattern values-global.yaml)) @if [ $(NAME) != $(GLOBAL_PATTERN) ]; then\ echo "";\ echo "WARNING: folder directory is \"$(NAME)\" and global.pattern is set to \"$(GLOBAL_PATTERN)\"";\ echo "this can create problems. Please make sure they are the same!";\ echo "";\ fi @if [ ! -f /run/.containerenv ]; then\ echo "Checking prerequisites:";\ echo -n " Check for python-kubernetes: ";\ if ! ansible -m ansible.builtin.command -a "{{ ansible_python_interpreter }} -c 'import kubernetes'" localhost > /dev/null 2>&1; then echo "Not found"; exit 1; fi;\ echo "OK";\ echo -n " Check for kubernetes.core collection: ";\ if ! ansible-galaxy collection list | grep kubernetes.core > /dev/null 2>&1; then echo "Not found"; exit 1; fi;\ echo "OK";\ else\ if [ -f values-global.yaml ]; then\ OUT=`yq -r '.main.multiSourceConfig.enabled // (.main.multiSourceConfig.enabled = "false")' values-global.yaml`;\ if [ "$${OUT,,}" = "false" ]; then\ echo "You must set \".main.multiSourceConfig.enabled: true\" in your 'values-global.yaml' file";\ echo "because your common subfolder is the slimmed down version with no helm charts in it";\ exit 1;\ fi;\ fi;\ fi .PHONY: argo-healthcheck argo-healthcheck: ## Checks if all argo applications are synced @echo "Checking argo applications" $(eval APPS := $(shell oc get applications.argoproj.io -A -o jsonpath='{range .items[*]}{@.metadata.namespace}{","}{@.metadata.name}{"\n"}{end}')) @NOTOK=0; \ for i in $(APPS); do\ n=`echo "$${i}" | cut -f1 -d,`;\ a=`echo "$${i}" | cut -f2 -d,`;\ STATUS=`oc get -n "$${n}" applications.argoproj.io/"$${a}" -o jsonpath='{.status.sync.status}'`;\ if [[ $$STATUS != "Synced" ]]; then\ NOTOK=$$(( $${NOTOK} + 1));\ fi;\ HEALTH=`oc get -n "$${n}" applications.argoproj.io/"$${a}" -o jsonpath='{.status.health.status}'`;\ if [[ $$HEALTH != "Healthy" ]]; then\ NOTOK=$$(( $${NOTOK} + 1));\ fi;\ echo "$${n} $${a} -> Sync: $${STATUS} - Health: $${HEALTH}";\ done;\ if [ $${NOTOK} -gt 0 ]; then\ echo "Some applications are not synced or are unhealthy";\ exit 1;\ fi ##@ Test and Linters Tasks .PHONY: qe-tests qe-tests: ## Runs the tests that QE runs @set -e; if [ -f ./tests/interop/run_tests.sh ]; then \ pushd ./tests/interop; ./run_tests.sh; popd; \ else \ echo "No ./tests/interop/run_tests.sh found skipping"; \ fi .PHONY: super-linter super-linter: ## Runs super linter locally rm -rf .mypy_cache podman run -e RUN_LOCAL=true -e USE_FIND_ALGORITHM=true \ -e VALIDATE_ANSIBLE=false \ -e VALIDATE_BASH=false \ -e VALIDATE_CHECKOV=false \ -e VALIDATE_DOCKERFILE_HADOLINT=false \ -e VALIDATE_JSCPD=false \ -e VALIDATE_JSON_PRETTIER=false \ -e VALIDATE_MARKDOWN_PRETTIER=false \ -e VALIDATE_KUBERNETES_KUBECONFORM=false \ -e VALIDATE_PYTHON_PYLINT=false \ -e VALIDATE_SHELL_SHFMT=false \ -e VALIDATE_TEKTON=false \ -e VALIDATE_YAML=false \ -e VALIDATE_YAML_PRETTIER=false \ $(DISABLE_LINTERS) \ -v $(PWD):/tmp/lint:rw,z \ -w /tmp/lint \ ghcr.io/super-linter/super-linter:slim-v7 .PHONY: deploy upgrade legacy-deploy legacy-upgrade deploy upgrade legacy-deploy legacy-upgrade: @echo "UNSUPPORTED TARGET: please switch to 'operator-deploy'"; exit 1