diff --git a/.github/workflows/check-format.yaml b/.github/workflows/check-format.yaml new file mode 100644 index 0000000..3002f71 --- /dev/null +++ b/.github/workflows/check-format.yaml @@ -0,0 +1,29 @@ +name: Check formatting + +on: + pull_request: + branches: + - main + paths: + - 'content/docs/**' + - 'content/blog/**' + - 'Makefile' + - '.prettierignore' + +jobs: + check: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: '20' + + - name: Install prettier + run: npm install -g prettier + + - name: Check formatting + run: PRETTIER=prettier make check-format diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..51d0c18 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,6 @@ +# Hugo homepage and section stubs (shortcodes, inline HTML) +content/_index.md +content/about/_index.md + +# RemoteMD wrappers; canonical source is in the enhancements repo +content/docs/enhancements/ diff --git a/Makefile b/Makefile index fd29bea..35f828c 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: build serve clean check-spell +.PHONY: build serve clean check-spell format check-format # Use cspell when installed; otherwise npx. Set SPELLCHECK when invoking make to override. ifeq ($(SPELLCHECK),) @@ -8,7 +8,11 @@ ifeq ($(SPELLCHECK),) SPELLCHECK := cspell endif endif +PRETTIER ?= npx prettier FILE ?= **/*.md +# Prose docs only; see .prettierignore for paths under these trees to skip. +FORMAT_FILES ?= content/docs/**/*.md content/blog/**/*.md +PRETTIER_FLAGS ?= --prose-wrap always --print-width 80 build: hugo --gc --minify @@ -21,3 +25,9 @@ clean: check-spell: $(SPELLCHECK) "$(FILE)" + +format: + $(PRETTIER) $(PRETTIER_FLAGS) --write $(FORMAT_FILES) + +check-format: + $(PRETTIER) $(PRETTIER_FLAGS) --check $(FORMAT_FILES) diff --git a/content/blog/_index.md b/content/blog/_index.md index e7e3060..1f7b6f0 100644 --- a/content/blog/_index.md +++ b/content/blog/_index.md @@ -4,4 +4,3 @@ title: Blog Stay updated with the latest news, releases, and technical articles about the DCM project. - diff --git a/content/blog/sovereignty-rehydrate-demo/index.md b/content/blog/sovereignty-rehydrate-demo/index.md index 19e404e..389d287 100644 --- a/content/blog/sovereignty-rehydrate-demo/index.md +++ b/content/blog/sovereignty-rehydrate-demo/index.md @@ -16,10 +16,10 @@ images: It is 2 a.m. when your on-call team gets an alert that a Region A datacenter is down. The application holding customer data is unreachable, customers are -waiting, and someone in leadership is already asking for an ETA. The engineer -on duty opens the provider list and finds a healthy datacenter in Region B at -the top. If you are only looking at infrastructure health, that is where you -would send the workload next. +waiting, and someone in leadership is already asking for an ETA. The engineer on +duty opens the provider list and finds a healthy datacenter in Region B at the +top. If you are only looking at infrastructure health, that is where you would +send the workload next. The workload was never supposed to leave Region A. Whether the constraint comes from GDPR, a data residency requirement, a customer contract, or an internal @@ -46,10 +46,10 @@ The application still stays in Region A. We run the scenario on three datacenters split across two regions: -| Region | Datacenters | Notes | -| --- | --- | --- | -| **Region A** | `dc-demo-2`, `dc-demo-3` | Where the app is allowed to live | -| **Region B** | `dc-demo-1` | Healthy, but off limits for this workload | +| Region | Datacenters | Notes | +| ------------ | ------------------------ | ----------------------------------------- | +| **Region A** | `dc-demo-2`, `dc-demo-3` | Where the app is allowed to live | +| **Region B** | `dc-demo-1` | Healthy, but off limits for this workload | All three start healthy. Here is the twist: **Region B sorts first.** If DCM only picked the first available provider, every new deployment would land there @@ -61,8 +61,9 @@ by default. That is exactly the trap the sovereignty policy is meant to prevent. ## One policy, enforced everywhere -The regional rule is a [Rego](https://www.openpolicyagent.org/docs/latest/policy-language/) -policy you create once in the DCM UI under **Policies → Create**. Name it +The regional rule is a +[Rego](https://www.openpolicyagent.org/docs/latest/policy-language/) policy you +create once in the DCM UI under **Policies → Create**. Name it `Sovereignty Region Policy`, set type to `GLOBAL`, priority to `1`, and paste the policy below. @@ -84,18 +85,16 @@ Region A workload. ### First match wins (within the region) -Among the survivors, the policy picks the first provider alphabetically. That -is why the initial deploy lands on `dc-demo-2`, and why failover moves to +Among the survivors, the policy picks the first provider alphabetically. That is +why the initial deploy lands on `dc-demo-2`, and why failover moves to `dc-demo-3` when `dc-demo-2` fails. -{{< callout type="warning" >}} -**What if an entire region goes down?** +{{< callout type="warning" >}} **What if an entire region goes down?** If no healthy provider exists in the requested region, the request is rejected with a clear error. DCM will not silently fail over across a regional boundary to "help." That is the point. A hard failure is easier to explain to a -compliance officer than a quiet data residency violation. -{{< /callout >}} +compliance officer than a quiet data residency violation. {{< /callout >}} {{% details title="View the full Rego policy" closed="true" %}} @@ -104,7 +103,7 @@ package provider.sovereignty import rego.v1 -spm_url := "http://service-provider-manager:8080/api/v1alpha1/providers" +spm_url := "http://control-plane:8080/api/v1alpha1/providers" main := {"rejected": true, "rejection_reason": "spec.service_type is required"} if { not input.spec.service_type @@ -156,18 +155,18 @@ _providers_result(providers, _, _) := {"rejected": false, "selected_provider": p ### 1. Deploy to Region A -Create a **Pet Clinic** instance from the **Instances** tab and choose -**Region A**. DCM evaluates the sovereignty policy, skips Region B, and places -the app on `dc-demo-2`. +Create a **Pet Clinic** instance from the **Instances** tab and choose **Region +A**. DCM evaluates the sovereignty policy, skips Region B, and places the app on +`dc-demo-2`. Behind the scenes, DCM stores your original request. That stored intent is the source of truth for everything that follows. ### 2. Simulate the outage -Take `dc-demo-2` offline (`podman stop` on the provider containers). Region B -is still healthy and still first on the list. In a typical setup, that is where -the story ends and the compliance review begins. +Take `dc-demo-2` offline (`podman stop` on the provider containers). Region B is +still healthy and still first on the list. In a typical setup, that is where the +story ends and the compliance review begins. Here, the policy has already ruled Region B out. @@ -198,14 +197,14 @@ Most platforms draw a hard line between **day-one placement** and **disaster recovery**. Different workflows, different runbooks, different approval paths. DCM treats them as the same operation: -| Scenario | What you do | What DCM does | -| --- | --- | --- | -| First deploy | Create a catalog instance | Evaluates policy, places the app | -| Datacenter failure | Rehydrate | Re-evaluates the same policy against current health | -| Planned migration | Rehydrate | Same code path, same policy engine | +| Scenario | What you do | What DCM does | +| ------------------ | ------------------------- | --------------------------------------------------- | +| First deploy | Create a catalog instance | Evaluates policy, places the app | +| Datacenter failure | Rehydrate | Re-evaluates the same policy against current health | +| Planned migration | Rehydrate | Same code path, same policy engine | -**Initial placement, disaster recovery, and migration share one mechanism.** -The catalog instance holds your intent. The policy engine applies your rules. +**Initial placement, disaster recovery, and migration share one mechanism.** The +catalog instance holds your intent. The policy engine applies your rules. Rehydration is replay, not a separate rebuild workflow invented for emergencies. That consistency is what makes regional sovereignty hold at 2 a.m. the same way @@ -221,17 +220,18 @@ Click through the DCM UI at your own pace: explore the providers, create the policy, deploy Pet Clinic, and watch where the app lands. The walkthrough covers almost the entire scenario in the browser, including -rehydration from the **Instances** tab. The step that still needs a -terminal today is simulating the datacenter failure. -The guide flags that when you reach it. +rehydration from the **Instances** tab. The step that still needs a terminal +today is simulating the datacenter failure. The guide flags that when you reach +it. Want to reproduce the full lab on your own hardware? You will need the -[DCM stack](/docs/getting-started/local-setup/), [three workload clusters with -region-tagged providers](https://github.com/dcm-project/api-gateway/blob/main/RUN.md#running-with-service-providers) -(see [`SP_REGION`](https://github.com/dcm-project/k8s-container-service-provider#provider-identity) -for region metadata), and the [Pet Clinic catalog -item](https://github.com/dcm-project/api-gateway/blob/main/docs/three-tier-app-kind.md) -configured with a [deployment region -field](/docs/user-guide/catalog-items/#fields-and-policy-evaluation). If you are -new to DCM, start with the walkthrough above and come back to the lab setup when -you are ready to go deeper. +[DCM stack](/docs/getting-started/local-setup/), +[three workload clusters with region-tagged providers](https://github.com/dcm-project/control-plane/blob/main/deploy/RUN.md#running-with-service-providers) +(see +[`SP_REGION`](https://github.com/dcm-project/k8s-container-service-provider#provider-identity) +for region metadata), and the +[Pet Clinic catalog item](https://github.com/dcm-project/control-plane/blob/main/deploy/docs/three-tier-app-kind.md) +configured with a +[deployment region field](/docs/user-guide/catalog-items/#fields-and-policy-evaluation). +If you are new to DCM, start with the walkthrough above and come back to the lab +setup when you are ready to go deeper. diff --git a/content/docs/_index.md b/content/docs/_index.md index 86bdd43..3cf9d07 100644 --- a/content/docs/_index.md +++ b/content/docs/_index.md @@ -11,6 +11,9 @@ Documentation for the DCM project. ## Documentation Sections -- **[Getting Started](getting-started/)** - Set up and run DCM on your local machine. -- **[User Guide](user-guide/)** - Manage DCM resources using the CLI or the web UI. -- **[Enhancements](enhancements/)** - Enhancement proposals documenting new features, architectural decisions, and significant changes to the DCM project. +- **[Getting Started](getting-started/)** - Set up and run DCM on your local + machine. +- **[User Guide](user-guide/)** - Manage DCM resources using the CLI or the web + UI. +- **[Enhancements](enhancements/)** - Enhancement proposals documenting new + features, architectural decisions, and significant changes to the DCM project. diff --git a/content/docs/getting-started/_index.md b/content/docs/getting-started/_index.md index 98dd85a..290cb06 100644 --- a/content/docs/getting-started/_index.md +++ b/content/docs/getting-started/_index.md @@ -8,10 +8,17 @@ weight: 1 Get up and running with DCM. -- **[Architecture Overview](architecture/)** — How DCM components fit together and the request flow. -- **[Local Setup](local-setup/)** — Install prerequisites, start DCM services, and build the CLI. -- **[Create Small VM Catalog Item](create-small-vm-catalog-item/)** — Define and create a catalog item for a small virtual machine. -- **[Create Placement Policy](create-placement-policy/)** — Define a placement policy to route instances to the KubeVirt service provider. -- **[Create Instance of Small VM Catalog Item](create-small-vm-instance/)** — Deploy a VM by creating an instance of the catalog item. -- **[Register Another Provider](register-another-provider/)** — Register a second service provider and create a random selection policy. -- **[Troubleshooting](troubleshooting/)** — Diagnose issues using container logs and status checks. +- **[Architecture Overview](architecture/)** — How DCM components fit together + and the request flow. +- **[Local Setup](local-setup/)** — Install prerequisites, start DCM services, + and build the CLI. +- **[Create Small VM Catalog Item](create-small-vm-catalog-item/)** — Define and + create a catalog item for a small virtual machine. +- **[Create Placement Policy](create-placement-policy/)** — Define a placement + policy to route instances to the KubeVirt service provider. +- **[Create Instance of Small VM Catalog Item](create-small-vm-instance/)** — + Deploy a VM by creating an instance of the catalog item. +- **[Register Another Provider](register-another-provider/)** — Register a + second service provider and create a random selection policy. +- **[Troubleshooting](troubleshooting/)** — Diagnose issues using container logs + and status checks. diff --git a/content/docs/getting-started/architecture.md b/content/docs/getting-started/architecture.md index c82bfd3..3fa3fac 100644 --- a/content/docs/getting-started/architecture.md +++ b/content/docs/getting-started/architecture.md @@ -4,16 +4,17 @@ type: docs weight: 1 --- -DCM (Data Center Management) is a control plane for managing infrastructure services across multiple providers. This page gives a high-level overview of how the components fit together. +DCM (Data Center Management) is a control plane for managing infrastructure +services across multiple providers. This page gives a high-level overview of how +the components fit together. ## Components ```mermaid graph TD User["User (CLI / API)"] - GW["API Gateway
(Traefik :9080)"] - subgraph Managers + subgraph CP["Control Plane (:8080)"] CM["Catalog Manager"] PM["Policy Manager"] PLM["Placement Manager"] @@ -23,7 +24,6 @@ graph TD subgraph Infrastructure PG["PostgreSQL"] NATS["NATS"] - OPA["OPA"] end subgraph Providers @@ -31,17 +31,13 @@ graph TD SP2["KubeVirt SP 2"] end - User --> GW - GW --> CM - GW --> PM - GW --> SPM + User --> CP CM --> PG PM --> PG PLM --> PG SPM --> PG - PM --> OPA PLM --> PM PLM --> SPM CM --> PLM @@ -55,17 +51,16 @@ graph TD ## Component Responsibilities -| Component | Role | -|---|---| -| **API Gateway** | Single entry point for all API requests. Routes to the appropriate manager based on URL path. | -| **Catalog Manager** | Manages service types, catalog items, and catalog item instances. Triggers placement when an instance is created. | -| **Policy Manager** | Stores placement policies (Rego) and evaluates them via OPA. | -| **Placement Manager** | Selects a service provider for a new instance by evaluating policies against available providers. | -| **Service Provider Manager** | Tracks registered service providers and their health status. | -| **PostgreSQL** | Persistent storage for all managers. | -| **NATS** | Message bus for communication between the Service Provider Manager and service providers. | -| **OPA** | Evaluates Rego policies for placement decisions. | -| **Service Providers** | External systems (e.g., KubeVirt) that create and manage the actual resources (VMs, containers, etc.). | +| Component | Role | +| ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | +| **Control Plane** | Single process that exposes all DCM APIs on `:8080`. Hosts the catalog, policy, placement, and service provider managers in one binary. | +| **Catalog Manager** | Manages service types, catalog items, and catalog item instances. Triggers placement when an instance is created. | +| **Policy Manager** | Stores placement policies (Rego) and evaluates them via an embedded OPA engine. | +| **Placement Manager** | Selects a service provider for a new instance by evaluating policies against available providers. | +| **Service Provider Manager** | Tracks registered service providers and their health status. | +| **PostgreSQL** | Persistent storage for the control plane. | +| **NATS** | Message bus for communication between the Service Provider Manager and service providers. | +| **Service Providers** | External systems (e.g., KubeVirt) that create and manage the actual resources (VMs, containers, etc.). | ## Request Flow @@ -74,26 +69,26 @@ When a user creates a catalog item instance, the following happens: ```mermaid sequenceDiagram participant User - participant GW as API Gateway + participant CP as Control Plane participant CM as Catalog Manager participant PLM as Placement Manager participant PM as Policy Manager - participant OPA participant SPM as SP Manager participant SP as KubeVirt SP - User->>GW: Create catalog item instance - GW->>CM: POST /catalog-item-instances + User->>CP: Create catalog item instance + CP->>CM: POST /catalog-item-instances CM->>PLM: Request placement - PLM->>PM: Evaluate policies - PM->>OPA: Evaluate Rego - OPA-->>PM: Placement decision + PLM->>PM: Evaluate policies (embedded OPA) PM-->>PLM: Placement decision PLM->>SPM: Create resource on provider SPM->>SP: Create VM SP-->>User: VM scheduling ``` -1. The **Catalog Manager** receives the request and asks the **Placement Manager** to find a suitable provider. -2. The **Placement Manager** evaluates placement policies through the **Policy Manager** and **OPA**. -3. Once a provider is selected, the resource is created on that provider through the **Service Provider Manager**. +1. The **Catalog Manager** receives the request and asks the **Placement + Manager** to find a suitable provider. +2. The **Placement Manager** evaluates placement policies through the **Policy + Manager**, which uses an embedded OPA engine to evaluate Rego. +3. Once a provider is selected, the resource is created on that provider through + the **Service Provider Manager**. diff --git a/content/docs/getting-started/create-placement-policy.md b/content/docs/getting-started/create-placement-policy.md index 7e37e25..5f9abfb 100644 --- a/content/docs/getting-started/create-placement-policy.md +++ b/content/docs/getting-started/create-placement-policy.md @@ -4,7 +4,11 @@ type: docs weight: 4 --- -Placement policies control how DCM decides which service provider should handle a catalog item instance. Policies are written in [Rego](https://www.openpolicyagent.org/docs/latest/policy-language/), the policy language used by Open Policy Agent (OPA). Each policy can accept or reject a placement request and optionally select a specific provider. +Placement policies control how DCM decides which service provider should handle +a catalog item instance. Policies are written in +[Rego](https://www.openpolicyagent.org/docs/latest/policy-language/), the policy +language used by Open Policy Agent (OPA). Each policy can accept or reject a +placement request and optionally select a specific provider. Policies have a `priority` — lower values are evaluated first. @@ -26,6 +30,7 @@ rego_code: | ``` This policy: + - Has the highest priority (`1`) - Always selects `kubevirt-service-provider` as the target service provider - Never rejects a request (`rejected: false`) diff --git a/content/docs/getting-started/create-small-vm-catalog-item.md b/content/docs/getting-started/create-small-vm-catalog-item.md index 3858d23..eb061fc 100644 --- a/content/docs/getting-started/create-small-vm-catalog-item.md +++ b/content/docs/getting-started/create-small-vm-catalog-item.md @@ -4,7 +4,8 @@ type: docs weight: 3 --- -This guide walks you through creating a catalog item for a small virtual machine using the DCM CLI. +This guide walks you through creating a catalog item for a small virtual machine +using the DCM CLI. ## Prerequisites @@ -13,7 +14,8 @@ This guide walks you through creating a catalog item for a small virtual machine ## Define the Catalog Item -For a detailed explanation of the catalog item schema, see the [Catalog Item Schema](../../enhancements/catalog-item-schema/) enhancement. +For a detailed explanation of the catalog item schema, see the +[Catalog Item Schema](../../enhancements/catalog-item-schema/) enhancement. Create a file called `small-vm.yaml` with the following content: @@ -57,6 +59,7 @@ spec: ``` This defines a small VM catalog item with: + - **Metadata** — editable by users, for setting VM name and labels - **2 vCPUs** — editable by users, between 1 and 4 - **2 GB memory** — fixed, not editable by users diff --git a/content/docs/getting-started/create-small-vm-instance.md b/content/docs/getting-started/create-small-vm-instance.md index a1560bb..bd2de82 100644 --- a/content/docs/getting-started/create-small-vm-instance.md +++ b/content/docs/getting-started/create-small-vm-instance.md @@ -4,13 +4,16 @@ type: docs weight: 5 --- -This guide walks you through deploying a virtual machine on a KubeVirt service provider by creating a catalog item instance using the DCM CLI. +This guide walks you through deploying a virtual machine on a KubeVirt service +provider by creating a catalog item instance using the DCM CLI. ## Prerequisites -- DCM services running with the KubeVirt profile (see [Local Setup](../local-setup/)) +- DCM services running with the KubeVirt profile (see + [Local Setup](../local-setup/)) - A KubeVirt service provider registered with DCM -- The `small-vm` catalog item created (see [Create Small VM Catalog Item](../create-small-vm-catalog-item/)) +- The `small-vm` catalog item created (see + [Create Small VM Catalog Item](../create-small-vm-catalog-item/)) - The `dcm` CLI installed and in your `PATH` ## Define the Catalog Item Instance @@ -33,6 +36,7 @@ spec: ``` This creates a VM instance based on the `small-vm` catalog item with: + - **Metadata** — sets the VM name to `small-vm` with a `dev` environment label - **1 vCPU** — overriding the default of 2 @@ -56,7 +60,8 @@ dcm catalog instance get my-dev-vm -o yaml ## Check the Resource Status -You can check the status of the underlying resource from the service provider resource manager: +You can check the status of the underlying resource from the service provider +resource manager: ```bash dcm sp resource get my-dev-vm diff --git a/content/docs/getting-started/local-setup.md b/content/docs/getting-started/local-setup.md index 7bdaf2a..274311f 100644 --- a/content/docs/getting-started/local-setup.md +++ b/content/docs/getting-started/local-setup.md @@ -10,32 +10,38 @@ Learn how to set up and run DCM on your local machine. - [Podman](https://podman.io/) and `podman-compose` installed - [Go](https://go.dev/) (for building the CLI) -- (Optional) A Kubernetes cluster with [KubeVirt](https://kubevirt.io/) for the kubevirt-service-provider +- (Optional) A Kubernetes cluster with [KubeVirt](https://kubevirt.io/) for the + kubevirt-service-provider ## Quick Start -Clone the [api-gateway](https://github.com/dcm-project/api-gateway) repository and start all core services (gateway, postgres, nats, opa, and all managers): +Clone the [control-plane](https://github.com/dcm-project/control-plane) +repository and start the core platform (postgres, nats, control-plane, and +dcm-ui): ```bash -git clone https://github.com/dcm-project/api-gateway.git -cd api-gateway +git clone https://github.com/dcm-project/control-plane.git +cd control-plane/deploy podman-compose up -d ``` -The API gateway will be available at `http://localhost:9080`. +The control-plane API is available at `http://localhost:8080`. The DCM UI is at +`http://localhost:7007`. ## Running with the KubeVirt Service Provider -The `kubevirt-service-provider` is behind a compose profile and does not start by default. -To include it, set the required environment variables and activate the `kubevirt` profile: +The `kubevirt-service-provider` is behind a compose profile and does not start +by default. To include it, set the required environment variables and activate +the `kubevirt` profile: ```bash -export KUBEVIRT_NAMESPACE=vms +export KUBERNETES_NAMESPACE=vms export KUBEVIRT_KUBECONFIG="/path/to/kubeconfig" podman-compose --profile kubevirt up -d ``` -> **Note:** The namespace set in `KUBEVIRT_NAMESPACE` must already exist in your Kubernetes cluster. +> **Note:** The namespace set in `KUBERNETES_NAMESPACE` must already exist in +> your Kubernetes cluster. ## Verifying the Deployment @@ -45,24 +51,24 @@ Check that all services are running: podman-compose ps ``` -Check health endpoints through the gateway: +Check the health endpoint: ```bash -curl http://localhost:9080/api/v1alpha1/health/providers -curl http://localhost:9080/api/v1alpha1/health/catalog -curl http://localhost:9080/api/v1alpha1/health/policies -curl http://localhost:9080/api/v1alpha1/health/placement +curl http://localhost:8080/api/v1alpha1/health ``` -If you deployed with the KubeVirt provider, you can also list the registered providers: +If you deployed with the KubeVirt provider, you can also list the registered +providers: ```bash -curl http://localhost:9080/api/v1alpha1/providers +curl http://localhost:8080/api/v1alpha1/providers ``` ## Setting Up the CLI -The DCM CLI (`dcm`) lets you interact with the DCM control plane from the command line. Clone the [cli](https://github.com/dcm-project/cli) repository and build the binary: +The DCM CLI (`dcm`) lets you interact with the DCM control plane from the +command line. Clone the [cli](https://github.com/dcm-project/cli) repository and +build the binary: ```bash git clone https://github.com/dcm-project/cli.git @@ -70,13 +76,15 @@ cd cli make build ``` -The binary will be available at `bin/dcm`. You can move it to a directory in your `PATH`: +The binary will be available at `bin/dcm`. You can move it to a directory in +your `PATH`: ```bash sudo cp bin/dcm /usr/local/bin/ ``` -By default, the CLI connects to the API gateway at `http://localhost:9080`. You can verify it's working with: +By default, the CLI connects to the control plane at `http://localhost:8080`. +You can verify it's working with: ```bash dcm version diff --git a/content/docs/getting-started/register-another-provider.md b/content/docs/getting-started/register-another-provider.md index 291e3bf..3a82abc 100644 --- a/content/docs/getting-started/register-another-provider.md +++ b/content/docs/getting-started/register-another-provider.md @@ -4,11 +4,16 @@ type: docs weight: 6 --- -In DCM, service providers self-register by calling the Service Provider Manager API. When you started the KubeVirt service provider in the [Local Setup](../local-setup/), it automatically registered itself. In this guide, you'll register a second provider manually and create a policy that randomly selects between the two. +In DCM, service providers self-register by calling the Service Provider Manager +API. When you started the KubeVirt service provider in the +[Local Setup](../local-setup/), it automatically registered itself. In this +guide, you'll register a second provider manually and create a policy that +randomly selects between the two. ## Register a Second Provider -Start another instance of the KubeVirt service provider with a different name and namespace: +Start another instance of the KubeVirt service provider with a different name +and namespace: ```bash podman-compose --profile kubevirt run --name another-kubevirt-provider -d --no-deps \ @@ -19,23 +24,30 @@ podman-compose --profile kubevirt run --name another-kubevirt-provider -d --no-d kubevirt-service-provider ``` -> **Note:** The `PROVIDER_ID` must be provided to ensure idempotent registration. The Service Provider Manager validates that no existing provider with the same name or ID is already registered with conflicting values. +> **Note:** The `PROVIDER_ID` must be provided to ensure idempotent +> registration. The Service Provider Manager validates that no existing provider +> with the same name or ID is already registered with conflicting values. -> **Note:** The `KUBEVIRT_PROVIDER_NAME` must be specified so it matches the container's DNS hostname within the compose network. Other services use this name to reach the provider's endpoint. +> **Note:** The `KUBEVIRT_PROVIDER_NAME` must be specified so it matches the +> container's DNS hostname within the compose network. Other services use this +> name to reach the provider's endpoint. -The new provider will automatically register itself with the Service Provider Manager. +The new provider will automatically register itself with the Service Provider +Manager. ## Verify Both Providers Are Registered ```bash -curl -s http://localhost:9080/api/v1alpha1/providers | jq +curl -s http://localhost:8080/api/v1alpha1/providers | jq ``` -You should see both `kubevirt-service-provider` and `another-kubevirt-provider` in the list. +You should see both `kubevirt-service-provider` and `another-kubevirt-provider` +in the list. ## Create a Random Selection Policy -Now create a policy that randomly selects between the two providers. Create a file called `random-provider-policy.yaml`: +Now create a policy that randomly selects between the two providers. Create a +file called `random-provider-policy.yaml`: ```yaml display_name: random-provider-selection @@ -57,11 +69,16 @@ rego_code: | ``` This Rego policy: -- Defines the two available providers: `kubevirt-service-provider` and `another-kubevirt-provider` + +- Defines the two available providers: `kubevirt-service-provider` and + `another-kubevirt-provider` - Randomly picks one using `rand.intn` - Returns the selected provider's name -> **Note:** If you previously created the `kubevirt-provider` policy from [Create Placement Policy](../create-placement-policy/), delete it first so the new policy takes effect: +> **Note:** If you previously created the `kubevirt-provider` policy from +> [Create Placement Policy](../create-placement-policy/), delete it first so the +> new policy takes effect: +> > ```bash > dcm policy delete > ``` @@ -80,7 +97,8 @@ dcm policy list ## Test the Random Selection -Create two VM instances using the `my-vm.yaml` from [Create Instance of Small VM Catalog Item](../create-small-vm-instance/): +Create two VM instances using the `my-vm.yaml` from +[Create Instance of Small VM Catalog Item](../create-small-vm-instance/): ```bash dcm catalog instance create --from-file my-vm.yaml @@ -101,4 +119,5 @@ ID PROVIDER STATUS CRE 57aae98f-443d-4444-95dd-bc1e9ddc9406 another-kubevirt-provider Scheduling 2026-03-26T08:42:44.87697Z ``` -Each instance was placed on a different provider, confirming the random selection policy is working. +Each instance was placed on a different provider, confirming the random +selection policy is working. diff --git a/content/docs/getting-started/troubleshooting.md b/content/docs/getting-started/troubleshooting.md index 4c44c40..c54f973 100644 --- a/content/docs/getting-started/troubleshooting.md +++ b/content/docs/getting-started/troubleshooting.md @@ -14,20 +14,21 @@ To view logs for a specific service: podman-compose logs ``` -For example, to check the API gateway logs: +For example, to check the control-plane logs: ```bash -podman-compose logs gateway +podman-compose logs control-plane ``` -Available service names: `gateway`, `postgres`, `nats`, `opa`, `service-provider-manager`, `catalog-manager`, `policy-manager`, `placement-manager`, `kubevirt-service-provider`. +Available service names: `control-plane`, `postgres`, `nats`, `dcm-ui`, +`kubevirt-service-provider`. ### Follow Logs in Real Time Use the `-f` flag to stream logs as they are produced: ```bash -podman-compose logs -f gateway +podman-compose logs -f control-plane ``` ### Limit Log Output @@ -35,7 +36,7 @@ podman-compose logs -f gateway To show only the last N lines: ```bash -podman-compose logs --tail 50 gateway +podman-compose logs --tail 50 control-plane ``` ## Checking Container Status diff --git a/content/docs/user-guide/_index.md b/content/docs/user-guide/_index.md index f689ed9..8add9d9 100644 --- a/content/docs/user-guide/_index.md +++ b/content/docs/user-guide/_index.md @@ -10,13 +10,20 @@ Learn how to manage DCM resources using the CLI or the web UI. ## CLI -- **[CLI Configuration](cli-configuration/)** — Configure the CLI, global flags, output formats, and shell completion. -- **[Providers](providers/)** — View registered service providers and their health status. -- **[Service Types](service-types/)** — Browse available service type definitions. -- **[Catalog Items](catalog-items/)** — Create and manage reusable resource templates. -- **[Policies](policies/)** — Define placement policies that control where instances are deployed. -- **[Catalog Item Instances](catalog-item-instances/)** — Deploy, manage, and monitor resource instances. -- **[Service Provider Resources](service-provider-resources/)** — View resources managed by service providers. +- **[CLI Configuration](cli-configuration/)** — Configure the CLI, global flags, + output formats, and shell completion. +- **[Providers](providers/)** — View registered service providers and their + health status. +- **[Service Types](service-types/)** — Browse available service type + definitions. +- **[Catalog Items](catalog-items/)** — Create and manage reusable resource + templates. +- **[Policies](policies/)** — Define placement policies that control where + instances are deployed. +- **[Catalog Item Instances](catalog-item-instances/)** — Deploy, manage, and + monitor resource instances. +- **[Service Provider Resources](service-provider-resources/)** — View resources + managed by service providers. ## DCM UI diff --git a/content/docs/user-guide/catalog-item-instances.md b/content/docs/user-guide/catalog-item-instances.md index 0fa2eaf..243dd00 100644 --- a/content/docs/user-guide/catalog-item-instances.md +++ b/content/docs/user-guide/catalog-item-instances.md @@ -4,11 +4,16 @@ type: docs weight: 6 --- -Catalog item instances represent deployed resources created from a [catalog item](../catalog-items/). When you create an instance, DCM evaluates policies to validate the input and select a provider, then provisions the resource on that provider. Instances can override fields allowed by the catalog item's `fields` via `user_values`. +Catalog item instances represent deployed resources created from a +[catalog item](../catalog-items/). When you create an instance, DCM evaluates +policies to validate the input and select a provider, then provisions the +resource on that provider. Instances can override fields allowed by the catalog +item's `fields` via `user_values`. ## Creating an Instance -To create an instance, define its configuration in a YAML or JSON file and pass it to the CLI: +To create an instance, define its configuration in a YAML or JSON file and pass +it to the CLI: ```bash dcm catalog instance create --from-file instance.yaml @@ -22,7 +27,9 @@ dcm catalog instance create --from-file instance.yaml --id my-instance ### Example YAML -Below is a complete instance definition that creates a virtual machine from an existing catalog item, overriding the vCPU count, setting the O/S type and adding name and labels to the metadata: +Below is a complete instance definition that creates a virtual machine from an +existing catalog item, overriding the vCPU count, setting the O/S type and +adding name and labels to the metadata: ```yaml api_version: v1alpha1 @@ -43,18 +50,26 @@ spec: ### Key Fields -| Field | Purpose | -|-------|---------| -| `display_name` | An optional human-readable name shown in listings and the UI. | -| `spec.catalog_item_id` | References the UID of an existing catalog item to deploy from. | -| `spec.user_values` | Sets of overrides for fields allowed by the catalog item's `fields` array. Only fields with `editable: true` can be customized here. | -| `spec.user_values[].path` | Path corresponding to the `path` key in the `catalog_item`'s `fields` item | +| Field | Purpose | +| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | +| `display_name` | An optional human-readable name shown in listings and the UI. | +| `spec.catalog_item_id` | References the UID of an existing catalog item to deploy from. | +| `spec.user_values` | Sets of overrides for fields allowed by the catalog item's `fields` array. Only fields with `editable: true` can be customized here. | +| `spec.user_values[].path` | Path corresponding to the `path` key in the `catalog_item`'s `fields` item | -> **Note:** Each value provided in `user_values` will be validated against its corresponding item in the catalog item's `fields` list. If the `field` is not editable (`editable=false`) or the `value` does not pass the `validation_schema`, the request will be rejected. +> **Note:** Each value provided in `user_values` will be validated against its +> corresponding item in the catalog item's `fields` list. If the `field` is not +> editable (`editable=false`) or the `value` does not pass the +> `validation_schema`, the request will be rejected. ### Policy Evaluation -Values set through `user_values` become part of the resource spec that placement [policies](../policies/) evaluate. They are accessible as `input.spec.*` in Rego code — for example, `input.spec.metadata.labels.env` for the label shown above. Only fields declared in the catalog item are included; see [How `input.spec` is Constructed](../policies/#how-inputspec-is-constructed) for details. +Values set through `user_values` become part of the resource spec that placement +[policies](../policies/) evaluate. They are accessible as `input.spec.*` in Rego +code — for example, `input.spec.metadata.labels.env` for the label shown above. +Only fields declared in the catalog item are included; see +[How `input.spec` is Constructed](../policies/#how-inputspec-is-constructed) for +details. ### Verifying the Instance @@ -80,7 +95,8 @@ b2d4f6a8-1c3e-5678-9abc-def012345678 My VM Instance f4a8b3c1-d2e5-6789-abcd- c5e7a9b1-2d4f-6789-0abc-123456789def Dev Database a7c2d9e4-b1f3-4567-89ab-cdef01234567 r-3b5d7f90-c1e3-4a26-98b0-d4f6a8c2e0a1 2026-04-03T14:15:00Z ``` -> **Note:** The Resource ID refers to the ID of the corresponding [Service Type Resource](../service-provider-resources). +> **Note:** The Resource ID refers to the ID of the corresponding +> [Service Type Resource](../service-provider-resources). ### Filtering by Catalog Item @@ -156,19 +172,24 @@ Example JSON output: ## Rehydrating an Instance -Use `dcm catalog instance rehydrate` to re-trigger the provisioning flow for an existing instance: +Use `dcm catalog instance rehydrate` to re-trigger the provisioning flow for an +existing instance: ```bash dcm catalog instance rehydrate b2d4f6a8-1c3e-5678-9abc-def012345678 ``` -Rehydration refreshes an instance by running the provisioning process again. This is useful when: +Rehydration refreshes an instance by running the provisioning process again. +This is useful when: -- A provider has recovered from a failure and the resource needs to be re-provisioned. +- A provider has recovered from a failure and the resource needs to be + re-provisioned. - The underlying resource needs to be recreated or updated. -- Placement policies have changed and you want the instance to be re-evaluated against the current configuration. +- Placement policies have changed and you want the instance to be re-evaluated + against the current configuration. -> **Note:** Rehydration will first provision the new resource before trying to delete the old one. Make sure to update any references (e.g. DNS) if needed +> **Note:** Rehydration will first provision the new resource before trying to +> delete the old one. Make sure to update any references (e.g. DNS) if needed ## Deleting an Instance @@ -178,8 +199,11 @@ To remove an instance: dcm catalog instance delete b2d4f6a8-1c3e-5678-9abc-def012345678 ``` -> **Note:** Deleting an instance also triggers cleanup of the underlying resource on the provider. The provisioned resource will be removed as part of the deletion process. +> **Note:** Deleting an instance also triggers cleanup of the underlying +> resource on the provider. The provisioned resource will be removed as part of +> the deletion process. --- -For a step-by-step walkthrough, see [Create Instance of Small VM Catalog Item](../../getting-started/create-small-vm-instance/). +For a step-by-step walkthrough, see +[Create Instance of Small VM Catalog Item](../../getting-started/create-small-vm-instance/). diff --git a/content/docs/user-guide/catalog-items.md b/content/docs/user-guide/catalog-items.md index 1723923..7a21412 100644 --- a/content/docs/user-guide/catalog-items.md +++ b/content/docs/user-guide/catalog-items.md @@ -4,11 +4,16 @@ type: docs weight: 4 --- -Catalog items are reusable templates that define a deployable resource. Each catalog item references a [service type](../service-types/) and may specify whether a resource configuration is editable while setting a preset, a default value and/or a validation schema for the user values — for example, CPU, memory, and storage for a virtual machine. +Catalog items are reusable templates that define a deployable resource. Each +catalog item references a [service type](../service-types/) and may specify +whether a resource configuration is editable while setting a preset, a default +value and/or a validation schema for the user values — for example, CPU, memory, +and storage for a virtual machine. ## Creating a Catalog Item -To create a catalog item, define its configuration in a YAML or JSON file and pass it to the CLI: +To create a catalog item, define its configuration in a YAML or JSON file and +pass it to the CLI: ```bash dcm catalog item create --from-file item.yaml @@ -65,28 +70,35 @@ spec: ### Key Sections -| Section | Purpose | -|---------|---------| -| `api_version` | Ties the catalog item to a specific schema version (e.g., `v1alpha1`). | -| `display_name` | A human-readable name shown in listings and the UI. | -| `spec.service_type` | Corresponding service type | -| `spec.fields` | List of fields with const or user values | -| `spec.fields[].path` | Path of the field within the `service_type` specification | -| `spec.fields[].display_name` | A human-readable name shown in listings and the UI | -| `spec.fields[].editable` | Specify whether the user may edit the value | -| `spec.fields[].default` | Default value for the field. When `editable` is `false` this becomes the actual value | -| `spec.fields[].validation_schema` | JSON Schema rules to validate input. See: https://json-schema.org/ | +| Section | Purpose | +| --------------------------------- | ------------------------------------------------------------------------------------- | +| `api_version` | Ties the catalog item to a specific schema version (e.g., `v1alpha1`). | +| `display_name` | A human-readable name shown in listings and the UI. | +| `spec.service_type` | Corresponding service type | +| `spec.fields` | List of fields with const or user values | +| `spec.fields[].path` | Path of the field within the `service_type` specification | +| `spec.fields[].display_name` | A human-readable name shown in listings and the UI | +| `spec.fields[].editable` | Specify whether the user may edit the value | +| `spec.fields[].default` | Default value for the field. When `editable` is `false` this becomes the actual value | +| `spec.fields[].validation_schema` | JSON Schema rules to validate input. See: https://json-schema.org/ | ### Fields and Policy Evaluation -Catalog item fields define the governance boundary for placement policies. When DCM builds the resource spec that policies evaluate, it includes **only** two sources: +Catalog item fields define the governance boundary for placement policies. When +DCM builds the resource spec that policies evaluate, it includes **only** two +sources: 1. **Field defaults** declared in the catalog item 2. **user_values** overrides provided at instance creation -Anything not declared as a catalog item field is invisible to the policy engine, even if set elsewhere on the instance request. This means labels must be exposed through fields with `metadata.labels.*` paths for policies to inspect them. For example, a field with `path: metadata.labels.region` makes the region label available to Rego policies as `input.spec.metadata.labels.region`. +Anything not declared as a catalog item field is invisible to the policy engine, +even if set elsewhere on the instance request. This means labels must be exposed +through fields with `metadata.labels.*` paths for policies to inspect them. For +example, a field with `path: metadata.labels.region` makes the region label +available to Rego policies as `input.spec.metadata.labels.region`. -See [Policies](../policies/) for details on how `input.spec` is constructed and how to write policies that use label values. +See [Policies](../policies/) for details on how `input.spec` is constructed and +how to write policies that use label values. ### Verifying the Catalog Item @@ -198,11 +210,7 @@ Example JSON output: "editable": true, "path": "guest_os.type", "validation_schema": { - "enum": [ - "fedora", - "centos", - "ubuntu" - ], + "enum": ["fedora", "centos", "ubuntu"], "type": "string" } } @@ -222,8 +230,10 @@ To remove a catalog item: dcm catalog item delete f4a8b3c1-d2e5-6789-abcd-ef0123456789 ``` -> **Note:** Deleting a catalog item with instances that were already created from it will fail. Remove all existing instances before deleting the item. +> **Note:** Deleting a catalog item with instances that were already created +> from it will fail. Remove all existing instances before deleting the item. --- -For a step-by-step walkthrough, see [Create Small VM Catalog Item](../../getting-started/create-small-vm-catalog-item/). +For a step-by-step walkthrough, see +[Create Small VM Catalog Item](../../getting-started/create-small-vm-catalog-item/). diff --git a/content/docs/user-guide/cli-configuration.md b/content/docs/user-guide/cli-configuration.md index fcc019a..f2b6868 100644 --- a/content/docs/user-guide/cli-configuration.md +++ b/content/docs/user-guide/cli-configuration.md @@ -4,16 +4,20 @@ type: docs weight: 1 --- -The DCM CLI (`dcm`) connects to the DCM API gateway to manage resources. It can be configured through command-line flags, environment variables, or a configuration file. +The DCM CLI (`dcm`) connects to the DCM control plane to manage resources. It +can be configured through command-line flags, environment variables, or a +configuration file. -For installation instructions, see [Setting Up the CLI](../../getting-started/local-setup/#setting-up-the-cli). +For installation instructions, see +[Setting Up the CLI](../../getting-started/local-setup/#setting-up-the-cli). ## Configuration File -The CLI reads its configuration from `~/.dcm/config.yaml` by default. Here is an example with all available fields: +The CLI reads its configuration from `~/.dcm/config.yaml` by default. Here is an +example with all available fields: ```yaml -api-gateway-url: http://localhost:9080 +control-plane-url: http://localhost:8080 output-format: table timeout: 30 tls-ca-cert: "" @@ -35,22 +39,22 @@ Settings are resolved in the following order (highest priority first): The following flags are available on all commands: -| Flag | Short | Default | Description | -|------|-------|---------|-------------| -| `--api-gateway-url` | | `http://localhost:9080` | URL of the DCM API gateway | -| `--output` | `-o` | `table` | Output format (`table`, `json`, `yaml`) | -| `--timeout` | | `30` | Request timeout in seconds | -| `--config` | | `~/.dcm/config.yaml` | Path to configuration file | +| Flag | Short | Default | Description | +| --------------------- | ----- | ----------------------- | --------------------------------------- | +| `--control-plane-url` | | `http://localhost:8080` | URL of the DCM control plane | +| `--output` | `-o` | `table` | Output format (`table`, `json`, `yaml`) | +| `--timeout` | | `30` | Request timeout in seconds | +| `--config` | | `~/.dcm/config.yaml` | Path to configuration file | ## TLS Configuration -To connect to a TLS-secured API gateway, use the following flags: +To connect to a TLS-secured control plane, use the following flags: -| Flag | Description | -|------|-------------| -| `--tls-ca-cert` | Path to CA certificate file for TLS verification | -| `--tls-client-cert` | Path to client certificate file for mutual TLS | -| `--tls-client-key` | Path to client private key file for mutual TLS | +| Flag | Description | +| ------------------- | ------------------------------------------------------------------ | +| `--tls-ca-cert` | Path to CA certificate file for TLS verification | +| `--tls-client-cert` | Path to client certificate file for mutual TLS | +| `--tls-client-key` | Path to client private key file for mutual TLS | | `--tls-skip-verify` | Skip TLS certificate verification (not recommended for production) | ## Output Formats @@ -85,4 +89,5 @@ dcm completion fish | source dcm completion powershell | Out-String | Invoke-Expression ``` -To make completion persistent, add the appropriate command to your shell profile (e.g., `~/.bashrc`, `~/.zshrc`). +To make completion persistent, add the appropriate command to your shell profile +(e.g., `~/.bashrc`, `~/.zshrc`). diff --git a/content/docs/user-guide/policies.md b/content/docs/user-guide/policies.md index c8ec774..c3e021f 100644 --- a/content/docs/user-guide/policies.md +++ b/content/docs/user-guide/policies.md @@ -4,7 +4,12 @@ type: docs weight: 5 --- -Policies are [Rego](https://www.openpolicyagent.org/docs/latest/policy-language/) rules (the OPA policy language) that validate service provider resources and control where they are placed. During the placement flow, DCM evaluates all enabled policies in priority order (lower number = evaluated first). A policy can reject a request or select a specific provider for it. It may also alter or set values. +Policies are +[Rego](https://www.openpolicyagent.org/docs/latest/policy-language/) rules (the +OPA policy language) that validate service provider resources and control where +they are placed. During the placement flow, DCM evaluates all enabled policies +in priority order (lower number = evaluated first). A policy can reject a +request or select a specific provider for it. It may also alter or set values. ## Creating a Policy @@ -22,7 +27,7 @@ rego_code: | import rego.v1 - spm_url := "http://service-provider-manager:8080/api/v1alpha1/providers" + spm_url := "http://control-plane:8080/api/v1alpha1/providers" main := {"rejected": true, "rejection_reason": "spec.service_type is required"} if { not input.spec.service_type @@ -52,20 +57,23 @@ rego_code: | } ``` -> **Note:** This Rego code assumes it can access the `service-provider-manager` to get the list of providers. Then, it filters only the `ready` ones, sorts alphabetically and returns the first one +> **Note:** This Rego code assumes it can access the control-plane provider API +> to get the list of providers. Then, it filters only the `ready` ones, sorts +> alphabetically and returns the first one ### Field Reference -| Field | Description | -|-------|-------------| -| `display_name` | A human-readable name for the policy. | -| `policy_type` | The scope of policy (e.g., `GLOBAL`). | -| `priority` | Evaluation order. Lower numbers are evaluated first. | -| `enabled` | Whether the policy is active (`true` or `false`). | -| `rego_code` | The Rego source code. Must define a `main` rule with `rejected`, and either `rejection_reason` or `selected_provider` fields. | -| `label_selector` | `key:value` pairs used to match between the policy and the `metadata.labels` field of the provisioned resource | +| Field | Description | +| ---------------- | ----------------------------------------------------------------------------------------------------------------------------- | +| `display_name` | A human-readable name for the policy. | +| `policy_type` | The scope of policy (e.g., `GLOBAL`). | +| `priority` | Evaluation order. Lower numbers are evaluated first. | +| `enabled` | Whether the policy is active (`true` or `false`). | +| `rego_code` | The Rego source code. Must define a `main` rule with `rejected`, and either `rejection_reason` or `selected_provider` fields. | +| `label_selector` | `key:value` pairs used to match between the policy and the `metadata.labels` field of the provisioned resource | -> **Note:** `label_selector` may also use the `service_type` key to match based on the resource's `service_type` +> **Note:** `label_selector` may also use the `service_type` key to match based +> on the resource's `service_type` ### Rego Rule Structure @@ -75,29 +83,38 @@ The `main` rule receives an `input` object and must return an output object. The `input` object includes: -| Field | Description | -|-------|-------------| -| `spec` | The current (patched) request payload. While policies do not have to be specific for service types, they will need to know the expected content. | -| `constraints` | The accumulated constraints context from prior policies in the chain. | -| `provider` | The currently selected service provider (empty string initially, populated as policies are evaluated). | -| `service_provider_constraints` | The accumulated service-provider constraints from prior policies. | +| Field | Description | +| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------ | +| `spec` | The current (patched) request payload. While policies do not have to be specific for service types, they will need to know the expected content. | +| `constraints` | The accumulated constraints context from prior policies in the chain. | +| `provider` | The currently selected service provider (empty string initially, populated as policies are evaluated). | +| `service_provider_constraints` | The accumulated service-provider constraints from prior policies. | ##### How `input.spec` is Constructed The `input.spec` object is built from exactly two sources: -1. **Catalog item field defaults** — the `default` values declared in the catalog item's `fields` array +1. **Catalog item field defaults** — the `default` values declared in the + catalog item's `fields` array 2. **Instance user_values** — overrides provided when the instance is created -No other data reaches the policy engine. Arbitrary metadata or fields that are not declared in the [catalog item](../catalog-items/) are **not** included in `input.spec`. The catalog item acts as a governance boundary: if a field is not declared, policies cannot see it. +No other data reaches the policy engine. Arbitrary metadata or fields that are +not declared in the [catalog item](../catalog-items/) are **not** included in +`input.spec`. The catalog item acts as a governance boundary: if a field is not +declared, policies cannot see it. -This means labels must be declared as catalog item fields (using `metadata.labels.*` paths) for policies to inspect them. See [Fields and Policy Evaluation](../catalog-items/#fields-and-policy-evaluation) for more on declaring fields. +This means labels must be declared as catalog item fields (using +`metadata.labels.*` paths) for policies to inspect them. See +[Fields and Policy Evaluation](../catalog-items/#fields-and-policy-evaluation) +for more on declaring fields. ##### Example: Policy Using Instance Labels -The following end-to-end example shows how a `region` label flows from a catalog item field declaration through an instance and into a Rego policy. +The following end-to-end example shows how a `region` label flows from a catalog +item field declaration through an instance and into a Rego policy. -**1. Catalog item field** — declares `metadata.labels.region` with allowed values: +**1. Catalog item field** — declares `metadata.labels.region` with allowed +values: ```yaml fields: @@ -136,22 +153,26 @@ main := {"rejected": false, "selected_provider": provider} if { } ``` -> **Note:** If `metadata.labels.region` were not declared as a catalog item field, `input.spec.metadata.labels.region` would be undefined and the policy would have no value to evaluate. +> **Note:** If `metadata.labels.region` were not declared as a catalog item +> field, `input.spec.metadata.labels.region` would be undefined and the policy +> would have no value to evaluate. #### Output The `main` rule must return an object with the following fields: -| Field | Type | Required | Description | -|-------|------|----------|-------------| -| `rejected` | boolean | Yes | Set to `true` to reject the placement request. Requests are approved by default. | -| `rejection_reason` | string | No | A human-readable reason when the request is rejected. | -| `selected_provider` | string | No | The name of the service provider chosen to fulfill the request. | -| `service_provider_constraints` | object | No | Constraints on which service providers are allowed. Contains `allow_list` (list of allowed provider names) and `patterns` (list of regex patterns for matching allowed providers). | -| `patch` | map | No | A dictionary of values to set or override in the request payload. | -| `constraints` | map | No | Field constraints for subsequent policies, following [JSON Schema (draft 2020-12)](https://json-schema.org/draft/2020-12/json-schema-validation). Supports `const` (immutable), numeric constraints (`minimum`, `maximum`, `multipleOf`), string patterns (`pattern`, `minLength`, `maxLength`), enumerations (`enum`), array constraints (`minItems`, `maxItems`), and conditional logic (`if`/`then`/`else`). | +| Field | Type | Required | Description | +| ------------------------------ | ------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `rejected` | boolean | Yes | Set to `true` to reject the placement request. Requests are approved by default. | +| `rejection_reason` | string | No | A human-readable reason when the request is rejected. | +| `selected_provider` | string | No | The name of the service provider chosen to fulfill the request. | +| `service_provider_constraints` | object | No | Constraints on which service providers are allowed. Contains `allow_list` (list of allowed provider names) and `patterns` (list of regex patterns for matching allowed providers). | +| `patch` | map | No | A dictionary of values to set or override in the request payload. | +| `constraints` | map | No | Field constraints for subsequent policies, following [JSON Schema (draft 2020-12)](https://json-schema.org/draft/2020-12/json-schema-validation). Supports `const` (immutable), numeric constraints (`minimum`, `maximum`, `multipleOf`), string patterns (`pattern`, `minLength`, `maxLength`), enumerations (`enum`), array constraints (`minItems`, `maxItems`), and conditional logic (`if`/`then`/`else`). | -> **Note:** While no single policy is required to set the `selected_provider` field, the combination of all processed policies must set one; otherwise, placement will fail. +> **Note:** While no single policy is required to set the `selected_provider` +> field, the combination of all processed policies must set one; otherwise, +> placement will fail. ### Create Command @@ -190,12 +211,12 @@ dev-only-policy Dev Only USER 30 false 2026-04-12T ### Optional Flags -| Flag | Description | -|------|-------------| -| `--filter` | A CEL filter expression to narrow results. | -| `--order-by` | Field and direction to sort by (e.g., `"priority asc"`). | -| `--page-size` | Maximum number of results per page (int32). | -| `--page-token` | Token for retrieving the next page of results. | +| Flag | Description | +| -------------- | -------------------------------------------------------- | +| `--filter` | A CEL filter expression to narrow results. | +| `--order-by` | Field and direction to sort by (e.g., `"priority asc"`). | +| `--page-size` | Maximum number of results per page (int32). | +| `--page-token` | Token for retrieving the next page of results. | ### Filter and Sort Examples @@ -240,14 +261,16 @@ dcm policy get prefer-provider-a -o json "path": "policies/7eff7e73-4c14-4311-8673-e03916b00ece", "policy_type": "GLOBAL", "priority": 1, - "rego_code": "package provider.selector\n\nimport rego.v1\n\nspm_url := \"http://service-provider-manager:8080/api/v1alpha1/providers\"\n\nmain := {\"rejected\": true, \"rejection_reason\": \"spec.service_type is required\"} if {\n not input.spec.service_type\n}\n\nmain := result if {\n service_type := input.spec.service_type\n response := http.send({\n \"method\": \"GET\",\n \"url\": sprintf(\"%s?type=%s\", [spm_url, service_type]),\n \"headers\": {\"Accept\": \"application/json\"},\n })\n providers := response.body.providers\n ready_providers := [p | some p in providers; p.health_status == \"ready\"]\n result := _providers_result(ready_providers, service_type)\n}\n\n_providers_result(providers, service_type) := {\"rejected\": true, \"rejection_reason\": msg} if {\n count(providers) == 0\n msg := sprintf(\"no ready providers found for service type '%s'\", [service_type])\n}\n\n_providers_result(providers, _) := {\"rejected\": false, \"selected_provider\": provider} if {\n count(providers) \u003e 0\n sorted_names := sort([p.name | some p in providers])\n provider := sorted_names[0]\n}\n", + "rego_code": "package provider.selector\n\nimport rego.v1\n\nspm_url := \"http://control-plane:8080/api/v1alpha1/providers\"\n\nmain := {\"rejected\": true, \"rejection_reason\": \"spec.service_type is required\"} if {\n not input.spec.service_type\n}\n\nmain := result if {\n service_type := input.spec.service_type\n response := http.send({\n \"method\": \"GET\",\n \"url\": sprintf(\"%s?type=%s\", [spm_url, service_type]),\n \"headers\": {\"Accept\": \"application/json\"},\n })\n providers := response.body.providers\n ready_providers := [p | some p in providers; p.health_status == \"ready\"]\n result := _providers_result(ready_providers, service_type)\n}\n\n_providers_result(providers, service_type) := {\"rejected\": true, \"rejection_reason\": msg} if {\n count(providers) == 0\n msg := sprintf(\"no ready providers found for service type '%s'\", [service_type])\n}\n\n_providers_result(providers, _) := {\"rejected\": false, \"selected_provider\": provider} if {\n count(providers) \u003e 0\n sorted_names := sort([p.name | some p in providers])\n provider := sorted_names[0]\n}\n", "update_time": "2026-04-15T18:38:13.990296Z" } ``` ## Updating a Policy -Use `dcm policy update` with a patch file. The update uses **JSON Merge Patch** semantics -- only fields present in the patch file are modified; all other fields remain unchanged. +Use `dcm policy update` with a patch file. The update uses **JSON Merge Patch** +semantics -- only fields present in the patch file are modified; all other +fields remain unchanged. For example, to change the priority and disable a policy: @@ -267,7 +290,8 @@ Verify the update: dcm policy get prefer-provider-a ``` -> **Note:** You do not need to include every field in the patch file. Only the fields you want to change should be present. +> **Note:** You do not need to include every field in the patch file. Only the +> fields you want to change should be present. ## Deleting a Policy @@ -277,11 +301,14 @@ Use `dcm policy delete` with the policy ID: dcm policy delete prefer-provider-a ``` -> **Note:** Deleting a policy is permanent. Ensure the policy is no longer needed before deleting it. +> **Note:** Deleting a policy is permanent. Ensure the policy is no longer +> needed before deleting it. ## Policy Priority and Evaluation -During instance placement, DCM evaluates all **enabled** policies that match the request (based on the `label_selector`). If no matching policies are found, the request succeeds without policy evaluation. +During instance placement, DCM evaluates all **enabled** policies that match the +request (based on the `label_selector`). If no matching policies are found, the +request succeeds without policy evaluation. ### Evaluation Order @@ -290,24 +317,43 @@ Policies are sorted by **level** first, then by **priority** within each level: 1. **Global** policies run first. 2. **User** policies run last. -Within each level, policies are sorted by `priority` in ascending order (lower number = evaluated first). +Within each level, policies are sorted by `priority` in ascending order (lower +number = evaluated first). -> **Note:** Choose priority values with gaps (e.g., 10, 20, 30) so you can insert new policies between existing ones without renumbering. +> **Note:** Choose priority values with gaps (e.g., 10, 20, 30) so you can +> insert new policies between existing ones without renumbering. ### Evaluation Pipeline For each policy in order, the engine performs the following steps: -1. **Evaluate** the policy's Rego code. The `input` object includes the current patched `spec`, the accumulated `constraints`, the currently `selected_provider` (empty string initially), and the accumulated `service_provider_constraints`. -2. **Check rejection.** If the policy sets `rejected` to `true`, the placement request is denied immediately and the `rejection_reason` is returned to the caller. No further policies are evaluated. -3. **Validate constraints.** A lower-level policy cannot relax or remove a constraint set by a higher-level policy. If it attempts to do so, the request is aborted with a policy conflict error. -4. **Merge constraints.** New `constraints` from the policy are merged into the accumulated constraint context for subsequent policies. -5. **Validate patch.** The policy's `patch` is validated against the accumulated constraint context. For example, if a prior policy marked a field as immutable using a `const` constraint, any attempt to patch that field causes a policy conflict error. +1. **Evaluate** the policy's Rego code. The `input` object includes the current + patched `spec`, the accumulated `constraints`, the currently + `selected_provider` (empty string initially), and the accumulated + `service_provider_constraints`. +2. **Check rejection.** If the policy sets `rejected` to `true`, the placement + request is denied immediately and the `rejection_reason` is returned to the + caller. No further policies are evaluated. +3. **Validate constraints.** A lower-level policy cannot relax or remove a + constraint set by a higher-level policy. If it attempts to do so, the request + is aborted with a policy conflict error. +4. **Merge constraints.** New `constraints` from the policy are merged into the + accumulated constraint context for subsequent policies. +5. **Validate patch.** The policy's `patch` is validated against the accumulated + constraint context. For example, if a prior policy marked a field as + immutable using a `const` constraint, any attempt to patch that field causes + a policy conflict error. 6. **Apply patch.** Valid patches are applied to the request payload. -7. **Validate service provider.** If the policy returned a `selected_provider` and `service_provider_constraints` exist from prior policies, the selected provider is validated against those constraints. +7. **Validate service provider.** If the policy returned a `selected_provider` + and `service_provider_constraints` exist from prior policies, the selected + provider is validated against those constraints. -After all policies have been evaluated, the engine returns the final payload, the selected provider, and the evaluation status to the Placement Manager. The status is `APPROVED` if the payload was not modified, or `MODIFIED` if any patches were applied. +After all policies have been evaluated, the engine returns the final payload, +the selected provider, and the evaluation status to the Placement Manager. The +status is `APPROVED` if the payload was not modified, or `MODIFIED` if any +patches were applied. --- -For a step-by-step walkthrough, see [Create Placement Policy](../../getting-started/create-placement-policy/). +For a step-by-step walkthrough, see +[Create Placement Policy](../../getting-started/create-placement-policy/). diff --git a/content/docs/user-guide/providers.md b/content/docs/user-guide/providers.md index 4c716ec..04151a9 100644 --- a/content/docs/user-guide/providers.md +++ b/content/docs/user-guide/providers.md @@ -4,9 +4,14 @@ type: docs weight: 2 --- -Providers are infrastructure endpoints registered by service provider instances. Each provider represents a backend system — such as a KubeVirt-enabled Kubernetes cluster — that can host virtual machines or other resources managed through DCM. +Providers are infrastructure endpoints registered by service provider instances. +Each provider represents a backend system — such as a KubeVirt-enabled +Kubernetes cluster — that can host virtual machines or other resources managed +through DCM. -Providers are **read-only** in the CLI. They are created automatically when a service provider instance connects to DCM and registers its available infrastructure. +Providers are **read-only** in the CLI. They are created automatically when a +service provider instance connects to DCM and registers its available +infrastructure. ## Listing Providers @@ -34,10 +39,12 @@ dcm sp provider list --type vm ### Pagination -For environments with many providers, use pagination flags to control the output: +For environments with many providers, use pagination flags to control the +output: - `--page-size` — Maximum number of providers to return per page (int32). -- `--page-token` — Token for retrieving the next page of results (returned in the previous response). +- `--page-token` — Token for retrieving the next page of results (returned in + the previous response). ```bash dcm sp provider list --page-size 10 @@ -45,7 +52,8 @@ dcm sp provider list --page-size 10 ## Getting Provider Details -Use `dcm sp provider get` to retrieve detailed information about a single provider: +Use `dcm sp provider get` to retrieve detailed information about a single +provider: ```bash dcm sp provider get 3f8a1b2c-4d5e-6f7a-8b9c-0d1e2f3a4b5c @@ -77,9 +85,16 @@ Example JSON output: Each provider exposes two key fields: -- **STATUS** — Reflects the provider's registration state within DCM. A status of `registered` means the provider has been successfully registered and is recognized by the system. -- **HEALTH** — Reflects the result of the provider's last health check. A health value of `ready` indicates that the provider is reachable and operating normally. +- **STATUS** — Reflects the provider's registration state within DCM. A status + of `registered` means the provider has been successfully registered and is + recognized by the system. +- **HEALTH** — Reflects the result of the provider's last health check. A health + value of `ready` indicates that the provider is reachable and operating + normally. -These fields are updated automatically as service provider instances report to DCM. +These fields are updated automatically as service provider instances report to +DCM. -> **Note:** See [Register Another Provider](../../getting-started/register-another-provider/) for a walkthrough of adding a new provider. +> **Note:** See +> [Register Another Provider](../../getting-started/register-another-provider/) +> for a walkthrough of adding a new provider. diff --git a/content/docs/user-guide/service-provider-resources.md b/content/docs/user-guide/service-provider-resources.md index 18e9112..9307efd 100644 --- a/content/docs/user-guide/service-provider-resources.md +++ b/content/docs/user-guide/service-provider-resources.md @@ -4,11 +4,21 @@ type: docs weight: 7 --- -Service provider resources are the actual infrastructure resources — such as virtual machines, containers, or other services — created on [providers](../providers/) when [catalog item instances](../catalog-item-instances/) are provisioned. For example, when you deploy a catalog item instance for a VM on a KubeVirt provider, the service provider manager creates a KubeVirt VirtualMachine resource. That underlying resource is the SP resource. - -SP resources are managed entirely by the service provider manager and are **read-only** in the CLI. Each SP resource is linked to a specific catalog item instance and the provider where it was provisioned. - -> **Note:** You cannot create, update, or delete SP resources directly. They are created and cleaned up automatically as part of the catalog item instance lifecycle. +Service provider resources are the actual infrastructure resources — such as +virtual machines, containers, or other services — created on +[providers](../providers/) when +[catalog item instances](../catalog-item-instances/) are provisioned. For +example, when you deploy a catalog item instance for a VM on a KubeVirt +provider, the control plane creates a KubeVirt VirtualMachine resource. That +underlying resource is the SP resource. + +SP resources are managed entirely by the control plane and are **read-only** in +the CLI. Each SP resource is linked to a specific catalog item instance and the +provider where it was provisioned. + +> **Note:** You cannot create, update, or delete SP resources directly. They are +> created and cleaned up automatically as part of the catalog item instance +> lifecycle. ## Listing Resources @@ -37,7 +47,8 @@ dcm sp resource list --provider kubevirt-provider-1 ### Showing Deleted Resources -By default, deleted resources are hidden. Use `--show-deleted` to include them in the output. This adds a DELETION STATUS column: +By default, deleted resources are hidden. Use `--show-deleted` to include them +in the output. This adds a DELETION STATUS column: ```bash dcm sp resource list --show-deleted @@ -54,7 +65,8 @@ r-9e1a3c5d-7f20-4b68-a0c2-e4d6f8b1a3c5 container-provider-1 PENDING ### Pagination -For environments with many resources, use pagination flags to control the output: +For environments with many resources, use pagination flags to control the +output: ```bash dcm sp resource list --page-size 10 @@ -130,19 +142,31 @@ dcm sp resource get r-3b5d7f90-c1e3-4a26-98b0-d4f6a8c2e0a1 --show-deleted SP resources follow the lifecycle of the catalog item instances they belong to: -1. **Creation** — When a catalog item instance is provisioned, the service provider manager automatically creates the corresponding SP resource on the selected provider. -2. **Active state** — The STATUS field reflects the current state of the resource on the provider (e.g., PENDING while being created, READY when fully provisioned). -3. **Rehydration** - When a catalog item instance is rehydrated, a new resource will be created and upon success, the old one will be scheduled for deletion. -4. **Deletion** — When a catalog item instance is deleted, the corresponding SP resource is cleaned up by the service provider manager. -5. **Viewing deleted resources** — Deleted resources are hidden by default but can still be viewed using the `--show-deleted` flag, which adds a DELETION STATUS column to the output. - -> **Note:** Deleted items will show while they are scheduled for deletion. Once they are removed from the SP they will no longer exist +1. **Creation** — When a catalog item instance is provisioned, the control plane + automatically creates the corresponding SP resource on the selected provider. +2. **Active state** — The STATUS field reflects the current state of the + resource on the provider (e.g., PENDING while being created, READY when fully + provisioned). +3. **Rehydration** - When a catalog item instance is rehydrated, a new resource + will be created and upon success, the old one will be scheduled for deletion. +4. **Deletion** — When a catalog item instance is deleted, the corresponding SP + resource is cleaned up by the control plane. +5. **Viewing deleted resources** — Deleted resources are hidden by default but + can still be viewed using the `--show-deleted` flag, which adds a DELETION + STATUS column to the output. + +> **Note:** Deleted items will show while they are scheduled for deletion. Once +> they are removed from the SP they will no longer exist ## Relationship to Catalog Item Instances -Each [catalog item instance](../catalog-item-instances/) results in one SP resource on the provider selected during placement. The `resource_id` field on a catalog item instance links directly to the corresponding SP resource's ID. +Each [catalog item instance](../catalog-item-instances/) results in one SP +resource on the provider selected during placement. The `resource_id` field on a +catalog item instance links directly to the corresponding SP resource's ID. -For example, if a catalog item instance has `resource_id: r-7a9c2e41-b3d5-4f68-80a1-e2c4d6f8a0b2`, you can inspect the underlying provider resource with: +For example, if a catalog item instance has +`resource_id: r-7a9c2e41-b3d5-4f68-80a1-e2c4d6f8a0b2`, you can inspect the +underlying provider resource with: ```bash dcm sp resource get r-7a9c2e41-b3d5-4f68-80a1-e2c4d6f8a0b2 diff --git a/content/docs/user-guide/service-types.md b/content/docs/user-guide/service-types.md index 462697d..ab8989f 100644 --- a/content/docs/user-guide/service-types.md +++ b/content/docs/user-guide/service-types.md @@ -4,11 +4,15 @@ type: docs weight: 3 --- -Service types define the kinds of services that DCM can manage. Each service type represents a specific resource category — for example, virtual machines or containers. +Service types define the kinds of services that DCM can manage. Each service +type represents a specific resource category — for example, virtual machines or +containers. -Service types define the schema that [catalog items](../catalog-items/) must conform to, ensuring that resources are created with valid configurations. +Service types define the schema that [catalog items](../catalog-items/) must +conform to, ensuring that resources are created with valid configurations. -> **Note:** Currently, service types cannot be created or modified through the CLI. They are pre-registered by the Catalog Manager. +> **Note:** Currently, service types cannot be created or modified through the +> CLI. They are pre-registered by the Catalog Manager. ## Listing Service Types @@ -30,16 +34,17 @@ vm vm v1alpha1 2026-04-15T17:34:21.22490 The table columns are: -| Column | Description | -|--------|-------------| -| `UID` | Unique identifier for the service type | +| Column | Description | +| -------------- | ------------------------------------------------- | +| `UID` | Unique identifier for the service type | | `SERVICE TYPE` | The type name, typically in a `group/Kind` format | -| `API VERSION` | Schema version of the service type | -| `CREATED` | Timestamp when the service type was registered | +| `API VERSION` | Schema version of the service type | +| `CREATED` | Timestamp when the service type was registered | ### Pagination -For environments with many service types, use pagination flags to control the output: +For environments with many service types, use pagination flags to control the +output: ```bash dcm catalog service-type list --page-size 10 @@ -53,7 +58,8 @@ dcm catalog service-type list --page-size 10 --page-token "eyJvZmZzZXQiOjEwfQ==" ## Getting Service Type Details -Use `dcm catalog service-type get` to retrieve details for a specific service type: +Use `dcm catalog service-type get` to retrieve details for a specific service +type: ```bash dcm catalog service-type get a1b2c3d4-e5f6-7890-abcd-ef1234567890 @@ -80,6 +86,10 @@ Example JSON output: Service types sit at the foundation of the DCM resource model: -- **Catalog items** reference a service type and must conform to its schema. See [Catalog Items](../catalog-items/). -- **Providers** register with a specific service type, indicating what kinds of resources they can host. See [Providers](../providers/). -- **Catalog item instances** are ultimately deployed according to the schema defined by the service type. See [Catalog Item Instances](../catalog-item-instances/). +- **Catalog items** reference a service type and must conform to its schema. See + [Catalog Items](../catalog-items/). +- **Providers** register with a specific service type, indicating what kinds of + resources they can host. See [Providers](../providers/). +- **Catalog item instances** are ultimately deployed according to the schema + defined by the service type. See + [Catalog Item Instances](../catalog-item-instances/). diff --git a/content/docs/user-guide/ui.md b/content/docs/user-guide/ui.md index 68e42b3..eeeb08f 100644 --- a/content/docs/user-guide/ui.md +++ b/content/docs/user-guide/ui.md @@ -4,7 +4,10 @@ type: docs weight: 8 --- -The DCM UI is a [Backstage](https://backstage.io/) plugin that provides a web interface for managing DCM resources. It offers the same resource management capabilities as the CLI, presented as interactive data tables with inline search, pagination, and action buttons. +The DCM UI is a [Backstage](https://backstage.io/) plugin that provides a web +interface for managing DCM resources. It offers the same resource management +capabilities as the CLI, presented as interactive data tables with inline +search, pagination, and action buttons. ## Accessing the Backstage UI @@ -12,7 +15,8 @@ To open the Backstage UI, first determine the URL for your deployment. **On a cluster (OpenShift):** -Run the following command, replacing `` with the namespace where DCM is deployed: +Run the following command, replacing `` with the namespace where +DCM is deployed: ```bash oc get routes -n @@ -22,42 +26,53 @@ Copy the URL from the `HOST/PORT` column and open it in your browser. **Local setup:** -If running DCM locally, Backstage is typically available at `http://localhost:3000`. +If running DCM locally, Backstage is typically available at +`http://localhost:7007`. -Once you have the Backstage URL open, navigate to **Administration → Data Center** in the Backstage sidebar, or go directly to `/dcm`. +Once you have the Backstage URL open, navigate to **Administration → Data +Center** in the Backstage sidebar, or go directly to `/dcm`. -The Data Center page is organized into six tabs, one for each core DCM resource type. +The Data Center page is organized into six tabs, one for each core DCM resource +type. ## Common patterns All tabs share the following interaction patterns: -- **Search** — A search field in the card header filters the table rows in real time across visible columns. -- **Pagination** — Each table supports 5, 10, or 25 rows per page. The selected page size is persisted across sessions. -- **Action buttons** — Row-level actions appear as icon buttons in the **Actions** column. Destructive actions open a confirmation dialog before proceeding. -- **Empty state** — When no data is available, the table shows an empty state with a prompt to create the first resource where applicable. +- **Search** — A search field in the card header filters the table rows in real + time across visible columns. +- **Pagination** — Each table supports 5, 10, or 25 rows per page. The selected + page size is persisted across sessions. +- **Action buttons** — Row-level actions appear as icon buttons in the + **Actions** column. Destructive actions open a confirmation dialog before + proceeding. +- **Empty state** — When no data is available, the table shows an empty state + with a prompt to create the first resource where applicable. ## Providers -The Providers tab lists all infrastructure providers registered with DCM. Providers are created automatically when service provider instances connect and register their available infrastructure. +The Providers tab lists all infrastructure providers registered with DCM. +Providers are created automatically when service provider instances connect and +register their available infrastructure. ![Providers tab showing a table of registered providers with columns for display name, name, endpoint, service type, operations, status, and actions](/images/ui/providers-tab.png) ### Columns -| Column | Description | -|--------|-------------| -| Display name | Human-readable label, with the provider ID shown as a caption below. | -| Name | Unique internal name of the provider. | -| Endpoint | The provider's API endpoint URL, with a copy button. | -| Service type | The service type the provider supports (e.g., `vm`). | -| Operations | Operations the provider exposes, shown as chips. Overflow is shown as a "+N" tooltip. | -| Status | Current health status of the provider. | -| Actions | Edit and delete buttons. | +| Column | Description | +| ------------ | ------------------------------------------------------------------------------------- | +| Display name | Human-readable label, with the provider ID shown as a caption below. | +| Name | Unique internal name of the provider. | +| Endpoint | The provider's API endpoint URL, with a copy button. | +| Service type | The service type the provider supports (e.g., `vm`). | +| Operations | Operations the provider exposes, shown as chips. Overflow is shown as a "+N" tooltip. | +| Status | Current health status of the provider. | +| Actions | Edit and delete buttons. | ### Actions -- **Register provider** — Opens a dialog to register a new provider (display name, name, endpoint, service type, operations). +- **Register provider** — Opens a dialog to register a new provider (display + name, name, endpoint, service type, operations). - **Edit** — Opens the edit dialog pre-filled with the current values. - **Delete** — Opens a confirmation dialog before removing the provider. - **Copy endpoint** — Copies the provider's API endpoint URL to the clipboard. @@ -72,73 +87,88 @@ The Policies tab lists all OPA Rego policies configured in DCM. ### Columns -| Column | Description | -|--------|-------------| -| Display name | Human-readable label, with the policy ID shown as a caption below. | -| Type | Policy scope (`GLOBAL` or `USER`). | -| Priority | Numeric evaluation order. Lower numbers are evaluated first (default: 500). | -| Enabled | Whether the policy is active (`Yes` or `No`). | -| Description | Short description of the policy's purpose. | -| Actions | An enable/disable toggle switch, an edit button, and a delete button. | +| Column | Description | +| ------------ | --------------------------------------------------------------------------- | +| Display name | Human-readable label, with the policy ID shown as a caption below. | +| Type | Policy scope (`GLOBAL` or `USER`). | +| Priority | Numeric evaluation order. Lower numbers are evaluated first (default: 500). | +| Enabled | Whether the policy is active (`Yes` or `No`). | +| Description | Short description of the policy's purpose. | +| Actions | An enable/disable toggle switch, an edit button, and a delete button. | ### Actions -- **Create policy** — Opens a dialog to create a new policy (display name, type, priority, enabled toggle, description, Rego code). +- **Create policy** — Opens a dialog to create a new policy (display name, type, + priority, enabled toggle, description, Rego code). - **Edit** — Opens the edit dialog pre-filled with the current values. - **Delete** — Opens a confirmation dialog before removing the policy. -- **Enable/Disable toggle** — Immediately enables or disables the policy inline, without opening a dialog. Disabled policies are not evaluated during instance placement. +- **Enable/Disable toggle** — Immediately enables or disables the policy inline, + without opening a dialog. Disabled policies are not evaluated during instance + placement. -> **Note:** For details on writing Rego code for DCM policies, including the expected input/output structure, see [Policies](../policies/#rego-rule-structure). +> **Note:** For details on writing Rego code for DCM policies, including the +> expected input/output structure, see +> [Policies](../policies/#rego-rule-structure). For CLI equivalent operations, see [Policies](../policies/). ## Service Types -The Service Types tab is a read-only view of all service type schemas registered in DCM. Service types define the structure and available fields for catalog items. They are created automatically when service provider instances register with DCM. +The Service Types tab is a read-only view of all service type schemas registered +in DCM. Service types define the structure and available fields for catalog +items. They are created automatically when service provider instances register +with DCM. ![Service Types tab showing a read-only table of service type schemas with columns for service type, API version, path, and created date](/images/ui/service-types-tab.png) ### Columns -| Column | Description | -|--------|-------------| +| Column | Description | +| ------------ | ---------------------------------------------------------------- | | Service type | Name of the service type, with its UID shown as a caption below. | -| API version | Schema version of the service type (e.g., `v1alpha1`). | -| Path | Resource path for the service type definition. | -| Created | Date and time the service type was registered. | +| API version | Schema version of the service type (e.g., `v1alpha1`). | +| Path | Resource path for the service type definition. | +| Created | Date and time the service type was registered. | ### Actions -Search, sort by column header, and pagination are available. There are no create, edit, or delete actions. +Search, sort by column header, and pagination are available. There are no +create, edit, or delete actions. For CLI equivalent operations, see [Service Types](../service-types/). ## Catalog Items -The Catalog Items tab lists all catalog items in DCM. Create and edit operations open a **side drawer** on the right side of the screen rather than a modal dialog. +The Catalog Items tab lists all catalog items in DCM. Create and edit operations +open a **side drawer** on the right side of the screen rather than a modal +dialog. ![Catalog Items tab showing a table of catalog items with columns for display name, API version, service type, fields count, created date, and actions](/images/ui/catalog-items-tab.png) ### Columns -| Column | Description | -|--------|-------------| -| Display name | Human-readable label for the catalog item. | -| API version | Schema version of the catalog item (e.g., `v1alpha1`). | -| Service type | The service type this catalog item is based on. | -| Fields | Number of configurable fields defined in the catalog item (e.g., `3 fields`). | -| Created | Date and time the catalog item was created. | -| Actions | Edit and delete buttons. | +| Column | Description | +| ------------ | ----------------------------------------------------------------------------- | +| Display name | Human-readable label for the catalog item. | +| API version | Schema version of the catalog item (e.g., `v1alpha1`). | +| Service type | The service type this catalog item is based on. | +| Fields | Number of configurable fields defined in the catalog item (e.g., `3 fields`). | +| Created | Date and time the catalog item was created. | +| Actions | Edit and delete buttons. | ### Actions -- **Create catalog item** — Opens the side drawer to define a new catalog item (display name, API version, service type, fields configuration). +- **Create catalog item** — Opens the side drawer to define a new catalog item + (display name, API version, service type, fields configuration). - **Edit** — Opens the side drawer pre-filled with the current values. - **Delete** — Opens a confirmation dialog before removing the catalog item. -> **Note:** Deleting a catalog item does not automatically delete existing instances created from it. Manage instances separately in the [Instances](#instances) tab. +> **Note:** Deleting a catalog item does not automatically delete existing +> instances created from it. Manage instances separately in the +> [Instances](#instances) tab. -For CLI equivalent operations and a full field reference, see [Catalog Items](../catalog-items/). +For CLI equivalent operations and a full field reference, see +[Catalog Items](../catalog-items/). ## Instances @@ -148,41 +178,53 @@ The Instances tab lists all provisioned catalog item instances. ### Columns -| Column | Description | -|--------|-------------| -| Display name | Human-readable label for the instance. | +| Column | Description | +| ------------ | ---------------------------------------------------------------- | +| Display name | Human-readable label for the instance. | | Catalog item | The catalog item the instance was created from, shown as a chip. | -| Resource ID | ID of the underlying service provider resource (truncated). | -| API version | Schema version of the instance (e.g., `v1alpha1`). | -| Created | Date and time the instance was created. | -| Actions | A rehydrate button and a delete button. | +| Resource ID | ID of the underlying service provider resource (truncated). | +| API version | Schema version of the instance (e.g., `v1alpha1`). | +| Created | Date and time the instance was created. | +| Actions | A rehydrate button and a delete button. | ### Actions -- **Create instance** — Opens a dialog to deploy a new instance (display name, catalog item selection, user values for editable fields). -- **Rehydrate** — Re-triggers the provisioning flow for the instance. Useful when a provider has recovered from a failure, the underlying resource needs to be recreated, or placement policies have changed. A new resource is provisioned before the old one is deleted. -- **Delete** — Opens a confirmation dialog before removing the instance. Deletion also triggers cleanup of the underlying resource on the provider. +- **Create instance** — Opens a dialog to deploy a new instance (display name, + catalog item selection, user values for editable fields). +- **Rehydrate** — Re-triggers the provisioning flow for the instance. Useful + when a provider has recovered from a failure, the underlying resource needs to + be recreated, or placement policies have changed. A new resource is + provisioned before the old one is deleted. +- **Delete** — Opens a confirmation dialog before removing the instance. + Deletion also triggers cleanup of the underlying resource on the provider. -For CLI equivalent operations, see [Catalog Item Instances](../catalog-item-instances/). +For CLI equivalent operations, see +[Catalog Item Instances](../catalog-item-instances/). ## Resources -The Resources tab is a read-only view of all service type instances provisioned through DCM — the actual infrastructure resources created on providers when catalog item instances are deployed. +The Resources tab is a read-only view of all service type instances provisioned +through DCM — the actual infrastructure resources created on providers when +catalog item instances are deployed. ![Resources tab showing a read-only table of provisioned resources with columns for ID, service type, provider, status, and created date](/images/ui/resources-tab.png) ### Columns -| Column | Description | -|--------|-------------| -| ID | Unique identifier of the service provider resource. | -| Service type | Service type of this resource (e.g., `vm`). | -| Provider | Name of the provider where this resource is hosted. | -| Status | Current state of the resource on the provider (e.g., `Scheduling`, `Ready`). | -| Created | Date and time the resource was created. | +| Column | Description | +| ------------ | ---------------------------------------------------------------------------- | +| ID | Unique identifier of the service provider resource. | +| Service type | Service type of this resource (e.g., `vm`). | +| Provider | Name of the provider where this resource is hosted. | +| Status | Current state of the resource on the provider (e.g., `Scheduling`, `Ready`). | +| Created | Date and time the resource was created. | ### Actions -Search and pagination are available. If the tab fails to load, an error alert with a **Retry** button is shown in place of the table. There are no create, edit, or delete actions — resources are managed automatically through the instance lifecycle. +Search and pagination are available. If the tab fails to load, an error alert +with a **Retry** button is shown in place of the table. There are no create, +edit, or delete actions — resources are managed automatically through the +instance lifecycle. -For CLI equivalent operations and a full explanation of the resource lifecycle, see [Service Provider Resources](../service-provider-resources/). +For CLI equivalent operations and a full explanation of the resource lifecycle, +see [Service Provider Resources](../service-provider-resources/).