Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Metrics deployment #391

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/lint-jobs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ jobs:
- uses: actions/checkout@v4
- name: Run ShellCheck
uses: ludeeus/action-shellcheck@master
env:
SHELLCHECK_OPTS: "-e SC1091" # ignores using .env for source as issue

markdown-lint:
runs-on: ubuntu-latest
steps:
Expand Down
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,7 @@ pathservice.pid
/playwright-report/
/blob-report/
/playwright/.cache/

playwright/.auth
# dont track secrets in git
deploy/k8s/overlays/kind/umami/umami-secret.yaml
deploy/k8s/overlays/openshift/umami/umami-secret.yaml
146 changes: 122 additions & 24 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,17 @@ else
PIPE_DEV_NULL=
endif

#add an alias between kubectl and oc
OC := $(shell command -v oc 2>/dev/null || echo kubectl)
ILAB_KUBE_CONTEXT?=kind-instructlab-ui
ILAB_KUBE_NAMESPACE?=instructlab
ILAB_KUBE_CLUSTER_NAME?=instructlab-ui
CONTAINER_ENGINE?=docker
DEVCONTAINER_BINARY_EXISTS ?= $(shell command -v devcontainer)
TAG=$(shell git rev-parse HEAD)
UMAMI_KUBE_NAMESPACE?=umami
SEALED_SECRETS_CONTROLLER_NAMESPACE=kube-system
SEALED_SECRETS_CONTROLLER_NAME=sealed-secrets-controller
##@ Development - Helper commands for development
.PHONY: md-lint
md-lint: ## Lint markdown files
Expand Down Expand Up @@ -89,7 +94,6 @@ start-dev-podman: ## Start UI development stack in podman
echo "Please create a .env file in the root of the project." ; \
exit 1 ; \
fi

$(CMD_PREFIX) yes | cp -rf .env ./deploy/compose/.env
$(CMD_PREFIX) podman-compose -f ./deploy/compose/ui-compose.yml up -d
$(CMD_PREFIX) echo "Development environment started."
Expand All @@ -111,9 +115,37 @@ check-kubectl:
exit 1 ; \
fi

.PHONY: check-kubeseal
check-kubeseal:
$(CMD_PREFIX) if [ -z "$(shell which kubeseal)" ]; then \
echo "Please install kubeseal" ; \
echo "https://github.com/bitnami-labs/sealed-secrets?tab=readme-ov-file#kubeseal" ; \
exit 1 ; \
fi

.PHONY: check-sealed-secrets-controller
check-sealed-secrets-controller:
$(CMD_PREFIX) kubectl get deployment ${SEALED_SECRETS_CONTROLLER_NAME} -n ${SEALED_SECRETS_CONTROLLER_NAMESPACE} > /dev/null 2>&1 || { \
echo "Error: Could not find the Sealed Secrets controller deployment named '${SEALED_SECRETS_CONTROLLER_NAME}' in namespace '${SEALED_SECRETS_CONTROLLER_NAMESPACE}'."; \
echo "Please update SEALED_SECRETS_CONTROLLER_NAME and SEALED_SECRETS_CONTROLLER_NAMESPACE at the top of the Makefile"; \
Gregory-Pereira marked this conversation as resolved.
Show resolved Hide resolved
echo "to match your deployment, or see https://github.com/bitnami-labs/sealed-secrets#controller for information on installing it."; \
exit 1; \
}

.PHONY: check-yq
check-yq:
$(CMD_PREFIX) if ! command -v yq >/dev/null 2>&1; then \
echo "Error: 'yq' is not installed."; \
echo "Please visit https://github.com/mikefarah/yq#install for installation instructions."; \
exit 1; \
fi

.PHONY: load-images
load-images: ## Load images onto Kind cluster
$(CMD_PREFIX) docker pull ghcr.io/instructlab/ui/ui:main
$(CMD_PREFIX) kind load --name $(ILAB_KUBE_CLUSTER_NAME) docker-image ghcr.io/instructlab/ui/ui:main
$(CMD_PREFIX) docker pull postgres:15-alpine
$(CMD_PREFIX) kind load --name $(ILAB_KUBE_CLUSTER_NAME) docker-image postgres:15-alpine

.PHONY: stop-dev-kind
stop-dev-kind: check-kind ## Stop the Kind cluster to destroy the development environment
Expand Down Expand Up @@ -152,8 +184,30 @@ undeploy: ## Undeploy the InstructLab UI stack from a kubernetes cluster
fi
$(CMD_PREFIX) kubectl --context=$(ILAB_KUBE_CONTEXT) delete namespace $(ILAB_KUBE_NAMESPACE)

