Skip to content

Instantly share code, notes, and snippets.

@benagricola
Last active July 14, 2022 13:46
Show Gist options
  • Save benagricola/615a5b07e058e0a44edd442a588a99ae to your computer and use it in GitHub Desktop.
Save benagricola/615a5b07e058e0a44edd442a588a99ae to your computer and use it in GitHub Desktop.
Crossplane provider-aws and provider-sql integration example
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
labels:
res.company.io/purpose: database-instance
res.company.io/provider: aws
database.res.company.io/instance-engine: rds-postgres
database.res.company.io/cluster-type: standalone
name: database-instance-aws-rds-standalone
spec:
compositeTypeRef:
apiVersion: res.company.io/v1alpha1
kind: CompositeDatabaseInstance
# Write composition secrets to crossplane-system so they're not accessible
# by any randomer.
writeConnectionSecretsToNamespace: crossplane-system
resources:
# Create an RDS Instance
- name: DatabaseInstance
base:
apiVersion: database.aws.crossplane.io/v1beta1
kind: RDSInstance
metadata:
labels:
"res.company.io/identifier": rds-instance
spec:
deletionPolicy: Delete
forProvider:
engine: postgres
# TODO: Re-enable this when provider-sql can support a default
# database name.
# masterUsername: crossplane
masterUsername: postgres
skipFinalSnapshotBeforeDeletion: true
allowMajorVersionUpgrade: true
applyModificationsImmediately: true
multiAZ: true
engineVersion: "13.1"
# Pick subnet group and security group using selectors
dbSubnetGroupNameSelector:
matchLabels:
"res.company.io/identifier": rds-subnet-group
vpcSecurityGroupIDSelector:
matchLabels:
"res.company.io/identifier": rds-allow-inbound-psql-from-all
writeConnectionSecretToRef:
namespace: crossplane-system
connectionDetails:
- fromConnectionSecretKey: username
- fromConnectionSecretKey: password
- name: hostname
fromConnectionSecretKey: endpoint
- name: port
value: "5432"
patches:
- fromFieldPath: metadata.labels["crossplane.io/claim-name"]
toFieldPath: spec.writeConnectionSecretToRef.name
transforms:
- type: string
string:
fmt: "%s-admin"
# Create a Postgres ProviderConfig using the secret written by RDSInstance
- name: DatabaseProviderConfig
base:
apiVersion: postgresql.sql.crossplane.io/v1alpha1
kind: ProviderConfig
spec:
credentials:
source: PostgreSQLConnectionSecret
# This is deliberate. We do not want to expose the 'root' postgres
# user anywhere outside of the crossplane-system namespace (aka. cluster admin)
# If you need to access the database, you can use provider-sql (configured with
# this config!) to create a new role.
connectionSecretRef:
namespace: crossplane-system
readinessChecks:
- type: None
patches:
# Generate a deterministic name for this ProviderConfig so it can be referenced
# by other resources.
# TODO: If ProviderConfigSelector is added, use labels instead :>
- fromFieldPath: metadata.labels["crossplane.io/claim-name"]
toFieldPath: metadata.name
transforms:
- type: string
string:
fmt: "%s-db"
- fromFieldPath: metadata.labels["crossplane.io/claim-name"]
toFieldPath: spec.credentials.connectionSecretRef.name
transforms:
- type: string
string:
# Note that this generates the same string as the patch to RDSInstance above.
# The other option is to use bidirectional patching so instead of generating
# the same string in 2 different places, it is generated on the RDSInstance and
# then patched back to the Composition, to then be patched _forward_ here.
fmt: "%s-admin"
# Create a Role IN the above RDSInstance using the ProviderConfig from above
- name: Role
base:
apiVersion: postgresql.sql.crossplane.io/v1alpha1
kind: Role
metadata:
name: my-role
labels:
"res.company.io/identifier": application-db-role
spec:
deletionPolicy: Delete
forProvider:
privileges:
login: true
patches:
- fromFieldPath: metadata.labels["crossplane.io/claim-name"]
toFieldPath: spec.providerConfigRef.name
transforms:
- type: string
string:
# Note that this generates the same string as the patch to ProviderConfig above.
fmt: "%s-db"
# These following patches cause provider-sql to output a secret containing
# the username, password, endpoint and port for a new 'unprivileged' application user.
# These details are stored in the namespace that the claim was created in, so can be
# accessed directly by the user application (e.g. referenced in a provider-helm release).
- fromFieldPath: metadata.labels["crossplane.io/claim-namespace"]
toFieldPath: spec.writeConnectionSecretToRef.namespace
- fromFieldPath: metadata.labels["crossplane.io/claim-name"]
toFieldPath: spec.writeConnectionSecretToRef.name
transforms:
- type: string
string:
fmt: "%s-app-role-login"
# Create a database IN the above RDSInstance using the ProviderConfig from above
- name: Database
base:
apiVersion: postgresql.sql.crossplane.io/v1alpha1
kind: Database
metadata:
name: "my-database-name"
spec:
forProvider:
allowConnections: true
connectionLimit: 200
owner: my-role
patches:
- fromFieldPath: metadata.labels["crossplane.io/claim-name"]
toFieldPath: spec.providerConfigRef.name
transforms:
- type: string
string:
# Note that this generates the same string as the patch to ProviderConfig above.
fmt: "%s-db"
@gchait
Copy link

gchait commented Jul 14, 2022

The readinessChecks None on the ProviderConfig just saved my sanity after a long day of not understanding why my XR isn't ready, thank you :)

@benagricola
Copy link
Author

The readinessChecks None on the ProviderConfig just saved my sanity after a long day of not understanding why my XR isn't ready, thank you :)

Welcome, probably should've commented why that was there 🙂

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment