Skip to content

API Usage with curl

This guide provides practical examples for using the Nextcloud Operator API with curl commands.

Authentication

# Create a service account
kubectl create serviceaccount nextcloud-api-user -n default

# Create a role with Nextcloud permissions
cat <<EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: nextcloud-user
rules:
  - apiGroups: ["k8s.bnerd.com"]
    resources: ["nextclouds"]
    verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
  - apiGroups: ["k8s.bnerd.com"]
    resources: ["nextclouds/status"]
    verbs: ["get"]
  - apiGroups: [""]
    resources: ["namespaces"]
    verbs: ["get", "list", "create"]
EOF

# Bind the role to the service account
kubectl create clusterrolebinding nextcloud-api-user \
  --clusterrole=nextcloud-user \
  --serviceaccount=default:nextcloud-api-user

# Get the service account token
TOKEN=$(kubectl create token nextcloud-api-user -n default --duration=87600h)

# Get API server URL
API_SERVER=$(kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}')

# Export for use in examples
export K8S_TOKEN="$TOKEN"
export K8S_API_SERVER="$API_SERVER"

Option 2: Using kubectl Proxy (Development/Testing)

# Start kubectl proxy in the background
kubectl proxy --port=8001 &

# Use localhost for API calls (no authentication needed with proxy)
export K8S_API_SERVER="http://localhost:8001"

Namespace Management

Create a Namespace for Tenant

TENANT_NAMESPACE="tenant-a"

curl -k -X POST "$K8S_API_SERVER/api/v1/namespaces" \
  -H "Authorization: Bearer $K8S_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "apiVersion": "v1",
  "kind": "Namespace",
  "metadata": {
    "name": "'$TENANT_NAMESPACE'",
    "labels": {
      "tenant": "tenant-a",
      "managed-by": "nextcloud-operator"
    }
  }
}'

Nextcloud CRUD Operations

Create from Pool

curl -k -X POST "$K8S_API_SERVER/apis/k8s.bnerd.com/v1alpha1/namespaces/$TENANT_NAMESPACE/nextclouds" \
  -H "Authorization: Bearer $K8S_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "apiVersion": "k8s.bnerd.com/v1alpha1",
  "kind": "Nextcloud",
  "metadata": {
    "name": "tenant-a-cloud",
    "namespace": "'$TENANT_NAMESPACE'"
  },
  "spec": {
    "poolSelector": {
      "matchLabels": {
        "profile": "basic"
      }
    },
    "ingress": {
      "host": "nc-basic.example.com"
    }
  }
}'

Create with Custom Configuration

curl -k -X POST "$K8S_API_SERVER/apis/k8s.bnerd.com/v1alpha1/namespaces/$TENANT_NAMESPACE/nextclouds" \
  -H "Authorization: Bearer $K8S_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "apiVersion": "k8s.bnerd.com/v1alpha1",
  "kind": "Nextcloud",
  "metadata": {
    "name": "tenant-a-custom-cloud"
  },
  "spec": {
    "poolSelector": {
      "matchLabels": {
        "profile": "basic"
      }
    },
    "version": "29",
    "ingress": {
      "host": "custom.tenant-a.example.com",
      "tls": {
        "enabled": true
      }
    },
    "database": {
      "managed": true,
      "type": "postgresql"
    },
    "redis": {
      "enabled": true
    }
  }
}'

List All Nextcloud Resources

curl -k -X GET "$K8S_API_SERVER/apis/k8s.bnerd.com/v1alpha1/namespaces/$TENANT_NAMESPACE/nextclouds" \
  -H "Authorization: Bearer $K8S_TOKEN" | jq '.items[] | {
  name: .metadata.name,
  phase: .status.phase,
  url: .status.url,
  admin: .status.admin
}'

Get Status

NEXTCLOUD_NAME="tenant-a-cloud"

curl -k -X GET "$K8S_API_SERVER/apis/k8s.bnerd.com/v1alpha1/namespaces/$TENANT_NAMESPACE/nextclouds/$NEXTCLOUD_NAME" \
  -H "Authorization: Bearer $K8S_TOKEN" | jq '{
  name: .metadata.name,
  phase: .status.phase,
  message: .status.message,
  url: .status.url,
  admin: .status.admin,
  instanceRef: .status.instanceRef,
  conditions: .status.conditions
}'

Get Admin Credentials

curl -k -X GET "$K8S_API_SERVER/apis/k8s.bnerd.com/v1alpha1/namespaces/$TENANT_NAMESPACE/nextclouds/$NEXTCLOUD_NAME" \
  -H "Authorization: Bearer $K8S_TOKEN" | jq '{
  url: .status.url,
  username: .status.admin.username,
  password: .status.admin.password
}'

Update (Patch)