.PHONY: deploy-umami-kind
deploy-umami-kind: wait-for-readiness load-images
$(CMD_PREFIX) if [ ! -f .env ]; then \
echo "Please create a .env file in the root of the project." ; \
exit 1 ; \
fi
$(CMD_PREFIX) kubectl --context=$(ILAB_KUBE_CONTEXT) create namespace $(UMAMI_KUBE_NAMESPACE) --dry-run=client -o yaml | kubectl apply -f -
$(CMD_PREFIX) bash -c "source .env && \
deploy/k8s/base/umami/deploy-umami-openshift-env-secret-conversion.sh KIND $(UMAMI_KUBE_NAMESPACE)"
$(CMD_PREFIX) kubectl create -f ./deploy/k8s/overlays/kind/umami/umami-secret.yaml
$(CMD_PREFIX) kubectl --context=$(ILAB_KUBE_CONTEXT) apply -k ./deploy/k8s/overlays/kind/umami
$(CMD_PREFIX) echo "Waiting for Umami Deployment (pods: postgresql and umami) ..."
$(CMD_PREFIX) kubectl --context=$(ILAB_KUBE_CONTEXT) wait --for=condition=Ready pods -n $(UMAMI_KUBE_NAMESPACE) --all -l app.kubernetes.io/part-of=umami --timeout=15m
$(CMD_PREFIX) umami_ingress=$$(kubectl get ingress umami-ingress -n umami -o jsonpath='{.spec.rules[*].host}') ; \
echo "Umami ingress deployed to: $$umami_ingress"

.PHONY: undeploy-umami-kind
undeploy-umami-kind:
-$(CMD_PREFIX) kubectl --context=$(ILAB_KUBE_CONTEXT) scale --replicas=0 deployment/umami -n $(UMAMI_KUBE_NAMESPACE)
-$(CMD_PREFIX) kubectl --context=$(ILAB_KUBE_CONTEXT) delete -f ./deploy/k8s/overlays/kind/umami/umami-secret.yaml
-$(CMD_PREFIX) kubectl --context=$(ILAB_KUBE_CONTEXT) delete -k ./deploy/k8s/overlays/kind/umami

.PHONY: start-dev-kind ## Run the development environment on Kind cluster
start-dev-kind: setup-kind deploy ## Setup a Kind cluster and deploy InstructLab UI on it
start-dev-kind: setup-kind load-images deploy ## Setup a Kind cluster and deploy InstructLab UI on it

##@ OpenShift - UI prod and qa deployment on OpenShift
.PHONY: deploy-qa-openshift
Expand All @@ -162,53 +216,97 @@ deploy-qa-openshift: ## Deploy QA stack of the InstructLab UI on OpenShift
echo "Please create a .env file in the root of the project." ; \
exit 1 ; \
fi

$(CMD_PREFIX) yes | cp -rf .env ./deploy/k8s/overlays/openshift/qa/.env
$(CMD_PREFIX) oc apply -k ./deploy/k8s/overlays/openshift/qa
$(CMD_PREFIX) oc wait --for=condition=Ready pods -n $(ILAB_KUBE_NAMESPACE) --all -l app.kubernetes.io/part-of=ui --timeout=15m
$(CMD_PREFIX) $(OC) apply -k ./deploy/k8s/overlays/openshift/qa
$(CMD_PREFIX) $(OC) wait --for=condition=Ready pods -n $(ILAB_KUBE_NAMESPACE) --all -l app.kubernetes.io/part-of=ui --timeout=15m

.PHONY: redeploy-qa-openshift
redeploy-qa-openshift: ## Redeploy QA stack of the InstructLab UI on OpenShift
$(CMD_PREFIX) oc -n $(ILAB_KUBE_NAMESPACE) rollout restart deploy/ui
$(CMD_PREFIX) oc -n $(ILAB_KUBE_NAMESPACE) rollout restart deploy/pathservice

$(CMD_PREFIX) $(OC) -n $(ILAB_KUBE_NAMESPACE) rollout restart deploy/ui
$(CMD_PREFIX) $(OC) -n $(ILAB_KUBE_NAMESPACE) rollout restart deploy/pathservice

.PHONY: undeploy-qa-openshift
undeploy-qa-openshift: ## Undeploy QA stack of the InstructLab UI on OpenShift
$(CMD_PREFIX) oc delete -k ./deploy/k8s/overlays/openshift/qa
$(CMD_PREFIX) $(OC) delete -k ./deploy/k8s/overlays/openshift/qa
$(CMD_PREFIX) if [ -f ./deploy/k8s/overlays/openshift/qa/.env ]; then \
rm ./deploy/k8s/overlays/openshift/qa/.env ; \
fi

