Skip to content

Commit 8d2aa87

Browse files
jcpowermacclaude
andcommitted
Add user and developer documentation
User docs cover installation with and without OLM. Developer docs cover the API reference, architecture/reconciliation flow, and the build/test/deploy workflow. README simplified to link both. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent f00c12b commit 8d2aa87

6 files changed

Lines changed: 603 additions & 204 deletions

File tree

README.md

Lines changed: 19 additions & 204 deletions
Original file line numberDiff line numberDiff line change
@@ -1,222 +1,37 @@
11
# vcf-migration-operator
22

3-
Kubernetes operator and OpenShift Console plugin for orchestrating migration of OpenShift clusters between VMware vCenters (e.g. VMware Cloud Foundation / VCF). Use the operator to drive the migration lifecycle and the console plugin to create migrations, browse vCenter inventory, and monitor progress from the OpenShift web console.
3+
Kubernetes operator and OpenShift Console plugin for migrating OpenShift clusters between VMware vCenters (e.g. VMware Cloud Foundation environments).
44

5-
## Description
5+
The operator reconciles the `VmwareCloudFoundationMigration` custom resource through a multi-phase workflow: preflight validation, destination initialization, multi-site configuration, workload migration (workers + control plane), source cleanup, and final health checks. The optional console plugin provides a web UI for creating migrations, browsing vCenter inventory, and monitoring progress.
66

7-
vcf-migration-operator automates moving an OpenShift cluster from a source vCenter to a target vCenter. The project consists of:
7+
## Documentation
88

9-
- **Operator**: A Kubebuilder-based controller that reconciles the `VmwareCloudFoundationMigration` custom resource. It prepares infrastructure (credentials, failure domains), initializes the destination, configures multi-site, migrates workload (machines/nodes), and cleans up the source. The operator uses the cluster's Machine API and OpenShift-specific resources; vSphere operations are performed via govmomi against the target vCenter.
9+
- **User Guide**
10+
- [Install with OLM](docs/user/install-with-olm.md)
11+
- [Install without OLM](docs/user/install-without-olm.md)
1012

11-
- **OpenShift Console Plugin**: A dynamic plugin that adds a "VCF Migration" section to the OpenShift console (Administrator perspective). It provides a list of migrations, a create wizard (credentials + vCenter browse for failure domains), and a detail view with condition progress, live event stream (SSE), and machine topology. The plugin backend is a Go HTTP server that serves the webpack-built frontend and exposes API routes for vCenter inventory browsing and event streaming; the UI uses the console SDK for all Kubernetes CRUD and watch operations.
13+
- **Developer Guide**
14+
- [API Reference](docs/dev/api.md) — CR spec, status, condition types
15+
- [Architecture](docs/dev/architecture.md) — package layout, reconciliation flow, requeue strategy
16+
- [Development](docs/dev/development.md) — build, test, deploy, code generation, CI
1217

13-
## Destination Topology Tags
18+
## Quick Start
1419

15-
During the `DestinationInitialized` phase, after preflight confirms the target vCenter user has the required tagging privileges, the operator creates the shared OpenShift topology tag model on the destination vCenter:
20+
```bash
21+
# Build and deploy the operator
22+
make operator-image operator-push IMG=<registry>/vcf-migration-operator:latest
23+
make deploy IMG=<registry>/vcf-migration-operator:latest
1624

17-
- The `openshift-region` and `openshift-zone` categories are created with `SINGLE` cardinality.
18-
- New categories are created with associable types `Datacenter`, `ClusterComputeResource`, `Datastore`, and `Folder`.
19-
- The region tag from `failureDomain.region` is attached to the target datacenter.
20-
- The zone tag from `failureDomain.zone` is attached to the target compute cluster.
21-
- Multiple failure domains can share the same region while using different zones.
22-
- This mirrors the topology tag model used by the OpenShift vSphere cloud provider and CSI driver to discover failure domains.
23-
24-
The category ownership model is intentionally shared per vCenter rather than cluster-specific. If `openshift-region` or `openshift-zone` already exists, the operator reuses it and never deletes or rewrites it. Brownfield reuse is validated before proceeding: the category must keep `SINGLE` cardinality and must allow at least `Datacenter` and `ClusterComputeResource`. Extra associable types and different descriptions are tolerated. If an existing category is incompatible, the operator fails with an error that tells the administrator to update the category in the vSphere UI or delete it and let the operator recreate it.
25-
26-
## Getting Started
27-
28-
### Prerequisites
29-
- go version v1.25.0+
30-
- podman
31-
- kubectl version v1.11.3+
32-
- Access to a Kubernetes v1.11.3+ cluster
33-
34-
### To Deploy on the cluster
35-
**Build and push your image to the location specified by `IMG`:**
36-
37-
```sh
38-
make operator-image operator-push IMG=<some-registry>/vcf-migration-operator:tag
39-
```
40-
41-
**NOTE:** This image ought to be published in the personal registry you specified.
42-
And it is required to have access to pull the image from the working environment.
43-
Make sure you have the proper permission to the registry if the above commands don't work.
44-
45-
**Install the CRDs into the cluster:**
46-
47-
```sh
48-
make install
49-
```
50-
51-
**Deploy the Manager to the cluster with the image specified by `IMG`:**
52-
53-
```sh
54-
make deploy IMG=<some-registry>/vcf-migration-operator:tag
55-
```
56-
57-
> **NOTE**: If you encounter RBAC errors, you may need to grant yourself cluster-admin
58-
privileges or be logged in as admin.
59-
60-
**Create instances of your solution**
61-
62-
Apply the sample migration CRs from `config/samples/` (if present):
63-
64-
```sh
25+
# Apply a sample migration
6526
kubectl apply -k config/samples/
6627
```
6728

68-
>**NOTE**: Ensure that the samples has default values to test it out.
69-
70-
### To Uninstall
71-
**Delete the instances (CRs) from the cluster:**
72-
73-
```sh
74-
kubectl delete -k config/samples/
75-
```
76-
77-
**Delete the APIs(CRDs) from the cluster:**
78-
79-
```sh
80-
make uninstall
81-
```
82-
83-
**UnDeploy the controller from the cluster:**
84-
85-
```sh
86-
make undeploy
87-
```
88-
89-
## OpenShift Console Plugin
90-
91-
The console plugin runs as a separate Deployment and registers with the OpenShift console via a `ConsolePlugin` custom resource. It serves the UI and backend APIs (vCenter browse, event stream) over HTTPS.
92-
93-
### Prerequisites (plugin)
94-
95-
- Node.js 18+ and npm (for building the frontend)
96-
- Go 1.25+ (backend shares the repo's Go module and reuses `internal/vsphere`)
97-
98-
### Build the plugin
99-
100-
```sh
101-
# Frontend (webpack bundle into console-plugin/web/dist)
102-
make console-plugin-frontend
103-
104-
# Backend (Go binary to bin/console-plugin)
105-
make console-plugin-backend
106-
107-
# Container image (default tag: vcf-migration-console-plugin:latest)
108-
make console-plugin-image
109-
# Or with a custom tag:
110-
make console-plugin-image CONSOLE_PLUGIN_IMG=<registry>/vcf-migration-console-plugin:<tag>
111-
```
112-
113-
### Push the plugin image
114-
115-
```sh
116-
make console-plugin-push CONSOLE_PLUGIN_IMG=<registry>/vcf-migration-console-plugin:<tag>
117-
```
118-
119-
### Deploy the plugin
120-
121-
Ensure the plugin image is available to the cluster (e.g. push to the cluster's registry or load into Kind). Then:
122-
123-
```sh
124-
make deploy-console-plugin CONSOLE_PLUGIN_IMG=<registry>/vcf-migration-console-plugin:<tag>
125-
```
126-
127-
This applies the Kustomize manifests under `console-plugin/deploy/` (ConsolePlugin CR, Deployment, Service, RBAC). The image in the Deployment manifest is set to `CONSOLE_PLUGIN_IMG` via kustomize. The plugin appears in the Administrator perspective under **VCF Migration → Migrations**.
128-
129-
### Undeploy the plugin
130-
131-
```sh
132-
make undeploy-console-plugin
133-
```
134-
135-
### Plugin layout
136-
137-
- `console-plugin/cmd/plugin/` — Go entrypoint; TLS flags, Kube client, server startup
138-
- `console-plugin/pkg/server/` — HTTP server, route registration, static file serving
139-
- `console-plugin/pkg/handlers/` — vSphere API handlers (connect, datacenters, clusters, datastores, networks, resource pools, templates, folders) and SSE events handler
140-
- `console-plugin/web/` — React + TypeScript + PatternFly; `console-extensions.json` for nav/routes; SDK for K8s watch/create
141-
- `console-plugin/deploy/` — ConsolePlugin, Deployment, Service, RBAC, kustomization
142-
143-
## Container Images
144-
145-
Both the operator and console plugin images are built with podman by default. The container tool can be overridden via `CONTAINER_TOOL`.
146-
147-
| Target | Description |
148-
|--------|-------------|
149-
| `make operator-image IMG=...` | Build the operator image |
150-
| `make operator-push IMG=...` | Push the operator image |
151-
| `make console-plugin-image CONSOLE_PLUGIN_IMG=...` | Build the console plugin image |
152-
| `make console-plugin-push CONSOLE_PLUGIN_IMG=...` | Push the console plugin image |
153-
154-
Both `make deploy` and `make deploy-console-plugin` use kustomize to set the image in the respective manifests before applying, so the deployed image always matches the variable you pass.
155-
156-
## Project Distribution
157-
158-
Following the options to release and provide this solution to the users.
159-
160-
### By providing a bundle with all YAML files
161-
162-
1. Build the installer for the image built and published in the registry:
163-
164-
```sh
165-
make build-installer IMG=<some-registry>/vcf-migration-operator:tag
166-
```
167-
168-
**NOTE:** The makefile target mentioned above generates an 'install.yaml'
169-
file in the dist directory. This file contains all the resources built
170-
with Kustomize, which are necessary to install this project without its
171-
dependencies.
172-
173-
2. Using the installer
174-
175-
Users can just run 'kubectl apply -f <URL for YAML BUNDLE>' to install
176-
the project, i.e.:
177-
178-
```sh
179-
kubectl apply -f https://raw.githubusercontent.com/<org>/vcf-migration-operator/<tag or branch>/dist/install.yaml
180-
```
181-
182-
### By providing a Helm Chart
183-
184-
1. Build the chart using the optional helm plugin
185-
186-
```sh
187-
operator-sdk edit --plugins=helm/v1-alpha
188-
```
189-
190-
2. See that a chart was generated under 'dist/chart', and users
191-
can obtain this solution from there.
192-
193-
**NOTE:** If you change the project, you need to update the Helm Chart
194-
using the same command above to sync the latest changes. Furthermore,
195-
if you create webhooks, you need to use the above command with
196-
the '--force' flag and manually ensure that any custom configuration
197-
previously added to 'dist/chart/values.yaml' or 'dist/chart/manager/manager.yaml'
198-
is manually re-applied afterwards.
29+
See the [user docs](docs/user/) for full installation instructions and the [development guide](docs/dev/development.md) for building from source.
19930

20031
## Contributing
20132

202-
Contributions are welcome. Please open an issue or PR and follow the code style and conventions described in this repo (see also `AGENTS.md` for build, lint, and test commands).
203-
204-
**NOTE:** Run `make help` for more information on all potential `make` targets.
205-
206-
More information can be found via the [Kubebuilder Documentation](https://book.kubebuilder.io/introduction.html)
33+
Contributions are welcome. Run `make help` for all available targets. See also `AGENTS.md` for build, lint, and test commands.
20734

20835
## License
20936

210-
Copyright 2026.
211-
212-
Licensed under the Apache License, Version 2.0 (the "License");
213-
you may not use this file except in compliance with the License.
214-
You may obtain a copy of the License at
215-
216-
http://www.apache.org/licenses/LICENSE-2.0
217-
218-
Unless required by applicable law or agreed to in writing, software
219-
distributed under the License is distributed on an "AS IS" BASIS,
220-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
221-
See the License for the specific language governing permissions and
222-
limitations under the License.
37+
Copyright 2026. Licensed under the [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0).

docs/dev/api.md

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# API Reference
2+
3+
**Group:** `migration.openshift.io`
4+
**Version:** `v1alpha1`
5+
**Kind:** `VmwareCloudFoundationMigration`
6+
**Short name:** `vcfm`
7+
**Scope:** Namespaced
8+
9+
## Spec
10+
11+
| Field | Type | Required | Default | Description |
12+
|-------|------|----------|---------|-------------|
13+
| `state` | `MigrationState` | Yes | `Pending` | `Pending`, `Running`, or `Paused`. Reconciler only acts when `Running`. |
14+
| `targetVCenterCredentialsSecret` | `SecretReference` | Yes | | Secret with target vCenter credentials. |
15+
| `failureDomains` | `[]VSpherePlatformFailureDomainSpec` | Yes (min 1) | | Target failure domains. Uses the OpenShift `configv1` type. |
16+
17+
### MigrationState Enum
18+
19+
| Value | Meaning |
20+
|-------|---------|
21+
| `Pending` | Migration has not started |
22+
| `Running` | Migration is actively progressing |
23+
| `Paused` | Migration is paused by the user |
24+
25+
### SecretReference
26+
27+
| Field | Type | Required | Description |
28+
|-------|------|----------|-------------|
29+
| `name` | `string` | Yes | Secret name |
30+
| `namespace` | `string` | No | Secret namespace (defaults to migration namespace) |
31+
32+
The secret must contain keys in the format `<vcenter-fqdn>.username` and `<vcenter-fqdn>.password`.
33+
34+
### VSpherePlatformFailureDomainSpec (from openshift/api configv1)
35+
36+
| Field | Type | Required | Description |
37+
|-------|------|----------|-------------|
38+
| `name` | `string` | Yes | Unique failure domain name (1-256 chars) |
39+
| `region` | `string` | Yes | Region tag name, category `openshift-region` (1-80 chars) |
40+
| `zone` | `string` | Yes | Zone tag name, category `openshift-zone` (1-80 chars) |
41+
| `server` | `string` | Yes | Target vCenter FQDN (1-255 chars) |
42+
| `topology.datacenter` | `string` | Yes | Datacenter name (max 80 chars) |
43+
| `topology.computeCluster` | `string` | Yes | Path: `/<dc>/host/<cluster>` |
44+
| `topology.datastore` | `string` | Yes | Path: `/<dc>/datastore/<ds>` |
45+
| `topology.networks` | `[]string` | Yes (min 1) | Port group network names |
46+
| `topology.resourcePool` | `string` | No | Path: `/<dc>/host/<cluster>/Resources/<pool>` |
47+
| `topology.folder` | `string` | No | Path: `/<dc>/vm/<folder>` |
48+
| `topology.template` | `string` | No | Template path. Defaults to `/<dc>/vm/{infraID}-rhcos-{region}-{zone}` |
49+
50+
## Status
51+
52+
| Field | Type | Description |
53+
|-------|------|-------------|
54+
| `conditions` | `[]metav1.Condition` | Ordered migration phase conditions |
55+
| `startTime` | `*metav1.Time` | When migration entered `Running` |
56+
| `completionTime` | `*metav1.Time` | When migration reached `Ready` |
57+
58+
### Condition Types (in order)
59+
60+
| Type | Description |
61+
|------|-------------|
62+
| `InfrastructurePrepared` | Preflight checks passed, migration path validated |
63+
| `DestinationInitialized` | Target vCenter folders and topology tags created |
64+
| `MultiSiteConfigured` | Cluster recognizes both vCenters |
65+
| `WorkloadMigrated` | Workers created on target, control plane rolled out, source scaled to 0 |
66+
| `SourceCleaned` | Source vCenter fully detached |
67+
| `Ready` | Migration complete, all operators healthy |
68+
69+
### Condition Reasons
70+
71+
`Progressing`, `Completed`, `Failed`, `Paused`, `Pending`
72+
73+
## Print Columns
74+
75+
```
76+
NAME STATE READY AGE
77+
sample Running True 5m
78+
```

0 commit comments

Comments
 (0)