Skip to content

Import Consumes

The import pattern lets you split large capability specs by extracting consumes definitions into separate files. The engine loads them at startup — the operator mounts them as individual files into the pod.


When to Use Import

Instead of declaring all consumed APIs inline:

# everything in one file — gets large
capability:
  consumes:
    - namespace: registry
      type: http
      baseUri: "https://..."
      resources: [ ... 50 lines ... ]
    - namespace: legacy
      type: http
      baseUri: "https://..."
      resources: [ ... 40 lines ... ]

Split into separate files:

# main spec — clean and focused
capability:
  consumes:
    - import: registry
      from: "./shared/registry-consumes.yaml"
    - import: legacy
      from: "./shared/legacy-consumes.yaml"

Import File Format

Each imported file contains a standard ikanos consumes definition:

# registry-consumes.yaml
ikanos: 1.0.0-alpha4
consumes:
- namespace: registry
  type: http
  baseUri: "https://api.example.com"
  authentication:
    type: bearer
    token: ''
  inputParameters:
    Registry-Version:
      in: header
      value: ''
  resources:
    ships:
      path: /ships
      operations:
        list-ships:
          method: GET
          inputParameters:
            status:
              in: query
    ship:
      path: /ships/
      operations:
        get-ship:
          method: GET
          inputParameters:
            imo_number:
              in: path

ConfigMap Convention

For each import entry, the operator expects a ConfigMap named:

{capability-name}-import-{import-namespace}

The ConfigMap key must match the filename from the from path:

from ConfigMap name ConfigMap key
./shared/registry-consumes.yaml {name}-import-registry registry-consumes.yaml
./shared/legacy-consumes.yaml {name}-import-legacy legacy-consumes.yaml
./shared/step6-registry-consumes.yaml {name}-import-registry step6-registry-consumes.yaml

Creating Import ConfigMaps

kubectl create configmap my-capability-import-registry \
  --from-file=registry-consumes.yaml=path/to/registry-consumes.yaml \
  -n default

kubectl create configmap my-capability-import-legacy \
  --from-file=legacy-consumes.yaml=path/to/legacy-consumes.yaml \
  -n default

The --from-file=<key>=<file> syntax sets the ConfigMap key explicitly. The key must match the filename in the from path.


What the Operator Does

For each import entry, the operator:

  1. Looks up {capability-name}-import-{namespace} in the cluster
  2. Mounts the file individually via subPath at /data/{from}
from: "./shared/registry-consumes.yaml"
  → mounted at: /data/shared/registry-consumes.yaml

Using subPath means multiple imports sharing the same parent directory (/data/shared/) do not conflict — each file gets its own VolumeMount.

# Verify the mounts on the generated Deployment
kubectl get deployment my-capability -n default \
  -o jsonpath='{.spec.template.spec.containers[0].volumeMounts}' \
  | python3 -m json.tool

Expected output includes entries like:

{
  "mountPath": "/data/shared/registry-consumes.yaml",
  "name": "import-registry",
  "readOnly": true,
  "subPath": "registry-consumes.yaml"
}

Error: ConfigMap Not Found

If the import ConfigMap does not exist, the operator throws a reconcile error:

Import ConfigMap 'my-capability-import-registry' not found in namespace 'default'.
Create it with:
kubectl create configmap my-capability-import-registry \
  --from-file=registry-consumes.yaml=<path-to-file> -n default

Create all import ConfigMaps before applying the Capability CR.


Complete Example

Directory structure:

my-capability/
├── spec.yaml
└── shared/
    ├── registry-consumes.yaml
    └── legacy-consumes.yaml

spec.yaml:

ikanos: "1.0.0-alpha4"
info:
  display: Shipyard
  description: "MCP capability for fleet management"
  labels:
    naftiko.io/tier: standard
binds:
  - namespace: "registry-env"
    location: "file:///./shared/secrets.yaml"
    keys:
      REGISTRY_TOKEN: "registry-bearer-token"
      REGISTRY_VERSION: "registry-api-version"
capability:
  consumes:
    - import: registry
      from: "./shared/registry-consumes.yaml"
    - import: legacy
      from: "./shared/legacy-consumes.yaml"
  exposes:
    - type: mcp
      address: "0.0.0.0"
      port: 3001
      namespace: shipyard-tools
      tools:
        list-ships:
          description: "List ships in the fleet"
          call: registry.list-ships
    - type: control
      address: "0.0.0.0"
      port: 9090
      observability:
        enabled: true
        metrics:
          local:
            enabled: true

Create ConfigMaps:

kubectl create configmap shipyard-spec \
  --from-file=capability.yaml=my-capability/spec.yaml \
  -n default

kubectl create configmap shipyard-import-registry \
  --from-file=registry-consumes.yaml=my-capability/shared/registry-consumes.yaml \
  -n default

kubectl create configmap shipyard-import-legacy \
  --from-file=legacy-consumes.yaml=my-capability/shared/legacy-consumes.yaml \
  -n default

Apply the Capability CR:

kubectl apply -f - <<EOF
apiVersion: naftiko.io/v1alpha3
kind: Capability
metadata:
  name: shipyard
  namespace: default
  labels:
    naftiko.io/tier: standard
spec:
  specRef:
    configMap: shipyard-spec
EOF

Verify imports are mounted:

kubectl wait pod -l naftiko.io/capability=shipyard \
  --for=condition=Ready --timeout=60s -n default

kubectl logs -l naftiko.io/capability=shipyard -n default | head -5
# → Reading configuration from: /data/capability.yaml
# → Capability started successfully.

In a GitOps Repository

When managing capabilities via ArgoCD, include the import ConfigMaps alongside the Capability CR and use sync-wave annotations to ensure they exist before the CR is applied:

capabilities/
└── shipyard/
    ├── configmap.yaml           ← sync-wave: "0" — ikanos spec
    ├── import-registry.yaml     ← sync-wave: "0" — registry consumes
    ├── import-legacy.yaml       ← sync-wave: "0" — legacy consumes
    ├── bind-secret.yaml         ← sync-wave: "0" — bind secrets
    └── capability.yaml          ← sync-wave: "1" — Capability CR

See Secrets & Binds for the bind secret pattern.