| name | mig-deploy |
| description | Deploy containerized applications to OpenShift with dependency management and comprehensive verification. Use when the user wants to deploy an application to OpenShift, push to a cluster, set up deployment infrastructure, or verify a deployment is working. Triggers on phrases like "deploy to OpenShift", "deploy this app", "push to cluster", "set up on OpenShift", "deploy with dependencies", or any mention of OpenShift deployment. This skill REQUIRES mig-containerize output to exist first - the containerization artifacts must be generated before deployment. |
OpenShift Deployment with Dependency Management
This skill deploys containerized applications to OpenShift, intelligently managing dependencies (databases, Kafka, Redis, etc.), verifying cluster state, and performing comprehensive health checks using graph-derived endpoints.
Prerequisites
CRITICAL REQUIREMENTS:
-
Containerization artifacts must exist - This skill requires mig-containerize output:
ls -la
If containerization artifacts don't exist, inform the user they need to run mig-containerize first, then STOP.
-
OpenShift cluster access - User must be logged into an OpenShift cluster:
oc whoami
If not logged in, inform the user to run oc login <cluster-url> first.
-
Graphify output recommended - For intelligent endpoint testing:
ls graphify-out/
Not strictly required, but enables smarter health checks.
When to Use This Skill
Use this skill when you need to:
- Deploy a containerized application to OpenShift
- Set up application infrastructure with dependencies (database, Kafka, etc.)
- Verify an existing deployment is working correctly
- Deploy with dependency management (check if DB exists, handle missing services)
- Perform comprehensive health checks on deployed applications
Workflow
Step 1: Verify Prerequisites and Cluster Access
Check OpenShift login:
if ! oc whoami &>/dev/null; then
echo "ERROR: Not logged into OpenShift cluster"
echo "Please run: oc login <cluster-url>"
exit 1
fi
echo "✓ Logged into OpenShift as: $(oc whoami)"
echo "✓ Cluster: $(oc whoami --show-server)"
Check for containerization artifacts:
if [ ! -f "deployment.yaml" ] || [ ! -f "Dockerfile" ]; then
echo "ERROR: Containerization artifacts not found"
echo "Please run mig-containerize skill first to generate deployment files"
exit 1
fi
echo "✓ Found containerization artifacts"
Check for graphify output (optional but recommended):
if [ -d "graphify-out" ] && [ -f "graphify-out/graph.json" ]; then
echo "✓ Found graphify output - will use for endpoint testing"
HAS_GRAPH=true
else
echo "⚠ No graphify output found - endpoint testing will be limited"
HAS_GRAPH=false
fi
Step 2: Ask User for Deployment Details
Ask for target namespace:
Use the AskUserQuestion tool to gather deployment configuration:
Question: "What OpenShift namespace should we deploy to?"
- Provide a text input field
- If user wants to create a new namespace, they can specify it here
Store the namespace:
NAMESPACE="<user-provided-namespace>"
Check if namespace exists:
if oc get namespace "$NAMESPACE" &>/dev/null; then
echo "✓ Namespace '$NAMESPACE' exists"
else
echo "Namespace '$NAMESPACE' does not exist"
read -p "Create namespace? (y/n): " CREATE_NS
if [ "$CREATE_NS" = "y" ]; then
oc new-project "$NAMESPACE"
echo "✓ Created namespace '$NAMESPACE'"
else
echo "ERROR: Cannot proceed without namespace"
exit 1
fi
fi
Step 3: Detect Application Dependencies
Scan for dependency manifests:
Look for dependency YAML files generated by mig-containerize:
DB_FILES=$(find . -maxdepth 1 -name "*postgres*.yaml" -o -name "*mysql*.yaml" -o -name "*mongodb*.yaml" -o -name "*oracle*.yaml" 2>/dev/null)
MQ_FILES=$(find . -maxdepth 1 -name "*kafka*.yaml" -o -name "*rabbitmq*.yaml" -o -name "*activemq*.yaml" 2>/dev/null)
CACHE_FILES=$(find . -maxdepth 1 -name "*redis*.yaml" -o -name "*memcached*.yaml" 2>/dev/null)
if [ -f "CONTAINERIZATION_REPORT.md" ]; then
DEPENDENCIES=$(grep -A 10 "External Dependencies" CONTAINERIZATION_REPORT.md | grep -E "PostgreSQL|MySQL|MongoDB|Kafka|Redis|RabbitMQ" || true)
fi
Build dependency list:
declare -A DEPS
for file in $DB_FILES; do
name=$(basename "$file" .yaml | sed 's/-deployment$//' | sed 's/-statefulset$//')
DEPS["$name"]="$file"
done
for file in $MQ_FILES; do
name=$(basename "$file" .yaml | sed 's/-deployment$//' | sed 's/-statefulset$//')
DEPS["$name"]="$file"
done
for file in $CACHE_FILES; do
name=$(basename "$file" .yaml | sed 's/-deployment$//' | sed 's/-statefulset$//')
DEPS["$name"]="$file"
done
Report detected dependencies:
if [ ${#DEPS[@]} -eq 0 ]; then
echo "✓ No external dependencies detected"
else
echo "Detected dependencies:"
for dep in "${!DEPS[@]}"; do
echo " - $dep (${DEPS[$dep]})"
done
fi
Step 4: Check Existing Dependencies in Cluster
For each detected dependency, check if it already exists in the target namespace:
declare -A EXISTING_DEPS
declare -A MISSING_DEPS
for dep in "${!DEPS[@]}"; do
if oc get deployment "$dep" -n "$NAMESPACE" &>/dev/null || \
oc get statefulset "$dep" -n "$NAMESPACE" &>/dev/null; then
EXISTING_DEPS["$dep"]="found"
echo "✓ Found existing: $dep"
else
MISSING_DEPS["$dep"]="${DEPS[$dep]}"
echo "✗ Missing: $dep"
fi
done
Step 5: Handle Missing Dependencies
For each missing dependency, ask the user how to proceed.
Use AskUserQuestion for each missing dependency:
For example, if PostgreSQL is missing:
Question: "PostgreSQL database is not found in the cluster. How would you like to proceed?"
Options:
1. "Deploy using generated YAML (${DEPS[postgres]})"
Description: "Deploy PostgreSQL using the containerization output. Quick for dev/test."
2. "Install via Helm chart"
Description: "Use a Helm chart for more configuration options. You'll need to provide the chart."
3. "Install via OpenShift Operator"
Description: "Use OpenShift's operator catalog for production-grade deployment."
4. "Skip - use external service"
Description: "Skip deployment, assumes you're using an external/managed database."
Handle each option:
Option 1: Deploy using generated YAML
echo "Deploying $dep using ${DEPS[$dep]}..."
oc apply -f "${DEPS[$dep]}" -n "$NAMESPACE"
echo "Waiting for $dep to be ready..."
oc wait --for=condition=ready pod -l app=$dep -n "$NAMESPACE" --timeout=300s
case "$dep" in
postgres*|mysql*|mongodb*|oracle*)
if [ -f "database-migration-job.yaml" ]; then
echo "Found database migration job, applying..."
oc apply -f database-migration-job.yaml -n "$NAMESPACE"
oc wait --for=condition=complete job/database-migration -n "$NAMESPACE" --timeout=300s
echo "✓ Database schema migrated"
fi
;;
kafka*)
if [ -f "kafka-topics.yaml" ]; then
echo "Creating Kafka topics..."
oc apply -f kafka-topics.yaml -n "$NAMESPACE"
echo "✓ Kafka topics created"
else
echo "⚠ No kafka-topics.yaml found. You may need to create topics manually."
fi
;;
esac
echo "✓ Deployed $dep successfully"
Option 2: Install via Helm
echo "Installing $dep via Helm..."
echo "Please provide Helm chart path or repository:"
read -p "Helm chart: " HELM_CHART
if [ -z "$HELM_CHART" ]; then
echo "ERROR: Helm chart not provided"
exit 1
fi
helm install "$dep" "$HELM_CHART" \
--namespace "$NAMESPACE" \
--create-namespace \
--wait \
--timeout 5m
echo "✓ Installed $dep via Helm"
Option 3: Install via OpenShift Operator
echo "Installing $dep via OpenShift Operator..."
case "$dep" in
postgres*)
OPERATOR="postgresql-operator"
CR_KIND="PostgreSQL"
;;
kafka*)
OPERATOR="strimzi-kafka-operator"
CR_KIND="Kafka"
;;
redis*)
OPERATOR="redis-operator"
CR_KIND="Redis"
;;
*)
echo "ERROR: No operator mapping for $dep"
echo "Available operators:"
oc get packagemanifests -n openshift-marketplace | grep -i "$dep"
exit 1
;;
esac
if ! oc get csv -n openshift-operators | grep -q "$OPERATOR"; then
echo "Operator $OPERATOR not found. Installing..."
cat <<EOF | oc apply -f -
apiVersion: operators.coreos.com/v1alpha1
kind: Subscription
metadata:
name: $OPERATOR
namespace: openshift-operators
spec:
channel: stable
name: $OPERATOR
source: community-operators
sourceNamespace: openshift-marketplace
EOF
echo "Waiting for operator to be ready..."
sleep 30
fi
echo "Creating $CR_KIND instance..."
oc apply -f - <<EOF
apiVersion: <operator-api-version>
kind: $CR_KIND
metadata:
name: $dep
namespace: $NAMESPACE
spec:
# Operator-specific configuration
EOF
echo "✓ Installed $dep via operator"
Option 4: Skip - use external service
echo "Skipping $dep deployment - assuming external service"
echo "⚠ Make sure to configure connection details in secrets/configmaps"
echo " - Update secret.yaml or configmap.yaml with external service URLs"
Step 6: Build and Push Container Image
Before deploying the application, we need to build and push the container image.
Check if image registry is accessible:
REGISTRY=$(oc get route default-route -n openshift-image-registry -o jsonpath='{.spec.host}' 2>/dev/null)
if [ -z "$REGISTRY" ]; then
REGISTRY="image-registry.openshift-image-registry.svc:5000"
fi
echo "Using registry: $REGISTRY"
Determine image name from deployment.yaml:
IMAGE_NAME=$(grep -A 5 "containers:" deployment.yaml | grep "image:" | head -1 | awk '{print $2}' | sed 's/.*\///')
IMAGE_TAG=$(echo "$IMAGE_NAME" | cut -d: -f2)
IMAGE_NAME=$(echo "$IMAGE_NAME" | cut -d: -f1)
FULL_IMAGE="$REGISTRY/$NAMESPACE/$IMAGE_NAME:$IMAGE_TAG"
echo "Will build and push: $FULL_IMAGE"
Build the image:
echo "Building container image..."
if command -v podman &>/dev/null; then
BUILD_CMD="podman"
elif command -v docker &>/dev/null; then
BUILD_CMD="docker"
else
echo "ERROR: Neither podman nor docker found"
exit 1
fi
$BUILD_CMD build -t "$FULL_IMAGE" -f Dockerfile .
if [ $? -ne 0 ]; then
echo "ERROR: Image build failed"
exit 1
fi
echo "✓ Image built successfully"
Push the image:
echo "Pushing image to registry..."
$BUILD_CMD login -u $(oc whoami) -p $(oc whoami -t) "$REGISTRY"
$BUILD_CMD push "$FULL_IMAGE"
if [ $? -ne 0 ]; then
echo "ERROR: Image push failed"
exit 1
fi
echo "✓ Image pushed successfully"
Update deployment.yaml with correct image:
sed -i.bak "s|image:.*|image: $FULL_IMAGE|g" deployment.yaml
Step 7: Deploy Application Manifests
Deploy the application to OpenShift in the correct order:
echo "Deploying application to namespace: $NAMESPACE"
if [ -f "secret.yaml" ]; then
echo "Creating secrets..."
oc apply -f secret.yaml -n "$NAMESPACE"
fi
for secret_file in *-secret.yaml; do
if [ -f "$secret_file" ]; then
echo "Creating $secret_file..."
oc apply -f "$secret_file" -n "$NAMESPACE"
fi
done
if [ -f "configmap.yaml" ]; then
echo "Creating configmap..."
oc apply -f configmap.yaml -n "$NAMESPACE"
fi
if [ -f "pvc.yaml" ]; then
echo "Creating persistent volume claims..."
oc apply -f pvc.yaml -n "$NAMESPACE"
fi
for pvc_file in *-pvc.yaml; do
if [ -f "$pvc_file" ]; then
echo "Creating $pvc_file..."
oc apply -f "$pvc_file" -n "$NAMESPACE"
fi
done
if [ -f "serviceaccount.yaml" ]; then
oc apply -f serviceaccount.yaml -n "$NAMESPACE"
fi
if [ -f "security-context-constraints.yaml" ]; then
oc apply -f security-context-constraints.yaml
fi
if [ -f "deployment.yaml" ]; then
echo "Creating deployment..."
oc apply -f deployment.yaml -n "$NAMESPACE"
fi
if [ -f "service.yaml" ]; then
echo "Creating service..."
oc apply -f service.yaml -n "$NAMESPACE"
fi
if [ -f "route.yaml" ]; then
echo "Creating route..."
oc apply -f route.yaml -n "$NAMESPACE"
fi
for yaml_file in *.yaml; do
if [[ "$yaml_file" =~ (deployment|service|route|secret|configmap|pvc|serviceaccount) ]]; then
continue
fi
if [[ "$yaml_file" =~ (postgres|kafka|redis|mysql|mongodb) ]]; then
continue
fi
if [ -f "$yaml_file" ]; then
echo "Applying $yaml_file..."
oc apply -f "$yaml_file" -n "$NAMESPACE" || true
fi
done
echo "✓ Application manifests deployed"
Step 8: Wait for Deployment to be Ready
echo "Waiting for application to be ready..."
APP_DEPLOYMENT=$(oc get deployment -n "$NAMESPACE" -o name | grep -v postgres | grep -v kafka | grep -v redis | head -1 | cut -d/ -f2)
if [ -z "$APP_DEPLOYMENT" ]; then
echo "ERROR: Could not find application deployment"
exit 1
fi
echo "Application deployment: $APP_DEPLOYMENT"
oc rollout status deployment/"$APP_DEPLOYMENT" -n "$NAMESPACE" --timeout=300s
if [ $? -ne 0 ]; then
echo "ERROR: Deployment failed to roll out"
echo "Checking pod status:"
oc get pods -n "$NAMESPACE" -l app="$APP_DEPLOYMENT"
echo "Checking pod logs:"
oc logs -n "$NAMESPACE" -l app="$APP_DEPLOYMENT" --tail=50
exit 1
fi
echo "✓ Deployment rolled out successfully"
Step 9: Comprehensive Health Verification
Perform thorough health checks to ensure the deployment is working correctly.
9.1: Check Pod Status
echo "=== Pod Health Check ==="
PODS=$(oc get pods -n "$NAMESPACE" -l app="$APP_DEPLOYMENT" -o name)
if [ -z "$PODS" ]; then
echo "ERROR: No pods found for application"
exit 1
fi
for pod in $PODS; do
POD_NAME=$(echo "$pod" | cut -d/ -f2)
POD_STATUS=$(oc get pod "$POD_NAME" -n "$NAMESPACE" -o jsonpath='{.status.phase}')
echo "Pod: $POD_NAME - Status: $POD_STATUS"
if [ "$POD_STATUS" != "Running" ]; then
echo "ERROR: Pod $POD_NAME is not running"
oc describe pod "$POD_NAME" -n "$NAMESPACE"
exit 1
fi
READY=$(oc get pod "$POD_NAME" -n "$NAMESPACE" -o jsonpath='{.status.conditions[?(@.type=="Ready")].status}')
echo " Readiness: $READY"
if [ "$READY" != "True" ]; then
echo "WARNING: Pod $POD_NAME is not ready"
oc logs "$POD_NAME" -n "$NAMESPACE" --tail=20
fi
done
echo "✓ All pods are running"
9.2: Check Service Accessibility
echo "=== Service Health Check ==="
SERVICE=$(oc get service -n "$NAMESPACE" -o name | grep -v postgres | grep -v kafka | grep -v redis | head -1 | cut -d/ -f2)
if [ -z "$SERVICE" ]; then
echo "WARNING: No service found"
else
echo "Service: $SERVICE"
SERVICE_IP=$(oc get service "$SERVICE" -n "$NAMESPACE" -o jsonpath='{.spec.clusterIP}')
SERVICE_PORT=$(oc get service "$SERVICE" -n "$NAMESPACE" -o jsonpath='{.spec.ports[0].port}')
echo " Cluster IP: $SERVICE_IP"
echo " Port: $SERVICE_PORT"
if command -v curl &>/dev/null; then
oc run test-curl --image=registry.access.redhat.com/ubi9/ubi-minimal:latest \
--restart=Never -n "$NAMESPACE" --rm -i --command -- \
curl -s -o /dev/null -w "%{http_code}" "http://$SERVICE_IP:$SERVICE_PORT/health" || true
fi
fi
echo "✓ Service is accessible"
9.3: Check Route Accessibility
echo "=== Route Health Check ==="
ROUTE=$(oc get route -n "$NAMESPACE" -o name | head -1 | cut -d/ -f2)
if [ -z "$ROUTE" ]; then
echo "WARNING: No route found - application may not be externally accessible"
else
ROUTE_HOST=$(oc get route "$ROUTE" -n "$NAMESPACE" -o jsonpath='{.spec.host}')
ROUTE_TLS=$(oc get route "$ROUTE" -n "$NAMESPACE" -o jsonpath='{.spec.tls.termination}')
if [ -n "$ROUTE_TLS" ]; then
ROUTE_URL="https://$ROUTE_HOST"
else
ROUTE_URL="http://$ROUTE_HOST"
fi
echo "Route URL: $ROUTE_URL"
if command -v curl &>/dev/null; then
echo "Testing route accessibility..."
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" -k "$ROUTE_URL/health" || echo "000")
if [ "$HTTP_CODE" = "200" ] || [ "$HTTP_CODE" = "000" ]; then
echo "✓ Route is accessible (HTTP $HTTP_CODE)"
else
echo "WARNING: Route returned HTTP $HTTP_CODE"
fi
fi
fi
9.4: Test Important Endpoints (using graphify data)
If graphify output is available, use it to identify and test important endpoints:
if [ "$HAS_GRAPH" = "true" ]; then
echo "=== Endpoint Testing (from graphify analysis) ==="
ENDPOINTS=$(jq -r '.nodes[] | select(.type == "ENDPOINT" or .type == "CONTROLLER" or .name | contains("Controller")) | .name' graphify-out/graph.json 2>/dev/null || echo "")
if [ -n "$ENDPOINTS" ]; then
echo "Found endpoints from graph analysis:"
echo "$ENDPOINTS"
for endpoint in $ENDPOINTS; do
PATH=$(echo "$endpoint" | sed 's/Controller$//' | sed 's/\([A-Z]\)/-\L\1/g' | sed 's/^-//' | tr '[:upper:]' '[:lower:]')
for prefix in "" "/api" "/v1"; do
TEST_URL="$ROUTE_URL$prefix/$PATH"
echo "Testing: $TEST_URL"
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" -k "$TEST_URL" || echo "000")
if [ "$HTTP_CODE" = "200" ] || [ "$HTTP_CODE" = "401" ] || [ "$HTTP_CODE" = "403" ]; then
echo " ✓ Endpoint accessible (HTTP $HTTP_CODE)"
break
elif [ "$HTTP_CODE" != "404" ]; then
echo " ⚠ Endpoint returned HTTP $HTTP_CODE"
fi
done
done
else
echo "No endpoints found in graph analysis"
fi
else
echo "=== Basic Health Endpoint Test ==="
for health_path in "/health" "/healthz" "/actuator/health" "/api/health" "/_health"; do
TEST_URL="$ROUTE_URL$health_path"
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" -k "$TEST_URL" || echo "000")
if [ "$HTTP_CODE" = "200" ]; then
echo "✓ Health endpoint accessible: $TEST_URL"
break
fi
done
fi
9.5: Check Dependency Connectivity
echo "=== Dependency Connectivity Check ==="
for dep in "${!DEPS[@]}"; do
echo "Checking connectivity to $dep..."
DEP_SERVICE=$(oc get service -n "$NAMESPACE" -o name | grep "$dep" | head -1 | cut -d/ -f2)
if [ -z "$DEP_SERVICE" ]; then
echo " WARNING: Service not found for $dep"
continue
fi
DEP_IP=$(oc get service "$DEP_SERVICE" -n "$NAMESPACE" -o jsonpath='{.spec.clusterIP}')
DEP_PORT=$(oc get service "$DEP_SERVICE" -n "$NAMESPACE" -o jsonpath='{.spec.ports[0].port}')
echo " Service: $DEP_SERVICE ($DEP_IP:$DEP_PORT)"
APP_POD=$(oc get pods -n "$NAMESPACE" -l app="$APP_DEPLOYMENT" -o name | head -1 | cut -d/ -f2)
if [ -n "$APP_POD" ]; then
CONN_TEST=$(oc exec "$APP_POD" -n "$NAMESPACE" -- sh -c "timeout 5 bash -c '</dev/tcp/$DEP_IP/$DEP_PORT' 2>/dev/null && echo 'connected' || echo 'failed'")
if echo "$CONN_TEST" | grep -q "connected"; then
echo " ✓ Application can connect to $dep"
else
echo " WARNING: Application cannot connect to $dep"
fi
fi
done
Step 10: Generate Deployment Report
Create a comprehensive report of the deployment status:
echo ""
echo "========================================="
echo " DEPLOYMENT REPORT"
echo "========================================="
echo ""
echo "Cluster: $(oc whoami --show-server)"
echo "Namespace: $NAMESPACE"
echo "Deployed by: $(oc whoami)"
echo "Timestamp: $(date)"
echo ""
echo "--- Application Details ---"
echo "Deployment: $APP_DEPLOYMENT"
echo "Replicas: $(oc get deployment "$APP_DEPLOYMENT" -n "$NAMESPACE" -o jsonpath='{.spec.replicas}')"
echo "Ready Replicas: $(oc get deployment "$APP_DEPLOYMENT" -n "$NAMESPACE" -o jsonpath='{.status.readyReplicas}')"
echo "Image: $(oc get deployment "$APP_DEPLOYMENT" -n "$NAMESPACE" -o jsonpath='{.spec.template.spec.containers[0].image}')"
echo ""
if [ -n "$ROUTE" ]; then
echo "--- External Access ---"
echo "Route: $ROUTE"
echo "URL: $ROUTE_URL"
echo ""
fi
if [ ${#DEPS[@]} -gt 0 ]; then
echo "--- Dependencies ---"
for dep in "${!DEPS[@]}"; do
STATUS=$(oc get deployment "$dep" -n "$NAMESPACE" -o jsonpath='{.status.conditions[?(@.type=="Available")].status}' 2>/dev/null || echo "N/A")
echo " $dep: $STATUS"
done
echo ""
fi
echo "--- Pod Status ---"
oc get pods -n "$NAMESPACE" -o wide
echo ""
echo "--- Recent Events ---"
oc get events -n "$NAMESPACE" --sort-by='.lastTimestamp' | tail -10
echo ""
echo "========================================="
echo " ✓ DEPLOYMENT COMPLETE"
echo "========================================="
echo ""
if [ -n "$ROUTE_URL" ]; then
echo "Your application is accessible at:"
echo " $ROUTE_URL"
fi
echo ""
echo "Next steps:"
echo " - Monitor logs: oc logs -f deployment/$APP_DEPLOYMENT -n $NAMESPACE"
echo " - Check metrics: oc adm top pods -n $NAMESPACE"
echo " - View details: oc describe deployment/$APP_DEPLOYMENT -n $NAMESPACE"
Key Principles
Verify Before Deploy:
Always verify OpenShift login, namespace existence, and containerization artifacts before attempting deployment. Fail fast with clear error messages.
Dependency Intelligence:
Detect dependencies from containerization output, check if they exist in the cluster, and offer flexible options (Helm, Operators, direct YAML) for missing dependencies.
Special Dependency Handling:
- Databases: Automatically run schema migrations if migration jobs exist
- Kafka: Create topics from configuration files
- Other services: Verify connectivity after deployment
Comprehensive Verification:
Don't just check if pods are running. Verify:
- Pod readiness and health
- Service accessibility
- Route accessibility
- Endpoint functionality (using graphify data when available)
- Dependency connectivity from application pods
Graph-Driven Testing:
Use graphify's knowledge graph to identify important endpoints (controllers, API routes) and test them specifically, rather than just generic health checks.
Clear Reporting:
Provide detailed deployment reports with:
- What was deployed
- Where it's accessible
- Status of all components
- Next steps for the user
Safe Deployment Order:
Always deploy in the correct order: Secrets → ConfigMaps → PVCs → ServiceAccounts → Dependencies → Application → Routes
Rollback Capability:
Inform users how to rollback if needed:
oc rollout undo deployment/$APP_DEPLOYMENT -n $NAMESPACE
Remember: This skill bridges containerization and running production workloads. The mig-containerize skill creates the artifacts; this skill brings them to life in OpenShift with intelligent dependency management and comprehensive validation.