.PHONY: deploy-umami-qa-openshift
deploy-umami-qa-openshift:
$(CMD_PREFIX) if [ ! -f .env ]; then \
echo "Please create a .env file in the root of the project." ; \
exit 1 ; \
fi
$(CMD_PREFIX) $(OC) create namespace $(UMAMI_KUBE_NAMESPACE) --dry-run=client -o yaml | $(OC) apply -f -
$(CMD_PREFIX) source .env && \
deploy/k8s/base/umami/deploy-umami-openshift-env-secret-conversion.sh OPENSHIFT $(UMAMI_KUBE_NAMESPACE)
$(CMD_PREFIX) $(OC) apply -f ./deploy/k8s/overlays/openshift/umami/umami-secret.yaml
$(CMD_PREFIX) $(OC) apply -k ./deploy/k8s/overlays/openshift/umami
$(CMD_PREFIX) echo "Waiting for Umami Deployment (pods: postgresql and umami) ..."
$(CMD_PREFIX) $(OC) wait --for=condition=Ready pods -n $(UMAMI_KUBE_NAMESPACE) --all -l app.kubernetes.io/part-of=umami --timeout=15m
$(CMD_PREFIX) umami_route=$$($(OC) get route umami -n $(UMAMI_KUBE_NAMESPACE) | tail -n 1 | awk '{print $$2}') ; \
echo "Umami route deployed to: $$umami_route"

.PHONY: undeploy-umami-qa-openshift
undeploy-umami-qa-openshift:
-$(CMD_PREFIX) $(OC) scale --replicas=0 deployment/umami -n $(UMAMI_KUBE_NAMESPACE)
-$(CMD_PREFIX) $(OC) delete -f ./deploy/k8s/overlays/openshift/umami/umami-secret.yaml
-$(CMD_PREFIX) $(OC) delete -k ./deploy/k8s/overlays/openshift/umami

.PHONY: deploy-prod-openshift
deploy-prod-openshift: ## Deploy production stack of the InstructLab UI on OpenShift
$(CMD_PREFIX) if [ ! -f .env ]; then \
echo "Please create a .env file in the root of the project." ; \
exit 1 ; \
fi

$(CMD_PREFIX) yes | cp -rf .env ./deploy/k8s/overlays/openshift/prod/.env
$(CMD_PREFIX) oc apply -k ./deploy/k8s/overlays/openshift/prod
$(CMD_PREFIX) oc wait --for=condition=Ready pods -n $(ILAB_KUBE_NAMESPACE) --all -l app.kubernetes.io/part-of=ui --timeout=15m
$(CMD_PREFIX) $(OC) apply -k ./deploy/k8s/overlays/openshift/prod
$(CMD_PREFIX) $(OC) wait --for=condition=Ready pods -n $(ILAB_KUBE_NAMESPACE) --all -l app.kubernetes.io/part-of=ui --timeout=15m

.PHONY: redeploy-prod-openshift
redeploy-prod-openshift: ## Redeploy production stack of the InstructLab UI on OpenShift
$(CMD_PREFIX) oc -n $(ILAB_KUBE_NAMESPACE) rollout restart deploy/ui
$(CMD_PREFIX) oc -n $(ILAB_KUBE_NAMESPACE) rollout restart deploy/pathservice

$(CMD_PREFIX) $(OC) -n $(ILAB_KUBE_NAMESPACE) rollout restart deploy/ui
$(CMD_PREFIX) $(OC) -n $(ILAB_KUBE_NAMESPACE) rollout restart deploy/pathservice

.PHONY: undeploy-prod-openshift
undeploy-prod-openshift: ## Undeploy production stack of the InstructLab UI on OpenShift
$(CMD_PREFIX) oc delete -k ./deploy/k8s/overlays/openshift/prod
$(CMD_PREFIX) $(OC) delete -k ./deploy/k8s/overlays/openshift/prod
$(CMD_PREFIX) if [ -f ./deploy/k8s/overlays/openshift/prod/.env ]; then \
rm ./deploy/k8s/overlays/openshift/prod/.env ; \
fi

