Skip to content

Latest commit

 

History

History
250 lines (180 loc) · 9.95 KB

File metadata and controls

250 lines (180 loc) · 9.95 KB
name oops
description Deploy applications to Kubernetes via OOPS PaaS using the Python CLI script. Use when the user asks to deploy/release/ship an application to OOPS, create a new OOPS app, inspect a pipeline, configure an app's build/service/runtime/env-vars, or mentions oops, ZIP/Git deploys, helloworld deploys, namespace/environment/pipeline/configmap.

OOPS — Deploy applications to Kubernetes via CLI

OOPS is a Kubernetes-based PaaS. This skill teaches the agent how to use the repo-vendored Python script skills/oops/scripts/oops.py to drive the end-to-end loop: create app → configure build → bind env → set service → set runtime → trigger pipeline → wait for rollout.

Confirmation policy

This is a production deployment system. Confirm with the user before executing every write step.

Before running any write command (create, set, deploy, stop), use the AskUserQuestion tool to show the user exactly what you are about to do and wait for explicit approval. Do not batch multiple steps into a single confirmation — confirm each step individually. Only proceed after the user approves.

Example confirmation question: "Run the following command?" with the full command as the option label.

Read-only commands (ls, get, status) do not require confirmation.

When to use

The user says things like "deploy X to oops", "create a new app on oops", "show me the pipeline for web-test on oops", "ship this zip to oops" — use this skill.

When NOT to use

Prerequisites

1. Locate the script

The CLI is a single Python script (skills/oops/scripts/oops.py) with no third-party dependencies. Invoke from the repo root:

python skills/oops/scripts/oops.py <subcommand>

No compilation, no pip install, no build step needed.

2. Authentication

The script only accepts a pre-issued access token — no username/password login. Tokens look like sk-oops-xxxxxxxxxxxxxxxx and are issued by the user in the OOPS UI ("Reset Access Token").

Three ways to pass it (highest precedence first):

# A. Environment variables (recommended for one session)
export OOPS_ENDPOINT=http://localhost:8080
export OOPS_TOKEN=sk-oops-...

# B. Per-invocation flags
python skills/oops/scripts/oops.py --endpoint http://localhost:8080 --token sk-oops-... ns ls

# C. Persist to ~/.oops/config.toml
python skills/oops/scripts/oops.py auth set --endpoint http://localhost:8080 --token sk-oops-...
python skills/oops/scripts/oops.py auth status   # verify

If the user has not provided a token, stop and ask — do not guess an endpoint or invent a token.

End-to-end deploy workflow

Below is the smallest verified loop. Every step matters; skipping any one breaks the deploy in subtle ways.

Step 1 — Discover namespace, environment, domain

python skills/oops/scripts/oops.py ns ls       # list namespaces
python skills/oops/scripts/oops.py env ls      # list environments (redacted — no K8s token leaked)
python skills/oops/scripts/oops.py domain ls   # list managed domains for service exposure

Note down the target namespace (e.g. default) and environment (e.g. dev) — every later command needs them.

Step 2 — Create the application

python skills/oops/scripts/oops.py app create -n <namespace> <app-name> --description "<one-line summary>"
  • <app-name> must follow Kubernetes naming (lowercase alphanum + dashes).
  • If the app already exists the command errors out. Use python skills/oops/scripts/oops.py app get -n <ns> <app-name> first to check.

Step 3 — Configure build (most common pitfall)

ZIP source (most common)

python skills/oops/scripts/oops.py app build set -n <ns> <app> \
    --source zip \
    --dockerfile-type user \
    --dockerfile-content "$(cat path/to/Dockerfile)"

Hard constraint: --dockerfile-type user requires --dockerfile-content (inline text). --dockerfile-path alone is not enough. The Dockerfile content is injected into the build env on every deploy, so the ZIP itself does not need to contain a Dockerfile.

Git source

python skills/oops/scripts/oops.py app build set -n <ns> <app> \
    --source git \
    --repository "https://github.com/owner/repo.git" \
    --build-image "maven:3.9-eclipse-temurin-21-alpine" \
    --dockerfile-type builtin \
    --dockerfile-path "Dockerfile"

builtin reads the real Dockerfile from the repository.

Step 4 — Bind to environments

python skills/oops/scripts/oops.py app env set -n <ns> <app> --env <env-name>
# multi-env: --env dev --env prod

Without an env binding, deploy fails.

Step 5 — Configure service exposure

python skills/oops/scripts/oops.py app service set -n <ns> <app> \
    --port <container-port> \
    --env-host <env>=<host>[:https]
