Skip to content

feat: upgrade crossplane init command to use v2#230

Merged
abangser merged 6 commits into
mainfrom
ab/xplane-v2
Apr 28, 2026
Merged

feat: upgrade crossplane init command to use v2#230
abangser merged 6 commits into
mainfrom
ab/xplane-v2

Conversation

@abangser
Copy link
Copy Markdown
Member

With Crossplane upgrading and releasing a stable v2, it is important that this CLI generates successfully on v2 resources.

The biggest change here is to actively not pass through the autogenerated XRD fields to the Kratix API. That is what created large test data changes.

This has been tested with the following files which were generated from following the official composition docs:

xrd ``` apiVersion: apiextensions.crossplane.io/v2 kind: CompositeResourceDefinition metadata: name: apps.example.crossplane.io spec: scope: Namespaced group: example.crossplane.io names: kind: App plural: apps versions: - name: v1 served: true referenceable: true schema: openAPIV3Schema: type: object properties: spec: type: object properties: image: description: The app's OCI container image. type: string default: nginx required: - image status: type: object properties: replicas: description: The number of available app replicas. type: integer address: description: The app's IP address. type: string ```
composition ``` apiVersion: apiextensions.crossplane.io/v1 kind: Composition metadata: name: app-yaml spec: compositeTypeRef: apiVersion: example.crossplane.io/v1 kind: App mode: Pipeline pipeline: - step: create-deployment-and-service functionRef: name: crossplane-contrib-function-patch-and-transform input: apiVersion: pt.fn.crossplane.io/v1beta1 kind: Resources resources: - name: deployment base: apiVersion: apps/v1 kind: Deployment spec: replicas: 2 template: spec: containers: - name: app ports: - containerPort: 80 patches: - type: FromCompositeFieldPath fromFieldPath: metadata.name toFieldPath: metadata.labels[example.crossplane.io/app] - type: FromCompositeFieldPath fromFieldPath: metadata.name toFieldPath: spec.selector.matchLabels[example.crossplane.io/app] - type: FromCompositeFieldPath fromFieldPath: metadata.name toFieldPath: spec.template.metadata.labels[example.crossplane.io/app] - type: FromCompositeFieldPath fromFieldPath: spec.image toFieldPath: spec.template.spec.containers[0].image - type: ToCompositeFieldPath fromFieldPath: status.availableReplicas toFieldPath: status.replicas readinessChecks: - type: MatchCondition matchCondition: type: Available status: "True" - name: service base: apiVersion: v1 kind: Service spec: ports: - protocol: TCP port: 8080 targetPort: 80 patches: - type: FromCompositeFieldPath fromFieldPath: metadata.name toFieldPath: metadata.labels[example.crossplane.io/app] - type: FromCompositeFieldPath fromFieldPath: metadata.name toFieldPath: spec.selector[example.crossplane.io/app] - type: ToCompositeFieldPath fromFieldPath: spec.clusterIP toFieldPath: status.address readinessChecks: - type: NonEmpty fieldPath: spec.clusterIP ```
function ``` apiVersion: pkg.crossplane.io/v1 kind: Function metadata: name: crossplane-contrib-function-patch-and-transform spec: package: xpkg.crossplane.io/crossplane-contrib/function-patch-and-transform:v0.8.2 ```
example request ``` apiVersion: example.crossplane.io/v1 kind: App metadata: namespace: default name: my-app spec: image: nginx ```

abangser and others added 6 commits April 27, 2026 21:04
1. Panic fix: xrd.Spec.ClaimNames.Kind → nil-safe with fallback to xrd.Spec.Names.Kind. In Crossplane v2, claimNames is replaced by scope:
  Namespaced on the XRD spec, so ClaimNames is always nil.
2. Dependency fidelity: Replaced runtime.DefaultUnstructuredConverter.ToUnstructured(xrd) with a new readFileAsUnstructured() that reads
  the raw YAML. This preserves v2-specific fields like scope: Namespaced that aren't in the v1 Go struct, and drops spurious fields that the
  typed conversion was injecting (metadata.creationTimestamp: null, status.controllers.*).
3. Nil guard in generateCRDFromXRD: Added a check for version.Schema == nil before accessing version.Schema.OpenAPIV3Schema.
The mandatoryAdditionalClaimFields map injected Crossplane-internal
plumbing fields (compositionRef, compositeDeletePolicy, etc.) into
every generated Kratix API CRD spec, which are not user-facing API
fields and should not appear in the Promise API.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Previously the generated CRD always set spec.default to {}, which is
invalid when the spec has required fields that lack their own defaults.
buildSpecDefault now inspects required fields: if all have defaults, it
returns a default object containing those values; if any required field
has no default, it returns nil so no spec-level default is set.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@abangser abangser merged commit 92ce86b into main Apr 28, 2026
3 checks passed
@abangser abangser deleted the ab/xplane-v2 branch April 28, 2026 13:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants