Skip to content

Commit 7c3c9f3

Browse files
saving full work
1 parent e11339f commit 7c3c9f3

16 files changed

+347
-16
lines changed

.devcontainer/Containerfile

+30-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
FROM registry.access.redhat.com/ubi9/nodejs-22:9.5-1730543890
22

3+
WORKDIR /opt/app-root/src
4+
35
ARG USERNAME=default
46
ARG NPM_GLOBAL=/usr/local/share/npm-global
57

@@ -10,13 +12,40 @@ USER root
1012

1113
RUN umask 0002
1214

15+
# install zsh and oh-my-zsh
16+
RUN dnf install -y zsh && \
17+
bash -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
18+
1319
RUN groupadd npm && \
1420
usermod -a -G npm ${USERNAME} && \
1521
bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash) && \
1622
chown -R ${USERNAME}:npm /usr/local/ && \
1723
mkdir -p /opt/app-root/src/.npm && chown -R ${USERNAME}:npm /opt/app-root/src/ && \
18-
dnf install -y vim
24+
dnf install -y vim jq
25+
26+
# install kubectl
27+
ADD install-kubectl.sh /tmp
28+
RUN /tmp/install-kubectl.sh; \
29+
rm /tmp/install-kubectl.sh
30+
31+
# install kubseal
32+
ADD install-kubeseal.sh /tmp
33+
RUN /tmp/install-kubeseal.sh; \
34+
rm /tmp/install-kubeseal.sh
35+
36+
# install docker as a dependency of kind
37+
# only need the CLI and runtime, binding to host docker socket for access to host docker context
38+
RUN dnf -y install dnf-plugins-core; \
39+
dnf config-manager --add-repo https://download.docker.com/linux/rhel/docker-ce.repo; \
40+
dnf install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
41+
42+
# install kind
43+
ADD install-kind.sh /tmp
44+
RUN /tmp/install-kind.sh; \
45+
rm /tmp/install-kind.sh
1946

47+
# symlink oc because cannot install stable stream without RH auth
48+
RUN ln -sf /usr/local/bin/kubectl /usr/local/bin/oc
2049

2150
USER default
2251

.devcontainer/devcontainer.json

+8-4
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,20 @@
1111
"dbaeumer.vscode-eslint",
1212
"esbenp.prettier-vscode",
1313
"DavidAnson.vscode-markdownlint",
14-
"ms-vscode-remote.remote-containers"
14+
"ms-vscode-remote.remote-containers",
15+
"foxundermoon.shell-format",
16+
"timonwong.shellcheck"
1517
],
1618
"settings": {
17-
"terminal.integrated.shell.linux": "/bin/bash"
19+
"terminal.integrated.shell.linux": "/bin/zsh"
1820
}
1921
}
2022
},
21-
"forwardPorts": [3000],
23+
"forwardPorts": [3000, 6443],
2224
"mounts": [
23-
"type=bind,source=${localWorkspaceFolder}/.env,target=/workspace/ui/.env,consistency=cached"
25+
"type=bind,source=${localWorkspaceFolder}/.env,target=/workspace/ui/.env,consistency=cached",
26+
"source=${env:HOME}/.kube,target=/opt/app-root/src/.kube,type=bind,consistency=cached",
27+
"source=/var/run/docker.sock,target=/var/run/docker.sock,type=bind"
2428
],
2529
"runArgs": ["-p", "3000:3000"]
2630
}

.devcontainer/install-kind.sh

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#!/bin/bash
2+
# -*- indent-tabs-mode: nil; tab-width: 2; sh-indentation: 2; -*-
3+
4+
# Install the kind binary
5+
6+
[ $(uname -m) = x86_64 ] && curl -Lo /tmp/kind https://kind.sigs.k8s.io/dl/v0.25.0/kind-linux-amd64
7+
[ $(uname -m) = aarch64 ] && curl -Lo /tmp/kind https://kind.sigs.k8s.io/dl/v0.25.0/kind-linux-arm64
8+
chmod +x /tmp/kind
9+
mv /tmp/kind /usr/local/bin/kind
10+
kind completion zsh > ~/.oh-my-zsh/cache/completions/_kind