# example: --env-host dev=hello.example.com:https

The host should be a subdomain under a managed domain from python skills/oops/scripts/oops.py domain ls. For example if example.com is managed, set the host to hello.example.com. Each managed domain belongs to one environment (the ENVIRONMENT column) — pick a domain whose environment matches the <env> you are configuring, or the save is rejected.

Step 6 — Configure runtime (easy to forget; replicas default to 0)

python skills/oops/scripts/oops.py app runtime set -n <ns> <app> \
    --env "<env>=cpu:1/2,mem:64/128,replicas:1" \
    --health --health-path /health

Strict format: cpu:<request>/<limit>,mem:<request>/<limit>,replicas:<n>. CPU is in cores, no unit suffix (e.g. 0.1, 0.5, 1, 2). Memory is a plain number in Mi, no suffix (e.g. 64, 128) — OOPS appends Mi automatically. --health enables both liveness and readiness probes using the same path/timing. For finer control, use --liveness / --readiness plus per-probe flags such as --readiness-path, --readiness-initial-delay, --liveness-timeout. Skip this and replicas stays at 0 — the Pod never starts. This is the most common cause of "deploy succeeded but I can't reach the app".

Step 7 — Trigger the deploy

ZIP mode

# Package the source first (enter the dir, then zip its contents)
cd path/to/source && zip -r /tmp/<app>.zip .

# One shot: upload + trigger + wait for rollout
python skills/oops/scripts/oops.py deploy zip -n <ns> <app> --env <env> --file /tmp/<app>.zip --wait

--wait polls pipeline status until SUCCEEDED / BUILD_SUCCEEDED / ERROR / STOPPED. Without --wait the command returns immediately after triggering and does not surface the build result.

Git mode

python skills/oops/scripts/oops.py deploy git -n <ns> <app> --env <env> --branch main --wait

Uses the repository configured in step 3; --branch is optional.

Step 8 — Verify

python skills/oops/scripts/oops.py pipeline ls -n <ns> <app>   # recent runs
python skills/oops/scripts/oops.py app get -n <ns> <app>       # app summary

Roll back to a previous successful pipeline

python skills/oops/scripts/oops.py pipeline rollback -n <ns> <app> <pipeline-id> --wait

Rollback is a write action. Confirm with the user first, and prefer showing pipeline get output for the target pipeline before running it.

Read-only inspection commands

python skills/oops/scripts/oops.py app build get -n <ns> <app>                # build config
python skills/oops/scripts/oops.py app service get -n <ns> <app>              # service config
python skills/oops/scripts/oops.py app runtime get -n <ns> <app>              # runtime spec
python skills/oops/scripts/oops.py app env ls -n <ns> <app>                   # env bindings
python skills/oops/scripts/oops.py app config get -n <ns> <app> --env <env>   # ConfigMap entries
python skills/oops/scripts/oops.py pipeline get -n <ns> <app> <pipeline-id>   # single pipeline detail
python skills/oops/scripts/oops.py pipeline watch -n <ns> <app> <pipeline-id> # poll status until terminal

Output format

All commands default to human-readable tables. For programmatic parsing pass --json:

python skills/oops/scripts/oops.py --json app ls -n default | jq '.[].name'

--json is a global flag and must appear before the subcommand.

Troubleshooting

Symptom Cause Fix
401 Unauthorized Token wrong or unset Run auth status; re-run auth set
405 Method Not Allowed Endpoint is hidden from /openapi Use the UI for hidden operations such as application deletion.
Dockerfile content is required when type is USER Missing --dockerfile-content See the hard constraint in step 3.
Application is being deployed Previous deploy still in flight Wait; check pipeline ls; or pipeline stop.
Pipeline SUCCEEDED but Pod count is 0 Runtime spec never set (replicas=0) Run step 6, then re-deploy.
External request times out but kubectl exec … wget localhost works Ingress / DNS issue, outside OOPS Check DNS / Traefik — not in scope here.

Hard boundaries

  • Do not try to delete applications via CLI — application deletion is deliberately hidden from /openapi and must go through the UI Danger Zone. Sandbox teardown is part of the sandbox lifecycle and remains available on /openapi/sandbox/**.
  • Do not pick namespace / env / host on behalf of the user — list them with ns ls / env ls / domain ls, and ask if the user didn't say.
  • Pre-deploy checklist: build ✓ env ✓ service ✓ runtime ✓ — miss any one and the deploy either fails or the app is unreachable.
  • When zipping the source, cd into the source dir first, then zip -r /tmp/foo.zip . — don't include the outer directory or the build container won't find the Dockerfile.