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

AI PRP: Request New Web Fingerprint for Kubeflow Model UI #422 #488

Merged
merged 4 commits into from
Aug 8, 2024
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
FROM alpine:3.8

RUN apk add --no-cache \
bash \
curl \
docker \
git \
jq \
openssl \
shadow \
vim \
wget

# Add Limited user
RUN groupadd -r kinduser \
-g 777 && \
useradd -c "kinduser runner account" \
-g kinduser \
-u 777 \
-m \
-r \
kinduser && \
usermod -aG docker kinduser


RUN curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.17.0/bin/linux/amd64/kubectl && \
chmod +x ./kubectl && \
mv ./kubectl /usr/local/bin/kubectl

# Install Kubernetes in Docker (kind)
RUN curl -Lo ./kind https://github.com/kubernetes-sigs/kind/releases/download/v0.7.0/kind-linux-amd64 && \
chmod +x ./kind && \
mv ./kind /usr/local/bin/kind

EXPOSE 58080
WORKDIR /src
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#!/bin/bash

while [ ! -f /lockconfig/lock ]; do
echo "Waiting for the file to be created by cluster"
sleep 2
done

# Define the Gunicorn start command
GUNICORN_CMD="gunicorn -w 3 --bind 0.0.0.0:5000 --access-logfile - entrypoint:app"

# Function to start Gunicorn
start_gunicorn() {
echo "Starting Gunicorn..."
$GUNICORN_CMD
}

# Function to monitor and restart Gunicorn if it exits
monitor_gunicorn() {
while true; do
start_gunicorn

# Wait for Gunicorn to exit
wait $!

# Log the exit and attempt a restart
echo "Gunicorn exited. Restarting..."
sleep 1 # Optional sleep before restarting
done
}

# Start monitoring Gunicorn
monitor_gunicorn
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
version: '3.7'

services:
kind:
image: kind_cluster:latest
privileged: true
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- kubeconfig:/root/.kube/
- lockconfig:/lockconfig
- ./kind_startup.sh:/src/startup.sh
entrypoint: /bin/sh -c "chmod +x /src/startup.sh && /src/startup.sh"
healthcheck:
test: ["CMD", "test", "-f", "/lockconfig/lock"]
interval: 30s
timeout: 10s
retries: 20
ports:
- "58080:58080"
environment:
- MODELS_WEB_APP_TAG=${MODELS_WEB_APP_TAG}

kubeflow:
image: kubeflow-models-ui:${MODELS_WEB_APP_TAG}
depends_on:
- kind
ports:
- "8080:5000"
volumes:
- kubeconfig:/root/.kube/
- lockconfig:/lockconfig
- ./app_startup.sh:/src/startup.sh
environment:
- APP_PREFIX=/
- APP_DISABLE_AUTH=True
- APP_SECURE_COOKIES=False

entrypoint: ["/bin/sh", "-c", "sleep 60 && chmod +x /src/startup.sh && /src/startup.sh"]
volumes:
kubeconfig:
lockconfig:
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#!/bin/sh

export DOCKER_GATEWAY_IP=$(docker network inspect bridge --format '{{range .IPAM.Config}}{{.Gateway}}{{end}}')
export KUBE_PROXY_PORT=58080
export KUBECTL_INSECURE_SKIP_TLS_VERIFY=true


kubectl_proxy_on() {
kubectl config set-cluster proxy-cluster --server="http://${DOCKER_GATEWAY_IP}:${KUBE_PROXY_PORT}"
kubectl config set-context proxy-context --cluster=proxy-cluster --user=$(kubectl config view -o jsonpath='{.contexts[?(@.name == "'"$(kubectl config current-context)"'")].context.user}')
kubectl config use-context proxy-context
echo "Switched to use kubectl proxy"
}

start_kubernetes_cluster() {
#delete if exists
kind delete cluster --name my-cluster

#create cluster
cat <<EOF | kind create cluster --name my-cluster --config=-
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
networking:
apiServerAddress: "0.0.0.0"
EOF

#wait for the cluster
sleep 5

#update the gateway IP
sed -i "s/0.0.0.0/$DOCKER_GATEWAY_IP/g" /root/.kube/config

}
start_proxy(){
kubectl --insecure-skip-tls-verify proxy --address='0.0.0.0' --accept-hosts='^.*$' --port=${KUBE_PROXY_PORT} &
sleep 5
}

configure_cluster(){
kubectl create namespace kubeflow
kubectl apply -f https://raw.githubusercontent.com/kserve/kserve/master/install/v$MODELS_WEB_APP_TAG/kserve_kubeflow.yaml
}

start_kubernetes_cluster
start_proxy
kubectl_proxy_on
configure_cluster