.devcontainer/install-kubectl.sh

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#!/bin/bash
2+
# -*- indent-tabs-mode: nil; tab-width: 2; sh-indentation: 2; -*-
3+
4+
# Install the kubectl binary
5+
6+
ARCH=$(uname -m)
7+
if [ "$ARCH" == "x86_64" ] || [ "$ARCH" == "amd64" ]; then
8+
ARCH="amd64"
9+
elif [ "$ARCH" == "aarch64" ] || [ "$ARCH" == "arm64" ]; then
10+
ARCH="arm64"
11+
else
12+
echo "Unsupported architecture: $ARCH"
13+
exit 1
14+
fi
15+
16+
KUBECTL_VERSION=$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)
17+
echo "Installing kubectl version $KUBECTL_VERSION for $ARCH..."
18+
curl -LO "https://dl.k8s.io/release/${KUBECTL_VERSION}/bin/linux/${ARCH}/kubectl"
19+
chmod +x kubectl
20+
mv kubectl /usr/local/bin/
21+
kubectl completion zsh > $ZSH/cache/completions/_kubectl
22+
23+
curl -sLO https://access.cdn.redhat.com/content/origin/files/sha256/99/99f0ecb5477ed1a038e7279252971b4c5d50fa9a877f78610b7d4e4ee02e0589/openshift-client-linux-amd64-rhel9-4.17.6.tar.gz

