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:
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 thefrompath.
What the Operator Does¶
For each import entry, the operator:
- Looks up
{capability-name}-import-{namespace}in the cluster - Mounts the file individually via
subPathat/data/{from}
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:
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.