diff --git a/examples/gcp/README.md b/examples/gcp/README.md index 62a5aaf8..d1eeb972 100644 --- a/examples/gcp/README.md +++ b/examples/gcp/README.md @@ -78,6 +78,9 @@ gcloud services enable \ gcloud iam service-accounts add-iam-policy-binding kcc-operator@${PROJECT_ID}.iam.gserviceaccount.com \ --member="serviceAccount:${PROJECT_ID}.svc.id.goog[cnrm-system/cnrm-controller-manager]" \ --role="roles/iam.workloadIdentityUser" + gcloud projects add-iam-policy-binding ${PROJECT_ID}\ + --member="serviceAccount:kcc-operator@${PROJECT_ID}.iam.gserviceaccount.com" \ + --role="roles/storage.admin" ``` 3. [Configure Config Connector](https://cloud.google.com/config-connector/docs/how-to/install-manually#addon-configuring) ``` diff --git a/examples/gcp/eventarc/README.md b/examples/gcp/eventarc/README.md new file mode 100644 index 00000000..78dd8d9c --- /dev/null +++ b/examples/gcp/eventarc/README.md @@ -0,0 +1,102 @@ +# GCSBucketWithFinalizerTrigger + +A **Platform Administrator** wants to give end users in their organization self-service access to creating GCS Buckets that triggers a Cloud Workflow when any object in it is finalized. The platform administrator creates a kro ResourceGraphDefinition called *gcsbucketwithfinalizertrigger.kro.run* that defines the required Kubernetes resources and a CRD called *GCSBucketWithFinalizertrigger* that exposes only the options they want to be configurable by end users. + +The following KCC objects are created by this RGD: +* IAMServiceAccount, IAMPolicyMember: Service Account with necessary permissions for Eventarc and Pub/Sub. +* StorageBucket +* PubSubTopic +* EventArcTrigger +* StorageNotification: To publish events from the GCS bucket to a Pub/Sub topic. + +Pre-requisites: +* Workflow: The workflow to be triggered on Finalizer event. + +Everything related to these resources would be hidden from the end user, simplifying their experience. + +![GCS EventArc Stack](gcsbucket-with-finalizer-trigger.png) + + + + + +## End User: GCSBucketWithFinalizerTrigger + +The administrator needs to install the RGD first. +The end user creates a `GCSBucketWithFinalizerTrigger` resource something like this: + +```yaml +apiVersion: kro.run/v1alpha1 +kind: GCSBucketWithFinalizerTrigger +metadata: + name: gcsevent-test + namespace: config-connector +spec: + name: demo-gcs # used as name or prefix for KCC objects + workflowName: gcs-finalizer-workflow # Replace with your workflow path + location: us-central1 # desired location + project: my-project-name # Replace with your project name +``` + +They can then check the status of the applied resource: + +``` +kubectl get gcsbucketwithfinalizertrigger -n config-connector +kubectl get gcsbucketwithfinalizertrigger gcsevent-test -n config-connector -o yaml +``` + +Navigate to GCS page in the GCP Console and verify the bucket creation. Also verify that the Triggers are setup correctly in the EventArc page. + +Once done, the user can delete the `GCSBucketWithFinalizerTrigger` instance: + +``` +kubectl delete gcsbucketwithfinalizertrigger gcsevent-test -n config-connector +``` + +## Administrator: ResourceGraphDefinition +The administrator needs to install the RGD in the cluster first before the user can consume it: + +``` +kubectl apply -f rgd.yaml +``` + +Validate the RGD is installed correctly: + +``` +kubectl get rgd gcsbucketwithfinalizertrigger.kro.run +``` + +Once all user created instances are deleted, the administrator can choose to deleted the RGD. diff --git a/examples/gcp/eventarc/gcsbucket-with-finalizer-trigger.png b/examples/gcp/eventarc/gcsbucket-with-finalizer-trigger.png new file mode 100644 index 00000000..8bfdd20f Binary files /dev/null and b/examples/gcp/eventarc/gcsbucket-with-finalizer-trigger.png differ diff --git a/examples/gcp/eventarc/rgd.yaml b/examples/gcp/eventarc/rgd.yaml new file mode 100644 index 00000000..593b150c --- /dev/null +++ b/examples/gcp/eventarc/rgd.yaml @@ -0,0 +1,161 @@ +apiVersion: kro.run/v1alpha1 +kind: ResourceGraphDefinition +metadata: + name: gcsbucketwithfinalizertrigger.kro.run +spec: + schema: + apiVersion: v1alpha1 + kind: GCSBucketWithFinalizerTrigger + spec: + name: string + workflowName: string + location: string + project: string + status: + url: ${bucket.status.url} + resources: + - id: storageEnable + template: + apiVersion: serviceusage.cnrm.cloud.google.com/v1beta1 + kind: Service + metadata: + annotations: + cnrm.cloud.google.com/deletion-policy: "abandon" + cnrm.cloud.google.com/disable-dependent-services: "false" + name: storage-enablement + spec: + resourceID: storage.googleapis.com + - id: iamEnable + template: + apiVersion: serviceusage.cnrm.cloud.google.com/v1beta1 + kind: Service + metadata: + annotations: + cnrm.cloud.google.com/deletion-policy: "abandon" + cnrm.cloud.google.com/disable-dependent-services: "false" + name: iam-enablement + spec: + resourceID: iam.googleapis.com + - id: pubsubEnable + template: + apiVersion: serviceusage.cnrm.cloud.google.com/v1beta1 + kind: Service + metadata: + annotations: + cnrm.cloud.google.com/deletion-policy: "abandon" + cnrm.cloud.google.com/disable-dependent-services: "false" + name: pubsub-enablement + spec: + resourceID: pubsub.googleapis.com + - id: eventarcEnable + template: + apiVersion: serviceusage.cnrm.cloud.google.com/v1beta1 + kind: Service + metadata: + annotations: + cnrm.cloud.google.com/deletion-policy: "abandon" + cnrm.cloud.google.com/disable-dependent-services: "false" + name: eventarc-enablement + spec: + resourceID: eventarc.googleapis.com + - id: iamsa + template: + apiVersion: iam.cnrm.cloud.google.com/v1beta1 + kind: IAMServiceAccount + metadata: + labels: + enabled-service: ${iamEnable.metadata.name} + #annotations: + # cnrm.cloud.google.com/project-id: ${schema.spec.project} + name: ${schema.spec.name} + spec: + displayName: ${schema.spec.name}-eventarc-workflow + - id: iampmEventarc + template: + apiVersion: iam.cnrm.cloud.google.com/v1beta1 + kind: IAMPolicyMember + metadata: + labels: + enabled-service: ${iamEnable.metadata.name} + name: ${schema.spec.name}-eventarc + spec: + memberFrom: + serviceAccountRef: + name: ${iamsa.metadata.name} + role: roles/eventarc.admin + resourceRef: + kind: Project + external: ${schema.spec.project} + - id: iampmWorkflow + template: + apiVersion: iam.cnrm.cloud.google.com/v1beta1 + kind: IAMPolicyMember + metadata: + labels: + enabled-service: ${iamEnable.metadata.name} + name: ${schema.spec.name}-workflow + spec: + memberFrom: + serviceAccountRef: + name: ${iamsa.metadata.name} + role: roles/workflows.admin + resourceRef: + kind: Project + external: ${schema.spec.project} + - id: topic + template: + apiVersion: pubsub.cnrm.cloud.google.com/v1beta1 + kind: PubSubTopic + metadata: + labels: + enabled-service: ${pubsubEnable.metadata.name} + name: ${schema.spec.name}-gcs-finalizer-topic + - id: bucket + template: + apiVersion: storage.cnrm.cloud.google.com/v1beta1 + kind: StorageBucket + metadata: + labels: + enabled-service: ${storageEnable.metadata.name} + name: ${schema.spec.name}-${schema.spec.project} + spec: + uniformBucketLevelAccess: true + - id: eventTrigger + template: + apiVersion: eventarc.cnrm.cloud.google.com/v1beta1 + kind: EventarcTrigger + metadata: + labels: + enabled-service: ${eventarcEnable.metadata.name} + name: ${schema.spec.name}-gcsfinalizer + spec: + destination: + workflowRef: + external: "projects/${schema.spec.project}/locations/${schema.spec.location}/workflows/${schema.spec.workflowName}" + location: ${schema.spec.location} + serviceAccountRef: + name: ${iamsa.metadata.name} + transport: + pubsub: + topicRef: + name: ${topic.metadata.name} + namespace: config-connector + matchingCriteria: + - attribute: "type" + value: "google.cloud.pubsub.topic.v1.messagePublished" + projectRef: + external: "projects/${schema.spec.project}" + - id: storageNotification + template: + apiVersion: storage.cnrm.cloud.google.com/v1beta1 + kind: StorageNotification + metadata: + name: ${schema.spec.name}-gcs + spec: + bucketRef: + name: ${bucket.metadata.name} + topicRef: + name: ${topic.metadata.name} + eventTypes: + - "OBJECT_FINALIZE" + payloadFormat: JSON_API_V1 diff --git a/website/docs/examples/gcp/eventarc.md b/website/docs/examples/gcp/eventarc.md new file mode 100644 index 00000000..5ff95175 --- /dev/null +++ b/website/docs/examples/gcp/eventarc.md @@ -0,0 +1,273 @@ +--- +sidebar_position: 407 +--- + +# GCSBucketWithFinalizerTrigger + +A **Platform Administrator** wants to give end users in their organization self-service access to creating GCS Buckets that triggers a Cloud Workflow when any object in it is finalized. The platform administrator creates a kro ResourceGraphDefinition called *gcsbucketwithfinalizertrigger.kro.run* that defines the required Kubernetes resources and a CRD called *GCSBucketWithFinalizertrigger* that exposes only the options they want to be configurable by end users. + +The following KCC objects are created by this RGD: +* IAMServiceAccount, IAMPolicyMember: Service Account with necessary permissions for Eventarc and Pub/Sub. +* StorageBucket +* PubSubTopic +* EventArcTrigger +* StorageNotification: To publish events from the GCS bucket to a Pub/Sub topic. + +Pre-requisites: +* Workflow: The workflow to be triggered on Finalizer event. + +Everything related to these resources would be hidden from the end user, simplifying their experience. + +![GCS EventArc Stack](gcsbucket-with-finalizer-trigger.png) + + + + + +## End User: GCSBucketWithFinalizerTrigger + +The administrator needs to install the RGD first. +The end user creates a `GCSBucketWithFinalizerTrigger` resource something like this: + +```yaml +apiVersion: kro.run/v1alpha1 +kind: GCSBucketWithFinalizerTrigger +metadata: + name: gcsevent-test + namespace: config-connector +spec: + name: demo-gcs # used as name or prefix for KCC objects + workflowName: gcs-finalizer-workflow # Replace with your workflow path + location: us-central1 # desired location + project: my-project-name # Replace with your project name +``` + +They can then check the status of the applied resource: + +``` +kubectl get gcsbucketwithfinalizertrigger -n config-connector +kubectl get gcsbucketwithfinalizertrigger gcsevent-test -n config-connector -o yaml +``` + +Navigate to GCS page in the GCP Console and verify the bucket creation. Also verify that the Triggers are setup correctly in the EventArc page. + +Once done, the user can delete the `GCSBucketWithFinalizerTrigger` instance: + +``` +kubectl delete gcsbucketwithfinalizertrigger gcsevent-test -n config-connector +``` + +## Administrator: ResourceGraphDefinition +The administrator needs to install the RGD in the cluster first before the user can consume it: + +``` +kubectl apply -f rgd.yaml +``` + +Validate the RGD is installed correctly: + +``` +kubectl get rgd gcsbucketwithfinalizertrigger.kro.run +``` + +Once all user created instances are deleted, the administrator can choose to deleted the RGD. + +
+ ResourceGraphDefinition + ```yaml title="rgd.yaml" +apiVersion: kro.run/v1alpha1 +kind: ResourceGraphDefinition +metadata: + name: gcsbucketwithfinalizertrigger.kro.run +spec: + schema: + apiVersion: v1alpha1 + kind: GCSBucketWithFinalizerTrigger + spec: + name: string + workflowName: string + location: string + project: string + status: + url: ${bucket.status.url} + resources: + - id: storageEnable + template: + apiVersion: serviceusage.cnrm.cloud.google.com/v1beta1 + kind: Service + metadata: + annotations: + cnrm.cloud.google.com/deletion-policy: "abandon" + cnrm.cloud.google.com/disable-dependent-services: "false" + name: storage-enablement + spec: + resourceID: storage.googleapis.com + - id: iamEnable + template: + apiVersion: serviceusage.cnrm.cloud.google.com/v1beta1 + kind: Service + metadata: + annotations: + cnrm.cloud.google.com/deletion-policy: "abandon" + cnrm.cloud.google.com/disable-dependent-services: "false" + name: iam-enablement + spec: + resourceID: iam.googleapis.com + - id: pubsubEnable + template: + apiVersion: serviceusage.cnrm.cloud.google.com/v1beta1 + kind: Service + metadata: + annotations: + cnrm.cloud.google.com/deletion-policy: "abandon" + cnrm.cloud.google.com/disable-dependent-services: "false" + name: pubsub-enablement + spec: + resourceID: pubsub.googleapis.com + - id: eventarcEnable + template: + apiVersion: serviceusage.cnrm.cloud.google.com/v1beta1 + kind: Service + metadata: + annotations: + cnrm.cloud.google.com/deletion-policy: "abandon" + cnrm.cloud.google.com/disable-dependent-services: "false" + name: eventarc-enablement + spec: + resourceID: eventarc.googleapis.com + - id: iamsa + template: + apiVersion: iam.cnrm.cloud.google.com/v1beta1 + kind: IAMServiceAccount + metadata: + labels: + enabled-service: ${iamEnable.metadata.name} + #annotations: + # cnrm.cloud.google.com/project-id: ${schema.spec.project} + name: ${schema.spec.name} + spec: + displayName: ${schema.spec.name}-eventarc-workflow + - id: iampmEventarc + template: + apiVersion: iam.cnrm.cloud.google.com/v1beta1 + kind: IAMPolicyMember + metadata: + labels: + enabled-service: ${iamEnable.metadata.name} + name: ${schema.spec.name}-eventarc + spec: + memberFrom: + serviceAccountRef: + name: ${iamsa.metadata.name} + role: roles/eventarc.admin + resourceRef: + kind: Project + external: ${schema.spec.project} + - id: iampmWorkflow + template: + apiVersion: iam.cnrm.cloud.google.com/v1beta1 + kind: IAMPolicyMember + metadata: + labels: + enabled-service: ${iamEnable.metadata.name} + name: ${schema.spec.name}-workflow + spec: + memberFrom: + serviceAccountRef: + name: ${iamsa.metadata.name} + role: roles/workflows.admin + resourceRef: + kind: Project + external: ${schema.spec.project} + - id: topic + template: + apiVersion: pubsub.cnrm.cloud.google.com/v1beta1 + kind: PubSubTopic + metadata: + labels: + enabled-service: ${pubsubEnable.metadata.name} + name: ${schema.spec.name}-gcs-finalizer-topic + - id: bucket + template: + apiVersion: storage.cnrm.cloud.google.com/v1beta1 + kind: StorageBucket + metadata: + labels: + enabled-service: ${storageEnable.metadata.name} + name: ${schema.spec.name}-${schema.spec.project} + spec: + uniformBucketLevelAccess: true + - id: eventTrigger + template: + apiVersion: eventarc.cnrm.cloud.google.com/v1beta1 + kind: EventarcTrigger + metadata: + labels: + enabled-service: ${eventarcEnable.metadata.name} + name: ${schema.spec.name}-gcsfinalizer + spec: + destination: + workflowRef: + external: "projects/${schema.spec.project}/locations/${schema.spec.location}/workflows/${schema.spec.workflowName}" + location: ${schema.spec.location} + serviceAccountRef: + name: ${iamsa.metadata.name} + transport: + pubsub: + topicRef: + name: ${topic.metadata.name} + namespace: config-connector + matchingCriteria: + - attribute: "type" + value: "google.cloud.pubsub.topic.v1.messagePublished" + projectRef: + external: "projects/${schema.spec.project}" + - id: storageNotification + template: + apiVersion: storage.cnrm.cloud.google.com/v1beta1 + kind: StorageNotification + metadata: + name: ${schema.spec.name}-gcs + spec: + bucketRef: + name: ${bucket.metadata.name} + topicRef: + name: ${topic.metadata.name} + eventTypes: + - "OBJECT_FINALIZE" + payloadFormat: JSON_API_V1 + ``` +
diff --git a/website/docs/examples/gcp/gcsbucket-with-finalizer-trigger.png b/website/docs/examples/gcp/gcsbucket-with-finalizer-trigger.png new file mode 100644 index 00000000..8bfdd20f Binary files /dev/null and b/website/docs/examples/gcp/gcsbucket-with-finalizer-trigger.png differ diff --git a/website/docs/examples/gcp/gke-cluster.md b/website/docs/examples/gcp/gke-cluster.md index 264db6ef..6b4cbd3e 100644 --- a/website/docs/examples/gcp/gke-cluster.md +++ b/website/docs/examples/gcp/gke-cluster.md @@ -38,15 +38,15 @@ They can then check the status of the applied resource: ``` kubectl get gkeclusters -kubectl get gkeclusters krodemo -o yaml +kubectl get gkeclusters krodemo -n config-connector -o yaml ``` Navigate to GKE Cluster page in the GCP Console and verify the cluster creation. -Once done, the user can delete the `GKECluster`: +Once done, the user can delete the `GKECluster` instance: ``` -kubectl delete gkecluster $CLUSTER_NAME +kubectl delete gkecluster krodemo -n config-connector ``` ## Administrator: ResourceGraphDefinition