.devcontainer/install-kubeseal.sh

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#!/bin/bash
2+
# -*- indent-tabs-mode: nil; tab-width: 2; sh-indentation: 2; -*-
3+
4+
# Install the kubeseal binary
5+
6+
set -x
7+
set -e
8+
set -o pipefail
9+
10+
# Determine architecture
11+
ARCH=$(uname -m)
12+
if [ "$ARCH" == "x86_64" ] || [ "$ARCH" == "amd64" ]; then
13+
ARCH="amd64"
14+
elif [ "$ARCH" == "aarch64" ] || [ "$ARCH" == "arm64" ]; then
15+
ARCH="arm64"
16+
else
17+
echo "Unsupported architecture: $ARCH"
18+
exit 1
19+
fi
20+
21+
KUBESEAL_VERSION=$(curl -s https://api.github.com/repos/bitnami-labs/sealed-secrets/tags | jq -r '.[0].name' | cut -c 2-)
22+
if [ -z "$KUBESEAL_VERSION" ]; then
23+
echo "Failed to fetch the latest KUBESEAL_VERSION"
24+
exit 1
25+
fi
26+
27+
curl -OL "https://github.com/bitnami-labs/sealed-secrets/releases/download/v${KUBESEAL_VERSION}/kubeseal-${KUBESEAL_VERSION}-linux-${ARCH}.tar.gz"
28+
tar -xvzf kubeseal-${KUBESEAL_VERSION}-linux-${ARCH}.tar.gz kubeseal
29+
install -m 755 kubeseal /usr/local/bin/kubeseal
30+
kubeseal completion zsh > ~/.oh-my-zsh/cache/completions/_kubeseal

Makefile

+85-11
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ ILAB_KUBE_CONTEXT?=kind-instructlab-ui
2020
ILAB_KUBE_NAMESPACE?=instructlab
2121
ILAB_KUBE_CLUSTER_NAME?=instructlab-ui
2222
CONTAINER_ENGINE?=docker
23-
DEVCONTAINER_BINARY_EXISTS ?= $(shell command -v devcontainer)
23+
DEVCONTAINER_BINARY_EXISTS?=$(shell command -v devcontainer)
24+
DEVCONTAINER_DEFAULT_SHELL?=zsh
2425
TAG=$(shell git rev-parse HEAD)
2526
##@ Development - Helper commands for development
2627
.PHONY: md-lint
@@ -111,9 +112,20 @@ check-kubectl:
111112
exit 1 ; \
112113
fi
113114

115+
.PHONY: check-kubeseal
116+
check-kubeseal:
117+
$(CMD_PREFIX) if [ -z "$(shell which kubeseal)" ]; then \
118+
echo "Please install kubeseal" ; \
119+
echo "https://github.com/bitnami-labs/sealed-secrets?tab=readme-ov-file#kubeseal" ; \
120+
exit 1 ; \
121+
fi
122+
114123
.PHONY: load-images
115124
load-images: ## Load images onto Kind cluster
125+
$(CMD_PREFIX) docker pull ghcr.io/instructlab/ui/ui:main
116126
$(CMD_PREFIX) kind load --name $(ILAB_KUBE_CLUSTER_NAME) docker-image ghcr.io/instructlab/ui/ui:main
127+
$(CMD_PREFIX) docker pull registry.redhat.io/rhel9/postgresql-15:9.5-1733127512
128+
$(CMD_PREFIX) kind load --name $(ILAB_KUBE_CLUSTER_NAME) docker-image registry.redhat.io/rhel9/postgresql-15:9.5-1733127512
117129

118130
.PHONY: stop-dev-kind
119131
stop-dev-kind: check-kind ## Stop the Kind cluster to destroy the development environment
@@ -130,8 +142,8 @@ wait-for-readiness: # Wait for operators to be ready
130142
$(CMD_PREFIX) kubectl --context=$(ILAB_KUBE_CONTEXT) -n ingress-nginx rollout restart deployment ingress-nginx-controller
131143
$(CMD_PREFIX) kubectl --context=$(ILAB_KUBE_CONTEXT) -n ingress-nginx rollout status deployment ingress-nginx-controller --timeout=10m
132144

133-
.PHONY: deploy
134-
deploy: wait-for-readiness ## Deploy a InstructLab UI development stack onto a kubernetes cluster
145+
.PHONY: deploy-kind
146+
deploy-kind: wait-for-readiness ## Deploy a InstructLab UI development stack onto a kubernetes cluster
135147
$(CMD_PREFIX) if [ ! -f .env ]; then \
136148
echo "Please create a .env file in the root of the project." ; \
137149
exit 1 ; \
@@ -140,20 +152,42 @@ deploy: wait-for-readiness ## Deploy a InstructLab UI development stack onto a k
140152
$(CMD_PREFIX) kubectl --context=$(ILAB_KUBE_CONTEXT) apply -k ./deploy/k8s/overlays/kind
141153
$(CMD_PREFIX) kubectl --context=$(ILAB_KUBE_CONTEXT) wait --for=condition=Ready pods -n $(ILAB_KUBE_NAMESPACE) --all -l app.kubernetes.io/part-of=ui --timeout=15m
142154

143-
.PHONY: redeploy
144-
redeploy: ui-image load-images ## Redeploy the InstructLab UI stack onto a kubernetes cluster
155+
.PHONY: redeploy-kind
156+
redeploy-kind: ui-image load-images ## Redeploy the InstructLab UI stack onto a kubernetes cluster
145157
$(CMD_PREFIX) kubectl --context=$(ILAB_KUBE_CONTEXT) -n $(ILAB_KUBE_NAMESPACE) rollout restart deploy/ui
146158
$(CMD_PREFIX) kubectl --context=$(ILAB_KUBE_CONTEXT) -n $(ILAB_KUBE_NAMESPACE) rollout restart deploy/pathservice
147159

148-
.PHONY: undeploy
149-
undeploy: ## Undeploy the InstructLab UI stack from a kubernetes cluster
160+
.PHONY: undeploy-kind
161+
undeploy-kind: ## Undeploy the InstructLab UI stack from a kubernetes cluster
150162
$(CMD_PREFIX) if [ -f ./deploy/k8s/overlays/kind/.env ]; then \
151163
rm ./deploy/k8s/overlays/kind/.env ; \
152164
fi
153165
$(CMD_PREFIX) kubectl --context=$(ILAB_KUBE_CONTEXT) delete namespace $(ILAB_KUBE_NAMESPACE)
154166

167+
.PHONY: deploy-umami-kind
168+
deploy-umami-kind: wait-for-readiness load-images
169+
$(CMD_PREFIX) if [ ! -f .env ]; then \
170+
echo "Please create a .env file in the root of the project." ; \
171+
exit 1 ; \
172+
fi
173+
$(CMD_PREFIX) bash -c "source .env && \
174+
deploy/k8s/base/umami/deploy-umami-openshift-env-secret-conversion.sh KIND $(UMAMI_KUBE_NAMESPACE)"
175+
176+
$(CMD_PREFIX) kubectl --context=$(ILAB_KUBE_CONTEXT) create namespace $(UMAMI_KUBE_NAMESPACE) --dry-run=client -o yaml | kubectl apply -f -
177+
$(CMD_PREFIX) kubectl create -f ./deploy/k8s/overlays/kind/umami/umami-secret.yaml
178+
$(CMD_PREFIX) kubectl --context=$(ILAB_KUBE_CONTEXT) apply -k ./deploy/k8s/overlays/kind/umami
179+
180+
$(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
181+
$(CMD_PREFIX) kubectl --context=$(ILAB_KUBE_CONTEXT) port-forward -n $(UMAMI_KUBE_NAMESPACE) service/umami 3001:3001
182+
183+
.PHONY: undeploy-umami-kind
184+
undeploy-umami-kind:
185+
$(CMD_PREFIX) kubectl --context=$(ILAB_KUBE_CONTEXT) scale --replicas=0 deployment/umami -n $(UMAMI_KUBE_NAMESPACE)
186+
$(CMD_PREFIX) kubectl --context=$(ILAB_KUBE_CONTEXT) delete -f ./deploy/k8s/overlays/kind/umami/umami-secret.yaml
187+
$(CMD_PREFIX) kubectl --context=$(ILAB_KUBE_CONTEXT) delete -k ./deploy/k8s/overlays/kind/umami
188+
155189
.PHONY: start-dev-kind ## Run the development environment on Kind cluster
156-
start-dev-kind: setup-kind deploy ## Setup a Kind cluster and deploy InstructLab UI on it
190+
start-dev-kind: setup-kind load-images deploy-kind ## Setup a Kind cluster and deploy InstructLab UI on it
157191

158192
##@ OpenShift - UI prod and qa deployment on OpenShift
159193
.PHONY: deploy-qa-openshift
@@ -162,7 +196,6 @@ deploy-qa-openshift: ## Deploy QA stack of the InstructLab UI on OpenShift
162196
echo "Please create a .env file in the root of the project." ; \
163197
exit 1 ; \
164198
fi
165-
166199
$(CMD_PREFIX) yes | cp -rf .env ./deploy/k8s/overlays/openshift/qa/.env
167200
$(CMD_PREFIX) oc apply -k ./deploy/k8s/overlays/openshift/qa
168201
$(CMD_PREFIX) oc wait --for=condition=Ready pods -n $(ILAB_KUBE_NAMESPACE) --all -l app.kubernetes.io/part-of=ui --timeout=15m
@@ -172,14 +205,33 @@ redeploy-qa-openshift: ## Redeploy QA stack of the InstructLab UI on OpenShift
172205
$(CMD_PREFIX) oc -n $(ILAB_KUBE_NAMESPACE) rollout restart deploy/ui
173206
$(CMD_PREFIX) oc -n $(ILAB_KUBE_NAMESPACE) rollout restart deploy/pathservice
174207

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

215+
.PHONY: deploy-umami-qa-openshift
216+
deploy-umami-qa-openshift:
217+
$(CMD_PREFIX) if [ ! -f .env ]; then \
218+
echo "Please create a .env file in the root of the project." ; \
219+
exit 1 ; \
220+
fi
221+
$(CMD_PREFIX) source .env && \
222+
deploy/k8s/base/umami/deploy-umami-openshift-env-secret-conversion.sh OPENSHIFT $(UMAMI_KUBE_NAMESPACE)
223+
$(CMD_PREFIX) oc create namespace $(UMAMI_KUBE_NAMESPACE) --dry-run=client -o yaml | oc apply -f -
224+
$(CMD_PREFIX) oc apply -f ./deploy/k8s/overlays/openshift/umami/umami-secret.yaml
225+
226+
$(CMD_PREFIX) oc apply -k ./deploy/k8s/overlays/openshift/umami
227+
$(CMD_PREFIX) oc wait --for=condition=Ready pods -n $(UMAMI_KUBE_NAMESPACE) --all -l app.kubernetes.io/part-of=umami --timeout=15m
228+
229+
.PHONY: undeploy-umami-qa-openshift
230+
undeploy-umami-qa-openshift:
231+
$(CMD_PREFIX) oc scale --replicas=0 deployment/umami -n $(UMAMI_KUBE_NAMESPACE)
232+
$(CMD_PREFIX) oc delete -f ./deploy/k8s/overlays/openshift/umami/umami-secret.yaml
233+
$(CMD_PREFIX) oc delete -k ./deploy/k8s/overlays/openshift/umami
234+
183235
.PHONY: deploy-prod-openshift
184236
deploy-prod-openshift: ## Deploy production stack of the InstructLab UI on OpenShift
185237
$(CMD_PREFIX) if [ ! -f .env ]; then \
@@ -204,6 +256,28 @@ undeploy-prod-openshift: ## Undeploy production stack of the InstructLab UI on O
204256
rm ./deploy/k8s/overlays/openshift/prod/.env ; \
205257
fi
206258

259+
.PHONY: deploy-umami-prod-openshift
260+
deploy-umami-prod-openshift: check-kubeseal
261+
$(CMD_PREFIX) if [ ! -f .env ]; then \
262+
echo "Please create a .env file in the root of the project." ; \
263+
exit 1 ; \
264+
fi
265+
$(CMD_PREFIX) source .env && \
266+
deploy/k8s/base/umami/deploy-umami-openshift-env-secret-conversion.sh "OPENSHIFT" $(UMAMI_KUBE_NAMESPACE)
267+
$(CMD_PREFIX) cat deploy/k8s/overlays/openshift/umami/umami-secret.yaml | kubeseal \
268+
--controller-name=sealed-secrets-controller \
269+
--controller-namespace=kube-system \
270+
--format yaml > ./deploy/k8s/overlays/openshift/umami/umami-secret.sealedsecret.yaml
271+
$(CMD_PREFIX) oc create namespace $(UMAMI_KUBE_NAMESPACE) --dry-run=client -o yaml | oc apply -f -
272+
$(CMD_PREFIX) oc apply -f deploy/k8s/overlays/openshift/umami/umami-secret.sealedsecret.yaml
273+
$(CMD_PREFIX) oc apply -k deploy/k8s/overlays/openshift/umami
274+
275+
.PHONY: undeploy-umami-prod-openshift
276+
undeploy-umami-prod-openshift:
277+
$(CMD_PREFIX) oc scale --replicas=0 deployment/umami -n $(UMAMI_KUBE_NAMESPACE)
278+
$(CMD_PREFIX) oc delete -f ./deploy/k8s/overlays/openshift/umami/umami-secret.sealedsecret.yaml
279+
$(CMD_PREFIX) oc delete -k ./deploy/k8s/overlays/openshift/umami
280+
207281
.PHONY: check-dev-container-installed
208282
check-dev-container-installed:
209283
@if [ -z "${DEVCONTAINER_BINARY_EXISTS}" ]; then \
@@ -224,7 +298,7 @@ start-dev-container:
224298
.PHONY: enter-dev-container
225299
enter-dev-container:
226300
$(MAKE) check-dev-container-installed
227-
devcontainer exec --workspace-folder=./ --docker-path=${CONTAINER_ENGINE} bash
301+
devcontainer exec --workspace-folder=./ --docker-path=${CONTAINER_ENGINE} ${DEVCONTAINER_DEFAULT_SHELL}
228302

229303
.PHONY: cycle-dev-container
230304
cycle-dev-container:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
#!/bin/bash
2+
# -*- indent-tabs-mode: nil; tab-width: 2; sh-indentation: 2; -*-
3+
4+
# Helper script to filter out `.env`` values related to umami deployment, and generate the secret manifest from that
5+
6+
source .env
7+
8+
if [ "$#" -ne 2 ]; then
9+
echo "USAGE: $0 TARGET NAMESPACE
10+
TARGET: The deployment target. Options: [\"OPENSHIFT\", \"KIND\"]
11+
NAMESPACE: The namespace where you want to deploy the umami-secret." 1>&2
12+
exit 1
13+
fi
14+
15+
TARGET="$1"
16+
NAMESPACE="$2"
17+
18+
19+
if [ "${TARGET}" == "OPENSHIFT" ]; then
20+
UMAMI_SECRET_FILE_PATH="deploy/k8s/overlays/openshift/umami/umami-secret.yaml"
21+
elif [ "${TARGET}" == "KIND" ]; then
22+
UMAMI_SECRET_FILE_PATH="deploy/k8s/overlays/kind/umami/umami-secret.yaml"
23+
else
24+
echo "Error, \$TARGET ${TARGET} not recongnized.
25+
TARGET options: [\"OPENSHIFT\", \"KIND\"]"
26+
exit 1
27+
fi
28+
29+
required_vars=("DATABASE_TYPE" "POSTGRESQL_DATABASE" "POSTGRESQL_USER" "POSTGRESQL_PASSWORD" "UMAMI_APP_SECRET" "DATABASE_URL")
30+
31+
missing_vars=()
32+
33+
for var in "${required_vars[@]}"; do
34+
if [[ -z "${!var}" ]]; then
35+
missing_vars+=("$var")
36+
fi
37+
done
38+
39+
if [[ ${#missing_vars[@]} -gt 0 ]]; then
40+
echo "The following environment variables are missing:"
41+
for var in "${missing_vars[@]}"; do
42+
echo " - $var"
43+
done
44+
echo "Please add these variables to your .env file."
45+
exit 1
46+
fi
47+
48+
# Note: `.env` value UMAMI_APP_SECRET is re-routed to APP_SECRET intentionally
49+
kubectl create secret generic umami-secret \
50+
--from-literal DATABASE_TYPE=${DATABASE_TYPE} \
51+
--from-literal POSTGRESQL_DATABASE=${POSTGRESQL_DATABASE} \
52+
--from-literal POSTGRESQL_USER=${POSTGRESQL_USER} \
53+
--from-literal POSTGRESQL_PASSWORD=${POSTGRESQL_PASSWORD} \
54+
--from-literal APP_SECRET=${UMAMI_APP_SECRET} \
55+
--from-literal DATABASE_URL=${DATABASE_URL} \
56+
--namespace ${NAMESPACE} \
57+
--dry-run=client \
58+
-o yaml > ${UMAMI_SECRET_FILE_PATH}
59+
60+
echo "Secret manifest has been created: ${UMAMI_SECRET_FILE_PATH}."

deploy/k8s/overlays/kind/kind.yaml

+2
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,5 @@ nodes:
2424
image: kindest/node:v1.30.0
2525
- role: worker
2626
image: kindest/node:v1.30.0
27+
networking:
28+
apiServerPort: 6443
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
apiVersion: kustomize.config.k8s.io/v1beta1
2+
kind: Kustomization
3+
namespace: umami
4+
resources:
5+
- ../../../base/umami
6+
- umami-ingress.yaml

0 commit comments

Comments
 (0)