feat(resource): add container infrastructure resource types
CI / benchmark-publish (pull_request) Has been skipped
CI / build (pull_request) Successful in 21s
CI / lint (pull_request) Successful in 27s
CI / helm (pull_request) Successful in 31s
CI / typecheck (pull_request) Successful in 1m9s
CI / quality (pull_request) Successful in 3m43s
CI / security (pull_request) Successful in 4m6s
CI / integration_tests (pull_request) Successful in 6m12s
CI / unit_tests (pull_request) Successful in 7m14s
CI / docker (pull_request) Successful in 2m7s
CI / coverage (pull_request) Successful in 11m52s
CI / e2e_tests (pull_request) Successful in 21m28s
CI / status-check (pull_request) Successful in 1s
CI / benchmark-regression (pull_request) Successful in 56m15s

Add 7 container infrastructure resource types per ADR-039:
container-runtime, container-image, container-mount, container-exec-env,
container-port, container-volume, container-network.

- YAML configs under examples/resource-types/
- Bootstrap registration via _resource_registry_container.py
- Updated container-instance parent_types (container-runtime, container-image)
  and child_types (container-mount, container-exec-env, container-port)
- container-runtime is top-level with auto-discovery rules (scan_depth: 1)
- container-mount/exec-env/port inherit snapshot sandbox from instance
- container-volume is user-addable with snapshot sandbox
- container-network is read-only, no sandbox
- Handler references are forward declarations (ADR-039)
- 33 Behave BDD scenarios, 4 Robot integration tests
- Updated BUILTIN_NAMES, service docstring, CHANGELOG

