diff --git a/.github/workflows/link-checker.yml b/.github/workflows/link-checker.yml index 7967e6ad0..9209981af 100644 --- a/.github/workflows/link-checker.yml +++ b/.github/workflows/link-checker.yml @@ -19,7 +19,7 @@ jobs: - name: Setup Hugo uses: peaceiris/actions-hugo@v2 with: - hugo-version: '0.109.0' + hugo-version: '0.119.0' extended: true - name: Build diff --git a/.github/workflows/weekly-link-checker.yml b/.github/workflows/weekly-link-checker.yml index 75baff01e..945296cc8 100644 --- a/.github/workflows/weekly-link-checker.yml +++ b/.github/workflows/weekly-link-checker.yml @@ -18,7 +18,7 @@ jobs: - name: Setup Hugo uses: peaceiris/actions-hugo@v2 with: - hugo-version: '0.109.0' + hugo-version: '0.119.0' extended: true - name: Build diff --git a/config.yaml b/config.yaml index 90dfd2d5c..71523cfa6 100644 --- a/config.yaml +++ b/config.yaml @@ -51,7 +51,7 @@ security: - ^REVIEW_ID params: - latest: "1.13" + latest: "1.14" upboundLink: "https://www.upbound.io/" slackLink: "https://slack.crossplane.io/" githubLink: "https://github.com/crossplane/crossplane" diff --git a/content/contribute/features.md b/content/contribute/features.md index 06c9912a1..697f63169 100644 --- a/content/contribute/features.md +++ b/content/contribute/features.md @@ -123,9 +123,9 @@ Hugo to fail. ## Images All images are in `/content/media`. -Crossplane supports standard [Markdown image -syntax](https://www.markdownguide.org/basic-syntax/#images-1) but using the -`img` shortcode is strongly recommended. +Crossplane supports standard +[Markdown image syntax](https://www.markdownguide.org/basic-syntax/#images-1) +but using the `img` shortcode is strongly recommended. Images using the shortcode are automatically converted to `webp` image format, compressed and use responsive image sizing. @@ -157,8 +157,9 @@ Which generates this responsive image (change your browser size to see it change {{Crossplane Popsicle Truck}} ## Links -Crossplane docs support standard [Markdown -links](https://www.markdownguide.org/basic-syntax/#links) but Crossplane prefers link shortcodes +Crossplane docs support standard +[Markdown links](https://www.markdownguide.org/basic-syntax/#links) +but Crossplane prefers link shortcodes for links between docs pages. Using shortcodes prevents incorrect link creation and notifies which links to change after moving a page. @@ -187,8 +188,9 @@ If the `ref` value points to a page that doesn't exist, Hugo fails to start. ### Linking to external sites Minimize linking to external sites. When linking to any page outside of -`crossplane.io` use standard [markdown link -syntax](https://www.markdownguide.org/basic-syntax/#links) without using the +`crossplane.io` use standard +[markdown link syntax](https://www.markdownguide.org/basic-syntax/#links) +without using the `ref` shortcode. For example, diff --git a/content/knowledge-base/guides/troubleshoot.md b/content/knowledge-base/guides/troubleshoot.md index a7d0e8e1e..19dd2bca6 100644 --- a/content/knowledge-base/guides/troubleshoot.md +++ b/content/knowledge-base/guides/troubleshoot.md @@ -387,88 +387,6 @@ For example, for a `CloudSQLInstance` managed resource (`database.gcp.crossplane kubectl patch cloudsqlinstance my-db -p '{"metadata":{"finalizers": []}}' --type=merge ``` -## Installing Crossplane Package - -After installing [Crossplane package], to verify the install results or -troubleshoot any issue spotted during the installation, there are a few things -you can do. - -Run below command to list all Crossplane resources available on your cluster: - -```shell -kubectl get crossplane -``` - -If you installed a Provider package, pay attention to the `Provider` and -`ProviderRevision` resource. Especially the `INSTALLED` and `HEALTHY` column. -They all need to be `TRUE`. Otherwise, there must be some errors that occurred -during the installation. - -If you installed a Configuration package, pay attention to the `Configuration` -and `ConfigurationRevision` resource. Again, the `INSTALLED` and `HEALTHY` -column for these resources need to be `TRUE`. Besides that, you should also see -the `CompositeResourceDefinition` and `Composition` resources included in this -package are listed if the package is installed successfully. - -If you only care about the installed packages, you can also run below command -which will show you all installed Configuration and Provider packages: - -```shell -kubectl get pkg -``` - -When there are errors, you can run below command to check detailed information -for the packages that are getting installed. - -```shell -kubectl get lock -o yaml -``` - -To inspect a particular package for troubleshooting, you can run -`kubectl describe` against the corresponding resources, e.g. the `Provider` and -`ProviderRevision` resource for Provider package, or the `Configuration` and -`ConfigurationRevision` resource for Configuration package. Usually, you should -be able to know the error reason by checking the `Status` and `Events` field for -these resources. - -## Handling Crossplane Package Dependency - -When using `crossplane.yaml` to define a Crossplane Configuration package, you -can specify packages that it depends on by including `spec.dependsOn`. You can -also specify version constraints for dependency packages. - -When you define a dependency package, please make sure you provide the fully -qualified address to the dependency package, but do not append the package -version (i.e. the OCI image tag) after the package name. This may lead to the -missing dependency error when Crossplane tries to install the dependency. - -When specifying the version constraint, you should strictly follow the -[semver spec]. Otherwise, it may not be able to find the appropriate version for -the dependency package even it says the dependency is found. This may lead to an -incompatible dependency error during the installation. - -Below is an example where a Configuration package depends on a provider pulled -from `xpkg.upbound.io/crossplane-contrib/provider-aws`. It defines `">=v0.18.2` -as the version constraint which means all versions after `v0.16.0` including all -prerelease versions, in the form of `-xyz` after the normal version string, will -be considered when Crossplane tries to find the best match. - -```yaml -apiVersion: meta.pkg.crossplane.io/v1 -kind: Configuration -metadata: - name: test-configuration - annotations: - provider: aws -spec: - crossplane: - version: ">=v1.4.0-0" - dependsOn: - - provider: xpkg.upbound.io/crossplane-contrib/provider-aws - version: ">=v0.18.2" -``` - - ## Tips, Tricks, and Troubleshooting In this section we'll cover some common tips, tricks, and troubleshooting steps diff --git a/content/master/concepts/composition-functions.md b/content/master/concepts/composition-functions.md index 809fba3e7..8c668e773 100644 --- a/content/master/concepts/composition-functions.md +++ b/content/master/concepts/composition-functions.md @@ -1,1026 +1,700 @@ --- title: Composition Functions -state: alpha +state: beta alphaVersion: "1.11" +betaVersion: "1.14" weight: 80 -description: "Composition Functions or XFNs allow for complex Composition patches" +description: "Composition Functions allow you to template resources using general-purpose programming languages" aliases: - /knowledge-base/guides/composition-functions --- - +Composition functions (or just functions, for short) are custom programs that +template Crossplane resources. Crossplane calls composition functions to +determine what resources it should create when you create a composite resource +(XR). You can write a function to template resources using a general purpose +programming language like Go or Python. Using a general purpose programming +language allows a Function to use more advanced logic to template resources, +like loops and conditionals. -Composition Functions allow you to supplement or replace your Compositions with -advanced logic not implementable through available patching strategies. +You can build a function using general purpose programming languages such as Go +or Python. The Crossplane community has also built functions that let you +template Crossplane resources using [CUE](https://cuelang.org), Helm-like +[Go templates](https://pkg.go.dev/text/template) or +[Patch and Transforms]({{}}). +## Install a composition function -You can build a Function using general-purpose programming -languages such as Go or Python, or relevant tools such as Helm, -[Kustomize](https://kustomize.io/), or -[CUE](https://cuelang.org/). +Installing a Function creates a function pod. Crossplane sends requests to this +pod to ask it what resources to create when you create a composite resource. -Functions complement contemporary "Patch and Transform" (P&T) style -Composition. It's possible to use only P&T, only Functions, or a mix of both in -the same Composition. +Install a Function with a Crossplane +{{}}Function{{}} object setting the +{{}}spec.package{{}} value to the +location of the function package. -```yaml -apiVersion: apiextensions.crossplane.io/v1 -kind: Composition + +For example, to install [Function Patch and Transform](https://github.com/crossplane-contrib/function-patch-and-transform), + +```yaml {label="install"} +apiVersion: pkg.crossplane.io/v1beta1 +kind: Function metadata: - name: example + name: function-patch-and-transform spec: - compositeTypeRef: - apiVersion: database.example.org/v1alpha1 - kind: XPostgreSQLInstance - functions: - - name: my-cool-Function - type: Container - container: - image: xpkg.upbound.io/my-cool-Function:0.1.0 + package: xpkg.upbound.io/crossplane-contrib/function-patch-and-transform:v0.1.4 ``` -A Composition Function is a short-lived OCI container that tells Crossplane how -to reconcile a Composite Resource (XR). The preceding example shows a minimal -`Composition` that uses a Composition Function. Note that it has a `functions` -array rather than the typical P&T style array of `resources`. +{{< hint "tip" >}} +Functions are Crossplane Packages. Read more about Packages in the +[Packages documentation]({{}}). +{{< /hint >}} -## Enabling functions +By default, the Function pod installs in the same namespace as Crossplane +(`crossplane-system`). -Enable support for Composition Functions by enabling the alpha feature flag in Crossplane with `helm install --args`. +## Verify a composition function -```shell -helm install crossplane --namespace crossplane-system crossplane-stable/crossplane \ - --create-namespace \ - --set "args='{--debug,--enable-composition-functions}'" \ - --set "xfn.enabled=true" \ - --set "xfn.args='{--debug}'" -``` +View the status of a Function with `kubectl get functions` -The preceding Helm command installs Crossplane with the Composition Functions -feature flag enabled, and with the reference _xfn_ Composition Function runner -deployed as a sidecar container. Confirm Composition Functions were enabled by -looking for a log line: +During the install a Function reports `INSTALLED` as `True` and `HEALTHY` as +`Unknown`. ```shell {copy-lines="1"} - kubectl -n crossplane-system logs -l app=crossplane -{"level":"info","ts":1674535093.36186,"logger":"crossplane","msg":"Alpha feature enabled","flag":"EnableAlphaCompositionFunctions"} +kubectl get functions +NAME INSTALLED HEALTHY PACKAGE AGE +function-patch-and-transform True Unknown xpkg.upbound.io/crossplane-contrib/function-patch-and-transform:v0.1.4 10s ``` -You should see the log line emitted shortly after Crossplane starts. +After the Function install completes and it's ready for use the `HEALTHY` status +reports `True`. +## Use a function in a composition -## Using functions +Crossplane calls a Function to determine what resources it should create when +you create a composite resource. The Function also tells Crossplane what to do +with these resources when a you update or delete a composite resource. -To use Composition Functions you must: +When Crossplane calls a Function it sends it the current state of the composite +resource. It also sends it the current state of any managed resources the +composite resource owns. -1. Find one or more Composition Functions, or write your own. -2. Create a `Composition` that uses your Functions. -3. Create an XR that uses your `Composition`. +Crossplane knows what Function to call when a composite resource changes by +looking at the Composition the composite resource uses. -Your XRs, claims, and providers don't need to be updated or otherwise aware -of Composition Functions to use them. They need only use a `Composition` that -includes one or more entries in its `spec.functions` array. +{{}} +Crossplane has four core components that users commonly mix up: -Composition Functions are designed to be run in a pipeline, so you can 'stack' -several of them together. Each Function is passed the output of the previous -Function as its input. Functions can also be used in conjunction with P&T -Composition (a `spec.resources` array). +* [Composition]({{}}) - A template to define how to create + resources. +* [CompositeResourceDefinition]({{}}) + (`XRD`) - A custom API specification. +* [Composite Resource]({{}}) (`XR`) - Created by + using the custom API defined in a CompositeResourceDefinition. XRs use the + Composition template to create new managed resources. +* [Claim]({{}}) (`XRC`) - Like a Composite Resource, but with + namespace scoping. +{{}} -In the following example P&T Composition composes an RDS instance. A pipeline of -(hypothetical) Composition Functions then mutates the desired RDS instance by -adding a randomly generated password, and composes an RDS security group. +To use composition functions set the Composition +{{}}mode{{}} to +{{}}Pipeline{{}}. -```yaml +Define a {{}}pipeline{{}} of +{{}}steps{{}}. Each +{{}}step{{}} calls a Function. + +Each {{}}step{{}} uses a +{{}}functionRef{{}} to reference the +{{}}name{{}} of the Function to call. + +{{}} +Compositions using {{}}mode: Pipeline{{}} +can't specify resource templates with a `resources` field. + +Use function "Patch and Transform" to create resource templates. +{{< /hint >}} + + +Some Functions also allow you to specify an +{{}}input{{}}. +The function defines the +{{}}kind{{}} of input. + +This example uses +[Function Patch and Transform](https://github.com/crossplane-contrib/function-patch-and-transform). +Function Patch and Transform implements Crossplane resource +templates. +The input kind is {{}}Resources{{}}, +and it accepts [Patch and Transform]({{}}) +{{}}resources{{}} as input. + +```yaml {label="single",copy-lines="none"} apiVersion: apiextensions.crossplane.io/v1 kind: Composition -metadata: - name: example +# Removed for Brevity spec: - compositeTypeRef: - apiVersion: database.example.org/v1alpha1 - kind: XPostgreSQLInstance - resources: - - name: rds-instance - base: - apiVersion: rds.aws.upbound.io/v1beta1 - kind: Instance - spec: - forProvider: - dbName: exmaple - instanceClass: db.t3.micro - region: us-west-2 - skipFinalSnapshot: true - username: exampleuser - engine: postgres - engineVersion: "12" - patches: - - fromFieldPath: spec.parameters.storageGB - toFieldPath: spec.forProvider.allocatedStorage - connectionDetails: - - type: FromFieldPath - name: username - fromFieldPath: spec.forProvider.username - - type: FromConnectionSecretKey - name: password - fromConnectionSecretKey: attribute.password - functions: - - name: rds-instance-password - type: Container - container: - image: xpkg.upbound.io/provider-aws-xfns/random-rds-password:v0.1.0 - - name: compose-dbsecuritygroup - type: Container - container: - image: xpkg.upbound.io/example-org/compose-rds-securitygroup:v0.9.0 + # Removed for Brevity + mode: Pipeline + pipeline: + - step: patch-and-transform + functionRef: + name: function-patch-and-transform + input: + apiVersion: pt.fn.crossplane.io/v1beta1 + kind: Resources + resources: + - name: storage-bucket + base: + apiVersion: s3.aws.upbound.io/v1beta1 + kind: Bucket + spec: + forProvider: + region: "us-east-2" ``` -Use `kubectl explain` to explore the configuration options available when using -Composition Functions, or take a look at the following example. +## Use a pipeline of functions in a composition -{{< expand "View Composition Function configuration options" >}} -```shell {copy-lines="1"} -kubectl explain composition.spec.functions -KIND: Composition -VERSION: apiextensions.crossplane.io/v1 +Crossplane can ask more than one Function what to do when a composite resource +changes. When a Composition has a pipeline of two or more steps, Crossplane +calls them all. It calls them in the order they appear in the pipeline. -RESOURCE: Functions <[]Object> +Crossplane passes each Function in the pipeline the result of the previous +Function. This enables powerful combinations of Functions. In this example, +Crossplane calls {{}}function-cue{{}} to +create an S3 bucket. Crossplane then passes the bucket to +{{}}function-auto-ready{{}}, which marks the +composite resource as ready when the bucket becomes ready. -DESCRIPTION: - Functions is list of Composition Functions that will be used when a - composite resource referring to this composition is created. At least one - of resources and Functions must be specified. If both are specified the - resources will be rendered first, then passed to the Functions for further - processing. THIS IS AN ALPHA FIELD. Do not use it in production. It is not - honored unless the relevant Crossplane feature flag is enabled, and may be - changed or removed without notice. +```yaml {label="double",copy-lines="none"} +apiVersion: apiextensions.crossplane.io/v1 +kind: Composition +# Removed for Brevity +spec: + # Removed for Brevity + mode: Pipeline + pipeline: + - step: cue-export-resources + functionRef: + name: function-cue + input: + apiVersion: cue.fn.crossplane.io/v1beta1 + kind: CUEInput + name: storage-bucket + export: + target: Resources + value: | + apiVersion: "s3.aws.upbound.io/v1beta1" + kind: "Bucket" + spec: forProvider: region: "us-east-2" + - step: automatically-detect-readiness + functionRef: + name: function-auto-ready +``` - A Function represents a Composition Function. +## Test a composition that uses functions -FIELDS: - config <> - Config is an optional, arbitrary Kubernetes resource (i.e. a resource with - an apiVersion and kind) that will be passed to the Composition Function as - the 'config' block of its FunctionIO. +You can preview the output of any composition that uses composition functions +using the Crossplane CLI. You don't need a Crossplane control plane to do +this. The Crossplane CLI uses Docker Engine to run functions. - container - Container configuration of this Function. - name -required- - Name of this Function. Must be unique within its Composition. +{{}} +See the [Crossplane CLI docs](https://github.com/crossplane/docs/pull/584) to +learn how to install and use the Crossplane CLI. +{{< /hint >}} + +{{}} +Running `crossplane beta render` requires [Docker](https://www.docker.com). +{{< /hint >}} - type -required- - Type of this Function. +Provide a composite resource, composition and composition functions to render +the output locally. + +```shell +crossplane beta render xr.yaml composition.yaml functions.yaml ``` -{{< /expand >}} -{{< expand "An example of most Composition Function configuration options" >}} +`crossplane beta render` prints resources as YAML to stdout. It prints the +composite resource first, followed by the resources the composition functions +created. + ```yaml -apiVersion: apiextensions.crossplane.io/v1 -kind: Composition +--- +apiVersion: example.crossplane.io/v1 +kind: XBucket metadata: - name: example + name: example-render +--- +apiVersion: s3.aws.upbound.io/v1beta1 +kind: Bucket +metadata: + annotations: + crossplane.io/composition-resource-name: storage-bucket + generateName: example-render- + labels: + crossplane.io/composite: example-render + ownerReferences: + - apiVersion: example.crossplane.io/v1 + blockOwnerDeletion: true + controller: true + kind: XBucket + name: example-render + uid: "" spec: - compositeTypeRef: - apiVersion: database.example.org/v1alpha1 - kind: XPostgreSQLInstance - functions: - - name: my-cool-Function - # Currently only Container is supported. Other types may be added in future. - type: Container - # Configuration specific to type: Container. - container: - # The OCI image to pull and run. - image: xkpg.io/my-cool-Function:0.1.0 - # Whether to pull the Function image Never, Always, or IfNotPresent. - imagePullPolicy: IfNotPresent - # Note that only resource limits are supported - not requests. - # The Function will be run with the specified resource limits, specified - # in Kubernetes-style resource.Quantity form. - resources: - limits: - # Defaults to 128Mi - memory: 64Mi - # Defaults to 100m (a 10th of a core) - cpu: 250m - # Defaults to 'Isolated' - an isolated network namespace with no network - # access. Use 'Runner' to allow a Function access to the runner's (the xfn - # container's) network namespace. - network: - policy: Runner - # How long the Function may run before it's killed. Defaults to 20s. - # Keep in mind the Function pipeline is typically invoked once every - # 30 to 60 seconds - sometimes more frequently during error conditions. - timeout: 30s - # An arbitrary Kubernetes resource. Passed to the Function as the config - # block of its FunctionIO. Doesn't need to exist as a Custom Resource (CR), - # since this resource doesn't exist by itself in the API server but must be - # a valid Kubernetes resource (have an apiVersion and kind). - config: - apiVersion: database.example.org/v1alpha1 - kind: Config - metadata: - name: cloudsql - spec: - version: POSTGRES_9_6 + forProvider: + region: us-east-2 ``` -{{< /expand >}} -Use `kubectl describe ` to debug Composition Functions. Look -for status conditions and events. Most Functions will emit events associated -with the XR if they experience issues. +{{}} -## Building a function +You can recreate the output below using by running `crossplane beta render` with +these files. - Crossplane doesn't have opinions about how a Composition Function is - implemented. Functions must: +The `xr.yaml` file contains the composite resource to render: - * Be packaged as an OCI image, where the `ENTRYPOINT` is the Function. - * Accept input in the form of a `FunctionIO` document on stdin. - * Return the `FunctionIO` they were passed, optionally mutated, on stdout. - * Run within the constraints specified by the Composition that includes them, - such as timeouts, compute, network access. - -This means Functions may be written using a general-purpose programming language -like Python, Go, or TypeScript. They may also be implemented using a shell -script, or an existing tool like Helm or Kustomize. +```yaml +apiVersion: example.crossplane.io/v1 +kind: XBucket +metadata: + name: example-render +spec: + bucketRegion: us-east-2 +``` -### FunctionIO +The `composition.yaml` file contains the Composition to use to render the +composite resource: -When a Composition Function runner like `xfn` runs your Function it will write -`FunctionIO` to its stdin. A `FunctionIO` is a Kubernetes style YAML manifest. -It's not a custom resource (it never gets created in the API server) but it -follows Kubernetes conventions. +```yaml +apiVersion: apiextensions.crossplane.io/v1 +kind: Composition +metadata: + name: example-render +spec: + compositeTypeRef: + apiVersion: example.crossplane.io/v1 + kind: XBucket + mode: Pipeline + pipeline: + - step: patch-and-transform + functionRef: + name: function-patch-and-transform + input: + apiVersion: pt.fn.crossplane.io/v1beta1 + kind: Resources + resources: + - name: storage-bucket + base: + apiVersion: s3.aws.upbound.io/v1beta1 + kind: Bucket + patches: + - type: FromCompositeFieldPath + fromFieldPath: spec.bucketRegion + toFieldPath: spec.forProvider.region +``` -A `FunctionIO` consists of: +The `functions.yaml` file contains the Functions the Composition references in +its pipeline steps: -* An optional, arbitrary `config` object. -* The `observed` state of the XR, any existing composed resources, and their connection details. -* The `desired` state of the XR and any composed resources. -* Optional `results` of the Function pipeline. +```yaml +--- +apiVersion: pkg.crossplane.io/v1beta1 +kind: Function +metadata: + name: function-patch-and-transform +spec: + package: xpkg.upbound.io/crossplane-contrib/function-patch-and-transform:v0.1.4 +``` +{{}} + +The Crossplane CLI uses Docker Engine to run functions. You can change how the +Crossplane CLI run a function by adding an annotation in `functions.yaml`. Add +the `render.crossplane.io/runtime` annotation to a Function to change how it's +run. + +`crossplane beta render` supports two `render.crossplane.io/runtime` values: + +* `Docker` (the default) connects to Docker Engine. It uses Docker to pull and + run a function runtime. +* `Development` connects to a function runtime you have run manually. + +When you use the {{}}Development{{}} +runtime the Crossplane CLI ignores the Function's {{}}package{{}}. Instead it expects you to make sure the function +is listening on localhost port 9443. The function must be listening without gRPC +transport security. Most function SDKs let you run a function with the +`--insecure` flag to disable transport security. For example you can run a Go +function locally using `go run . --insecure`. + +```yaml {label="development"} +apiVersion: pkg.crossplane.io/v1beta1 +kind: Function +metadata: + name: function-patch-and-transform + annotation: + render.crossplane.io/runtime: Development +spec: + package: xpkg.upbound.io/crossplane-contrib/function-patch-and-transform:v0.1.4 +``` -Here's a brief example of a `FunctionIO`: +{{}} +Use the `Development` runtime when you +[write a composition function](#write-a-composition-function) to test your +function end-to-end. +{{}} + +`crossplane beta render` also supports the following Function annotations. These +annotations affect how it runs Functions: + +* `render.crossplane.io/runtime-docker-cleanup` - When using the `Docker` +runtime this annotation specifies whether the CLI should stop the function +container after it calls the function. It supports the values `Stop`, to stop +the container, and `Orphan`, to leave it running. +* `render.crossplane.io/runtime-docker-pull-policy` - When using the `Docker` + runtime this annotation specifies when the CLI should pull the Function's + package. It supports the values `Always`, `Never`, and `IfNotPresent`. +* `render.crossplane.io/runtime-development-target` - When using the + `Development` runtime this annotation tells the CLI to connect to a Function + running at the specified target. It uses + [gRPC target syntax](https://github.com/grpc/grpc/blob/v1.59.1/doc/naming.md). + +## Write a composition function + +Composition functions let you replace complicated Compositions with code written +in your programming language of choice. Crossplane has tools, software +development kits (SDKs) and templates to help you write a function. + + + +Here's an example of a tiny, hello world function. This example is written in +[Go](https://go.dev). + + +```go +func (f *Function) RunFunction(_ context.Context, req *fnv1beta1.RunFunctionRequest) (*fnv1beta1.RunFunctionResponse, error) { + rsp := response.To(req, response.DefaultTTL) + response.Normal(rsp, "Hello world!") + return rsp, nil +} +``` -```yaml -apiVersion: apiextensions.crossplane.io/v1alpha1 -kind: FunctionIO -config: - apiVersion: database.example.org/v1alpha1 - kind: Config - metadata: - name: cloudsql - spec: - version: POSTGRES_9_6 -observed: - composite: - resource: - apiVersion: database.example.org/v1alpha1 - kind: XPostgreSQLInstance - metadata: - name: platform-ref-gcp-db-p9wrj - connectionDetails: - - name: privateIP - value: 10.135.0.3 - resources: - - name: db-instance - resource: - apiVersion: sql.gcp.upbound.io/v1beta1 - kind: DatabaseInstance - metadata: - name: platform-ref-gcp-db-p9wrj-tvvtg - connectionDetails: - - name: privateIP - value: 10.135.0.3 -desired: - composite: - resource: - apiVersion: database.example.org/v1alpha1 - kind: XPostgreSQLInstance - metadata: - name: platform-ref-gcp-db-p9wrj - connectionDetails: - - name: privateIP - value: 10.135.0.3 - resources: - - name: db-instance - resource: - apiVersion: sql.gcp.upbound.io/v1beta1 - kind: DatabaseInstance - metadata: - name: platform-ref-gcp-db-p9wrj-tvvtg - - name: db-user - resource: - apiVersion: sql.gcp.upbound.io/v1beta1 - kind: User - metadata: - name: platform-ref-gcp-db-p9wrj-z8lpz - connectionDetails: - - name: password - type: FromValue - value: very-secret - readinessChecks: - - type: None -results: -- severity: Normal - message: "Successfully composed GCP SQL user" +Some people design composition functions for you to use them with any kind of +composite resource. +[Function Patch and Transform](https://github.com/crossplane-contrib/function-patch-and-transform) +and +[Function Auto Ready](https://github.com/crossplane-contrib/function-auto-ready) +work with any kind of composite resource. + +Another common pattern is to write a composition function specific to one kind +of composite resource. The function contains all the logic needed to tell +Crossplane what resources to create when you create a composite resource. When +you write a composition function like this, your Composition can be small. It +just tells Crossplane what function to run when you create, update, or delete a +composite resource. + +This Composition tells Crossplane to call {{}}function-xr-xbucket{{}} whenever you create, update, or +delete an {{}}XBucket{{}} composite +resource. `function-xr-xbucket` is hard coded to handle `XBucket` composite +resources. + +```yaml {label="dedicated"} +apiVersion: apiextensions.crossplane.io/v1 +kind: Composition +metadata: + name: example-bucket-function +spec: + compositeTypeRef: + apiVersion: example.crossplane.io/v1 + kind: XBucket + mode: Pipeline + pipeline: + - step: handle-xbucket-xr + functionRef: + name: function-xr-xbucket ``` -The `config` object is copied from the `Composition`. It will match what's -passed as your Function's `config` in the `Functions` array. It must be a valid -Kubernetes object - have an `apiVersion` and `kind`. - -The `observed` state of the XR and any existing composed resources reflects the -observed state at the beginning of a reconcile, before any Composition happens. -Your Function will only see composite and composed resources that _actually -exist_ in the API server in the `observed` state. The `observed` state also -includes any observed connection details. Initial function invocations -might see empty connection details, but once external resources are created, -connection details will be passed to the functions. Access to the connection -details enables us to implement quite sophisticated tweaks on composed resources. - -For example, if a composition is declared on two or more resources, it is possible -to use one resource's connection details to update another. This ability is not available -with any of the available patch types available. - -The `desired` state of the XR and composed resources is how your Function tells -Crossplane what it should do. Crossplane 'bootstraps' the initial desired state -passed to a Function pipeline with: - -* A copy of the observed state of the composite resource (XR). -* A copy of the observed state of any existing composed resources produced - from the `resources` array. -* Any new composed resources or modifications to observed resources produced - from the `resources` array. - -{{< hint "note" >}} -The initial desired state doesn't include any copies of observed resources -produced by the function pipeline. When using multiple functions each function -passes their desired resources output as input to the next pipeline function. -{{< /hint >}} +To write a composition function, you: -When adding a new desired resource to the `desired.resources` array you don't -need to: +1. Create the function from a template. +1. Edit the template to add the function's logic. +1. [Test the function](#test-a-composition-that-uses-functions). +1. Build the function, and push it to a package registry. -* Update the XR's resource references. -* Add any composition annotations like `crossplane.io/composite-resource-name`. -* Set the XR as a controller/owner reference of the desired resource. +You use the [Crossplane CLI](https://github.com/crossplane/docs/pull/584) to +create, test, build, and push a function. For example, -Crossplane will take care of all of these for you. It won't do anything else, -including setting a sensible `metadata.name` for the new composed resource - -this is up to your Function. +```shell {copy-lines=none} +# Create the function from a template. +crossplane beta xpkg init function-example function-template-go +Initialized package "function-example" in directory "/home/negz/control/negz/function-example" from https://github.com/crossplane/function-template-go/tree/91a1a5eed21964ff98966d72cc6db6f089ad63f4 (main) -Finally, the `results` array allows your Function to surface events and debug -logs on the XR. Results support the following severities: +$ ls +Dockerfile fn.go fn_test.go go.mod go.sum input LICENSE main.go package README.md renovate.json -* `Normal` emits a debug log and a `Normal` event associated with the XR. -* `Warning` emits a debug log and a `Warning` event associated with the XR. -* `Fatal` stops the Composition process before applying any changes. +# Edit the template to add your function's logic +$ vim fn.go -When Crossplane encounters a `Fatal` result it will finish running the -Composition Function pipeline. Crossplane will then return an error without -applying any changes to the API server. Crossplane surfaces this error as a -`Warning` event, a debug log, and by setting the `Synced` status condition of -the XR to "False". +# Build the function. +$ docker build . --quiet --tag runtime +sha256:2c31b0f7a34b34ba5b0b2dacc94c360d18aca1b99f56ca4f40a1f26535a7c1c4 -The preceding example is heavily edited for brevity. Expand the following -example for a more detailed, realistic, and commented example of a `FunctionIO`. +# Package the function. +$ crossplane xpkg build -f package --embed-runtime-image=runtime -{{< expand "A more detailed example" >}} -In this example a `XPostgreSQLInstance` XR has one existing composed resource - -`db-instance`. The composition Function returns a `desired` object with one new -composed resource, a `db-user`, to tell Crossplane it should also create a -database user. +# Test the function. +$ go run . --insecure +$ crossplane beta render xr.yaml composition.yaml functions.yaml -```yaml -apiVersion: apiextensions.crossplane.io/v1alpha1 -kind: FunctionIO -config: - apiVersion: database.example.org/v1alpha1 - kind: Config - metadata: - name: cloudsql - spec: - version: POSTGRES_9_6 -observed: - # The observed state of the Composite Resource. - composite: - resource: - apiVersion: database.example.org/v1alpha1 - kind: XPostgreSQLInstance - metadata: - creationTimestamp: "2023-01-27T23:47:12Z" - finalizers: - - composite.apiextensions.crossplane.io - generateName: platform-ref-gcp-db- - generation: 5 - labels: - crossplane.io/claim-name: platform-ref-gcp-db - crossplane.io/claim-namespace: default - crossplane.io/composite: platform-ref-gcp-db-p9wrj - name: platform-ref-gcp-db-p9wrj - resourceVersion: "6817" - uid: 96623f41-be2e-4eda-84d4-9668b48e284d - spec: - claimRef: - apiVersion: database.example.org/v1alpha1 - kind: PostgreSQLInstance - name: platform-ref-gcp-db - namespace: default - compositionRef: - name: xpostgresqlinstances.database.example.org - compositionRevisionRef: - name: xpostgresqlinstances.database.example.org-eb6c684 - compositionUpdatePolicy: Automatic - parameters: - storageGB: 10 - resourceRefs: - - apiVersion: sql.gcp.upbound.io/v1beta1 - kind: DatabaseInstance - name: platform-ref-gcp-db-p9wrj-tvvtg - writeConnectionSecretToRef: - name: 96623f41-be2e-4eda-84d4-9668b48e284d - namespace: upbound-system - status: - conditions: - - lastTransitionTime: "2023-01-27T23:47:12Z" - reason: ReconcileSuccess - status: "True" - type: Synced - - lastTransitionTime: "2023-01-28T00:09:12Z" - reason: Creating - status: "False" - type: Ready - connectionDetails: - lastPublishedTime: "2023-01-28T00:08:12Z" - # Any observed Composite Resource connection details. - connectionDetails: - - name: privateIP - value: 10.135.0.3 - # The observed state of any existing Composed Resources. - resources: - - name: db-instance - resource: - apiVersion: sql.gcp.upbound.io/v1beta1 - kind: DatabaseInstance - metadata: - annotations: - crossplane.io/composition-resource-name: db-instance - crossplane.io/external-name: platform-ref-gcp-db-p9wrj-tvvtg - creationTimestamp: "2023-01-27T23:47:12Z" - finalizers: - - finalizer.managedresource.crossplane.io - generateName: platform-ref-gcp-db-p9wrj- - generation: 80 - labels: - crossplane.io/claim-name: platform-ref-gcp-db - crossplane.io/claim-namespace: default - crossplane.io/composite: platform-ref-gcp-db-p9wrj - name: platform-ref-gcp-db-p9wrj-tvvtg - ownerReferences: - - apiVersion: database.example.org/v1alpha1 - blockOwnerDeletion: true - controller: true - kind: XPostgreSQLInstance - name: platform-ref-gcp-db-p9wrj - uid: 96623f41-be2e-4eda-84d4-9668b48e284d - resourceVersion: "7992" - uid: 43919834-fdce-427e-85d9-d03eab9501f1 - spec: - forProvider: - databaseVersion: POSTGRES_13 - deletionProtection: false - project: example - region: us-west2 - settings: - - diskSize: 10 - ipConfiguration: - - privateNetwork: projects/example/global/networks/platform-ref-gcp-cluster - privateNetworkRef: - name: platform-ref-gcp-cluster - tier: db-f1-micro - providerConfigRef: - name: default - writeConnectionSecretToRef: - name: 96623f41-be2e-4eda-84d4-9668b48e284d-gcp-postgresql - namespace: upbound-system - status: - atProvider: - connectionName: example:us-west2:platform-ref-gcp-db-p9wrj-tvvtg - firstIpAddress: 34.102.103.85 - id: platform-ref-gcp-db-p9wrj-tvvtg - privateIpAddress: 10.135.0.3 - publicIpAddress: 34.102.103.85 - settings: - - version: 1 - conditions: - - lastTransitionTime: "2023-01-28T00:07:30Z" - reason: Available - status: "True" - type: Ready - - lastTransitionTime: "2023-01-27T23:47:14Z" - reason: ReconcileSuccess - status: "True" - type: Synced - # Any observed composed resource connection details. - connectionDetails: - - name: privateIP - value: 10.135.0.3 -desired: - # The observed state of the Composite Resource. - composite: - resource: - apiVersion: database.example.org/v1alpha1 - kind: XPostgreSQLInstance - metadata: - creationTimestamp: "2023-01-27T23:47:12Z" - finalizers: - - composite.apiextensions.crossplane.io - generateName: platform-ref-gcp-db- - generation: 5 - labels: - crossplane.io/claim-name: platform-ref-gcp-db - crossplane.io/claim-namespace: default - crossplane.io/composite: platform-ref-gcp-db-p9wrj - name: platform-ref-gcp-db-p9wrj - resourceVersion: "6817" - uid: 96623f41-be2e-4eda-84d4-9668b48e284d - spec: - claimRef: - e apiVersion: database.example.org/v1alpha1 - kind: PostgreSQLInstance - name: platform-ref-gcp-db - namespace: default - compositionRef: - name: xpostgresqlinstances.database.example.org - compositionRevisionRef: - name: xpostgresqlinstances.database.example.org-eb6c684 - compositionUpdatePolicy: Automatic - parameters: - storageGB: 10 - resourceRefs: - - apiVersion: sql.gcp.upbound.io/v1beta1 - kind: DatabaseInstance - name: platform-ref-gcp-db-p9wrj-tvvtg - writeConnectionSecretToRef: - name: 96623f41-be2e-4eda-84d4-9668b48e284d - namespace: upbound-system - status: - conditions: - - lastTransitionTime: "2023-01-27T23:47:12Z" - reason: ReconcileSuccess - status: "True" - type: Synced - - lastTransitionTime: "2023-01-28T00:09:12Z" - reason: Creating - status: "False" - type: Ready - connectionDetails: - lastPublishedTime: "2023-01-28T00:08:12Z" - # Any desired Composite Resource connection details. Your Composition - # Function can add new entries to this array and Crossplane will record them - # as the XR's connection details. - connectionDetails: - - name: privateIP - value: 10.135.0.3 - # The desired composed resources. - resources: - # This db-instance matches the entry in observed. Functions must include any - # observed resources in their desired resources array. If you omit an observed - # resource from the desired resources array Crossplane will delete it. - # Crossplane will 'bootstrap' the desired state passed to the Function - # pipeline by copying all observed resources into the desired resources array. - - name: db-instance - resource: - apiVersion: sql.gcp.upbound.io/v1beta1 - kind: DatabaseInstance - metadata: - annotations: - crossplane.io/composition-resource-name: DBInstance - crossplane.io/external-name: platform-ref-gcp-db-p9wrj-tvvtg - creationTimestamp: "2023-01-27T23:47:12Z" - finalizers: - - finalizer.managedresource.crossplane.io - generateName: platform-ref-gcp-db-p9wrj- - generation: 80 - labels: - crossplane.io/claim-name: platform-ref-gcp-db - crossplane.io/claim-namespace: default - crossplane.io/composite: platform-ref-gcp-db-p9wrj - name: platform-ref-gcp-db-p9wrj-tvvtg - ownerReferences: - - apiVersion: database.example.org/v1alpha1 - blockOwnerDeletion: true - controller: true - kind: XPostgreSQLInstance - name: platform-ref-gcp-db-p9wrj - uid: 96623f41-be2e-4eda-84d4-9668b48e284d - resourceVersion: "7992" - uid: 43919834-fdce-427e-85d9-d03eab9501f1 - spec: - forProvider: - databaseVersion: POSTGRES_13 - deletionProtection: false - project: example - region: us-west2 - settings: - - diskSize: 10 - ipConfiguration: - - privateNetwork: projects/example/global/networks/platform-ref-gcp-cluster - privateNetworkRef: - name: platform-ref-gcp-cluster - tier: db-f1-micro - providerConfigRef: - name: default - writeConnectionSecretToRef: - name: 96623f41-be2e-4eda-84d4-9668b48e284d-gcp-postgresql - namespace: upbound-system - status: - atProvider: - connectionName: example:us-west2:platform-ref-gcp-db-p9wrj-tvvtg - firstIpAddress: 34.102.103.85 - id: platform-ref-gcp-db-p9wrj-tvvtg - privateIpAddress: 10.135.0.3 - publicIpAddress: 34.102.103.85 - settings: - - version: 1 - conditions: - - lastTransitionTime: "2023-01-28T00:07:30Z" - reason: Available - status: "True" - type: Ready - - lastTransitionTime: "2023-01-27T23:47:14Z" - reason: ReconcileSuccess - status: "True" - type: Synced - # This db-user is a desired composed resource that doesn't yet exist. This - # Composition Function is requesting it be created. - - name: db-user - resource: - apiVersion: sql.gcp.upbound.io/v1beta1 - kind: User - metadata: - annotations: - crossplane.io/composition-resource-name: db-user - crossplane.io/external-name: platform-ref-gcp-db-p9wrj-z8lpz - creationTimestamp: "2023-01-27T23:47:12Z" - finalizers: - - finalizer.managedresource.crossplane.io - generateName: platform-ref-gcp-db-p9wrj- - generation: 115 - labels: - crossplane.io/claim-name: platform-ref-gcp-db - crossplane.io/claim-namespace: default - crossplane.io/composite: platform-ref-gcp-db-p9wrj - name: platform-ref-gcp-db-p9wrj-z8lpz - ownerReferences: - - apiVersion: database.example.org/v1alpha1 - blockOwnerDeletion: true - controller: true - kind: XPostgreSQLInstance - name: platform-ref-gcp-db-p9wrj - uid: 96623f41-be2e-4eda-84d4-9668b48e284d - resourceVersion: "9951" - uid: ab5dafbe-2bc8-47ea-8b5b-9bcb40183e45 - spec: - forProvider: - instance: platform-ref-gcp-db-p9wrj-tvvtg - project: example - providerConfigRef: - name: default - # Any desired connection details for the new db-user composed resource. - # Desired connection details can be FromValue, FromFieldPath, or - # FromConnectionSecretKey, just like their P&T Composition equivalents. - connectionDetails: - - name: password - type: FromValue - value: very-secret - # Any desired readiness checks for the new db-user composed resource. - # Desired readiness checks can be NonEmpty, MatchString, MatchInteger, or - # None, just like their P&T Composition equivalents. - readinessChecks: - - type: None -# An optional array of results. -results: -- severity: Normal - message: "Successfully composed GCP SQL user" +# Push the function package to xpkg.upbound.io. +$ crossplane xpkg push -f package/*.xpkg crossplane-contrib/function-example:v0.1.0 ``` -{{< /expand >}} - -### An example Function -You can write a Composition Function using any programming language that can be -containerized, or existing tools like Helm or Kustomize. +{{}} +Crossplane has +[language specific guides]({{}}) to writing +a composition function. Refer to the guide for your preferred language for a +more detailed guide to writing a function. +{{}} + +When you're writing a composition function it's useful to know how composition +functions work. Read the next section to learn +[how composition functions work](#how-composition-functions-work). + +## How composition functions work + +Each composition function is actually a [gRPC](https://grpc.io) server. gRPC is +a high performance, open source remote procedure call (RPC) framework. When you +[install a function](#install-a-composition-function) Crossplane deploys the +function as a gRPC server. Crossplane encrypts and authenticates all gRPC +communication. + +You don't have to be a gRPC expert to write a function. Crossplane's function +SDKs setup gRPC for you. It's useful to understand how Crossplane calls your +function though, and how your function should respond. + +```mermaid +sequenceDiagram + User->>+API Server: Create composite resource + Crossplane Pod->>+API Server: Observe composite resource + Crossplane Pod->>+Function Pod: gRPC RunFunctionRequest + Function Pod->>+Crossplane Pod: gRPC RunFunctionResponse + Crossplane Pod->>+API Server: Apply desired composed resources +``` -Here's a Python Composition Function that doesn't create any new desired -resources, but instead annotates any existing desired resources with a quote. -Because this function accesses the internet it needs to be run with the `Runner` -network policy. +When you create, update, or delete a composite resource that uses composition +functions Crossplane calls each function in the order they appear in the +Composition's pipeline. Crossplane calls each function by sending it a gRPC +RunFunctionRequest. The function must respond with a gRPC RunFunctionResponse. -```python -import sys +{{}} +You can find detailed schemas for the RunFunctionRequest and RunFunctionResponse +RPCs in the [Buf Schema Registry](https://buf.build/crossplane/crossplane/docs/main:apiextensions.fn.proto.v1beta1). +{{}} -import requests -import yaml +When Crossplane calls a function it includes four important things in the +RunFunctionRequest. -ANNOTATION_KEY_AUTHOR = "quotable.io/author" -ANNOTATION_KEY_QUOTE = "quotable.io/quote" +1. The __observed state__ of the composite resource, and any composed resources. +1. The __desired state__ of the composite resource, and any composed resources. +1. The function's __input__. +1. The function pipeline's __context__. +A function's main job is to update the __desired state__ and return it to +Crossplane. It does this by returning a RunFunctionResponse. -def get_quote() -> tuple[str, str]: - """Get a quote from quotable.io""" - rsp = requests.get("https://api.quotable.io/random") - rsp.raise_for_status() - j = rsp.json() - return (j["author"], j["content"]) +Most composition functions read the observed state of the composite resource, +and use it to add composed resources to the desired state. This tells Crossplane +which composed resources it should create or update. +{{}} + + +A _composed_ resource is a resource created by a composite resource. Composed +resources are usually Crossplane managed resources (MRs), but they can be any +kind of Crossplane resource. For example a composite resource could also create +a ProviderConfig, or another kind of composite resource. + +{{}} -def read_Functionio() -> dict: - """Read the FunctionIO from stdin.""" - return yaml.load(sys.stdin.read(), yaml.Loader) +### Observed state +When you create a composite resource like this one, Crossplane _observes_ it and +sends it to the composition function as part of the observed state. -def write_Functionio(Functionio: dict): - """Write the FunctionIO to stdout and exit.""" - sys.stdout.write(yaml.dump(Functionio)) - sys.exit(0) +```yaml +apiVersion: example.crossplane.io/v1 +kind: XBucket +metadata: + name: example-render +spec: + bucketRegion: us-east-2 +``` +If any composed resources already exist, Crossplane observes them and sends them +to your function to as part of the observed state. -def result_warning(Functionio: dict, message: str): - """Add a warning result to the supplied FunctionIO.""" - if "results" not in Functionio: - Functionio["results"] = [] - Functionio["results"].append({"severity": "Warning", "message": message}) +Crossplane also observes the connection details of your composite resource and +any composed resources. It sends them to your function as part of the observed +state. +Crossplane observes the composite resource and any composed resources once, +right before it starts calling the functions in the pipeline. This means that +Crossplane sends every function in the pipeline the same observed state. -def main(): - """Annotate all desired composed resources with a quote from quotable.io""" - try: - Functionio = read_Functionio() - except yaml.parser.ParserError as err: - sys.stdout.write("cannot parse FunctionIO: {}\n".format(err)) - sys.exit(1) +### Desired state - # Return early if there are no desired resources to annotate. - if "desired" not in Functionio or "resources" not in Functionio["desired"]: - write_Functionio(Functionio) +Desired state is the set of the changes the function pipeline wants to make to +the composite resource and any composed resources. When a function adds composed +resources to the desired state Crossplane creates them. - # If we can't get our quote, add a warning and return early. - try: - quote, author = get_quote() - except requests.exceptions.RequestException as err: - result_warning(Functionio, "Cannot get quote: {}".format(err)) - write_Functionio(Functionio) +A function can change: - # Annotate all desired resources with our quote. - for r in Functionio["desired"]["resources"]: - if "resource" not in r: - # This shouldn't happen - add a warning and continue. - result_warning( - Functionio, - "Desired resource {name} missing resource body".format( - name=r.get("name", "unknown") - ), - ) - continue +* The `status` of the composite resource. +* The `metadata` and `spec` of any composed resource. - if "metadata" not in r["resource"]: - r["resource"]["metadata"] = {} +A function can also change the connection details and readiness of the composite +resource. A function indicates that the composite resource is ready by telling +Crossplane whether its composed resources are ready. When the function pipeline +tells Crossplane that all composed resources are ready, Crossplane marks the +composite resource as ready. - if "annotations" not in r["resource"]["metadata"]: - r["resource"]["metadata"]["annotations"] = {} +A function can't change: - if ANNOTATION_KEY_QUOTE in r["resource"]["metadata"]["annotations"]: - continue +* The `metadata` or `spec` of the composite resource. +* The `status` of any composed resource. +* The connection details of any composed resource. - r["resource"]["metadata"]["annotations"][ANNOTATION_KEY_AUTHOR] = author - r["resource"]["metadata"]["annotations"][ANNOTATION_KEY_QUOTE] = quote +A pipeline of functions _accumulates_ desired state. This means that each +function builds upon the desired state of previous functions in the pipeline. +Crossplane sends a function the desired state accumulated by all previous +functions in the pipeline. The function adds to or updates the desired state and +then passes it on. When the last function in the pipeline has run, Crossplane +applies the desired state it returns. - write_Functionio(Functionio) +{{}} +A function __must__ copy all desired state from its RunFunctionRequest to its +RunFunctionResponse. If a function adds a resource to its desired state the next +function must copy it to its desired state. If it doesn't, Crossplane doesn't +apply the resource. If the resource exists, Crossplane deletes it. +A function can _intentionally_ choose not to copy parts of the desired state. +For example a function may choose not to copy a desired resource to prevent that +resource from existing. -if __name__ == "__main__": - main() -``` +Most function SDKs handle copying desired state automatically. +{{}} -Building this function requires its `requirements.txt` and a `Dockerfile`: - -{{< expand "The Function's requirements" >}} -```python -certifi==2022.12.7 -charset-normalizer==3.0.1 -click==8.1.3 -idna==3.4 -pathspec==0.10.3 -platformdirs==2.6.2 -PyYAML==6.0 -requests==2.28.2 -tomli==2.0.1 -urllib3==1.26.14 -``` -{{< /expand >}} - -{{< expand "The Function's Dockerfile" >}} -```Dockerfile -FROM debian:11-slim AS build -RUN apt-get update && \ - apt-get install --no-install-suggests --no-install-recommends --yes python3-venv && \ - python3 -m venv /venv && \ - /venv/bin/pip install --upgrade pip setuptools wheel - -FROM build AS build-venv -COPY requirements.txt /requirements.txt -RUN /venv/bin/pip install --disable-pip-version-check -r /requirements.txt - -FROM gcr.io/distroless/python3-debian11 -COPY --from=build-venv /venv /venv -COPY . /app -WORKDIR /app -ENTRYPOINT ["/venv/bin/python3", "main.py"] -``` -{{< /expand >}} +A function should only add the fields it cares about to the desired state. It +should add these fields every time Crossplane calls it. If a function adds a +field to the desired state once, but doesn't add it the next time it's called, +Crossplane deletes the field. The same is true for composed resources. If a +function adds a composed resource to the desired state, but doesn't add it the +next time it's called, Crossplane deletes the composed resource. -Create and push the Function just like you would any Docker image. +{{}} +Crossplane uses +[server side apply](https://kubernetes.io/docs/reference/using-api/server-side-apply/) +to apply the desired state returned by a function pipeline. In server side apply +terminology, the desired state is a _fully specified intent_. +{{}} -Build the function. +For example, if all a function wants is to make sure an S3 bucket in region +`us-east-2` exists, it should add this resource to its desired composed +resources. -```shell {copy-lines="1"} -docker build . -Sending build context to Docker daemon 38.99MB -Step 1/10 : FROM debian:11-slim AS build - ---> 4810399f6c13 -Step 2/10 : RUN apt-get update && apt-get install --no-install-suggests --no-install-recommends --yes python3-venv gcc && python3 -m venv /venv && /venv/bin/pip install --upgrade pip setuptools wheel - ---> Using cache - ---> 9b34960c88d7 -Step 3/10 : FROM build AS build-venv - ---> 9b34960c88d7 -Step 4/10 : COPY requirements.txt /requirements.txt - ---> Using cache - ---> fae19dad52af -Step 5/10 : RUN /venv/bin/pip install --disable-pip-version-check -r /requirements.txt - ---> Using cache - ---> f4b811c75812 -Step 6/10 : FROM gcr.io/distroless/python3-debian11 - ---> 2a0e74a2b005 -Step 7/10 : COPY --from=build-venv /venv /venv - ---> Using cache - ---> cf727d3f20d3 -Step 8/10 : COPY . /app - ---> a044aef45e32 -Step 9/10 : WORKDIR /app - ---> Running in d08a6144815b -Removing intermediate container d08a6144815b - ---> 7250f5aa653e -Step 10/10 : ENTRYPOINT ["/venv/bin/python3", "main.py"] - ---> Running in 3f4d9dc55bad -Removing intermediate container 3f4d9dc55bad - ---> bfd2f920c591 -Successfully built bfd2f920c591 +```yaml +apiVersion: s3.aws.upbound.io/v1beta1 +kind: Bucket +spec: + forProvider: + region: us-east-2 ``` -Tag the function. -```shell -docker tag bfd2f920c591 example-org/xfn-quotable-simple:v0.1.0 -``` +Even if the Bucket already exists and has other `spec` fields, or a `status`, +`name`, `labels`, etc the function should omit them. The function should only +include the fields it has an opinion about. Crossplane takes care of applying +the fields the function cares about, merging them with the existing Bucket. -Push the function. +{{}} +Composition functions don't actually use YAML for desired and observed +resources. This example uses YAML for illustration purposes only. +{{}} -```shell {copy-lines="1"} -docker push xpkg.upbound.io/example-org/xfn-quotable-simple:v0.1.0 -The push refers to repository [xpkg.upbound.io/example-org/xfn-quotable-simple] -cf6d94b88843: Pushed -77646fd315d2: Mounted from example-org/xfn-quotable -50630ee42b6e: Mounted from example-org/xfn-quotable -7e2cf97ed8c4: Mounted from example-org/xfn-quotable -96e320b34b54: Mounted from example-org/xfn-quotable -fba4381f2bb7: Mounted from example-org/xfn-quotable -v0.1.0: digest: sha256:d8a6404e5fe38936aa8dadd861fea35ede0aded6168d501052f91cdabab0135e size: 1584 -``` +### Function input -You can now use this Function in your Composition. The following example will -create an `RDSInstance` using P&T Composition, then run the Function to annotate -it with a quote. +If a Composition includes {{}}input{{}} +Crossplane sends it to the function. Input is a useful way to provide extra +configuration to a function. Supporting input is optional. Not all functions +support input. -```yaml +```yaml {label="input",copy-lines="none"} apiVersion: apiextensions.crossplane.io/v1 kind: Composition metadata: - name: example + name: example-render spec: compositeTypeRef: - apiVersion: database.example.org/v1alpha1 - kind: XPostgreSQLInstance - resources: - - name: rds-instance - base: - apiVersion: rds.aws.upbound.io/v1beta1 - kind: Instance - spec: - forProvider: - dbName: example - instanceClass: db.t3.micro - region: us-west-2 - skipFinalSnapshot: true - username: exampleuser - engine: postgres - engineVersion: "12" - patches: - - fromFieldPath: spec.parameters.storageGB - toFieldPath: spec.forProvider.allocatedStorage - connectionDetails: - - type: FromFieldPath - name: username - fromFieldPath: spec.forProvider.username - - type: FromConnectionSecretKey - name: password - fromConnectionSecretKey: attribute.password - functions: - - name: quotable - type: Container - container: - image: xpkg.upbound.io/example-org/xfn-quotable-simple:v0.1.0 - network: - policy: Runner + apiVersion: example.crossplane.io/v1 + kind: XBucket + mode: Pipeline + pipeline: + - step: patch-and-transform + functionRef: + name: function-patch-and-transform + input: + apiVersion: pt.fn.crossplane.io/v1beta1 + kind: Resources + resources: + - name: storage-bucket + base: + apiVersion: s3.aws.upbound.io/v1beta1 + kind: Bucket + patches: + - type: FromCompositeFieldPath + fromFieldPath: spec.bucketRegion + toFieldPath: spec.forProvider.region ``` -### Tips for new functions - -Here are some things to keep in mind when building a Composition Function: - -* Your Function may be running as part of a pipeline. This means your Function - _must_ pass through any desired state that it's unconcerned with. If your - Function is passed a desired composed resource and doesn't return that - composed resource in its output, it will be deleted. Crossplane considers the - desired state of the XR and any composed resources to be whatever `FunctionIO` - is returned by the last Function in the pipeline. -* Crossplane won't set a `metadata.name` for your desired resources resources. - It's a good practice to match P&T Composition's behavior by setting - `metadata.generateName: "name-of-the-xr-"` for any new desired resources. -* Don't add new entries to the desired resources array every time your function - is invoked. Remember to check whether your desired resource is already in the - `observed` and/or `desired` objects. You may need to update it rather than - create it. -* Don't bypass providers. Composition Functions are designed to tell Crossplane - how to orchestrate managed resources - not to directly orchestrate external - systems. -* Include your function name and version in any results you return to aid in - debugging. -* Write tests for your function. Pass it a `FunctionIO` on stdin in and ensure - it returns the expected `FunctionIO` on stdout. -* Keep your Functions fast and lightweight. Remember that Crossplane runs them - approximately once every 30-60 seconds. - -## The xfn runner - -Composition Function runners are designed to be pluggable. Each time Crossplane -needs to invoke a Composition Function it makes a gRPC call to a configurable -endpoint. The default, reference Composition Function runner is named `xfn`. - -{{< hint "note" >}} -The default runner endpoint is `unix-abstract:crossplane/fn/default.sock`. It's -possible to run Functions using a different endpoint, for example: +{{}} +Crossplane doesn't validate function input. It's a good idea for a function to +validate its own input. +{{}} -```yaml - functions: - - name: my-cool-Function - type: Container - container: - image: xkpg.io/my-cool-Function:0.1.0 - runner: - endpoint: unix-abstract:/your/custom/runner.sock -``` - -Currently Crossplane uses unauthenticated, unencrypted gRPC requests to run -Functions, so requests shouldn't be sent over the network. Encryption and -authentication will be added in a future release. -{{< /hint >}} +### Function pipeline context -`xfn` runs as a sidecar container within the Crossplane pod. It runs each -Composition Function as a nested [rootless container][rootless-containers]. +Sometimes two functions in a pipeline want to share information with each other +that isn't desired state. Functions can use context for this. Any function can +write to the pipeline context. Crossplane passes the context to all following +functions. When Crossplane has called all functions it discards the pipeline +context. -{{< img src="media/composition-functions-xfn-runner.png" alt="Crossplane running Functions using xfn via gRPC" size="tiny" >}} +Crossplane can write context too. If you enable the alpha +[composition environment]({{}}) feature Crossplane +writes the environment to the top-level context field +`apiextensions.crossplane.io/environment`. -The Crossplane Helm chart deploys `xfn` with: +## Disable composition functions -* The [`Unconfined` seccomp profile][kubernetes-seccomp]. -* The `CAP_SETUID` and `CAP_SETGID` capabilities. +Crossplane enables composition functions by default. Disable support for +composition functions by disabling the beta feature flag in Crossplane with +`helm install --args`. -The `Unconfined` seccomp profile allows Crossplane to make required syscalls -such as `unshare` and `mount` that are not allowed by most `RuntimeDefault` -profiles. It's possible to run `xfn` with nearly the same restrictions as most -`RuntimeDefault` profiles by authoring a custom `Localhost` profile. Refer to -the [seccomp documentation][kubernetes-seccomp] for information on how to do so. +```shell +helm install crossplane --namespace crossplane-system crossplane-stable/crossplane \ + --create-namespace \ + --set "args='{--enable-composition-functions=false}'" +``` -Granting `CAP_SETUID` and `CAP_SETGID` allows `xfn` to create Function -containers that support up to 65,536 UIDs and GIDs. If `xfn` is run without -these capabilities it will be restricted to creating Function containers that -support only UID and GID 0. +The preceding Helm command installs Crossplane with the composition functions +feature flag disabled. Confirm you have disabled composition functions by +looking for a log line: -Regardless of capabilities `xfn` always runs each Composition Function as an -unprivileged user. That user will appear to be root inside the Composition -Function container thanks to [`user_namespaces(7)`]. +```shell {copy-lines="1"} + kubectl -n crossplane-system logs -l app=crossplane +{"level":"info","ts":1674535093.36186,"logger":"crossplane","msg":"Beta feature enabled","flag":"EnableBetaCompositionFunctions"} +``` -[rootless-containers]: https://rootlesscontaine.rs -[kubernetes-seccomp]: https://kubernetes.io/docs/tutorials/security/seccomp/ -[`user_namespaces(7)`]: https://man7.org/linux/man-pages/man7/user_namespaces.7.html +If you don't see the log line emitted when Crossplane starts, you have disabled +composition functions. diff --git a/content/master/concepts/compositions.md b/content/master/concepts/compositions.md index 15a11ee74..f9666c6d2 100644 --- a/content/master/concepts/compositions.md +++ b/content/master/concepts/compositions.md @@ -41,8 +41,8 @@ Optionally, Compositions also support: * [Modifying and patching](#changing-resource-fields) resource settings. * [Storing connection details](#storing-connection-details) and secrets generated by the managed resources. -* Using [Composition functions](#composition-functions) to allow custom - programs to run alongside the Composition. +* Using [Composition Functions](#use-composition-functions) to template + resources using custom programs. * Creating a [custom check of when a resource is ready](#resource-readiness-checks) to use. @@ -664,40 +664,72 @@ spec: The [EnvironmentConfigs]({{}}) page has more information on EnvironmentConfigs options and usage. -### Composition functions +### Use composition functions -Composition functions (`XFNs`) are containers executing any code you define. -Composition functions can read and write to any resource in the Composition -they're attached to. This allows composition functions to perform complex -operations to patch fields, determine if a resource is ready for use or notify -an external system about the details of resource. +Composition functions (or just functions, for short) are custom programs that +template Crossplane resources. You can write a function to template resources +using a general purpose programming language like Go or Python. Using a general +purpose programming language allows a function to use more advanced logic to +template resources, like loops and conditionals. {{}} -Composition functions are an alpha feature. Alpha features aren't enabled by -default. +Composition functions is a beta feature. Crossplane enables beta functions by +default. The +[Composition Functions]({{}}) +page explains how to disable composition functions. {{< /hint >}} -To attach a composition function to a Composition define a -{{}}function{{}} inside the Composition -{{}}spec{{}}. +To use composition functions set the Composition +{{}}mode{{}} to +{{}}Pipeline{{}}. + +Define a {{}}pipeline{{}} of +{{}}steps{{}}. Each +{{}}step{{}} calls a Function. + +Each {{}}step{{}} uses a +{{}}functionRef{{}} to reference the +{{}}name{{}} of the Function to call. + +Some Functions also allow you to specify an +{{}}input{{}}. +The function defines the +{{}}kind{{}} of input. + +{{}} +Compositions using {{}}mode: Pipeline{{}} +can't specify resource templates with a `resources` field. + +Use function "Patch and Transform" to create resource templates. +{{< /hint >}} -Provide a {{}}name{{}} for the function. -The {{}}type{{}} is always `Container`. -The {{}}container.image{{}} is the -location of the composition function container image. +This example uses Function Patch and Transform. Function Patch and Transform is +a function that implements Crossplane resource templates. You can use Function +Patch and Transform to specify resource templates in a pipeline with other +Functions. ```yaml {label="xfn",copy-lines="none"} apiVersion: apiextensions.crossplane.io/v1 kind: Composition # Removed for Brevity spec: - resources: # Removed for Brevity - functions: - - name: rds-instance-password - type: Container - container: - image: xpkg.upbound.io/provider-aws-xfns/random-rds-password:v0.1.0 + mode: Pipeline + pipeline: + - step: patch-and-transform + functionRef: + name: function-patch-and-transform + input: + apiVersion: pt.fn.crossplane.io/v1beta1 + kind: Resources + resources: + - name: storage-bucket + base: + apiVersion: s3.aws.upbound.io/v1beta1 + kind: Bucket + spec: + forProvider: + region: "us-east-2" ``` Read the [composition functions]({{}}) page for @@ -1293,6 +1325,9 @@ Composition. When creating a Composition Crossplane automatically validates specific parameters in the Composition. +If using `mode: Resources`: + +* The `resources` field isn't empty. * All resources either use a `name` or don't. Compositions can't use both named and unnamed resources. * No duplicate resource names. @@ -1303,10 +1338,11 @@ parameters in the Composition. * Readiness checks using `matchString` aren't empty. * Readiness checks using `matchInteger` isn't `0`. * Readiness checks requiring a `fieldPath` value provide it. -* If using composition functions, all resources must have names. -* Composition function container field isn't empty. -* Composition function `type` is `container`. -* Composition function names are unique. + +If using `mode: Pipeline` (Composition Functions): + +* The `pipeline` field isn't empty. +* No duplicate step names. ### Resource schema validation diff --git a/content/master/concepts/packages.md b/content/master/concepts/packages.md index 3bd1f527d..16007cf39 100644 --- a/content/master/concepts/packages.md +++ b/content/master/concepts/packages.md @@ -1,513 +1,489 @@ --- -title: Crossplane Packages -weight: 104 +title: Configuration Packages description: "Packages combine multiple Crossplane resources into a single, portable, OCI image." +altTitle: "Crossplane Packages" --- - - -Crossplane packages are opinionated [OCI images] that contain a stream of YAML -that can be parsed by the Crossplane package manager. Crossplane packages come -in two varieties: [Providers] and Configurations. Ultimately, the primary -purposes of Crossplane packages are as follows: - -- **Convenient Distribution**: Crossplane packages can be pushed to or installed - from any OCI-compatible registry. -- **Version Upgrade**: Crossplane can update packages in-place, meaning that you - can pick up support for new resource types or controller bug-fixes without - modifying your existing infrastructure. -- **Permissions**: Crossplane allocates permissions to packaged controllers in a - manner that ensures they will not maliciously take over control of existing - resources owned by other packages. Installing CRDs via packages also allows - Crossplane itself to manage those resources, allowing for powerful - [composition] features to be enabled. -- **Dependency Management**: Crossplane resolves dependencies between packages, - automatically installing a package's dependencies if they are not present in - the cluster, and checking if dependency versions are valid if they are already - installed. - -## Table of Contents - -The following packaging operations are covered in detail below: - -- [Table of Contents](#table-of-contents) -- [Building a Package](#building-a-package) - - [Provider Packages](#provider-packages) - - [Configuration Packages](#configuration-packages) -- [Pushing a Package](#pushing-a-package) -- [Installing a Package](#installing-a-package) - - [spec.package](#specpackage) - - [spec.packagePullPolicy](#specpackagepullpolicy) - - [spec.revisionActivationPolicy](#specrevisionactivationpolicy) - - [spec.revisionHistoryLimit](#specrevisionhistorylimit) - - [spec.packagePullSecrets](#specpackagepullsecrets) - - [spec.skipDependencyResolution](#specskipdependencyresolution) - - [spec.ignoreCrossplaneConstraints](#specignorecrossplaneconstraints) - - [spec.controllerConfigRef](#speccontrollerconfigref) -- [Upgrading a Package](#upgrading-a-package) - - [Package Upgrade Issues](#package-upgrade-issues) -- [The Package Cache](#the-package-cache) - - [Pre-Populating the Package Cache](#pre-populating-the-package-cache) - -## Building a Package - -As stated above, Crossplane packages are just opinionated OCI images, meaning -they can be constructed using any tool that outputs files that comply the the -OCI specification. However, constructing packages using the Crossplane CLI is a -more streamlined experience, as it will perform build-time checks on your -packages to ensure that they are compliant with the Crossplane [package format]. - -Providers and Configurations vary in the types of resources they may contain in -their packages. All packages must have a `crossplane.yaml` file in the root -directory with package contents. The `crossplane.yaml` contains the package's -metadata, which governs how Crossplane will install the package. - -### Provider Packages - -A Provider package contains a `crossplane.yaml` with the following format: - -```yaml -apiVersion: meta.pkg.crossplane.io/v1 -kind: Provider + +A _Configuration_ package is an +[OCI container images](https://opencontainers.org/) containing a collection of +[Compositions]({{}}), +[Composite Resource Definitions]({{}}) +and any required [Providers]({{}}) +representing a set of custom APIs and resources. + +Configuration packages make your Crossplane configuration fully portable. + +{{}} +Crossplane [Providers]({{}}) and +[Functions]({{}}) are also Crossplane packages. + +This document describes how to install and manage configuration packages. + +Refer to the +[Provider]({{}}) and +[Composition Functions]({{}}) chapters for +details on their usage of packages. +{{< /hint >}} + +## Install a Configuration + +Install a Configuration with a Crossplane +{{}}Configuration{{}} object by setting +the {{}}spec.package{{}} value to the +location of the configuration package. + +For example to install the +[Upbound AWS reference platform](https://marketplace.upbound.io/configurations/upbound/platform-ref-aws/v0.6.0), + +```yaml {label="install"} +apiVersion: pkg.crossplane.io/v1 +kind: Configuration metadata: - name: provider-gcp + name: platform-ref-aws spec: - crossplane: - version: ">=v1.0.0" - controller: - image: crossplane/provider-gcp-controller:v0.14.0 - permissionRequests: - - apiGroups: - - apiextensions.crossplane.io - resources: - - compositions - verbs: - - get - - list - - create - - update - - patch - - watch + package: xpkg.upbound.io/upbound/platform-ref-aws:v0.6.0 ``` -See all available fields in the [official documentation][provider-docs]. +Crossplane installs the Compositions, Composite Resource Definitions and +Providers listed in the Configuration. + +### Install with Helm -> Note: The `meta.pkg.crossplane.io` group does not contain custom resources -> that may be installed into the cluster. They are strictly used as metadata in -> a Crossplane package. +Crossplane supports installing Configurations during an initial Crossplane +installation with the Crossplane Helm chart. -A Provider package may optionally contain one or more CRDs. These CRDs will be -installed prior to the creation of the Provider's `Deployment`. Crossplane will -not install _any_ CRDs for a package unless it can determine that _all_ CRDs can -be installed. This guards against multiple Providers attempting to reconcile the -same CRDs. Crossplane will also create a `ServiceAccount` with permissions to -reconcile these CRDs and it will be assigned to the controller `Deployment`. +Use the +{{}}--set configuration.packages{{}} +argument with `helm install`. -The `spec.controller.image` fields specifies that the `Provider` desires for the -controller `Deployment` to be created with the provided image. It is important -to note that this image is separate from the package image itself. In the case -above, it is an image containing the `provider-gcp` controller binary. +For example, to install the Upbound AWS reference platform, -The `spec.controller.permissionRequests` field allows a package author to -request additional RBAC for the packaged controller. The controller's -`ServiceAccount` will automatically give the controller permission to reconcile -all types that its package installs, as well as `Secrets`, `ConfigMaps`, and -`Events`. Any additional permissions must be explicitly requested. +```shell {label="helm"} +helm install crossplane \ +crossplane-stable/crossplane \ +--namespace crossplane-system \ +--create-namespace \ +--set configuration.packages='{xpkg.upbound.io/upbound/platform-ref-aws:v0.6.0}' +``` -> Note that the Crossplane RBAC manager can be configured to reject permissions -> for certain API groups. If a package requests permissions that Crossplane is -> configured to reject, the package will fail to be installed. -> Authorized permissions should be aggregated to the rbac manager clusterrole -> (the cluster role defined by the provider-clusterrole flag in the rbac manager) -> by using the label `rbac.crossplane.io/aggregate-to-allowed-provider-permissions: "true"` +### Install offline -The `spec.crossplane.version` field specifies the version constraints for core -Crossplane that the `Provider` is compatible with. It is advisable to use this -field if a package relies on specific features in a minimum version of -Crossplane. +Crossplane installs packages from a local package cache. By +default the Crossplane package cache is an +[emptyDir volume](https://kubernetes.io/docs/concepts/storage/volumes/#emptydir). -> All version constraints used in packages follow the [specification] outlined -> in the `Masterminds/semver` repository. +Configure Crossplane to use a +[PersistentVolumeClaim](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) +to use a storage location containing the Configuration image. Read more about +configuring the Crossplane Pod settings in the +[Crossplane install documentation]({{}}). -For an example Provider package, see [provider-gcp]. +Provide the name of the Configuration's `.xpkg` file and set +{{}}packagePullPolicy: Never{{}}. -To build a Provider package, navigate to the package root directory and execute -the following command: +For example, to install a locally downloaded version of +Upbound AWS reference platform set the +{{}}package{{}} to the local filename +and set the Configuration's +{{}}packagePullPolicy: Never{{}}. +```yaml {label="offline"} +apiVersion: pkg.crossplane.io/v1 +kind: Configuration +metadata: + name: offline-platform-ref-aws +spec: + package: platform-ref-aws + packagePullPolicy: Never ``` -crossplane build provider + +### Installation options + +Configurations support multiple options to change configuration package related +settings. + + +#### Configuration revisions + +When installing a newer version of an existing Configuration Crossplane creates +a new configuration revision. + +View the configuration revisions with +{{}}kubectl get configurationrevisions{{}}. + +```shell {label="rev",copy-lines="1"} +kubectl get configurationrevisions +NAME HEALTHY REVISION IMAGE STATE DEP-FOUND DEP-INSTALLED AGE +platform-ref-aws-1735d56cd88d True 2 xpkg.upbound.io/upbound/platform-ref-aws:v0.5.0 Active 2 2 46s +platform-ref-aws-3ac761211893 True 1 xpkg.upbound.io/upbound/platform-ref-aws:v0.4.1 Inactive 5m13s ``` -If the Provider package is valid, you will see a file with the `.xpkg` -extension. +Only a single revision is active at a time. The active revision determines the +available resources, including Compositions and Composite Resource Definitions. + +By default Crossplane keeps only a single _Inactive_ revision. -> Note that the Crossplane CLI will not follow symbolic links for files in the -> root package directory. +Change the number of revisions Crossplane maintains with a Configuration package +{{}}revisionHistoryLimit{{}}. -### Configuration Packages +The {{}}revisionHistoryLimit{{}} +field is an integer. +The default value is `1`. +Disable storing revisions by setting +{{}}revisionHistoryLimit{{}} to `0`. -A Configuration package contains a `crossplane.yaml` with the following format: +For example, to change the default setting and store 10 revisions use +{{}}revisionHistoryLimit: 10{{}}. -```yaml -apiVersion: meta.pkg.crossplane.io/v1 +```yaml {label="revHistory"} +apiVersion: pkg.crossplane.io/v1 kind: Configuration metadata: - name: my-org-infra + name: platform-ref-aws spec: - crossplane: - version: ">=v1.0.0" - dependsOn: - - provider: xpkg.upbound.io/crossplane-contrib/provider-gcp - version: ">=v0.14.0" + revisionHistoryLimit: 10 +# Removed for brevity ``` -See all available fields in the [official documentation][configuration-docs]. - -A Configuration package may also specify one or more of -`CompositeResourceDefinition` and `Composition` types. These resources will be -installed and will be solely owned by the Configuration package. No other -package will be able to modify them. +#### Configuration package pull policy -The `spec.crossplane.version` field serves the same purpose that it does in a -`Provider` package. +Use a {{}}packagePullPolicy{{}} to +define when Crossplane should download the Configuration package to the local +Crossplane package cache. -The `spec.dependsOn` field specifies packages that this package depends on. When -installed, the package manager will ensure that all dependencies are present and -have a valid version given the constraint. If a dependency is not installed, the -package manager will install it at the latest version that fits within the -provided constraints. +The `packagePullPolicy` options are: +* `IfNotPresent` - (**default**) Only download the package if it isn't in the cache. +* `Always` - Check for new packages every minute and download any matching + package that isn't in the cache. +* `Never` - Never download the package. Packages are only installed from the + local package cache. -> Dependency resolution is a `beta` feature and depends on the `v1beta1` -> [`Lock` API][lock-api]. +{{}} +The Crossplane +{{}}packagePullPolicy{{}} works +like the Kubernetes container image +[image pull policy](https://kubernetes.io/docs/concepts/containers/images/#image-pull-policy). -For an example Configuration package, see [getting-started-with-gcp](https://github.com/crossplane/docs/tree/master/content/media/snippets/package/gcp). +Crossplane supports the use of tags and package digest hashes like +Kubernetes images. +{{< /hint >}} -To build a Configuration package, navigate to the package root directory and -execute the following command: +For example, to `Always` download a given Configuration package use the +{{}}packagePullPolicy: Always{{}} +configuration. -``` -crossplane build configuration +```yaml {label="pullpolicy",copy-lines="6"} +apiVersion: pkg.crossplane.io/v1 +kind: Configuration +metadata: + name: platform-ref-aws +spec: + packagePullPolicy: Always +# Removed for brevity ``` -If the Provider package is valid, you will see a file with the `.xpkg` -extension. +#### Upgrade policy -## Pushing a Package +Crossplane automatically upgrades a Configuration the to the latest version +available in the package cache. -Crossplane packages can be pushed to any OCI-compatible registry. If a specific -registry is not specified they will be pushed to Docker Hub. +Control the Configuration upgrade behavior with a +{{}}revisionActivationPolicy{{}}. -To push a Provider package, execute the following command: +The {{}}revisionActivationPolicy{{}} +options are: +* `Automatic` - (**default**) Automatically use the latest Configuration version + available in the cache. +* `Manual` - Require the current Configuration in use to be manually set. -``` -crossplane push provider xpkg.upbound.io/crossplane-contrib/provider-gcp:v0.22.0 +For example, to change the upgrade behavior to require manual upgrades, set +{{}}revisionActivationPolicy: Manual{{}}. + +```yaml {label="revision"} +apiVersion: pkg.crossplane.io/v1 +kind: Configuration +metadata: + name: platform-ref-aws +spec: + revisionActivationPolicy: Manual +# Removed for brevity ``` -To push a Configuration package, execute the following command: +{{}} +Crossplane only upgrades a Configuration if a newer version is in the package +cache. +By default the Crossplane +[`packagePullPolicy`](#configuration-package-pull-policy) doesn't +download new Configuration versions, even if they're available. +{{< /hint >}} -``` -crossplane push configuration xpkg.upbound.io/crossplane-contrib/my-org-infra:v0.1.0 -``` +Read the [Configuration package revision](#configuration-revisions) +section for more information on the use of package revisions. -> Note: Both of the above commands assume a single `.xpkg` file exists in the -> directory. If multiple exist or you would like to specify a package in a -> different directory, you can supply the `-f` flag with the path to the -> package. +#### Install a Configuration from a private registry -## Installing a Package +Like Kubernetes uses `imagePullSecrets` to +[install images from private registries](https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/), +Crossplane uses `packagePullSecrets` to install Configuration packages from a +private registry. -Packages can be installed into a Crossplane cluster using the Crossplane CLI. +Use {{}}packagePullSecrets{{}} to provide a +Kubernetes secret to use for authentication when downloading a Configuration +package. -To install a Provider package, execute the following command: +{{}} +The Kubernetes secret must be in the same namespace as Crossplane. +{{}} -``` -crossplane install provider xpkg.upbound.io/crossplane-contrib/provider-gcp:v0.22.0 -``` +The {{}}packagePullSecrets{{}} is a list of +secrets. -To install a Configuration package, execute the following command: +For example, to use the secret named +{{}}example-secret{{}} configure a +{{}}packagePullSecrets{{}}. +```yaml {label="pps"} +apiVersion: pkg.crossplane.io/v1 +kind: Configuration +metadata: + name: platform-ref-aws +spec: + packagePullSecrets: + - name: example-secret +# Removed for brevity ``` -crossplane install configuration xpkg.upbound.io/crossplane-contrib/my-org-infra:v0.1.0 -``` -Packages can also be installed manually by creating a `Provider` or -`Configuration` object directly. The preceding commands would result in the -creation of the following two resources, which could have been authored by hand: +#### Ignore dependencies + +By default Crossplane installs any [dependencies](#manage-dependencies) listed +in a Configuration package. + +Crossplane can ignore a Configuration package's dependencies with +{{}}skipDependencyResolution{{}}. -```yaml +{{< hint "warning" >}} +Most Configurations include dependencies for the required Providers. + +If a Configuration ignores dependencies, the required Providers must be +manually installed. +{{< /hint >}} + +For example, to disable dependency resolution configure +{{}}skipDependencyResolution: true{{}}. + +```yaml {label="pkgDep"} apiVersion: pkg.crossplane.io/v1 -kind: Provider +kind: Configuration metadata: - name: provider-gcp + name: platform-ref-aws spec: - package: xpkg.upbound.io/crossplane-contrib/provider-gcp:v0.22.0 - packagePullPolicy: IfNotPresent - revisionActivationPolicy: Automatic - revisionHistoryLimit: 1 + skipDependencyResolution: true +# Removed for brevity ``` -```yaml +#### Ignore Crossplane version requirements + +A Configuration package may require a specific or minimum Crossplane version +before installing. By default, Crossplane doesn't install a Configuration if +the Crossplane version doesn't meet the required version. + +Crossplane can ignore the required version with +{{}}ignoreCrossplaneConstraints{{}}. + +For example, to install a Configuration package into an unsupported Crossplane +version, configure +{{}}ignoreCrossplaneConstraints: true{{}}. + +```yaml {label="xpVer"} apiVersion: pkg.crossplane.io/v1 kind: Configuration metadata: - name: my-org-infra + name: platform-ref-aws spec: - package: xpkg.upbound.io/crossplane-contrib/my-org-infra:v0.1.0 - packagePullPolicy: IfNotPresent - revisionActivationPolicy: Automatic - revisionHistoryLimit: 1 + ignoreCrossplaneConstraints: true +# Removed for brevity ``` -> Note: These types differ from the `Provider` and `Configuration` types we saw -> earlier. They exist in the `pkg.crossplane.io` group rather than the -> `meta.pkg.crossplane.io` group and are actual custom resources created in the -> cluster. - -The default fields specified above can be configured with different values to -modify the installation and upgrade behavior of a package. In addition, there -are multiple other fields which can further customize how the package manager -handles a specific revision. - -### spec.package - -This is the package image that we built, pushed, and are asking Crossplane to -install. The tag we specify here is important. Crossplane will periodically -check if the installed image matches the digest of the image in the remote -registry. If it does not, Crossplane will create a new _Revision_ (either -`ProviderRevision` or `ConfigurationRevision`). If you do not wish Crossplane to -ever update your packages without explicitly instructing it to do so, you should -consider specifying a tag which you know will not have the underlying contents -change unexpectedly (e.g. a specific semantic version, such as `v0.1.0`) or, for -an even stronger guarantee, providing the image with a `@sha256` extension -instead of a tag. - -### spec.packagePullPolicy - -Valid values: `IfNotPresent`, `Always`, or `Never` (default: `IfNotPresent`) - -When a package is installed, Crossplane downloads the image contents into a -cache. Depending on the image identifier (tag or digest) and the -`packagePullPolicy`, the Crossplane package manager will decide if and when to -check and see if newer package contents are available. The following table -describes expected behavior based on the supplied fields: - -| | `IfNotPresent` | `Always` | `Never` | -|---------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------| -| Semver Tag (e.g. `v1.3.0`) | Package is downloaded when initially installed, and as long as it is present in the cache, it will not be downloaded again. If the cache is lost and the a new version of the package image has been pushed for the same tag, package could inadvertently be upgraded.

**Upgrade Safety: Strong** | Package is downloaded when initially installed, but Crossplane will check every minute if new content is available. New content would have to be pushed for the same semver tag for upgrade to take place.

**Upgrade Safety: Weak** | Crossplane will never download content. Must manually load package image in cache.

**Upgrade Safety: Strongest** | -| Digest (e.g. `@sha256:28b6...`) | Package is downloaded when initially installed, and as long as it is present in the cache, it will not be downloaded again. If the cache is lost but an image with this digest is still available, it will be downloaded again. The package will never be upgraded without a user changing the digest.

**Upgrade Safety: Very Strong** | Package is downloaded when initially installed, but Crossplane will check every minute if new content is available. Because image digest is used, new content will never be downloaded.

**Upgrade Safety: Strong** | Crossplane will never download content. Must manually load package image in cache.

**Upgrade Safety: Strongest** | -| Channel Tag (e.g. `latest`) | Package is downloaded when initially installed, and as long as it is present in the cache, it will not be downloaded again. If the cache is lost, the latest version of this package image will be downloaded again, which will frequently have different contents.

**Upgrade Safety: Weak** | Package is downloaded when initially installed, but Crossplane will check every minute if new content is available. When the image content is new, Crossplane will download the new contents and create a new revision.

**Upgrade Safety: Very Weak** | Crossplane will never download content. Must manually load package image in cache.

**Upgrade Safety: Strongest** | - -### spec.revisionActivationPolicy - -Valid values: `Automatic` or `Manual` (default: `Automatic`) - -When Crossplane downloads new contents for a package, regardless of whether it -was a manual upgrade (i.e. user updating package image tag), or an automatic one -(enabled by the `packagePullPolicy`), it will create a new package revision. -However, the new objects and / or controllers will not be installed until the -new revision is marked as `Active`. This activation process is configured by the -`revisionActivationPolicy` field. - -An `Active` package revision attempts to become the _controller_ of all -resources it installs. There can only be one controller of a resource, so if two -`Active` revisions both install the same resource, one will fail to install -until the other cedes control. - -An `Inactive` package revision attempts to become the _owner_ of all resources -it installs. There can be an arbitrary number of owners of a resource, so -multiple `Inactive` revisions and a single `Active` revision can exist for a -resource. Importantly, an `Inactive` package revision will not perform any -auxiliary actions (such as creating a `Deployment` in the case of a `Provider`), -meaning we will not encounter a situation where two revisions are fighting over -reconciling a resource. - -With `revisionActivationPolicy: Automatic`, Crossplane will mark any new -revision as `Active` when it is created, as well as transition any old revisions -to `Inactive`. When `revisionActivationPolicy: Manual`, the user must manually -edit a new revision and mark it as `Active`. This can be useful if you are using -a `packagePullPolicy: Automatic` with a channel tag (e.g. `latest`) and you want -Crossplane to create new revisions when a new version is available, but you -don't want to automatically update to that newer revision. - -It is recommended for most users to use semver tags or image digests and -manually update their packages, but use a `revisionActivationPolicy: Automatic` -to avoid having to manually activate new versions. However, each user should -consider their specific environment and choose a combination that makes sense -for them. - -For security reasons, it's suggested using image digests instead or alongside -tags (`vx.y.z@sha256:...`), to ensure that the package content wasn't tampered -with. - -### spec.revisionHistoryLimit - -Valid values: any integer, disabled by explicitly setting to `0` (default `1`) - -When a revision transitions from `Inactive` to `Active`, its revision number -gets set to one greater than the largest revision number of all revisions for -its package. Therefore, as the number of revisions increases, the least recently -`Active` revision will have the lowest revision number. Crossplane will garbage -collect old `Inactive` revisions if they fall outside the -`spec.revisionHistoryLimit`. For instance, if my revision history limit is `3` -and I currently have three old `Inactive` revisions and one `Active` revision, -when I upgrade the next time, the new revision will be given the highest -revision number when it becomes `Active`, the previously `Active` revision will -become `Inactive`, and the oldest `Inactive` revision will be garbage collected. - -> Note: In the case that `spec.revisionActivationPolicy: Manual` and you upgrade -> enough times (but do not make `Active` the new revisions), it is possible that -> activating a newer revision could cause the previously `Active` revision to -> immediately be garbage collected if it is outside the -> `spec.revisionHistoryLimit`. - -### spec.packagePullSecrets - -Valid values: slice of `Secret` names (secrets must exist in `namespace` -Crossplane was installed in, typically `crossplane-system`) - -This field allows a user to provide credentials required to pull a package from -a private repository on a registry. The credentials are passed along to a -packaged controller if the package is a `Provider`, but are not passed along to -any dependencies. - -### spec.skipDependencyResolution - -Valid values: `true` or `false` (default: `false`) - -If `skipDependencyResolution: true`, the package manager will install a package -without considering its dependencies. -### spec.ignoreCrossplaneConstraints +### Verify a Configuration -Valid values: `true` or `false` (default: `false`) +Verify a Configuration with +{{}}kubectl get configuration{{}}. -If `ignoreCrossplaneConstraints: true`, the package manager will install a -package without considering the version of Crossplane that is installed. +```shell {label="verify",copy-lines="1"} +kubectl get configuration +NAME INSTALLED HEALTHY PACKAGE AGE +platform-ref-aws True True xpkg.upbound.io/upbound/platform-ref-aws:v0.6.0 54s +``` -### spec.controllerConfigRef +### Manage dependencies -{{< hint "warning" >}} -The `ControllerConfig` API has been deprecated and will be removed in a future -release when a comparable alternative is available. +Configuration packages may include dependencies on other packages including +Providers or other Configurations. + +If Crossplane can't meet the dependencies of a Configuration the Configuration +reports `HEALTHY` as `False`. + +For example, this installation of the Upbound AWS reference platform is +`HEALTHY: False`. + +```shell {copy-lines="1"} +kubectl get configuration +NAME INSTALLED HEALTHY PACKAGE AGE +platform-ref-aws True False xpkg.upbound.io/upbound/platform-ref-aws:v0.6.0 71s +``` + +To see more information on why the Configuration isn't `HEALTHY` use +{{}}kubectl describe configurationrevisions{{}}. + +```yaml {copy-lines="1",label="depend"} +kubectl describe configurationrevision +Name: platform-ref-aws-a30ad655c769 +API Version: pkg.crossplane.io/v1 +Kind: ConfigurationRevision +# Removed for brevity +Spec: + Desired State: Active + Image: xpkg.upbound.io/upbound/platform-ref-aws:v0.6.0 + Revision: 1 +Status: + Conditions: + Last Transition Time: 2023-10-06T20:08:14Z + Reason: UnhealthyPackageRevision + Status: False + Type: Healthy + Controller Ref: + Name: +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Warning LintPackage 29s (x2 over 29s) packages/configurationrevision.pkg.crossplane.io incompatible Crossplane version: package is not compatible with Crossplane version (v1.12.0) +``` + +The {{}}Events{{}} show a +{{}}Warning{{}} with a message that the +current version of Crossplane doesn't meet the Configuration package +requirements. + +## Create a Configuration + +Crossplane Configuration packages are +[OCI container images](https://opencontainers.org/) containing one or more YAML +files. + +{{}} +Configuration packages are fully OCI compliant. Any tool that builds OCI images +can build Configuration packages. + +It's strongly recommended to use the Crossplane command-line tool to +provide error checking and formatting to Crossplane package builds. + +Read the +[Crossplane package specification](https://github.com/crossplane/crossplane/blob/master/contributing/specifications/xpkg.md) +for package requirements when building packages with third-party tools. +{{}} + +A Configuration package requires a `crossplane.yaml` file and may include +Composition and CompositeResourceDefinition files. + +### The crossplane.yaml file + +To build a Configuration package using the Crossplane CLI, create a file +named +{{}}crossplane.yaml{{}}. +The +{{}}crossplane.yaml{{}} +file defines the requirements and name of the +Configuration. + +{{}} +The Crossplane CLI only supports a file named `crossplane.yaml`. {{< /hint >}} -Valid values: name of a `ControllerConfig` object +Configuration package uses the +{{}}meta.pkg.crossplane.io{{}} +Crossplane API group. -Packaged `Provider` controllers are installed in the form of a `Deployment`. -Crossplane populates the `Deployment` with default values that may not be -appropriate for every use-case. In the event that a user wants to override some -of the defaults that Crossplane has set, they may create and reference a -`ControllerConfig`. +Specify any other Configurations, Functions or Providers in the +{{}}dependsOn{{}} list. +Optionally, you can require a specific or minimum package version with the +{{}}version{{}} option. -An example of when this may be useful is when a user is running Crossplane on -EKS and wants to take advantage of [IAM Roles for Service Accounts]. This -requires setting an `fsGroup` and annotating the `ServiceAccount` that -Crossplane creates for the controller. This could be accomplished with the -following `ControllerConfig` and `Provider`: +You can also define a specific or minimum version of Crossplane for this +Configuration with the +{{}}crossplane.version{{}} option. -```yaml -apiVersion: pkg.crossplane.io/v1alpha1 -kind: ControllerConfig -metadata: - name: aws-config - annotations: - eks.amazonaws.com/role-arn: arn:aws:iam::$AWS_ACCOUNT_ID\:role/$IAM_ROLE_NAME -spec: - podSecurityContext: - fsGroup: 2000 ---- -apiVersion: pkg.crossplane.io/v1 -kind: Provider +{{}} +Defining the {{}}crossplane{{}} object +or required versions is optional. +{{< /hint >}} + +```yaml {label="cfgMeta",copy-lines="all"} +$ cat crossplane.yaml +apiVersion: meta.pkg.crossplane.io/v1alpha1 +kind: Configuration metadata: - name: provider-aws + name: test-configuration spec: - package: xpkg.upbound.io/crossplane-contrib/provider-aws:v0.33.0 - controllerConfigRef: - name: aws-config + dependsOn: + - provider: xpkg.upbound.io/crossplane-contrib/provider-aws + version: ">=v0.36.0" + crossplane: + version: ">=v1.12.1-0" ``` -You can find all configurable values in the [official `ControllerConfig` -documentation][controller-config-docs]. - -## Upgrading a Package - -Upgrading a `Provider` or `Configuration` to a new version can be accomplished -by editing the existing manifest and applying it with a new version tag in -`spec.package`. Crossplane will observe the updated manifest and create a new -`ProviderRevision` or `ConfigurationRevision` for the specified version. The new -revision will be activated in accordance with `spec.revisionActivationPolicy`. - -### Package Upgrade Issues - -Upgrading a package can require manual intervention in the event that the -previous version of the package supported a version of a custom resource that -has been dropped and replaced by a new version in the new package revision. -Kubernetes does not allow for applying a `CustomResourceDefinition` (CRD) that -drops a version in the `spec` that is in the current `status.storedVersions` -list, meaning that a revision cannot update and become the _controller_ of all -of its resources. - -This situation can be remedied by manually deleting the offending CRD and -letting the new revision re-create it. In the event that custom resources exist -for the given CRD, they must be deleted before the CRD can be removed. - -## The Package Cache - -When a package is installed into a cluster, Crossplane fetches the package image -and stores its contents in a dedicated package cache. By default, this cache is -backed by an [`emptyDir` Volume][emptyDir-volume], meaning that all cached data -is lost when a `Pod` restarts. Users who wish for cache contents to be persisted -between `Pod` restarts may opt to instead use a [`persistentVolumeClaim` -(PVC)][pvc] by setting the `packageCache.pvc` Helm chart parameter to the name -of the PVC. - -### Pre-Populating the Package Cache - -Because the package cache can be backed by any storage medium, users are able to -optionally to pre-populate the cache with images that are not present on an -external [OCI registry]. To utilize a package that has been manually stored in -the cache, users must specify the name of the package in `spec.package` and use -`packagePullPolicy: Never`. For instance, if a user built a `Configuration` -package named `mycoolpkg.xpkg` and loaded it into the volume that was to be used -for the package cache (i.e. copied the `.xpkg` file into the storage medium -backing the PVC), the package could be utilized with the following manifest: - -```yaml -apiVersion: pkg.crossplane.io/v1 +### Build the package + +Create the package using the Crossplane CLI command +`crossplane build configuration -f `. + +Where the `` is the directory containing the `crossplane.yaml` file +and any Composition or CompositeResourceDefinition YAML files. + +The CLI recursively searches for `.yml` or `.yaml` files in the directory to +include in the package. + +{{}} +You must ignore any other YAML files with `--ignore=`. +For +example, `crossplane build configuration -f test-directory --ignore=".tmp/*,other-file.yaml"`. + +Including YAML files that aren't Compositions or CompositeResourceDefinitions, +including Claims isn't supported. +{{}} + +By default, Crossplane creates an `.xpkg` file of the Configuration name and +a SHA-256 hash of the package contents. + +For example, a {{}}Configuration{{}} +named {{}}test-configuration{{}}. +The +Crossplane CLI builds a package named `test-configuration-e8c244f6bf21.xpkg`. + +```yaml {label="xpkgName"} +apiVersion: meta.pkg.crossplane.io/v1alpha1 kind: Configuration metadata: - name: my-cool-pkg -spec: - package: mycoolpkg - packagePullPolicy: Never + name: test-configuration +# Removed for brevity +``` + +Specify the output file with `--name=` option. + +For example, to build a package from a directory named `test-directory` and +generate a package named `test-package.xpkg` use the command: + +```shell +crossplane build configuration -f test-directory --name=test-package +``` + +Crossplane automatically adds the `.xpkg` extension. + +Crossplane places the package in the provided directory, in this example, +`test-directory`. + +```shell +ls test-directory +composition.yml crossplane.yaml compositeresourcedefinition.yml test-package.xpkg ``` -Importantly, as long as a package is being used as the `spec.package` of a -`Configuration` or `Provider`, it must remain in the cache. For this reason, it -is recommended that users opt for a durable storage medium when manually loading -packages into the cache. - -In addition, if manually loading a `Provider` package into the cache, users must -ensure that the controller image that it references is able to be pulled by the -cluster nodes. This can be accomplished either by pushing it to a registry, or -by [pre-pulling images] onto nodes in the cluster. - - - - -[OCI images]: https://github.com/opencontainers/image-spec -[Providers]: {{}} -[provider-docs]: https://doc.crds.dev/github.com/crossplane/crossplane/meta.pkg.crossplane.io/Provider/v1 -[configuration-docs]: https://doc.crds.dev/github.com/crossplane/crossplane/meta.pkg.crossplane.io/Configuration/v1 -[lock-api]: https://doc.crds.dev/github.com/crossplane/crossplane/pkg.crossplane.io/Lock/v1beta1 -[specification]: https://github.com/Masterminds/semver#basic-comparisons -[composition]: {{}} -[IAM Roles for Service Accounts]: https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html -[controller-config-docs]: https://doc.crds.dev/github.com/crossplane/crossplane/pkg.crossplane.io/ControllerConfig/v1alpha1 -[package format]: https://github.com/crossplane/crossplane/blob/1aa83092172bdf0d2ed64754d33517c612ff7368/design/one-pager-package-format-v2.md -[provider-gcp]: https://doc.crds.dev/github.com/crossplane/crossplane/meta.pkg.crossplane.io/Provider/v1 -[emptyDir-volume]: https://kubernetes.io/docs/concepts/storage/volumes/#emptydir -[pvc]: https://kubernetes.io/docs/concepts/storage/volumes/#persistentvolumeclaim -[OCI registry]: https://github.com/opencontainers/distribution-spec -[pre-pulling images]: https://kubernetes.io/docs/concepts/containers/images/#pre-pulled-images diff --git a/content/master/concepts/providers.md b/content/master/concepts/providers.md index 446ed6ac6..ab273d973 100644 --- a/content/master/concepts/providers.md +++ b/content/master/concepts/providers.md @@ -28,15 +28,11 @@ Find more providers in the [Upbound Marketplace](https://marketplace.upbound.io) Providers define every external resource they can create in Kubernetes as a -Kubernetes API endpoint. These endpoints are +Kubernetes API endpoint. +These endpoints are [_Managed Resources_]({{}}). -{{< hint "note" >}} -Instructions on building your own Provider are outside of the scope of this -document. Read the Crossplane contributing [Provider Development Guide](https://github.com/crossplane/crossplane/blob/master/contributing/guide-provider-development.md) -for more information. -{{< /hint >}} ## Install a Provider @@ -63,14 +59,35 @@ spec: package: xpkg.upbound.io/crossplane-contrib/provider-aws:v0.39.0 ``` -{{< hint "tip" >}} -Providers are Crossplane Packages. Read more about Packages in the -[Packages documentation]({{}}). -{{< /hint >}} - By default, the Provider pod installs in the same namespace as Crossplane (`crossplane-system`). +{{}} +Providers are part of the +{{}}pkg.crossplane.io{{}} group. + +The {{}}meta.pkg.crossplane.io{{}} +group is for creating Provider packages. + +Instructions on building Providers are outside of the scope of this +document. +Read the Crossplane contributing +[Provider Development Guide](https://github.com/crossplane/crossplane/blob/master/contributing/guide-provider-development.md) +for more information. + +For information on the specification of Provider packages read the +[Crossplane Provider Package specification](https://github.com/crossplane/crossplane/blob/master/contributing/specifications/xpkg.md#provider-package-requirements). + +```yaml {label="meta-pkg"} +apiVersion: meta.pkg.crossplane.io/v1 +kind: Provider +metadata: + name: provider-aws +spec: +# Removed for brevity +``` +{{}} + ### Install with Helm Crossplane supports installing Providers during an initial Crossplane @@ -90,28 +107,277 @@ crossplane-stable/crossplane \ --set provider.packages='{xpkg.upbound.io/crossplane-contrib/provider-aws:v0.39.0}' ``` -### Install from a private repository +### Install offline + +Crossplane installs packages from a local package cache. By +default the Crossplane package cache is an +[emptyDir volume](https://kubernetes.io/docs/concepts/storage/volumes/#emptydir). + +Configure Crossplane to use a +[PersistentVolumeClaim](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) +to use a storage location containing the Provider image. Read more about +configuring the Crossplane Pod settings in the +[Crossplane install documentation]({{}}). + +Provide the name of the Provider's `.xpkg` file and set +{{}}packagePullPolicy: Never{{}}. + +For example, to install a locally downloaded version of Provider AWS set the +{{}}package{{}} to the local filename +and set the Provider's +{{}}packagePullPolicy: Never{{}}. + +```yaml {label="offline"} +apiVersion: pkg.crossplane.io/v1 +kind: Provider +metadata: + name: offline-provider-aws +spec: + package: provider-aws + packagePullPolicy: Never +``` + +### Installation options + +Providers support multiple configuration options to change installation related +settings. + +#### Provider pull policy + +Use a {{}}packagePullPolicy{{}} to +define when Crossplane should download the Provider package to the local +Crossplane package cache. + +The `packagePullPolicy` options are: +* `IfNotPresent` - (**default**) Only download the package if it isn't in the cache. +* `Always` - Check for new packages every minute and download any matching + package that isn't in the cache. +* `Never` - Never download the package. Packages are only installed from the + local package cache. + +{{}} +The Crossplane +{{}}packagePullPolicy{{}} works +like the Kubernetes container image +[image pull policy](https://kubernetes.io/docs/concepts/containers/images/#image-pull-policy). + +Crossplane supports the use of tags and package digest hashes like +Kubernetes images. +{{< /hint >}} + +For example, to `Always` download a given Provider package use the +{{}}packagePullPolicy: Always{{}} +configuration. + +```yaml {label="pullpolicy",copy-lines="6"} +apiVersion: pkg.crossplane.io/v1 +kind: Provider +metadata: + name: provider-aws +spec: + packagePullPolicy: Always +# Removed for brevity +``` + +#### Upgrade policy + +Crossplane automatically upgrades a Provider the to the latest version available +in the package cache. + +Control the Provider upgrade behavior with a +{{}}revisionActivationPolicy{{}}. + +The {{}}revisionActivationPolicy{{}} +options are: +* `Automatic` - (**default**) Automatically use the latest Provider version + available in the cache. +* `Manual` - Require the current Provider in use to be manually set. + +For example, to change the upgrade behavior to require manual upgrades, set +{{}}revisionActivationPolicy: Manual{{}}. + +```yaml {label="revision"} +apiVersion: pkg.crossplane.io/v1 +kind: Provider +metadata: + name: provider-aws +spec: + revisionActivationPolicy: Manual +# Removed for brevity +``` + +{{}} +Crossplane only upgrades a Provider if a newer version is in the package cache. +By default the Crossplane [`packagePullPolicy`](#provider-pull-policy) doesn't +download new Provider versions, even if they're available. +{{< /hint >}} + +Read the [Provider upgrade](#upgrade-a-provider) section for +more information on the use of package revisions. + +#### Package revision history limit + +When Crossplane installs a different version of the same Provider package +Crossplane creates a new _revision_. + +By default Crossplane maintains one _Inactive_ revision. + +{{}} +Read the [Provider upgrade](#upgrade-a-provider) section for +more information on the use of package revisions. +{{< /hint >}} + +Change the number of revisions Crossplane maintains with a Provider Package +{{}}revisionHistoryLimit{{}}. -Installing a Provider from a private package repository requires a -Kubernetes secret object. The Provider uses the secret with the -{{}}packagePullSecrets{{}} option. +The {{}}revisionHistoryLimit{{}} +field is an integer. +The default value is `1`. +Disable storing revisions by setting +{{}}revisionHistoryLimit{{}} to `0`. + +For example, to change the default setting and store 10 revisions use +{{}}revisionHistoryLimit: 10{{}}. + +```yaml {label="revHistoryLimit"} +apiVersion: pkg.crossplane.io/v1 +kind: Provider +metadata: + name: provider-aws +spec: + revisionHistoryLimit: 10 +# Removed for brevity +``` + +#### Install a provider from a private registry + +Like Kubernetes uses `imagePullSecrets` to +[install images from private registries](https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/), +Crossplane uses `packagePullSecrets` to install Provider packages from a private +registry. + +Use {{}}packagePullSecrets{{}} to provide a +Kubernetes secret to use for authentication when downloading a Provider package. + +{{}} +The Kubernetes secret must be in the same namespace as Crossplane. +{{}} + +The {{}}packagePullSecrets{{}} is a list of +secrets. + +For example, to use the secret named +{{}}example-secret{{}} configure a +{{}}packagePullSecrets{{}}. ```yaml {label="pps"} apiVersion: pkg.crossplane.io/v1 kind: Provider metadata: - name: private-provider + name: provider-aws spec: - package: private-repo.example.org/providers/my-provider - packagePullSecrets: - - name: my-secret + packagePullSecrets: + - name: example-secret +# Removed for brevity ``` -{{< hint "note" >}} -The Kubernetes secret object the Provider uses must be in the same namespace as -the Crossplane pod. +{{}} +Configured `packagePullSecrets` aren't passed to any Provider package +dependencies. {{< /hint >}} +#### Ignore dependencies + +By default Crossplane installs any [dependencies](#manage-dependencies) listed +in a Provider package. + +Crossplane can ignore a Provider package's dependencies with +{{}}skipDependencyResolution{{}}. + +For example, to disable dependency resolution configure +{{}}skipDependencyResolution: true{{}}. + +```yaml {label="pkgDep"} +apiVersion: pkg.crossplane.io/v1 +kind: Provider +metadata: + name: provider-aws +spec: + skipDependencyResolution: true +# Removed for brevity +``` + +#### Ignore Crossplane version requirements + +A Provider package may require a specific or minimum Crossplane version before +installing. By default, Crossplane doesn't install a Provider if the Crossplane +version doesn't meet the required version. + +Crossplane can ignore the required version with +{{}}ignoreCrossplaneConstraints{{}}. + +For example, to install a Provider package into an unsupported Crossplane +version, configure +{{}}ignoreCrossplaneConstraints: true{{}}. + +```yaml {label="xpVer"} +apiVersion: pkg.crossplane.io/v1 +kind: Provider +metadata: + name: provider-aws +spec: + ignoreCrossplaneConstraints: true +# Removed for brevity +``` + +### Manage dependencies + +Providers packages may include dependencies on other packages including +Configurations or other Providers. + +If Crossplane can't meet the dependencies of a Provider package the Provider +reports `HEALTHY` as `False`. + +For example, this installation of the Upbound AWS reference platform is +`HEALTHY: False`. + +```shell {copy-lines="1"} +kubectl get providers +NAME INSTALLED HEALTHY PACKAGE AGE +provider-aws-s3 True False xpkg.upbound.io/upbound/provider-aws-s3:v0.41.0 12s +``` + +To see more information on why the Provider isn't `HEALTHY` use +{{}}kubectl describe providerrevisions{{}}. + +```yaml {copy-lines="1",label="depend"} +kubectl describe providerrevisions +Name: provider-aws-s3-92206523fff4 +API Version: pkg.crossplane.io/v1 +Kind: ProviderRevision +Spec: + Desired State: Active + Image: xpkg.upbound.io/upbound/provider-aws-s3:v0.41.0 + Revision: 1 +Status: + Conditions: + Last Transition Time: 2023-10-10T21:06:39Z + Reason: UnhealthyPackageRevision + Status: False + Type: Healthy + Controller Ref: + Name: +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Warning LintPackage 41s (x3 over 47s) packages/providerrevision.pkg.crossplane.io incompatible Crossplane version: package is not compatible with Crossplane version (v1.10.0) +``` + +The {{}}Events{{}} show a +{{}}Warning{{}} with a message that the +current version of Crossplane doesn't meet the Configuration package +requirements. + ## Upgrade a Provider To upgrade an existing Provider edit the installed Provider Package by either @@ -120,10 +386,34 @@ applying a new Provider manifest or with `kubectl edit providers`. Update the version number in the Provider's `spec.package` and apply the change. Crossplane installs the new image and creates a new `ProviderRevision`. +The `ProviderRevision` allows Crossplane to store deprecated Provider CRDs +without removing them until you decide. + +View the `ProviderRevisions` with +{{}}kubectl get providerrevisions{{}} + +```shell {label="getPR",copy-lines="1"} +kubectl get providerrevisions +NAME HEALTHY REVISION IMAGE STATE DEP-FOUND DEP-INSTALLED AGE +provider-aws-s3-dbc7f981d81f True 1 xpkg.upbound.io/upbound/provider-aws-s3:v0.37.0 Active 1 1 10d +provider-nop-552a394a8acc True 2 xpkg.upbound.io/crossplane-contrib/provider-nop:v0.3.0 Active 11d +provider-nop-7e62d2a1a709 True 1 xpkg.upbound.io/crossplane-contrib/provider-nop:v0.2.0 Inactive 13d +upbound-provider-family-aws-710d8cfe9f53 True 1 xpkg.upbound.io/upbound/provider-family-aws:v0.40.0 Active 10d +``` + +By default Crossplane keeps a single +{{}}Inactive{{}} Provider. + +Read the [revision history limit](#package-revision-history-limit) section to +change the default value. + +Only a single revision of a Provider is +{{}}Active{{}} at a time. + ## Remove a Provider -Remove a Provider by deleting the Provider object with `kubectl delete -provider`. +Remove a Provider by deleting the Provider object with +`kubectl delete provider`. {{< hint "warning" >}} Removing a Provider without first removing the Provider's managed resources @@ -294,7 +584,9 @@ Reason: UnknownPackageRevisionHealth Providers have two different types of configurations: * _Controller configurations_ that change the settings of the Provider pod - running inside the Kubernetes cluster. For example, Pod `toleration`. + running inside the Kubernetes cluster. For example, setting a `toleration` on + the Provider pod. + * _Provider configurations_ that change settings used when communicating with an external provider. For example, cloud provider authentication. @@ -308,14 +600,17 @@ Apply `ProviderConfig` objects to managed resources. {{< hint "important" >}} The Crossplane community deprecated the `ControllerConfig` type in v1.11 to -indicate that no further enhancements will be made to it. +announce that there are no further enhancements. Applying a Controller configuration generates a deprecation warning. - + + + Controller configurations are still supported until there is a replacement type -in a future Crossplane version. You can read more about the design of +in a future Crossplane version. You can read more about the design of the [Package Runtime Config](https://github.com/crossplane/crossplane/blob/master/design/one-pager-package-runtime-config.md) -which will replace it in the future. - +which is a future replacement. + + {{< /hint >}} Applying a Crossplane `ControllerConfig` to a Provider changes the settings of diff --git a/content/master/getting-started/install-crossplane-include.md b/content/master/getting-started/install-crossplane-include.md index 0d88a6cb8..8e38ef1a5 100644 --- a/content/master/getting-started/install-crossplane-include.md +++ b/content/master/getting-started/install-crossplane-include.md @@ -127,37 +127,6 @@ serviceAccount: tolerations: [] webhooks: enabled: true -xfn: - args: [] - cache: - configMap: "" - medium: "" - pvc: "" - sizeLimit: 1Gi - enabled: false - extraEnvVars: {} - image: - pullPolicy: IfNotPresent - repository: crossplane/xfn - tag: "" - resources: - limits: - cpu: 2000m - memory: 2Gi - requests: - cpu: 1000m - memory: 1Gi - securityContext: - allowPrivilegeEscalation: false - capabilities: - add: - - SETUID - - SETGID - readOnlyRootFilesystem: true - runAsGroup: 65532 - runAsUser: 65532 - seccompProfile: - type: Unconfined HOOKS: MANIFEST: diff --git a/content/v1.11/concepts/composition.md b/content/v1.11/concepts/composition.md deleted file mode 100644 index ac2fdffa3..000000000 --- a/content/v1.11/concepts/composition.md +++ /dev/null @@ -1,1277 +0,0 @@ ---- -title: Composite Resources -weight: 103 ---- - -Crossplane Composite Resources are opinionated Kubernetes Custom Resources that -are _composed_ of [Managed Resources][managed-resources]. We often call them XRs -for short. - -![Diagram of claims, XRs, and Managed Resources][xrs-and-mrs] - -Composite Resources are designed to let you build your own platform with your -own opinionated concepts and APIs without needing to write a Kubernetes -controller from scratch. Instead, you define the schema of your XR and teach -Crossplane which Managed Resources it should compose (i.e. create) when someone -creates the XR you defined. - -If you're already familiar with Composite Resources and looking for a detailed -configuration reference or some tips, tricks, and troubleshooting information, -try the [Composition Reference][xr-ref]. - -Below is an example of a Composite Resource: - -```yaml -apiVersion: database.example.org/v1alpha1 -kind: XPostgreSQLInstance -metadata: - name: my-db -spec: - parameters: - storageGB: 20 - compositionRef: - name: production - writeConnectionSecretToRef: - namespace: crossplane-system - name: my-db-connection-details -``` - -You define your own XRs, so they can be of whatever API version and kind you -like, and contain whatever spec and status fields you need. - -## How It Works - -The first step towards using Composite Resources is configuring Crossplane so -that it knows what XRs you'd like to exist, and what to do when someone creates -one of those XRs. This is done using a `CompositeResourceDefinition` (XRD) -resource and one or more `Composition` resources. - -Once you've configured Crossplane with the details of your new XR you can either -create one directly, or use a _claim_. Typically only the folks responsible for -configuring Crossplane (often a platform or SRE team) have permission to create -XRs directly. Everyone else manages XRs via a lightweight proxy resource called -a Composite Resource Claim (or claim for short). More on that later. - -![Diagram combining all Composition concepts][how-it-works] - -> If you're coming from the Terraform world you can think of an XRD as similar -> to the `variable` blocks of a Terraform module, while the `Composition` is -> the rest of the module's HCL code that describes how to use those variables to -> create a bunch of resources. In this analogy the XR or claim is a little like -> a `tfvars` file providing inputs to the module. - -### Defining Composite Resources - -A `CompositeResourceDefinition` (or XRD) defines the type and schema of your XR. -It lets Crossplane know that you want a particular kind of XR to exist, and what -fields that XR should have. An XRD is a little like a `CustomResourceDefinition` -(CRD), but slightly more opinionated. Writing an XRD is mostly a matter of -specifying an OpenAPI ["structural schema"][crd-docs]. - -The XRD that defines the `XPostgreSQLInstance` XR above would look like this: - -```yaml -apiVersion: apiextensions.crossplane.io/v1 -kind: CompositeResourceDefinition -metadata: - name: xpostgresqlinstances.database.example.org -spec: - group: database.example.org - names: - kind: XPostgreSQLInstance - plural: xpostgresqlinstances - claimNames: - kind: PostgreSQLInstance - plural: postgresqlinstances - versions: - - name: v1alpha1 - served: true - referenceable: true - schema: - openAPIV3Schema: - type: object - properties: - spec: - type: object - properties: - parameters: - type: object - properties: - storageGB: - type: integer - required: - - storageGB - required: - - parameters -``` - -You might notice that the `XPostgreSQLInstance` example above has some fields -that don't appear in the XRD, like the `writeConnectionSecretToRef` and -`compositionRef` fields. This is because Crossplane automatically injects some -standard Crossplane Resource Model (XRM) fields into all XRs. - -### Configuring Composition - -A `Composition` lets Crossplane know what to do when someone creates a Composite -Resource. Each `Composition` creates a link between an XR and a set of one or -more Managed Resources - when the XR is created, updated, or deleted the set of -Managed Resources are created, updated or deleted accordingly. - -You can add multiple Compositions for each XRD, and choose which should be used -when XRs are created. This allows a Composition to act like a class of service - -for example you could configure one Composition for each environment you -support, such as production, staging, and development. - -A basic `Composition` for the above `XPostgreSQLInstance` might look like this: - -```yaml -apiVersion: apiextensions.crossplane.io/v1 -kind: Composition -metadata: - name: example - labels: - crossplane.io/xrd: xpostgresqlinstances.database.example.org - provider: gcp -spec: - writeConnectionSecretsToNamespace: crossplane-system - compositeTypeRef: - apiVersion: database.example.org/v1alpha1 - kind: XPostgreSQLInstance - resources: - - name: cloudsqlinstance - base: - apiVersion: database.gcp.crossplane.io/v1beta1 - kind: CloudSQLInstance - spec: - forProvider: - databaseVersion: POSTGRES_12 - region: us-central1 - settings: - tier: db-custom-1-3840 - dataDiskType: PD_SSD - ipConfiguration: - ipv4Enabled: true - authorizedNetworks: - - value: "0.0.0.0/0" - patches: - - type: FromCompositeFieldPath - fromFieldPath: spec.parameters.storageGB - toFieldPath: spec.forProvider.settings.dataDiskSizeGb -``` - -The above `Composition` tells Crossplane that when someone creates an -`XPostgreSQLInstance` XR Crossplane should create a `CloudSQLInstance` in -response. The `storageGB` field of the `XPostgreSQLInstance` should be used to -configure the `dataDiskSizeGb` field of the `CloudSQLInstance`. This is only a -small subset of the functionality a `Composition` enables - take a look at the -[reference page][xr-ref] to learn more. - -> We almost always talk about XRs composing Managed Resources, but actually an -> XR can also compose other XRs to allow nested layers of abstraction. XRs don't -> support composing arbitrary Kubernetes resources (e.g. Deployments, operators, -> etc) directly but you can do so using our [Kubernetes][provider-kubernetes] -> and [Helm][provider-helm] providers. - -### Claiming Composite Resources - -Crossplane uses Composite Resource Claims (or just claims, for short) to allow -application operators to provision and manage XRs. When we talk about using XRs -it's typically implied that the XR is being used via a claim. Claims are almost -identical to their corresponding XRs. It helps to think of a claim as an -application team’s interface to an XR. You could also think of claims as the -public (app team) facing part of the opinionated platform API, while XRs are the -private (platform team) facing part. - -A claim for the `XPostgreSQLInstance` XR above would look like this: - -```yaml -apiVersion: database.example.org/v1alpha1 -kind: PostgreSQLInstance -metadata: - namespace: default - name: my-db -spec: - parameters: - storageGB: 20 - compositionRef: - name: production - writeConnectionSecretToRef: - name: my-db-connection-details -``` - -There are three key differences between an XR and a claim: - -1. Claims are namespaced, while XRs (and Managed Resources) are cluster scoped. -1. Claims are of a different `kind` than the XR - by convention the XR's `kind` - without the proceeding `X`. For example a `PostgreSQLInstance` claims an - `XPostgreSQLInstance`. -1. An active claim contains a reference to its corresponding XR, while an XR - contains both a reference to the claim an array of references to the managed - resources it composes. - -Not all XRs offer a claim - doing so is optional. See the XRD section of the -[Composition reference][xr-ref] to learn how to offer a claim. - -![Diagram showing the relationship between claims and XRs][claims-and-xrs] - -Claims may seem a little superfluous at first, but they enable some handy -scenarios, including: - -- **Private XRs.** Sometimes a platform team might not want a type of XR to be - directly consumed by their application teams. For example because the XR - represents 'supporting' infrastructure - consider the above VPC `XNetwork` XR. App - teams might create `PostgreSQLInstance` claims that _reference_ (i.e. consume) - an `XNetwork`, but they shouldn't be _creating their own_. Similarly, some - kinds of XR might be intended only for 'nested' use - intended only to be - composed by other XRs. - -- **Global XRs**. Not all infrastructure is conceptually namespaced. Say your - organisation uses team scoped namespaces. A `PostgreSQLInstance` that belongs - to Team A should probably be part of the `team-a` namespace - you'd represent - this by creating a `PostgreSQLInstance` claim in that namespace. On the other - hand the `XNetwork` XR we mentioned previously could be referenced (i.e. used) - by XRs from many different namespaces - it doesn't exist to serve a particular - team. - -- **Pre-provisioned XRs**. Finally, separating claims from XRs allows a platform - team to pre-provision certain kinds of XR. Typically an XR is created - on-demand in response to the creation of a claim, but it's also possible for a - claim to instead request an existing XR. This can allow application teams to - instantly claim infrastructure like database instances that would otherwise - take minutes to provision on-demand. - - -This reference provides detailed examples of defining, configuring, and using -Composite Resources in Crossplane. You can also refer to Crossplane's [API -documentation][api-docs] for more details. If you're looking for a more general -overview of Composite Resources and Composition in Crossplane, try the -[Composite Resources][xr-concepts] page under Concepts. - -## Composite Resources and Claims - -The type and most of the schema of Composite Resources and claims are largely of -your own choosing, but there is some common 'machinery' injected into them. -Here's a hypothetical XR that doesn't have any user-defined fields and thus only -includes the automatically injected Crossplane machinery: - -```yaml -apiVersion: database.example.org/v1alpha1 -kind: XPostgreSQLInstance -metadata: - # This XR was created automatically by a claim, so its name is derived from - # the claim's name. - name: my-db-mfd1b - annotations: - # The external name annotation has special meaning in Crossplane. When a - # claim creates an XR its external name will automatically be propagated to - # the XR. Whether and how the external name is propagated to the resources - # the XR composes is up to its Composition. - crossplane.io/external-name: production-db-0 -spec: - # XRs have a reference to the claim that created them (or, if the XR was - # pre-provisioned, to the claim that later claimed them). - claimRef: - apiVersion: database.example.org/v1alpha1 - kind: PostgreSQLInstance - name: my-db - # The compositeDeletePolicy specifies the propagation policy that will be used by Crossplane - # when deleting the Composite Resource that is associated with the Claim. The default - # value is Background, which causes the Composite resource to be deleted using - # the kubernetes default propagation policy of Background, and all associated - # resources will be deleted simultaneously. The other value for this field is Foreground, - # which will cause the Composite resource to be deleted using Foreground Cascading Deletion. - # Kubernetes will add a foregroundDeletion finalizer to all of the resources in the - # dependency graph, and they will be deleted starting with the edge or leaf nodes and - # working back towards the root Composite. See https://kubernetes.io/docs/concepts/architecture/garbage-collection/#cascading-deletion - # for more information on cascading deletion. - compositeDeletePolicy: Background - # The compositionRef specifies which Composition this XR will use to compose - # resources when it is created, updated, or deleted. This can be omitted and - # will be set automatically if the XRD has a default or enforced composition - # reference, or if the below composition selector is set. - compositionRef: - name: production-us-east - # The compositionSelector allows you to match a Composition by labels rather - # than naming one explicitly. It is used to set the compositionRef if none is - # specified explicitly. - compositionSelector: - matchLabels: - environment: production - region: us-east - provider: gcp - # The environment is an in-memory object that can be patched from / to during - # rendering. - # The environment is composed by merging the 'data' of all EnvironmentConfigs - # referenced below. It is disposed after every reconcile. - # NOTE: EnvironmentConfigs are an alpha feature and need to be enabled with - # the '--enable-environment-configs' flag on startup. - environment: - # EnvironmentConfigs is a list of object references that is made up of - # name references and label selectors - environmentConfigs: - - type: Reference # this is the default - ref: - name: example-environment - - type: Selector - selector: - matchLabels: - - key: stage - type: FromCompositeFieldPath # this is the default - valueFromFieldPath: spec.parameters.stage - - key: provider - type: Value - value: "gcp" - # The resourceRefs array contains references to all of the resources of which - # this XR is composed. Despite being in spec this field isn't intended to be - # configured by humans - Crossplane will take care of keeping it updated. - resourceRefs: - - apiVersion: database.gcp.crossplane.io/v1beta1 - kind: CloudSQLInstance - name: my-db-mfd1b-md9ab - # The writeConnectionSecretToRef field specifies a Kubernetes Secret that this - # XR should write its connection details (if any) to. - writeConnectionSecretToRef: - namespace: crossplane-system - name: my-db-connection-details -status: - # An XR's 'Ready' condition will become True when all of the resources it - # composes are deemed ready. Refer to the Composition 'readinessChecks' field - # for more information. - conditions: - - type: Ready - statue: "True" - reason: Available - lastTransitionTime: 2021-10-02T07:20:50.52Z - # The last time the XR published its connection details to a Secret. - connectionDetails: - lastPublishedTime: 2021-10-02T07:20:51.24Z -``` - -Similarly, here's an example of the claim that corresponds to the above XR: - -```yaml -apiVersion: database.example.org/v1alpha1 -kind: PostgreSQLInstance -metadata: - # Claims are namespaced, unlike XRs. - namespace: default - name: my-db - annotations: - # The external name annotation has special meaning in Crossplane. When a - # claim creates an XR its external name will automatically be propagated to - # the XR. Whether and how the external name is propagated to the resources - # the XR composes is up to its Composition. - crossplane.io/external-name: production-db-0 -spec: - # The resourceRef field references the XR this claim corresponds to. You can - # either set it to an existing (compatible) XR that you'd like to claim or - # (the more common approach) leave it blank and let Crossplane automatically - # create and reference an XR for you. - resourceRef: - apiVersion: database.example.org/v1alpha1 - kind: XPostgreSQLInstance - name: my-db-mfd1b - # A claim's compositionRef and compositionSelector work the same way as an XR. - compositionRef: - name: production-us-east - compositionSelector: - matchLabels: - environment: production - region: us-east - provider: gcp - # A claim's writeConnectionSecretToRef mostly works the same way as an XR's. - # The one difference is that the Secret is always written to the namespace of - # the claim. - writeConnectionSecretToRef: - name: my-db-connection-details -status: - # A claim's 'Ready' condition will become True when its XR's 'Ready' condition - # becomes True. - conditions: - - type: Ready - statue: "True" - reason: Available - lastTransitionTime: 2021-10-02T07:20:50.52Z - # The last time the claim published its connection details to a Secret. - connectionDetails: - lastPublishedTime: 2021-10-02T07:20:51.24Z -``` - -> If your XR or claim isn't working as you'd expect you can try running `kubectl -> describe` against it for details - pay particular attention to any events and -> status conditions. You may need to follow the references from claim to XR to -> composed resources to find out what's happening. - -## CompositeResourceDefinitions - -Below is an example `CompositeResourceDefinition` that includes all configurable -fields. - -```yaml -apiVersion: apiextensions.crossplane.io/v1 -kind: CompositeResourceDefinition -metadata: - # XRDs must be named '.', per the plural and group names below. - name: xpostgresqlinstances.example.org -spec: - # This XRD defines an XR in the 'example.org' API group. - group: example.org - # The kind of this XR will be 'XPostgreSQLInstance`. You may also optionally - # specify a singular name and a listKind. - names: - kind: XPostgreSQLInstance - plural: xpostgresqlinstances - # This type of XR offers a claim. Omit claimNames if you don't want to do so. - # The claimNames must be different from the names above - a common convention - # is that names are prefixed with 'X' while claim names are not. This lets app - # team members think of creating a claim as (e.g.) 'creating a - # PostgreSQLInstance'. - claimNames: - kind: PostgreSQLInstance - plural: postgresqlinstances - # Each type of XR can declare any keys they write to their connection secret - # which will act as a filter during aggregation of the connection secret from - # composed resources. It's recommended to provide the set of keys here so that - # consumers of claims and XRs can see what to expect in the connection secret. - # If no key is given, then all keys in the aggregated connection secret will - # be written to the connection secret of the XR. - connectionSecretKeys: - - hostname - # Each type of XR may specify a default Composition to be used when none is - # specified (e.g. when the XR has no compositionRef or selector). A similar - # enforceCompositionRef field also exists to allow XRs to enforce a specific - # Composition that should always be used. - defaultCompositionRef: - name: example - # Each type of XR may be served at different versions - e.g. v1alpha1, v1beta1 - # and v1 - simultaneously. Currently Crossplane requires that all versions - # have an identical schema, so this is mostly useful to 'promote' a type of XR - # from alpha to beta to production ready. - versions: - - name: v1alpha1 - # Served specifies that XRs should be served at this version. It can be set - # to false to temporarily disable a version, for example to test whether - # doing so breaks anything before a version is removed wholesale. - served: true - # Referenceable denotes the version of a type of XR that Compositions may - # use. Only one version may be referenceable. - referenceable: true - # Schema is an OpenAPI schema just like the one used by Kubernetes CRDs. It - # determines what fields your XR and claim will have. Note that Crossplane - # will automatically extend with some additional Crossplane machinery. - schema: - openAPIV3Schema: - type: object - properties: - spec: - type: object - properties: - parameters: - type: object - properties: - storageGB: - type: integer - required: - - storageGB - required: - - parameters - status: - type: object - properties: - address: - description: Address of this MySQL server. - type: string -``` - -Take a look at the Kubernetes [CRD documentation][crd-docs] for a more detailed -guide to writing OpenAPI schemas. Note that the following fields are reserved -for Crossplane machinery, and will be ignored if your schema includes them: - -* `spec.resourceRef` -* `spec.resourceRefs` -* `spec.claimRef` -* `spec.writeConnectionSecretToRef` -* `status.conditions` -* `status.connectionDetails` - -> If your `CompositeResourceDefinition` isn't working as you'd expect you can -> try running `kubectl describe xrd` for details - pay particular attention to -> any events and status conditions. - -## Compositions - -You'll encounter a lot of 'field paths' when reading or writing a `Composition`. -Field paths reference a field within a Kubernetes object via a simple string -'path'. [API conventions][field-paths] describe the syntax as: - -> Standard JavaScript syntax for accessing that field, assuming the JSON object -> was transformed into a JavaScript object, without the leading dot, such as -> `metadata.name`. - - Valid field paths include: - -* `metadata.name` - The `name` field of the `metadata` object. -* `spec.containers[0].name` - The `name` field of the 0th `containers` element. -* `data[.config.yml]` - The `.config.yml` field of the `data` object. -* `apiVersion` - The `apiVersion` field of the root object. - - While the following are invalid: - -* `.metadata.name` - Leading period. -* `metadata..name` - Double period. -* `metadata.name.` - Trailing period. -* `spec.containers[]` - Empty brackets. -* `spec.containers.[0].name` - Period before open bracket. - -Below is a detailed example of a `Composition`. While detailed, this example -doesn't include every patch, transform, connection detail, and readiness check -type. Keep reading below to discover those. - -```yaml -apiVersion: apiextensions.crossplane.io/v1 -kind: Composition -metadata: - name: example - labels: - # An optional convention is to include a label of the XRD. This allows - # easy discovery of compatible Compositions. - crossplane.io/xrd: xpostgresqlinstances.database.example.org - # The following label marks this Composition for GCP. This label can - # be used in 'compositionSelector' in an XR or Claim. - provider: gcp -spec: - - # Each Composition must declare that it is compatible with a particular type - # of Composite Resource using its 'compositeTypeRef' field. The referenced - # version must be marked 'referenceable' in the XRD that defines the XR. - compositeTypeRef: - apiVersion: database.example.org/v1alpha1 - kind: XPostgreSQLInstance - - # When an XR is created in response to a claim Crossplane needs to know where - # it should create the XR's connection secret. This is configured using the - # 'writeConnectionSecretsToNamespace' field. - writeConnectionSecretsToNamespace: crossplane-system - - # Each Composition must specify at least one composed resource template. In - # this case the Composition tells Crossplane that it should create, update, or - # delete a CloudSQLInstance whenever someone creates, updates, or deletes an - # XPostgresSQLInstance. - resources: - - # It's good practice to provide a unique name for each entry. Note that - # this identifies the resources entry within the Composition - it's not - # the name the CloudSQLInstance. The 'name' field will be required in a - # future version of this API. - - name: cloudsqlinstance - - # The 'base' template for the CloudSQLInstance Crossplane will create. - # You can use the base template to specify fields that never change, or - # default values for fields that may optionally be patched over. Bases must - # be a valid Crossplane resource - a Managed Resource, Composite Resource, - # or a ProviderConfig. - base: - apiVersion: database.gcp.crossplane.io/v1beta1 - kind: CloudSQLInstance - spec: - forProvider: - databaseVersion: POSTGRES_12 - region: us-central1 - settings: - dataDiskType: PD_SSD - ipConfiguration: - ipv4Enabled: true - authorizedNetworks: - - value: "0.0.0.0/0" - - # Each resource can optionally specify a set of 'patches' that copy fields - # from (or to) the XR. - patches: - # FromCompositeFieldPath is the default when 'type' is omitted, but it's - # good practice to always include the type for readability. - - type: FromCompositeFieldPath - fromFieldPath: spec.parameters.size - toFieldPath: spec.forProvider.settings.tier - - # Each patch can optionally specify one or more 'transforms', which - # transform the 'from' field's value before applying it to the 'to' field. - # Transforms are applied in the order they are specified; each transform's - # output is passed to the following transform's input. - transforms: - - type: map - map: - medium: db-custom-1-3840 - - policy: - # By default a patch from a field path that does not exist is simply - # skipped until it does. Use the 'Required' policy to instead block and - # return an error when the field path does not exist. - fromFieldPath: Required - - # You can patch entire objects or arrays from one resource to another. - # By default the 'to' object or array will be overwritten, not merged. - # Use the 'mergeOptions' field to override this behaviour. Note that - # these fields accidentally leak Go terminology - 'slice' means 'array'. - # 'map' means 'map' in YAML or 'object' in JSON. - mergeOptions: - appendSlice: true - keepMapValues: true - - # You can include connection details to propagate from this CloudSQLInstance - # up to the XPostgreSQLInstance XR (and then on to the PostgreSQLInstance - # claim). Remember that your XRD must declare which connection secret keys - # it supports. - connectionDetails: - - name: hostname - fromConnectionSecretKey: hostname - - # By default an XR's 'Ready' status condition will become True when the - # 'Ready' status conditions of all of its composed resources become true. - # You can optionally specify custom readiness checks to override this. - readinessChecks: - - type: None - - - # If you find yourself repeating patches a lot you can group them as a named - # 'patch set' then use a PatchSet type patch to reference them. - patchSets: - - name: metadata - patches: - - type: FromCompositeFieldPath - # When both field paths are the same you can omit the 'toFieldPath' and it - # will default to the 'fromFieldPath'. - fromFieldPath: metadata.labels[some-important-label] -``` - -### Pause Annotation -There is an annotation named `crossplane.io/paused` that you can use on -Composite Resources and Composite Resource Claims to temporarily pause -reconciliations of their respective controllers on them. An example -for a Composite Resource Claim is as follows: -```yaml -apiVersion: test.com/v1alpha1 -kind: MyResource -metadata: - annotations: - crossplane.io/paused: "true" - namespace: upbound-system - name: my-resource -spec: - parameters: - tagValue: demo-test - compositionRef: - name: example -``` -where `MyResource` is a Composite Resource Claim kind. -When a Composite Resource or a Claim has the `crossplane.io/paused` annotation -with its value set to `true`, the Composite Resource controller or the Claim -controller pauses reconciliations on the resource until -the annotation is removed or its value set to something other than `true`. -Before temporarily pausing reconciliations, an event with the type `Synced`, -the status `False`, and the reason `ReconcilePaused` is emitted -on the resource. -Please also note that annotations on a Composite Resource Claim are propagated -to the associated Composite Resource but when the -`crossplane.io/paused: "true"` annotation is added to a Claim, because -reconciliations on the Claim are now paused, this newly added annotation -will not be propagated. However, whenever the annotation's value is set to a -non-`true` value, reconciliations on the Claim will now resume, and thus the -annotation will now be propagated to the associated Composite Resource -with a non-`true` value. An implication of the described behavior is that -pausing reconciliations on the Claim will not inherently pause reconciliations -on the associated Composite Resource. - - -### Patch Types - -You can use the following types of patch in a `Composition`: - -`FromCompositeFieldPath`. The default if the `type` is omitted. This type -patches from a field within the XR to a field within the composed resource. It's -commonly used to expose a composed resource spec field as an XR spec field. - -```yaml -# Patch from the XR's spec.parameters.size field to the composed resource's -# spec.forProvider.settings.tier field. -- type: FromCompositeFieldPath - fromFieldPath: spec.parameters.size - toFieldPath: spec.forProvider.settings.tier -``` - -`ToCompositeFieldPath`. The inverse of `FromCompositeFieldPath`. This type -patches from a field within the composed resource to a field within the XR. It's -commonly used to derive an XR status field from a composed resource status -field. - -```yaml -# Patch from the composed resource's status.atProvider.zone field to the XR's -# status.zone field. -- type: ToCompositeFieldPath - fromFieldPath: status.atProvider.zone - toFieldPath: status.zone -``` - -`FromCompositeFieldPath` and `ToCompositeFieldPath` patches can also take a wildcarded -field path in the `toFieldPath` parameter and patch each array element in the `toFieldPath` -with the singular value provided in the `fromFieldPath`. - -```yaml -# Patch from the XR's spec.parameters.allowedIPs to the CIDRBlock elements -# inside the array spec.forProvider.firewallRules on the composed resource. -resources: -- name: exampleFirewall - base: - apiVersion: firewall.example.crossplane.io/v1beta1 - kind: Firewall - spec: - forProvider: - firewallRules: - - Action: "Allow" - Destination: "example1" - CIDRBlock: "" - - Action: "Allow" - Destination: "example2" - CIDRBlock: "" -- type: FromCompositeFieldPath - fromFieldPath: spec.parameters.allowedIP - toFieldPath: spec.forProvider.firewallRules[*].CIDRBlock -``` - -`FromEnvironmentFieldPath`. This type patches from a field within the in-memory -environment to a field within the composed resource. It's commonly used to -expose a composed resource spec field as an XR spec field. -Note that EnvironmentConfigs are an alpha feature and need to be enabled with -the `--enable-environment-configs` flag on startup. - -```yaml -# Patch from the environment's tier.name field to the composed resource's -# spec.forProvider.settings.tier field. -- type: FromEnvironmentFieldPath - fromFieldPath: tier.name - toFieldPath: spec.forProvider.settings.tier -``` - -`ToEnvironmentFieldPath`. This type patches from a composed field to the -in-memory environment. Note that, unlike `ToCompositeFieldPath` patches, this -is executed before the composed resource is applied on the cluster which means -that the `status` is not available. -Note that EnvironmentConfigs are an alpha feature and need to be enabled with -the `--enable-environment-configs` flag on startup. - -```yaml -# Patch from the environment's tier.name field to the composed resource's -# spec.forProvider.settings.tier field. -- type: ToEnvironmentFieldPath - fromFieldPath: spec.forProvider.settings.tier - toFieldPath: tier.name -``` - -Note that the field to be patched requires some initial value to be set. - -`CombineFromComposite`. Combines multiple fields from the XR to produce one -composed resource field. - -```yaml -# Patch from the XR's spec.parameters.location field and the -# metadata.labels[crossplane.io/claim-name] label to the composed -# resource's spec.forProvider.administratorLogin field. -- type: CombineFromComposite - combine: - # The patch will only be applied when all variables have non-zero values. - variables: - - fromFieldPath: spec.parameters.location - - fromFieldPath: metadata.labels[crossplane.io/claim-name] - strategy: string - string: - fmt: "%s-%s" - toFieldPath: spec.forProvider.administratorLogin - # By default Crossplane will skip the patch until all of the variables to be - # combined have values. Set the fromFieldPath policy to 'Required' to instead - # abort composition and return an error if a variable has no value. - policy: - fromFieldPath: Required -``` - -`CombineFromEnvironment`. Combines multiple fields from the in-memory -environment to produce one composed resource field. -Note that EnvironmentConfigs are an alpha feature and need to be enabled with -the `--enable-environment-configs` flag on startup. - -```yaml -# Patch from the environments's location field and region to the composed -# resource's spec.forProvider.administratorLogin field. -- type: CombineFromEnvironment - combine: - # The patch will only be applied when all variables have non-zero values. - variables: - - fromFieldPath: location - - fromFieldPath: region - strategy: string - string: - fmt: "%s-%s" - toFieldPath: spec.forProvider.administratorLogin -``` - -At the time of writing only the `string` combine strategy is supported. It uses -[Go string formatting][pkg/fmt] to combine values, so if the XR's location was -`us-west` and its claim name was `db` the composed resource's administratorLogin -would be set to `us-west-db`. - -`CombineToComposite` is the inverse of `CombineFromComposite`. - -```yaml -# Patch from the composed resource's spec.parameters.administratorLogin and -# status.atProvider.fullyQualifiedDomainName fields back to the XR's -# status.adminDSN field. -- type: CombineToComposite - combine: - variables: - - fromFieldPath: spec.parameters.administratorLogin - - fromFieldPath: status.atProvider.fullyQualifiedDomainName - strategy: string - # Here, our administratorLogin parameter and fullyQualifiedDomainName - # status are formatted to a single output string representing a DSN. - string: - fmt: "mysql://%s@%s:3306/my-database-name" - toFieldPath: status.adminDSN -``` - -`CombineToEnvironment` is the inverse of `CombineFromEnvironment`. -Note that EnvironmentConfigs are an alpha feature and need to be enabled with -the `--enable-environment-configs` flag on startup. - -```yaml -# Patch from the composed resource's spec.parameters.administratorLogin and -# spec.forProvider.domainName fields back to the environment's adminDSN field. -- type: CombineToEnvironment - combine: - variables: - - fromFieldPath: spec.parameters.administratorLogin - - fromFieldPath: spec.forProvider.domainName - strategy: string - # Here, our administratorLogin parameter and fullyQualifiedDomainName - # status are formatted to a single output string representing a DSN. - string: - fmt: "mysql://%s@%s:3306/my-database-name" - toFieldPath: adminDSN -``` - -`PatchSet`. References a named set of patches defined in the `spec.patchSets` -array of a `Composition`. - -```yaml -# This is equivalent to specifying all of the patches included in the 'metadata' -# PatchSet. -- type: PatchSet - patchSetName: metadata -``` - -The `patchSets` array may not contain patches of `type: PatchSet`. The -`transforms` and `patchPolicy` fields are ignored by `type: PatchSet`. - -### Transform Types - -You can use the following types of transform on a value being patched: - -`map`. Transforms values using a map. - -```yaml -# If the value of the 'from' field is 'us-west', the value of the 'to' field -# will be set to 'West US'. -- type: map - map: - us-west: West US - us-east: East US - au-east: Australia East -``` - -`match`. A more complex version of `map` that can match different kinds of -patterns. It should be used if more advanced pattern matchings than a simple -string equality check are required. -The result of the first matching pattern is used as the output of this -transform. - -```yaml -- type: match - match: - patterns: - - type: literal # Not needed. This is the default. - literal: us-west - result: West US - - type: regexp - regexp: '^af-.*' - result: Somewhere in Africa - fallbackValue: Unknown -``` - -`math`. Transforms values using math. The input value must be an integer. -Currently only `multiply` is supported. - -```yaml -# If the value of the 'from' field is 2, the value of the 'to' field will be set -# to 4. -- type: math - math: - multiply: 2 -``` - -`string`. Transforms string values. -* string transform type `Format`, Currently only Go style fmt is supported. [Go style `fmt`][pkg/fmt] is supported. -* string transform type `Convert`, accepts one of `ToUpper`, `ToLower`, `ToBase64`, `FromBase64`, `ToJson`, `ToSha1`, `ToSha256`, `ToSha512`. -* string transform type `TrimPrefix`, accepts a string to be trimmed from the beginning of the input. -* string transform type `TrimSuffix`, accepts a string to be trimmed from the end of the input. -* string transform type `Regexp`, accepts a string for regexp to be applied to. - -```yaml -# If you omit the field type, by default type is set to `Format` -# If the value of the 'from' field is 'hello', the value of the 'to' field will -# be set to 'hello-world'. -- type: string - string: - fmt: "%s-world" - -# This is the same as above -# the value of the 'to' field will be set to 'hello-world'. -- type: string - string: - type: Format - fmt: "%s-world" - -# If the value of the 'from' field is 'hello', the value of the 'to' field will -# be set to 'HELLO'. -- type: string - string: - type: Convert - convert: ToUpper - -# If the value of the 'from' field is 'Hello', the value of the 'to' field will -# be set to 'hello'. -- type: string - string: - type: Convert - convert: ToLower - -# If the value of the 'from' field is 'Hello', the value of the 'to' field will -# be set to 'SGVsbG8='. -- type: string - string: - type: Convert - convert: ToBase64 - -# If the value of the 'from' field is 'SGVsbG8=', the value of the 'to' field will -# be set to 'Hello'. -- type: string - string: - type: Convert - convert: FromBase64 - -# If the value of the 'from' field is not nil, the value of the 'to' field will be -# set to raw JSON representation of the 'from' field. -- type: string - string: - type: Convert - convert: ToJson - -# The output will be the hash of the JSON representation of the 'from' field. -- type: string - string: - type: Convert - convert: ToSha1 # alternatives: 'ToSha256' or 'ToSha512' - -# If the value of the 'from' field is https://crossplane.io, the value of the 'to' field will -# be set to crossplane.io -- type: string - string: - type: TrimPrefix - trim: 'https://' - -# If the value of the 'from' field is my-string-test, the value of the 'to' field will -# be set to my-string -- type: string - string: - type: TrimSuffix - trim: '-test' - -# If the value of the 'from' field is 'arn:aws:iam::42:example, the value of the -# 'to' field will be set to "42". Note that the 'to' field is always a string. -- type: string - string: - type: Regexp - regexp: - match: 'arn:aws:iam::(\d+):.*' - group: 1 # Optional capture group. Omit to match the entire regexp. -``` - -`convert`. Transforms values of one type to another, for example from a string -to an integer. The following values are supported by the `from` and `to` fields: - -* `string` -* `bool` -* `int` -* `int64` -* `float64` - -The strings 1, t, T, TRUE, true, and True are considered 'true', while 0, f, F, -FALSE, false, and False are considered 'false'. The integer 1 and float 1.0 are -considered true, while all other values are considered false. Similarly, boolean -true converts to integer 1 and float 1.0, while false converts to 0 and 0.0. - -```yaml -# If the value to be converted is "1" (a string), the value of the 'toType' -# field will be set to 1 (an integer). -- type: convert - convert: - toType: int -``` - -Converting `string` to `float64` additionally supports parsing string in -[K8s quantity format](https://pkg.go.dev/k8s.io/apimachinery/pkg/api/resource#Quantity), -such as `1000m` or `500 Mi`: - -```yaml -- type: convert - convert: - toType: float64 - format: quantity -``` - -### Connection Details - -Connection details secret of XR is an aggregated sum of the connection details -of the composed resources. It's recommended that the author of XRD specify -exactly which keys will be allowed in the XR connection secret by listing them -in `spec.connectionSecretKeys` so that consumers of claims and XRs can see what -they can expect in the connection details secret. - -If `spec.connectionSecretKeys` is empty, then all keys of the aggregated connection -details secret will be propagated. - -You can derive the following types of connection details from a composed -resource to be aggregated: - -`FromConnectionSecretKey`. Derives an XR connection detail from a connection -secret key of a composed resource. - -```yaml -# Derive the XR's 'user' connection detail from the 'username' key of the -# composed resource's connection secret. -- type: FromConnectionSecretKey - name: user - fromConnectionSecretKey: username -``` - -`FromFieldPath`. Derives an XR connection detail from a field path within the -composed resource. - -```yaml -# Derive the XR's 'user' connection detail from the 'adminUser' status field of -# the composed resource. -- type: FromFieldPath - name: user - fromFieldPath: status.atProvider.adminUser -``` - -`FromValue`. Derives an XR connection detail from a fixed value. - -```yaml -# Always sets the XR's 'user' connection detail to 'admin'. -- type: FromValue - name: user - value: admin -``` - -### Readiness Checks - -Crossplane can use the following types of readiness check to determine whether a -composed resource is ready (and therefore whether the XR and claim should be -considered ready). Specify multiple readiness checks if multiple conditions must -be met for a composed resource to be considered ready. - -> Note that if you don't specify any readiness checks Crossplane will consider -> the composed resource to be ready when its 'Ready' status condition becomes -> 'True'. - -`MatchString`. Considers the composed resource to be ready when the value of a -field within that resource matches a specified string. - -```yaml -# The composed resource will be considered ready when the 'state' status field -# matches the string 'Online'. -- type: MatchString - fieldPath: status.atProvider.state - matchString: "Online" -``` - -`MatchInteger`. Considers the composed resource to be ready when the value of a -field within that resource matches a specified integer. - -```yaml -# The composed resource will be considered ready when the 'state' status field -# matches the integer 4. -- type: MatchInteger - fieldPath: status.atProvider.state - matchInteger: 4 -``` - -`NonEmpty`. Considers the composed resource to be ready when a field exists in -the composed resource. The name of this check can be a little confusing in that -a field that exists with a zero value (e.g. an empty string or zero integer) is -not considered to be 'empty', and thus will pass the readiness check. - -```yaml -# The composed resource will be considered ready if and when 'online' status -# field exists. -- type: NonEmpty - fieldPath: status.atProvider.online -``` - -`None`. Considers the composed resource to be ready as soon as it exists. - -### Missing Functionality - -You might find while reading through this reference that Crossplane is missing -some functionality you need to compose resources. If that's the case, please -[raise an issue] with as much detail **about your use case** as possible. Please -understand that the Crossplane maintainers are growing the feature set of the -`Composition` type conservatively. We highly value the input of our users and -community, but we also feel it's critical to avoid bloat and complexity. We -therefore wish to carefully consider each new addition. We feel some features -may be better suited for a real, expressive programming language and intend to -build an alternative to the `Composition` type as it is documented here per -[this proposal][issue-2524]. - -## Tips, Tricks, and Troubleshooting - -In this section we'll cover some common tips, tricks, and troubleshooting steps -for working with Composite Resources. If you're trying to track down why your -Composite Resources aren't working the [Troubleshooting][trouble-ref] page also -has some useful information. - -### Troubleshooting Claims and XRs - -Crossplane relies heavily on status conditions and events for troubleshooting. -You can see both using `kubectl describe` - for example: - -```console -# Describe the PostgreSQLInstance claim named my-db -kubectl describe postgresqlinstance.database.example.org my-db -``` - -Per Kubernetes convention, Crossplane keeps errors close to the place they -happen. This means that if your claim is not becoming ready due to an issue with -your `Composition` or with a composed resource you'll need to "follow the -references" to find out why. Your claim will only tell you that the XR is not -yet ready. - -To follow the references: - -1. Find your XR by running `kubectl describe` on your claim and looking for its - "Resource Ref" (aka `spec.resourceRef`). -1. Run `kubectl describe` on your XR. This is where you'll find out about issues - with the `Composition` you're using, if any. -1. If there are no issues but your XR doesn't seem to be becoming ready, take a - look for the "Resource Refs" (or `spec.resourceRefs`) to find your composed - resources. -1. Run `kubectl describe` on each referenced composed resource to determine - whether it is ready and what issues, if any, it is encountering. - -### Composite Resource Connection Secrets - -Claim and Composite Resource connection secrets are often derived from the -connection secrets of the managed resources they compose. This is a common -source of confusion because several things need to align for it to work: - -1. The **claim** must specify the secret where the aggregated connection details - should be written - * This is the `spec.writeConnectionSecretToRef` field in a claim - * If creating a composite resource directly (without a claim) then this same - field must be set on your composite resource instead -1. The **composite resource definition** must state which connection details to - aggregate from its children to publish to the claim - * This is the `spec.connectionSecretKeys` field in a - `CompositeResourceDefinition` -1. The **composition** must define where to write its aggregated connection - details - * This is the `spec.writeConnectionSecretsToNamespace` field in the - `Composition` -1. Each child **composed resource** must define the connection details it - publishes and where to write them - * These are the `connectionDetails` and - `base.spec.writeConnectionSecretToRef` fields of the composed resources - -Finally, you can't currently edit a XRD's supported connection details. The -XRD's `spec.connectionSecretKeys` is effectively immutable. This may change in -future per [this issue][issue-2024] - -### Claiming an Existing Composite Resource - -Most people create Composite Resources using a claim, but you can actually claim -an existing Composite Resource as long as its a type of XR that offers a claim -and no one else has already claimed it. To do so: - -1. Set the `spec.resourceRef` of your claim to reference the existing XR. -1. Make sure the rest of your claim's spec fields match the XR's. - -If your claim's spec fields don't match the XR's Crossplane will still claim it -but will then try to update the XR's spec fields to match the claim's. - -### Influencing External Names - -The `crossplane.io/external-name` annotation has special meaning to Crossplane -managed resources - it specifies the name (or identifier) of the resource in the -external system, for example the actual name of a `CloudSQLInstance` in the GCP -API. Some managed resources don't let you specify an external name - in those -cases Crossplane will set it for you to whatever the external system requires. - -If you add the `crossplane.io/external-name` annotation to a claim Crossplane -will automatically propagate it when it creates an XR. It's good practice to -have your `Composition` further propagate the annotation to one or more composed -resources, but it's not required. - -### Mixing and Matching Providers - -Crossplane has providers for many things in addition to the big clouds. Take a -look at the [Upbound Marketplace][upbound-marketplace] to find many of them. -Keep in mind that you can mix and match managed resources from different -providers within a `Composition` to create Composite Resources. For example you -might use provider-aws and provider-sql to create an XR that provisions an -`RDSInstance` then creates an SQL `Database` and `User`, or provider-gcp and -provider-helm to create a `GKECluster` and deploy a Helm Chart `Release` to it. - -Often when mixing and matching providers you'll need to compose a -`ProviderConfig` for one provider that loads credentials from the connection -secret of a managed resource from another provider. Sometimes you may need to -use an intermediary XR to mutate the connection details to suit your needs. -[This example][helm-and-gcp] from provider-helm demonstrates using a GKE cluster -connection secret as Helm `ProviderConfig` credentials. - -### Patching From One Composed Resource to Another or Itself - -It's not possible to patch _directly_ from one composed resource to another - -i.e. from one entry in the `spec.resources` array of a `Composition` to another. -It is however possible to achieve this by using the XR as an intermediary. To do -so: - -1. Use a `ToCompositeFieldPath` patch to patch from your source composed - resource to the XR. Typically you'll want to patch to a status field or an - annotation. -1. Use a `FromCompositeFieldPath` patch to patch from the 'intermediary' field - you patched to in step 1 to a field on the destination composed resource. - -Note that the source and the target composed resource can be the same. - -[managed-resources]: {{}} -[crd-docs]: https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/ -[raise an issue]: https://github.com/crossplane/crossplane/issues/new?assignees=&labels=enhancement&template=feature_request.md -[issue-2524]: https://github.com/crossplane/crossplane/issues/2524 -[field-paths]: https://github.com/kubernetes/community/blob/61f3d0/contributors/devel/sig-architecture/api-conventions.md#selecting-fields -[pkg/fmt]: https://pkg.go.dev/fmt -[upbound-marketplace]: https://marketplace.upbound.io -[helm-and-gcp]: https://github.com/crossplane-contrib/provider-helm/blob/2dcbdd0/examples/in-composition/composition.yaml -[issue-2024]: https://github.com/crossplane/crossplane/issues/2024 -[xrs-and-mrs]: /media/composition-xrs-and-mrs.svg -[how-it-works]: /media/composition-how-it-works.svg -[provider-kubernetes]: https://marketplace.upbound.io/providers/crossplane-contrib/provider-kubernetes -[provider-helm]: https://marketplace.upbound.io/providers/crossplane-contrib/provider-helm/ -[claims-and-xrs]: /media/composition-claims-and-xrs.svg -[xr-ref]: {{}} diff --git a/content/v1.11/concepts/packages.md b/content/v1.11/concepts/packages.md deleted file mode 100644 index ccdb1a7cd..000000000 --- a/content/v1.11/concepts/packages.md +++ /dev/null @@ -1,509 +0,0 @@ ---- -title: Crossplane Packages -weight: 104 ---- - -Crossplane packages are opinionated [OCI images] that contain a stream of YAML -that can be parsed by the Crossplane package manager. Crossplane packages come -in two varieties: [Providers] and Configurations. Ultimately, the primary -purposes of Crossplane packages are as follows: - -- **Convenient Distribution**: Crossplane packages can be pushed to or installed - from any OCI-compatible registry. -- **Version Upgrade**: Crossplane can update packages in-place, meaning that you - can pick up support for new resource types or controller bug-fixes without - modifying your existing infrastructure. -- **Permissions**: Crossplane allocates permissions to packaged controllers in a - manner that ensures they will not maliciously take over control of existing - resources owned by other packages. Installing CRDs via packages also allows - Crossplane itself to manage those resources, allowing for powerful - [composition] features to be enabled. -- **Dependency Management**: Crossplane resolves dependencies between packages, - automatically installing a package's dependencies if they are not present in - the cluster, and checking if dependency versions are valid if they are already - installed. - -## Table of Contents - -The following packaging operations are covered in detail below: - -- [Table of Contents](#table-of-contents) -- [Building a Package](#building-a-package) - - [Provider Packages](#provider-packages) - - [Configuration Packages](#configuration-packages) -- [Pushing a Package](#pushing-a-package) -- [Installing a Package](#installing-a-package) - - [spec.package](#specpackage) - - [spec.packagePullPolicy](#specpackagepullpolicy) - - [spec.revisionActivationPolicy](#specrevisionactivationpolicy) - - [spec.revisionHistoryLimit](#specrevisionhistorylimit) - - [spec.packagePullSecrets](#specpackagepullsecrets) - - [spec.skipDependencyResolution](#specskipdependencyresolution) - - [spec.ignoreCrossplaneConstraints](#specignorecrossplaneconstraints) - - [spec.controllerConfigRef](#speccontrollerconfigref) -- [Upgrading a Package](#upgrading-a-package) - - [Package Upgrade Issues](#package-upgrade-issues) -- [The Package Cache](#the-package-cache) - - [Pre-Populating the Package Cache](#pre-populating-the-package-cache) - -## Building a Package - -As stated above, Crossplane packages are just opinionated OCI images, meaning -they can be constructed using any tool that outputs files that comply the the -OCI specification. However, constructing packages using the Crossplane CLI is a -more streamlined experience, as it will perform build-time checks on your -packages to ensure that they are compliant with the Crossplane [package format]. - -Providers and Configurations vary in the types of resources they may contain in -their packages. All packages must have a `crossplane.yaml` file in the root -directory with package contents. The `crossplane.yaml` contains the package's -metadata, which governs how Crossplane will install the package. - -### Provider Packages - -A Provider package contains a `crossplane.yaml` with the following format: - -```yaml -apiVersion: meta.pkg.crossplane.io/v1 -kind: Provider -metadata: - name: provider-gcp -spec: - crossplane: - version: ">=v1.0.0" - controller: - image: crossplane/provider-gcp-controller:v0.14.0 - permissionRequests: - - apiGroups: - - apiextensions.crossplane.io - resources: - - compositions - verbs: - - get - - list - - create - - update - - patch - - watch -``` - -See all available fields in the [official documentation][provider-docs]. - -> Note: The `meta.pkg.crossplane.io` group does not contain custom resources -> that may be installed into the cluster. They are strictly used as metadata in -> a Crossplane package. - -A Provider package may optionally contain one or more CRDs. These CRDs will be -installed prior to the creation of the Provider's `Deployment`. Crossplane will -not install _any_ CRDs for a package unless it can determine that _all_ CRDs can -be installed. This guards against multiple Providers attempting to reconcile the -same CRDs. Crossplane will also create a `ServiceAccount` with permissions to -reconcile these CRDs and it will be assigned to the controller `Deployment`. - -The `spec.controller.image` fields specifies that the `Provider` desires for the -controller `Deployment` to be created with the provided image. It is important -to note that this image is separate from the package image itself. In the case -above, it is an image containing the `provider-gcp` controller binary. - -The `spec.controller.permissionRequests` field allows a package author to -request additional RBAC for the packaged controller. The controller's -`ServiceAccount` will automatically give the controller permission to reconcile -all types that its package installs, as well as `Secrets`, `ConfigMaps`, and -`Events`. Any additional permissions must be explicitly requested. - -> Note that the Crossplane RBAC manager can be configured to reject permissions -> for certain API groups. If a package requests permissions that Crossplane is -> configured to reject, the package will fail to be installed. -> Authorized permissions should be aggregated to the rbac manager clusterrole -> (the cluster role defined by the provider-clusterrole flag in the rbac manager) -> by using the label `rbac.crossplane.io/aggregate-to-allowed-provider-permissions: "true"` - -The `spec.crossplane.version` field specifies the version constraints for core -Crossplane that the `Provider` is compatible with. It is advisable to use this -field if a package relies on specific features in a minimum version of -Crossplane. - -> All version constraints used in packages follow the [specification] outlined -> in the `Masterminds/semver` repository. - -For an example Provider package, see [provider-gcp]. - -To build a Provider package, navigate to the package root directory and execute -the following command: - -``` -crossplane build provider -``` - -If the Provider package is valid, you will see a file with the `.xpkg` -extension. - -> Note that the Crossplane CLI will not follow symbolic links for files in the -> root package directory. - -### Configuration Packages - -A Configuration package contains a `crossplane.yaml` with the following format: - -```yaml -apiVersion: meta.pkg.crossplane.io/v1 -kind: Configuration -metadata: - name: my-org-infra -spec: - crossplane: - version: ">=v1.0.0" - dependsOn: - - provider: xpkg.upbound.io/crossplane-contrib/provider-gcp - version: ">=v0.14.0" -``` - -See all available fields in the [official documentation][configuration-docs]. - -A Configuration package may also specify one or more of -`CompositeResourceDefinition` and `Composition` types. These resources will be -installed and will be solely owned by the Configuration package. No other -package will be able to modify them. - -The `spec.crossplane.version` field serves the same purpose that it does in a -`Provider` package. - -The `spec.dependsOn` field specifies packages that this package depends on. When -installed, the package manager will ensure that all dependencies are present and -have a valid version given the constraint. If a dependency is not installed, the -package manager will install it at the latest version that fits within the -provided constraints. - -> Dependency resolution is a `beta` feature and depends on the `v1beta1` -> [`Lock` API][lock-api]. - -For an example Configuration package, see [getting-started-with-gcp](https://github.com/crossplane/docs/tree/master/content/media/snippets/package/gcp). - -To build a Configuration package, navigate to the package root directory and -execute the following command: - -``` -crossplane build configuration -``` - -If the Provider package is valid, you will see a file with the `.xpkg` -extension. - -## Pushing a Package - -Crossplane packages can be pushed to any OCI-compatible registry. If a specific -registry is not specified they will be pushed to Docker Hub. - -To push a Provider package, execute the following command: - -``` -crossplane push provider xpkg.upbound.io/crossplane-contrib/provider-gcp:v0.22.0 -``` - -To push a Configuration package, execute the following command: - -``` -crossplane push configuration xpkg.upbound.io/crossplane-contrib/my-org-infra:v0.1.0 -``` - -> Note: Both of the above commands assume a single `.xpkg` file exists in the -> directory. If multiple exist or you would like to specify a package in a -> different directory, you can supply the `-f` flag with the path to the -> package. - -## Installing a Package - -Packages can be installed into a Crossplane cluster using the Crossplane CLI. - -To install a Provider package, execute the following command: - -``` -crossplane install provider xpkg.upbound.io/crossplane-contrib/provider-gcp:v0.22.0 -``` - -To install a Configuration package, execute the following command: - -``` -crossplane install configuration xpkg.upbound.io/crossplane-contrib/my-org-infra:v0.1.0 -``` - -Packages can also be installed manually by creating a `Provider` or -`Configuration` object directly. The preceding commands would result in the -creation of the following two resources, which could have been authored by hand: - -```yaml -apiVersion: pkg.crossplane.io/v1 -kind: Provider -metadata: - name: provider-gcp -spec: - package: xpkg.upbound.io/crossplane-contrib/provider-gcp:v0.22.0 - packagePullPolicy: IfNotPresent - revisionActivationPolicy: Automatic - revisionHistoryLimit: 1 -``` - -```yaml -apiVersion: pkg.crossplane.io/v1 -kind: Configuration -metadata: - name: my-org-infra -spec: - package: xpkg.upbound.io/crossplane-contrib/my-org-infra:v0.1.0 - packagePullPolicy: IfNotPresent - revisionActivationPolicy: Automatic - revisionHistoryLimit: 1 -``` - -> Note: These types differ from the `Provider` and `Configuration` types we saw -> earlier. They exist in the `pkg.crossplane.io` group rather than the -> `meta.pkg.crossplane.io` group and are actual custom resources created in the -> cluster. - -The default fields specified above can be configured with different values to -modify the installation and upgrade behavior of a package. In addition, there -are multiple other fields which can further customize how the package manager -handles a specific revision. - -### spec.package - -This is the package image that we built, pushed, and are asking Crossplane to -install. The tag we specify here is important. Crossplane will periodically -check if the installed image matches the digest of the image in the remote -registry. If it does not, Crossplane will create a new _Revision_ (either -`ProviderRevision` or `ConfigurationRevision`). If you do not wish Crossplane to -ever update your packages without explicitly instructing it to do so, you should -consider specifying a tag which you know will not have the underlying contents -change unexpectedly (e.g. a specific semantic version, such as `v0.1.0`) or, for -an even stronger guarantee, providing the image with a `@sha256` extension -instead of a tag. - -### spec.packagePullPolicy - -Valid values: `IfNotPresent`, `Always`, or `Never` (default: `IfNotPresent`) - -When a package is installed, Crossplane downloads the image contents into a -cache. Depending on the image identifier (tag or digest) and the -`packagePullPolicy`, the Crossplane package manager will decide if and when to -check and see if newer package contents are available. The following table -describes expected behavior based on the supplied fields: - -| | `IfNotPresent` | `Always` | `Never` | -|---------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------| -| Semver Tag (e.g. `v1.3.0`) | Package is downloaded when initially installed, and as long as it is present in the cache, it will not be downloaded again. If the cache is lost and the a new version of the package image has been pushed for the same tag, package could inadvertently be upgraded.

**Upgrade Safety: Strong** | Package is downloaded when initially installed, but Crossplane will check every minute if new content is available. New content would have to be pushed for the same semver tag for upgrade to take place.

**Upgrade Safety: Weak** | Crossplane will never download content. Must manually load package image in cache.

**Upgrade Safety: Strongest** | -| Digest (e.g. `@sha256:28b6...`) | Package is downloaded when initially installed, and as long as it is present in the cache, it will not be downloaded again. If the cache is lost but an image with this digest is still available, it will be downloaded again. The package will never be upgraded without a user changing the digest.

**Upgrade Safety: Very Strong** | Package is downloaded when initially installed, but Crossplane will check every minute if new content is available. Because image digest is used, new content will never be downloaded.

**Upgrade Safety: Strong** | Crossplane will never download content. Must manually load package image in cache.

**Upgrade Safety: Strongest** | -| Channel Tag (e.g. `latest`) | Package is downloaded when initially installed, and as long as it is present in the cache, it will not be downloaded again. If the cache is lost, the latest version of this package image will be downloaded again, which will frequently have different contents.

**Upgrade Safety: Weak** | Package is downloaded when initially installed, but Crossplane will check every minute if new content is available. When the image content is new, Crossplane will download the new contents and create a new revision.

**Upgrade Safety: Very Weak** | Crossplane will never download content. Must manually load package image in cache.

**Upgrade Safety: Strongest** | - -### spec.revisionActivationPolicy - -Valid values: `Automatic` or `Manual` (default: `Automatic`) - -When Crossplane downloads new contents for a package, regardless of whether it -was a manual upgrade (i.e. user updating package image tag), or an automatic one -(enabled by the `packagePullPolicy`), it will create a new package revision. -However, the new objects and / or controllers will not be installed until the -new revision is marked as `Active`. This activation process is configured by the -`revisionActivationPolicy` field. - -An `Active` package revision attempts to become the _controller_ of all -resources it installs. There can only be one controller of a resource, so if two -`Active` revisions both install the same resource, one will fail to install -until the other cedes control. - -An `Inactive` package revision attempts to become the _owner_ of all resources -it installs. There can be an arbitrary number of owners of a resource, so -multiple `Inactive` revisions and a single `Active` revision can exist for a -resource. Importantly, an `Inactive` package revision will not perform any -auxiliary actions (such as creating a `Deployment` in the case of a `Provider`), -meaning we will not encounter a situation where two revisions are fighting over -reconciling a resource. - -With `revisionActivationPolicy: Automatic`, Crossplane will mark any new -revision as `Active` when it is created, as well as transition any old revisions -to `Inactive`. When `revisionActivationPolicy: Manual`, the user must manually -edit a new revision and mark it as `Active`. This can be useful if you are using -a `packagePullPolicy: Automatic` with a channel tag (e.g. `latest`) and you want -Crossplane to create new revisions when a new version is available, but you -don't want to automatically update to that newer revision. - -It is recommended for most users to use semver tags or image digests and -manually update their packages, but use a `revisionActivationPolicy: Automatic` -to avoid having to manually activate new versions. However, each user should -consider their specific environment and choose a combination that makes sense -for them. - -For security reasons, it's suggested using image digests instead or alongside -tags (`vx.y.z@sha256:...`), to ensure that the package content wasn't tampered -with. - -### spec.revisionHistoryLimit - -Valid values: any integer, disabled by explicitly setting to `0` (default `1`) - -When a revision transitions from `Inactive` to `Active`, its revision number -gets set to one greater than the largest revision number of all revisions for -its package. Therefore, as the number of revisions increases, the least recently -`Active` revision will have the lowest revision number. Crossplane will garbage -collect old `Inactive` revisions if they fall outside the -`spec.revisionHistoryLimit`. For instance, if my revision history limit is `3` -and I currently have three old `Inactive` revisions and one `Active` revision, -when I upgrade the next time, the new revision will be given the highest -revision number when it becomes `Active`, the previously `Active` revision will -become `Inactive`, and the oldest `Inactive` revision will be garbage collected. - -> Note: In the case that `spec.revisionActivationPolicy: Manual` and you upgrade -> enough times (but do not make `Active` the new revisions), it is possible that -> activating a newer revision could cause the previously `Active` revision to -> immediately be garbage collected if it is outside the -> `spec.revisionHistoryLimit`. - -### spec.packagePullSecrets - -Valid values: slice of `Secret` names (secrets must exist in `namespace` -Crossplane was installed in, typically `crossplane-system`) - -This field allows a user to provide credentials required to pull a package from -a private repository on a registry. The credentials are passed along to a -packaged controller if the package is a `Provider`, but are not passed along to -any dependencies. - -### spec.skipDependencyResolution - -Valid values: `true` or `false` (default: `false`) - -If `skipDependencyResolution: true`, the package manager will install a package -without considering its dependencies. - -### spec.ignoreCrossplaneConstraints - -Valid values: `true` or `false` (default: `false`) - -If `ignoreCrossplaneConstraints: true`, the package manager will install a -package without considering the version of Crossplane that is installed. - -### spec.controllerConfigRef - -{{< hint "warning" >}} -The `ControllerConfig` API has been deprecated and will be removed in a future -release when a comparable alternative is available. -{{< /hint >}} - -Valid values: name of a `ControllerConfig` object - -Packaged `Provider` controllers are installed in the form of a `Deployment`. -Crossplane populates the `Deployment` with default values that may not be -appropriate for every use-case. In the event that a user wants to override some -of the defaults that Crossplane has set, they may create and reference a -`ControllerConfig`. - -An example of when this may be useful is when a user is running Crossplane on -EKS and wants to take advantage of [IAM Roles for Service Accounts]. This -requires setting an `fsGroup` and annotating the `ServiceAccount` that -Crossplane creates for the controller. This could be accomplished with the -following `ControllerConfig` and `Provider`: - -```yaml -apiVersion: pkg.crossplane.io/v1alpha1 -kind: ControllerConfig -metadata: - name: aws-config - annotations: - eks.amazonaws.com/role-arn: arn:aws:iam::$AWS_ACCOUNT_ID\:role/$IAM_ROLE_NAME -spec: - podSecurityContext: - fsGroup: 2000 ---- -apiVersion: pkg.crossplane.io/v1 -kind: Provider -metadata: - name: provider-aws -spec: - package: xpkg.upbound.io/crossplane-contrib/provider-aws:v0.33.0 - controllerConfigRef: - name: aws-config -``` - -You can find all configurable values in the [official `ControllerConfig` -documentation][controller-config-docs]. - -## Upgrading a Package - -Upgrading a `Provider` or `Configuration` to a new version can be accomplished -by editing the existing manifest and applying it with a new version tag in -`spec.package`. Crossplane will observe the updated manifest and create a new -`ProviderRevision` or `ConfigurationRevision` for the specified version. The new -revision will be activated in accordance with `spec.revisionActivationPolicy`. - -### Package Upgrade Issues - -Upgrading a package can require manual intervention in the event that the -previous version of the package supported a version of a custom resource that -has been dropped and replaced by a new version in the new package revision. -Kubernetes does not allow for applying a `CustomResourceDefinition` (CRD) that -drops a version in the `spec` that is in the current `status.storedVersions` -list, meaning that a revision cannot update and become the _controller_ of all -of its resources. - -This situation can be remedied by manually deleting the offending CRD and -letting the new revision re-create it. In the event that custom resources exist -for the given CRD, they must be deleted before the CRD can be removed. - -## The Package Cache - -When a package is installed into a cluster, Crossplane fetches the package image -and stores its contents in a dedicated package cache. By default, this cache is -backed by an [`emptyDir` Volume][emptyDir-volume], meaning that all cached data -is lost when a `Pod` restarts. Users who wish for cache contents to be persisted -between `Pod` restarts may opt to instead use a [`persistentVolumeClaim` -(PVC)][pvc] by setting the `packageCache.pvc` Helm chart parameter to the name -of the PVC. - -### Pre-Populating the Package Cache - -Because the package cache can be backed by any storage medium, users are able to -optionally to pre-populate the cache with images that are not present on an -external [OCI registry]. To utilize a package that has been manually stored in -the cache, users must specify the name of the package in `spec.package` and use -`packagePullPolicy: Never`. For instance, if a user built a `Configuration` -package named `mycoolpkg.xpkg` and loaded it into the volume that was to be used -for the package cache (i.e. copied the `.xpkg` file into the storage medium -backing the PVC), the package could be utilized with the following manifest: - -```yaml -apiVersion: pkg.crossplane.io/v1 -kind: Configuration -metadata: - name: my-cool-pkg -spec: - package: mycoolpkg - packagePullPolicy: Never -``` - -Importantly, as long as a package is being used as the `spec.package` of a -`Configuration` or `Provider`, it must remain in the cache. For this reason, it -is recommended that users opt for a durable storage medium when manually loading -packages into the cache. - -In addition, if manually loading a `Provider` package into the cache, users must -ensure that the controller image that it references is able to be pulled by the -cluster nodes. This can be accomplished either by pushing it to a registry, or -by [pre-pulling images] onto nodes in the cluster. - - - - -[OCI images]: https://github.com/opencontainers/image-spec -[Providers]: {{}} -[provider-docs]: https://doc.crds.dev/github.com/crossplane/crossplane/meta.pkg.crossplane.io/Provider/v1 -[configuration-docs]: https://doc.crds.dev/github.com/crossplane/crossplane/meta.pkg.crossplane.io/Configuration/v1 -[lock-api]: https://doc.crds.dev/github.com/crossplane/crossplane/pkg.crossplane.io/Lock/v1beta1 -[specification]: https://github.com/Masterminds/semver#basic-comparisons -[composition]: {{}} -[IAM Roles for Service Accounts]: https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html -[controller-config-docs]: https://doc.crds.dev/github.com/crossplane/crossplane/pkg.crossplane.io/ControllerConfig/v1alpha1 -[package format]: https://github.com/crossplane/crossplane/blob/1aa83092172bdf0d2ed64754d33517c612ff7368/design/one-pager-package-format-v2.md -[provider-gcp]: https://doc.crds.dev/github.com/crossplane/crossplane/meta.pkg.crossplane.io/Provider/v1 -[emptyDir-volume]: https://kubernetes.io/docs/concepts/storage/volumes/#emptydir -[pvc]: https://kubernetes.io/docs/concepts/storage/volumes/#persistentvolumeclaim -[OCI registry]: https://github.com/opencontainers/distribution-spec -[pre-pulling images]: https://kubernetes.io/docs/concepts/containers/images/#pre-pulled-images diff --git a/content/v1.11/concepts/terminology.md b/content/v1.11/concepts/terminology.md deleted file mode 100644 index 7b98f6410..000000000 --- a/content/v1.11/concepts/terminology.md +++ /dev/null @@ -1,211 +0,0 @@ ---- -title: Terminology -weight: 110 ---- -## A Note on Style - -Each type of Kubernetes resource has a ‘Pascal case’ name - i.e. a title case -name with no spaces between each word. Examples include ‘DaemonSet’ and -‘PersistentVolumeClaim’. Often these names are written using fixed width fonts -to draw attention to the fact that they’re a concrete type of resource within -the API - e.g. `PersistentVolumeClaim`. - -Crossplane follows this convention. We often use names like RDSInstance or -CompositeResourceDefinition when discussing Crossplane types. Crossplane also -has “classes of types” - i.e. concepts that aren’t a distinct type of API -resource, but rather describe a group of conceptually similar types. For example -there is no ManagedResource type in Crossplane - instead types like RDSInstance -and GKECluster are said to be “a managed resource”. - -Use your discretion as to whether you use pascal case when writing about a -distinct type - e.g. “RDS Instance” and “RDSInstance” are both fine. The pascal -case form makes more sense in contexts like documentation where you’re referring -to Crossplane’s RDSInstance managed resource rather than the general concept of -“an RDS instance”. Avoid using Pascal case when talking about classes of types - -i.e. always write “managed resource”, not “ManagedResource”. Each of the below -terms clarify whether they correspond to a single type, or a class of types. - -### Why 'X'? - -You may notice that Crossplane uses “X” as shorthand for “Crossplane” and/or -“Composite”. This is because some of our concepts - specifically Composite -Resources (XRs) and Composite Resource Definitions (XRDs) are modelled on -similar Kubernetes concepts - Custom Resources (CRs) and Custom Resource -Definitions (CRDs). We chose to abbreviate to (e.g.) XRD instead of CRD to avoid -confusion. - -## Crossplane Terms - -The below terms are commonly used in the Crossplane ecosystem. - -### Composition - -The term Composition has two related but distinct meanings. - -“Composition” refers broadly to the feature of Crossplane that allows teams to -define their own opinionated platform APIs. - -“A Composition” or `Composition` (fixed width) refers to the key Crossplane API -type that configures how Crossplane should compose resources into a higher level -“composite resource”. A Composition tells Crossplane “when someone creates -composite resource X, you should respond by creating resources Y and Z”. - -The latter use of Composition represents a distinct Crossplane API type so -Pascal case and fixed width fonts are appropriate. We also tend to capitalise -the former use, representing the feature in general, but fixed width fonts are -not appropriate in that context. - -> Folks accustomed to Terraform might think of a Composition as a Terraform -> module; the HCL code that describes how to take input variables and use them -> to create resources in some cloud API. Folks accustomed to Helm might think of -> a Composition as a Helm chart’s templates; the moustache templated YAML files -> that describe how to take Helm chart values and render Kubernetes resources. - -### Composite Resource - -A “Composite Resource” or “XR” is an API type defined using Crossplane. A -composite resource’s API type is arbitrary - dictated by the concept the author -wishes to expose as an API, for example an “AcmeCoDB”. A common convention is -for types to start with "X" - e.g. "XAcmeCoDB". - -We talk about Crossplane being a tool teams can use to define their own -opinionated platform APIs. Those APIs are made up of composite resources; when -you are interacting with an API that your platform team has defined, you’re -interacting with composite resources. - -A composite resource can be thought of as the interface to a Composition. It -provides the inputs a Composition uses to compose resources into a higher level -concept. In fact, the composite resource _is_ the high level concept. - -The term “Composite Resource” refers to a class of types, so avoid using Pascal -case - “Composite Resource” not CompositeResource. Use pascal case when -referring to a distinct type of composite resource - e.g. a XAcmeCoDB. - -> Folks accustomed to Terraform might think of a composite resource as a -> `tfvars` file that supplies values for the variables a Terraform module uses -> to create resources in some cloud API. Folks accustomed to Helm might think of -> a composite resource as the `values.yaml` file that supplies inputs to a Helm -> chart’s templates. - -### Composite Resource Claim - -A “Composite Resource Claim”, “XRC”, or just “a claim” is also an API type -defined using Crossplane. Each type of claim corresponds to a type of composite -resource, and the pair have nearly identical schemas. Like composite resources, -the type of a claim is arbitrary. - -We talk about Crossplane being a tool platform teams can use to offer -opinionated platform APIs to the application teams they support. The platform -team offers those APIs using claims. It helps to think of the claim as an -application team’s interface to a composite resource. You could also think of -claims as the public (app team) facing part of the opinionated platform API, -while composite resources are the private (platform team) facing part. - -A common convention is for a claim to be of the same type as its corresponding -composite resource, but without the "X" prefix. So an "AcmeCoDB" would be a type -of claim, and a "XAcmeCoDB" would be the corresponding type of composite -resource. This allows claim consumers to be relatively ignorant of Crossplane -and composition, and to instead simply think about managing “an AcmeCo DB” while -the platform team worries about the implementation details. - -The term “Composite Resource Claim” refers to a class of types, so avoid using -Pascal case - “Composite Resource Claim” not CompositeResourceClaim. Use Pascal -case when referring to a distinct type of composite resource claim - e.g. an -AcmeCoDB. - -> Claims map to the same concepts as described above under the composite -> resource heading; i.e. `tfvars` files and Helm `values.yaml` files. Imagine -> that some `tfvars` files and some `values.yaml` files were only accessible to -> the platform team while others were offered to application teams; that’s the -> difference between a composite resource and a claim. - -### Composite Resource Definition - -A “Composite Resource Definition” or “XRD” is the API type used to define new -types of composite resources and claims. Types of composite resources and types -of claims exist because they were defined into existence by an XRD. The XRD -configures Crossplane with support for the composite resources and claims that -make up a platform API. - -XRDs are often conflated with composite resources (XRs) - try to avoid this. -When someone uses the platform API to create infrastructure they’re not creating -XRDs but rather creating composite resources (XRs). It may help to think of a -composite resource as a database entry, while an XRD is a database schema. For -those familiar with Kubernetes, the relationship is very similar to that between -a Custom Resource Definition (CRD) and a Custom Resource (CR). - -A `CompositeResourceDefinition` is a distinct Crossplane API type, so Pascal -case and fixed width fonts are appropriate. - -> There isn’t a direct analog to XRDs in the Helm ecosystem, but they’re a -> little bit like the variable blocks in a Terraform module that define which -> variables exist, whether those variables are strings or integers, whether -> they’re required or optional, etc. - -### Managed Resource - -Managed resources are granular, high fidelity Crossplane representations of a -resource in an external system - i.e. resources that are managed by Crossplane. -Managed resources are what Crossplane enables platform teams to compose into -higher level composite resources, forming an opinionated platform API. They're -the building blocks of Crossplane. - -You’ll often hear three related terms used in the Crossplane ecosystem; composed -resource, managed resource, and external resource. While there are some subtle -contextual differences, these all broadly refer to the same thing. Take an -RDSInstance for example; it is a managed resource. A distinct resource within -the Crossplane API that represents an AWS RDS instance. When we make a -distinction between the managed resource and an external resource we’re simply -making the distinction between Crossplane’s representation of the thing (the -`RDSInstance` in the Kubernetes API), and the actual thing in whatever external -system Crossplane is orchestrating (the RDS instance in AWS's API). When we -mention composed resources, we mean a managed resource of which a composite -resource is composed. - -Managed resources are a class of resource, so avoid using Pascal case - “managed -resource” not “ManagedResource”. - -> Managed resources are similar to Terraform resource blocks, or a distinct -> Kubernetes resource within a Helm chart. - -### Package - -Packages extend Crossplane, either with support for new kinds of composite -resources and claims, or support for new kinds of managed resources. There are -two types of Crossplane package; configurations and providers. - -A package is not a distinct type in the Crossplane API, but rather a class of -types. Therefore Pascal case is not appropriate. - -### Configuration - -A configuration extends Crossplane by installing conceptually related groups of -XRDs and Compositions, as well as dependencies like providers or further -configurations. Put otherwise, it configures the opinionated platform API -that Crossplane exposes. - -A `Configuration` is a distinct type in the Crossplane API, therefore Pascal -case and fixed width fonts are appropriate. - -### Provider - -A provider extends Crossplane by installing controllers for new kinds of managed -resources. Providers typically group conceptually related managed resources; for -example the AWS provider installs support for AWS managed resources like -RDSInstance and S3Bucket. - -A `Provider` is a distinct type in the Crossplane API, therefore Pascal case and -fixed width fonts are appropriate. Note that each Provider package has its own -configuration type, called a `ProviderConfig`. Don’t confuse the two; the former -installs the provider while the latter specifies configuration that is relevant -to all of its managed resources. - -> Providers are directly analogous to Terraform providers. - -### Crossplane Resource Model - -The Crossplane Resource Model or XRM is neither a distinct Crossplane API type, -or a class of types. Rather it represents the fact that Crossplane has a -consistent, opinionated API. The strict definition of the XRM is currently -somewhat vague, but it could broadly be interpreted as a catchall term referring -to all of the concepts mentioned on this page. diff --git a/content/v1.11/getting-started/provider-aws-part-2.md b/content/v1.11/getting-started/provider-aws-part-2.md deleted file mode 100644 index eae352b9a..000000000 --- a/content/v1.11/getting-started/provider-aws-part-2.md +++ /dev/null @@ -1,967 +0,0 @@ ---- -title: AWS Quickstart Part 2 -weight: 120 -tocHidden: true ---- - -{{< hint "important" >}} -This guide is part 2 of a series. Follow **[part 1]({{}})** -to install Crossplane and connect your Kubernetes cluster to AWS. - -**[Part 3]({{}})** covers patching _composite resources_ -and using Crossplane _packages_. -{{< /hint >}} - -This section creates a _[Composition](#create-a-composition)_, -_[Composite Resource Definition](#define-a-composite-resource)_ and a -_[Claim](#create-a-claim)_ -to create a custom Kubernetes API to create AWS resources. This custom API is a -_Composite Resource_ (XR) API. - -## Prerequisites -* Complete [quickstart part 1]({{}}) connecting Kubernetes - to AWS. -* an AWS account with permissions to create an AWS S3 storage bucket and a -DynamoDB instance - -{{}} -1. Add the Crossplane Helm repository and install Crossplane -```shell -helm repo add \ -crossplane-stable https://charts.crossplane.io/stable -helm repo update -&& -helm install crossplane \ -crossplane-stable/crossplane \ ---namespace crossplane-system \ ---create-namespace -``` - -2. When the Crossplane pods finish installing and are ready, apply the AWS Provider - -```yaml {label="provider",copy-lines="all"} -cat <}} -```ini {copy-lines="all"} -[default] -aws_access_key_id = $@$@ -aws_secret_access_key = $@$@ -``` -{{}} - -4. Create a Kubernetes secret from the AWS keys -```shell {label="kube-create-secret",copy-lines="all"} -kubectl create secret \ -generic aws-secret \ --n crossplane-system \ ---from-file=creds=./aws-credentials.txt -``` - -5. Create a _ProviderConfig_ -```yaml {label="providerconfig",copy-lines="all"} -cat <}} - -## Create a composition -[Part 1]({{}}) created a single _managed resource_. -A _Composition_ is a template to create one or more _managed resource_ at the same time. - -This sample _composition_ creates an DynamoDB instance and associated S3 storage -bucket. - -{{< hint "note" >}} -This example comes from the AWS recommendation for -[storing large DynamoDB attributes in S3](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/bp-use-s3-too.html#bp-use-s3-too-large-values). -{{< /hint >}} - -To create a _composition_, first define each individual managed resource. - -### Create an S3 bucket object -Define a `bucket` resource using the configuration from the previous section: - -{{< hint "note" >}} -Don't apply this configuration. This YAML is part of a larger -definition. -{{< /hint >}} - -```yaml -apiVersion: s3.aws.upbound.io/v1beta1 -kind: Bucket -metadata: - name: crossplane-quickstart-bucket -spec: - forProvider: - region: "us-east-2" - providerConfigRef: - name: default -``` - -### Create a DynamoDB table resource -Next, define a DynamoDB `table` resource. - -{{< hint "tip" >}} -The [Upbound Marketplace](https://marketplace.upbound.io/) provides -[schema -documentation](https://marketplace.upbound.io/providers/upbound/provider-aws/v0.27.0/resources/dynamodb.aws.upbound.io/Table/v1beta1) -for a `Table` resource. -{{< /hint >}} - -The _AWS Provider_ defines the -{{}}apiVersion{{}} -and -{{}}kind{{}}. - -DynamoDB instances require a -{{}}region{{}}, -{{}}writeCapacity{{}} -and -{{}}readCapacity{{}} -parameters. - -The {{}}attribute{{}} section creates -the database "Partition key" and "Hash key." - -This example creates a single key named -{{}}S3ID{{}} of type -{{}}S{{}} for "string" -```yaml {label="dynamoMR"} -apiVersion: dynamodb.aws.upbound.io/v1beta1 -kind: Table -metadata: - name: crossplane-quickstart-database -spec: - forProvider: - region: "us-east-2" - writeCapacity: 1 - readCapacity: 1 - attribute: - - name: S3ID - type: S - hashKey: S3ID -``` - -{{< hint "note" >}} -DynamoDB specifics are beyond the scope of this guide. Read the -[DynamoDB Developer Guide](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Introduction.html) -for more information. -{{
}} - -### Create the composition object -The _composition_ combines the two resource definitions. - -A -{{}}Composition{{}} comes from the -{{}}Crossplane{{}} -API resources. - -Create any {{}}name{{}} for this _composition_. - -```yaml {label="compName"} -apiVersion: apiextensions.crossplane.io/v1 -kind: Composition -metadata: - name: dynamodb-with-bucket -``` - -Add the resources to the -{{}}spec.resources{{}} -section of the _composition_. - -Give each resource a -{{}}name{{}} -and put the resource definition under the -{{}}base{{}} -key. - -```yaml {label="specResources"} -apiVersion: apiextensions.crossplane.io/v1 -kind: Composition -metadata: - name: dynamodb-with-bucket -spec: - resources: - - name: s3-bucket - base: - apiVersion: s3.aws.upbound.io/v1beta1 - kind: Bucket - spec: - forProvider: - region: "us-east-2" - providerConfigRef: - name: default - - name: dynamodb - base: - apiVersion: dynamodb.aws.upbound.io/v1beta1 - kind: Table - spec: - forProvider: - region: "us-east-2" - writeCapacity: 1 - readCapacity: 1 - attribute: - - name: S3ID - type: S - hashKey: S3ID -``` - -_Compositions_ are a template for generating resources. A _composite -resource_ actually creates the resources. - -A _composition_ defines what _composite resources_ can use this -template. - -_Compositions_ do this with the -{{}}spec.compositeTypeRef{{}} -definition. - -{{< hint "tip" >}} -Crossplane recommends prefacing the `kind` with an `X` to show it's a Composition. -{{< /hint >}} - -```yaml {label="compRef"} -apiVersion: apiextensions.crossplane.io/v1 -kind: Composition -metadata: - name: dynamodb-with-bucket -spec: - compositeTypeRef: - apiVersion: custom-api.example.org/v1alpha1 - kind: XDatabase - resources: - # Removed for Brevity -``` - -A _composite resource_ is actually a custom Kubernetes API type you define. The -platform team controls the kind, API endpoint and version. - - - -With this {{}}spec.compositeTypeRef{{}} -Crossplane only allows _composite resources_ from the API group -{{}}custom-api.example.org{{}} -that are of -{{}}kind: XDatabase{{}} -to use this template to create resources. - - -### Apply the composition -Apply the full _Composition_ to your Kubernetes cluster. - -```yaml -cat <}} -_Composite resource definitions_ are also called `XRDs` for short. -{{< /hint >}} - -Just like a _composition_ the -{{}}composite resource definition{{}} -is part of the -{{}}Crossplane{{}} -API group. - -The _XRD_ {{}}name{{}} is the new -API endpoint. - -{{< hint "tip" >}} -Crossplane recommends using a plural name for the _XRD_ -{{}}name{{}}. -{{< /hint >}} - -```yaml {label="xrdName"} -apiVersion: apiextensions.crossplane.io/v1 -kind: CompositeResourceDefinition -metadata: - name: xdatabases.custom-api.example.org -``` - -The _XRD's_ -{{}}spec{{}} defines the new custom -API. - -### Define the API endpoint and kind -First, define the new API -{{}}group{{}}. -Next, create the API {{}}kind{{}} and -{{}}plural{{}}. - -```yaml {label="xrdGroup"} -apiVersion: apiextensions.crossplane.io/v1 -kind: CompositeResourceDefinition -metadata: - name: xdatabases.custom-api.example.org -spec: - group: custom-api.example.org - names: - kind: XDatabase - plural: xdatabases -``` - -{{}} -The _XRD_ {{}}group{{}} matches the _composition_ {{}}apiVersion{{}} and the -_XRD_ {{}}kind{{}} matches the _composition_ -{{}}compositeTypeRef.kind{{}}. - -```yaml {label="noteComp"} -kind: Composition -# Removed for brevity -spec: - compositeTypeRef: - apiVersion: custom-api.example.org/v1alpha1 - kind: XDatabase -``` -{{< /hint >}} - -### Set the API version -In Kubernetes, all API endpoints have a version to show the stability of the API -and track revisions. - -Apply a version to the _XRD_ with a -{{}}versions.name{{}}. -This matches the -{{}}compositeTypeRef.apiVersion{{}} - -_XRDs_ require both -{{}}versions.served{{}} -and -{{}}versions.referenceable{{}}. - -```yaml {label="xrdVersion"} -apiVersion: apiextensions.crossplane.io/v1 -kind: CompositeResourceDefinition -metadata: - name: xdatabases.custom-api.example.org -spec: - group: custom-api.example.org - names: - kind: XDatabase - plural: xdatabases - versions: - - name: v1alpha1 - served: true - referenceable: true -``` - -{{}} -For more information on defining versions in Kubernetes read the -[API versioning](https://kubernetes.io/docs/reference/using-api/#api-versioning) section of the Kubernetes documentation. -{{< /hint >}} - -### Create the API schema -With an API endpoint named, now define the API schema, or what's allowed -inside the `spec` of the new Kubernetes object. - -{{< hint "note" >}} -_XRDs_ follow the Kubernetes -[_custom resource definition_ rules for schemas](https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#specifying-a-structural-schema). -{{}} - -Place the API -{{< hover label="xrdSchema" line="8" >}}schema{{}} -under the -{{< hover label="xrdSchema" line="7" >}}version.name{{}} - -The _XRD_ type defines the next lines. They're always the same. - - - -{{< hover label="xrdSchema" line="9" >}}openAPIV3Schema{{}} specifies -how the schema gets validated. - - -Next, the entire API is an -{{< hover label="xrdSchema" line="10" >}}object{{}} -with a -{{< hover label="xrdSchema" line="11" >}}property{{}} of -{{< hover label="xrdSchema" line="12" >}}spec{{}}. - -The -{{< hover label="xrdSchema" line="12" >}}spec{{}} is also an -{{< hover label="xrdSchema" line="13" >}}object{{}} with -{{< hover label="xrdSchema" line="14" >}}properties{{}}. - -```yaml {label="xrdSchema"} -apiVersion: apiextensions.crossplane.io/v1 -kind: CompositeResourceDefinition -# Removed for brevity -spec: - # Removed for brevity - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - type: object - properties: - spec: - type: object - properties: -``` - -{{< hint "tip" >}} -For more information on the values allowed in a _composite resource definition_ view its schema with -`kubectl explain xrd` -{{< /hint >}} - -Now, define the custom API. Your custom API continues under the last -{{}}properties{{}} definition in the -previous example. - -This custom API has only one setting: - -* {{}}region{{}} - where to deploy -the resources, a choice of "EU" or "US" - - -Users can't change any other settings of the S3 bucket or DynamoDB instance. - -The{{}}region{{}} -is a {{}}string{{}} -and can match the regular expression that's -{{}}oneOf{{}} -{{}}EU{{}} -or -{{}}US{{}}. - -This API requires the setting -{{}}region{{}}. - - -```yaml {label="customAPI"} -# Removed for brevity -# schema.openAPIV3Schema.type.properties.spec -properties: - region: - type: string - oneOf: - - pattern: '^EU$' - - pattern: '^US$' -required: - - region -``` - -### Enable claims to the API -Tell this _XRD_ to offer a _claim_ by defining the _claim_ API endpoint under -the _XRD_ {{}}spec{{< /hover >}}. - -{{< hint "tip" >}} -Crossplane recommends a _Claim_ {{}}kind{{}} match the _Composite Resource_ (XR) -{{}}kind{{}}, -without the preceding `X`. -{{< /hint >}} - - -```yaml {label="XRDclaim"} -apiVersion: apiextensions.crossplane.io/v1 -kind: CompositeResourceDefinition -# Removed for brevity -spec: -# Removed for brevity - names: - kind: XDatabase - plural: xdatabases - claimNames: - kind: Database - plural: databases -``` - -{{}} -The [Claims](#create-a-claim) section later in this guide discusses _claims_. -{{< /hint >}} - -### Apply the composite resource definition -Apply the complete _XRD_ to your Kubernetes cluster. - - -```yaml -cat <}}group{{}} -becomes the _composite resource_ -{{}}apiVersion{{}}. - -The _XRD_ {{}}kind{{}} -is the _composite resource_ -{{}}kind{{}} - -The _XRD_ API {{}}spec{{}} defines the -_composite resource_ {{}}spec{{}}. - -The _XRD_ {{}}properties{{}} section -defines the options for the _composite resource_ -{{}}spec{{}}. - -The one option is {{}}region{{}} and it -can be either {{}}EU{{}} or -{{}}US{{}}. - -This _composite resource_ uses -{{}}region: US{{}}. - -### Apply the composite resource - -Apply the composite resource to the Kubernetes cluster. - -```yaml {label="xr"} -cat <}} -Use `kubectl get ` to view a specific `kind` of _composite resource_. -View all _composite resources_ with `kubectl get composite`. -{{< /hint >}} - -```shell {copy-lines="1"} -kubectl get xdatabase -NAME SYNCED READY COMPOSITION AGE -my-composite-resource True True dynamo-with-bucket 31s -``` - -Both `SYNCED` and `READY` are `True` when Crossplane created the AWS resources. - -Now look at the S3 `bucket` and DynmoDB `table` _managed resources_ with -`kubectl get bucket` and `kubectl get table`. - -{{< hint "important" >}} -This guide uses Upbound AWS provider v0.27.0. AWS Provider v0.30.0 and later -requires the full CRD name `bucket.s3.aws.upbound.io` instead of `buckets`. -{{
}} - -```shell {copy-lines="1"} -kubectl get bucket -NAME READY SYNCED EXTERNAL-NAME AGE -my-composite-resource-8b6tx True True my-composite-resource-8b6tx 56s -``` - -```shell {copy-lines="1"} -kubectl get table -NAME READY SYNCED EXTERNAL-NAME AGE -my-composite-resource-m6vk6 True True my-composite-resource-m6vk6 59s -``` - -The _composite resource_ automatically generated both _managed resources_. - -Using `kubectl describe` on a _managed resource_ shows the `Owner References` is -the _composite resource_. - -```yaml {copy-lines="1"} -kubectl describe bucket | grep "Owner References" -A5 - Owner References: - API Version: custom-api.example.org/v1alpha1 - Block Owner Deletion: true - Controller: true - Kind: XDatabase - Name: my-composite-resource -``` - -Each _composite resource_ creates and owns a unique set of _managed resources_. -If you create a second _composite resource_ Crossplane creates a new S3 `bucket` -and DynamoDB `table`. - -```yaml {label="xr"} -cat <}} -Delete a specific _composite resource_ with `kubectl delete ` or -`kubectl delete composite`. -{{< /hint >}} - -Delete the second composition -```shell -kubectl delete xdatabase my-second-composite-resource -``` - -{{}} -There may a delay in deleting the _managed resources_. Crossplane is making API -calls to AWS and waits for AWS to confirm they deleted the resources before -updating the state in Kubernetes. -{{}} - -Now only one bucket and table exist. - -```shell {copy-lines="1"} -kubectl get bucket -NAME READY SYNCED EXTERNAL-NAME AGE -my-composite-resource-8b6tx True True my-composite-resource-8b6tx 7m34s -``` - -```shell {copy-lines="1"} -kubectl get table -NAME READY SYNCED EXTERNAL-NAME AGE -my-composite-resource-m6vk6 True True my-composite-resource-m6vk6 7m37s -``` - -Delete the other _composite resource_ to remove the last `bucket` and `table` -_managed resources_. - -```shell -kubectl delete xdatabase my-composite-resource -``` - -_Composite resources_ are great for creating one or more related resources against -a template, but all _composite resources_ exist at the Kubernetes "cluster -level." There's no isolation between _composite resources_. Crossplane uses -_claims_ to create resources with namespace isolation. - -## Create a claim - -_Claims_, just like _composite resources_ use the custom API defined in the -_XRD_. Unlike a _composite resource_, Crossplane can create _claims_ in a -namespace. - -### Create a new Kubernetes namespace -Create a new namespace with `kubectl create namespace`. - -```shell -kubectl create namespace test -``` - -Look at the _XRD_ to see the parameters for the _claim_. -A _claim_ uses the same {{}}group{{}} -a _composite resource_ uses but a different -{{}}kind{{}}. - -```yaml {label="XRDclaim2"} -apiVersion: apiextensions.crossplane.io/v1 -kind: CompositeResourceDefinition -# Removed for brevity -spec: -# Removed for brevity - group: custom-api.example.org - claimNames: - kind: Database - plural: databases -``` - -Like the _composite resource_, create a new object with the -{{}}custom-api.example.org{{}} API -endpoint. - -The _XRD_ -{{}}claimNames.kind{{}} defines the -{{}}kind{{}}. - -The {{}}spec{{}} uses the same -API options as the _composite resource_. - -### Apply the claim -Apply the _claim_ to your Kubernetes cluster. - -```yaml {label="claim"} -cat <}} -View claims with `kubectl get ` or use `kubectl get claim` to view all -_claims_. -{{
}} - -```shell {copy-lines="1"} -kubectl get database -n test -NAME SYNCED READY CONNECTION-SECRET AGE -claimed-database True True 35s -``` - -When Crossplane creates a _claim_, a unique _composite resource_ is also -created. View the new _composite resource_ with `kubectl get xdatabase`. - -```shell {copy-lines="1"} -kubectl get xdatabase -NAME SYNCED READY COMPOSITION AGE -claimed-database-6xsgq True True dynamo-with-bucket 46s -``` - -The _composite resource_ exists at the "cluster scope" while the _claim_ exists -at the "namespace scope." - -Create a second namespace and a second claim. - -```shell -kubectl create namespace test2 -cat <}}) of this guide covers _composition -patches_ and making all this configuration portable in Crossplane _packages_. - -## Next steps -* **[Continue to part 3]({{< ref "provider-aws-part-3">}})** to create a learn - about _patching_ resources and creating Crossplane _packages_. -* Explore AWS resources that Crossplane can configure in the [Provider CRD reference](https://marketplace.upbound.io/providers/upbound/provider-family-aws/). -* Join the [Crossplane Slack](https://slack.crossplane.io/) and connect with Crossplane users and contributors. \ No newline at end of file diff --git a/content/v1.11/getting-started/provider-aws-part-3.md b/content/v1.11/getting-started/provider-aws-part-3.md deleted file mode 100644 index 12d68896a..000000000 --- a/content/v1.11/getting-started/provider-aws-part-3.md +++ /dev/null @@ -1,639 +0,0 @@ ---- -title: AWS Quickstart Part 3 -weight: 120 -tocHidden: true ---- - -{{< hint "important" >}} -This guide is part 3 of a series. - -Follow **[part 1]({{}})** -to install Crossplane and connect your Kubernetes cluster to AWS. - -Follow **[part 2]({{}})** to create a _composition_, -_custom resource definition_ and a _claim_. -{{< /hint >}} - -[Part 2]({{}}) created a _composite resource -definition_ to define the schema of the custom API. Users create a _claim_ to -use the custom API and apply their options. Part 2 didn't show how the options -set in a _claim_ change or get applied the associated _composite resources_. - -## Prerequisites -* Complete quickstart [part 1]({{}}) and [Part 2]({{}}) to install Crossplane and the quickstart - configurations. - -{{}} -1. Add the Crossplane Helm repository and install Crossplane -```shell -helm repo add \ -crossplane-stable https://charts.crossplane.io/stable -helm repo update -&& -helm install crossplane \ -crossplane-stable/crossplane \ ---namespace crossplane-system \ ---create-namespace -``` - -2. When the Crossplane pods finish installing and are ready, apply the AWS Provider - -```yaml {label="provider",copy-lines="all"} -cat <}} -```ini {copy-lines="all"} -[default] -aws_access_key_id = $@$@ -aws_secret_access_key = $@$@ -``` -{{}} - -4. Create a Kubernetes secret from the AWS keys -```shell {label="kube-create-secret",copy-lines="all"} -kubectl create secret \ -generic aws-secret \ --n crossplane-system \ ---from-file=creds=./aws-credentials.txt -``` - -5. Create a _ProviderConfig_ -```yaml {label="providerconfig",copy-lines="all"} -cat <}} - -## Enable composition patches -In a _composition_ `patches` map fields in the custom API to fields inside the -_managed resources_. - -The example _composition_ has two _managed resources_, a -{{}}bucket{{}} and a -{{}}table{{}}. - -```yaml {label="compResources"} -apiVersion: apiextensions.crossplane.io/v1 -kind: Composition -# Removed for Brevity -resources: - - name: s3-bucket - base: - apiVersion: s3.aws.upbound.io/v1beta1 - kind: Bucket - spec: - forProvider: - region: "us-east-2" - - name: dynamodb - base: - apiVersion: dynamodb.aws.upbound.io/v1beta1 - kind: Table - spec: - forProvider: - region: "us-east-2" - writeCapacity: 1 - readCapacity: 1 - attribute: - - name: S3ID - type: S - hashKey: S3ID -``` - -The custom API defined a single option, -{{}}region{{}}. A -{{}}region{{}} can be either -{{}}EU{{}} or -{{}}US{{}}. - - -```yaml {label="xrdSnip"} -apiVersion: apiextensions.crossplane.io/v1 -kind: CompositeResourceDefinition -# Removed for brevity -spec: - group: custom-api.example.org - names: - kind: XDatabase -# Removed for brevity - spec: - type: object - properties: - region: - type: string - oneOf: - - pattern: '^EU$' - - pattern: '^US$' -``` - -Creating a _composition_ `patch` allows Crossplane to update the settings of the -_composite resource_. Patches apply to the individual _managed resources_ -inside the _composition_. - -A {{}}patch{{}} has a -{{}}fromField{{}} and a -{{}}toField{{}} specifying which value -_from_ the custom API should apply _to_ the _managed resource_. -Patches can create a -{{}}transform{{}} to change the _from_ -field before it's applied. - -The transform -{{}}type{{}} is what kind of change to -make on the _from_ field. Types of changes could include appending a string, -preforming a math operation or mapping one value to another. - -Applying a {{}}patch{{}} to the -{{}}Bucket{{}} uses the custom API -{{}}region{{}} to use as the _managed resource_ -{{}}region{{}}. - - -The custom API value "EU" is -{{}}mapped{{}} to the value "eu-north-1" -and "US" is {{}}mapped{{}} to the value -"us-east-2." - - - -```yaml {label="patch"} -apiVersion: apiextensions.crossplane.io/v1 -kind: Composition -# Removed for Brevity -resources: - - name: s3-bucket - base: - apiVersion: s3.aws.upbound.io/v1beta1 - kind: Bucket - spec: - forProvider: - region: "us-east-2" - patches: - - fromFieldPath: "region" - toFieldPath: "spec.forProvider.region" - transforms: - - type: map - map: - EU: "eu-north-1" - US: "us-east-2" -``` - -Patching is a powerful tool enabling simpler or abstracted APIs. A developer -isn't required to know the specific AWS region identifier, only the abstracted -option of "EU" or "US." - - -### Apply the updated composition -Apply the same `patch` to the `Table` _managed resource_ and apply the updated -_composition_. - -```yaml -cat <}}region{{}} to "EU." - -```yaml {label="claim"} -cat < -Using {{}}region: "EU"{{}} patches the -_composite resource_, updating the AWS region from `us-east-2` to `eu-north-1`. -The developer creating the claim isn't required to know which specific AWS -region or the naming conventions. Using the abstract API options of "EU" or "US" -the developer places their resources in the desired location. - - -Deleting the claim removes the _managed resources_. - -{{}} -The _managed resources_ take up to 5 minutes to delete. -{{< /hint >}} - -```shell -kubectl delete database claimed-eu-database -n test -``` - -## Create a Crossplane configuration package - -Crossplane _configuration packages_ allow users to combine their _custom -resource definition_ and _composition_ files into an OCI image. - -{{< hint "note" >}} -The [Open Container Initiative](https://opencontainers.org/faq/) -defines the OCI image standard. -An OCI images is a standard way to package data. -{{< /hint >}} - -You can host configuration packages in image registries like -[Docker Hub](https://hub.docker.com/) or the -[Upbound Marketplace](https://marketplace.upbound.io/). - -Crossplane can download and install configuration packages into a Kubernetes -cluster. - -Creating a configuration package makes your Crossplane custom APIs portable -and versioned. - -Building and installing configuration packages requires an OCI image compatible -tool. - -{{< hint "note" >}} -You can use any software that builds OCI images. This includes -[Docker](https://www.docker.com/) or -[Upbound's Up CLI)](https://github.com/upbound/up). -{{< /hint >}} - -A configuration package includes three files: -* `crossplane.yaml` defines the metadata of the package. -* `definition.yaml` is the _composite resource definition_ for the package. -* `composition.yaml` is the _composition_ template for the package. - - - -### Create a crossplane.yaml file - -Configuration packages describe their contents and requirements with a -`crossplane.yaml` file. - -The `crossplane.yaml` file lists the required Crossplane _providers_ and their -compatible versions as well as the required Crossplane version. - -The Crossplane -{{}}meta.pkg{{}} API defines the schema -for a -{{}}Configuration{{}}. - -Inside the {{}}spec{{}} define the -required Crossplane -{{}}version{{}}. - -The {{}}dependsOn{{}} section lists the -dependencies for a package. - -This package lists the Upbound -{{}}provider-aws{{}} -version {{}}0.27.0{{}} or later as a -dependency. - -{{}} -Crossplane automatically installs dependencies. Dependencies can include other -configuration packages. -{{< /hint >}} - -```yaml {label="xpyaml"} -apiVersion: meta.pkg.crossplane.io/v1 -kind: Configuration -metadata: - name: crossplane-aws-quickstart -spec: - crossplane: - version: ">=v1.11.0" - dependsOn: - - provider: xpkg.upbound.io/upbound/provider-aws - version: ">=v0.27.0" -``` - -Create a new directory and save the `crossplane.yaml` file. - -```yaml -mkdir crossplane-aws-quickstart -cat < crossplane-aws-quickstart/crossplane.yaml -apiVersion: meta.pkg.crossplane.io/v1 -kind: Configuration -metadata: - name: crossplane-aws-quickstart -spec: - crossplane: - version: ">=v1.11.0" - dependsOn: - - provider: xpkg.upbound.io/upbound/provider-aws - version: ">=v0.27.0" -EOF -``` - - - -### Create a definition.yaml file - - -A configuration package requires a _composite resource definition_ (XRD) to define the -custom API. - -Save the _XRD_ as `definition.yaml` in the same directory as the -`crossplane.yaml` file. - -```yaml -cat < crossplane-aws-quickstart/definition.yaml -apiVersion: apiextensions.crossplane.io/v1 -kind: CompositeResourceDefinition -metadata: - name: xdatabases.custom-api.example.org -spec: - group: custom-api.example.org - names: - kind: XDatabase - plural: xdatabases - versions: - - name: v1alpha1 - served: true - referenceable: true - schema: - openAPIV3Schema: - type: object - properties: - spec: - type: object - properties: - region: - type: string - oneOf: - - pattern: '^EU$' - - pattern: '^US$' - required: - - region - claimNames: - kind: Database - plural: databases -EOF -``` - - - -### Create a composition.yaml file - - -The _composition_ template creates the _managed resources_ and allows _patches_ -to customize the _managed resources_. - -Copy the _composition_ into the `composition.yaml` file in the same directory as -`crossplane.yaml`. - -```yaml -cat < crossplane-aws-quickstart/composition.yaml -apiVersion: apiextensions.crossplane.io/v1 -kind: Composition -metadata: - name: dynamodb-with-bucket -spec: - compositeTypeRef: - apiVersion: custom-api.example.org/v1alpha1 - kind: XDatabase - resources: - - name: s3-bucket - base: - apiVersion: s3.aws.upbound.io/v1beta1 - kind: Bucket - spec: - providerConfigRef: - name: default - patches: - - fromFieldPath: "spec.region" - toFieldPath: "spec.forProvider.region" - transforms: - - type: map - map: - EU: "eu-north-1" - US: "us-east-1" - - name: dynamodb - base: - apiVersion: dynamodb.aws.upbound.io/v1beta1 - kind: Table - spec: - forProvider: - writeCapacity: 1 - readCapacity: 1 - attribute: - - name: S3ID - type: S - hashKey: S3ID - patches: - - fromFieldPath: "spec.region" - toFieldPath: "spec.forProvider.region" - transforms: - - type: map - map: - EU: "eu-north-1" - US: "us-east-1" -EOF -``` - -### Install the Crossplane command-line -To build a configuration package install the Crossplane Kubernetes command-line -extension. - -```shell -wget "https://raw.githubusercontent.com/crossplane/crossplane/master/install.sh" -chmod +x install.sh -./install.sh -sudo mv crossplane /usr/local/bin -``` - -Verify the Crossplane command-line installed with `crossplane --help` - -```shell -crossplane --help -Usage: crossplane - -A command line tool for interacting with Crossplane. - -Flags: - -h, --help Show context-sensitive help. - -v, --version Print version and quit. - --verbose Print verbose logging statements. -# Ouptut removed for brevity -``` - -### Build a configuration package - -Use the `crossplane` CLI to create an `.xpkg` file containing the -custom APIs and Crossplane configuration. - -```shell -crossplane build configuration -f crossplane-aws-quickstart/ --name="crossplane-aws-quickstart" -``` - -Now an `.xpkg` OCI image is inside the `crossplane-aws-quickstart` directory. - -```shell -ls crossplane-aws-quickstart/ -composition.yaml crossplane-aws-quickstart.xpkg crossplane.yaml definition.yaml -``` - -## Next steps -* Explore AWS resources that Crossplane can configure in the [Provider CRD reference](https://marketplace.upbound.io/providers/upbound/provider-family-aws/). -* Join the [Crossplane Slack](https://slack.crossplane.io/) and connect with Crossplane users and contributors. -* Read more about [Crossplane concepts]({{}}) \ No newline at end of file diff --git a/content/v1.11/getting-started/provider-azure-part-2.md b/content/v1.11/getting-started/provider-azure-part-2.md deleted file mode 100644 index ea8446d89..000000000 --- a/content/v1.11/getting-started/provider-azure-part-2.md +++ /dev/null @@ -1,1056 +0,0 @@ ---- -title: Azure Quickstart Part 2 -weight: 120 -tocHidden: true ---- - -{{< hint "important" >}} -This guide is part 2 of a series. Follow **[part 1]({{}})** -to install Crossplane and connect your Kubernetes cluster to Azure. - -**[Part 3]({{}})** covers patching _CompositeResources_ -and using Crossplane _Packages_. -{{< /hint >}} - -This section creates a _[Composition](#create-a-composition)_, -_[CompositeResourceDefinition](#define-a-composite-resource)_ and a -_[Claim](#create-a-claim)_ -to create a custom Kubernetes API to create Azure resources. This custom API -is a _composite resource_ (XR) API. - -## Prerequisites -* Complete [quickstart part 1]({{}}) connecting - Kubernetes to Azure. -* an Azure account with permissions to create an Azure Virtual Machine and - Virtual Networking - -{{}} -1. Add the Crossplane Helm repository and install Crossplane -```shell -helm repo add \ -crossplane-stable https://charts.crossplane.io/stable -helm repo update -&& -helm install crossplane \ -crossplane-stable/crossplane \ ---namespace crossplane-system \ ---create-namespace -``` - -2. When the Crossplane pods finish installing and are ready, apply the Azure - Provider - -```yaml {label="provider",copy-lines="all"} -cat <}} -```console -az ad sp create-for-rbac \ ---sdk-auth \ ---role Owner \ ---scopes /subscriptions/$$$$ -``` -{{}} - -4. Create a Kubernetes secret from the Azure JSON file. -```shell {label="kube-create-secret",copy-lines="all"} -kubectl create secret \ -generic azure-secret \ --n crossplane-system \ ---from-file=creds=./azure-credentials.json -``` - -5. Create a _ProviderConfig_ -```yaml {label="providerconfig",copy-lines="all"} -cat <}} - -## Create a composition -[Part 1]({{}}) created a single _managed resource_. -A _Composition_ is a template to create one or more _managed resource_ at the -same time. - -This sample _composition_ creates an Linux Virtual Machine and the required -networking components. - -Compositions have multiple components: -* The individual managed resources. -* The Composition kind and version. -* A Composite type reference. - -The following steps describe each of these components before -[applying the final Composition](#apply-the-composition). - -### Define a virtual network -Define a `virtualnetwork` resource using the configuration from the previous -section: - -{{< hint "note" >}} -Don't apply this configuration. This YAML is part of a larger -definition. -{{< /hint >}} - -```yaml {copy-lines="none"} -apiVersion: network.azure.upbound.io/v1beta1 -kind: VirtualNetwork -metadata: - name: crossplane-quickstart-network -spec: - forProvider: - addressSpace: - - 10.0.0.0/16 - location: "Central US" - resourceGroupName: -``` - -### Define a subnet resource -Next, define a `Subnet` resource. - -{{< hint "note" >}} -Don't apply this configuration. This YAML is part of a larger -definition. -{{< /hint >}} - -```yaml {label="subnet",copy-lines="none"} -apiVersion: network.azure.upbound.io/v1beta1 -kind: Subnet -metadata: - name: crossplane-quickstart-subnet -spec: - forProvider: - addressPrefixes: - - 10.0.1.0/24 - resourceGroupName: -``` - -### Define a network interface -Define a network interface to attach to the virtual machine. - -{{< hint "note" >}} -Don't apply this configuration. This YAML is part of a larger -definition. -{{< /hint >}} - -```yaml {label="nic",copy-lines="none"} -apiVersion: network.azure.upbound.io/v1beta1 -kind: NetworkInterface -metadata: - name: crossplane-quickstart-nic -spec: - forProvider: - ipConfiguration: - - name: crossplane-quickstart-configuration - privateIpAddressAllocation: Dynamic - location: "Central US" - resourceGroupName: -``` - -### Define a virtual machine -Define the `LinuxVirtualMachine` with its settings. - -{{< hint "note" >}} -Don't apply this configuration. This YAML is part of a larger -definition. -{{< /hint >}} - -```yaml {label="vm",copy-lines="none"} -apiVersion: compute.azure.upbound.io/v1beta1 -kind: LinuxVirtualMachine -metadata: - name: crossplane-quickstart-vm -spec: - forProvider: - adminUsername: adminuser - adminSshKey: - - publicKey: ssh-rsa - AAAAB3NzaC1yc2EAAAADAQABAAABAQC+wWK73dCr+jgQOAxNsHAnNNNMEMWOHYEccp6wJm2gotpr9katuF/ZAdou5AaW1C61slRkHRkpRRX9FA9CYBiitZgvCCz+3nWNN7l/Up54Zps/pHWGZLHNJZRYyAB6j5yVLMVHIHriY49d/GZTZVNB8GoJv9Gakwc/fuEZYYl4YDFiGMBP///TzlI4jhiJzjKnEvqPFki5p2ZRJqcbCiF4pJrxUQR/RXqVFQdbRLZgYfJ8xGB878RENq3yQ39d8dVOkq4edbkzwcUmwwwkYVPIoDGsYLaRHnG+To7FvMeyO7xDVQkMKzopTQV8AuKpyvpqu0a9pWOMaiCyDytO7GGN - example@docs.crossplane.io - username: adminuser - location: "Central US" - osDisk: - - caching: ReadWrite - storageAccountType: Standard_LRS - size: Standard_B1ms - sourceImageReference: - - offer: debian-11 - publisher: Debian - sku: 11-backports-gen2 - version: latest - resourceGroupName: -``` - -### Create the composition object -The _Composition_ combines all the managed resources into a single object. - -A -{{}}Composition{{}} comes from the -{{}}Crossplane{{}} -API resources. - -Create any {{}}name{{}} for this _Composition_. - -```yaml {label="compName",copy-lines="none"} -apiVersion: apiextensions.crossplane.io/v1 -kind: Composition -metadata: - name: crossplane-quickstart-vm-with-network -``` - -Add all the defined resources to the -{{}}spec.resources{{}} -section of the _Composition_. - -Give each resource a -{{}}name{{}} -and put the resource definition under the -{{}}base{{}} -key. - -Add your {{}}resourceGroupName{{< /hover >}} -for each resource in the Composition. - -{{}} -The contents of the -{{}}base{{}} key -doesn't include the `metadata` field from the managed resources. -{{< /hint >}} - -```yaml {label="specResources",copy-lines="none"} -apiVersion: apiextensions.crossplane.io/v1 -kind: Composition -metadata: - name: crossplane-quickstart-vm-with-network -spec: - resources: - - name: quickstart-subnet - base: - apiVersion: network.azure.upbound.io/v1beta1 - kind: Subnet - spec: - forProvider: - addressPrefixes: - - 10.0.1.0/24 - virtualNetworkNameSelector: - matchControllerRef: true - resourceGroupName: -# Removed for brevity -``` - -{{}} -Crossplane provides the -{{}}matchControllerRef{{}} value -to automatically link resources created by the same _Composition_. -{{}} - -_Compositions_ are a template for generating resources. A _composite -resource_ actually creates the resources. - -A _Composition_ defines what _composite resources_ can use this -template. - -_Compositions_ do this with the -{{}}spec.compositeTypeRef{{}} -definition. - -{{< hint "tip" >}} -Crossplane recommends prefacing the `kind` with an `X` to show it's a Composition. -{{< /hint >}} - -```yaml {label="compRef",copy-lines="none"} -apiVersion: apiextensions.crossplane.io/v1 -kind: Composition -metadata: - name: crossplane-quickstart-vm-with-network -spec: - compositeTypeRef: - apiVersion: custom-api.example.org/v1alpha1 - kind: XVirtualMachine - resources: - # Removed for Brevity -``` - -A _composite resource_ is actually a custom Kubernetes API type you define. The -platform team controls the kind, API endpoint and version. - - - -With this {{}}spec.compositeTypeRef{{}} -Crossplane only allows _composite resources_ from the API group -{{}}custom-api.example.org{{}} -that are of -{{}}kind: XVirtualMachine{{}} -to use this template to create resources. - - -### Apply the composition -Apply the full _Composition_ to your Kubernetes cluster. - -{{}} -Add your {{}}resourceGroupName{{}} to -each resource. -{{< /hint >}} - -{{< editCode >}} -```yaml {label="fullComp"} -cat <$$ - size: Standard_B1ms - sourceImageReference: - - offer: debian-11 - publisher: Debian - sku: 11-backports-gen2 - version: latest - networkInterfaceIdsSelector: - matchControllerRef: true - - name: quickstart-nic - base: - apiVersion: network.azure.upbound.io/v1beta1 - kind: NetworkInterface - spec: - forProvider: - ipConfiguration: - - name: crossplane-quickstart-configuration - privateIpAddressAllocation: Dynamic - subnetIdSelector: - matchControllerRef: true - location: "Central US" - resourceGroupName: $$$$ - - name: quickstart-subnet - base: - apiVersion: network.azure.upbound.io/v1beta1 - kind: Subnet - spec: - forProvider: - addressPrefixes: - - 10.0.1.0/24 - virtualNetworkNameSelector: - matchControllerRef: true - resourceGroupName: $$$$ - - name: quickstart-network - base: - apiVersion: network.azure.upbound.io/v1beta1 - kind: VirtualNetwork - spec: - forProvider: - addressSpace: - - 10.0.0.0/16 - location: "Central US" - resourceGroupName: $$$$ -EOF -``` -{{< /editCode >}} - -Confirm the _Composition_ exists with `kubectl get composition` - -```shell {copy-lines="1"} -kubectl get composition -NAME XR-KIND XR-APIVERSION AGE -crossplane-quickstart-vm-with-network XVirtualMachine custom-api.example.org/v1alpha1 5s -``` - -Again, the _Composition_ is only a template. At this point, Crossplane hasn't -created any resources inside of Azure. - -## Define a composite resource - -The _Composition_ that was just created limited which _composite resources_ can -use that template. - -A _composite resource_ is a custom API defined by the platform teams. -A _CompositeResourceDefinition_ defines the schema for a _composite resource_. - - -A _CompositeResourceDefinition_ installs the custom API type into Kubernetes -and defines what `spec` keys and values are valid when calling this new custom API. - -Before creating a _composite resource_ Crossplane requires a _CompositeResourceDefinition_. - -{{< hint "tip" >}} -_CompositeResourceDefinitions_ are also called `XRDs` for short. -{{< /hint >}} - -Just like a _Composition_ the -{{}}CompositeResourceDefinition{{}} -is part of the -{{}}Crossplane{{}} -API group. - -The _XRD_ {{}}name{{}} is the new -API endpoint. - -{{< hint "tip" >}} -Crossplane recommends using a plural name for the _XRD_ -{{}}name{{}}. -{{< /hint >}} - -```yaml {label="xrdName",copy-lines="none"} -apiVersion: apiextensions.crossplane.io/v1 -kind: CompositeResourceDefinition -metadata: - name: xvirtualmachines.custom-api.example.org -``` - -The _XRD's_ -{{}}spec{{}} defines the new custom -API. - -### Define the API endpoint and kind -First, define the new API -{{}}group{{}}. -Next, create the API {{}}kind{{}} and -{{}}plural{{}}. - -```yaml {label="xrdGroup",copy-lines="none"} -apiVersion: apiextensions.crossplane.io/v1 -kind: CompositeResourceDefinition -metadata: - name: xvirtualmachines.custom-api.example.org -spec: - group: custom-api.example.org - names: - kind: XVirtualMachine - plural: xvirtualmachines -``` - -{{}} -The _XRD_ {{}}group{{}} matches the _composition_ {{}}apiVersion{{}} and the -_XRD_ {{}}kind{{}} matches the _composition_ -{{}}compositeTypeRef.kind{{}}. - -```yaml {label="noteComp",copy-lines="none"} -kind: Composition -# Removed for brevity -spec: - compositeTypeRef: - apiVersion: custom-api.example.org/v1alpha1 - kind: XVirtualMachine -``` -{{< /hint >}} - -### Set the API version -In Kubernetes, all API endpoints have a version to show the stability of the API -and track revisions. - -Apply a version to the _XRD_ with a -{{}}versions.name{{}}. -This matches the -{{}}compositeTypeRef.apiVersion{{}} - -_XRDs_ require both -{{}}versions.served{{}} -and -{{}}versions.referenceable{{}}. - -```yaml {label="xrdVersion",copy-lines="none"} -apiVersion: apiextensions.crossplane.io/v1 -kind: CompositeResourceDefinition -metadata: - name: xvirtualmachines.custom-api.example.org -spec: - group: custom-api.example.org - names: - kind: XVirtualMachine - plural: xvirtualmachines - versions: - - name: v1alpha1 - served: true - referenceable: true -``` - -{{}} -For more information on defining versions in Kubernetes read the -[API versioning](https://kubernetes.io/docs/reference/using-api/#api-versioning) section of the Kubernetes documentation. -{{< /hint >}} - -### Create the API schema -With an API endpoint named, now define the API schema, or what's allowed -inside the `spec` of the new Kubernetes object. - -{{< hint "note" >}} -_XRDs_ follow the Kubernetes -[_CustomResourceDefinition_ rules for schemas](https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#specifying-a-structural-schema). -{{}} - -Place the API -{{< hover label="xrdSchema" line="8" >}}schema{{}} -under the -{{< hover label="xrdSchema" line="7" >}}version.name{{}} - -The _XRD_ type defines the next lines. They're always the same. - - - -{{< hover label="xrdSchema" line="9" >}}openAPIV3Schema{{}} specifies -how the schema gets validated. - - -Next, the entire API is an -{{< hover label="xrdSchema" line="10" >}}object{{}} -with a -{{< hover label="xrdSchema" line="11" >}}property{{}} of -{{< hover label="xrdSchema" line="12" >}}spec{{}}. - -The -{{< hover label="xrdSchema" line="12" >}}spec{{}} is also an -{{< hover label="xrdSchema" line="13" >}}object{{}} with -{{< hover label="xrdSchema" line="14" >}}properties{{}}. - -```yaml {label="xrdSchema",copy-lines="none"} -apiVersion: apiextensions.crossplane.io/v1 -kind: CompositeResourceDefinition -# Removed for brevity -spec: - # Removed for brevity - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - type: object - properties: - spec: - type: object - properties: -``` - -{{< hint "tip" >}} -For more information on the values allowed in a _CompositeResourceDefinition_ view its schema with -`kubectl explain xrd` -{{< /hint >}} - -Now, define the custom API. Your custom API continues under the last -{{}}properties{{}} definition in the -previous example. - -This custom API has only one setting: - -* {{}}region{{}} - where to deploy -the resources, a choice of "EU" or "US" - -Users can't change any other settings of the VM or its network. - -The{{}}region{{}} -is a {{}}string{{}} -and can match the regular expression that's -{{}}oneOf{{}} -{{}}EU{{}} -or -{{}}US{{}}. - -This API requires the setting -{{}}region{{}}. - - -```yaml {label="customAPI",copy-lines="none"} -# Removed for brevity -# schema.openAPIV3Schema.type.properties.spec -properties: - region: - type: string - oneOf: - - pattern: '^EU$' - - pattern: '^US$' -required: - - region -``` - -### Enable claims to the API -Tell this _XRD_ to offer a _claim_ by defining the _claim_ API endpoint under -the _XRD_ {{}}spec{{< /hover >}}. - -{{< hint "tip" >}} -Crossplane recommends a _Claim_ {{}}kind{{}} match the _Composite Resource_ (XR) -{{}}kind{{}}, -without the preceding `X`. -{{< /hint >}} - - -```yaml {label="XRDclaim",copy-lines="none"} -apiVersion: apiextensions.crossplane.io/v1 -kind: CompositeResourceDefinition -# Removed for brevity -spec: -# Removed for brevity - names: - kind: XVirtualMachine - plural: xvirtualmachines - claimNames: - kind: VirtualMachine - plural: virtualmachines -``` - -{{}} -The [Claims](#create-a-claim) section later in this guide discusses _claims_. -{{< /hint >}} - -### Apply the CompositeResourceDefinition -Apply the complete _XRD_ to your Kubernetes cluster. - - -```yaml -cat <}}group{{}} -becomes the _composite resource_ -{{}}apiVersion{{}}. - -The _XRD_ {{}}kind{{}} -is the _composite resource_ -{{}}kind{{}} - -The _XRD_ API {{}}spec{{}} defines the -_composite resource_ {{}}spec{{}}. - -The _XRD_ {{}}properties{{}} section -defines the options for the _composite resource_ -{{}}spec{{}}. - -The one option is {{}}region{{}} and it -can be either {{}}EU{{}} or -{{}}US{{}}. - -This _composite resource_ uses -{{}}region: US{{}}. - -### Apply the composite resource - -Apply the composite resource to the Kubernetes cluster. - -```yaml {label="xr"} -cat <}} -It may take up to 10 minutes for Azure to create the Virtual Machine resources. -{{< /hint >}} - -```shell {copy-lines="1"} -kubectl get xvirtualmachine -NAME SYNCED READY COMPOSITION AGE -my-composite-resource True True crossplane-quickstart-vm-with-network 5m2s -``` - -{{}} -Use `kubectl get ` to view a specific `kind` of _composite resource_. -View all _composite resources_ with `kubectl get composite`. -{{< /hint >}} - - -Both `SYNCED` and `READY` are `True` when Crossplane created the Azure -resources. - -Now look at the `linuxvirtualmachine` and `networkinterface` -_managed resources_ with -`kubectl get linuxvirtualmachine` and `kubectl get networkinterface`. - -```shell {copy-lines="1"} -kubectl get linuxvirtualmachine -NAME READY SYNCED EXTERNAL-NAME AGE -my-composite-resource-w564c True True my-composite-resource-w564c 8m33s -``` - -```shell {copy-lines="1"} -kubectl get networkinterface -NAME READY SYNCED EXTERNAL-NAME AGE -my-composite-resource-72ft8 True True my-composite-resource-72ft8 8m54s -``` - -The _composite resource_ automatically generated the _managed resources_. - -Using `kubectl describe` on a _managed resource_ shows the `Owner References` is -the _composite resource_. - -```yaml {copy-lines="1"} - kubectl describe linuxvirtualmachine | grep "Owner References" -A5 - Owner References: - API Version: custom-api.example.org/v1alpha1 - Block Owner Deletion: true - Controller: true - Kind: XVirtualMachine - Name: my-composite-resource -``` - -Each _composite resource_ creates and owns a unique set of _managed resources_. -If you create a second _composite resource_ Crossplane creates a new -`LinuxVirtualMachine` and new networking resources. - -```yaml {label="xr"} -cat <}} -Delete a specific _composite resource_ with `kubectl delete ` or -`kubectl delete composite`. -{{< /hint >}} - -Delete the second composition -```shell -kubectl delete xvirtualmachine my-second-composite-resource -``` - -{{}} -It may take up to five minutes before Crossplane finishes deleting resources. -{{}} - -Now only one virtual machine and network interface exist. - -```shell {copy-lines="1"} -kubectl get linuxvirtualmachines -NAME READY SYNCED EXTERNAL-NAME AGE -my-composite-resource-w564c True True my-composite-resource-w564c 28m -``` - -```shell {copy-lines="1"} -kubectl get networkinterface -NAME READY SYNCED EXTERNAL-NAME AGE -my-composite-resource-72ft8 True True my-composite-resource-72ft8 29m -``` - -Delete the other _composite resource_ to remove the last `linuxvirtualmachines` -and `networkinterface` _managed resources_. - -```shell -kubectl delete xvirtualmachine my-composite-resource -``` - -_Composite resources_ are great for creating one or more related resources against -a template, but all _composite resources_ exist at the Kubernetes "cluster -level." There's no isolation between _composite resources_. Crossplane uses -_Claims_ to create resources with namespace isolation. - -## Create a claim - -_Claims_, just like _composite resources_ use the custom API defined in the -_XRD_. Unlike a _composite resource_, Crossplane can create _Claims_ in a -namespace. - -### Create a new Kubernetes namespace -Create a new namespace with `kubectl create namespace`. - -```shell -kubectl create namespace test -``` - -Look at the _XRD_ to see the parameters for the _Claim_. -A _Claim_ uses the same {{}}group{{}} -a _composite resource_ uses but a different -{{}}kind{{}}. - -```yaml {label="XRDclaim2",copy-lines="none"} -apiVersion: apiextensions.crossplane.io/v1 -kind: CompositeResourceDefinition -# Removed for brevity -spec: -# Removed for brevity - group: custom-api.example.org - claimNames: - kind: VirtualMachine - plural: virtualmachines -``` - -Like the _composite resource_, create a new object with the -{{}}custom-api.example.org{{}} API -endpoint. - -The _XRD_ -{{}}claimNames.kind{{}} defines the -{{}}kind{{}}. - -The {{}}spec{{}} uses the same -API options as the _composite resource_. - -### Apply the claim -Apply the _claim_ to your Kubernetes cluster. - -```yaml {label="claim"} -cat <}} -View claims with `kubectl get ` or use `kubectl get claim` to view all -_Claims_. -{{}} - -```shell {copy-lines="1"} -kubectl get virtualmachine -n test -NAME SYNCED READY CONNECTION-SECRET AGE -claimed-virtualmachine True True 3m40s -``` - -When Crossplane creates a _Claim_, a unique _composite resource_ is also -created. View the new _composite resource_ with `kubectl get xvirtualmachine`. - -```shell {copy-lines="1"} -kubectl get xvirtualmachine -NAME SYNCED READY COMPOSITION AGE -claimed-virtualmachine-cw6cv True True crossplane-quickstart-vm-with-network 3m57s -``` - -The _composite resource_ exists at the "cluster scope" while the _Claim_ exists -at the "namespace scope." - -Create a second namespace and a second claim. - -```yaml -kubectl create namespace test2 -cat <}}) of this guide covers _composition -patches_ and making all this configuration portable in Crossplane _Packages_. - -## Next steps -* **[Continue to part 3]({{< ref "provider-azure-part-3">}})** to learn - about _patching_ resources and creating Crossplane _Packages_. -* Explore Azure resources that Crossplane can configure in the - [Provider CRD reference](https://marketplace.upbound.io/providers/upbound/provider-family-azure/). -* Join the [Crossplane Slack](https://slack.crossplane.io/) and connect with Crossplane users and contributors. \ No newline at end of file diff --git a/content/v1.11/getting-started/provider-azure-part-3.md b/content/v1.11/getting-started/provider-azure-part-3.md deleted file mode 100644 index b5583feda..000000000 --- a/content/v1.11/getting-started/provider-azure-part-3.md +++ /dev/null @@ -1,811 +0,0 @@ ---- -title: Azure Quickstart Part 3 -weight: 120 -tocHidden: true ---- - -{{< hint "important" >}} -This guide is part 3 of a series. - -Follow **[part 1]({{}})** -to install Crossplane and connect your Kubernetes cluster to Azure. - -Follow **[part 2]({{}})** to create a _composition_, -_custom resource definition_ and a _claim_. -{{< /hint >}} - -[Part 2]({{}}) created a -_CompositeResourceDefinition_ to define the schema of the custom API. -Users create a _Claim_ to use the custom API and apply their options. -Part 2 didn't show how the options set in a _Claim_ change or get -applied to the associated _composite resources_. - -## Prerequisites -* Complete quickstart [part 1]({{}}) and [part 2]({{}}) to install Crossplane and the quickstart - configurations. - -{{}} -1. Add the Crossplane Helm repository and install Crossplane -```shell -helm repo add \ -crossplane-stable https://charts.crossplane.io/stable -helm repo update -&& -helm install crossplane \ -crossplane-stable/crossplane \ ---namespace crossplane-system \ ---create-namespace -``` - -2. When the Crossplane pods finish installing and are ready, apply the Azure - Provider - -```yaml {label="provider",copy-lines="all"} -cat <}} -```console -az ad sp create-for-rbac \ ---sdk-auth \ ---role Owner \ ---scopes /subscriptions/$$$$ -``` -{{}} - -4. Create a Kubernetes secret from the Azure JSON file. -```shell {label="kube-create-secret",copy-lines="all"} -kubectl create secret \ -generic azure-secret \ --n crossplane-system \ ---from-file=creds=./azure-credentials.json -``` - -5. Create a _ProviderConfig_ -```yaml {label="providerconfig",copy-lines="all"} -cat <}} -Apply your -{{}}resourceGroupName{{}} to each resource. -{{< /hint >}} - -{{< editCode >}} -```yaml {label="Composition"} -cat <$$ - size: Standard_B1ms - sourceImageReference: - - offer: debian-11 - publisher: Debian - sku: 11-backports-gen2 - version: latest - networkInterfaceIdsSelector: - matchControllerRef: true - - name: quickstart-nic - base: - apiVersion: network.azure.upbound.io/v1beta1 - kind: NetworkInterface - spec: - forProvider: - ipConfiguration: - - name: crossplane-quickstart-configuration - privateIpAddressAllocation: Dynamic - subnetIdSelector: - matchControllerRef: true - location: "Central US" - resourceGroupName: $$$$ - - name: quickstart-subnet - base: - apiVersion: network.azure.upbound.io/v1beta1 - kind: Subnet - spec: - forProvider: - addressPrefixes: - - 10.0.1.0/24 - virtualNetworkNameSelector: - matchControllerRef: true - resourceGroupName: $$$$ - - name: quickstart-network - base: - apiVersion: network.azure.upbound.io/v1beta1 - kind: VirtualNetwork - spec: - forProvider: - addressSpace: - - 10.0.0.0/16 - location: "Central US" - resourceGroupName: $$$$ -EOF -``` -{{< /editCode >}} - -7. Create a _CompositeResourceDefinition_ -```yaml -cat <}} - -## Enable composition patches -In a _Composition_ `patches` map fields in the custom API to fields inside the -_managed resources_. - -The example _Composition_ has four _managed resources_. A {{}}LinuxVirtualMachine{{}}, -{{}}NetworkInterface{{}}, -{{}}Subnet{{}} and a -{{}}VirtualNetwork{{}}. - - -```yaml {label="compResources",copy-lines="none"} -apiVersion: apiextensions.crossplane.io/v1 -kind: Composition -# Removed for Brevity -resources: - - name: quickstart-vm - base: - apiVersion: compute.azure.upbound.io/v1beta1 - kind: LinuxVirtualMachine - - name: quickstart-nic - base: - apiVersion: network.azure.upbound.io/v1beta1 - kind: NetworkInterface - - name: quickstart-subnet - base: - apiVersion: network.azure.upbound.io/v1beta1 - kind: Subnet - - name: quickstart-network - base: - apiVersion: network.azure.upbound.io/v1beta1 - kind: VirtualNetwork -``` - -The custom API defined a single option, -{{}}region{{}}. A -{{}}region{{}} can be either -{{}}EU{{}} or -{{}}US{{}}. - - -```yaml {label="xrdSnip",copy-lines="none"} -apiVersion: apiextensions.crossplane.io/v1 -kind: CompositeResourceDefinition -# Removed for brevity -spec: - group: custom-api.example.org - names: - kind: XVirtualMachine -# Removed for brevity - spec: - type: object - properties: - region: - type: string - oneOf: - - pattern: '^EU$' - - pattern: '^US$' -``` - -Creating a _composition_ `patch` allows Crossplane to update the settings of the -_composite resource_. Patches apply to the individual _managed resources_ -inside the _Composition_. - -A {{}}patch{{}} has a -{{}}fromField{{}} and a -{{}}toField{{}} specifying which value -_from_ the custom API should apply _to_ a field in the _managed resource_. -Patches can create a -{{}}transform{{}} to change the _from_ -field before it's applied. - -The transform -{{}}type{{}} is what kind of change to -make on the _from_ field. Types of changes could include appending a string, -preforming a math operation or mapping one value to another. - -Applying a {{}}patch{{}} to the -{{}}LinuxVirtualMachine{{}} uses the -custom API -{{}}region{{}} to use as the -_managed resource_ -{{}}location{{}}. - - -The custom API value "EU" is -{{}}mapped{{}} to the value -"Sweden Central" -and "US" is {{}}mapped{{}} to the value -"Central US." - - - -```yaml {label="patch",copy-lines="none"} -apiVersion: apiextensions.crossplane.io/v1 -kind: Composition -# Removed for Brevity - resources: - - name: quickstart-vm - base: - apiVersion: compute.azure.upbound.io/v1beta1 - kind: LinuxVirtualMachine - spec: - forProvider: - location: "Central US" - # Removed for Brevity - patches: - - fromFieldPath: "spec.region" - toFieldPath: "spec.forProvider.location" - transforms: - - type: map - map: - EU: "Sweden Central" - US: "Central US" -``` - -Patching is a powerful tool enabling simpler or abstracted APIs. A developer -isn't required to know the specific Azure location names, only the abstracted -option of "EU" or "US." - - -### Apply the updated composition -Apply the same `patch` to all other _managed resource_ -and apply the updated _Composition_. - -{{< hint "tip" >}} -Update each `resourceGroupName` with your Azure Resource Group. -{{< /hint >}} - -{{< editCode >}} -```yaml -cat <$$ - size: Standard_B1ms - sourceImageReference: - - offer: debian-11 - publisher: Debian - sku: 11-backports-gen2 - version: latest - networkInterfaceIdsSelector: - matchControllerRef: true - patches: - - fromFieldPath: "spec.region" - toFieldPath: "spec.forProvider.location" - transforms: - - type: map - map: - EU: "Sweden Central" - US: "Central US" - - name: quickstart-nic - base: - apiVersion: network.azure.upbound.io/v1beta1 - kind: NetworkInterface - spec: - forProvider: - ipConfiguration: - - name: crossplane-quickstart-configuration - privateIpAddressAllocation: Dynamic - subnetIdSelector: - matchControllerRef: true - location: "Central US" - resourceGroupName: $$$$ - patches: - - fromFieldPath: "spec.region" - toFieldPath: "spec.forProvider.location" - transforms: - - type: map - map: - EU: "Sweden Central" - US: "Central US" - - name: quickstart-subnet - base: - apiVersion: network.azure.upbound.io/v1beta1 - kind: Subnet - spec: - forProvider: - addressPrefixes: - - 10.0.1.0/24 - virtualNetworkNameSelector: - matchControllerRef: true - resourceGroupName: $$$$ - patches: - - fromFieldPath: "spec.region" - toFieldPath: "spec.forProvider.location" - transforms: - - type: map - map: - EU: "Sweden Central" - US: "Central US" - - name: quickstart-network - base: - apiVersion: network.azure.upbound.io/v1beta1 - kind: VirtualNetwork - spec: - forProvider: - addressSpace: - - 10.0.0.0/16 - location: "Sweden Central" - resourceGroupName: $$$$ - patches: - - fromFieldPath: "spec.region" - toFieldPath: "spec.forProvider.location" - transforms: - - type: map - map: - EU: "Sweden Central" - US: "Central US" -EOF -``` -{{< /editCode >}} - -### Create a claim -Create a new _claim_ and set the -{{}}region{{}} to "EU." - -```yaml {label="claim"} -cat <}} -It may take up to 10 minutes for the Claim to be `READY`. -{{< /hint >}} - -```shell {copy-lines="1"} -kubectl get claim -n test -NAME SYNCED READY CONNECTION-SECRET AGE -claimed-eu-virtualmachine True True 6m2s -``` - -The claim reports `SYNCED` and `READY` as `True` after Crossplane creates -all the _managed resources_. - -Describe the `LinuxVirtualMachine` resource to see the Azure location is `Sweden -Central`. - -```shell {copy-lines="1"} -kubectl describe linuxvirtualmachine | grep "At Provider\|Location" - Location: Sweden Central - At Provider: - Location: swedencentral -``` - - -Using {{}}region: "EU"{{}} patches the -_composite resource_, updating the Azure location from `Central US` to -`Sweden Central`. -The developer creating the claim isn't required to know which specific Azure -location or the location naming conventions. Using the abstract API options of -"EU" or "US" the developer places their resources in the desired location. - - -Deleting the claim removes the _managed resources_. - -{{}} -The _managed resources_ take up to 5 minutes to delete. -{{< /hint >}} - -```shell -kubectl delete virtualmachine claimed-eu-virtualmachine -n test -``` - -## Create a Crossplane configuration package - -Crossplane _configuration packages_ allow users to combine their -_CustomResourceDefinition_ and _Composition_ files into a single OCI image. - -{{< hint "note" >}} -The [Open Container Initiative](https://opencontainers.org/faq/) -defines the OCI image standard. -An OCI images is a standard way to package data. -{{< /hint >}} - -You can host configuration packages in image registries like -[Docker Hub](https://hub.docker.com/) or the -[Upbound Marketplace](https://marketplace.upbound.io/). - -Crossplane can download and install configuration packages into a Kubernetes -cluster. - -Creating a configuration package makes your Crossplane custom APIs portable -and versioned. - -Building and installing configuration packages requires an OCI image compatible -tool. - -{{< hint "note" >}} -You can use any software that builds OCI images. This includes -[Docker](https://www.docker.com/) or -[Upbound's Up CLI](https://github.com/upbound/up). -{{< /hint >}} - -A configuration package includes at least three files: -* `crossplane.yaml` defines the metadata of the package. -* `definition.yaml` is the _CompositeResourceDefinition_ for the package. -* `composition.yaml` is the _Composition_ template for the package. - - - -### Create a crossplane.yaml file - -Configuration packages describe their contents and requirements with a -`crossplane.yaml` file. - -The `crossplane.yaml` file lists the required Crossplane _Providers_ and their -compatible versions as well as the required Crossplane version. - -The Crossplane -{{}}meta.pkg{{}} API defines the schema -for a -{{}}Configuration{{}}. - -Inside the {{}}spec{{}} define the -required Crossplane -{{}}version{{}}. - -The {{}}dependsOn{{}} section lists the -dependencies for a package. - -This package lists the Upbound -{{}}provider-azure{{}} -version {{}}0.32.0{{}} or later as a -dependency. - -{{}} -Crossplane automatically installs dependencies. Dependencies can include other -configuration packages. -{{< /hint >}} - -Create a new directory and save the `crossplane.yaml` file. - -```yaml {label="xpyaml"} -mkdir crossplane-azure-quickstart -cat < crossplane-azure-quickstart/crossplane.yaml -apiVersion: meta.pkg.crossplane.io/v1 -kind: Configuration -metadata: - name: crossplane-azure-quickstart -spec: - crossplane: - version: ">=v1.11.0" - dependsOn: - - provider: xpkg.upbound.io/upbound/provider-azure - version: ">=v0.32.0" -EOF -``` - - - -### Create a definition.yaml file - - -A configuration package requires a _CompositeResourceDefinition_ (XRD) to -define the custom API. - -Save the _XRD_ as `definition.yaml` in the same directory as the -`crossplane.yaml` file. - -```yaml -cat < crossplane-azure-quickstart/definition.yaml -apiVersion: apiextensions.crossplane.io/v1 -kind: CompositeResourceDefinition -metadata: - name: xvirtualmachines.custom-api.example.org -spec: - group: custom-api.example.org - names: - kind: XVirtualMachine - plural: xvirtualmachines - versions: - - name: v1alpha1 - served: true - referenceable: true - schema: - openAPIV3Schema: - type: object - properties: - spec: - type: object - properties: - region: - type: string - oneOf: - - pattern: '^EU$' - - pattern: '^US$' - required: - - region - claimNames: - kind: VirtualMachine - plural: virtualmachines -EOF -``` - - - -### Create a composition.yaml file - - -The _Composition_ template creates the _managed resources_ and allows _patches_ -to customize the _managed resources_. - -Copy the _Composition_ into the `composition.yaml` file in the same directory as -`crossplane.yaml`. - -{{< hint "tip" >}} -Update each `resourceGroupName` with your Azure Resource Group. -{{< /hint >}} - -{{< editCode >}} -```yaml -cat < crossplane-azure-quickstart/composition.yaml -apiVersion: apiextensions.crossplane.io/v1 -kind: Composition -metadata: - name: crossplane-quickstart-vm-with-network -spec: - compositeTypeRef: - apiVersion: custom-api.example.org/v1alpha1 - kind: XVirtualMachine - resources: - - name: quickstart-vm - base: - apiVersion: compute.azure.upbound.io/v1beta1 - kind: LinuxVirtualMachine - spec: - forProvider: - adminUsername: adminuser - adminSshKey: - - publicKey: ssh-rsa - AAAAB3NzaC1yc2EAAAADAQABAAABAQC+wWK73dCr+jgQOAxNsHAnNNNMEMWOHYEccp6wJm2gotpr9katuF/ZAdou5AaW1C61slRkHRkpRRX9FA9CYBiitZgvCCz+3nWNN7l/Up54Zps/pHWGZLHNJZRYyAB6j5yVLMVHIHriY49d/GZTZVNB8GoJv9Gakwc/fuEZYYl4YDFiGMBP///TzlI4jhiJzjKnEvqPFki5p2ZRJqcbCiF4pJrxUQR/RXqVFQdbRLZgYfJ8xGB878RENq3yQ39d8dVOkq4edbkzwcUmwwwkYVPIoDGsYLaRHnG+To7FvMeyO7xDVQkMKzopTQV8AuKpyvpqu0a9pWOMaiCyDytO7GGN - example@docs.crossplane.io - username: adminuser - location: "Central US" - osDisk: - - caching: ReadWrite - storageAccountType: Standard_LRS - resourceGroupName: $$$$ - size: Standard_B1ms - sourceImageReference: - - offer: debian-11 - publisher: Debian - sku: 11-backports-gen2 - version: latest - networkInterfaceIdsSelector: - matchControllerRef: true - patches: - - fromFieldPath: "spec.region" - toFieldPath: "spec.forProvider.location" - transforms: - - type: map - map: - EU: "Sweden Central" - US: "Central US" - - name: quickstart-nic - base: - apiVersion: network.azure.upbound.io/v1beta1 - kind: NetworkInterface - spec: - forProvider: - ipConfiguration: - - name: crossplane-quickstart-configuration - privateIpAddressAllocation: Dynamic - subnetIdSelector: - matchControllerRef: true - location: "Central US" - resourceGroupName: $$$$ - patches: - - fromFieldPath: "spec.region" - toFieldPath: "spec.forProvider.location" - transforms: - - type: map - map: - EU: "Sweden Central" - US: "Central US" - - name: quickstart-subnet - base: - apiVersion: network.azure.upbound.io/v1beta1 - kind: Subnet - spec: - forProvider: - addressPrefixes: - - 10.0.1.0/24 - virtualNetworkNameSelector: - matchControllerRef: true - resourceGroupName: $$$$ - patches: - - fromFieldPath: "spec.region" - toFieldPath: "spec.forProvider.location" - transforms: - - type: map - map: - EU: "Sweden Central" - US: "Central US" - - name: quickstart-network - base: - apiVersion: network.azure.upbound.io/v1beta1 - kind: VirtualNetwork - spec: - forProvider: - addressSpace: - - 10.0.0.0/16 - location: "Sweden Central" - resourceGroupName: $$$$ - patches: - - fromFieldPath: "spec.region" - toFieldPath: "spec.forProvider.location" - transforms: - - type: map - map: - EU: "Sweden Central" - US: "Central US" -EOF -``` -{{< /editCode >}} - -### Install the Crossplane command-line -To build a configuration package install the Crossplane Kubernetes command-line -extension. - -```shell -wget "https://raw.githubusercontent.com/crossplane/crossplane/master/install.sh" -chmod +x install.sh -./install.sh -sudo mv crossplane /usr/local/bin -``` - -Follow the directions and move the `crossplane` binary to the correct -directory. - -Verify the Crossplane command-line installed with `crossplane --help` - -```shell {copy-lines="1"} -crossplane --help -Usage: crossplane - -A command line tool for interacting with Crossplane. - -Flags: - -h, --help Show context-sensitive help. - -v, --version Print version and quit. - --verbose Print verbose logging statements. -# Ouptut removed for brevity -``` - -### Build a configuration package - -Use the `crossplane` CLI to create an `.xpkg` file containing the -custom APIs and Crossplane configuration. - -```shell -crossplane build configuration -f crossplane-azure-quickstart/ --name="crossplane-azure-quickstart" -``` - -Now an `.xpkg` OCI image is inside the `crossplane-azure-quickstart` directory. - -```shell {copy-lines="1"} -ls crossplane-azure-quickstart/ -composition.yaml crossplane-azure-quickstart.xpkg crossplane.yaml definition.yaml -``` - -## Next steps -* Explore Azure resources that Crossplane can configure in the [Provider CRD reference](https://marketplace.upbound.io/providers/upbound/provider-family-azure/). -* Join the [Crossplane Slack](https://slack.crossplane.io/) and connect with Crossplane users and contributors. -* Read more about [Crossplane concepts]({{}}) \ No newline at end of file diff --git a/content/v1.11/getting-started/provider-azure.md b/content/v1.11/getting-started/provider-azure.md deleted file mode 100644 index 5a71015c5..000000000 --- a/content/v1.11/getting-started/provider-azure.md +++ /dev/null @@ -1,1250 +0,0 @@ ---- -title: Azure Quickstart -weight: 110 ---- - -Connect Crossplane to Azure to create and manage cloud resources from Kubernetes -with the -[Upbound Azure Provider](https://marketplace.upbound.io/providers/upbound/provider-azure). - -This guide is in three parts: -* Part 1 walks through installing Crossplane, configuring the provider to -authenticate to Azure and creating a _Managed Resource_ in Azure directly from -your Kubernetes cluster. This shows Crossplane can communicate with Azure. -* [Part 2]({{< ref "provider-azure-part-2" >}}) creates a -_Composite Resource Definition_ (XRD), _Composite Resource_ (XR) and a _Claim_ -(XRC) to show how to create and use custom APIs. -* [Part 3]({{< ref "provider-azure-part-3" >}}) demonstrates how to patch -_Compositions_ with values used in a _Claim_ and how to build a Crossplane -_Package_ to make a Crossplane platform portable and reusable. - -## Prerequisites -This quickstart requires: -* a Kubernetes cluster with at least 6 GB of RAM -* permissions to create pods and secrets in the Kubernetes cluster -* [Helm](https://helm.sh/) version `v3.2.0` or later -* an Azure account with permissions to create an - [Azure Virtual Machine](https://learn.microsoft.com/en-us/azure/virtual-machines/) - and - [Virtual Network](https://learn.microsoft.com/en-us/azure/virtual-network/) -* an Azure account with permissions to create an Azure [service principal](https://learn.microsoft.com/en-us/azure/active-directory/develop/app-objects-and-service-principals#service-principal-object) and an [Azure resource group](https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/manage-resource-groups-portal) - -## Install Crossplane - -Crossplane installs into an existing Kubernetes cluster. - -{{< hint type="tip" >}} -If you don't have a Kubernetes cluster create one locally with -[Kind](https://kind.sigs.k8s.io/). -{{< /hint >}} - - -### Install the Crossplane Helm chart - -Helm enables Crossplane to install all its Kubernetes components through a -_Helm Chart_. - -Enable the Crossplane Helm Chart repository: - -```shell -helm repo add \ -crossplane-stable https://charts.crossplane.io/stable && helm repo update -``` - -Run the Helm dry-run to see all the Crossplane components Helm installs. - -```shell -helm install crossplane \ -crossplane-stable/crossplane \ ---dry-run --debug \ ---namespace crossplane-system \ ---create-namespace -``` -{{}} -```shell -helm install crossplane \ -crossplane-stable/crossplane \ ---dry-run --debug \ ---namespace crossplane-system \ ---create-namespace -install.go:193: [debug] Original chart version: "" -install.go:210: [debug] CHART PATH: /home/vagrant/.cache/helm/repository/crossplane-1.10.1.tgz - -NAME: crossplane -LAST DEPLOYED: Thu Jan 19 15:52:08 2023 -NAMESPACE: crossplane-system -STATUS: pending-install -REVISION: 1 -TEST SUITE: None -USER-SUPPLIED VALUES: -{} - -COMPUTED VALUES: -affinity: {} -args: {} -configuration: - packages: [] -customAnnotations: {} -customLabels: {} -deploymentStrategy: RollingUpdate -extraEnvVarsCrossplane: {} -extraEnvVarsRBACManager: {} -image: - pullPolicy: IfNotPresent - repository: crossplane/crossplane - tag: v1.10.1 -imagePullSecrets: {} -leaderElection: true -metrics: - enabled: false -nodeSelector: {} -packageCache: - medium: "" - pvc: "" - sizeLimit: 5Mi -podSecurityContextCrossplane: {} -podSecurityContextRBACManager: {} -priorityClassName: "" -provider: - packages: [] -rbacManager: - affinity: {} - args: {} - deploy: true - leaderElection: true - managementPolicy: All - nodeSelector: {} - replicas: 1 - skipAggregatedClusterRoles: false - tolerations: {} -registryCaBundleConfig: {} -replicas: 1 -resourcesCrossplane: - limits: - cpu: 100m - memory: 512Mi - requests: - cpu: 100m - memory: 256Mi -resourcesRBACManager: - limits: - cpu: 100m - memory: 512Mi - requests: - cpu: 100m - memory: 256Mi -securityContextCrossplane: - allowPrivilegeEscalation: false - readOnlyRootFilesystem: true - runAsGroup: 65532 - runAsUser: 65532 -securityContextRBACManager: - allowPrivilegeEscalation: false - readOnlyRootFilesystem: true - runAsGroup: 65532 - runAsUser: 65532 -serviceAccount: - customAnnotations: {} -tolerations: {} -webhooks: - enabled: false - -HOOKS: -MANIFEST: ---- -# Source: crossplane/templates/rbac-manager-serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: rbac-manager - labels: - app: crossplane - helm.sh/chart: crossplane-1.10.1 - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: cloud-infrastructure-controller - app.kubernetes.io/part-of: crossplane - app.kubernetes.io/name: crossplane - app.kubernetes.io/instance: crossplane - app.kubernetes.io/version: "1.10.1" ---- -# Source: crossplane/templates/serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: crossplane - labels: - app: crossplane - helm.sh/chart: crossplane-1.10.1 - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: cloud-infrastructure-controller - app.kubernetes.io/part-of: crossplane - app.kubernetes.io/name: crossplane - app.kubernetes.io/instance: crossplane - app.kubernetes.io/version: "1.10.1" ---- -# Source: crossplane/templates/clusterrole.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: crossplane - labels: - app: crossplane - helm.sh/chart: crossplane-1.10.1 - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: cloud-infrastructure-controller - app.kubernetes.io/part-of: crossplane - app.kubernetes.io/name: crossplane - app.kubernetes.io/instance: crossplane - app.kubernetes.io/version: "1.10.1" -aggregationRule: - clusterRoleSelectors: - - matchLabels: - rbac.crossplane.io/aggregate-to-crossplane: "true" ---- -# Source: crossplane/templates/clusterrole.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: crossplane:system:aggregate-to-crossplane - labels: - app: crossplane - helm.sh/chart: crossplane-1.10.1 - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: cloud-infrastructure-controller - app.kubernetes.io/part-of: crossplane - app.kubernetes.io/name: crossplane - app.kubernetes.io/instance: crossplane - app.kubernetes.io/version: "1.10.1" - crossplane.io/scope: "system" - rbac.crossplane.io/aggregate-to-crossplane: "true" -rules: -- apiGroups: - - "" - resources: - - events - verbs: - - create - - update - - patch - - delete -- apiGroups: - - apiextensions.k8s.io - resources: - - customresourcedefinitions - verbs: - - "*" -- apiGroups: - - "" - resources: - - secrets - verbs: - - get - - list - - watch - - create - - update - - patch - - delete -- apiGroups: - - "" - resources: - - serviceaccounts - - services - verbs: - - "*" -- apiGroups: - - apiextensions.crossplane.io - - pkg.crossplane.io - - secrets.crossplane.io - resources: - - "*" - verbs: - - "*" -- apiGroups: - - extensions - - apps - resources: - - deployments - verbs: - - get - - list - - create - - update - - patch - - delete - - watch -- apiGroups: - - "" - - coordination.k8s.io - resources: - - configmaps - - leases - verbs: - - get - - list - - create - - update - - patch - - watch - - delete -- apiGroups: - - admissionregistration.k8s.io - resources: - - validatingwebhookconfigurations - - mutatingwebhookconfigurations - verbs: - - get - - list - - create - - update - - patch - - watch - - delete ---- -# Source: crossplane/templates/rbac-manager-allowed-provider-permissions.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: crossplane:allowed-provider-permissions - labels: - app: crossplane - helm.sh/chart: crossplane-1.10.1 - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: cloud-infrastructure-controller - app.kubernetes.io/part-of: crossplane - app.kubernetes.io/name: crossplane - app.kubernetes.io/instance: crossplane - app.kubernetes.io/version: "1.10.1" -aggregationRule: - clusterRoleSelectors: - - matchLabels: - rbac.crossplane.io/aggregate-to-allowed-provider-permissions: "true" ---- -# Source: crossplane/templates/rbac-manager-clusterrole.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: crossplane-rbac-manager - labels: - app: crossplane - helm.sh/chart: crossplane-1.10.1 - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: cloud-infrastructure-controller - app.kubernetes.io/part-of: crossplane - app.kubernetes.io/name: crossplane - app.kubernetes.io/instance: crossplane - app.kubernetes.io/version: "1.10.1" -rules: -- apiGroups: - - "" - resources: - - events - verbs: - - create - - update - - patch - - delete -- apiGroups: - - "" - resources: - - namespaces - - serviceaccounts - verbs: - - get - - list - - watch -- apiGroups: - - apiextensions.crossplane.io - resources: - - compositeresourcedefinitions - verbs: - - get - - list - - watch -- apiGroups: - - pkg.crossplane.io - resources: - - providerrevisions - verbs: - - get - - list - - watch -- apiGroups: - - apiextensions.k8s.io - resources: - - customresourcedefinitions - verbs: - - get - - list - - watch -- apiGroups: - - rbac.authorization.k8s.io - resources: - - clusterroles - - roles - verbs: - - get - - list - - watch - - create - - update - - patch - # The RBAC manager may grant access it does not have. - - escalate -- apiGroups: - - rbac.authorization.k8s.io - resources: - - clusterroles - verbs: - - bind -- apiGroups: - - rbac.authorization.k8s.io - resources: - - clusterrolebindings - verbs: - - "*" -- apiGroups: - - "" - - coordination.k8s.io - resources: - - configmaps - - leases - verbs: - - get - - list - - create - - update - - patch - - watch - - delete ---- -# Source: crossplane/templates/rbac-manager-managed-clusterroles.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: crossplane-admin - labels: - app: crossplane - helm.sh/chart: crossplane-1.10.1 - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: cloud-infrastructure-controller - app.kubernetes.io/part-of: crossplane - app.kubernetes.io/name: crossplane - app.kubernetes.io/instance: crossplane - app.kubernetes.io/version: "1.10.1" -aggregationRule: - clusterRoleSelectors: - - matchLabels: - rbac.crossplane.io/aggregate-to-admin: "true" ---- -# Source: crossplane/templates/rbac-manager-managed-clusterroles.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: crossplane-edit - labels: - app: crossplane - helm.sh/chart: crossplane-1.10.1 - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: cloud-infrastructure-controller - app.kubernetes.io/part-of: crossplane - app.kubernetes.io/name: crossplane - app.kubernetes.io/instance: crossplane - app.kubernetes.io/version: "1.10.1" -aggregationRule: - clusterRoleSelectors: - - matchLabels: - rbac.crossplane.io/aggregate-to-edit: "true" ---- -# Source: crossplane/templates/rbac-manager-managed-clusterroles.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: crossplane-view - labels: - app: crossplane - helm.sh/chart: crossplane-1.10.1 - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: cloud-infrastructure-controller - app.kubernetes.io/part-of: crossplane - app.kubernetes.io/name: crossplane - app.kubernetes.io/instance: crossplane - app.kubernetes.io/version: "1.10.1" -aggregationRule: - clusterRoleSelectors: - - matchLabels: - rbac.crossplane.io/aggregate-to-view: "true" ---- -# Source: crossplane/templates/rbac-manager-managed-clusterroles.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: crossplane-browse - labels: - app: crossplane - helm.sh/chart: crossplane-1.10.1 - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: cloud-infrastructure-controller - app.kubernetes.io/part-of: crossplane - app.kubernetes.io/name: crossplane - app.kubernetes.io/instance: crossplane - app.kubernetes.io/version: "1.10.1" -aggregationRule: - clusterRoleSelectors: - - matchLabels: - rbac.crossplane.io/aggregate-to-browse: "true" ---- -# Source: crossplane/templates/rbac-manager-managed-clusterroles.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: crossplane:aggregate-to-admin - labels: - rbac.crossplane.io/aggregate-to-admin: "true" - app: crossplane - helm.sh/chart: crossplane-1.10.1 - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: cloud-infrastructure-controller - app.kubernetes.io/part-of: crossplane - app.kubernetes.io/name: crossplane - app.kubernetes.io/instance: crossplane - app.kubernetes.io/version: "1.10.1" -rules: -# Crossplane administrators have access to view events. -- apiGroups: [""] - resources: [events] - verbs: [get, list, watch] -# Crossplane administrators must create provider credential secrets, and may -# need to read or otherwise interact with connection secrets. They may also need -# to create or annotate namespaces. -- apiGroups: [""] - resources: [secrets, namespaces] - verbs: ["*"] -# Crossplane administrators have access to view the roles that they may be able -# to grant to other subjects. -- apiGroups: [rbac.authorization.k8s.io] - resources: [clusterroles, roles] - verbs: [get, list, watch] -# Crossplane administrators have access to grant the access they have to other -# subjects. -- apiGroups: [rbac.authorization.k8s.io] - resources: [clusterrolebindings, rolebindings] - verbs: ["*"] -# Crossplane administrators have full access to built in Crossplane types. -- apiGroups: - - apiextensions.crossplane.io - resources: ["*"] - verbs: ["*"] -- apiGroups: - - pkg.crossplane.io - resources: [providers, configurations, providerrevisions, configurationrevisions] - verbs: ["*"] -# Crossplane administrators have access to view CRDs in order to debug XRDs. -- apiGroups: [apiextensions.k8s.io] - resources: [customresourcedefinitions] - verbs: [get, list, watch] ---- -# Source: crossplane/templates/rbac-manager-managed-clusterroles.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: crossplane:aggregate-to-edit - labels: - rbac.crossplane.io/aggregate-to-edit: "true" - app: crossplane - helm.sh/chart: crossplane-1.10.1 - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: cloud-infrastructure-controller - app.kubernetes.io/part-of: crossplane - app.kubernetes.io/name: crossplane - app.kubernetes.io/instance: crossplane - app.kubernetes.io/version: "1.10.1" -rules: -# Crossplane editors have access to view events. -- apiGroups: [""] - resources: [events] - verbs: [get, list, watch] -# Crossplane editors must create provider credential secrets, and may need to -# read or otherwise interact with connection secrets. -- apiGroups: [""] - resources: [secrets] - verbs: ["*"] -# Crossplane editors may see which namespaces exist, but not edit them. -- apiGroups: [""] - resources: [namespaces] - verbs: [get, list, watch] -# Crossplane editors have full access to built in Crossplane types. -- apiGroups: - - apiextensions.crossplane.io - resources: ["*"] - verbs: ["*"] -- apiGroups: - - pkg.crossplane.io - resources: [providers, configurations, providerrevisions, configurationrevisions] - verbs: ["*"] ---- -# Source: crossplane/templates/rbac-manager-managed-clusterroles.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: crossplane:aggregate-to-view - labels: - rbac.crossplane.io/aggregate-to-view: "true" - app: crossplane - helm.sh/chart: crossplane-1.10.1 - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: cloud-infrastructure-controller - app.kubernetes.io/part-of: crossplane - app.kubernetes.io/name: crossplane - app.kubernetes.io/instance: crossplane - app.kubernetes.io/version: "1.10.1" -rules: -# Crossplane viewers have access to view events. -- apiGroups: [""] - resources: [events] - verbs: [get, list, watch] -# Crossplane viewers may see which namespaces exist. -- apiGroups: [""] - resources: [namespaces] - verbs: [get, list, watch] -# Crossplane viewers have read-only access to built in Crossplane types. -- apiGroups: - - apiextensions.crossplane.io - resources: ["*"] - verbs: [get, list, watch] -- apiGroups: - - pkg.crossplane.io - resources: [providers, configurations, providerrevisions, configurationrevisions] - verbs: [get, list, watch] ---- -# Source: crossplane/templates/rbac-manager-managed-clusterroles.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: crossplane:aggregate-to-browse - labels: - rbac.crossplane.io/aggregate-to-browse: "true" - app: crossplane - helm.sh/chart: crossplane-1.10.1 - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: cloud-infrastructure-controller - app.kubernetes.io/part-of: crossplane - app.kubernetes.io/name: crossplane - app.kubernetes.io/instance: crossplane - app.kubernetes.io/version: "1.10.1" -rules: -# Crossplane browsers have access to view events. -- apiGroups: [""] - resources: [events] - verbs: [get, list, watch] -# Crossplane browsers have read-only access to compositions and XRDs. This -# allows them to discover and select an appropriate composition when creating a -# resource claim. -- apiGroups: - - apiextensions.crossplane.io - resources: ["*"] - verbs: [get, list, watch] ---- -# Source: crossplane/templates/rbac-manager-managed-clusterroles.yaml -# The below ClusterRoles are aggregated to the namespaced RBAC roles created by -# the Crossplane RBAC manager when it is running in --manage=All mode. -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: crossplane:aggregate-to-ns-admin - labels: - rbac.crossplane.io/aggregate-to-ns-admin: "true" - rbac.crossplane.io/base-of-ns-admin: "true" - app: crossplane - helm.sh/chart: crossplane-1.10.1 - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: cloud-infrastructure-controller - app.kubernetes.io/part-of: crossplane - app.kubernetes.io/name: crossplane - app.kubernetes.io/instance: crossplane - app.kubernetes.io/version: "1.10.1" -rules: -# Crossplane namespace admins have access to view events. -- apiGroups: [""] - resources: [events] - verbs: [get, list, watch] -# Crossplane namespace admins may need to read or otherwise interact with -# resource claim connection secrets. -- apiGroups: [""] - resources: [secrets] - verbs: ["*"] -# Crossplane namespace admins have access to view the roles that they may be -# able to grant to other subjects. -- apiGroups: [rbac.authorization.k8s.io] - resources: [roles] - verbs: [get, list, watch] -# Crossplane namespace admins have access to grant the access they have to other -# subjects. -- apiGroups: [rbac.authorization.k8s.io] - resources: [rolebindings] - verbs: ["*"] ---- -# Source: crossplane/templates/rbac-manager-managed-clusterroles.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: crossplane:aggregate-to-ns-edit - labels: - rbac.crossplane.io/aggregate-to-ns-edit: "true" - rbac.crossplane.io/base-of-ns-edit: "true" - app: crossplane - helm.sh/chart: crossplane-1.10.1 - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: cloud-infrastructure-controller - app.kubernetes.io/part-of: crossplane - app.kubernetes.io/name: crossplane - app.kubernetes.io/instance: crossplane - app.kubernetes.io/version: "1.10.1" -rules: -# Crossplane namespace editors have access to view events. -- apiGroups: [""] - resources: [events] - verbs: [get, list, watch] -# Crossplane namespace editors may need to read or otherwise interact with -# resource claim connection secrets. -- apiGroups: [""] - resources: [secrets] - verbs: ["*"] ---- -# Source: crossplane/templates/rbac-manager-managed-clusterroles.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: crossplane:aggregate-to-ns-view - labels: - rbac.crossplane.io/aggregate-to-ns-view: "true" - rbac.crossplane.io/base-of-ns-view: "true" - app: crossplane - helm.sh/chart: crossplane-1.10.1 - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: cloud-infrastructure-controller - app.kubernetes.io/part-of: crossplane - app.kubernetes.io/name: crossplane - app.kubernetes.io/instance: crossplane - app.kubernetes.io/version: "1.10.1" -rules: -# Crossplane namespace viewers have access to view events. -- apiGroups: [""] - resources: [events] - verbs: [get, list, watch] ---- -# Source: crossplane/templates/clusterrolebinding.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: crossplane - labels: - app: crossplane - helm.sh/chart: crossplane-1.10.1 - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: cloud-infrastructure-controller - app.kubernetes.io/part-of: crossplane - app.kubernetes.io/name: crossplane - app.kubernetes.io/instance: crossplane - app.kubernetes.io/version: "1.10.1" -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: crossplane -subjects: -- kind: ServiceAccount - name: crossplane - namespace: crossplane-system ---- -# Source: crossplane/templates/rbac-manager-clusterrolebinding.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: crossplane-rbac-manager - labels: - app: crossplane - helm.sh/chart: crossplane-1.10.1 - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: cloud-infrastructure-controller - app.kubernetes.io/part-of: crossplane - app.kubernetes.io/name: crossplane - app.kubernetes.io/instance: crossplane - app.kubernetes.io/version: "1.10.1" -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: crossplane-rbac-manager -subjects: -- kind: ServiceAccount - name: rbac-manager - namespace: crossplane-system ---- -# Source: crossplane/templates/rbac-manager-managed-clusterroles.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: crossplane-admin - labels: - app: crossplane - helm.sh/chart: crossplane-1.10.1 - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: cloud-infrastructure-controller - app.kubernetes.io/part-of: crossplane - app.kubernetes.io/name: crossplane - app.kubernetes.io/instance: crossplane - app.kubernetes.io/version: "1.10.1" -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: crossplane-admin -subjects: -- apiGroup: rbac.authorization.k8s.io - kind: Group - name: crossplane:masters ---- -# Source: crossplane/templates/deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: crossplane - labels: - app: crossplane - release: crossplane - helm.sh/chart: crossplane-1.10.1 - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: cloud-infrastructure-controller - app.kubernetes.io/part-of: crossplane - app.kubernetes.io/name: crossplane - app.kubernetes.io/instance: crossplane - app.kubernetes.io/version: "1.10.1" -spec: - replicas: 1 - selector: - matchLabels: - app: crossplane - release: crossplane - strategy: - type: RollingUpdate - template: - metadata: - labels: - app: crossplane - release: crossplane - helm.sh/chart: crossplane-1.10.1 - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: cloud-infrastructure-controller - app.kubernetes.io/part-of: crossplane - app.kubernetes.io/name: crossplane - app.kubernetes.io/instance: crossplane - app.kubernetes.io/version: "1.10.1" - spec: - securityContext: - {} - serviceAccountName: crossplane - initContainers: - - image: crossplane/crossplane:v1.10.1 - args: - - core - - init - imagePullPolicy: IfNotPresent - name: crossplane-init - resources: - limits: - cpu: 100m - memory: 512Mi - requests: - cpu: 100m - memory: 256Mi - securityContext: - allowPrivilegeEscalation: false - readOnlyRootFilesystem: true - runAsGroup: 65532 - runAsUser: 65532 - env: - - name: POD_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: POD_SERVICE_ACCOUNT - valueFrom: - fieldRef: - fieldPath: spec.serviceAccountName - containers: - - image: crossplane/crossplane:v1.10.1 - args: - - core - - start - imagePullPolicy: IfNotPresent - name: crossplane - resources: - limits: - cpu: 100m - memory: 512Mi - requests: - cpu: 100m - memory: 256Mi - securityContext: - allowPrivilegeEscalation: false - readOnlyRootFilesystem: true - runAsGroup: 65532 - runAsUser: 65532 - env: - - name: POD_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: LEADER_ELECTION - value: "true" - volumeMounts: - - mountPath: /cache - name: package-cache - volumes: - - name: package-cache - emptyDir: - medium: - sizeLimit: 5Mi ---- -# Source: crossplane/templates/rbac-manager-deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: crossplane-rbac-manager - labels: - app: crossplane-rbac-manager - release: crossplane - helm.sh/chart: crossplane-1.10.1 - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: cloud-infrastructure-controller - app.kubernetes.io/part-of: crossplane - app.kubernetes.io/name: crossplane - app.kubernetes.io/instance: crossplane - app.kubernetes.io/version: "1.10.1" -spec: - replicas: 1 - selector: - matchLabels: - app: crossplane-rbac-manager - release: crossplane - strategy: - type: RollingUpdate - template: - metadata: - labels: - app: crossplane-rbac-manager - release: crossplane - helm.sh/chart: crossplane-1.10.1 - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: cloud-infrastructure-controller - app.kubernetes.io/part-of: crossplane - app.kubernetes.io/name: crossplane - app.kubernetes.io/instance: crossplane - app.kubernetes.io/version: "1.10.1" - spec: - securityContext: - {} - serviceAccountName: rbac-manager - initContainers: - - image: crossplane/crossplane:v1.10.1 - args: - - rbac - - init - imagePullPolicy: IfNotPresent - name: crossplane-init - resources: - limits: - cpu: 100m - memory: 512Mi - requests: - cpu: 100m - memory: 256Mi - securityContext: - allowPrivilegeEscalation: false - readOnlyRootFilesystem: true - runAsGroup: 65532 - runAsUser: 65532 - containers: - - image: crossplane/crossplane:v1.10.1 - args: - - rbac - - start - - --manage=All - - --provider-clusterrole=crossplane:allowed-provider-permissions - imagePullPolicy: IfNotPresent - name: crossplane - resources: - limits: - cpu: 100m - memory: 512Mi - requests: - cpu: 100m - memory: 256Mi - securityContext: - allowPrivilegeEscalation: false - readOnlyRootFilesystem: true - runAsGroup: 65532 - runAsUser: 65532 - env: - - name: LEADER_ELECTION - value: "true" - -NOTES: -Release: crossplane - -Chart Name: crossplane -Chart Description: Crossplane is an open source Kubernetes add-on that enables platform teams to assemble infrastructure from multiple vendors, and expose higher level self-service APIs for application teams to consume. -Chart Version: 1.10.1 -Chart Application Version: 1.10.1 - -Kube Version: v1.24.9 -``` -{{< /expand >}} - -Install the Crossplane components using `helm install`. - -```shell -helm install crossplane \ -crossplane-stable/crossplane \ ---namespace crossplane-system \ ---create-namespace -``` - -Verify Crossplane installed with `kubectl get pods`. - -```shell {copy-lines="1"} -kubectl get pods -n crossplane-system -NAME READY STATUS RESTARTS AGE -crossplane-d4cd8d784-ldcgb 1/1 Running 0 54s -crossplane-rbac-manager-84769b574-6mw6f 1/1 Running 0 54s -``` - -Installing Crossplane creates new Kubernetes API end-points. Look at the new API -end-points with `kubectl api-resources | grep crossplane`. - -```shell {label="grep",copy-lines="1"} -kubectl api-resources | grep crossplane -compositeresourcedefinitions xrd,xrds apiextensions.crossplane.io/v1 false CompositeResourceDefinition -compositionrevisions apiextensions.crossplane.io/v1alpha1 false CompositionRevision -compositions apiextensions.crossplane.io/v1 false Composition -configurationrevisions pkg.crossplane.io/v1 false ConfigurationRevision -configurations pkg.crossplane.io/v1 false Configuration -controllerconfigs pkg.crossplane.io/v1alpha1 false ControllerConfig -locks pkg.crossplane.io/v1beta1 false Lock -providerrevisions pkg.crossplane.io/v1 false ProviderRevision -providers pkg.crossplane.io/v1 false Provider -storeconfigs secrets.crossplane.io/v1alpha1 false StoreConfig -``` - -## Install the Azure provider - -Install the provider into the Kubernetes cluster with a Kubernetes configuration -file. - -```yaml {label="provider",copy-lines="all"} -cat <}}Provider{{}} -Custom Resource Definitions tells Kubernetes how to -connect to the provider. - -Verify the provider installed with `kubectl get providers`. - -{{< hint type="note" >}} -It may take up to five minutes for the provider to list `HEALTHY` as `True`. -{{< /hint >}} - -```shell {copy-lines="1"} -kubectl get providers -NAME INSTALLED HEALTHY PACKAGE AGE -upbound-provider-azure True True xpkg.upbound.io/upbound/provider-azure:v0.32.0 22m -``` - -A provider installs their own Kubernetes _Custom Resource Definitions_ (CRDs). -These CRDs allow you to create Azure resources directly inside Kubernetes. - -You can view the new CRDs with `kubectl get crds`. Every CRD maps to a unique -Azure service Crossplane can provision and manage. - - -{{< hint type="tip" >}} -See details about all the supported CRDs in the -[Upbound Marketplace](https://marketplace.upbound.io/providers/upbound/provider-family-azure/). -{{< /hint >}} - -## Create a Kubernetes secret for Azure -The provider requires credentials to create and manage Azure resources. -Providers use a Kubernetes _Secret_ to connect the credentials to the provider. - -This guide generates an Azure service principal JSON file and saves it as a -Kubernetes _Secret_. - -{{< hint type="note" >}} -Other authentication methods exist and are beyond the scope of this guide. The -[Provider documentation](https://github.com/upbound/provider-azure/blob/main/AUTHENTICATION.md) -contains information on alternative authentication methods. -{{< /hint >}} - -### Install the Azure command-line -Generating an [authentication file](https://docs.microsoft.com/en-us/azure/developer/go/azure-sdk-authorization#use-file-based-authentication) requires the Azure command-line. -Follow the documentation from Microsoft to [Download and install the Azure command-line](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli). - -Log in to the Azure command-line. - -```command -az login -``` -### Create an Azure service principal -Follow the Azure documentation to [find your Subscription ID](https://docs.microsoft.com/en-us/azure/azure-portal/get-subscription-tenant-id) from the Azure Portal. - -Using the Azure command-line and provide your Subscription ID create a service principal and authentication file. - -{{< editCode >}} -```console {copy-lines="all"} -az ad sp create-for-rbac \ ---sdk-auth \ ---role Owner \ ---scopes /subscriptions/$$$$ -``` -{{< /editCode >}} - -Save your Azure JSON output as `azure-credentials.json`. - -{{< hint type="note" >}} -The Azure Provider -[Authentication documentation](https://github.com/upbound/provider-azure/blob/main/AUTHENTICATION.md) -describes other authentication methods. -{{< /hint >}} - -### Create a Kubernetes secret with the Azure credentials -A Kubernetes generic secret has a name and contents. Use {{< hover label="kube-create-secret" line="1">}}kubectl create secret{{< /hover >}} to generate the secret object named {{< hover label="kube-create-secret" line="2">}}azure-secret{{< /hover >}} in the {{< hover label="kube-create-secret" line="3">}}crossplane-system{{}} namespace. - - - -Use the {{< hover label="kube-create-secret" line="4">}}--from-file={{}} argument to set the value to the contents of the {{< hover label="kube-create-secret" line="4">}}azure-credentials.json{{< /hover >}} file. - -```shell {label="kube-create-secret",copy-lines="all"} -kubectl create secret \ -generic azure-secret \ --n crossplane-system \ ---from-file=creds=./azure-credentials.json -``` - -View the secret with `kubectl describe secret` - -{{< hint type="note" >}} -The size may be larger if there are extra blank spaces in your text file. -{{< /hint >}} - -```shell {copy-lines="1"} -kubectl describe secret azure-secret -n crossplane-system -Name: azure-secret -Namespace: crossplane-system -Labels: -Annotations: - -Type: Opaque - -Data -==== -creds: 629 bytes -``` - -## Create a ProviderConfig -A `ProviderConfig` customizes the settings of the Azure Provider. - -Apply the {{< hover label="providerconfig" line="5">}}ProviderConfig{{}} with the command: -```yaml {label="providerconfig",copy-lines="all"} -cat <}}secretRef{{}}. - -The {{< hover label="providerconfig" line="11">}}spec.credentials.secretRef.name{{< /hover >}} value is the name of the Kubernetes secret containing the Azure credentials in the {{< hover label="providerconfig" line="10">}}spec.credentials.secretRef.namespace{{< /hover >}}. - - -## Create a managed resource -A _managed resource_ is anything Crossplane creates and manages outside of the -Kubernetes cluster. This example creates an Azure Virtual Network with -Crossplane. The Virtual Network is a _managed resource_. - -{{< hint type="note" >}} -Add your Azure Resource Group name. Follow the Azure documentation to -[create a resource group](https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/manage-resource-groups-portal) -if you don't have one. -{{< /hint >}} - -{{< editCode >}} -```yaml {label="xr"} -cat <}} - -The {{< hover label="xr" line="2">}}apiVersion{{< /hover >}} and -{{< hover label="xr" line="3">}}kind{{}} are from the provider's CRDs. - -The {{< hover label="xr" line="10">}}spec.forProvider.location{{< /hover >}} -tells Azure which location to use when deploying the resource. - -Use `kubectl get virtualnetwork.network` to verify Crossplane created the -Azure Virtual Network. - -{{< hint type="tip" >}} -Crossplane created the virtual network when the values `READY` and `SYNCED` are `True`. -This may take up to 5 minutes. -{{< /hint >}} - -```shell {copy-lines="1"} -kubectl get virtualnetwork.network -NAME READY SYNCED EXTERNAL-NAME AGE -crossplane-quickstart-network True True crossplane-quickstart-network 10m -``` - -## Delete the managed resource -Before shutting down your Kubernetes cluster, delete the virtual network just -created. - -Use `kubectl delete virtualnetwork.network` to delete the virtual network. - - -```shell {copy-lines="1"} -kubectl delete virtualnetwork.network crossplane-quickstart-network -virtualnetwork.network.azure.upbound.io "crossplane-quickstart-network" deleted -``` - -## Next steps -* **[Continue to part 2]({{< ref "provider-azure-part-2">}})** to create a - Crossplane _Composite Resource_ and _Claim_. -* Explore Azure resources that Crossplane can configure in the - [Provider CRD reference](https://marketplace.upbound.io/providers/upbound/provider-family-azure/). -* Join the [Crossplane Slack](https://slack.crossplane.io/) and connect with - Crossplane users and contributors. \ No newline at end of file diff --git a/content/v1.11/getting-started/provider-gcp-part-2.md b/content/v1.11/getting-started/provider-gcp-part-2.md deleted file mode 100644 index bdcfedd43..000000000 --- a/content/v1.11/getting-started/provider-gcp-part-2.md +++ /dev/null @@ -1,967 +0,0 @@ ---- -title: GCP Quickstart Part 2 -weight: 120 -tocHidden: true ---- - -{{< hint "important" >}} -This guide is part 2 of a series. Follow **[part 1]({{}})** -to install Crossplane and connect your Kubernetes cluster to GCP. - -**[Part 3]({{}})** covers patching -_composite resources_ and using Crossplane _packages_. -{{< /hint >}} - -This section creates a _[Composition](#create-a-composition)_, -_[Composite Resource Definition](#define-a-composite-resource)_ and a -_[Claim](#create-a-claim)_ -to create a custom Kubernetes API to create GCP resources. This custom API is a -_Composite Resource_ (XR) API. - -## Prerequisites -* Complete [quickstart part 1]({{}}) connecting Kubernetes - to GCP. -* a GCP account with permissions to create a GCP - [storage bucket](https://cloud.google.com/storage) and a - [Pub/Sub topic](https://cloud.google.com/pubsub). - -{{}} -1. Add the Crossplane Helm repository and install Crossplane. -```shell -helm repo add \ -crossplane-stable https://charts.crossplane.io/stable -helm repo update -&& -helm install crossplane \ -crossplane-stable/crossplane \ ---namespace crossplane-system \ ---create-namespace -``` - -2. When the Crossplane pods finish installing and are ready, apply the GCP Provider. - -```yaml {label="provider",copy-lines="all"} -cat <}} -The -[GCP documentation](https://cloud.google.com/iam/docs/creating-managing-service-account-keys) -provides information on how to generate a service account JSON file. -{{< /hint >}} - -4. Create a Kubernetes secret from the GCP JSON file -```shell {label="kube-create-secret",copy-lines="all"} -kubectl create secret \ -generic gcp-secret \ --n crossplane-system \ ---from-file=creds=./gcp-credentials.json -``` - -5. Create a _ProviderConfig_ -Include your -{{< hover label="providerconfig" line="7" >}}GCP project ID{{< /hover >}} in the -_ProviderConfig_ settings. - -{{< hint type="warning" >}} -Find your GCP project ID from the `project_id` field of the -`gcp-credentials.json` file. -{{< /hint >}} - -{{< editCode >}} -```yaml {label="providerconfig",copy-lines="all"} -cat <$@ - credentials: - source: Secret - secretRef: - namespace: crossplane-system - name: gcp-secret - key: creds -EOF -``` -{{< /editCode >}} - -{{}} - -## Create a composition -[Part 1]({{}}) created a single _managed resource_. -A _Composition_ is a template to create one or more _managed resources_ at the -same time. - -This sample _composition_ creates a Pub/Sub instance and associated GCP storage -bucket. - -{{< hint "note" >}} -This example comes from part of the GCP -[Stream messages from Pub/Sub by using Dataflow](https://cloud.google.com/pubsub/docs/stream-messages-dataflow) -guide. -{{< /hint >}} - -To create a _composition_, first define each individual managed resource. - -### Create a storage bucket object -Define a `bucket` resource using the configuration from the previous section: - -{{< hint "note" >}} -Don't apply this configuration. This YAML is part of a larger -definition. -{{< /hint >}} - -```yaml -apiVersion: storage.gcp.upbound.io/v1beta1 -kind: Bucket -metadata: - name: crossplane-quickstart-bucket -spec: - forProvider: - location: US - providerConfigRef: - name: default -``` - -### Create a Pub/Sub topic resource -Next, define a Pub/Sub `topic` resource. - -{{< hint "tip" >}} -The [Upbound Marketplace](https://marketplace.upbound.io/) provides -[schema documentation](https://marketplace.upbound.io/providers/upbound/provider-gcp/v0.28.0/resources/pubsub.gcp.upbound.io/Topic/v1beta1) -for a `topic` resource. -{{< /hint >}} - -The _GCP Provider_ defines the -{{}}apiVersion{{}} -and -{{}}kind{{}}. - -A Pub/Sub topic doesn't have requirements but using -{{}}messageStoragePolicy.allowedPersistenceRegions{{< /hover >}} -can keep messages stored in the same location as the storage bucket. - -```yaml {label="topicMR"} -apiVersion: pubsub.gcp.upbound.io/v1beta1 -kind: Topic -metadata: - name: crossplane-quickstart-topic -spec: - forProvider: - messageStoragePolicy: - - allowedPersistenceRegions: - - "us-central1" -``` - -{{< hint "note" >}} -Pub/Sub topic specifics are beyond the scope of this guide. Read the GCP -[Pub/Sub API reference](https://cloud.google.com/compute/docs/apis) -for more information. -{{}} - -### Create the composition object -The _composition_ combines the two resource definitions. - -A -{{}}Composition{{}} comes from the -{{}}Crossplane{{}} -API resources. - -Create any {{}}name{{}} for this _composition_. - -```yaml {label="compName"} -apiVersion: apiextensions.crossplane.io/v1 -kind: Composition -metadata: - name: topic-with-bucket -``` - -Add the resources to the -{{}}spec.resources{{}} -section of the _composition_. - -Give each resource a -{{}}name{{}} -and put the resource definition under the -{{}}base{{}} -key. - -{{< hint "note" >}} -Don't include resource `metadata` under the -{{}}base{{}} key. -{{< /hint >}} - -```yaml {label="specResources"} -apiVersion: apiextensions.crossplane.io/v1 -kind: Composition -metadata: - name: topic-with-bucket -spec: - resources: - - name: crossplane-quickstart-bucket - base: - apiVersion: storage.gcp.upbound.io/v1beta1 - kind: Bucket - spec: - forProvider: - location: US - - name: crossplane-quickstart-topic - base: - apiVersion: pubsub.gcp.upbound.io/v1beta1 - kind: Topic - spec: - forProvider: - messageStoragePolicy: - - allowedPersistenceRegions: - - "us-central1" -``` - -_Compositions_ are a template for generating resources. A -_composite resource_ actually creates the resources. - -A _composition_ defines which _composite resources_ can use this -template. - -_Compositions_ do this with the -{{}}spec.compositeTypeRef{{}} -definition. - -{{< hint "tip" >}} -Crossplane recommends prefacing the `kind` with an `X` to show it's a -Composition. -{{< /hint >}} - -```yaml {label="compRef"} -apiVersion: apiextensions.crossplane.io/v1 -kind: Composition -metadata: - name: topic-with-bucket -spec: - compositeTypeRef: - apiVersion: custom-api.example.org/v1alpha1 - kind: XTopicBucket - resources: - # Removed for Brevity -``` - -A _composite resource_ is actually a custom Kubernetes API type you define. The -platform team controls the kind, API endpoint and version. - - - -With this {{}}spec.compositeTypeRef{{}} -Crossplane allows _composite resources_ from the API group -{{}}custom-api.example.org{{}} -that are of -{{}}kind: XTopicBucket{{}} -to use this template to create resources. No other API group or kind can use -this template. - - -### Apply the composition -Apply the full _Composition_ to your Kubernetes cluster. - -```yaml {copy-lines="all"} -cat <}} -_Composite resource definitions_ are also called `XRDs` for short. -{{< /hint >}} - -Just like a _composition_ the -{{}}composite resource definition{{}} -is part of the -{{}}Crossplane{{}} -API group. - -The _XRD_ {{}}name{{}} is the new -API endpoint. - -{{< hint "tip" >}} -Crossplane recommends using a plural name for the _XRD_ -{{}}name{{}}. -{{< /hint >}} - -```yaml {label="xrdName"} -apiVersion: apiextensions.crossplane.io/v1 -kind: CompositeResourceDefinition -metadata: - name: xtopicbuckets.custom-api.example.org -``` - -The _XRD's_ -{{}}spec{{}} defines the new custom -API. - -### Define the API endpoint and kind -First, define the new API -{{}}group{{}}. -Next, create the API {{}}kind{{}} and -{{}}plural{{}}. - -```yaml {label="xrdGroup"} -apiVersion: apiextensions.crossplane.io/v1 -kind: CompositeResourceDefinition -metadata: - name: xtopicbuckets.custom-api.example.org -spec: - group: custom-api.example.org - names: - kind: XTopicBucket - plural: xtopicbuckets -``` - -{{}} -The _XRD_ {{}}group{{}} matches the _composition_ {{}}apiVersion{{}} and the -_XRD_ {{}}kind{{}} matches the _composition_ -{{}}compositeTypeRef.kind{{}}. - -```yaml {label="noteComp"} -kind: Composition -# Removed for brevity -spec: - compositeTypeRef: - apiVersion: custom-api.example.org/v1alpha1 - kind: XTopicBucket -``` -{{< /hint >}} - -### Set the API version -In Kubernetes, all API endpoints have a version to show the stability of the API -and track revisions. - -Apply a version to the _XRD_ with a -{{}}versions.name{{}}. -This matches the -{{}}compositeTypeRef.apiVersion{{}} - -_XRDs_ require both -{{}}versions.served{{}} -and -{{}}versions.referenceable{{}}. - -```yaml {label="xrdVersion"} -apiVersion: apiextensions.crossplane.io/v1 -kind: CompositeResourceDefinition -metadata: - name: xtopicbuckets.custom-api.example.org -spec: - group: custom-api.example.org - names: - kind: XTopicBucket - plural: xtopicbuckets - versions: - - name: v1alpha1 - served: true - referenceable: true -``` - -{{}} -For more information on defining versions in Kubernetes read the -[API versioning](https://kubernetes.io/docs/reference/using-api/#api-versioning) -section of the Kubernetes documentation. -{{< /hint >}} - -### Create the API schema -With an API endpoint named, now define the API schema, or what's allowed -inside the `spec` of the new Kubernetes object. - -{{< hint "note" >}} -_XRDs_ follow the Kubernetes -[_custom resource definition_ rules for schemas](https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#specifying-a-structural-schema). -{{}} - -Place the API -{{< hover label="xrdSchema" line="8" >}}schema{{}} -under the -{{< hover label="xrdSchema" line="7" >}}version.name{{}} - -The _XRD_ type defines the next lines. They're always the same. - - - -{{< hover label="xrdSchema" line="9" >}}openAPIV3Schema{{}} specifies -how the schema gets validated. - - -Next, the entire API is an -{{< hover label="xrdSchema" line="10" >}}object{{}} -with a -{{< hover label="xrdSchema" line="11" >}}property{{}} of -{{< hover label="xrdSchema" line="12" >}}spec{{}}. - -The -{{< hover label="xrdSchema" line="12" >}}spec{{}} is also an -{{< hover label="xrdSchema" line="13" >}}object{{}} with -{{< hover label="xrdSchema" line="14" >}}properties{{}}. - -```yaml {label="xrdSchema"} -apiVersion: apiextensions.crossplane.io/v1 -kind: CompositeResourceDefinition -# Removed for brevity -spec: - # Removed for brevity - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - type: object - properties: - spec: - type: object - properties: -``` - -{{< hint "tip" >}} -For more information on the values allowed in a _composite resource definition_ view its schema with -`kubectl explain xrd` -{{< /hint >}} - -Now, define the custom API. Your custom API continues under the last -{{}}properties{{}} definition in the -previous example. - -This custom API has one setting: - -* {{}}location{{}} - where to deploy -the resources, a choice of "EU" or "US." - - -Users can't change any other settings of the storage bucket or Pub/Sub topic. - -The{{}}location{{}} -is a {{}}string{{}} -and matches the regular expression that's -{{}}oneOf{{}} -{{}}EU{{}} -or -{{}}US{{}}. - -This API requires the setting -{{}}location{{}}. - - -```yaml {label="customAPI"} -# Removed for brevity -# schema.openAPIV3Schema.type.properties.spec -properties: - location: - type: string - oneOf: - - pattern: '^EU$' - - pattern: '^US$' -required: - - location -``` - -### Enable claims to the API -Tell this _XRD_ to offer a _claim_ by defining the _claim_ API endpoint under -the _XRD_ {{}}spec{{< /hover >}}. - -{{< hint "tip" >}} -Crossplane recommends a _Claim_ -{{}}kind{{}} match the -_Composite Resource Definition_ (XRD) -{{}}kind{{}}, -without the preceding `X`. -{{< /hint >}} - - -```yaml {label="XRDclaim"} -apiVersion: apiextensions.crossplane.io/v1 -kind: CompositeResourceDefinition -# Removed for brevity -spec: -# Removed for brevity - names: - kind: XTopicBucket - plural: xtopicbuckets - claimNames: - kind: TopicBucket - plural: topicbuckets -``` - -{{}} -The [Claims](#create-a-claim) section later in this guide discusses _claims_. -{{< /hint >}} - -### Apply the composite resource definition -Apply the complete _XRD_ to your Kubernetes cluster. - - -```yaml {copy-lines="all"} -cat <}}group{{}} -becomes the _composite resource_ -{{}}apiVersion{{}}. - -The _XRD_ {{}}kind{{}} -is the _composite resource_ -{{}}kind{{}} - -The _XRD_ API {{}}spec{{}} defines the -_composite resource_ {{}}spec{{}}. - -The _XRD_ {{}}properties{{}} section -defines the options for the _composite resource_ -{{}}spec{{}}. - -The one option is {{}}location{{}} -and it can be either {{}}EU{{}} or -{{}}US{{}}. - -This _composite resource_ uses -{{}}location: US{{}}. - -### Apply the composite resource - -Apply the composite resource to the Kubernetes cluster. - -```yaml {label="xr", copy-lines="all"} -cat <}} -Use `kubectl get ` to view a specific `kind` of _composite resource_. -View all _composite resources_ with `kubectl get composite`. -{{< /hint >}} - -```shell {copy-lines="1"} -kubectl get XTopicBucket -NAME SYNCED READY COMPOSITION AGE -my-composite-resource True True topic-with-bucket 2m3s -``` - -Both `SYNCED` and `READY` are `True` when Crossplane created the GCP resources. - -Now look at the GCP storage `bucket` and Pub/Sub `topic` _managed resources_ -with `kubectl get bucket` and `kubectl get topic`. - -```shell {copy-lines="1"} -kubectl get bucket -NAME READY SYNCED EXTERNAL-NAME AGE -my-composite-resource-m6lbx True True my-composite-resource-m6lbx 4m34s -``` - -```shell {copy-lines="1"} -kubectl get topics -NAME READY SYNCED EXTERNAL-NAME AGE -my-composite-resource-88vzp True True my-composite-resource-88vzp 4m48s -``` - -The _composite resource_ automatically generated both _managed resources_. - -Using `kubectl describe` on a _managed resource_ shows the `Owner References` is -the _composite resource_. - -```yaml {copy-lines="1"} -kubectl describe bucket | grep "Owner References" -A5 - Owner References: - API Version: custom-api.example.org/v1alpha1 - Block Owner Deletion: true - Controller: true - Kind: XTopicBucket - Name: my-composite-resource -``` - -Each _composite resource_ creates and owns a unique set of _managed resources_. -If you create a second _composite resource_ Crossplane creates a new storage -`bucket` and Pub/Sub `topic`. - -```yaml {label="xr", copy-lines="all"} -cat <}} -Delete a specific _composite resource_ with -`kubectl delete ` or -`kubectl delete composite `. -{{< /hint >}} - -Delete the second composition -```shell -kubectl delete XTopicBucket my-second-composite-resource -``` - -{{}} -There may a delay in deleting the _managed resources_. Crossplane is making API -calls to GCP and waits for GCP to confirm they deleted the resources before -updating the state in Kubernetes. -{{}} - -Now a single bucket and topic exist. - -```shell {copy-lines="1"} -kubectl get bucket -NAME READY SYNCED EXTERNAL-NAME AGE -my-composite-resource-m6lbx True True my-composite-resource-m6lbx 11m -``` - -```shell {copy-lines="1"} -kubectl get topic -NAME READY SYNCED EXTERNAL-NAME AGE -my-composite-resource-88vzp True True my-composite-resource-88vzp 11m -``` - -Delete the other _composite resource_ to remove the last `bucket` and `table` -_managed resources_. - -```shell -kubectl delete xtopicbucket my-composite-resource -``` - -_Composite resources_ are great for creating one or more related resources against -a template, but all _composite resources_ exist at the Kubernetes "cluster -level." There's no isolation between _composite resources_. Crossplane uses -_claims_ to create resources with namespace isolation. - -## Create a claim - -_Claims_, just like _composite resources_ use the custom API defined in the -_XRD_. Unlike a _composite resource_, Crossplane can create _claims_ in a -namespace. - -### Create a new Kubernetes namespace -Create a new namespace with `kubectl create namespace`. - -```shell -kubectl create namespace test -``` - -Look at the _XRD_ to see the parameters for the _claim_. -A _claim_ uses the same {{}}group{{}} -a _composite resource_ uses but a different -{{}}kind{{}}. - -```yaml {label="XRDclaim2"} -apiVersion: apiextensions.crossplane.io/v1 -kind: CompositeResourceDefinition -# Removed for brevity -spec: -# Removed for brevity - group: custom-api.example.org - claimNames: - kind: TopicBucket - plural: topicbuckets -``` - -Like the _composite resource_, create a new object with the -{{}}custom-api.example.org{{}} API -endpoint. - -The _XRD_ -{{}}claimNames.kind{{}} defines the -{{}}kind{{}}. - -The {{}}spec{{}} uses the same -API options as the _composite resource_. - -### Apply the claim -Apply the _claim_ to your Kubernetes cluster. - -```yaml {label="claim", copy-lines="all"} -cat <}} -View claims with `kubectl get ` or use `kubectl get claim` to view all -_claims_. -{{}} - -```shell {copy-lines="1"} -kubectl get TopicBucket -n test -NAME SYNCED READY CONNECTION-SECRET AGE -claimed-topic-with-bucket True True 4m37s -``` - -When Crossplane creates a _claim_, a unique _composite resource_ is also -created. View the new _composite resource_ with `kubectl get xtopicbucket`. - -```shell {copy-lines="1"} -kubectl get xtopicbucket -NAME SYNCED READY COMPOSITION AGE -claimed-topic-with-bucket-7k2lj True True topic-with-bucket 4m58s -``` - -The _composite resource_ exists at the "cluster scope" while the _claim_ exists -at the "namespace scope." - -Create a second namespace and a second claim. - -```shell {copy-lines="all"} -kubectl create namespace test2 -cat <}}) of this guide covers -_composition patches_ and making all this configuration portable in Crossplane -_packages_. - -## Next steps -* **[Continue to part 3]({{< ref "provider-gcp-part-3">}})** to create a learn - about _patching_ resources and creating Crossplane _packages_. -* Explore GCP resources that Crossplane can configure in the - [Provider CRD reference](https://marketplace.upbound.io/providers/upbound/provider-family-gcp/). -* Join the [Crossplane Slack](https://slack.crossplane.io/) and connect with Crossplane users and contributors. \ No newline at end of file diff --git a/content/v1.11/getting-started/provider-gcp-part-3.md b/content/v1.11/getting-started/provider-gcp-part-3.md deleted file mode 100644 index a6253fa9f..000000000 --- a/content/v1.11/getting-started/provider-gcp-part-3.md +++ /dev/null @@ -1,659 +0,0 @@ ---- -title: GCP Quickstart Part 3 -weight: 120 -tocHidden: true ---- - -{{< hint "important" >}} -This guide is part 3 of a series. - -Follow **[part 1]({{}})** -to install Crossplane and connect your Kubernetes cluster to GCP. - -Follow **[part 2]({{}})** to create a _composition_, -_custom resource definition_ and a _claim_. -{{< /hint >}} - -[Part 2]({{}}) created a _composite resource -definition_ to define the schema of the custom API. Users create a _claim_ to -use the custom API and apply their options. Part 2 didn't show how the options -set in a _claim_ change or get applied the associated _composite resources_. - -## Prerequisites -* Complete quickstart [part 1]({{}}) and [Part 2]({{}}) to install Crossplane and the quickstart - configurations. - -{{}} - -1. Add the Crossplane Helm repository and install Crossplane. -```shell -helm repo add \ -crossplane-stable https://charts.crossplane.io/stable -helm repo update -&& -helm install crossplane \ -crossplane-stable/crossplane \ ---namespace crossplane-system \ ---create-namespace -``` - -2. When the Crossplane pods finish installing and are ready, apply the GCP Provider. - -```yaml {label="provider",copy-lines="all"} -cat <}} -The -[GCP documentation](https://cloud.google.com/iam/docs/creating-managing-service-account-keys) -provides information on how to generate a service account JSON file. -{{< /hint >}} - -4. Create a Kubernetes secret from the GCP JSON file -```shell {label="kube-create-secret",copy-lines="all"} -kubectl create secret \ -generic gcp-secret \ --n crossplane-system \ ---from-file=creds=./gcp-credentials.json -``` - -5. Create a _ProviderConfig_ -Include your -{{< hover label="providerconfig" line="7" >}}GCP project ID{{< /hover >}} in the -_ProviderConfig_ settings. - -{{< hint type="warning" >}} -Find your GCP project ID from the `project_id` field of the -`gcp-credentials.json` file. -{{< /hint >}} - -{{< editCode >}} -```yaml {label="providerconfig",copy-lines="all"} -cat <$@ - credentials: - source: Secret - secretRef: - namespace: crossplane-system - name: gcp-secret - key: creds -EOF -``` -{{< /editCode >}} - - -6. Create a _composition_ -```yaml {copy-lines="all"} -cat <}} - -## Enable composition patches -In a _composition_, `patches` map fields in the custom API to fields inside the -_managed resources_. - -The example _composition_ has two _managed resources_, a -{{}}bucket{{}} and a -{{}}topic{{}}. - -```yaml {label="compResources"} -apiVersion: apiextensions.crossplane.io/v1 -kind: Composition -# Removed for Brevity -resources: - - name: crossplane-quickstart-bucket - base: - apiVersion: storage.gcp.upbound.io/v1beta1 - kind: Bucket - spec: - forProvider: - location: US - - name: crossplane-quickstart-topic - base: - apiVersion: pubsub.gcp.upbound.io/v1beta1 - kind: Topic - spec: - forProvider: - messageStoragePolicy: - - allowedPersistenceRegions: - - "us-central1" -``` - -The custom API defined a single option, -{{}}location{{}}. A -{{}}location{{}} can be either -{{}}EU{{}} or -{{}}US{{}}. - - -```yaml {label="xrdSnip"} -apiVersion: apiextensions.crossplane.io/v1 -kind: CompositeResourceDefinition -# Removed for brevity -spec: - group: custom-api.example.org - names: - kind: XDatabase -# Removed for brevity - spec: - type: object - properties: - location: - type: string - oneOf: - - pattern: '^EU$' - - pattern: '^US$' -``` - -Creating a _composition_ `patch` allows Crossplane to update the settings of a -_composite resource_. Patches apply to an individual _managed resource_ -inside the _composition_. - -A {{}}patch{{}} has a -{{}}fromField{{}} and a -{{}}toField{{}} specifying which value -_from_ the custom API should apply _to_ a field in the _managed resource_. -Patches can create a -{{}}transform{{}} to change the _from_ -field before it's applied. - -The transform -{{}}type{{}} is what kind of change to -make on the _from_ field. Types of changes could include appending a string, -preforming a math operation or mapping one value to another. - -Applying a {{}}patch{{}} to the -{{}}Topic{{}} uses the custom API -{{}}spec.location{{}} field to use as the -_managed resource_ -{{}}allowedPersistenceRegions{{}} value. - - -The custom API value "EU" is -{{}}mapped{{}} to the value -"europe-central2" and "US" is -{{}}mapped{{}} to the value -"us-central1." - - - -```yaml {label="patch"} -apiVersion: apiextensions.crossplane.io/v1 -kind: Composition -# Removed for Brevity -resources: - - name: crossplane-quickstart-topic - base: - apiVersion: pubsub.gcp.upbound.io/v1beta1 - kind: Topic - spec: - forProvider: - messageStoragePolicy: - - allowedPersistenceRegions: - - "us-central1" - patches: - - fromFieldPath: "spec.location" - toFieldPath: "spec.forProvider.messageStoragePolicy[*].allowedPersistenceRegions[*]" - transforms: - - type: map - map: - EU: "europe-central2" - US: "us-central1" -``` - -Patching is a powerful tool enabling simpler or abstracted APIs. Developers -aren't required to know the specific GCP region, just the abstracted -option of "EU" or "US." - - -### Apply the updated composition -Apply a similar `patch` to the `Bucket` _managed resource_ and apply the updated -_composition_. - -```yaml -cat <}}location{{}} to "EU." - -```yaml {label="claim"} -cat <}}europe-central2{{< /hover >}}. - -```shell {copy-lines="1",label="topicLocation"} -kubectl describe topic | grep "For Provider" -A3 - For Provider: - Message Storage Policy: - Allowed Persistence Regions: - europe-central2 -``` - -Describe the `Bucket` resource to see the GCP location is also set to -{{}}EU{{}}. - -```shell {copy-lines="1",label="bucketLocation"} -kubectl describe bucket | grep "For Provider" -A1 - For Provider: - Location: EU -``` - - -Using {{}}location: "EU"{{}} in the -claim patches the _composite resource_, updating the `Topic` GCP region from -`us-central1` to `europe-central-2` and the `Bucket` from GCP region `US` to GCP -region `EU`. -The developer creating the claim isn't required to know which specific GCP -region or the naming conventions. Using the abstract API options of "EU" or "US" -the developer places their resources in the desired location. - -In this example, patching also allows platform teams to ensure all resources are -in the same location. - - -Deleting the claim removes the _managed resources_. - -{{}} -The _managed resources_ take up to 5 minutes to delete. -{{< /hint >}} - -```shell -kubectl delete TopicBucket claimed-eu-topic-with-bucket -n test -``` - -## Create a Crossplane configuration package - -Creating a configuration package makes your Crossplane custom APIs portable -and versioned. - -Crossplane _configuration packages_ allow users to combine their _custom -resource definition_ and _composition_ files into an OCI image. - -{{< hint "note" >}} -The [Open Container Initiative](https://opencontainers.org/faq/) -defines the OCI image standard. -An OCI images is a standard way to package data. -{{< /hint >}} - -You can host configuration packages in image registries like -[Docker Hub](https://hub.docker.com/) or the -[Upbound Marketplace](https://marketplace.upbound.io/). - -Crossplane can download and install configuration packages into a Kubernetes -cluster. - -Building and installing configuration packages requires an OCI image compatible -tool. - -{{< hint "note" >}} -You can use any software that builds OCI images. This includes -[Docker](https://www.docker.com/) or -[Upbound's Up command-line tool](https://github.com/upbound/up) -{{< /hint >}} - -A configuration package includes three files: -* `crossplane.yaml` defines the metadata of the package. -* `definition.yaml` is the _composite resource definition_ for the package. -* `composition.yaml` is the _composition_ template for the package. - - - -### Create a crossplane.yaml file - -Configuration packages describe their contents and requirements with a -`crossplane.yaml` file. - -The `crossplane.yaml` file lists the required Crossplane _providers_ and their -compatible versions as well as the required Crossplane version. - -The Crossplane -{{}}meta.pkg{{}} API defines the schema -for a -{{}}Configuration{{}}. - -Inside the {{}}spec{{}} define the -required Crossplane -{{}}version{{}}. - -The {{}}dependsOn{{}} section lists the -dependencies for a package. - -This package lists the Upbound -{{}}provider-gcp{{}} -version {{}}0.28.0{{}} or later as a -dependency. - -{{}} -Crossplane automatically installs dependencies. Dependencies can include other -configuration packages. -{{< /hint >}} - -```yaml {label="xpyaml"} -apiVersion: meta.pkg.crossplane.io/v1 -kind: Configuration -metadata: - name: crossplane-gcp-quickstart -spec: - crossplane: - version: ">=v1.11.0" - dependsOn: - - provider: xpkg.upbound.io/upbound/provider-gcp - version: ">=v0.28.0" -``` - -Create a new directory and save the `crossplane.yaml` file. - -```yaml {copy-lines="all"} -mkdir crossplane-gcp-quickstart -cat < crossplane-gcp-quickstart/crossplane.yaml -apiVersion: meta.pkg.crossplane.io/v1 -kind: Configuration -metadata: - name: crossplane-gcp-quickstart -spec: - crossplane: - version: ">=v1.11.0" - dependsOn: - - provider: xpkg.upbound.io/upbound/provider-gcp - version: ">=v0.28.0" -EOF -``` - - - -### Create a definition.yaml file - - -A configuration package requires a _composite resource definition_ (XRD) to define the -custom API. - -Save the _XRD_ as `definition.yaml` in the same directory as the -`crossplane.yaml` file. - -```yaml {copy-lines="all"} -cat < crossplane-gcp-quickstart/definition.yaml -apiVersion: apiextensions.crossplane.io/v1 -kind: CompositeResourceDefinition -metadata: - name: xtopicbuckets.custom-api.example.org -spec: - group: custom-api.example.org - names: - kind: XTopicBucket - plural: xtopicbuckets - versions: - - name: v1alpha1 - served: true - referenceable: true - schema: - openAPIV3Schema: - type: object - properties: - spec: - type: object - properties: - location: - type: string - oneOf: - - pattern: '^EU$' - - pattern: '^US$' - required: - - location - claimNames: - kind: TopicBucket - plural: topicbuckets -EOF -``` - - - -### Create a composition.yaml file - - -The _composition_ template creates the _managed resources_ and allows _patches_ -to customize the _managed resources_. - -Copy the _composition_ into the `composition.yaml` file in the same directory as -`crossplane.yaml`. - -```yaml -cat < crossplane-gcp-quickstart/composition.yaml -apiVersion: apiextensions.crossplane.io/v1 -kind: Composition -metadata: - name: topic-with-bucket -spec: - compositeTypeRef: - apiVersion: custom-api.example.org/v1alpha1 - kind: XTopicBucket - resources: - - name: crossplane-quickstart-bucket - base: - apiVersion: storage.gcp.upbound.io/v1beta1 - kind: Bucket - spec: - forProvider: - location: "US" - patches: - - fromFieldPath: "spec.location" - toFieldPath: "spec.forProvider.location" - transforms: - - type: map - map: - EU: "EU" - US: "US" - - name: crossplane-quickstart-topic - base: - apiVersion: pubsub.gcp.upbound.io/v1beta1 - kind: Topic - spec: - forProvider: - messageStoragePolicy: - - allowedPersistenceRegions: - - "us-central1" - patches: - - fromFieldPath: "spec.location" - toFieldPath: "spec.forProvider.messageStoragePolicy[*].allowedPersistenceRegions[*]" - transforms: - - type: map - map: - EU: "europe-central2" - US: "us-central1" -EOF -``` - -### Install the Crossplane command-line -To build a configuration package install the Crossplane Kubernetes command-line -extension. - -```shell -wget "https://raw.githubusercontent.com/crossplane/crossplane/master/install.sh" -chmod +x install.sh -./install.sh -sudo mv crossplane /usr/local/bin -``` - -Verify the Crossplane command-line installed with `crossplane --help` - -```shell -crossplane --help -Usage: crossplane - -A command line tool for interacting with Crossplane. - -Flags: - -h, --help Show context-sensitive help. - -v, --version Print version and quit. - --verbose Print verbose logging statements. -# Ouptut removed for brevity -``` - -### Build a configuration package - -Use the `crossplane` CLI to create an `.xpkg` file containing the -custom APIs and Crossplane configuration. - -```shell -crossplane build configuration -f crossplane-gcp-quickstart/ --name="crossplane-gcp-quickstart" -``` - -Now an `.xpkg` OCI image is inside the `crossplane-gcp-quickstart` directory. - -```shell -ls crossplane-gcp-quickstart/ -composition.yaml crossplane-gcp-quickstart.xpkg crossplane.yaml definition.yaml -``` - -## Next steps -* Explore GCP resources that Crossplane can configure in the [Provider CRD reference](https://marketplace.upbound.io/providers/upbound/provider-family-gcp/). -* Join the [Crossplane Slack](https://slack.crossplane.io/) and connect with Crossplane users and contributors. -* Read more about [Crossplane concepts]({{}}) \ No newline at end of file diff --git a/content/v1.11/getting-started/provider-gcp.md b/content/v1.11/getting-started/provider-gcp.md deleted file mode 100644 index 5f5c7d5ac..000000000 --- a/content/v1.11/getting-started/provider-gcp.md +++ /dev/null @@ -1,1255 +0,0 @@ ---- -title: GCP Quickstart -weight: 140 ---- - -Connect Crossplane to GCP to create and manage cloud resources from Kubernetes -with the -[Upbound GCP Provider](https://marketplace.upbound.io/providers/upbound/provider-gcp). - -This guide is in three parts: -* Part 1 walks through installing Crossplane, configuring the provider to -authenticate to GCP and creating a _Managed Resource_ in GCP directly from your -Kubernetes cluster. This shows Crossplane can communicate with GCP. -* [Part 2]({{< ref "provider-gcp-part-2" >}}) creates a -_Composite Resource Definition_ (XRD), _Composite Resource_ (XR) and a _Claim_ -(XRC) to show how to create and use custom APIs. -* [Part 3]({{< ref "provider-gcp-part-3" >}}) demonstrates how to patch -_Compositions_ with values used in a _Claim_ and how to build a Crossplane -_Package_ to make a Crossplane platform portable and reusable. -## Prerequisites -This quickstart requires: -* a Kubernetes cluster with at least 6 GB of RAM -* permissions to create pods and secrets in the Kubernetes cluster -* [Helm](https://helm.sh/) version `v3.2.0` or later -* a GCP account with permissions to create a storage bucket -* GCP [account keys](https://cloud.google.com/iam/docs/creating-managing-service-account-keys) -* GCP [Project ID](https://support.google.com/googleapi/answer/7014113?hl=en) - -## Install Crossplane - -Crossplane installs into an existing Kubernetes cluster. - -{{< hint type="tip" >}} -If you don't have a Kubernetes cluster create one locally with -[Kind](https://kind.sigs.k8s.io/). -{{< /hint >}} - -### Install the Crossplane Helm chart - -Helm enables Crossplane to install all its Kubernetes components through a -_Helm Chart_. - -Enable the Crossplane Helm Chart repository: - -```shell -helm repo add \ -crossplane-stable https://charts.crossplane.io/stable && helm repo update -``` - -Run the Helm dry-run to see all the Crossplane components Helm installs. - -```shell -helm install crossplane \ -crossplane-stable/crossplane \ ---dry-run --debug \ ---namespace crossplane-system \ ---create-namespace -``` -{{}} -```shell -helm install crossplane \ -crossplane-stable/crossplane \ ---dry-run --debug \ ---namespace crossplane-system \ ---create-namespace -install.go:193: [debug] Original chart version: "" -install.go:210: [debug] CHART PATH: /home/vagrant/.cache/helm/repository/crossplane-1.10.1.tgz - -NAME: crossplane -LAST DEPLOYED: Thu Jan 19 15:52:08 2023 -NAMESPACE: crossplane-system -STATUS: pending-install -REVISION: 1 -TEST SUITE: None -USER-SUPPLIED VALUES: -{} - -COMPUTED VALUES: -affinity: {} -args: {} -configuration: - packages: [] -customAnnotations: {} -customLabels: {} -deploymentStrategy: RollingUpdate -extraEnvVarsCrossplane: {} -extraEnvVarsRBACManager: {} -image: - pullPolicy: IfNotPresent - repository: crossplane/crossplane - tag: v1.10.1 -imagePullSecrets: {} -leaderElection: true -metrics: - enabled: false -nodeSelector: {} -packageCache: - medium: "" - pvc: "" - sizeLimit: 5Mi -podSecurityContextCrossplane: {} -podSecurityContextRBACManager: {} -priorityClassName: "" -provider: - packages: [] -rbacManager: - affinity: {} - args: {} - deploy: true - leaderElection: true - managementPolicy: All - nodeSelector: {} - replicas: 1 - skipAggregatedClusterRoles: false - tolerations: {} -registryCaBundleConfig: {} -replicas: 1 -resourcesCrossplane: - limits: - cpu: 100m - memory: 512Mi - requests: - cpu: 100m - memory: 256Mi -resourcesRBACManager: - limits: - cpu: 100m - memory: 512Mi - requests: - cpu: 100m - memory: 256Mi -securityContextCrossplane: - allowPrivilegeEscalation: false - readOnlyRootFilesystem: true - runAsGroup: 65532 - runAsUser: 65532 -securityContextRBACManager: - allowPrivilegeEscalation: false - readOnlyRootFilesystem: true - runAsGroup: 65532 - runAsUser: 65532 -serviceAccount: - customAnnotations: {} -tolerations: {} -webhooks: - enabled: false - -HOOKS: -MANIFEST: ---- -# Source: crossplane/templates/rbac-manager-serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: rbac-manager - labels: - app: crossplane - helm.sh/chart: crossplane-1.10.1 - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: cloud-infrastructure-controller - app.kubernetes.io/part-of: crossplane - app.kubernetes.io/name: crossplane - app.kubernetes.io/instance: crossplane - app.kubernetes.io/version: "1.10.1" ---- -# Source: crossplane/templates/serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: crossplane - labels: - app: crossplane - helm.sh/chart: crossplane-1.10.1 - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: cloud-infrastructure-controller - app.kubernetes.io/part-of: crossplane - app.kubernetes.io/name: crossplane - app.kubernetes.io/instance: crossplane - app.kubernetes.io/version: "1.10.1" ---- -# Source: crossplane/templates/clusterrole.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: crossplane - labels: - app: crossplane - helm.sh/chart: crossplane-1.10.1 - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: cloud-infrastructure-controller - app.kubernetes.io/part-of: crossplane - app.kubernetes.io/name: crossplane - app.kubernetes.io/instance: crossplane - app.kubernetes.io/version: "1.10.1" -aggregationRule: - clusterRoleSelectors: - - matchLabels: - rbac.crossplane.io/aggregate-to-crossplane: "true" ---- -# Source: crossplane/templates/clusterrole.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: crossplane:system:aggregate-to-crossplane - labels: - app: crossplane - helm.sh/chart: crossplane-1.10.1 - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: cloud-infrastructure-controller - app.kubernetes.io/part-of: crossplane - app.kubernetes.io/name: crossplane - app.kubernetes.io/instance: crossplane - app.kubernetes.io/version: "1.10.1" - crossplane.io/scope: "system" - rbac.crossplane.io/aggregate-to-crossplane: "true" -rules: -- apiGroups: - - "" - resources: - - events - verbs: - - create - - update - - patch - - delete -- apiGroups: - - apiextensions.k8s.io - resources: - - customresourcedefinitions - verbs: - - "*" -- apiGroups: - - "" - resources: - - secrets - verbs: - - get - - list - - watch - - create - - update - - patch - - delete -- apiGroups: - - "" - resources: - - serviceaccounts - - services - verbs: - - "*" -- apiGroups: - - apiextensions.crossplane.io - - pkg.crossplane.io - - secrets.crossplane.io - resources: - - "*" - verbs: - - "*" -- apiGroups: - - extensions - - apps - resources: - - deployments - verbs: - - get - - list - - create - - update - - patch - - delete - - watch -- apiGroups: - - "" - - coordination.k8s.io - resources: - - configmaps - - leases - verbs: - - get - - list - - create - - update - - patch - - watch - - delete -- apiGroups: - - admissionregistration.k8s.io - resources: - - validatingwebhookconfigurations - - mutatingwebhookconfigurations - verbs: - - get - - list - - create - - update - - patch - - watch - - delete ---- -# Source: crossplane/templates/rbac-manager-allowed-provider-permissions.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: crossplane:allowed-provider-permissions - labels: - app: crossplane - helm.sh/chart: crossplane-1.10.1 - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: cloud-infrastructure-controller - app.kubernetes.io/part-of: crossplane - app.kubernetes.io/name: crossplane - app.kubernetes.io/instance: crossplane - app.kubernetes.io/version: "1.10.1" -aggregationRule: - clusterRoleSelectors: - - matchLabels: - rbac.crossplane.io/aggregate-to-allowed-provider-permissions: "true" ---- -# Source: crossplane/templates/rbac-manager-clusterrole.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: crossplane-rbac-manager - labels: - app: crossplane - helm.sh/chart: crossplane-1.10.1 - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: cloud-infrastructure-controller - app.kubernetes.io/part-of: crossplane - app.kubernetes.io/name: crossplane - app.kubernetes.io/instance: crossplane - app.kubernetes.io/version: "1.10.1" -rules: -- apiGroups: - - "" - resources: - - events - verbs: - - create - - update - - patch - - delete -- apiGroups: - - "" - resources: - - namespaces - - serviceaccounts - verbs: - - get - - list - - watch -- apiGroups: - - apiextensions.crossplane.io - resources: - - compositeresourcedefinitions - verbs: - - get - - list - - watch -- apiGroups: - - pkg.crossplane.io - resources: - - providerrevisions - verbs: - - get - - list - - watch -- apiGroups: - - apiextensions.k8s.io - resources: - - customresourcedefinitions - verbs: - - get - - list - - watch -- apiGroups: - - rbac.authorization.k8s.io - resources: - - clusterroles - - roles - verbs: - - get - - list - - watch - - create - - update - - patch - # The RBAC manager may grant access it does not have. - - escalate -- apiGroups: - - rbac.authorization.k8s.io - resources: - - clusterroles - verbs: - - bind -- apiGroups: - - rbac.authorization.k8s.io - resources: - - clusterrolebindings - verbs: - - "*" -- apiGroups: - - "" - - coordination.k8s.io - resources: - - configmaps - - leases - verbs: - - get - - list - - create - - update - - patch - - watch - - delete ---- -# Source: crossplane/templates/rbac-manager-managed-clusterroles.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: crossplane-admin - labels: - app: crossplane - helm.sh/chart: crossplane-1.10.1 - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: cloud-infrastructure-controller - app.kubernetes.io/part-of: crossplane - app.kubernetes.io/name: crossplane - app.kubernetes.io/instance: crossplane - app.kubernetes.io/version: "1.10.1" -aggregationRule: - clusterRoleSelectors: - - matchLabels: - rbac.crossplane.io/aggregate-to-admin: "true" ---- -# Source: crossplane/templates/rbac-manager-managed-clusterroles.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: crossplane-edit - labels: - app: crossplane - helm.sh/chart: crossplane-1.10.1 - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: cloud-infrastructure-controller - app.kubernetes.io/part-of: crossplane - app.kubernetes.io/name: crossplane - app.kubernetes.io/instance: crossplane - app.kubernetes.io/version: "1.10.1" -aggregationRule: - clusterRoleSelectors: - - matchLabels: - rbac.crossplane.io/aggregate-to-edit: "true" ---- -# Source: crossplane/templates/rbac-manager-managed-clusterroles.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: crossplane-view - labels: - app: crossplane - helm.sh/chart: crossplane-1.10.1 - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: cloud-infrastructure-controller - app.kubernetes.io/part-of: crossplane - app.kubernetes.io/name: crossplane - app.kubernetes.io/instance: crossplane - app.kubernetes.io/version: "1.10.1" -aggregationRule: - clusterRoleSelectors: - - matchLabels: - rbac.crossplane.io/aggregate-to-view: "true" ---- -# Source: crossplane/templates/rbac-manager-managed-clusterroles.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: crossplane-browse - labels: - app: crossplane - helm.sh/chart: crossplane-1.10.1 - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: cloud-infrastructure-controller - app.kubernetes.io/part-of: crossplane - app.kubernetes.io/name: crossplane - app.kubernetes.io/instance: crossplane - app.kubernetes.io/version: "1.10.1" -aggregationRule: - clusterRoleSelectors: - - matchLabels: - rbac.crossplane.io/aggregate-to-browse: "true" ---- -# Source: crossplane/templates/rbac-manager-managed-clusterroles.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: crossplane:aggregate-to-admin - labels: - rbac.crossplane.io/aggregate-to-admin: "true" - app: crossplane - helm.sh/chart: crossplane-1.10.1 - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: cloud-infrastructure-controller - app.kubernetes.io/part-of: crossplane - app.kubernetes.io/name: crossplane - app.kubernetes.io/instance: crossplane - app.kubernetes.io/version: "1.10.1" -rules: -# Crossplane administrators have access to view events. -- apiGroups: [""] - resources: [events] - verbs: [get, list, watch] -# Crossplane administrators must create provider credential secrets, and may -# need to read or otherwise interact with connection secrets. They may also need -# to create or annotate namespaces. -- apiGroups: [""] - resources: [secrets, namespaces] - verbs: ["*"] -# Crossplane administrators have access to view the roles that they may be able -# to grant to other subjects. -- apiGroups: [rbac.authorization.k8s.io] - resources: [clusterroles, roles] - verbs: [get, list, watch] -# Crossplane administrators have access to grant the access they have to other -# subjects. -- apiGroups: [rbac.authorization.k8s.io] - resources: [clusterrolebindings, rolebindings] - verbs: ["*"] -# Crossplane administrators have full access to built in Crossplane types. -- apiGroups: - - apiextensions.crossplane.io - resources: ["*"] - verbs: ["*"] -- apiGroups: - - pkg.crossplane.io - resources: [providers, configurations, providerrevisions, configurationrevisions] - verbs: ["*"] -# Crossplane administrators have access to view CRDs in order to debug XRDs. -- apiGroups: [apiextensions.k8s.io] - resources: [customresourcedefinitions] - verbs: [get, list, watch] ---- -# Source: crossplane/templates/rbac-manager-managed-clusterroles.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: crossplane:aggregate-to-edit - labels: - rbac.crossplane.io/aggregate-to-edit: "true" - app: crossplane - helm.sh/chart: crossplane-1.10.1 - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: cloud-infrastructure-controller - app.kubernetes.io/part-of: crossplane - app.kubernetes.io/name: crossplane - app.kubernetes.io/instance: crossplane - app.kubernetes.io/version: "1.10.1" -rules: -# Crossplane editors have access to view events. -- apiGroups: [""] - resources: [events] - verbs: [get, list, watch] -# Crossplane editors must create provider credential secrets, and may need to -# read or otherwise interact with connection secrets. -- apiGroups: [""] - resources: [secrets] - verbs: ["*"] -# Crossplane editors may see which namespaces exist, but not edit them. -- apiGroups: [""] - resources: [namespaces] - verbs: [get, list, watch] -# Crossplane editors have full access to built in Crossplane types. -- apiGroups: - - apiextensions.crossplane.io - resources: ["*"] - verbs: ["*"] -- apiGroups: - - pkg.crossplane.io - resources: [providers, configurations, providerrevisions, configurationrevisions] - verbs: ["*"] ---- -# Source: crossplane/templates/rbac-manager-managed-clusterroles.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: crossplane:aggregate-to-view - labels: - rbac.crossplane.io/aggregate-to-view: "true" - app: crossplane - helm.sh/chart: crossplane-1.10.1 - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: cloud-infrastructure-controller - app.kubernetes.io/part-of: crossplane - app.kubernetes.io/name: crossplane - app.kubernetes.io/instance: crossplane - app.kubernetes.io/version: "1.10.1" -rules: -# Crossplane viewers have access to view events. -- apiGroups: [""] - resources: [events] - verbs: [get, list, watch] -# Crossplane viewers may see which namespaces exist. -- apiGroups: [""] - resources: [namespaces] - verbs: [get, list, watch] -# Crossplane viewers have read-only access to built in Crossplane types. -- apiGroups: - - apiextensions.crossplane.io - resources: ["*"] - verbs: [get, list, watch] -- apiGroups: - - pkg.crossplane.io - resources: [providers, configurations, providerrevisions, configurationrevisions] - verbs: [get, list, watch] ---- -# Source: crossplane/templates/rbac-manager-managed-clusterroles.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: crossplane:aggregate-to-browse - labels: - rbac.crossplane.io/aggregate-to-browse: "true" - app: crossplane - helm.sh/chart: crossplane-1.10.1 - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: cloud-infrastructure-controller - app.kubernetes.io/part-of: crossplane - app.kubernetes.io/name: crossplane - app.kubernetes.io/instance: crossplane - app.kubernetes.io/version: "1.10.1" -rules: -# Crossplane browsers have access to view events. -- apiGroups: [""] - resources: [events] - verbs: [get, list, watch] -# Crossplane browsers have read-only access to compositions and XRDs. This -# allows them to discover and select an appropriate composition when creating a -# resource claim. -- apiGroups: - - apiextensions.crossplane.io - resources: ["*"] - verbs: [get, list, watch] ---- -# Source: crossplane/templates/rbac-manager-managed-clusterroles.yaml -# The below ClusterRoles are aggregated to the namespaced RBAC roles created by -# the Crossplane RBAC manager when it is running in --manage=All mode. -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: crossplane:aggregate-to-ns-admin - labels: - rbac.crossplane.io/aggregate-to-ns-admin: "true" - rbac.crossplane.io/base-of-ns-admin: "true" - app: crossplane - helm.sh/chart: crossplane-1.10.1 - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: cloud-infrastructure-controller - app.kubernetes.io/part-of: crossplane - app.kubernetes.io/name: crossplane - app.kubernetes.io/instance: crossplane - app.kubernetes.io/version: "1.10.1" -rules: -# Crossplane namespace admins have access to view events. -- apiGroups: [""] - resources: [events] - verbs: [get, list, watch] -# Crossplane namespace admins may need to read or otherwise interact with -# resource claim connection secrets. -- apiGroups: [""] - resources: [secrets] - verbs: ["*"] -# Crossplane namespace admins have access to view the roles that they may be -# able to grant to other subjects. -- apiGroups: [rbac.authorization.k8s.io] - resources: [roles] - verbs: [get, list, watch] -# Crossplane namespace admins have access to grant the access they have to other -# subjects. -- apiGroups: [rbac.authorization.k8s.io] - resources: [rolebindings] - verbs: ["*"] ---- -# Source: crossplane/templates/rbac-manager-managed-clusterroles.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: crossplane:aggregate-to-ns-edit - labels: - rbac.crossplane.io/aggregate-to-ns-edit: "true" - rbac.crossplane.io/base-of-ns-edit: "true" - app: crossplane - helm.sh/chart: crossplane-1.10.1 - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: cloud-infrastructure-controller - app.kubernetes.io/part-of: crossplane - app.kubernetes.io/name: crossplane - app.kubernetes.io/instance: crossplane - app.kubernetes.io/version: "1.10.1" -rules: -# Crossplane namespace editors have access to view events. -- apiGroups: [""] - resources: [events] - verbs: [get, list, watch] -# Crossplane namespace editors may need to read or otherwise interact with -# resource claim connection secrets. -- apiGroups: [""] - resources: [secrets] - verbs: ["*"] ---- -# Source: crossplane/templates/rbac-manager-managed-clusterroles.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: crossplane:aggregate-to-ns-view - labels: - rbac.crossplane.io/aggregate-to-ns-view: "true" - rbac.crossplane.io/base-of-ns-view: "true" - app: crossplane - helm.sh/chart: crossplane-1.10.1 - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: cloud-infrastructure-controller - app.kubernetes.io/part-of: crossplane - app.kubernetes.io/name: crossplane - app.kubernetes.io/instance: crossplane - app.kubernetes.io/version: "1.10.1" -rules: -# Crossplane namespace viewers have access to view events. -- apiGroups: [""] - resources: [events] - verbs: [get, list, watch] ---- -# Source: crossplane/templates/clusterrolebinding.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: crossplane - labels: - app: crossplane - helm.sh/chart: crossplane-1.10.1 - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: cloud-infrastructure-controller - app.kubernetes.io/part-of: crossplane - app.kubernetes.io/name: crossplane - app.kubernetes.io/instance: crossplane - app.kubernetes.io/version: "1.10.1" -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: crossplane -subjects: -- kind: ServiceAccount - name: crossplane - namespace: crossplane-system ---- -# Source: crossplane/templates/rbac-manager-clusterrolebinding.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: crossplane-rbac-manager - labels: - app: crossplane - helm.sh/chart: crossplane-1.10.1 - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: cloud-infrastructure-controller - app.kubernetes.io/part-of: crossplane - app.kubernetes.io/name: crossplane - app.kubernetes.io/instance: crossplane - app.kubernetes.io/version: "1.10.1" -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: crossplane-rbac-manager -subjects: -- kind: ServiceAccount - name: rbac-manager - namespace: crossplane-system ---- -# Source: crossplane/templates/rbac-manager-managed-clusterroles.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: crossplane-admin - labels: - app: crossplane - helm.sh/chart: crossplane-1.10.1 - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: cloud-infrastructure-controller - app.kubernetes.io/part-of: crossplane - app.kubernetes.io/name: crossplane - app.kubernetes.io/instance: crossplane - app.kubernetes.io/version: "1.10.1" -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: crossplane-admin -subjects: -- apiGroup: rbac.authorization.k8s.io - kind: Group - name: crossplane:masters ---- -# Source: crossplane/templates/deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: crossplane - labels: - app: crossplane - release: crossplane - helm.sh/chart: crossplane-1.10.1 - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: cloud-infrastructure-controller - app.kubernetes.io/part-of: crossplane - app.kubernetes.io/name: crossplane - app.kubernetes.io/instance: crossplane - app.kubernetes.io/version: "1.10.1" -spec: - replicas: 1 - selector: - matchLabels: - app: crossplane - release: crossplane - strategy: - type: RollingUpdate - template: - metadata: - labels: - app: crossplane - release: crossplane - helm.sh/chart: crossplane-1.10.1 - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: cloud-infrastructure-controller - app.kubernetes.io/part-of: crossplane - app.kubernetes.io/name: crossplane - app.kubernetes.io/instance: crossplane - app.kubernetes.io/version: "1.10.1" - spec: - securityContext: - {} - serviceAccountName: crossplane - initContainers: - - image: crossplane/crossplane:v1.10.1 - args: - - core - - init - imagePullPolicy: IfNotPresent - name: crossplane-init - resources: - limits: - cpu: 100m - memory: 512Mi - requests: - cpu: 100m - memory: 256Mi - securityContext: - allowPrivilegeEscalation: false - readOnlyRootFilesystem: true - runAsGroup: 65532 - runAsUser: 65532 - env: - - name: POD_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: POD_SERVICE_ACCOUNT - valueFrom: - fieldRef: - fieldPath: spec.serviceAccountName - containers: - - image: crossplane/crossplane:v1.10.1 - args: - - core - - start - imagePullPolicy: IfNotPresent - name: crossplane - resources: - limits: - cpu: 100m - memory: 512Mi - requests: - cpu: 100m - memory: 256Mi - securityContext: - allowPrivilegeEscalation: false - readOnlyRootFilesystem: true - runAsGroup: 65532 - runAsUser: 65532 - env: - - name: POD_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: LEADER_ELECTION - value: "true" - volumeMounts: - - mountPath: /cache - name: package-cache - volumes: - - name: package-cache - emptyDir: - medium: - sizeLimit: 5Mi ---- -# Source: crossplane/templates/rbac-manager-deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: crossplane-rbac-manager - labels: - app: crossplane-rbac-manager - release: crossplane - helm.sh/chart: crossplane-1.10.1 - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: cloud-infrastructure-controller - app.kubernetes.io/part-of: crossplane - app.kubernetes.io/name: crossplane - app.kubernetes.io/instance: crossplane - app.kubernetes.io/version: "1.10.1" -spec: - replicas: 1 - selector: - matchLabels: - app: crossplane-rbac-manager - release: crossplane - strategy: - type: RollingUpdate - template: - metadata: - labels: - app: crossplane-rbac-manager - release: crossplane - helm.sh/chart: crossplane-1.10.1 - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: cloud-infrastructure-controller - app.kubernetes.io/part-of: crossplane - app.kubernetes.io/name: crossplane - app.kubernetes.io/instance: crossplane - app.kubernetes.io/version: "1.10.1" - spec: - securityContext: - {} - serviceAccountName: rbac-manager - initContainers: - - image: crossplane/crossplane:v1.10.1 - args: - - rbac - - init - imagePullPolicy: IfNotPresent - name: crossplane-init - resources: - limits: - cpu: 100m - memory: 512Mi - requests: - cpu: 100m - memory: 256Mi - securityContext: - allowPrivilegeEscalation: false - readOnlyRootFilesystem: true - runAsGroup: 65532 - runAsUser: 65532 - containers: - - image: crossplane/crossplane:v1.10.1 - args: - - rbac - - start - - --manage=All - - --provider-clusterrole=crossplane:allowed-provider-permissions - imagePullPolicy: IfNotPresent - name: crossplane - resources: - limits: - cpu: 100m - memory: 512Mi - requests: - cpu: 100m - memory: 256Mi - securityContext: - allowPrivilegeEscalation: false - readOnlyRootFilesystem: true - runAsGroup: 65532 - runAsUser: 65532 - env: - - name: LEADER_ELECTION - value: "true" - -NOTES: -Release: crossplane - -Chart Name: crossplane -Chart Description: Crossplane is an open source Kubernetes add-on that enables -platform teams to assemble infrastructure from multiple vendors, and expose -higher level self-service APIs for application teams to consume. -Chart Version: 1.10.1 -Chart Application Version: 1.10.1 - -Kube Version: v1.24.9 -``` -{{< /expand >}} - -Install the Crossplane components using `helm install`. - -```shell -helm install crossplane \ -crossplane-stable/crossplane \ ---namespace crossplane-system \ ---create-namespace -``` - -Verify Crossplane installed with `kubectl get pods`. - -```shell {copy-lines="1"} -kubectl get pods -n crossplane-system -NAME READY STATUS RESTARTS AGE -crossplane-644f4d5958-97m5v 1/1 Running 0 16s -crossplane-rbac-manager-7f8ccd95f8-nkq78 1/1 Running 0 16s -``` - -Installing Crossplane creates new Kubernetes API end-points. Look at the new -API end-points with `kubectl api-resources | grep crossplane`. - -```shell {label="grep",copy-lines="1"} -kubectl api-resources | grep crossplane -compositeresourcedefinitions xrd,xrds apiextensions.crossplane.io/v1 false CompositeResourceDefinition -compositionrevisions apiextensions.crossplane.io/v1alpha1 false CompositionRevision -compositions apiextensions.crossplane.io/v1 false Composition -configurationrevisions pkg.crossplane.io/v1 false ConfigurationRevision -configurations pkg.crossplane.io/v1 false Configuration -controllerconfigs pkg.crossplane.io/v1alpha1 false ControllerConfig -locks pkg.crossplane.io/v1beta1 false Lock -providerrevisions pkg.crossplane.io/v1 false ProviderRevision -providers pkg.crossplane.io/v1 false Provider -storeconfigs secrets.crossplane.io/v1alpha1 false StoreConfig -``` - -## Install the GCP provider - -Install the provider into the Kubernetes cluster with a Kubernetes configuration -file. - -```shell {label="provider",copy-lines="all"} -cat <}}kind: Provider{{< /hover >}} uses the -Crossplane `Provider` _Custom Resource Definition_ to connect your Kubernetes -cluster to your cloud provider. - -Verify the provider installed with `kubectl get providers`. - -{{< hint type="note" >}} -It may take up to five minutes for the provider to list `HEALTHY` as `True`. -{{< /hint >}} - -```shell {copy-lines="1"} -kubectl get providers -NAME INSTALLED HEALTHY PACKAGE AGE -upbound-provider-gcp True True xpkg.upbound.io/upbound/provider-gcp:v0.28.0 107s -``` - -A provider installs their own Kubernetes _Custom Resource Definitions_ (CRDs). -These CRDs allow you to create GCP resources directly inside Kubernetes. - -You can view the new CRDs with `kubectl get crds`. Every CRD maps to a unique -GCP service Crossplane can provision and manage. - - -{{< hint type="tip" >}} -See details about all the supported CRDs in the -[Upbound Marketplace](https://marketplace.upbound.io/providers/upbound/provider-family-gcp/). -{{< /hint >}} - -## Create a Kubernetes secret for GCP -The provider requires credentials to create and manage GCP resources. Providers -use a Kubernetes _Secret_ to connect the credentials to the provider. - -First generate a Kubernetes _Secret_ from a Google Cloud service account JSON -file and then configure the Provider to use it. - -{{< hint type="note" >}} -Other authentication methods exist and are beyond the scope of this guide. The -[Provider documentation](https://marketplace.upbound.io/providers/upbound/provider-gcp/latest/docs/configuration) contains information on alternative authentication methods. -{{< /hint >}} - -### Generate a GCP service account JSON file -For basic user authentication, use a Google Cloud service account JSON file. - -{{< hint type="tip" >}} -The -[GCP documentation](https://cloud.google.com/iam/docs/creating-managing-service-account-keys) -provides information on how to generate a service account JSON file. -{{< /hint >}} - -Save this JSON file as `gcp-credentials.json` - -{{< hint type="note" >}} -The [Configuration](https://marketplace.upbound.io/providers/upbound/provider-gcp/latest/docs/configuration) section of the Provider documentation describes other -authentication methods. -{{< /hint >}} - -### Create a Kubernetes secret with the GCP credentials -A Kubernetes generic secret has a name and contents. Use -{{< hover label="kube-create-secret" line="1">}}kubectl create secret{{< /hover >}} -to generate the secret object named -{{< hover label="kube-create-secret" line="2">}}gcp-secret{{< /hover >}} in the -{{< hover label="kube-create-secret" line="3">}}crossplane-system{{}} -namespace. -Use the {{< hover label="kube-create-secret" line="4">}}--from-file={{}} -argument to set the value to the contents of the -{{< hover label="kube-create-secret" line="4">}}gcp-credentials.json{{< /hover >}} -file. - - -```shell {label="kube-create-secret",copy-lines="all"} -kubectl create secret \ -generic gcp-secret \ --n crossplane-system \ ---from-file=creds=./gcp-credentials.json -``` - -View the secret with `kubectl describe secret` - -{{< hint type="note" >}} -The size may be larger if there are extra blank spaces in your JSON file. -{{< /hint >}} - -```shell {copy-lines="1"} -kubectl describe secret gcp-secret -n crossplane-system -Name: gcp-secret -Namespace: crossplane-system -Labels: -Annotations: - -Type: Opaque - -Data -==== -creds: 2330 bytes -``` - -## Create a ProviderConfig -A `ProviderConfig` customizes the settings of the GCP Provider. - -Apply the -{{< hover label="providerconfig" line="2">}}ProviderConfig{{}}. -Include your -{{< hover label="providerconfig" line="7" >}}GCP project ID{{< /hover >}} in the -_ProviderConfig_ settings. - -{{< hint type="warning" >}} -Find your GCP project ID from the `project_id` field of the -`gcp-credentials.json` file. -{{< /hint >}} - -{{< editCode >}} -```yaml {label="providerconfig",copy-lines="all"} -cat <$@ - credentials: - source: Secret - secretRef: - namespace: crossplane-system - name: gcp-secret - key: creds -EOF -``` -{{< /editCode >}} - -This attaches the GCP credentials, saved as a Kubernetes secret, as a -{{< hover label="providerconfig" line="10">}}secretRef{{}}. - -The {{< hover label="providerconfig" line="12">}}spec.credentials.secretRef.name{{< /hover >}} value is the name of the Kubernetes secret containing the GCP credentials in the -{{< hover label="providerconfig" line="11">}}spec.credentials.secretRef.namespace{{< /hover >}}. - -## Create a managed resource -A _managed resource_ is anything Crossplane creates and manages outside of the -Kubernetes cluster. This creates a GCP storage bucket with Crossplane. -The storage bucket is a _managed resource_. - -{{< hint type="note" >}} -To generate a unique name use -{{}}generateName{{}} instead of `name`. -{{< /hint >}} - -```yaml {label="xr",copy-lines="all"} -cat <}}apiVersion{{< /hover >}} and -{{< hover label="xr" line="3">}}kind{{}} are from the provider's CRDs. - -The {{< hover label="xr" line="10">}}spec.forProvider.location{{< /hover >}} -tells GCP which GCP region to use when deploying resources. For a -{{}}bucket{{}} the -region can be any -[GCP multi-region location](https://cloud.google.com/storage/docs/locations#location-mr) - -Use `kubectl get bucket` to verify Crossplane created the bucket. - -{{< hint type="tip" >}} -Crossplane created the bucket when the values `READY` and `SYNCED` are `True`. -This may take up to 5 minutes. -{{< /hint >}} - -```shell {copy-lines="1"} -kubectl get bucket -NAME READY SYNCED EXTERNAL-NAME AGE -crossplane-bucket-8b7gw True True crossplane-bucket-8b7gw 2m2s -``` - -## Delete the managed resource -Before shutting down your Kubernetes cluster, delete the GCP bucket just -created. - -Use `kubectl delete bucket` to remove the bucket. - -{{}} -Use the `--selector` flag to delete by label instead of by name. -{{}} - -```shell {copy-lines="1"} -kubectl delete bucket --selector docs.crossplane.io/example=provider-gcp -bucket.storage.gcp.upbound.io "crossplane-bucket-8b7gw" deleted -``` - -## Next steps -* **[Continue to part 2]({{< ref "provider-gcp-part-2">}})** to create a -Crossplane _Composite Resource_ and _Claim_. -* Explore GCP resources that can Crossplane can configure in the -[Provider CRD reference](https://marketplace.upbound.io/providers/upbound/provider-family-gcp/). -* Join the [Crossplane Slack](https://slack.crossplane.io/) and connect with -Crossplane users and contributors. \ No newline at end of file diff --git a/content/v1.11/_index.md b/content/v1.14/_index.md similarity index 94% rename from content/v1.11/_index.md rename to content/v1.14/_index.md index 8bbbfbd2c..b9d55816d 100644 --- a/content/v1.11/_index.md +++ b/content/v1.14/_index.md @@ -2,7 +2,7 @@ title: "Overview" weight: -1 cascade: - version: "1.11" + version: "1.14" --- {{< img src="/media/banner.png" alt="Crossplane Popsicle Truck" size="large" >}} @@ -18,7 +18,7 @@ APIs. Crossplane can even let you directly from Kubernetes. If it has an API, Crossplane can connect to it. With Crossplane, platform teams can create new abstractions and custom -APIs with the full power of Kubernetes policies, namespaces, role-based access +APIs with the full power of Kubernetes policies, namespaces, role based access controls and more. Crossplane brings all your non-Kubernetes resources under one roof. @@ -29,16 +29,18 @@ and use Kubernetes as the control plane for everything. {{< hint "tip" >}} **What's a control plane?** + Control planes create and manage the lifecycle of resources. Control planes constantly _check_ that the intended resources exist, _report_ when the intended state doesn't match reality and _act_ to make things right. Crossplane extends the Kubernetes control plane to be a **universal control plane** to check, report and act on any resource, anywhere. + {{< /hint >}} -# Get Started +# Get started * [Install Crossplane]({{}}) in your Kubernetes cluster * Learn more about how Crossplane works in the [Crossplane introduction]({{}}) diff --git a/content/v1.14/cli/_index.md b/content/v1.14/cli/_index.md new file mode 100644 index 000000000..10150e54c --- /dev/null +++ b/content/v1.14/cli/_index.md @@ -0,0 +1,64 @@ +--- +weight: 400 +title: Crossplane CLI +description: "Documentation for the Crossplane command-line interface" +--- + +The Crossplane CLI helps simplify some development and administration aspects of +Crossplane. + +The Crossplane CLI includes: +* tools to build, install, update and push Crossplane Packages +* standalone Composition Function testing and rendering without the need to access a Kubernetes cluster running Crossplane +* troubleshoot Crossplane Compositions, Composite Resources and Managed Resources + +## Installing the CLI + +The Crossplane CLI is a single standalone binary with no external dependencies. + +{{}} +Install the Crossplane CLI on a user's computer. + +Most Crossplane CLI commands are independent of Kubernetes and +don't require access to a Crossplane pod. +{{< /hint >}} + +To download the latest version for your CPU architecture with the Crossplane +install script. + +```shell +curl -sL "https://raw.githubusercontent.com/crossplane/crossplane/master/install.sh" | sh +``` + +[The script](https://raw.githubusercontent.com/crossplane/crossplane/master/install.sh) +detects your CPU architecture and downloads the latest stable release. + +{{}} + +If you don't want to run shell script you can manually download a binary from +the Crossplane releases repository at +https://releases.crossplane.io/stable/current/bin + +{{}} + +The CLI is named `crank` in the release repository. Download this file. + + +The `crossplane` binary is the Kubernetes Crossplane pod image. +{{< /hint >}} + +Move the binary to a location in your `$PATH`, for example `/usr/local/bin`. +{{< /expand >}} + +### Download other CLI versions + +Download different Crossplane CLI versions or different release branches with +the `XP_CHANNEL` and `XP_VERSION` environmental variables. + +By default the CLI installs from the `XP_CHANNEL` named `stable` and the +`XP_VERSION` of `current`, matching the most recent stable release. + +For example, to install CLI version `v1.14.0` add `XP_VERSION=v1.14.0` to the +download script curl command: + +`curl -sL "https://raw.githubusercontent.com/crossplane/crossplane/master/install.sh" | XP_VERSION=v1.14.0 sh` \ No newline at end of file diff --git a/content/v1.14/cli/command-reference.md b/content/v1.14/cli/command-reference.md new file mode 100644 index 000000000..98bab252e --- /dev/null +++ b/content/v1.14/cli/command-reference.md @@ -0,0 +1,611 @@ +--- +weight: 50 +title: Command Reference +description: "Command reference for the Crossplane CLI" +--- + + +The `crossplane` CLI provides utilities to make using Crossplane easier. + +Read the [Crossplane CLI overview]({{}}) page for information on +installing `crossplane`. + +## Global flags +The following flags are available for all commands. + +{{< table "table table-sm table-striped">}} +| Short flag | Long flag | Description | +|------------|-------------|------------------------------| +| `-h` | `--help` | Show context sensitive help. | +| `-v` | `--version` | Print version and exit. | +| | `--verbose` | Print verbose output. | +{{< /table >}} + +## xpkg + +The `crossplane xpkg` commands create, install and update Crossplane +[packages]({{}}) as well as enable authentication +and publishing of Crossplane packages to a Crossplane package registry. + +### xpkg build + +Using `crossplane xpkg build` provides automation and simplification to build +Crossplane packages. + +The Crossplane CLI combines a directory of YAML files and packages them as +an [OCI container image](https://opencontainers.org/). + +The CLI applies the required annotations and values to meet the +[Crossplane XPKG specification](https://github.com/crossplane/crossplane/blob/master/contributing/specifications/xpkg.md). + +The `crossplane` CLI supports building +[configuration]({{< ref "../concepts/packages" >}}), +[function]({{}}) and +[provider]({{}}) package types. + + +#### Flags +{{< table "table table-sm table-striped">}} +| Short flag | Long flag | Description | +| ------------ | ------------- | ------------------------------ | +| | `--embed-runtime-image-name=NAME` | The image name and tag of an image to include in the package. Only for provider and function packages. | +| | `--embed-runtime-image-tarball=PATH` | The filename of an image to include in the package. Only for provider and function packages. | +| `-e` | `--examples-root="./examples"` | The path to a directory of examples related to the package. | +| | `--ignore=PATH,...` | List of files and directories to ignore. | +| `-o` | `--package-file=PATH` | Directory and filename of the created package. | +| `-f` | `--package-root="."` | Directory to search for YAML files. | +{{< /table >}} + +The `crossplane xpkg build` command recursively looks in the directory set by +`--package-root` and attempts to combine any files ending in `.yml` or `.yaml` +into a package. + +All YAML files must be valid Kubernetes manifests with `apiVersion`, `kind`, +`metadata` and `spec` fields. + +#### Ignore files + +Use `--ignore` to provide a list of files and directories to ignore. + +For example, +`crossplane xpkg build --ignore="./test/*,kind-config.yaml"` + +#### Set the package name + +`crossplane` automatically names the new package a combination of the +`metadata.name` and a hash of the package contents and saves the contents +in the same location as `--package-root`. Define a specific location and +filename with `--package-file` or `-o`. + +For example, +`crossplane xpkg build -o /home/crossplane/example.xpkg`. + + +#### Include examples + +Include YAML files demonstrating how to use the package with `--examples-root`. + +[Upbound Marketplace](https://marketplace.upbound.io/) uses files included with +`--examples-root` as documentation for published packages. + +#### Include a runtime image + +Functions and Providers require YAML files describing their dependencies and +settings as well as a container image for their runtime. + +Using `--embed-runtime-image-name` runs a specified image and +includes the image inside the function or provider package. + +{{}} +Images referenced with `--embed-runtime-image-name` must be in the local Docker +cache. + +Use `docker pull` to download a missing image. +{{< /hint >}} + +The `--embed-runtime-image-tarball` flag includes a local OCI image tarball +inside the function or provider package. + + +### xpkg install + +Download and install packages into Crossplane with `crossplane xpkg install`. + +By default the `crossplane xpkg install` command uses the Kubernetes +configuration defined in `~/.kube/config`. + +Define a custom Kubernetes configuration file location with the environmental +variable `KUBECONFIG`. + +Specify the package kind, package file and optionally a name to give the package +inside Crossplane. + +`crossplane xpkg install []` + +The `` is either a `configuration`, `function` or `provider`. + +For example, to install version 0.42.0 of the +[AWS S3 provider](https://marketplace.upbound.io/providers/upbound/provider-aws-s3/v0.42.0): + +`crossplane xpkg install provider xpkg.upbound.io/upbound/provider-aws-s3:v0.42.0` + +#### Flags +{{< table "table table-sm table-striped">}} +| Short flag | Long flag | Description | +| ------------ | ------------- | ------------------------------ | +| | `--runtime-config=` | Install the package with a runtime configuration. | +| `-m` | `--manual-activation` | Set the `revisionActiviationPolicy` to `Manual`. | +| | `--package-pull-secrets=` | A comma-seperated list of Kubernetes secrets to use for authenticating to the package registry. | +| `-r` | `--revision-history-limit=` | Set the `revisionHistoryLimit`. Defaults to `1`. | +| `-w` | `--wait=` | Number of seconds to wait for a package to install. | + +{{< /table >}} + +#### Wait for package install + +When installing a package the `crossplane xpkg install` command doesn't wait for +the package to download and install. View any download or installation problems +by inspecting the `configuration` with `kubectl describe configuration`. + +Use `--wait` to have the `crossplane xpkg install` command to wait for a +package to have the condition `HEALTHY` before continuing. The command +returns an error if the `wait` time expires before the package is `HEALTHY`. + +#### Require manual package activation + +Set the package to require +[manual activation]({{}}), +preventing an automatic upgrade of a package with `--manual-activation` + +#### Authenticate to a private registry + +To authenticate to a private package registry use `--package-pull-secrets` and +provide a list of Kubernetes Secret objects. + +{{}} +The secrets must be in the same namespace as the Crossplane pod. +{{< /hint >}} + +#### Customize the number of stored package versions + +By default Crossplane only stores a single inactive package in the local package +cache. + +Store more inactive copies of a package with `--revision-history-limit`. + +Read more about +[package revisions]({{< ref "../concepts/packages#configuration-revisions" >}}) +in the package documentation. + +### xpkg login + +Use `xpkg login` to authenticate to `xpkg.upbound.io`, the +[Upbound Marketplace](https://marketplace.upbound.io/) container registry. + +[Register with the Upbound Marketplace](https://accounts.upbound.io/register) +to push packages and create private repositories. + +#### Flags + +{{< table "table table-sm table-striped">}} +| Short flag | Long flag | Description | +| ------------ | ------------- | ------------------------------ | +| `-u` | `--username=` | Username to use for authentication. | +| `-p` | `--password=` | Password to use for authentication. | +| `-t` | `--token=` | User token string to use for authentication. | +| `-a` | `--account=` | Specify an Upbound organization during authentication. | +{{< /table >}} + + +#### Authentication options + +The `crossplane xpkg login` command can use a username and password or Upbound API token. + +By default, `crossplane xpkg login` without arguments, prompts for a username +and password. + +Provide a username and password with the `--username` and `--password` flags or +set the environmental variable `UP_USER` for a username or `UP_PASSWORD` for the +password. + +Use an Upbound user token instead of a username and password with `--token` or +the `UP_TOKEN` environmental variable. + +{{< hint "important" >}} +The `--token` or `UP_TOKEN` environmental variables take precedence over a +username and password. +{{< /hint >}} + +Using `-` as the input for `--password` or `--token` reads the input from stdin. +For example, `crossplane xpkg login --password -`. + +After logging in the Crossplane CLI creates a `profile` in +`.crossplane/config.json` to cache unprivileged account information. + +{{}} +The `session` field of `config.json` file is a session cookie identifier. + +The `session` value isn't used for authentication. This isn't a `token`. +{{< /hint >}} + +#### Authenticate with a registered Upbound organization + +Authenticate to a registered organization in the Upbound Marketplace with the +`--account` option, along with the username and password or token. + +For example, +`crossplane xpkg login --account=Upbound --username=my-user --password -`. + +### xpkg logout + +Use `crossplane xpkg logout` to invalidate the current `crossplane xpkg login` +session. + +{{< hint "note" >}} +Using `crossplane xpkg logout` removes the `session` from the +`~/.crossplane/config.json` file, but doesn't delete the configuration file. +{{< /hint >}} + +### xpkg push + +Push a Crossplane package file to a package registry. + +The Crossplane CLI pushes images to the +[Upbound Marketplace](https://marketplace.upbound.io/) at `xpkg.upbound.io` by +default. + +{{< hint "note" >}} +Pushing a package may require authentication with +[`crossplane xpkg login`](#xpkg-login) +{{< /hint >}} + +Specify the organization, package name and tag with +`crossplane xpkg push ` + +By default the command looks in the current directory for a single `.xpkg` file +to push. + +To push multiple files or to specify a specific `.xpkg` file use the `-f` flag. + +For example, to push a local package named `my-package` to +`crossplane-docs/my-package:v0.14.0` use: + +`crossplane xpkg push -f my-package.xpkg crossplane-docs/my-package:v0.14.0` + +To push to another package registry, like [DockerHub](https://hub.docker.com/) +provide the full URL along with the package name. + +For example, to push a local package named `my-package` to +DockerHub organization `crossplane-docs/my-package:v0.14.0` use: +`crossplane xpkg push -f my-package.xpkg index.docker.io/crossplane-docs/my-package:v0.14.0`. + + +#### Flags + +{{< table "table table-sm table-striped">}} +| Short flag | Long flag | Description | +| ------------ | ------------- | ------------------------------ | +| `-f` | `--package-files=PATH` | A comma-separated list of xpkg files to push. | +{{< /table >}} + +### xpkg update + +The `crossplane xpkg update` command downloads and updates an existing package. + +By default the `crossplane xpkg update` command uses the Kubernetes +configuration defined in `~/.kube/config`. + +Define a custom Kubernetes configuration file location with the environmental +variable `KUBECONFIG`. + +Specify the package kind, package file and optionally the name of the package +already installed in Crossplane. + +`crossplane xpkg update []` + +The package file must be an organization, image and tag on the `xpkg.upbound.io` +registry on [Upbound Marketplace](https://marketplace.upbound.io/). + +For example, to update to version 0.42.0 of the +[AWS S3 provider](https://marketplace.upbound.io/providers/upbound/provider-aws-s3/v0.42.0): + +`crossplane xpkg update provider xpkg.upbound.io/upbound/provider-aws-s3:v0.42.0` + + +## beta + +Crossplane `beta` commands are experimental. These commands may change the +flags, options or outputs in future releases. + +Crossplane maintainers may promote or remove commands under `beta` in future +releases. + +### beta render + +The `crossplane beta render` command previews the output of a +[composite resource]({{}}) after applying +any [composition functions]({{}}). + +{{< hint "important" >}} +The `crossplane beta render` command doesn't apply +[patch and transform composition patches]({{}}). + +The command only supports function "patch and transforms." +{{< /hint >}} + +The `crossplane beta render` command connects to the locally running Docker +Engine to pull and run composition functions. + +{{}} +Running `crossplane beta render` requires [Docker](https://www.docker.com/). +{{< /hint >}} + +Provide a composite resource, composition and composition function YAML +definition with the command to render the output locally. + +For example, +`crossplane beta render xr.yaml composition.yaml function.yaml` + +The output includes the original composite resource followed by the generated +managed resources. + +{{}} +```yaml +--- +apiVersion: nopexample.org/v1 +kind: XBucket +metadata: + name: test-xrender +status: + bucketRegion: us-east-2 +--- +apiVersion: s3.aws.upbound.io/v1beta1 +kind: Bucket +metadata: + annotations: + crossplane.io/composition-resource-name: my-bucket + generateName: test-xrender- + labels: + crossplane.io/composite: test-xrender + ownerReferences: + - apiVersion: nopexample.org/v1 + blockOwnerDeletion: true + controller: true + kind: XBucket + name: test-xrender + uid: "" +spec: + forProvider: + region: us-east-2 +``` +{{< /expand >}} + +#### Flags + +{{< table "table table-sm table-striped">}} +| Short flag | Long flag | Description | +| ------------ | ------------- | ------------------------------ | +| | `--context-files==,=` | A comma separated list of files to load for function "contexts." | +| | `--context-values==,=` | A comma separated list of key-value pairs to load for function "contexts." | +| `-r` | `--include-function-results` | Include the "results" or events from the function. | +| `-o` | `--observed-resources=` | Provide artificial managed resource data to the function. | +| | `--timeout=` | Amount of time to wait for a function to finish. | +{{< /table >}} + +The `crossplane beta render` command relies on standard +[Docker environmental variables](https://docs.docker.com/engine/reference/commandline/cli/#environment-variables) +to connect to the local Docker engine and run composition functions. + + +#### Provide function context + +The `--context-files` and `--context-values` flags can provide data +to a function's `context`. +The context is JSON formatted data. + +#### Include function results + +If a function produces Kubernetes events with statuses use the +`--include-function-results` to print them along with the managed resource +outputs. + +#### Mock managed resources + +Provide mocked, or artificial data representing a managed resource with +`--observed-resources`. The `crossplane beta render` command treats the +provided inputs as if they were resources in a Crossplane cluster. + +A function can reference and manipulate the included resource as part of +running the function. + +The `observed-resources` may be a single YAML file with multiple resources or a +directory of YAML files representing multiple resources. + +Inside the YAML file include an +{{}}apiVersion{{}}, +{{}}kind{{}}, +{{}}metadata{{}} and +{{}}spec{{}}. + +```yaml {label="or"} +apiVersion: example.org/v1alpha1 +kind: ComposedResource +metadata: + name: test-render-b + annotations: + crossplane.io/composition-resource-name: resource-b +spec: + coolerField: "I'm cooler!" +``` + +The schema of the resource isn't validated and may contain any data. + + +### beta trace + +Use the `crossplane beta trace` command to display a visual relationship of +Crossplane objects. The `trace` command supports claims, compositions or +managed resources. + +The command requires a resource type and a resource name. + +`crossplane beta trace ` + +For example to view a resource named `my-claim` of type `example.crossplane.io`: +`crossplane beta trace example.crossplane.io my-claim` + +The command also accepts Kubernetes CLI style `/` input. +For example, +`crossplane beta trace example.crossplane.io/my-claim` + +By default the `crossplane beta trace` command uses the Kubernetes +configuration defined in `~/.kube/config`. + +Define a custom Kubernetes configuration file location with the environmental +variable `KUBECONFIG`. + +#### Flags +{{< table "table table-sm table-striped">}} + + +| Short flag | Long flag | Description | +| ------------ | ------------- | ------------------------------ | +| `-n` | `--namespace` | The namespace of the resource. | +| `-o` | `--output=` | Change the graph output with `wide`, `json`, or `dot` for a [Graphviz dot](https://graphviz.org/docs/layouts/dot/) output. | +| `-s` | `--show-connection-secrets` | Print any connection secret names. Doesn't print the secret values. | + +{{< /table >}} + +#### Output options + +By default `crossplane beta trace` prints directly to the terminal, limiting the +"Ready" condition and "Status" messages to 64 characters. + +The following an example output a "cluster" claim from the AWS reference +platform, which includes multiple Compositions and composed resources: + +```shell {copy-lines="1"} +crossplane beta trace cluster.aws.platformref.upbound.io platform-ref-aws +NAME SYNCED READY STATUS +Cluster/platform-ref-aws (default) True True Available +└─ XCluster/platform-ref-aws-mlnwb True True Available + ├─ XNetwork/platform-ref-aws-mlnwb-6nvkx True True Available + │ ├─ VPC/platform-ref-aws-mlnwb-ckblr True True Available + │ ├─ InternetGateway/platform-ref-aws-mlnwb-r7w47 True True Available + │ ├─ Subnet/platform-ref-aws-mlnwb-lhr4h True True Available + │ ├─ Subnet/platform-ref-aws-mlnwb-bss4b True True Available + │ ├─ Subnet/platform-ref-aws-mlnwb-fzbxx True True Available + │ ├─ Subnet/platform-ref-aws-mlnwb-vxbf4 True True Available + │ ├─ RouteTable/platform-ref-aws-mlnwb-cs9nl True True Available + │ ├─ Route/platform-ref-aws-mlnwb-vpxdg True True Available + │ ├─ MainRouteTableAssociation/platform-ref-aws-mlnwb-sngx5 True True Available + │ ├─ RouteTableAssociation/platform-ref-aws-mlnwb-hprsp True True Available + │ ├─ RouteTableAssociation/platform-ref-aws-mlnwb-shb8f True True Available + │ ├─ RouteTableAssociation/platform-ref-aws-mlnwb-hvb2h True True Available + │ ├─ RouteTableAssociation/platform-ref-aws-mlnwb-m58vl True True Available + │ ├─ SecurityGroup/platform-ref-aws-mlnwb-xxbl2 True True Available + │ ├─ SecurityGroupRule/platform-ref-aws-mlnwb-7qt56 True True Available + │ └─ SecurityGroupRule/platform-ref-aws-mlnwb-szgxp True True Available + ├─ XEKS/platform-ref-aws-mlnwb-fqjzz True True Available + │ ├─ Role/platform-ref-aws-mlnwb-gmpqv True True Available + │ ├─ RolePolicyAttachment/platform-ref-aws-mlnwb-t6rct True True Available + │ ├─ Cluster/platform-ref-aws-mlnwb-crrt8 True True Available + │ ├─ ClusterAuth/platform-ref-aws-mlnwb-dgn6f True True Available + │ ├─ Role/platform-ref-aws-mlnwb-tdnx4 True True Available + │ ├─ RolePolicyAttachment/platform-ref-aws-mlnwb-qzljh True True Available + │ ├─ RolePolicyAttachment/platform-ref-aws-mlnwb-l64q2 True True Available + │ ├─ RolePolicyAttachment/platform-ref-aws-mlnwb-xn2px True True Available + │ ├─ NodeGroup/platform-ref-aws-mlnwb-4sfss True True Available + │ ├─ OpenIDConnectProvider/platform-ref-aws-mlnwb-h26xx True True Available + │ └─ ProviderConfig/platform-ref-aws - - + └─ XServices/platform-ref-aws-mlnwb-bgndx True True Available + ├─ Release/platform-ref-aws-mlnwb-bcj7r True True Available + └─ Release/platform-ref-aws-mlnwb-7hfkv True True Available +``` + +#### Wide outputs +Print the entire "Ready" or "Status" message if they're longer than +64 characters with `--output=wide`. + +For example, the output truncates the "Status" message that's too long. + +```shell {copy-lines="1" +crossplane trace cluster.aws.platformref.upbound.io platform-ref-aws +NAME SYNCED READY STATUS +Cluster/platform-ref-aws (default) True False Waiting: ...resource claim is waiting for composite resource to become Ready +``` + +Use `--output=wide` to see the full message. + +```shell {copy-lines="1" +crossplane trace cluster.aws.platformref.upbound.io platform-ref-aws --output=wide +NAME SYNCED READY STATUS +Cluster/platform-ref-aws (default) True False Waiting: Composite resource claim is waiting for composite resource to become Ready +``` + +#### Graphviz dot file output + +Use the `--output=dot` to print out a textual +[Graphviz dot](https://graphviz.org/docs/layouts/dot/) output. + +Save the output and export it or the output directly to Graphviz `dot` to +render an image. + +For example, to save the output as a `graph.png` file use +`dot -Tpng -o graph.png`. + +`crossplane beta trace cluster.aws.platformref.upbound.io platform-ref-aws -o dot | dot -Tpng -o graph.png` + +#### Print connection secrets + +Use `-s` to print any connection secret names along with the other resources. + +{{}} +The `crossplane beta trace` command doesn't print secret values. +{{< /hint >}} + +The output includes both the secret name along with the secret's namespace. + +```shell +NAME SYNCED READY STATUS +Cluster/platform-ref-aws (default) True True Available +└─ XCluster/platform-ref-aws-mlnwb True True Available + ├─ XNetwork/platform-ref-aws-mlnwb-6nvkx True True Available + │ ├─ SecurityGroupRule/platform-ref-aws-mlnwb-szgxp True True Available + │ └─ Secret/3f11c30b-dd94-4f5b-aff7-10fe4318ab1f (upbound-system) - - + ├─ XEKS/platform-ref-aws-mlnwb-fqjzz True True Available + │ ├─ OpenIDConnectProvider/platform-ref-aws-mlnwb-h26xx True True Available + │ └─ Secret/9666eccd-929c-4452-8658-c8c881aee137-eks (upbound-system) - - + ├─ XServices/platform-ref-aws-mlnwb-bgndx True True Available + │ ├─ Release/platform-ref-aws-mlnwb-7hfkv True True Available + │ └─ Secret/d0955929-892d-40c3-b0e0-a8cabda55895 (upbound-system) - - + └─ Secret/9666eccd-929c-4452-8658-c8c881aee137 (upbound-system) - - +``` + +### beta xpkg init + +The `crossplane beta xpkg init` command populates the current directory with +files to build a package. + +Provide a name to use for the package and the package template to start from +with the command +`crossplane beta xpkg init