crossplane
  • crossplane
  • CROSSPLANE - Cloud Control Plane and more
  • Crossplane as a Universal Cloud Control Plane
  • Automating Infrastructure with Crossplane
  • Composing Infrastructure with Crossplane
  • Building an XR
  • Platform Patterns
  • ControllerConfig
  • refs
Powered by GitBook
On this page
  • Evolving APIs
  • API implementation change
  • Enable Composition Revisions
  • API contract changes
  • Non-breaking changes
  • Version upgrade
  • Version upgrade with breaking changes
  • Nested and multi-resource XRs
  • Naming the versions
  • OpenAPIV3Schema structure
  • Printer Columns

Platform Patterns

PreviousBuilding an XRNextControllerConfig

Last updated 1 year ago

Evolving APIs

API implementation change

  • CmpositionRevision is Crossplane concept that will work with compositions to support changes

  • If the --enable-composition-revisions flag is set while installing Crossplane, a CompositionRevision object is created with all the updates to composition

  • The compositions are mutable objects that can change forever, but individual CompositionRevision is immutable

  • Composition and CompositionRevision are in one-to-many relationships

  • Only one CompositionRevision active at any given instance

  • In a Crossplane environment where the composition revision flag is enabled, we will have two attributes automatically added to every XR/Claim object by Crossplane

    • spec.compositionRevisionRef This will hold the name of CompositionRevision with which the resources are created

    • spec.compositionUpdatePolicy This attribute will indicate whether the XR/Claim will automatically migrate to a new, available CompositionRevision. Manual and automatic are the two possible values, with automatic as the default value. If you would like to override the default behavior, add this attribute with a manual indicator in the XR/Claim configuration.

Enable Composition Revisions

helm upgrade crossplane --namespace crossplane-system crossplane-stable/crossplane --set args='{--enable-composition-revisions}'
  • Let's try

    • Building an XR API for GCP MySQL provisioning in a composition revision-enabled Crossplane environment

    • Creating two MySQL instances with automated and manual composition revision policies

    • Updating the Composition to change the calculation for database disk size

    • Validating if the MySQL instance with automated revision policy automatically migrates to the latest composition revision

    • Seeing that the MySQL instance with the manual revision policy does not migrate to the latest composition revision

    • Finally, migrating the second MySQL instance manually to the latest composition revision

cat <<EOF | kubectl apply -f -
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
  name: xmysqls.composition-revision.imarunrk.com
spec:
  group: composition-revision.imarunrk.com
  names:
    kind: XMySql
    plural: xmysqls
  claimNames:
    kind: MySql
    plural: mysqls
  versions:
  - name: v1
    served: true
    referenceable: true
    schema:
      openAPIV3Schema:
        type: object
        properties:
          spec:
            type: object
            properties:
              parameters:
                type: object
                properties:
                  size:
                    type: integer
                required:
                - size
            required:
            - parameters
EOF
cat <<EOF | kubectl apply -f -
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
  name: gcp-mysql
spec:
  compositeTypeRef:
    apiVersion: composition-revision.imarunrk.com/v1
    kind: XMySql
  resources:
  - name: cloudsqlinstance
    base:
      apiVersion: database.gcp.crossplane.io/v1beta1
      kind: CloudSQLInstance
      spec:
        providerConfigRef:
          name: gcp-credentials-project-1
        forProvider:
          region: us-central1
          databaseVersion: MYSQL_5_7
          settings:
            tier: db-g1-small
            dataDiskSizeGb: 40
    patches:
    - type: FromCompositeFieldPath
      fromFieldPath: spec.parameters.size
      toFieldPath: spec.forProvider.settings.dataDiskSizeGb
EOF
k get compositionrevision -l crossplane.io/composition-name=gcp-mysql
NAME                REVISION   XR-KIND   XR-APIVERSION                          AGE
gcp-mysql-8e5f8dc   1          XMySql    composition-revision.imarunrk.com/v1   11m
cat <<EOF | k apply -f -
apiVersion: composition-revision.imarunrk.com/v1
kind: MySql
metadata:
  namespace: alpha
  name: mysql-db-manual
spec:
  compositionUpdatePolicy: Manual
  compositionRef:
    name: gcp-mysql
  parameters:
    size: 10
EOF
cat <<EOF | k apply -f -
apiVersion: composition-revision.imarunrk.com/v1
kind: MySql
metadata:
  namespace: alpha
  name: mysql-db
spec:
  compositionRef:
    name: gcp-mysql
  parameters:
    size: 10
EOF
k get claim -A
NAMESPACE   NAME                                                      SYNCED   READY   CONNECTION-SECRET   AGE
alpha       mysql.composition-revision.imarunrk.com/mysql-db          True     False                       14s
alpha       mysql.composition-revision.imarunrk.com/mysql-db-manual   True     False                       2m33s
kubectl get mysql mysql-db-manual -o yaml -n alpha | k neat
apiVersion: composition-revision.imarunrk.com/v1
kind: MySql
metadata:
  name: mysql-db-manual
  namespace: alpha
spec:
  compositeDeletePolicy: Background
  compositionRef:
    name: gcp-mysql
  compositionUpdatePolicy: Manual
  parameters:
    size: 10
  resourceRef:
    apiVersion: composition-revision.imarunrk.com/v1
    kind: XMySql
    name: mysql-db-manual-p27v4
kubectl get mysql mysql-db -o yaml -n alpha | k neat
apiVersion: composition-revision.imarunrk.com/v1
kind: MySql
metadata:
  name: mysql-db
  namespace: alpha
spec:
  compositeDeletePolicy: Background
  compositionRef:
    name: gcp-mysql
  compositionRevisionRef:
    name: gcp-mysql-8e5f8dc
  compositionUpdatePolicy: Automatic
  parameters:
    size: 10
  resourceRef:
    apiVersion: composition-revision.imarunrk.com/v1
    kind: XMySql
    name: mysql-db-wjmvl
  • Update composition patch with transform function

cat <<EOF | kubectl apply -f -
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
  name: gcp-mysql
spec:
  compositeTypeRef:
    apiVersion: composition-revision.imarunrk.com/v1
    kind: XMySql
  resources:
  - name: cloudsqlinstance
    base:
      apiVersion: database.gcp.crossplane.io/v1beta1
      kind: CloudSQLInstance
      spec:
        providerConfigRef:
          name: gcp-credentials-project-1
        forProvider:
          region: us-central1
          databaseVersion: MYSQL_5_7
          settings:
            tier: db-g1-small
            dataDiskSizeGb: 40
    patches:
    - type: FromCompositeFieldPath
      fromFieldPath: spec.parameters.size
      toFieldPath: spec.forProvider.settings.dataDiskSizeGb
      transforms:
      - type: math
        math:
          multiply: 4
EOF
 k get compositionrevision -l crossplane.io/composition-name=gcp-mysql
NAME                REVISION   XR-KIND   XR-APIVERSION                          AGE
gcp-mysql-8e5f8dc   1          XMySql    composition-revision.imarunrk.com/v1   12h
gcp-mysql-f7ea509   2          XMySql    composition-revision.imarunrk.com/v1   6h50m
kind: MySql
metadata:
  name: mysql-db
  namespace: alpha
spec:
  ...
  compositionRevisionRef:
    name: gcp-mysql-8e5f8dc
  • For manual upgrade update mysql-db-manual with the latest compositionRevisionRef

  compositionRevisionRef:
    name: gcp-mysql-cf3862c

API contract changes

Non-breaking changes

  • A simple way to think about this is that if Composition/CompositionRevision can handle the co-existence of old and newly provisioned resources, then the XRD contract change is non-breaking

cat <<EOF | kubectl apply -f -
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
  name: xmysqls.xrd-non-breaking.imarunrk.com
spec:
  group: xrd-non-breaking.imarunrk.com
  names:
    kind: XMySql
    plural: xmysqls
  claimNames:
    kind: MySql
    plural: mysqls
  versions:
  - name: v1
    served: true
    referenceable: true
    schema:
      openAPIV3Schema:
        type: object
        properties:
          spec:
            type: object
            properties:
              parameters:
                type: object
                properties:
                  vm:
                    type: string
                required:
                - vm
            required:
            - parameters
EOF
cat <<EOF | kubectl apply -f -
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
  name: gcp-mysql
spec:
  compositeTypeRef:
    apiVersion: xrd-non-breaking.imarunrk.com/v1
    kind: XMySql
  resources:
  - name: cloudsqlinstance
    base:
      apiVersion: database.gcp.crossplane.io/v1beta1
      kind: CloudSQLInstance
      spec:
        providerConfigRef:
          name: gcp-credentials-project-1
        forProvider:
          region: us-central1
          databaseVersion: MYSQL_5_7
          settings:
            tier: db-g1-small
            dataDiskSizeGb: 40
    patches:
    - type: FromCompositeFieldPath
      fromFieldPath: spec.parameters.vm
      toFieldPath: spec.forProvider.settings.tier
EOF
cat <<EOF | kubectl apply -f -
apiVersion: xrd-non-breaking.imarunrk.com/v1
kind: MySql
metadata:
  namespace: alpha
  name: mysql-db-v1
spec:
  compositionRef:
    name: gcp-mysql
  parameters:
    vm: db-n1-standard-1
EOF
k get composition
NAME        XR-KIND   XR-APIVERSION                      AGE
gcp-mysql   XMySql    xrd-non-breaking.imarunrk.com/v1   118m

k get compositionrevision
NAME                REVISION   XR-KIND   XR-APIVERSION                      AGE
gcp-mysql-cd48db8   1          XMySql    xrd-non-breaking.imarunrk.com/v1   118m

k get xrd
NAME                                    ESTABLISHED   OFFERED   AGE
xmysqls.xrd-non-breaking.imarunrk.com   True          True      120m

k get mysql -n alpha
NAME          SYNCED   READY   CONNECTION-SECRET   AGE
mysql-db-v1   True     True                        119m
cat <<EOF | kubectl apply -f -
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
  name: xmysqls.xrd-non-breaking.imarunrk.com
spec:
  group: xrd-non-breaking.imarunrk.com
  names:
    kind: XMySql
    plural: xmysqls
  claimNames:
    kind: MySql
    plural: mysqls
  versions:
  - name: v1
    served: true
    referenceable: true
    schema:
      openAPIV3Schema:
        type: object
        properties:
          spec:
            type: object
            properties:
              parameters:
                type: object
                properties:
                  size:
                    type: integer
                  vm:
                    type: string
                required:
                - vm
            required:
            - parameters
EOF
cat <<EOF | kubectl apply -f -
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
  name: gcp-mysql
spec:
  compositeTypeRef:
    apiVersion: xrd-non-breaking.imarunrk.com/v1
    kind: XMySql
  resources:
  - name: cloudsqlinstance
    base:
      apiVersion: database.gcp.crossplane.io/v1beta1
      kind: CloudSQLInstance
      spec:
        providerConfigRef:
          name: gcp-credentials-project-1
        forProvider:
          region: us-central1
          databaseVersion: MYSQL_5_7
          settings:
            tier: db-g1-small
            dataDiskSizeGb: 40
    patches:
    - type: FromCompositeFieldPath
      fromFieldPath: spec.parameters.size
      toFieldPath: spec.forProvider.settings.dataDiskSizeGb
    - type: FromCompositeFieldPath
      fromFieldPath: spec.parameters.vm
      toFieldPath: spec.forProvider.settings.tier
EOF
cat <<EOF | kubectl apply -f -
apiVersion: xrd-non-breaking.imarunrk.com/v1
kind: MySql
metadata:
  namespace: alpha
  name: mysql-db-v2
spec:
  compositionRef:
    name: gcp-mysql
  parameters:
    size: 10
    vm: db-n1-standard-2
EOF
  • To validate whether the first MySQL instance can be sill updated, change the tier with an update YAML

cat <<EOF | kubectl apply -f -
apiVersion: xrd-non-breaking.imarunrk.com/v1
kind: MySql
metadata:
  namespace: alpha
  name: mysql-db-v1
spec:
  compositionRef:
    name: gcp-mysql
  parameters:
    vm: db-n1-standard-4
EOF

Version upgrade

  • referenceable: flag will determine if we can define a composition implementation for the given version

    • Only one version can have referenceable flag set to true

  • served: will indicate if given XR API version is in use

cat <<EOF | kubectl apply -f - 
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
  name: xversiontests.xrd-version.imarunrk.com
spec:
  group: xrd-version.imarunrk.com
  names:
    kind: XVersionTest
    plural: xversiontests
  claimNames:
    kind: VersionTest
    plural: versiontests
  versions:
  - name: v1
    served: true
    referenceable: true
    schema:
      openAPIV3Schema:
        type: object
        properties:
          spec:
            type: object
            properties:
              parameters:
                type: object
                properties:
                  size:
                    type: integer
                required:
                - size
            required:
            - parameters
  - name: alpha
    served: false
    referenceable: false
    schema:
      openAPIV3Schema:
        type: object
        properties:
          spec:
            type: object
            properties:
              parameters:
                type: object
                properties:
                  size:
                    type: integer
                required:
                - size
            required:
            - parameters
  - name: beta
    served: true
    referenceable: false
    schema:
      openAPIV3Schema:
        type: object
        properties:
          spec:
            type: object
            properties:
              parameters:
                type: object
                properties:
                  size:
                    type: integer
                required:
                - size
            required:
            - parameters
