Migration Manifest Validation and Field Reference¶
kcp validates the migration manifest every time a command reads it. This page lists the validation rules and every manifest field with its type, default, and allowed values.
Validation¶
Validation runs on every read of the manifest rather than through a separate
kcp migration validate subcommand. Every read, by execute or lag-check, parses and structurally
validates the manifest in one step, so both commands get validation automatically and
neither can skip it by accident.
Validation collects every problem before returning, rather than failing fast, so you can fix the file in one pass:
3 problem(s) found in the migration manifest:
- spec.source.bootstrapServers: must not be empty
- spec.target.clusterId: required for target type "confluent-cloud"
- spec.staticMigration.policies.detectUnroutedProducersDuration: must be at least 10s when set (0 skips the check) — a shorter window cannot span a producer's metadata refresh
Key rules, beyond whether each field is required or optional:
apiVersionandkindmust be the exact literals, andmetadata.namemust be non-blank.spec.source.typeandspec.target.typemust be one of their listed enum values.- Every
bootstrapServersentry must behost:port. - Exactly one of
spec.staticMigration,spec.dynamicMigration, andspec.dynamicToStaticConversionmust be set. A manifest still usingspec.routeorspec.defaultPoliciesis rejected with a hint to move to the new shape. spec.staticMigration.consumerOffsetSync.baselineis required whenpauseis set, and if set at all must beenabledordisabled.spec.clusterLink.namemust not be blank (existence itself isn't checked until the firstexecuterun touches the destination).spec.clusterLink.linkCredentialsmust not be blank.- Every credentials field (
spec.source.credentials,spec.target.kafka.clusterCredentials,spec.clusterLink.linkCredentials) must be a non-blank file path. An inline mapping is rejected at parse. spec.gateway.namespaceandcr-namemust not be blank. The retiredcrsandrouteskeys must not be set at all (they fail the strict decode).- The declared section's
route.nameandroute.targetStreamingDomainmust not be blank. A migration'stopicGroupmust have exactly one entry. AdynamicToStaticConversionhas notopicGroupfield. - Each entry must set at least one of
topicsortopicPatterns(both is allowed). Neither present is rejected. If present,topicsandtopicPatternsmust be non-empty with no blank entries. EachtopicPatternsentry must compile as an anchored RE2 regular expression. - Duration policies are written with a unit (
0s,10m). A bare number is a parse error. - No
policiesfield can be negative. If greater than zero,detectUnroutedProducersDurationanddetectUnroutedCommitsDurationmust be at least10s(0skips the check).
Rules that need the contents of a credentials file run when that file is read,
not when the manifest is parsed: the iam-needs-an-msk-source rule, the
rejection of iam on the destination, and the credentials file's own
validation. execute (including --dry-run) reads the source, destination, and
REST credentials files. lag-check reads only the REST one.
kcp migration cutover execute --dry-run performs the same validation execute would and prints a reconcile plan, but takes no actions and runs no migration steps. It validates the manifest structure, credentials, the effective policy, and the reconcile preconditions against the live Gateway custom resource (CR), clusters, and cluster link. Use it to validate your infrastructure and manifest while you iterate, before you schedule a live cutover.
Field reference¶
| Path | Type | Required | Default | Allowed values |
|---|---|---|---|---|
apiVersion |
string | yes | — | kcp.confluent.io/v1alpha1 |
kind |
string | yes | — | GatewayMigration |
metadata.name |
string | yes | — | non-blank |
spec.source.type |
enum | yes | — | msk, apache-kafka |
spec.source.bootstrapServers |
[]string |
yes | — | host:port |
spec.source.credentials |
path | yes | — | file path (Kafka family, iam only if type: msk) |
spec.target.type |
enum | yes | — | confluent-cloud, confluent-platform |
spec.target.clusterId |
string | yes | — | required for both target types |
spec.target.kafka.bootstrapServers |
[]string |
yes | — | host:port |
spec.target.kafka.restEndpoint |
string | yes | — | non-blank (not parsed as a URL) |
spec.target.kafka.clusterCredentials |
path | yes | — | file path (Kafka family except iam) |
spec.clusterLink.name |
string | yes | — | must reference an existing link |
spec.clusterLink.bootstrapServers |
[]string |
no | — | repeats spec.target.kafka.bootstrapServers (not validated) |
spec.clusterLink.linkCredentials |
path | yes | — | file path (api_key and api_secret, basic, bearer, or mtls) |
spec.gateway.namespace |
string | yes | — | — |
spec.gateway.kubeconfig |
string | no | in-cluster in a pod, else ~/.kube/config |
~/ expanded |
spec.gateway.cr-name |
string | yes | — | Kubernetes object name |
spec.<section>.route.name |
string | yes | — | must exist in the initial CR |
spec.<section>.route.targetStreamingDomain |
string | yes | — | must be declared in the initial CR's spec.streamingDomains |
spec.<migration>.topicGroup |
list | yes (migrations only) | — | exactly one entry |
spec.<migration>.topicGroup[].topics |
[]string |
at least one of topics or topicPatterns |
— | non-empty if present, literal names |
spec.<migration>.topicGroup[].topicPatterns |
[]string |
at least one of topics or topicPatterns |
— | non-empty if present, anchored RE2 patterns (['.*'] = all) |
spec.staticMigration.consumerOffsetSync.pause |
bool | no | false |
— |
spec.staticMigration.consumerOffsetSync.baseline |
string | when pause is set |
— | enabled, disabled |
spec.<section>.policies.lagThreshold |
int | no | 0 |
>= 0 (static, dynamic) |
spec.<section>.policies.promoteBatchSize |
int | no | 0 |
>= 0 (static, dynamic) |
spec.<section>.policies.rolloutTimeout |
duration | no | 0s |
>= 0s (all) |
spec.<section>.policies.detectUnroutedProducersDuration |
duration | no | 0s |
0s, or >= 10s (static, dynamic) |
spec.staticMigration.policies.consumerOffsetSyncDrainDuration |
duration | no | 0s |
>= 0s |
spec.<section>.policies.hotReloadTimeout |
duration | no | 0s |
>= 0s (all) |
spec.<section>.policies.gatewayConfigPort |
int | no | 0 |
>= 0 (all) |
spec.dynamicToStaticConversion.policies.detectUnroutedCommitsDuration |
duration | no | 0s |
0s, or >= 10s |
spec.dynamicToStaticConversion.policies.offsetSyncConcurrency |
int | no | 0 |
>= 0 |