curl -k -X PATCH "$K8S_API_SERVER/apis/k8s.bnerd.com/v1alpha1/namespaces/$TENANT_NAMESPACE/nextclouds/$NEXTCLOUD_NAME" \
  -H "Authorization: Bearer $K8S_TOKEN" \
  -H "Content-Type: application/merge-patch+json" \
  -d '{
  "spec": {
    "ingress": {
      "host": "new-hostname.tenant-a.example.com"
    }
  }
}'

Delete

curl -k -X DELETE "$K8S_API_SERVER/apis/k8s.bnerd.com/v1alpha1/namespaces/$TENANT_NAMESPACE/nextclouds/$NEXTCLOUD_NAME" \
  -H "Authorization: Bearer $K8S_TOKEN"

Status and Monitoring

Watch Resources (Stream Changes)

curl -k -X GET "$K8S_API_SERVER/apis/k8s.bnerd.com/v1alpha1/namespaces/$TENANT_NAMESPACE/nextclouds?watch=true" \
  -H "Authorization: Bearer $K8S_TOKEN" \
  -H "Accept: application/json"

Get Events

curl -k -X GET "$K8S_API_SERVER/api/v1/namespaces/$TENANT_NAMESPACE/events?fieldSelector=involvedObject.name=$NEXTCLOUD_NAME" \
  -H "Authorization: Bearer $K8S_TOKEN" | jq '.items[] | {type: .type, reason: .reason, message: .message, time: .lastTimestamp}'

List All Nextclouds (All Namespaces)

curl -k -X GET "$K8S_API_SERVER/apis/k8s.bnerd.com/v1alpha1/nextclouds" \
  -H "Authorization: Bearer $K8S_TOKEN" | jq '.items[] | {
  name: .metadata.name,
  namespace: .metadata.namespace,
  phase: .status.phase,
  url: .status.url
}'

Complete Example: Tenant Onboarding

#!/bin/bash
set -e

# Configuration
export TENANT_NAME="tenant-a"
export TENANT_NAMESPACE="tenant-a"
export NEXTCLOUD_NAME="main-cloud"
export DOMAIN="tenant-a.example.com"

echo "==> Creating namespace for $TENANT_NAME..."
curl -k -X POST "$K8S_API_SERVER/api/v1/namespaces" \
  -H "Authorization: Bearer $K8S_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "apiVersion": "v1",
  "kind": "Namespace",
  "metadata": {
    "name": "'$TENANT_NAMESPACE'",
    "labels": {
      "tenant": "'$TENANT_NAME'",
      "managed-by": "nextcloud-operator"
    }
  }
}' | jq '.metadata.name'

echo "==> Creating Nextcloud instance from pool..."
curl -k -X POST "$K8S_API_SERVER/apis/k8s.bnerd.com/v1alpha1/namespaces/$TENANT_NAMESPACE/nextclouds" \
  -H "Authorization: Bearer $K8S_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "apiVersion": "k8s.bnerd.com/v1alpha1",
  "kind": "Nextcloud",
  "metadata": {
    "name": "'$NEXTCLOUD_NAME'"
  },
  "spec": {
    "poolSelector": {"matchLabels": {"profile": "basic"}},
    "ingress": {"host": "'$DOMAIN'", "tls": {"enabled": true}}
  }
}' | jq '{name: .metadata.name, namespace: .metadata.namespace}'

echo "==> Waiting for Nextcloud to be ready..."
for i in {1..60}; do
  STATUS=$(curl -s "$K8S_API_SERVER/apis/k8s.bnerd.com/v1alpha1/namespaces/$TENANT_NAMESPACE/nextclouds/$NEXTCLOUD_NAME" \
    -H "Authorization: Bearer $K8S_TOKEN" | jq -r '.status.phase')

  if [ "$STATUS" = "Ready" ]; then
    echo "==> Nextcloud is ready!"
    break
  fi

  echo "   Status: $STATUS (attempt $i/60)"
  sleep 5
done

echo "==> Getting Nextcloud details..."
curl -k -s "$K8S_API_SERVER/apis/k8s.bnerd.com/v1alpha1/namespaces/$TENANT_NAMESPACE/nextclouds/$NEXTCLOUD_NAME" \
  -H "Authorization: Bearer $K8S_TOKEN" | jq '{
  name: .metadata.name,
  phase: .status.phase,
  url: .status.url,
  admin: .status.admin,
  instanceRef: .status.instanceRef
}'

echo "==> Onboarding complete!"

Error Handling

Common HTTP Status Codes

Code Meaning
200 Request successful
201 Resource created
404 Resource doesn't exist
409 Resource already exists
422 Invalid resource specification
403 Insufficient permissions
401 Invalid or missing authentication

Tips

  1. Use jq for JSON parsing
  2. Save tokens securely — don't hardcode in scripts
  3. Use kubectl proxy for simpler authentication during development
  4. Check events on errors for detailed information
  5. Use ?watch=true for real-time resource updates