EOF
  • In kubernetesConversion webhook is configured by the CRD author to support conversion between the versions

  • A conversion webhook involves programming.

  • Taking that route will violate the no-code agenda of Crossplane when composing APIs.

  • It’s important to note that the Crossplane community is actively working to build a configuration-based solution to support conversion and migration between versions.


Version upgrade with breaking changes

cat <<EOF | kubectl apply -f -
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
  name: xmysqls.xrd-breaking.imarunrk.com
spec:
  group: xrd-breaking.imarunrk.com
  names:
    kind: XMySql
    plural: xmysqls
  claimNames:
    kind: MySql
    plural: mysqls
  versions:
  - name: v1
    served: true
    referenceable: true
    schema:
      openAPIV3Schema:
        type: object
        properties:
          spec:
            type: object
            properties:
              parameters:
                type: object
                properties:
                  size:
                    type: integer
                  vm:
                    type: string
                required:
                - vm
            required:
            - parameters
EOF
cat <<EOF | kubectl apply -f -
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
  name: gcp-mysql
spec:
  compositeTypeRef:
    apiVersion: xrd-breaking.imarunrk.com/v1
    kind: XMySql
  resources:
  - name: cloudsqlinstance
    base:
      apiVersion: database.gcp.crossplane.io/v1beta1
      kind: CloudSQLInstance
      metadata:
        annotations:
          crossplane.io/external-name: default
      spec:
        deletionPolicy: Orphan
        providerConfigRef:
          name: gcp-credentials-project-1
        forProvider:
          region: us-central1
          databaseVersion: MYSQL_5_7
          settings:
            tier: db-g1-small
            dataDiskSizeGb: 40
    patches:
    - type: FromCompositeFieldPath
      fromFieldPath: spec.parameters.size
      toFieldPath: spec.forProvider.settings.dataDiskSizeGb
    - type: FromCompositeFieldPath
      fromFieldPath: spec.parameters.vm
      toFieldPath: spec.forProvider.settings.tier
    - type: FromCompositeFieldPath
      fromFieldPath: metadata.labels[claim.name]
      toFieldPath: metadata.annotations[crossplane.io/external-name]
      transforms:
      - type: string
        string:
          fmt: "%s-gcp-mysql-cloudsqlinstance"
EOF
cat <<EOF | kubectl apply -f -
apiVersion: xrd-breaking.imarunrk.com/v1
kind: MySql
metadata:
  namespace: alpha
  name: my-db
  labels:
    claim.name: my-db
spec:
  compositionRef:
    name: gcp-mysql
  parameters:
    size: 10
    vm: db-n1-standard-2
EOF
k get claim -n alpha
NAME    SYNCED   READY   CONNECTION-SECRET   AGE
my-db   True     True                        15m

k delete claim my-db -n alpha
mysql.xrd-breaking.imarunrk.com "my-db" deleted
cat <<EOF | kubectl apply -f -
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
  name: xmysqls.xrd-breaking.imarunrk.com
spec:
  group: xrd-breaking.imarunrk.com
  names:
    kind: XMySql
    plural: xmysqls
  claimNames:
    kind: MySql
    plural: mysqls
  versions:
  - name: v2
    served: true
    referenceable: true
    schema:
      openAPIV3Schema:
        type: object
        properties:
          spec:
            type: object
            properties:
              parameters:
                type: object
                properties:
                  size:
                    type: integer
EOF
cat <<EOF | kubectl apply -f -
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
  name: gcp-mysql
spec:
  compositeTypeRef:
    apiVersion: xrd-breaking.imarunrk.com/v2
    kind: XMySql
  resources:
  - name: cloudsqlinstance
    base:
      apiVersion: database.gcp.crossplane.io/v1beta1
      kind: CloudSQLInstance
      spec:
        deletionPolicy: Orphan
        providerConfigRef:
          name: gcp-credentials-project-1
        forProvider:
          region: us-central1
          databaseVersion: MYSQL_5_7
          settings:
            tier: db-n1-standard-4
            dataDiskSizeGb: 40
    patches:
    - type: FromCompositeFieldPath
      fromFieldPath: spec.parameters.size
      toFieldPath: spec.forProvider.settings.dataDiskSizeGb
    - type: FromCompositeFieldPath
      fromFieldPath: metadata.labels[claim.name]
      toFieldPath: metadata.annotations[crossplane.io/external-name]
      transforms:
      - type: string
        string:
          fmt: "%s-gcp-mysql-cloudsqlinstance"