.PHONY: deploy-umami-prod-openshift
deploy-umami-prod-openshift: check-kubeseal check-sealed-secrets-controller
$(CMD_PREFIX) if [ ! -f .env ]; then \
echo "Please create a .env file in the root of the project." ; \
exit 1 ; \
fi
$(CMD_PREFIX) $(OC) create namespace $(UMAMI_KUBE_NAMESPACE) --dry-run=client -o yaml | $(OC) apply -f -
$(CMD_PREFIX) source .env && \
deploy/k8s/base/umami/deploy-umami-openshift-env-secret-conversion.sh "OPENSHIFT" $(UMAMI_KUBE_NAMESPACE)
$(CMD_PREFIX) cat deploy/k8s/overlays/openshift/umami/umami-secret.yaml | kubeseal \
--controller-name=${SEALED_SECRETS_CONTROLLER_NAME} \
--controller-namespace=${SEALED_SECRETS_CONTROLLER_NAMESPACE} \
--format yaml > ./deploy/k8s/overlays/openshift/umami/umami-secret.sealedsecret.yaml
$(CMD_PREFIX) $(OC) apply -f deploy/k8s/overlays/openshift/umami/umami-secret.sealedsecret.yaml
$(CMD_PREFIX) $(OC) apply -k deploy/k8s/overlays/openshift/umami
$(CMD_PREFIX) echo "Waiting for Umami Deployment (pods: postgresql and umami) ..."
$(CMD_PREFIX) $(OC) wait --for=condition=Ready pods -n $(UMAMI_KUBE_NAMESPACE) --all -l app.kubernetes.io/part-of=umami --timeout=15m
$(CMD_PREFIX) umami_route=$$($(OC) get route umami -n $(UMAMI_KUBE_NAMESPACE) | tail -n 1 | awk '{print $$2}') ; \
echo "Umami route deployed to: $$umami_route"

.PHONY: undeploy-umami-prod-openshift
undeploy-umami-prod-openshift:
-$(CMD_PREFIX) $(OC) scale --replicas=0 deployment/umami -n $(UMAMI_KUBE_NAMESPACE)
-$(CMD_PREFIX) $(OC) delete -f ./deploy/k8s/overlays/openshift/umami/umami-secret.sealedsecret.yaml
-$(CMD_PREFIX) $(OC) delete -k ./deploy/k8s/overlays/openshift/umami

.PHONY: check-dev-container-installed
check-dev-container-installed:
@if [ -z "${DEVCONTAINER_BINARY_EXISTS}" ]; then \
echo "You do not have devcontainer installed, please isntall it!"; \
exit 1; \
echo "You do not have devcontainer installed, please isntall it!" ; \
exit 1 ; \
fi;

.PHONY: build-dev-container
Expand All @@ -233,12 +331,12 @@ cycle-dev-container:
CONTAINER_IDS=$(shell ${CONTAINER_ENGINE} ps -a | grep "quay.io/instructlab-ui/devcontainer" | awk '{print $$1}') && \
if [ -n "$$CONTAINER_IDS" ]; then \
for CONTAINER_ID in "$$CONTAINER_IDS"; do \
echo "Stopping and removing container $$CONTAINER_ID of imageid $$image_id..."; \
${CONTAINER_ENGINE} rm "$$CONTAINER_ID" -f; \
done; \
fi; \
echo "removing image with id $$image_id and all containers using that image ..."; \
${CONTAINER_ENGINE} rmi $$image_id -f; \
echo "Stopping and removing container $$CONTAINER_ID of imageid $$image_id..." ; \
${CONTAINER_ENGINE} rm "$$CONTAINER_ID" -f ; \
done ; \
fi ; \
echo "removing image with id $$image_id and all containers using that image ..." ; \
${CONTAINER_ENGINE} rmi $$image_id -f ; \
fi;
$(MAKE) build-dev-container
$(MAKE) start-dev-container
19 changes: 19 additions & 0 deletions argocd/overlays/applicaitons/app-of-apps.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: app-of-apps-ilab
spec:
destination:
namespace: openshift-gitpos
name: in-cluster
project: default
source:
path: argocd/overlays/applicaitons
repoURL: https://github.com/instructlab/ui.git
targetRevision: HEAD
syncPolicy:
syncOptions:
- Validate=false
- ApplyOutOfSyncOnly=true
# automated:
# selfHeal: true
7 changes: 7 additions & 0 deletions argocd/overlays/applicaitons/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: openshift-gitops
resources:
# - prod.yaml # currently not deployed via argo
- qa.yaml
- umami.yaml
2 changes: 1 addition & 1 deletion argocd/overlays/applicaitons/prod.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ metadata:
name: ilab-ui-stack-production
spec:
destination:
name: in-cluster
name: in-cluster # THIS NEEDS TO CHANGE once we get prod on ARGO
namespace: instructlab
project: default
source:
Expand Down
17 changes: 17 additions & 0 deletions argocd/overlays/applicaitons/umami.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: umami
spec:
project: default
source:
repoURL: https://github.com/instructlab/ui.git
path: deploy/k8s/overlays/openshift/umami
targetRevision: main
destination:
namespace: umami
name: in-cluster
syncPolicy:
automated:
selfHeal: true

Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#!/bin/bash
# -*- indent-tabs-mode: nil; tab-width: 2; sh-indentation: 2; -*-

