Hi there Agent, read the instructions below.

Spin up a simple Kubernetes cluster on Atlas Cloud (our CloudStack at https://sky.runatlas.is/client/api) using the cmk (CloudMonkey) CLI.

---

STEP 0 — CREDENTIALS

The CloudStack API needs CLOUDSTACK_API_KEY and CLOUDSTACK_SECRET_KEY. Check both are set:

  printenv CLOUDSTACK_API_KEY | wc -c
  printenv CLOUDSTACK_SECRET_KEY | wc -c

Both should return > 1. If either is zero or missing, stop and ask the user to write a .env file in the working directory:

  CLOUDSTACK_API_KEY=<key>
  CLOUDSTACK_SECRET_KEY=<secret>

Do not proceed until both are confirmed non-empty. Never print or echo the values.

Important: export in the user's terminal does not propagate to your Bash subshell. Every command that needs credentials must begin with:

  set -a && source .env && set +a &&

---

STEP 1 — INSTALL AND CONFIGURE cmk

Check if cmk is installed (which cmk). If not, detect architecture (uname -m) and download the correct binary from the latest GitHub release at https://github.com/apache/cloudstack-cloudmonkey/releases:

  arm64  -> cmk.darwin.arm64
  x86_64 -> cmk.darwin.x86-64

Install:

  curl -sL https://github.com/apache/cloudstack-cloudmonkey/releases/download/6.5.0/cmk.darwin.arm64 \
    -o /usr/local/bin/cmk
  chmod +x /usr/local/bin/cmk

Configure (source .env first so the keys are in scope):

  cmk set url https://sky.runatlas.is/client/api
  cmk set apikey "$CLOUDSTACK_API_KEY"
  cmk set secretkey "$CLOUDSTACK_SECRET_KEY"
  cmk set output json
  cmk sync

Verify with: cmk list zones
Expected: zone named "is1".

---

STEP 2 — DISCOVER RESOURCES

  cmk list zones
  cmk list kubernetessupportedversions zoneid=<zone-id>
  cmk list serviceofferings
  cmk list sshkeypairs

Expected on Atlas Cloud:

  Zone:              is1
  Kubernetes:        Kubernetes 1.33.1 Calico (only version available)
                     Minimum per node: 2 vCPU / 2 GB RAM
  Service offerings: Atlas.a4 (1 vCPU / 4 GB)
                     Atlas.a5 (2 vCPU / 8 GB)  <-- use this as default
                     Atlas.a6 (4 vCPU / 16 GB)
                     Atlas.a7 (8 vCPU / 32 GB)

Pick up the IDs for the zone, Kubernetes version, and Atlas.a5 service offering from the output.

For SSH key pairs: if one or more exist, use the first one and note its name. If none
exist, stop and ask the user to create and register one themselves:

  ssh-keygen -t ed25519 -f ./atlas-k8s-key -N "" -C "atlas-k8s"
  PUBKEY=$(cat ./atlas-k8s-key.pub)
  cmk register sshkeypair name=atlas-k8s-key publickey="$PUBKEY"

Ask them to come back with the key pair name once done, then continue.

---

STEP 3 — CREATE THE CLUSTER

  cmk create kubernetescluster \
    name=atlas-k8s \
    zoneid=<zone-id> \
    kubernetesversionid=<k8s-version-id> \
    serviceofferingid=<atlas-a5-id> \
    controlnodes=1 \
    size=2 \
    keypair=<keypair-name> \
    description="Simple CKS cluster on Atlas Cloud"

CRITICAL: Do not pass networkid. Let CKS auto-create its own isolated network.
Specifying an existing user network causes a 530 error ("Kubernetes service has not
been configured properly") even when the network exists and CKS is otherwise fully
functional. Omitting networkid is the correct approach.

CRITICAL: Do not run this command in the background or retry it if it appears to hang.
The API call is synchronous and returns only after all nodes are provisioned and Running.
Running it twice creates two clusters. Wait for the full JSON response.

A successful response includes the cluster id, endpoint (API server URL), keypair field
set to the key name, and all three VMs listed with state=Running.

---

STEP 4 — FETCH KUBECONFIG

  cmk get kubernetesclusterconfig id=<cluster-id> \
    | python3 -c "import json,sys; print(json.load(sys.stdin)['clusterconfig']['configdata'], end='')" \
    > ./kubeconfig
  chmod 0600 ./kubeconfig

---

STEP 5 — VERIFY NODES

  kubectl --kubeconfig ./kubeconfig get nodes -o wide

All three nodes (1 control plane + 2 workers) should show Ready.

---

REPORT BACK

Cluster name, cluster ID, API server endpoint, kubeconfig path, kubectl get nodes output