ISSUES CLOSED: #831
This commit is contained in:
2026-03-18 04:37:35 +00:00
committed by Forgejo
parent f03e510a11
commit 2370e19da8
18 changed files with 1006 additions and 3 deletions
+1
View File
@@ -167,3 +167,4 @@ PIPE
# Git worktrees for parallel task branches
worktrees/
*.bak
+49
View File
@@ -475,3 +475,52 @@ Sandbox: `copy_on_write`.
A hard link (link count > 1). Parent: `fs-directory`. Leaf type.
Sandbox: `copy_on_write`.
---
# Container Infrastructure Resource Types (#831)
## container-runtime
A container runtime engine (Docker, Podman, containerd, etc.).
Top-level type with no parents. Children: `container-image`,
`container-instance`, `container-volume`, `container-network`.
Auto-discovers from Docker API endpoints and docker-compose files.
User-addable. Sandbox: `none`.
## container-image
A container image identified by tag and/or digest.
Parent: `container-runtime`. Child: `container-instance`.
Auto-discovers from Dockerfiles and docker-compose files.
User-addable. Sandbox: `none`.
## container-mount
A bind mount or volume mount inside a container instance.
Parent: `container-instance`. Children: `fs-directory`, `fs-file`.
Not user-addable (auto-discovered). Sandbox: `snapshot`.
## container-exec-env
Execution environment variables and configuration inside a container.
Parent: `container-instance`. Leaf type.
Not user-addable. Sandbox: `snapshot`.
## container-port
A port mapping between host and container (e.g. 8080:80/tcp).
Parent: `container-instance`. Leaf type.
Not user-addable. Sandbox: `snapshot`.
## container-volume
A named container volume managed by the runtime engine.
Parent: `container-runtime`. Child: `fs-directory`.
User-addable. Sandbox: `snapshot`.
## container-network
A container network (bridge, host, overlay, macvlan, or none).
Parent: `container-runtime`. Leaf type.
Not user-addable. Sandbox: `none`.
@@ -0,0 +1,16 @@
# Spec reference: ADR-039, docs/specification.md ~lines 25096-25114
schema_version: "1.0"
name: container-exec-env
description: "Execution environment variables and configuration inside a container"
resource_kind: physical
sandbox_strategy: snapshot
user_addable: false
built_in: true
parent_types: ["container-instance"]
child_types: []
capabilities:
read: true
write: false
sandbox: true
checkpoint: true
handler: "cleveragents.resource.handlers.container:ContainerChildHandler"
@@ -0,0 +1,25 @@
# Spec reference: ADR-039, docs/specification.md ~lines 25096-25114
schema_version: "1.0"
name: container-image
description: "A container image identified by tag and/or digest"
resource_kind: physical
sandbox_strategy: none
user_addable: true
built_in: true
cli_args:
- name: image-ref
type: string
required: true
description: "Image reference (e.g. ubuntu:22.04, ghcr.io/org/app:latest)"
- name: digest
type: string
required: false
description: "Image digest (sha256:...)"
parent_types: ["container-runtime"]
child_types: ["container-instance"]
capabilities:
read: true
write: false
sandbox: false
checkpoint: false
handler: "cleveragents.resource.handlers.container:ContainerImageHandler"
@@ -0,0 +1,16 @@
# Spec reference: ADR-039, docs/specification.md ~lines 25096-25114
schema_version: "1.0"
name: container-mount
description: "A bind mount or volume mount inside a container instance"
resource_kind: physical
sandbox_strategy: snapshot
user_addable: false
built_in: true
parent_types: ["container-instance"]
child_types: ["fs-directory", "fs-file"]
capabilities:
read: true
write: true
sandbox: true
checkpoint: true
handler: "cleveragents.resource.handlers.container:ContainerChildHandler"
@@ -0,0 +1,16 @@
# Spec reference: ADR-039, docs/specification.md ~lines 25096-25114
schema_version: "1.0"
name: container-network
description: "A container network (bridge, host, overlay, macvlan, or none)"
resource_kind: physical
sandbox_strategy: none
user_addable: false
built_in: true
parent_types: ["container-runtime"]
child_types: []
capabilities:
read: true
write: false
sandbox: false
checkpoint: false
handler: "cleveragents.resource.handlers.container:ContainerNetworkHandler"
@@ -0,0 +1,16 @@
# Spec reference: ADR-039, docs/specification.md ~lines 25096-25114
schema_version: "1.0"
name: container-port
description: "A port mapping between host and container (e.g. 8080:80/tcp)"
resource_kind: physical
sandbox_strategy: snapshot
user_addable: false
built_in: true
parent_types: ["container-instance"]
child_types: []
capabilities:
read: true
write: false
sandbox: true
checkpoint: true
handler: "cleveragents.resource.handlers.container:ContainerChildHandler"
@@ -0,0 +1,41 @@
# Spec reference: ADR-039, docs/specification.md ~lines 25096-25114
schema_version: "1.0"
name: container-runtime
description: "A container runtime engine (Docker, Podman, containerd, etc.)"
resource_kind: physical
sandbox_strategy: none
user_addable: true
built_in: true
cli_args:
- name: engine-type
type: string
required: true
description: "Container engine type (docker, podman, containerd, lxc, lxd, cri-o, other)"
- name: socket-path
type: path
required: false
description: "Path to the container engine socket"
- name: endpoint
type: string
required: false
description: "Remote endpoint URL for the engine API"
parent_types: []
child_types: ["container-image", "container-instance", "container-volume", "container-network"]
auto_discovery:
enabled: true
scan_depth: 1
rules:
- type: container-image
pattern: "images/*"
- type: container-instance
pattern: "containers/*"
- type: container-volume
pattern: "volumes/*"
- type: container-network
pattern: "networks/*"
capabilities:
read: true
write: false
sandbox: false
checkpoint: false
handler: "cleveragents.resource.handlers.container:ContainerRuntimeHandler"
@@ -0,0 +1,25 @@
# Spec reference: ADR-039, docs/specification.md ~lines 25096-25114
schema_version: "1.0"
name: container-volume
description: "A named container volume managed by the runtime engine"
resource_kind: physical
sandbox_strategy: snapshot
user_addable: true
built_in: true
cli_args:
- name: volume-name
type: string
required: true
description: "Name of the volume"
- name: driver
type: string
required: false
description: "Volume driver (e.g. local, nfs)"
parent_types: ["container-runtime"]
child_types: ["fs-directory"]
capabilities:
read: true
write: true
sandbox: true
checkpoint: true
handler: "cleveragents.resource.handlers.container:ContainerVolumeHandler"
@@ -0,0 +1,129 @@
@container-infra
Feature: Container infrastructure resource types
Verifies that the 7 container infrastructure resource types
(container-runtime, container-image, container-mount, container-exec-env,
container-port, container-volume, container-network) are correctly
defined, registered, and have proper parent/child relationships.
# YAML schema loading
Scenario Outline: Container infra YAML validates for container_infra
Given the built-in "<type_name>" YAML for container_infra
When I load the YAML via from_yaml_file for container_infra
Then the container_infra schema should be valid
And the container_infra schema name should be "<type_name>"
And the container_infra schema resource_kind should be "physical"
Examples:
| type_name |
| container-runtime |
| container-image |
| container-mount |
| container-exec-env |
| container-port |
| container-volume |
| container-network |
# ── Domain model creation ───────────────────────────────
Scenario Outline: Container infra YAML loads as domain model for container_infra
Given the built-in "<type_name>" YAML for container_infra
When I load the YAML as a ResourceTypeSpec for container_infra
Then the container_infra domain model should be valid
And the container_infra domain model name should be "<type_name>"
And the container_infra domain model resource_kind should be physical
Examples:
| type_name |
| container-runtime |
| container-image |
| container-mount |
| container-exec-env |
| container-port |
| container-volume |
| container-network |
# ── Parent/child relationships ──────────────────────────
Scenario: container-runtime is top-level with children for container_infra
Given the built-in "container-runtime" YAML for container_infra
When I load the YAML as a ResourceTypeSpec for container_infra
Then the container_infra spec should have empty parent_types
And the container_infra child_types should contain "container-image"
And the container_infra child_types should contain "container-instance"
And the container_infra child_types should contain "container-volume"
And the container_infra child_types should contain "container-network"
Scenario: container-image parent is runtime for container_infra
Given the built-in "container-image" YAML for container_infra
When I load the YAML as a ResourceTypeSpec for container_infra
Then the container_infra parent_types should contain "container-runtime"
And the container_infra child_types should contain "container-instance"
Scenario: container-mount parent is instance for container_infra
Given the built-in "container-mount" YAML for container_infra
When I load the YAML as a ResourceTypeSpec for container_infra
Then the container_infra parent_types should contain "container-instance"
And the container_infra child_types should contain "fs-directory"
And the container_infra child_types should contain "fs-file"
Scenario: container-volume parent is runtime for container_infra
Given the built-in "container-volume" YAML for container_infra
When I load the YAML as a ResourceTypeSpec for container_infra
Then the container_infra parent_types should contain "container-runtime"
And the container_infra child_types should contain "fs-directory"
# ── User-addable flags ──────────────────────────────────
Scenario Outline: Container infra user_addable flags for container_infra
Given the built-in "<type_name>" YAML for container_infra
When I load the YAML as a ResourceTypeSpec for container_infra
Then the container_infra user_addable should be <addable>
Examples:
| type_name | addable |
| container-runtime | true |
| container-image | true |
| container-mount | false |
| container-exec-env | false |
| container-port | false |
| container-volume | true |
| container-network | false |
# ── BUILTIN_NAMES registration ──────────────────────────
Scenario Outline: Container infra types in BUILTIN_NAMES for container_infra
Then BUILTIN_NAMES should contain "<type_name>" for container_infra
Examples:
| type_name |
| container-runtime |
| container-image |
| container-mount |
| container-exec-env |
| container-port |
| container-volume |
| container-network |
# ── Bootstrap registration ─────────────────────────────
Scenario: All 7 container infra types in BUILTIN_TYPES for container_infra
Given the bootstrap builtin type definitions for container_infra
Then BUILTIN_TYPES should contain "container-runtime" for container_infra
And BUILTIN_TYPES should contain "container-image" for container_infra
And BUILTIN_TYPES should contain "container-mount" for container_infra
And BUILTIN_TYPES should contain "container-exec-env" for container_infra
And BUILTIN_TYPES should contain "container-port" for container_infra
And BUILTIN_TYPES should contain "container-volume" for container_infra
And BUILTIN_TYPES should contain "container-network" for container_infra
# ── Coverage: verify CONTAINER_INFRA_TYPES module directly ──
Scenario: CONTAINER_INFRA_TYPES has exactly 7 entries for container_infra
Then CONTAINER_INFRA_TYPES should have 7 entries for container_infra
Scenario: Each container infra type has handler reference for container_infra
Then every CONTAINER_INFRA_TYPES entry should have a handler for container_infra
Scenario: container-runtime has auto-discovery rules for container_infra
Then container-runtime in CONTAINER_INFRA_TYPES should have auto_discovery for container_infra
@@ -0,0 +1,191 @@
"""Step definitions for resource_type_container_infra.feature.
Tests container infrastructure resource types: container-runtime,
container-image, container-mount, container-exec-env, container-port,
container-volume, container-network.
"""
from __future__ import annotations
from pathlib import Path
from typing import Any
import yaml
from behave import given, then, when
from cleveragents.application.services._resource_registry_container import (
CONTAINER_INFRA_TYPES,
)
from cleveragents.application.services._resource_registry_data import (
BUILTIN_TYPES,
)
from cleveragents.domain.models.core.resource_type import (
ResourceKind,
ResourceTypeSpec,
)
from cleveragents.resource.schema import ResourceTypeConfigSchema
_EXAMPLES_DIR = (
Path(__file__).resolve().parent.parent.parent / "examples" / "resource-types"
)
# ── Given steps ──────────────────────────────────────────
@given('the built-in "{type_name}" YAML for container_infra')
def step_builtin_yaml(context: object, type_name: str) -> None:
path = _EXAMPLES_DIR / f"{type_name}.yaml"
assert path.exists(), f"YAML not found: {path}"
context.ci_yaml_path = path
@given("the bootstrap builtin type definitions for container_infra")
def step_bootstrap_defs(context: object) -> None:
context.ci_builtin_defs = list(BUILTIN_TYPES)
# ── When steps ───────────────────────────────────────────
@when("I load the YAML via from_yaml_file for container_infra")
def step_load_yaml(context: object) -> None:
path: Path = context.ci_yaml_path
schema = ResourceTypeConfigSchema.from_yaml_file(path)
context.ci_schema = schema
@when("I load the YAML as a ResourceTypeSpec for container_infra")
def step_load_domain(context: object) -> None:
path: Path = context.ci_yaml_path
raw: dict[str, Any] = yaml.safe_load(path.read_text(encoding="utf-8"))
spec = ResourceTypeSpec.from_config(raw)
context.ci_spec = spec
# ── Then steps: schema ───────────────────────────────────
@then("the container_infra schema should be valid")
def step_schema_valid(context: object) -> None:
schema = context.ci_schema
assert schema is not None
assert isinstance(schema, ResourceTypeConfigSchema)
@then('the container_infra schema name should be "{name}"')
def step_schema_name(context: object, name: str) -> None:
assert context.ci_schema.name == name
@then('the container_infra schema resource_kind should be "{kind}"')
def step_schema_kind(context: object, kind: str) -> None:
assert context.ci_schema.resource_kind == kind
# ── Then steps: domain model ─────────────────────────────
@then("the container_infra domain model should be valid")
def step_domain_valid(context: object) -> None:
spec = context.ci_spec
assert spec is not None
assert isinstance(spec, ResourceTypeSpec)
@then('the container_infra domain model name should be "{name}"')
def step_domain_name(context: object, name: str) -> None:
assert context.ci_spec.name == name
@then("the container_infra domain model resource_kind should be physical")
def step_domain_kind_physical(context: object) -> None:
assert context.ci_spec.resource_kind == ResourceKind.PHYSICAL
# ── Then steps: parent/child ─────────────────────────────
@then("the container_infra spec should have empty parent_types")
def step_empty_parents(context: object) -> None:
spec = context.ci_spec
assert spec.parent_types == [], f"Expected empty, got {spec.parent_types}"
@then('the container_infra parent_types should contain "{name}"')
def step_parent_contains(context: object, name: str) -> None:
spec = context.ci_spec
assert name in spec.parent_types, (
f"'{name}' not in parent_types: {spec.parent_types}"
)
@then('the container_infra child_types should contain "{name}"')
def step_child_contains(context: object, name: str) -> None:
spec = context.ci_spec
assert name in spec.child_types, f"'{name}' not in child_types: {spec.child_types}"
# ── Then steps: user_addable ─────────────────────────────
@then("the container_infra user_addable should be {addable}")
def step_user_addable(context: object, addable: str) -> None:
spec = context.ci_spec
expected = addable.lower() == "true"
assert spec.user_addable is expected, (
f"Expected user_addable={expected}, got {spec.user_addable}"
)
# ── Then steps: BUILTIN_NAMES ────────────────────────────
@then('BUILTIN_NAMES should contain "{name}" for container_infra')
def step_builtin_names(context: object, name: str) -> None:
assert name in ResourceTypeSpec.BUILTIN_NAMES, f"'{name}' not in BUILTIN_NAMES"
# ── Then steps: BUILTIN_TYPES ────────────────────────────
@then('BUILTIN_TYPES should contain "{name}" for container_infra')
def step_builtin_types(context: object, name: str) -> None:
defs: list[dict[str, Any]] = context.ci_builtin_defs
names = [d["name"] for d in defs]
assert name in names, f"'{name}' not in BUILTIN_TYPES: {names}"
# ── Coverage: CONTAINER_INFRA_TYPES direct access ────────
@then("CONTAINER_INFRA_TYPES should have 7 entries for container_infra")
def step_infra_count(context: object) -> None:
assert len(CONTAINER_INFRA_TYPES) == 7, (
f"Expected 7, got {len(CONTAINER_INFRA_TYPES)}"
)
@then("every CONTAINER_INFRA_TYPES entry should have a handler for container_infra")
def step_all_have_handler(context: object) -> None:
for entry in CONTAINER_INFRA_TYPES:
assert entry.get("handler") is not None, f"{entry['name']} has no handler"
@then(
"container-runtime in CONTAINER_INFRA_TYPES should have auto_discovery"
" for container_infra"
)
def step_runtime_auto_discovery(context: object) -> None:
runtime = next(d for d in CONTAINER_INFRA_TYPES if d["name"] == "container-runtime")
ad = runtime.get("auto_discovery")
assert ad is not None, "container-runtime missing auto_discovery"
assert ad.get("enabled") is True
assert ad.get("scan_depth") == 1
rules = ad.get("rules", [])
assert len(rules) >= 4, f"Expected >=4 rules, got {len(rules)}"
# Verify Dockerfile/docker-compose patterns
patterns = [r["pattern"] for r in rules]
assert any("docker-compose" in p for p in patterns), (
f"Missing docker-compose pattern: {patterns}"
)
@@ -0,0 +1,129 @@
"""Helper script for container infrastructure resource type Robot tests.
Usage:
python helper_resource_type_container_infra.py check-registration
python helper_resource_type_container_infra.py check-instance-children
python helper_resource_type_container_infra.py check-hierarchy
python helper_resource_type_container_infra.py check-yaml-loading
"""
from __future__ import annotations
import sys
from pathlib import Path
_SRC = str(Path(__file__).resolve().parents[1] / "src")
if _SRC not in sys.path:
sys.path.insert(0, _SRC)
from cleveragents.application.services._resource_registry_data import ( # noqa: E402
BUILTIN_TYPES,
)
from cleveragents.domain.models.core.resource_type import ( # noqa: E402
ResourceTypeSpec,
)
from cleveragents.resource.schema import ( # noqa: E402
ResourceTypeConfigSchema,
)
_EXAMPLES = Path(__file__).resolve().parents[1] / "examples" / "resource-types"
_CONTAINER_INFRA_NAMES = [
"container-runtime",
"container-image",
"container-mount",
"container-exec-env",
"container-port",
"container-volume",
"container-network",
]
def cmd_check_registration() -> None:
"""Verify all 7 container infra types in BUILTIN_TYPES."""
names = [d["name"] for d in BUILTIN_TYPES]
for cn in _CONTAINER_INFRA_NAMES:
assert cn in names, f"{cn} not in BUILTIN_TYPES: {names}"
assert cn in ResourceTypeSpec.BUILTIN_NAMES, f"{cn} not in BUILTIN_NAMES"
entry = next(d for d in BUILTIN_TYPES if d["name"] == cn)
assert entry["resource_kind"] == "physical"
assert entry["built_in"] is True
print("check-registration-ok")
def cmd_check_instance_children() -> None:
"""Verify container-instance has updated children."""
entry = next(d for d in BUILTIN_TYPES if d["name"] == "container-instance")
for child in ("container-mount", "container-exec-env", "container-port"):
assert child in entry["child_types"], (
f"{child} not in container-instance children: {entry['child_types']}"
)
for parent in ("container-runtime", "container-image"):
assert parent in entry["parent_types"], (
f"{parent} not in container-instance parents: {entry['parent_types']}"
)
print("check-instance-children-ok")
def cmd_check_hierarchy() -> None:
"""Verify runtime -> image -> instance DAG."""
by_name = {d["name"]: d for d in BUILTIN_TYPES}
runtime = by_name["container-runtime"]
assert "container-image" in runtime["child_types"]
assert "container-instance" in runtime["child_types"]
assert "container-volume" in runtime["child_types"]
assert "container-network" in runtime["child_types"]
image = by_name["container-image"]
assert "container-runtime" in image["parent_types"]
assert "container-instance" in image["child_types"]
mount = by_name["container-mount"]
assert "container-instance" in mount["parent_types"]
assert "fs-directory" in mount["child_types"]
volume = by_name["container-volume"]
assert "container-runtime" in volume["parent_types"]
assert "fs-directory" in volume["child_types"]
network = by_name["container-network"]
assert "container-runtime" in network["parent_types"]
assert network["child_types"] == []
print("check-hierarchy-ok")
def cmd_check_yaml_loading() -> None:
"""Load all 7 YAML configs and verify schema."""
for cn in _CONTAINER_INFRA_NAMES:
path = _EXAMPLES / f"{cn}.yaml"
assert path.exists(), f"Missing YAML: {path}"
schema = ResourceTypeConfigSchema.from_yaml_file(path)
assert schema.name == cn
assert schema.resource_kind == "physical"
spec = ResourceTypeSpec.from_config(schema.model_dump())
assert spec.name == cn
print("check-yaml-loading-ok")
_COMMANDS = {
"check-registration": cmd_check_registration,
"check-instance-children": cmd_check_instance_children,
"check-hierarchy": cmd_check_hierarchy,
"check-yaml-loading": cmd_check_yaml_loading,
}
def main() -> None:
if len(sys.argv) < 2 or sys.argv[1] not in _COMMANDS:
print(
f"Usage: {sys.argv[0]} <{'|'.join(_COMMANDS)}>",
file=sys.stderr,
)
sys.exit(1)
_COMMANDS[sys.argv[1]]()
if __name__ == "__main__":
main()
+47
View File
@@ -0,0 +1,47 @@
*** Settings ***
Documentation Integration tests for container infrastructure resource types.
... Verifies all 7 container infra types are registered,
... have correct parent/child relationships, and load from YAML.
Resource ${CURDIR}/common.resource
Suite Setup Setup Test Environment
Suite Teardown Cleanup Test Environment
*** Variables ***
${HELPER} ${CURDIR}/helper_resource_type_container_infra.py
*** Test Cases ***
All Container Infra Types In BUILTIN_TYPES
[Documentation] Verify all 7 container infra types in BUILTIN_TYPES
[Tags] container registration smoke
${result}= Run Process ${PYTHON} ${HELPER} check-registration
... timeout=60s on_timeout=kill
Should Be Equal As Integers ${result.rc} 0
... Registration check failed: ${result.stderr}
Should Contain ${result.stdout} check-registration-ok
Container Instance Updated With Children
[Documentation] Verify container-instance has mount/exec-env/port children
[Tags] container parent-child
${result}= Run Process ${PYTHON} ${HELPER} check-instance-children
... timeout=60s on_timeout=kill
Should Be Equal As Integers ${result.rc} 0
... Instance children check failed: ${result.stderr}
Should Contain ${result.stdout} check-instance-children-ok
Container Runtime Hierarchy
[Documentation] Verify runtime -> image -> instance DAG hierarchy
[Tags] container hierarchy
${result}= Run Process ${PYTHON} ${HELPER} check-hierarchy
... timeout=60s on_timeout=kill
Should Be Equal As Integers ${result.rc} 0
... Hierarchy check failed: ${result.stderr}
Should Contain ${result.stdout} check-hierarchy-ok
Container YAML Schema Loading
[Documentation] Load all 7 container YAML configs and verify schema
[Tags] container yaml schema
${result}= Run Process ${PYTHON} ${HELPER} check-yaml-loading
... timeout=60s on_timeout=kill
Should Be Equal As Integers ${result.rc} 0
... YAML loading failed: ${result.stderr}
Should Contain ${result.stdout} check-yaml-loading-ok
@@ -0,0 +1,272 @@
"""Container infrastructure resource type definitions for the Resource Registry.
Contains the 7 built-in container infrastructure type entries
(container-runtime, container-image, container-mount, container-exec-env,
container-port, container-volume, container-network) that are appended
to ``BUILTIN_TYPES`` in ``_resource_registry_data``.
Defined per ADR-039: Container Resource Types and the specification's
built-in handler table (~line 25096).
.. note::
This is an **internal** module (``_``-prefixed). External code
should import ``BUILTIN_TYPES`` from ``_resource_registry_data``
instead.
"""
from __future__ import annotations
from typing import Any
__all__ = ["CONTAINER_INFRA_TYPES"]
# Handler references per spec line 25096-25114. These handler classes
# do not exist yet — the references are forward declarations that will
# be resolved when the container runtime integration is implemented.
_RUNTIME_HANDLER = "cleveragents.resource.handlers.container:ContainerRuntimeHandler"
_IMAGE_HANDLER = "cleveragents.resource.handlers.container:ContainerImageHandler"
_CHILD_HANDLER = "cleveragents.resource.handlers.container:ContainerChildHandler"
_VOLUME_HANDLER = "cleveragents.resource.handlers.container:ContainerVolumeHandler"
_NETWORK_HANDLER = "cleveragents.resource.handlers.container:ContainerNetworkHandler"
CONTAINER_INFRA_TYPES: list[dict[str, Any]] = [
# ------------------------------------------------------------------
# container-runtime: top-level runtime (Docker, Podman, etc.)
# ------------------------------------------------------------------
{
"name": "container-runtime",
"description": (
"A container runtime engine (Docker, Podman, containerd, etc.)."
),
"resource_kind": "physical",
"sandbox_strategy": "none",
"user_addable": True,
"built_in": True,
"cli_args": [
{
"name": "engine-type",
"type": "string",
"required": True,
"description": (
"Container engine type "
"(docker, podman, containerd, lxc, lxd, cri-o, other)."
),
},
{
"name": "socket-path",
"type": "path",
"required": False,
"description": "Path to the container engine socket.",
"default": None,
},
{
"name": "endpoint",
"type": "string",
"required": False,
"description": "Remote endpoint URL for the engine API.",
"default": None,
},
],
"parent_types": [],
"child_types": [
"container-image",
"container-instance",
"container-volume",
"container-network",
],
"auto_discovery": {
"enabled": True,
"scan_depth": 1,
"rules": [
{"type": "container-image", "pattern": "images/*"},
{"type": "container-instance", "pattern": "containers/*"},
{"type": "container-volume", "pattern": "volumes/*"},
{"type": "container-network", "pattern": "networks/*"},
{"type": "container-image", "pattern": "docker-compose.yml"},
{"type": "container-image", "pattern": "docker-compose.yaml"},
{"type": "container-image", "pattern": "compose.yml"},
{"type": "container-image", "pattern": "compose.yaml"},
],
},
"handler": _RUNTIME_HANDLER,
"capabilities": {
"read": True,
"write": False,
"sandbox": False,
"checkpoint": False,
},
},
# ------------------------------------------------------------------
# container-image: immutable container image (tag + digest)
# ------------------------------------------------------------------
{
"name": "container-image",
"description": ("A container image identified by tag and/or digest."),
"resource_kind": "physical",
"sandbox_strategy": "none",
"user_addable": True,
"built_in": True,
"cli_args": [
{
"name": "image-ref",
"type": "string",
"required": True,
"description": (
"Image reference (e.g. ubuntu:22.04, ghcr.io/org/app:latest)."
),
},
{
"name": "digest",
"type": "string",
"required": False,
"description": "Image digest (sha256:...).",
"default": None,
},
],
"parent_types": ["container-runtime"],
"child_types": ["container-instance"],
"auto_discovery": {
"enabled": True,
"scan_depth": 1,
"rules": [
{"type": "container-image", "pattern": "Dockerfile"},
{"type": "container-image", "pattern": "Dockerfile.*"},
{"type": "container-image", "pattern": "*.dockerfile"},
],
},
"handler": _IMAGE_HANDLER,
"capabilities": {
"read": True,
"write": False,
"sandbox": False,
"checkpoint": False,
},
},
# ------------------------------------------------------------------
# container-mount: bind mount or volume mount inside a container
# ------------------------------------------------------------------
{
"name": "container-mount",
"description": ("A bind mount or volume mount inside a container instance."),
"resource_kind": "physical",
"sandbox_strategy": "snapshot",
"user_addable": False,
"built_in": True,
"cli_args": [],
"parent_types": ["container-instance"],
"child_types": ["fs-directory", "fs-file"],
"handler": _CHILD_HANDLER,
"capabilities": {
"read": True,
"write": True,
"sandbox": True,
"checkpoint": True,
},
},
# ------------------------------------------------------------------
# container-exec-env: execution environment inside a container
# ------------------------------------------------------------------
{
"name": "container-exec-env",
"description": (
"Execution environment variables and configuration "
"inside a container instance."
),
"resource_kind": "physical",
"sandbox_strategy": "snapshot",
"user_addable": False,
"built_in": True,
"cli_args": [],
"parent_types": ["container-instance"],
"child_types": [],
"handler": _CHILD_HANDLER,
"capabilities": {
"read": True,
"write": False,
"sandbox": True,
"checkpoint": True,
},
},
# ------------------------------------------------------------------
# container-port: port mapping on a container
# ------------------------------------------------------------------
{
"name": "container-port",
"description": (
"A port mapping between host and container (e.g. 8080:80/tcp)."
),
"resource_kind": "physical",
"sandbox_strategy": "snapshot",
"user_addable": False,
"built_in": True,
"cli_args": [],
"parent_types": ["container-instance"],
"child_types": [],
"handler": _CHILD_HANDLER,
"capabilities": {
"read": True,
"write": False,
"sandbox": True,
"checkpoint": True,
},
},
# ------------------------------------------------------------------
# container-volume: named Docker/Podman volume
# ------------------------------------------------------------------
{
"name": "container-volume",
"description": ("A named container volume managed by the runtime engine."),
"resource_kind": "physical",
"sandbox_strategy": "snapshot",
"user_addable": True,
"built_in": True,
"cli_args": [
{
"name": "volume-name",
"type": "string",
"required": True,
"description": "Name of the volume.",
},
{
"name": "driver",
"type": "string",
"required": False,
"description": "Volume driver (e.g. local, nfs).",
"default": None,
},
],
"parent_types": ["container-runtime"],
"child_types": ["fs-directory"],
"handler": _VOLUME_HANDLER,
"capabilities": {
"read": True,
"write": True,
"sandbox": True,
"checkpoint": True,
},
},
# ------------------------------------------------------------------
# container-network: container network configuration
# ------------------------------------------------------------------
{
"name": "container-network",
"description": (
"A container network (bridge, host, overlay, macvlan, or none)."
),
"resource_kind": "physical",
"sandbox_strategy": "none",
"user_addable": False,
"built_in": True,
"cli_args": [],
"parent_types": ["container-runtime"],
"child_types": [],
"handler": _NETWORK_HANDLER,
"capabilities": {
"read": True,
"write": False,
"sandbox": False,
"checkpoint": False,
},
},
]
@@ -22,6 +22,9 @@ from cleveragents.application.services._resource_registry_cloud import (
CLOUD_BASE_TYPES,
GCP_AZURE_TYPES,
)
from cleveragents.application.services._resource_registry_container import (
CONTAINER_INFRA_TYPES,
)
from cleveragents.application.services._resource_registry_lsp import (
LSP_RESOURCE_TYPES,
)
@@ -177,14 +180,23 @@ _GIT_FS_CONTAINER_TYPES: list[dict[str, Any]] = [
"default": None,
},
],
"parent_types": ["git-checkout", "fs-directory"],
"child_types": [],
"parent_types": [
"container-runtime",
"container-image",
"git-checkout",
"fs-directory",
],
"child_types": [
"container-mount",
"container-exec-env",
"container-port",
],
"handler": ("cleveragents.resource.handlers.devcontainer:DevcontainerHandler"),
"capabilities": {
"read": True,
"write": True,
"sandbox": True,
"checkpoint": False,
"checkpoint": True,
},
},
{
@@ -263,6 +275,8 @@ BUILTIN_TYPES: list[dict[str, Any]] = [
*CLOUD_BASE_TYPES,
*AWS_TYPES,
*GCP_AZURE_TYPES,
# Container infrastructure types -- see _resource_registry_container.py (#831)
*CONTAINER_INFRA_TYPES,
*DATABASE_TYPE_DEFS,
# Virtual core resource types -- see _resource_registry_virtual.py (#329)
*VIRTUAL_CORE_TYPES,
@@ -16,6 +16,13 @@ development workflows. Built-in types are **unnamespaced** (no
|-------------------|----------|------------------|--------------------------------|
| ``git-checkout`` | physical | ``git_worktree`` | Git repository checkout |
| ``fs-directory`` | physical | ``copy_on_write``| Filesystem directory |
| ``container-runtime``| physical | ``none`` | Container runtime engine |
| ``container-image``| physical | ``none`` | Container image (tag + digest) |
| ``container-mount``| physical | ``snapshot`` | Bind/volume mount in container |
| ``container-exec-env``| physical | ``snapshot`` | Container exec environment |
| ``container-port`` | physical | ``snapshot`` | Container port mapping |
| ``container-volume``| physical | ``snapshot`` | Named container volume |
| ``container-network``| physical | ``none`` | Container network |
| ``file`` | virtual | ``none`` | Cross-layer file identity |
| ``directory`` | virtual | ``none`` | Cross-layer directory identity |
| ``commit`` | virtual | ``none`` | Cross-repo commit identity |
@@ -24,7 +24,14 @@ BUILTIN_TYPE_NAMES: frozenset[str] = frozenset(
"fs-directory",
"fs-mount",
"fs-file",
"container-exec-env",
"container-image",
"container-instance",
"container-mount",
"container-network",
"container-port",
"container-runtime",
"container-volume",
"devcontainer-instance",
"devcontainer-file",
"postgres",
@@ -174,6 +174,8 @@ class ResourceTypeSpec(BaseModel):
# Built-in resource type names (unnamespaced).
# The actual frozenset lives in _resource_type_validation to keep
# this module under the 500-line CONTRIBUTING limit.
# Built-in resource type names — sourced from _resource_type_validation.py
# to keep this module under the 500-line CONTRIBUTING limit.
BUILTIN_NAMES: ClassVar[frozenset[str]] = BUILTIN_TYPE_NAMES
name: str = Field(