Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,6 @@
# Defaults are for local dev and subsystem tests only.
# POSTGRES_USER=admin
# POSTGRES_PASSWORD=adminpass
#
# For the full platform stack (UI, service providers, image version pins),
# see deploy/.env.example.
43 changes: 39 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,16 @@ $(error No supported container engine found. Please install podman or docker, or
endif

COMPOSE_FILE := deploy/compose.yaml
COMPOSE_PROJECT_NAME ?= control-plane
COMPOSE_NETWORK := $(COMPOSE_PROJECT_NAME)_default
PROFILES ?= providers

COMPOSE ?= $(shell command -v podman-compose >/dev/null 2>&1 && echo podman-compose || \
(command -v docker-compose >/dev/null 2>&1 && echo docker-compose || \
(echo "$(CONTAINER_ENGINE) compose")))

export COMPOSE_PROJECT_NAME

CONTAINER_IMAGE_NAME ?= quay.io/dcm-project/$(BINARY_NAME)
CONTAINER_IMAGE_TAG ?= $(shell git rev-parse --short HEAD 2>/dev/null || echo unknown)

Expand All @@ -41,12 +46,42 @@ run:
run-dev:
go run ./cmd/$(BINARY_NAME)

# Local dev stack: Postgres, NATS, and control-plane (see deploy/compose.yaml).
# Platform stack: Postgres, NATS, control-plane, and dcm-ui (see deploy/compose.yaml).
compose-up:
$(COMPOSE) -f $(COMPOSE_FILE) up -d --build

# Platform stack with optional service providers (see deploy/RUN.md).
compose-up-with-providers:
$(COMPOSE) -f $(COMPOSE_FILE) --profile $(PROFILES) up -d --build

# Tear down the compose stack. Kind (or other externals) joined to the compose
# network block "compose down" from removing it — disconnect them first.
# Network cleanup uses podman- or docker-specific commands (not portable flags).
compose-down:
$(COMPOSE) -f $(COMPOSE_FILE) down -v
@for network in deploy_default $(COMPOSE_NETWORK); do \
if [ "$(CONTAINER_ENGINE)" = podman ]; then \
if podman network exists "$$network" 2>/dev/null; then \
for c in $$(podman ps -a --filter network=$$network -q 2>/dev/null); do \
podman network disconnect -f "$$network" "$$c" 2>/dev/null || true; \
done; \
fi; \
elif [ "$(CONTAINER_ENGINE)" = docker ]; then \
if docker network inspect "$$network" >/dev/null 2>&1; then \
for c in $$(docker ps -a --filter network=$$network -q 2>/dev/null); do \
docker network disconnect "$$network" "$$c" --force 2>/dev/null || true; \
done; \
fi; \
fi; \
done; \
COMPOSE_PROJECT_NAME=deploy $(COMPOSE) -f $(COMPOSE_FILE) down -v --remove-orphans 2>/dev/null || true; \
$(COMPOSE) -f $(COMPOSE_FILE) down -v --remove-orphans; \
for network in deploy_default $(COMPOSE_NETWORK); do \
if [ "$(CONTAINER_ENGINE)" = podman ]; then \
podman network rm -f "$$network" 2>/dev/null || true; \
elif [ "$(CONTAINER_ENGINE)" = docker ]; then \
docker network rm "$$network" 2>/dev/null || true; \
fi; \
done

image-build:
$(CONTAINER_ENGINE) build -f Containerfile -t $(CONTAINER_IMAGE_NAME):$(CONTAINER_IMAGE_TAG) .
Expand Down Expand Up @@ -74,5 +109,5 @@ test:
tidy:
go mod tidy

.PHONY: build run run-dev compose-up compose-down image-build clean fmt vet lint test \
test-catalog test-placement test-policy test-sp tidy
.PHONY: build run run-dev compose-up compose-up-with-providers compose-down image-build \
clean fmt vet lint test test-catalog test-placement test-policy test-sp tidy
41 changes: 37 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ internal/sp/ # service provider manager
api/ # OpenAPI specs per domain
pkg/ # generated HTTP clients
test/subsystem/ # per-domain subsystem tests
deploy/ # compose and postgres init
deploy/ # platform compose, helm chart, postgres init
```

See the [control plane monolith enhancement](https://github.com/dcm-project/enhancements/tree/main/enhancements/control-plane-monolith).
Expand All @@ -36,17 +36,17 @@ Run the monolith (pick one):
|---------|---------------|----------|------------|
| `make run` | host | SQLite at `/tmp/control-plane.db` | NATS disabled |
| `make run-dev` | host | Postgres (`DB_*` defaults) | Postgres + NATS running locally |
| `make compose-up` | containers | Postgres in compose | also starts NATS and control-plane |
| `make compose-up` | containers | Postgres in compose | also starts NATS, control-plane, and dcm-ui |

```bash
make run # SQLite, no containers
make compose-up # full stack in containers
make compose-up # platform stack in containers
make compose-down # stop stack and remove volumes
```

Compose uses `POSTGRES_USER` and `POSTGRES_PASSWORD` (defaults in compose
are for local dev only). Override via environment or a `.env` file; see
`.env.example`.
`deploy/.env.example`.

Policy evaluation and placement provisioning run in-process in the monolith
(`EvaluationService`, `PlacementService` via local clients). There is no public
Expand All @@ -71,3 +71,36 @@ CI pushes to `quay.io/dcm-project/control-plane` on merges to `main` and
`release/v*` branches (and on version tags). See
[Releasing](https://github.com/dcm-project/shared-workflows#release-flow)
in shared-workflows for tag behavior and version conventions.

## Platform deploy

Full-stack Compose and Helm packaging live under `deploy/`:

- **Compose:** control-plane, postgres, nats, dcm-ui, and optional service providers
- **Helm:** Kubernetes/OpenShift chart at `deploy/helm/dcm`

See [deploy/RUN.md](deploy/RUN.md) for local stack usage and service provider profiles.
See [deploy/helm/dcm/README.md](deploy/helm/dcm/README.md) for cluster installs.

The control-plane API is exposed on `:8080`.

### Image versions

Service repos push images to `quay.io/dcm-project/<service>` with the following tags:

| Tag format | Example | When created |
|---|---|---|
| `main` | `main` | Every push to `main` |
| `<short-sha>` | `a6882f7` | Every push to `main` or `release/v*` branch, and `v*` git tag pushes |
| `v<semver>-rc.N` | `v0.0.1-rc.2` | Retag script (promotes a release branch SHA to an RC tag) |
| `v<semver>` | `v0.0.1` | When a `v*` git tag is pushed (final release) |

Browse available tags at `https://quay.io/repository/dcm-project/<service>?tab=tags`.

Pin versions in `.env` (see `deploy/.env.example`):

```bash
CONTROL_PLANE_VERSION=v0.0.1
```

Omitting the variable defaults to `main`.
37 changes: 37 additions & 0 deletions deploy/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Optional: copy to .env in the repo root and set for local overrides.
# Used by deploy/compose.yaml. Defaults (admin / adminpass) are for local dev only.
# POSTGRES_USER=admin
# POSTGRES_PASSWORD=adminpass

# K8s container service provider (profile: k8s-container)
# K8S_CONTAINER_SP_KUBECONFIG=/path/to/kubeconfig
# K8S_CONTAINER_SP_NAMESPACE=default
# K8S_CONTAINER_SP_NAME=k8s-container-provider
# K8S_CONTAINER_SP_EXTERNAL_SVC_TYPE=NodePort

# Three-tier demo app service provider (profile: three-tier)
# Same kubeconfig + cluster namespace as k8s-container (K8S_CONTAINER_SP_* above).
# THREE_TIER_SP_NAME=three-tier-provider

# ACM cluster service provider (profile: acm-cluster)
# Supports two platforms: KubeVirt (default) and BareMetal.
# Both enabled by default (SP_ENABLED_PLATFORMS=kubevirt,baremetal).
# ACM_CLUSTER_SP_NAME=acm-cluster-sp
# ACM_CLUSTER_SP_BASE_DOMAIN=apps.example.com
# ACM_CLUSTER_SP_PULL_SECRET=<base64-encoded-dockerconfigjson>
# BareMetal platform only — not used by KubeVirt:
# ACM_CLUSTER_SP_DEFAULT_INFRA_ENV=my-infra-env
# ACM_CLUSTER_SP_AGENT_NAMESPACE=my-agent-namespace

# --- Service image versions ---
# Pin specific versions instead of "main". Valid values:
# main - most recent main build (default)
# v0.0.1 - final release (from git tag)
# v0.0.1-rc.3 - release candidate (from release branch)
# abc1234 - specific commit build (for local testing only)
# CONTROL_PLANE_VERSION=main
# KUBEVIRT_SERVICE_PROVIDER_VERSION=main
# K8S_CONTAINER_SERVICE_PROVIDER_VERSION=main
# ACM_CLUSTER_SERVICE_PROVIDER_VERSION=main
# THREE_TIER_DEMO_SERVICE_PROVIDER_VERSION=main
# DCM_UI_VERSION=main
197 changes: 197 additions & 0 deletions deploy/RUN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
# Running DCM

## Prerequisites

- [Podman](https://podman.io/) or [Docker](https://www.docker.com/) (the Makefile auto-detects which engine is available)
- (Optional) A Kubernetes cluster with KubeVirt for the kubevirt-service-provider
- (Optional) A Kubernetes cluster for the k8s-container-service-provider
- (Optional) An OpenShift cluster with ACM/MCE and HyperShift for the acm-cluster-service-provider

## Quick start

Start the core platform (postgres, nats, control-plane, and dcm-ui):

```bash
make compose-up
```

The control-plane API is at `http://localhost:8080`. DCM UI is at `http://localhost:7007`.

## CLI configuration

The [DCM CLI](https://github.com/dcm-project/cli) uses the same control-plane URL by default
(`http://localhost:8080`). Override it with the `control-plane-url` key in `~/.dcm/config.yaml`
or the `DCM_CONTROL_PLANE_URL` environment variable. See the [CLI README](https://github.com/dcm-project/cli/blob/main/README.md)
for install and usage.

## Running with service providers

Service providers are behind compose profiles and do not start by default.

### KubeVirt service provider

To include the `kubevirt-service-provider`, set the required environment variables and
activate the `kubevirt` profile:

```bash
export KUBERNETES_NAMESPACE=vms
export KUBEVIRT_KUBECONFIG="/path/to/kubeconfig"
make compose-up-with-providers PROFILES=kubevirt
```

### K8s container service provider

To include the `k8s-container-service-provider`, set the required environment variables and
activate the `k8s-container` profile:

```bash
export K8S_CONTAINER_SP_KUBECONFIG="/path/to/kubeconfig"
make compose-up-with-providers PROFILES=k8s-container
```

If using Kind, see [K8s Container SP with Kind](docs/k8s-container-sp-kind.md) for additional network setup.

Optionally override the provider name or external service type:

```bash
export K8S_CONTAINER_SP_NAME=my-provider
export K8S_CONTAINER_SP_EXTERNAL_SVC_TYPE=LoadBalancer
```

### ACM cluster service provider

To include the `acm-cluster-service-provider`, set the required environment variables and
activate the `acm-cluster` profile:

```bash
export ACM_CLUSTER_SP_KUBECONFIG="/path/to/kubeconfig"
export ACM_CLUSTER_SP_PULL_SECRET="<base64-encoded-dockerconfigjson>"
make compose-up-with-providers PROFILES=acm-cluster
```

Optionally override the provider name, namespace, or base domain:

```bash
export ACM_CLUSTER_SP_NAME=my-acm-provider
export ACM_CLUSTER_SP_NAMESPACE=clusters
export ACM_CLUSTER_SP_BASE_DOMAIN="apps.example.com"
```

For BareMetal provisioning, also set:

```bash
export ACM_CLUSTER_SP_DEFAULT_INFRA_ENV="my-infra-env"
export ACM_CLUSTER_SP_AGENT_NAMESPACE="my-agent-namespace"
```

### Three-tier demo app service provider

To include the `three-tier-demo-service-provider`, set the required environment variables and
activate the `three-tier` profile:

```bash
export K8S_CONTAINER_SP_KUBECONFIG="/path/to/kubeconfig"
make compose-up-with-providers PROFILES=three-tier
```

When using Kind, complete the k8s-container setup (steps 1–5 in [K8s Container
SP with Kind](docs/k8s-container-sp-kind.md)) first.
For Pet Clinic usage, see [Three-Tier Demo App with Kind](docs/three-tier-app-kind.md).

Optionally override the provider name or cluster namespace (`K8S_CONTAINER_SP_NAMESPACE` applies
to both k8s-container and three-tier SPs):

```bash
export THREE_TIER_SP_NAME=my-provider
export K8S_CONTAINER_SP_NAMESPACE=default
```

### All providers

To start all providers at once, set the required environment variables and run:

```bash
export KUBEVIRT_KUBECONFIG="/path/to/kubeconfig"
export K8S_CONTAINER_SP_KUBECONFIG="/path/to/kubeconfig"
export ACM_CLUSTER_SP_KUBECONFIG="/path/to/kubeconfig"
export ACM_CLUSTER_SP_PULL_SECRET="<base64-encoded-dockerconfigjson>"
# BareMetal only:
export ACM_CLUSTER_SP_DEFAULT_INFRA_ENV="my-infra-env"
export ACM_CLUSTER_SP_AGENT_NAMESPACE="my-agent-namespace"
make compose-up-with-providers
```

This defaults to the `providers` Compose profile (all service providers, including the
three-tier demo SP). To start a single provider instead, pass `PROFILES=`:

```bash
make compose-up-with-providers PROFILES=kubevirt
make compose-up-with-providers PROFILES=k8s-container
make compose-up-with-providers PROFILES=acm-cluster
make compose-up-with-providers PROFILES=three-tier
```

## Verifying the deployment

Check that all services are running:

```bash
podman compose -f deploy/compose.yaml ps # or: docker compose -f deploy/compose.yaml ps
```

Check the health endpoint:

```bash
curl http://localhost:8080/api/v1alpha1/health
```

Check health endpoint through DCM UI:

```bash
curl http://localhost:7007/api/dcm/health
```

## Stopping services

```bash
make compose-down
```

This stops all compose services and removes volumes. If Kind was connected to
the compose network (see [k8s-container-sp-kind.md](docs/k8s-container-sp-kind.md)),
`compose-down` disconnects external containers and removes both
`control-plane_default` and legacy `deploy_default` networks.

## Configuration

| Variable | Default | Description |
| ------------------------------------------ | --------------------------- | ----------------------------------------------------------------------------------------------------------- |
| `POSTGRES_USER` | `admin` | PostgreSQL username |
| `POSTGRES_PASSWORD` | `adminpass` | PostgreSQL password |
| `KUBERNETES_NAMESPACE` | `default` | Kubernetes namespace for KubeVirt VMs |
| `KUBEVIRT_KUBECONFIG` | `~/.kube/config` | Path to kubeconfig on the host |
| `KUBEVIRT_PROVIDER_NAME` | `kubevirt-service-provider` | Provider name and Compose service `container_name` |
| `K8S_CONTAINER_SP_KUBECONFIG` | `~/.kube/config` | Path to kubeconfig on the host for the k8s-container-service-provider |
| `K8S_CONTAINER_SP_NAMESPACE` | `default` | Kubernetes namespace for k8s containers |
| `K8S_CONTAINER_SP_NAME` | `k8s-container-provider` | Provider name for the k8s-container-service-provider |
| `K8S_CONTAINER_SP_EXTERNAL_SVC_TYPE` | `NodePort` | Kubernetes Service type for external ports (`NodePort` or `LoadBalancer`) |
| `ACM_CLUSTER_SP_KUBECONFIG` | `~/.kube/config` | Path to kubeconfig on the host for the acm-cluster-service-provider |
| `ACM_CLUSTER_SP_NAMESPACE` | `default` | Kubernetes namespace for ACM hosted clusters |
| `ACM_CLUSTER_SP_NAME` | `acm-cluster-sp` | Provider name for the acm-cluster-service-provider |
| `ACM_CLUSTER_SP_BASE_DOMAIN` | _(none)_ | Base DNS domain for hosted clusters; can be overridden per-request via `provider_hints.acm.base_domain` |
| `ACM_CLUSTER_SP_PULL_SECRET` | _(required)_ | Base64-encoded dockerconfigjson pull secret for ACM hosted clusters |
| `ACM_CLUSTER_SP_DEFAULT_INFRA_ENV` | _(none)_ | **BareMetal only.** Default InfraEnv name; can be overridden per-request via `provider_hints.acm.infra_env` |
| `ACM_CLUSTER_SP_AGENT_NAMESPACE` | _(none)_ | **BareMetal only.** Namespace where Agent resources are located |
| `CONTROL_PLANE_VERSION` | `main` | Image tag for control-plane monolith |
| `KUBEVIRT_SERVICE_PROVIDER_VERSION` | `main` | Image tag for kubevirt-service-provider |
| `K8S_CONTAINER_SERVICE_PROVIDER_VERSION` | `main` | Image tag for k8s-container-service-provider |
| `ACM_CLUSTER_SERVICE_PROVIDER_VERSION` | `main` | Image tag for acm-cluster-service-provider |
| `THREE_TIER_DEMO_SERVICE_PROVIDER_VERSION` | `main` | Image tag for three-tier-demo-service-provider |
| `THREE_TIER_SP_NAME` | `three-tier-provider` | Provider name for the three-tier-demo-service-provider |
| `DCM_UI_VERSION` | `main` | Image tag for dcm-ui |

See [Image versions](../README.md#image-versions) in the README for available tag formats and how to update.

## Kubernetes / OpenShift

See [helm/dcm/README.md](helm/dcm/README.md).
17 changes: 17 additions & 0 deletions deploy/compose.override.example.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# OpenShift: Route-based web exposure for three-tier-demo-service-provider.
# For Kind / default kubernetes exposure, do not install an override (remove
# deploy/compose.override.yaml if present).
#
# cp deploy/compose.override.example.yaml deploy/compose.override.yaml
#
# Match SP_OPENSHIFT_ROUTE_NAMESPACE to the k8s container SP namespace (same as
# K8S_CONTAINER_SP_NAMESPACE in .env). See deploy/docs/three-tier-app-kind.md.

services:
three-tier-demo-service-provider:
environment:
SP_WEB_EXPOSURE: openshift
SP_OPENSHIFT_ROUTE_NAMESPACE: ${K8S_CONTAINER_SP_NAMESPACE:-default}
SP_OPENSHIFT_KUBECONFIG: /openshift-kubeconfig
volumes:
- ${KUBECONFIG:-$HOME/.kube/config}:/openshift-kubeconfig:ro,z
Loading