# Helper script to filter out `.env`` values related to umami deployment, and generate the secret manifest from that

# Requires: kubectl, yq

if [ -f ".env" ]; then
source .env
fi

if [ "$#" -ne 2 ]; then
echo "USAGE: $0 TARGET NAMESPACE
TARGET: The deployment target. Options: [\"OPENSHIFT\", \"KIND\"]
NAMESPACE: The namespace where you want to deploy the umami-secret." 1>&2
exit 1
fi

TARGET="$1"
NAMESPACE="$2"

if [ "${TARGET}" == "OPENSHIFT" ]; then
UMAMI_SECRET_FILE_PATH="deploy/k8s/overlays/openshift/umami/umami-secret.yaml"
UMAMI_DATABASE_NAME_KEY_NAME=POSTGRESQL_DATABASE
UMAMI_DATABASE_USER_KEY_NAME=POSTGRESQL_USER
UMAMI_DATABASE_PASSWORD_KEY_NAME=POSTGRESQL_PASSWORD
elif [ "${TARGET}" == "KIND" ]; then
UMAMI_SECRET_FILE_PATH="deploy/k8s/overlays/kind/umami/umami-secret.yaml"
UMAMI_DATABASE_NAME_KEY_NAME=POSTGRES_DB
UMAMI_DATABASE_USER_KEY_NAME=POSTGRES_USER
UMAMI_DATABASE_PASSWORD_KEY_NAME=POSTGRES_PASSWORD
else
echo "Error, \$TARGET ${TARGET} not recongnized.
TARGET options: [\"OPENSHIFT\", \"KIND\"]"
exit 1
fi

required_vars=("DATABASE_TYPE" "UMAMI_DATABASE_NAME" "UMAMI_DATABASE_USER" "UMAMI_DATABASE_PASSWORD" "UMAMI_APP_SECRET" "DATABASE_URL")

missing_vars=()

for var in "${required_vars[@]}"; do
if [[ -z "${!var}" ]]; then
missing_vars+=("$var")
fi
done

if [[ ${#missing_vars[@]} -gt 0 ]]; then
echo "The following environment variables are missing:"
for var in "${missing_vars[@]}"; do
echo " - $var"
done
echo "Please add these variables to your .env file."
exit 1
fi

cluster_domain=$(kubectl cluster-info | grep 'Kubernetes control plane' | awk -F// '{print $2}' | awk -F: '{print $1}')

# Note: `.env` values get rerouted to their correct image target
# Prod uses: `POSTGRESQL_DATABASE`,`POSTGRESQL_USER`, and `POSTGRESQL_PASSWORD`
# Stage uses: `POSTGRES_DB`, `POSTGRES_USER` and `POSTGRES_PASSWORD`
# This different is due to the differences in the `postgresql:15-alpine` image and the `registry.redhat.io/rhel9/postgresql-15:9.5-1733127512` image
# Both map `UMAMI_APP_SECRET` to `APP_SECRET`

kubectl create secret generic umami-secret \
--from-literal "DATABASE_TYPE=${DATABASE_TYPE}" \
--from-literal "${UMAMI_DATABASE_NAME_KEY_NAME}=${UMAMI_DATABASE_NAME}" \
--from-literal "${UMAMI_DATABASE_USER_KEY_NAME}=${UMAMI_DATABASE_USER}" \
--from-literal "${UMAMI_DATABASE_PASSWORD_KEY_NAME}=${UMAMI_DATABASE_PASSWORD}" \
--from-literal "APP_SECRET=${UMAMI_APP_SECRET}" \
--from-literal "DATABASE_URL=${DATABASE_URL}" \
--namespace "${NAMESPACE}" \
--dry-run=client \
-o yaml > ${UMAMI_SECRET_FILE_PATH}

yq eval ".metadata.labels.cluster_domain = \"${cluster_domain}\"" -i ${UMAMI_SECRET_FILE_PATH}

echo "Secret manifest has been created: ${UMAMI_SECRET_FILE_PATH}."
Loading
Loading