diff --git a/content/v1.11/getting-started/provider-gcp-part-2.md b/content/v1.11/getting-started/provider-gcp-part-2.md new file mode 100644 index 00000000..ec3443f7 --- /dev/null +++ b/content/v1.11/getting-started/provider-gcp-part-2.md @@ -0,0 +1,967 @@ +--- +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-gcp/latest/crds). +* 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 new file mode 100644 index 00000000..e84ecf12 --- /dev/null +++ b/content/v1.11/getting-started/provider-gcp-part-3.md @@ -0,0 +1,659 @@ +--- +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 +don't need 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 doesn't need 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 kubectl-crossplane /usr/bin +``` + +Verify the Crossplane command-line installed with `kubectl crossplane --help` + +```shell +kubectl crossplane --help +Usage: kubectl 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 `kubectl crossplane` command to create an `.xpkg` file containing the +custom APIs and Crossplane configuration. + +```shell +kubectl 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-gcp/latest/crds). +* 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 index a73aeb1c..815f45f4 100644 --- a/content/v1.11/getting-started/provider-gcp.md +++ b/content/v1.11/getting-started/provider-gcp.md @@ -3,41 +3,1039 @@ title: GCP Quickstart weight: 140 --- -Connect Crossplane to Google GCP to create and manage cloud resources from Kubernetes with the [Upbound GCP Provider](https://marketplace.upbound.io/providers/upbound/provider-gcp/). - -This guide walks you through the steps required to get started with the Upbound GCP Provider. This includes installing Crossplane, configuring the provider to authenticate to GCP and creating a _Managed Resource_ in GCP directly from your Kubernetes cluster. - -- [Prerequisites](#prerequisites) -- [Install the GCP provider](#install-the-gcp-provider) -- [Create a Kubernetes secret for GCP](#create-a-kubernetes-secret-for-gcp) - - [Generate a GCP service account JSON file](#generate-a-gcp-service-account-json-file) - - [Create a Kubernetes secret with the GCP credentials](#create-a-kubernetes-secret-with-the-gcp-credentials) -- [Create a ProviderConfig](#create-a-providerconfig) -- [Create a managed resource](#create-a-managed-resource) -- [Delete the managed resource](#delete-the-managed-resource) -- [Next steps](#next-steps) +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 3 GB of RAM +* 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 [minikube](https://minikube.sigs.k8s.io/docs/start/) or [kind](https://kind.sigs.k8s.io/). +If you don't have a Kubernetes cluster create one locally with +[Kind](https://kind.sigs.k8s.io/). {{< /hint >}} +### Install the Crossplane Helm chart -{{< hint type="note" >}} -All commands use the current `kubeconfig` context and configuration. -{{< /hint >}} +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. +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. +The {{< hover label="provider" line="3">}}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`. @@ -58,48 +1058,64 @@ Verify the provider installed with `kubectl get providers`. It may take up to five minutes for the provider to list `HEALTHY` as `True`. {{< /hint >}} -```shell +```shell {copy-lines="1"} kubectl get providers NAME INSTALLED HEALTHY PACKAGE AGE -upbound-provider-gcp True False xpkg.upbound.io/upbound/provider-gcp:v0.26.0 8s +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. +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. -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" >}} -All the supported CRDs are also available in the [Upbound Marketplace](https://marketplace.upbound.io/providers/upbound/provider-gcp/latest/crds). +See details about all the supported CRDs in the +[Upbound Marketplace](https://marketplace.upbound.io/providers/upbound/provider-gcp/v0.28.0/crds). {{< /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. +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. +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. +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. +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. +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. - +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 \ @@ -111,10 +1127,10 @@ generic gcp-secret \ 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. +The size may be larger if there are extra blank spaces in your JSON file. {{< /hint >}} -```shell +```shell {copy-lines="1"} kubectl describe secret gcp-secret -n crossplane-system Name: gcp-secret Namespace: crossplane-system @@ -131,12 +1147,18 @@ 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 >}}. +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" >}} -Add your GCP `project ID` into the output below. +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 < + projectID: $$$$ credentials: source: Secret secretRef: @@ -153,18 +1175,22 @@ spec: key: creds EOF ``` +{{< /editCode >}} -This attaches the GCP credentials, saved as a Kubernetes secret, as a {{< hover label="providerconfig" line="9">}}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 >}}. +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_. +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 the example uses `generateName` instead of `name`. -Manifests that use `generateName` must use `kubectl create`, not `apply`. +To generate a unique name use +{{}}generateName{{}} instead of `name`. {{< /hint >}} ```yaml {label="xr",copy-lines="all"} @@ -178,51 +1204,52 @@ metadata: spec: forProvider: location: US - storageClass: MULTI_REGIONAL providerConfigRef: name: default - deletionPolicy: Delete EOF ``` -Notice 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="2">}}apiVersion{{< /hover >}} and +{{< hover label="xr" line="3">}}kind{{}} are from the provider's CRDs. -{{< hover label="xr" line="11" >}}spec.storageClass{{< /hover >}} defines the GCP storage bucket is [single-region, dual-region or multi-region](https://cloud.google.com/storage/docs/locations#key-concepts). +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) -{{< hover label="xr" line="10">}}spec.forProvider.location{{< /hover >}} is a [GCP location based](https://cloud.google.com/storage/docs/locations) on the {{< hover label="xr" line="11" >}}storageClass{{< /hover >}}. - -Use `kubectl get buckets` to verify Crossplane created the bucket. +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 +```shell {copy-lines="1"} kubectl get bucket NAME READY SYNCED EXTERNAL-NAME AGE -crossplane-bucket-lrxrf True True crossplane-bucket-lrxrf 3m3s +crossplane-bucket-8b7gw True True crossplane-bucket-8b7gw 2m2s ``` -Optionally, log into the [GCP Console](https://console.cloud.google.com/) and see the storage bucket inside GCP. - ## Delete the managed resource -Before shutting down your Kubernetes cluster, delete the S3 bucket just created. +Before shutting down your Kubernetes cluster, delete the GCP bucket just +created. Use `kubectl delete bucket` to remove the bucket. {{}} -Use the `--label` flag to delete by label instead of by name. +Use the `--selector` flag to delete by label instead of by name. {{}} -```shell -kubectl delete bucket --label docs.crossplane.io/example: provider-gcp -bucket.storage.gcp.upbound.io "crossplane-bucket-lrxrf" deleted +```shell {copy-lines="1"} +kubectl delete bucket --selector docs.crossplane.io/example=provider-gcp +bucket.storage.gcp.upbound.io "crossplane-bucket-8b7gw" deleted ``` -Look in the [GCP Console](https://console.cloud.google.com/) to confirm Crossplane deleted the bucket from GCP. - - ## Next steps -* Explore GCP resources that can Crossplane can configure in the [Provider CRD reference](https://marketplace.upbound.io/providers/upbound/provider-gcp/latest/crds). -* Join the [Crossplane Slack](https://slack.crossplane.io/) and connect with Crossplane users and contributors. \ No newline at end of file +* **[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-gcp/latest/crds). +* Join the [Crossplane Slack](https://slack.crossplane.io/) and connect with +Crossplane users and contributors. \ No newline at end of file diff --git a/utils/vale/styles/Crossplane/spelling-exceptions.txt b/utils/vale/styles/Crossplane/spelling-exceptions.txt index 89441609..9eafb26e 100644 --- a/utils/vale/styles/Crossplane/spelling-exceptions.txt +++ b/utils/vale/styles/Crossplane/spelling-exceptions.txt @@ -4,6 +4,8 @@ Bootstrap CRDs Crossplane Crossplane's +Dataflow +Datastore editCode Env GCP's diff --git a/utils/vale/styles/Google/Headings.yml b/utils/vale/styles/Google/Headings.yml index a807769e..858450c9 100644 --- a/utils/vale/styles/Google/Headings.yml +++ b/utils/vale/styles/Google/Headings.yml @@ -8,19 +8,24 @@ indicators: - ':' exceptions: - Azure + - BigQuery - CLI - Code - Cosmos + - Crossplane - Docker - Emmet - Hugo - gRPC + - Helm - I - Kubernetes - Linux - macOS - Marketplace - MongoDB + - ProviderConfig + - Pub/Sub - REPL - Studio - TypeScript diff --git a/utils/vale/styles/Microsoft/HeadingAcronyms.yml b/utils/vale/styles/Microsoft/HeadingAcronyms.yml index 9dc3b6c2..8674cf6e 100644 --- a/utils/vale/styles/Microsoft/HeadingAcronyms.yml +++ b/utils/vale/styles/Microsoft/HeadingAcronyms.yml @@ -5,3 +5,7 @@ level: warning scope: heading tokens: - '[A-Z]{2,4}' +exceptions: + - API + - GCP + - JSON \ No newline at end of file