Skip to content

Commit

Permalink
Merge pull request #11 from vmware-tanzu/horlh/gcp_postgres
Browse files Browse the repository at this point in the history
Introduce reference package for a Google Cloud SQL service instance
  • Loading branch information
Samze authored Jul 19, 2022
2 parents 5044be2 + 020cbf7 commit be6416f
Show file tree
Hide file tree
Showing 11 changed files with 557 additions and 3 deletions.
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,13 @@ Follow the instructions for a specific Service Instance below:

## Service Instances

| Type | Resource | Description | Status |
| ----------- | ----------- | ----------- | ----------- |
| [Amazon RDS](./amazon/ack/rds/README.md) | DBInstance | Create RDS instances | 🚧 Experimental |
| Type | Resource(s) | Description | Status |
| ------------------ | ---------------------------------- | -------------------------- | ---------------- |
| [Amazon RDS] | DBInstance | Create RDS instances | 🚧 Experimental |
| [Google Cloud SQL] | SQLInstance, SQLDatabase, SQLUser | Create Cloud SQL instances | 🚧 Experimental |

[Amazon RDS]: ./amazon/ack/rds/README.md
[Google Cloud SQL]: ./google/config-connector/cloudsql/README.md

## Building the Package Repository

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
---
apiVersion: imgpkg.carvel.dev/v1alpha1
kind: ImagesLock
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#@data/values-schema
---
#@schema/title "Service Instance Name"
#@schema/desc "The name of the Cloud SQL instance and related objects"
name: ""

#@schema/title "Service Instance Namespace"
#@schema/desc "The namespace the service instance objects should be deployed into"
#@schema/nullable
namespace: ""

#@schmea/title "Database Version"
#@schema/desc "The database version of the Cloud SQL instance\nsee: https://cloud.google.com/config-connector/docs/reference/resource-docs/sql/sqlinstance#:~:text=Fields-,databaseVersion,-Optional"
version: POSTGRES_14

#@schema/title "Database Region"
#@schema/desc "The region this Cloud SQL instance should be deployed into\nsee: https://cloud.google.com/config-connector/docs/reference/resource-docs/sql/sqlinstance#:~:text=with%2Dobjects/namespaces/-,region,-Optional"
region: europe-west6

#@schema/title "Database Machine Type"
#@schema/desc "The machine type for the Cloud SQL instance\nsee: https://cloud.google.com/config-connector/docs/reference/resource-docs/sql/sqlinstance#:~:text=from%20your%20configuration.-,settings.tier,-Required"
tier: db-g1-small

#@schema/title "Labels"
#@schema/desc "A set of labels which will be applied to all resources related to this instance"
#@schema/default {"app.kubernetes.io/component":"cloudsql-postgres"}
#@schema/examples ("Set custom labels on all objects", {"mycorp.io/service-type": "gcp-sql","mycorp.io/owner":"[email protected]"})
#@schema/type any=True
labels:

#@schema/title "Service Instance Labels"
#@schema/desc "A set of labels which will be applied to the claimable secret"
#@schema/default {"services.apps.tanzu.vmware.com/class":"cloudsql-postgres"}
#@schema/type any=True
serviceInstanceLabels:

#@schema/title "Allowed Networks"
#@schema/desc "A list of CIDR ranges allowed to talk to this Cloud SQL instance"
#@schema/examples ("Allow one (named) network & one host", [{"name": "my-onprem-net","value":"11.22.33.44/24"},{"value":"8.8.8.8/32"}])
#@schema/nullable
allowedNetworks:
-
#@schema/desc "the name for the authorized/allowed network (optional)"
#@schema/nullable
name: ""
#@schema/desc "the IPv4 CIDR of the authorized/allowed network"
value: ""
239 changes: 239 additions & 0 deletions bundles/google/config-connector/cloudsql/bundle/config/10-instance.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,239 @@
#@ load("@ytt:data", "data")
#@ load("@ytt:assert", "assert")
#@ load("@ytt:overlay", "overlay")
#@ load("@ytt:template", "template")


#@ if data.values.name == "":
#@ assert.fail('data value "name" must not be empty')
#@ end
#@ instanceName = data.values.name
#@ namespace = data.values.namespace
#@ labels = data.values.labels
#@ siLabels = data.values.serviceInstanceLabels
#@ version = data.values.version
#@ region = data.values.region
#@ tier = data.values.tier
#@ allowedNetworks = data.values.allowedNetworks