sleep 2
touch /lockconfig/lock
tail -f /dev/null
163 changes: 163 additions & 0 deletions google/fingerprinters/web/scripts/updater/community/kubeflow/update.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
#!/usr/bin/env bash

# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

set -e

source ../../common.sh

SCRIPT_PATH="$(cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P)"
PROJECT_ROOT="$(cd -- "${SCRIPT_PATH}/../../../.." >/dev/null 2>&1 ; pwd -P)"
APP_PATH="${SCRIPT_PATH}/app"
TMP_DATA="/tmp/kubeflow_fingerprints"
GIT_REPO="${TMP_DATA}/repo"
FINGERPRINTS_PATH="${TMP_DATA}/fingerprints"
JSON_DATA="${FINGERPRINTS_PATH}/fingerprint.json"
BIN_DATA="${FINGERPRINTS_PATH}/fingerprint.binproto"
BINPROTO="${PROJECT_ROOT}/src/main/resources/fingerprinters/web/data/community/kubeflow.binproto"

mkdir -p "${FINGERPRINTS_PATH}"


removeCluster(){
docker rmi -f kind_cluster:latest
}
buildCluster() {
pushd "${APP_PATH}" >/dev/null
docker build -t kind_cluster:latest -f Dockerfile.kind .
popd >/dev/null
}

buildKubeFlowImage(){
local version="$1"
pushd "${GIT_REPO}" >/dev/null
docker build -t kubeflow-models-ui:${version} -f Dockerfile .
popd >/dev/null
}

removeKubeFlowImage(){
local version="$1"
#docker rmi -f kubeflow-models-ui:${version}
}

startKubeflow(){
local version="$1"
pushd "${APP_PATH}" >/dev/null
MODELS_WEB_APP_TAG="${version}" docker-compose up -d
popd >/dev/null
}

stopContainer(){
local name="$1"

CONTAINER_ID=$(docker ps | grep "${name}" | cut -d " " -f1)
if [ -n "$KUBEFLOW_CONTAINER" ]; then
docker stop $CONTAINER_ID
fi

}

stopKubeFlow(){
local version="$1"
pushd "${APP_PATH}" >/dev/null
MODELS_WEB_APP_TAG="${version}" docker-compose down
stopContainer "kindest/node"
stopContainer "kubeflow-models-ui:${version}"
stopContainer "kind_cluster"

popd >/dev/null
}

waitForServer() {
local url="http://localhost:8080"
local wait_time="${2:-5}"

echo "Waiting for server at $url to be available..."

while true; do
http_response=$(curl --write-out "%{http_code}" --silent --output /dev/null "$url" || echo "failed")
if [ "$http_response" -eq 200 ]; then
echo "Server is up and running at $url!"
break
elif [ "$http_response" = "failed" ]; then
echo "Curl command failed. Waiting for $wait_time seconds before retrying..."
else
echo "Server not yet available (HTTP status: $http_response). Waiting for $wait_time seconds..."
fi
sleep "$wait_time"
done
}


#Build kuberentes cluster
buildCluster

# Convert existing data file to a human-readable JSON file
convertFingerprint "${BINPROTO}" "${JSON_DATA}"

# Clone Kubeflow Models UI repository if not already present
if [[ ! -d "${GIT_REPO}" ]]; then
git clone https://github.com/kserve/models-web-app.git "${GIT_REPO}"
fi


# Read all versions to be fingerprinted
readarray -t ALL_VERSIONS < "${SCRIPT_PATH}/versions.txt"

# Update fingerprints for all listed versions
for app_version in "${ALL_VERSIONS[@]}"; do
echo "Fingerprinting Kubeflow Models UI version ${app_version} ..."

# Checkout the repository to the correct tag
checkOutRepo "${GIT_REPO}" "v${app_version}"

# Build and run the container
buildKubeFlowImage "${app_version}"

# Start the cluser and kubeflow
startKubeflow "${app_version}"

echo "Waiting for Kubeflow ${app_version} to be ready ..."
sleep 60

# Wait for the container to be fully up
waitForServer

echo "Application is up, updating fingerprint."

# Capture the fingerprints
updateFingerprint \
"kubeflow" \
"${app_version}" \
"${FINGERPRINTS_PATH}" \
"${GIT_REPO}" \
"http://localhost:8080"

# Stop and remove the container
stopKubeFlow "${app_version}"

removeKubeFlowImage "${app_version}"

done

removeCluster

# Convert the updated JSON data to binary proto format
convertFingerprint "${JSON_DATA}" "${BIN_DATA}"

echo "Fingerprint updated for Kubeflow Models UI. Please commit the following file:"
echo " ${BIN_DATA}"
echo "to"
echo " ${BINPROTO}"
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
0.7.0
0.8.0
0.9.0
0.10.0
0.13.0-rc.0
Loading
Loading