mirror of
https://github.com/taylanbakircioglu/flowfish.git
synced 2026-09-18 16:45:18 +00:00
6e503368f7
- Grafana Beyla DaemonSet for kernel-level HTTP/gRPC/DNS capture (passive, zero application changes, W3C traceparent header propagation) - flowfish-l7-collector in-cluster bridge: OTLP receiver + buffered pull API - L7 Ingestion Service: K8s service-proxy poll → enrich → RabbitMQ - ClickHouse l7_http_flows / l7_grpc_flows / l7_dns_flows + APM RED MVs - Neo4j L7Workload nodes + SAME_WORKLOAD cross-cluster bridges - New pages: Service Map, Trace Explorer, APM Services List, APM Service Detail - Analysis Wizard now supports L4 / L7 / Both modes with HTTP/gRPC/DNS picks - Integration Hub gains L7 dependency summary + tree-summary integrations - Multi-Cluster Management: dual-agent install (Inspector Gadget L4 + Beyla L7), runtime OpenShift detection so SCCs auto-install with kubectl too - ServiceMap edge → Trace Explorer drill-down with virtual_trace_id correlation - Docs: new L7 architecture diagram, README L7 sections, 3 new screenshots
435 lines
18 KiB
Bash
Executable File
435 lines
18 KiB
Bash
Executable File
#!/bin/bash
|
|
set -e
|
|
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
echo "[DEPLOY] APPLICATION DEPLOYMENT"
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
|
|
# ==============================================================================
|
|
# Load build info from artifact
|
|
# ==============================================================================
|
|
BUILD_INFO_LOADED=false
|
|
|
|
# Try multiple possible paths for build-info file
|
|
# Note: Artifact alias is "_Flowfish-CI-Pilot" in Release Pipeline
|
|
POSSIBLE_PATHS=(
|
|
"$BUILD_INFO_FILE"
|
|
"${SYSTEM_ARTIFACTSDIRECTORY}/_Flowfish-CI-Internal/build-info/build-info.env"
|
|
"${SYSTEM_ARTIFACTSDIRECTORY}/_Flowfish-CI-Internal/drop/build-info/build-info.env"
|
|
"${SYSTEM_ARTIFACTSDIRECTORY}/_Flowfish-CI-Pilot/build-info/build-info.env"
|
|
"${SYSTEM_ARTIFACTSDIRECTORY}/_Flowfish-CI-Pilot/drop/build-info/build-info.env"
|
|
"${SYSTEM_ARTIFACTSDIRECTORY}/Flowfish-CI-Pilot/build-info/build-info.env"
|
|
"${SYSTEM_ARTIFACTSDIRECTORY}/_Flowfish-CI/build-info/build-info.env"
|
|
"${SYSTEM_ARTIFACTSDIRECTORY}/_Flowfish-CI/drop/build-info/build-info.env"
|
|
"${SYSTEM_ARTIFACTSDIRECTORY}/Flowfish-CI/build-info/build-info.env"
|
|
"${SYSTEM_ARTIFACTSDIRECTORY}/_Flowfish/build-info/build-info.env"
|
|
"${SYSTEM_ARTIFACTSDIRECTORY}/Flowfish/build-info/build-info.env"
|
|
"$(dirname "${SYSTEM_ARTIFACTSDIRECTORY:-/tmp}")/a/_Flowfish-CI-Internal/build-info/build-info.env"
|
|
"$(dirname "${SYSTEM_ARTIFACTSDIRECTORY:-/tmp}")/a/_Flowfish-CI-Internal/drop/build-info/build-info.env"
|
|
"$(dirname "${SYSTEM_ARTIFACTSDIRECTORY:-/tmp}")/a/_Flowfish-CI-Pilot/build-info/build-info.env"
|
|
"$(dirname "${SYSTEM_ARTIFACTSDIRECTORY:-/tmp}")/a/_Flowfish-CI/build-info/build-info.env"
|
|
"$(dirname "${SYSTEM_ARTIFACTSDIRECTORY:-/tmp}")/a/_Flowfish/build-info/build-info.env"
|
|
)
|
|
|
|
echo "[CHECK] Searching for build-info.env..."
|
|
for path in "${POSSIBLE_PATHS[@]}"; do
|
|
if [ -n "$path" ] && [ -f "$path" ]; then
|
|
echo "[INFO] Found build info at: $path"
|
|
source "$path"
|
|
BUILD_INFO_LOADED=true
|
|
echo "[OK] Build info loaded successfully!"
|
|
echo ""
|
|
echo "[INFO] Build Info Contents:"
|
|
cat "$path"
|
|
echo ""
|
|
break
|
|
fi
|
|
done
|
|
|
|
# Fallback: search recursively under artifact directory
|
|
if [ "$BUILD_INFO_LOADED" != "true" ] && [ -d "${SYSTEM_ARTIFACTSDIRECTORY:-}" ]; then
|
|
FOUND_FILE=$(find "${SYSTEM_ARTIFACTSDIRECTORY}" -name "build-info.env" -type f 2>/dev/null | head -1)
|
|
if [ -n "$FOUND_FILE" ]; then
|
|
echo "[INFO] Found build info via search: $FOUND_FILE"
|
|
source "$FOUND_FILE"
|
|
BUILD_INFO_LOADED=true
|
|
echo "[OK] Build info loaded successfully!"
|
|
echo ""
|
|
echo "[INFO] Build Info Contents:"
|
|
cat "$FOUND_FILE"
|
|
echo ""
|
|
fi
|
|
fi
|
|
|
|
if [ "$BUILD_INFO_LOADED" != "true" ]; then
|
|
echo "[WARN] BUILD_INFO_FILE not found in any expected location"
|
|
echo " Searched paths:"
|
|
for path in "${POSSIBLE_PATHS[@]}"; do
|
|
echo " - ${path:-'(empty)'}"
|
|
done
|
|
echo ""
|
|
echo " Listing artifact directory contents:"
|
|
ls -laR "${SYSTEM_ARTIFACTSDIRECTORY:-/tmp}" 2>/dev/null | head -80 || echo " (could not list)"
|
|
echo ""
|
|
echo " Will determine deployment based on manifest content"
|
|
fi
|
|
|
|
# Get commit hash
|
|
if [ -n "$BUILD_COMMIT" ]; then
|
|
cmtHashShort="$BUILD_COMMIT"
|
|
elif [ -n "$RELEASE_ARTIFACTS__FLOWFISH_CI_SOURCEVERSION" ]; then
|
|
cmtHashShort=$(echo $RELEASE_ARTIFACTS__FLOWFISH_CI_SOURCEVERSION | cut -c1-7)
|
|
elif [ -n "$BUILD_SOURCEVERSION" ]; then
|
|
cmtHashShort=$(echo $BUILD_SOURCEVERSION | cut -c1-7)
|
|
else
|
|
cmtHashShort="unknown"
|
|
fi
|
|
|
|
MANIFEST_DIR="${MANIFEST_DIR:-${BUILD_ARTIFACTSTAGINGDIRECTORY:-/tmp}/manifests}"
|
|
|
|
echo ""
|
|
echo "[INFO] Deployment Configuration:"
|
|
echo " Commit: $cmtHashShort"
|
|
echo " Namespace: ${OPENSHIFT_NAMESPACE}"
|
|
echo " Manifest Dir: $MANIFEST_DIR"
|
|
echo " BACKEND_BUILT: ${BACKEND_BUILT:-false}"
|
|
echo " FRONTEND_BUILT: ${FRONTEND_BUILT:-false}"
|
|
echo ""
|
|
|
|
# ==============================================================================
|
|
# OpenShift Login
|
|
# ==============================================================================
|
|
echo "[AUTH] Logging into OpenShift..."
|
|
oc login ${OPENSHIFT_API_URL} -u ${OPENSHIFT_USER} -p ${OPENSHIFT_PASSWORD} --insecure-skip-tls-verify=true
|
|
oc project ${OPENSHIFT_NAMESPACE}
|
|
echo "[OK] OpenShift login successful"
|
|
echo ""
|
|
|
|
cd $MANIFEST_DIR
|
|
|
|
# ==============================================================================
|
|
# Helper Functions
|
|
# ==============================================================================
|
|
|
|
# Get current image tag from a deployment
|
|
# Tries the given container_name first, falls back to first container
|
|
get_current_image_tag() {
|
|
local deployment_name="$1"
|
|
local container_name="$2"
|
|
|
|
# Try specific container name
|
|
local current_image=$(oc get deployment "$deployment_name" -n "${OPENSHIFT_NAMESPACE}" \
|
|
-o jsonpath="{.spec.template.spec.containers[?(@.name=='$container_name')].image}" 2>/dev/null || echo "")
|
|
|
|
# Fallback: get first container's image if specific name didn't match
|
|
if [ -z "$current_image" ]; then
|
|
current_image=$(oc get deployment "$deployment_name" -n "${OPENSHIFT_NAMESPACE}" \
|
|
-o jsonpath="{.spec.template.spec.containers[0].image}" 2>/dev/null || echo "")
|
|
fi
|
|
|
|
if [ -n "$current_image" ]; then
|
|
local tag="${current_image##*:}"
|
|
if [ -n "$tag" ] && [ "$tag" != "latest" ] && [[ ! "$tag" =~ ^NOT_ ]]; then
|
|
echo "$tag"
|
|
return 0
|
|
fi
|
|
fi
|
|
echo ""
|
|
return 1
|
|
}
|
|
|
|
# Get last known working tag from deployment history (rollout history)
|
|
get_last_working_tag() {
|
|
local deployment_name="$1"
|
|
local container_name="$2"
|
|
|
|
# Get the previous revision's image (revision before current)
|
|
local history=$(oc rollout history deployment/$deployment_name -n "${OPENSHIFT_NAMESPACE}" 2>/dev/null || echo "")
|
|
|
|
# Try to get tag from a running pod (if any pods are actually running)
|
|
local running_pod=$(oc get pods -n "${OPENSHIFT_NAMESPACE}" -l app=$deployment_name \
|
|
--field-selector=status.phase=Running -o jsonpath='{.items[0].spec.containers[0].image}' 2>/dev/null || echo "")
|
|
|
|
if [ -n "$running_pod" ]; then
|
|
local tag="${running_pod##*:}"
|
|
if [ -n "$tag" ] && [ "$tag" != "latest" ]; then
|
|
echo "$tag"
|
|
return 0
|
|
fi
|
|
fi
|
|
|
|
echo ""
|
|
return 1
|
|
}
|
|
|
|
# Verify if an image tag is usable (not in error state)
|
|
verify_image_exists() {
|
|
local deployment_name="$1"
|
|
local tag="$2"
|
|
|
|
# Check pod status for the deployment
|
|
local pod_statuses=$(oc get pods -n "${OPENSHIFT_NAMESPACE}" -l app=$deployment_name \
|
|
-o jsonpath='{range .items[*]}{.status.containerStatuses[*].state}{" "}{end}' 2>/dev/null || echo "")
|
|
|
|
# Also check waiting reasons
|
|
local waiting_reasons=$(oc get pods -n "${OPENSHIFT_NAMESPACE}" -l app=$deployment_name \
|
|
-o jsonpath='{range .items[*]}{.status.containerStatuses[*].state.waiting.reason}{" "}{end}' 2>/dev/null || echo "")
|
|
|
|
# If pods are in ImagePullBackOff or ErrImagePull, the tag is bad
|
|
if echo "$waiting_reasons" | grep -qE "ImagePullBackOff|ErrImagePull" 2>/dev/null; then
|
|
return 1
|
|
fi
|
|
|
|
# If tag contains placeholder markers, it's definitely bad
|
|
if [[ "$tag" =~ (NOT_BUILT|NEEDS_CLUSTER_TAG|unknown|IMAGE_TAG) ]]; then
|
|
return 1
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
# Check if manifest has a valid image tag (not a placeholder or error marker)
|
|
manifest_has_valid_tag() {
|
|
local manifest_file="$1"
|
|
|
|
if [ ! -f "$manifest_file" ]; then
|
|
return 1
|
|
fi
|
|
|
|
# Check for placeholder or error markers
|
|
if grep -qE "{{IMAGE_TAG}}|NOT_BUILT|:unknown|NEEDS_CLUSTER_TAG" "$manifest_file" 2>/dev/null; then
|
|
return 1
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
# Fix manifest image tag if needed (use current cluster tag for non-built services)
|
|
# $1: manifest_file $2: deployment_name $3: container_name
|
|
# $4: built_flag $5: image_short_name (e.g. "change-worker" for flowfish-change-worker)
|
|
fix_manifest_if_needed() {
|
|
local manifest_file="$1"
|
|
local deployment_name="$2"
|
|
local container_name="$3"
|
|
local built_flag="$4"
|
|
local image_short_name="${5:-$deployment_name}"
|
|
|
|
if [ ! -f "$manifest_file" ]; then
|
|
return 0
|
|
fi
|
|
|
|
# Get the tag currently in the manifest using the actual image name
|
|
local manifest_tag=$(grep -oP "flowfish-${image_short_name}:\K[^\s\"']+" "$manifest_file" 2>/dev/null | head -1 || echo "")
|
|
|
|
# If service was NOT built, we MUST use a working tag
|
|
if [ "${built_flag}" != "true" ]; then
|
|
echo " [CHECK] Service not rebuilt, finding a working image tag..."
|
|
|
|
# First, check if current cluster tag is actually working
|
|
local current_tag=$(get_current_image_tag "$deployment_name" "$container_name")
|
|
local use_tag=""
|
|
|
|
if [ -n "$current_tag" ]; then
|
|
# Verify if this tag is actually working (not in ImagePullBackOff)
|
|
if verify_image_exists "$deployment_name" "$current_tag"; then
|
|
use_tag="$current_tag"
|
|
echo " [OK] Current cluster tag '$current_tag' is valid"
|
|
else
|
|
echo " [WARN] Current cluster tag '$current_tag' is NOT working (ImagePullBackOff)"
|
|
# Try to get last working tag from running pods
|
|
local working_tag=$(get_last_working_tag "$deployment_name" "$container_name")
|
|
if [ -n "$working_tag" ]; then
|
|
use_tag="$working_tag"
|
|
echo " [RESTART] Found working tag from history: $working_tag"
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
# If no cluster tag found, this may be a first-time deployment.
|
|
# Check if the manifest already has a valid tag (set by prepare-manifests).
|
|
if [ -z "$use_tag" ]; then
|
|
if [ -n "$manifest_tag" ] && [[ ! "$manifest_tag" =~ (NOT_BUILT|unknown|IMAGE_TAG|NEEDS_CLUSTER_TAG) ]]; then
|
|
echo " [INFO] No existing deployment found. Using manifest tag '$manifest_tag' (first-time deploy)"
|
|
use_tag="$manifest_tag"
|
|
else
|
|
echo " [WARN] No working tag found for $deployment_name - SKIPPING deployment"
|
|
echo " (Service will keep running with current image)"
|
|
return 0
|
|
fi
|
|
fi
|
|
|
|
if [ "$use_tag" != "$manifest_tag" ]; then
|
|
echo " [BUILD] Fixing $manifest_file: $manifest_tag -> $use_tag"
|
|
sed -i -E "s|(image:.*flowfish-${image_short_name}:)[^[:space:]]+|\1${use_tag}|g" "$manifest_file"
|
|
fi
|
|
return 0
|
|
fi
|
|
|
|
# Check for obviously invalid tags (including NEEDS_CLUSTER_TAG from prepare-manifests)
|
|
if grep -qE "NOT_BUILT|:unknown|{{IMAGE_TAG}}|NEEDS_CLUSTER_TAG" "$manifest_file" 2>/dev/null; then
|
|
echo " [BUILD] Fixing invalid tag in $manifest_file..."
|
|
local current_tag=$(get_current_image_tag "$deployment_name" "$container_name")
|
|
if [ -n "$current_tag" ]; then
|
|
if verify_image_exists "$deployment_name" "$current_tag"; then
|
|
sed -i -E "s|(image:.*flowfish-${image_short_name}:)[^[:space:]]+|\1${current_tag}|g" "$manifest_file"
|
|
echo " -> Using cluster tag: $current_tag"
|
|
else
|
|
echo " [WARN] Cluster tag '$current_tag' not found in registry - SKIPPING"
|
|
return 0
|
|
fi
|
|
else
|
|
echo " [WARN] No valid tag found - SKIPPING deployment"
|
|
return 0
|
|
fi
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
# Deploy a service
|
|
# $1: display name $2: manifest file $3: built flag $4: deployment name
|
|
# $5: container name (defaults to $4) $6: image short name (defaults to $4)
|
|
deploy_service() {
|
|
local service_name="$1"
|
|
local manifest_file="$2"
|
|
local built_flag="$3"
|
|
local deployment_name="${4:-$service_name}"
|
|
local container_name="${5:-$deployment_name}"
|
|
local image_short_name="${6:-$deployment_name}"
|
|
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
echo "[INFO] Processing $service_name..."
|
|
|
|
if [ ! -f "$manifest_file" ]; then
|
|
echo "[WARN] Manifest not found: $manifest_file - Skipping $service_name"
|
|
return 0
|
|
fi
|
|
|
|
# CRITICAL: Fix manifest if service was not built (use cluster's current tag)
|
|
fix_manifest_if_needed "$manifest_file" "$deployment_name" "$container_name" "$built_flag" "$image_short_name"
|
|
|
|
# Verify manifest has valid tag
|
|
if ! manifest_has_valid_tag "$manifest_file"; then
|
|
echo "[WARN] $service_name has invalid image tag - Skipping to prevent deployment failure"
|
|
return 0
|
|
fi
|
|
|
|
# Extract image tag from manifest for logging
|
|
local image_tag=$(grep -oP "flowfish-${image_short_name}:\K[^\s\"']+" "$manifest_file" 2>/dev/null | head -1 || echo "unknown")
|
|
|
|
if [ "${built_flag}" = "true" ]; then
|
|
echo "[BUILD] Deploying $service_name (NEW BUILD)"
|
|
echo "[INFO] Image Tag: $image_tag"
|
|
else
|
|
echo "[RESTART] Deploying $service_name (existing image from cluster)"
|
|
echo "[INFO] Image Tag: $image_tag"
|
|
fi
|
|
|
|
# Apply manifest
|
|
oc apply -f "$manifest_file"
|
|
|
|
# Wait for rollout if it's a deployment
|
|
if grep -q "kind: Deployment" "$manifest_file" 2>/dev/null; then
|
|
echo "Waiting for $deployment_name rollout..."
|
|
if oc rollout status deployment/$deployment_name -n ${OPENSHIFT_NAMESPACE} --timeout=300s; then
|
|
echo "[OK] $service_name deployed successfully!"
|
|
else
|
|
echo "[WARN] $service_name rollout timed out or failed"
|
|
# Don't fail the entire deployment - continue with other services
|
|
fi
|
|
else
|
|
echo "[OK] $service_name applied!"
|
|
fi
|
|
|
|
echo ""
|
|
}
|
|
|
|
# ==============================================================================
|
|
# Deploy Applications
|
|
# ==============================================================================
|
|
|
|
# Deploy Backend
|
|
deploy_service "Backend" "08-backend.yaml" "${BACKEND_BUILT:-false}" "backend"
|
|
|
|
# Deploy Frontend
|
|
deploy_service "Frontend" "09-frontend.yaml" "${FRONTEND_BUILT:-false}" "frontend"
|
|
|
|
# ==============================================================================
|
|
# Deploy Microservices
|
|
# ==============================================================================
|
|
|
|
# Deploy API Gateway
|
|
deploy_service "API Gateway" "14-api-gateway.yaml" "${API_GATEWAY_BUILT:-false}" "api-gateway"
|
|
|
|
# Deploy Cluster Manager
|
|
deploy_service "Cluster Manager" "12-cluster-manager.yaml" "${CLUSTER_MANAGER_BUILT:-false}" "cluster-manager"
|
|
|
|
# Deploy Analysis Orchestrator
|
|
deploy_service "Analysis Orchestrator" "13-analysis-orchestrator.yaml" "${ANALYSIS_ORCHESTRATOR_BUILT:-false}" "analysis-orchestrator"
|
|
|
|
# Deploy Graph Writer
|
|
deploy_service "Graph Writer" "15-graph-writer.yaml" "${GRAPH_WRITER_BUILT:-false}" "graph-writer"
|
|
|
|
# Deploy Graph Query
|
|
deploy_service "Graph Query" "16-graph-query.yaml" "${GRAPH_QUERY_BUILT:-false}" "graph-query"
|
|
|
|
# Deploy Timeseries Writer
|
|
deploy_service "Timeseries Writer" "11-timeseries-writer.yaml" "${TIMESERIES_WRITER_BUILT:-false}" "timeseries-writer"
|
|
|
|
# Deploy Timeseries Query
|
|
deploy_service "Timeseries Query" "17-timeseries-query.yaml" "${TIMESERIES_QUERY_BUILT:-false}" "timeseries-query"
|
|
|
|
# Deploy Ingestion Service
|
|
deploy_service "Ingestion Service" "10-ingestion-service.yaml" "${INGESTION_SERVICE_BUILT:-false}" "ingestion-service"
|
|
|
|
# Deploy Change Detection Worker (if manifest exists)
|
|
# container name is "worker", image name is "flowfish-change-worker"
|
|
if [ -f "18-change-detection-worker.yaml" ]; then
|
|
deploy_service "Change Worker" "18-change-detection-worker.yaml" "${CHANGE_WORKER_BUILT:-false}" "change-detection-worker" "worker" "change-worker"
|
|
fi
|
|
|
|
# Deploy L7 Ingestion Service (if manifest exists)
|
|
if [ -f "22-l7-ingestion-service.yaml" ]; then
|
|
deploy_service "L7 Ingestion Service" "22-l7-ingestion-service.yaml" "${L7_INGESTION_SERVICE_BUILT:-false}" "l7-ingestion-service"
|
|
fi
|
|
|
|
# Deploy Flowfish L7 Collector (if manifest exists)
|
|
if [ -f "21-flowfish-l7-collector.yaml" ]; then
|
|
deploy_service "L7 Collector" "21-flowfish-l7-collector.yaml" "${L7_COLLECTOR_BUILT:-false}" "flowfish-l7-collector" "l7-collector" "l7-collector"
|
|
fi
|
|
|
|
# ==============================================================================
|
|
# Apply Ingress/Routes (if not already configured)
|
|
# ==============================================================================
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
echo "[NET] Checking Ingress/Routes..."
|
|
|
|
# Check if route already exists (OpenShift manages routes, not Ingress)
|
|
existing_route=$(oc get route flowfish -n ${OPENSHIFT_NAMESPACE} -o name 2>/dev/null || echo "")
|
|
if [ -n "$existing_route" ]; then
|
|
echo "[OK] Route already exists - skipping ingress apply"
|
|
oc get route flowfish -n ${OPENSHIFT_NAMESPACE} -o wide 2>/dev/null || true
|
|
else
|
|
echo "[WARN] No existing route found. Route should be created via OpenShift console or separate manifest."
|
|
echo " (11-ingress.yaml contains placeholders that need to be replaced)"
|
|
fi
|
|
echo ""
|
|
|
|
# ==============================================================================
|
|
# Deployment Summary
|
|
# ==============================================================================
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
echo "[SUMMARY] DEPLOYMENT SUMMARY"
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
|
|
echo ""
|
|
echo "[INFO] Current Deployments:"
|
|
oc get deployments -n ${OPENSHIFT_NAMESPACE} -o wide 2>/dev/null || true
|
|
|
|
echo ""
|
|
echo "[NET] Routes:"
|
|
oc get routes -n ${OPENSHIFT_NAMESPACE} 2>/dev/null || true
|
|
|
|
echo ""
|
|
echo "[DONE] Application deployment completed!"
|