Catalog Item Schema
Summary
This ADR defines the structure for Catalog Items in the DCM Service Catalog.
Motivation
Catalog Items wrap service specifications with validation rules and defaults, enabling administrators to create curated offerings. The design is both provider-agnostic and service type-agnostic — Catalog Items work with any service type defined in Service Type Definition
Goals
- Define the structure for Catalog Items
- Maintain independence between service types while applying consistent design patterns
- Add validation rule
- Enable administrators to create curated offerings for users
- Design catalog schemas as service type and provider-agnostic and service type-agnostic specifications that Service Providers can translate to their native platform formats
Non-Goals
- Defining the service schemas themselves (see Service Type Definition )
Proposal
The catalog schema acts as a translation layer between what the DCM users want (abstract service specifications) and what providers deliver (platform-specific implementations).
Implementation Details/Notes/Constraints
Catalog Item
A catalog item wraps a service specification with validation rules and defaults. Administrators create catalog offerings like “Small Dev VM” or “Production Database” that users can request without knowing the underlying details.
apiVersion: v1alpha1
kind: CatalogItem
metadata:
name: production-postgres
spec:
serviceType: database
fields:
- path: "engine"
default: "postgresql"
- path: "version"
editable: true
default: "15"
validationSchema: { enum: ["14", "15", "16"] }
- path: "resources.cpu"
editable: true
default: 4
validationSchema: { minimum: 2, maximum: 16 }
- path: "resources.memory"
editable: true
default: "16GB"See catalog-item-schema.yaml for complete schema definition.
CatalogItem components
| Field | Required | Type | Description |
|---|---|---|---|
| apiVersion | Yes | string | CatalogItem schema version (e.g., v1alpha1). Enables CatalogItem schema evolution |
| serviceType | Yes | string | Type of service (e.g., vm, container, database, cluster) |
| fields | Yes | array | List of field configurations (see below) |
Each field in the fields array has:
| Field | Required | Type | Default | Description |
|---|---|---|---|---|
| path | Yes | string | - | Field path in service schema (e.g., vcpu.count) |
| displayName | No | string | - | Human-readable label for UI. If not set, derived from the path |
| editable | No | boolean | false | Whether users can modify this field |
| default | No | any | - | Default value for this field |
| validationSchema | No | object | - | JSON Schema rules (only applies if editable) |
| dependsOn | No | object | - | Conditional options derived from another field (single option when read-only) |
The dependsOn object specifies conditional options for this field based on another
field’s value. It has:
| Field | Required | Type | Description |
|---|---|---|---|
| path | Yes | string | JSON path of the field this one depends on (e.g., region) |
| allowedValues | Yes | object | If the field at path equals key K, this field’s options are the array at |
allowedValues[K]. |
When dependsOn is set, the field’s options are derived from the field at path.
Each allowedValues entry is the list of options for that key (one or more).
If the field at path has a value with no corresponding key in allowedValues,
there are no value restrictions for this field. UIs use this to show the right
options; the chosen or derived values are sent when ordering the catalog item.
Object keys are always strings. When the field at path is a boolean or number, use the JSON string representation as the key.
For example, to model backup.retention_days (retention in days) depending on
backup.enabled:
- path: backup.retention_days
displayName: Retention (days)
editable: true
dependsOn:
path: backup.enabled
allowedValues:
"true": ["7", "30", "90"]
"false": ["0"]When backup is disabled, retention is 0; when enabled, the user selects 7, 30, or 90 days.
Fields not listed are neither editable nor have default values. The catalog item owner must ensure all mandatory fields are listed.
Example “Development VM” CatalogItem - only CPU and memory required
apiVersion: v1alpha1
kind: CatalogItem
metadata:
name: dev-vm
displayName: "Development VM"
spec:
serviceType: vm
fields:
- path: "vcpu.count"
displayName: "CPU Count"
editable: true
default: 2
validationSchema: { minimum: 1, maximum: 4 }
- path: "memory.size"
displayName: "Memory"
editable: true
default: "4GB"
validationSchema: { minimum: 2, maximum: 8 }
- path: "guestOS.type"
displayName: "Operating System"
editable: false
default: "rhel-9"Multiple CatalogItems can reference the same ServiceType with different
constraints: a Production VM item could require vcpu.count between 4-16
instead of 1-4, while sharing the same underlying vm ServiceType definition.
Versioning
The apiVersion field versions the CatalogItem schema itself (e.g.,
v1alpha1), enabling evolution of the CatalogItem structure.
Design Details
Validation
The validationSchema field follows
JSON Schema (draft 2020-12).
This
standard supports:
- Numeric constraints: minimum, maximum, multipleOf
- String patterns: pattern, minLength, maxLength
- Enumerations: enum
- Array constraints: minItems, maxItems
- Conditional logic: if/then/else
For the complete validation vocabulary, see the JSON Schema Validation specification.
Data Flow
- Admin creates CatalogItem with defaults and validation rules
- User requests service from CatalogItem
- User submits request (UI may validate against
validationSchemafor early feedback) - DCM validates input against
validationSchemaand translates CatalogItem + user input into ServiceType payload - Placement Service calls policy engine for validation/mutation
- Once approved, Placement Service selects a Service Provider and sends the ServiceType payload
- Service Provider translates the ServiceType payload to their native format
Note: The validationSchema is used by both UI (for UX) and DCM (for enforcement). Users may bypass the UI (CLI, Ansible, cURL), so DCM must always validate.