#! for now we only create one db and one user
#@ dbs = [ instanceName ]
#@ users = [ instanceName ]

#@ objReader = '{}-obj-reader'.format(instanceName)

#@ collectedPasswords = []
#@ generateCredName = lambda user: '{}-{}-creds'.format(instanceName, user)

#@ def generatePassword(name, len=64):
apiVersion: secretgen.k14s.io/v1alpha1
kind: Password
metadata:
name: #@ name
spec:
length: #@ len
secretTemplate:
type: Opaque
stringData:
password: $(value)
#@ collectedPasswords.append(name)
#@ end


---
#@ adminCredName = generateCredName("admin")
apiVersion: sql.cnrm.cloud.google.com/v1beta1
kind: SQLInstance
metadata:
name: #@ instanceName
spec:
databaseVersion: #@ version
region: #@ region
rootPassword:
valueFrom:
secretKeyRef:
key: password
name: #@ adminCredName
settings:
activationPolicy: ALWAYS
availabilityType: ZONAL
backupConfiguration:
backupRetentionSettings:
retainedBackups: 1
retentionUnit: COUNT
startTime: "16:00"
transactionLogRetentionDays: 1
diskAutoresize: true
diskAutoresizeLimit: 0
diskSize: 10
diskType: PD_SSD
ipConfiguration:
#@ if allowedNetworks:
authorizedNetworks: #@ allowedNetworks
#@ end
ipv4Enabled: true
locationPreference:
zone: #@ '{}-a'.format(region)
pricingPlan: PER_USE
tier: #@ tier
--- #@ generatePassword(adminCredName)

#@ for db in dbs:
---
apiVersion: sql.cnrm.cloud.google.com/v1beta1
kind: SQLDatabase
metadata:
name: #@ db
spec:
charset: UTF8
collation: en_US.UTF8
instanceRef:
name: #@ instanceName
#@ end

#@ for user in users:
---
#@ userCredName = generateCredName("user")
apiVersion: sql.cnrm.cloud.google.com/v1beta1
kind: SQLUser
metadata:
name: #@ user
spec:
instanceRef:
name: #@ instanceName
password:
valueFrom:
secretKeyRef:
key: password
name: #@ userCredName
--- #@ generatePassword(userCredName)
#@ end

---
apiVersion: v1
kind: ServiceAccount
metadata:
name: #@ objReader

---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: #@ objReader
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: #@ objReader
subjects:
- kind: ServiceAccount
name: #@ objReader

---
#! This can only happen after we've created all `Password`, otherwise
#! collectedPasswords won't be fully popoulated yet

#@ objReaderVerbs = ["get"]
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: #@ objReader
rules:
- apiGroups: [ "" ]
resources: [ "secrets" ]
verbs: #@ objReaderVerbs
resourceNames: #@ collectedPasswords
- apiGroups: [ "sql.cnrm.cloud.google.com" ]
resources: [ "sqlinstances" ]
verbs: #@ objReaderVerbs
resourceNames: #@ [ instanceName ]
#@ if/end len(dbs) >= 1:
- apiGroups: [ "sql.cnrm.cloud.google.com" ]
resources: [ "sqldatabases" ]
verbs: #@ objReaderVerbs
resourceNames: #@ dbs
#@ if/end len(users) >= 1:
- apiGroups: [ "sql.cnrm.cloud.google.com" ]
resources: [ "sqlusers" ]
verbs: #@ objReaderVerbs
resourceNames: #@ users

---
#@ def generateSecretTemplate(instance, user, db):

#! For now we deploy one instance with one database and one user. Thus we give
#! the SecretTemplate and therefor also the claimable secret the same name as
#! the instance itself.
#! Once we split that up and have multiple databases and/or users, we need to
#! come up with a naming strategy for the claimable secret.
#@ secTmplName = instance

apiVersion: secretgen.carvel.dev/v1alpha1
kind: SecretTemplate
metadata:
name: #@ secTmplName
spec:
inputResources:
- name: sqlInstance
ref:
apiVersion: sql.cnrm.cloud.google.com/v1beta1
kind: SQLInstance
name: #@ instance
- name: sqlDatabase
ref:
apiVersion: sql.cnrm.cloud.google.com/v1beta1
kind: SQLDatabase
name: #@ db
- name: sqlUser
ref:
apiVersion: sql.cnrm.cloud.google.com/v1beta1
kind: SQLUser
name: #@ user
- name: sqlUserSecret
ref:
apiVersion: v1
kind: Secret
name: $(.sqlUser.spec.password.valueFrom.secretKeyRef.name)
serviceAccountName: #@ objReader
template:
data:
password: $(.sqlUserSecret.data.password)
metadata:
labels:
#! services.apps.tanzu.vmware.com/CloudSQLInstance: $(.sqlInstance.metadata.name)
#! services.apps.tanzu.vmware.com/CloudSQLUser: $(.sqlUser.metadata.name)
#! services.apps.tanzu.vmware.com/CloudSQLDatabase: $(.sqlUser.metadata.name)
#! services.apps.tanzu.vmware.com/CloudSQLVersion: $(.sqlInstance.spec.databaseVersion)
app.kubernetes.io/instance: $(.sqlInstance.metadata.name)
_1: #@ template.replace(labels)
_2: #@ template.replace(siLabels)
stringData:
database: $(.sqlDatabase.metadata.name)
host: $(.sqlInstance.status.publicIpAddress)
port: "5432"
type: postgresql
username: $(.sqlUser.metadata.name)
#@ end

#@ for user in users:
#@ for db in dbs:
--- #@ generateSecretTemplate(instanceName, user, db)
#@ end
#@ end


#@ objToLabelAndNamespace = overlay.not_op(
#@ overlay.or_op(
#@ overlay.subset({"apiVersion":"kapp.k14s.io/v1alpha1","kind":"Config"}),
#@ overlay.subset({"kind": "ImagesLock"}),
#@ )
#@ )
#@overlay/match expects="1+", by=objToLabelAndNamespace
---
metadata:
#@overlay/match missing_ok=True
labels: #@ labels

#@ if namespace not in [None, ""]:
#@overlay/match missing_ok=True
namespace: #@ namespace
#@ end
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
apiVersion: kapp.k14s.io/v1alpha1
kind: Config
waitRules:
- supportsObservedGeneration: true
conditionMatchers:
- status: "True"
type: Ready
success: true
resourceMatchers: &cloudSqlResources
- apiVersionKindMatcher: {apiVersion: sql.cnrm.cloud.google.com/v1beta1, kind: SQLInstance}
- apiVersionKindMatcher: {apiVersion: sql.cnrm.cloud.google.com/v1beta1, kind: SQLDatabase}
- apiVersionKindMatcher: {apiVersion: sql.cnrm.cloud.google.com/v1beta1, kind: SQLUser}
rebaseRules:
- paths:
- [metadata, annotations, cnrm.cloud.google.com/management-conflict-prevention-policy]
- [metadata, annotations, cnrm.cloud.google.com/project-id]
- [metadata, annotations, cnrm.cloud.google.com/state-into-spec]
- [metadata, annotations, cnrm.cloud.google.com/observed-secret-versions]
- [metadata, annotations, cnrm.cloud.google.com/mutable-but-unreadable-fields]
- [spec, resourceID]
type: copy
sources: [new, existing]
resourceMatchers: *cloudSqlResources
4 changes: 4 additions & 0 deletions google/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Google

See:
- [Config Connector for Google Cloud SQL](./config-connector/cloudsql/README.md)
37 changes: 37 additions & 0 deletions google/config-connector/cloudsql/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Google Config Connector - CloudSQL PSQL Instance

Status: Experimental

## Description

This is a using the [Config Connector] to manage Google Cloud SQL PostrgreSQL
instances as a [Carvel Package].

[Config Connector]: https://cloud.google.com/config-connector/docs/overview
[Carvel Package]: https://carvel.dev/kapp-controller/docs/develop/packaging/

<!-- TODO update when published -->
<!--
## Use
For detailed instructions follow the guide [Services Toolkit Documentation on
Config Connector using Cloud SQL][stk]
[stk]: https://docs.vmware.com/en/Services-Toolkit-for-VMware-Tanzu-Application-Platform/index.html
-->

## Bundle

For more information on customizing the bundle see [here][bundle], specifically
the [values-schema]. Alternatively you can also see the configuration options
with the tanzu CLI once the [package repo has been installed][repo-install] on
your cluster:

```shell
tanzu package available get \
--values-schema psql.google.references.services.apps.tanzu.vmware.com/0.0.1-alpha
```

[bundle]: ../../../bundles/google/config-connector/cloudsql
[values-schema]: ../../../bundles/google/config-connector/cloudsql/bundle/config/00-schema.yml
[repo-install]: ../../../README.md#quick-start
Loading

0 comments on commit be6416f

Please sign in to comment.