EOF
cat <<EOF | kubectl apply -f -
apiVersion: xrd-breaking.imarunrk.com/v2
kind: MySql
metadata:
  namespace: alpha
  name: my-db
  labels:
    claim.name: my-db
spec:
  compositionRef:
    name: gcp-mysql
  parameters:
    size: 20
EOF

Nested and multi-resource XRs

cat <<EOF | kubectl apply -f -
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
  name: xgcpclusters.nested-xr.imarunrk.com
spec:
  group: nested-xr.imarunrk.com
  names:
    kind: XGCPCluster
    plural: xgcpclusters
  versions:
  - name: v1
    served: true
    referenceable: true
    schema:
      openAPIV3Schema:
        type: object
        properties:
          spec:
            type: object
            properties:
              parameters:
                type: object
                properties:
                  autopilot:
                    type: boolean
                  region:
                    type: string
                required:
                - region
            required:
            - parameters
EOF
cat <<EOF | kubectl apply -f -
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
  name: gcp-kubernetes
spec:
  compositeTypeRef:
    apiVersion: nested-xr.imarunrk.com/v1
    kind: XGCPCluster
  resources:
  - name: cluster
    base:
      apiVersion: container.gcp.crossplane.io/v1beta2
      kind: Cluster
      spec:
        providerConfigRef:
          name: gcp-credentials-project-1
        forProvider:
          location: us-central1
          autopilot:
            enabled: true
    patches:
    - type: FromCompositeFieldPath
      fromFieldPath: spec.parameters.autopilot
      toFieldPath: spec.forProvider.autopilot.enabled
    - type: PatchSet
      patchSetName: region
  - name: bucket
    base:
      apiVersion: storage.gcp.crossplane.io/v1alpha3
      kind: Bucket
      spec:
        providerConfigRef:
          name: gcp-credentials-project-1
        forProvider:
          location: us-central1
    patches:
    - type: PatchSet
      patchSetName: region
  patchSets:
  - name: region
    patches:
    - type: FromCompositeFieldPath
      fromFieldPath: spec.parameters.region
      toFieldPath: spec.forProvider.region
EOF
cat <<EOF | kubectl apply -f -
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
  name: xapplications.nested-xr.imarunrk.com
spec:
  group: nested-xr.imarunrk.com
  names:
    kind: XApplication
    plural: xapplications
  claimNames:
    kind: Application
    plural: applications
  versions:
  - name: v1
    served: true
    referenceable: true
    schema:
      openAPIV3Schema:
        type: object
        properties:
          spec:
            type: object
            properties:
              parameters:
                type: object
                properties:
                  region:
                    type: string
                required:
                - region
            required:
            - parameters
EOF
cat <<EOF | kubectl apply -f -
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
  name: gcp-application
spec:
  compositeTypeRef:
    apiVersion: nested-xr.imarunrk.com/v1
    kind: XApplication
  resources:
  - name: cluster
    base:
      apiVersion: nested-xr.imarunrk.com/v1
      kind: XGCPCluster
      spec:
        parameters:
          region: us-central1-b
          autopilot: true
    patches:
    - type: FromCompositeFieldPath
      fromFieldPath: spec.parameters.region
      toFieldPath: spec.parameters.region
  - name: cloudsqlinstance
    base:
      apiVersion: database.gcp.crossplane.io/v1beta1
      kind: CloudSQLInstance
      spec:
        providerConfigRef:
          name: gcp-credentials-project-1
        forProvider:
          databaseVersion: MYSQL_5_7
          region: us-central1
          settings:
            tier: db-g1-small
    patches:
    - type: FromCompositeFieldPath
      fromFieldPath: spec.parameters.region
      toFieldPath: spec.forProvider.region
EOF
k get xrds
NAME                                   ESTABLISHED   OFFERED   AGE
xapplications.nested-xr.imarunrk.com   True          True      6s
xgcpclusters.nested-xr.imarunrk.com    True                    12m

k get compositions
NAME              XR-KIND        XR-APIVERSION               AGE
gcp-application   XApplication   nested-xr.imarunrk.com/v1   26m
gcp-kubernetes    XGCPCluster    nested-xr.imarunrk.com/v1   17m
  • ESTABLISHED: true: indicates that the Crossplane has started a new controller to reconcile the established XR

  • OFFERED: true: indicates that the Crossplane has started a new controller to reconcile the established Claim only for the application XR

cat <<EOF | kubectl apply -f -
apiVersion: nested-xr.imarunrk.com/v1
kind: Application
metadata:
  name: my-application
  namespace: alpha
spec:
  parameters:
    region: us-central1
EOF
 k get application -n alpha
NAME             SYNCED   READY   CONNECTION-SECRET   AGE
my-application   True     False                       2d4h
 
 k get xapplication
NAME                   SYNCED   READY   COMPOSITION       AGE
my-application-zctd2   True     False   gcp-application   2d4h
 
 k get cloudsqlinstance
NAME                         READY   SYNCED   STATE      VERSION     AGE
my-application-zctd2-xhvkq   True    True     RUNNABLE   MYSQL_5_7   2d4h
 
 k get xgcpcluster
NAME                         SYNCED   READY   COMPOSITION      AGE
my-application-zctd2-ch9xv   True     False   gcp-kubernetes   2d4h
 
 k get cluster
NAME                         READY   SYNCED   STATE     ENDPOINT       LOCATION      AGE
my-application-zctd2-lnm2q   False   False    RUNNING   34.172.76.21   us-central1   2d4h
 
 k get bucket
NAME                         READY   SYNCED   STORAGE_CLASS   LOCATION   AGE
my-application-zctd2-x8bzd   True    True     STANDARD        US         2d4h

Naming the versions

cat <<EOF | kubectl apply -f -
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
  name: xbuckets.version-test.imarunrk.com
spec:
  group: version-test.imarunrk.com
  names:
    kind: XBuckets
    plural: xbuckets
  versions:
  - name: v1.0
    served: true
    referenceable: true
    schema:
      openAPIV3Schema:
        type: object
        properties:
          spec:
            type: object
            properties:
              parameters:
                type: object
                properties:
                  region:
                    type: string
                required:
                - region
            required:
            - parameters
EOF
The CompositeResourceDefinition "xbuckets.version-test.imarunrk.com" is invalid: 
* <generated_CRD_"xbuckets.version-test.imarunrk.com">.spec.versions[0].name: Invalid value: "v1.0": a DNS-1035 label must consist of lower case alphanumeric characters or '-', start with an alphabetic character, and end with an alphanumeric character (e.g. 'my-name',  or 'abc-123', regex used for validation is '[a-z]([-a-z0-9]*[a-z0-9])?')
* <generated_CRD_"xbuckets.version-test.imarunrk.com">.spec.version: Invalid value: "v1.0": a DNS-1035 label must consist of lower case alphanumeric characters or '-', start with an alphabetic character, and end with an alphanumeric character (e.g. 'my-name',  or 'abc-123', regex used for validation is '[a-z]([-a-z0-9]*[a-z0-9])?')

When we troubleshoot an issue with Crossplane, logs from the Crossplane pod can help. Enable debugging mode by adding an argument, --debug, to the Crossplane pod. Similarly, we can even look at the provider’s container logs.


OpenAPIV3Schema structure

openAPIV3Schema:
  type: object
  properties:
    # spec – the API input configuration
    spec:
      type: object
      properties:
        ............. configuration continues 
    # status – the API output configuration 
    status:
      type: object
      properties:
        ............. configuration continues
# The root attribute openAPIV3Schema of type object
openAPIV3Schema:
  type: object
  # spec/status - attributes (properties) of openAPIV3Schema
  properties:
    # spec – the XR input
    spec:
      type: object
      properties:
        # parameters - again an object with attributes list
        parameters:
          type: object
          properties:
            # region – string primitive  - node ends
            region:
            type: string
    # status – API output configuration
    # The exact structure of configuration as before
    # Attributes, their types, and properties
    status:
      type: object
            properties:
              zone:
                description: DB zone.
                type: string   
spec:
  type: object
  description: API input specification 
  properties:
    parameters:
      type: object
      description: Parameter's to configure the resource
      properties:
        size:
          type: integer
          description: Disk size of the database
          default: 20
          minimum: 10
          maximum: 100
        vm:
          type: string
          description: Size of the virtual machine.
        enum:
        - small
        - medium
        - large
      required:
      - size
  required:
  - parameters

Printer Columns

additionalPrinterColumns:
- name: Zone
  type: string
  description: 
  jsonPath: .spec.zone
- name: Age
  type: date
  jsonPath: .metadata.creationTimestamp

Multi-resource nested XR

More on OpenAPI
img.png
img.png