Skip to content

Commit

Permalink
Merge pull request #1 from loft-orbital/feat/add-postgres-module
Browse files Browse the repository at this point in the history
feat: add postgres module
  • Loading branch information
b4nst authored Feb 18, 2024
2 parents 93fa7a0 + c4910cb commit 67d2814
Show file tree
Hide file tree
Showing 17 changed files with 470 additions and 9 deletions.
4 changes: 3 additions & 1 deletion .prototools
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# Made with love by the Loft Orbital team under the APACHE 2.0 license

# vim: set filetype=toml :

moon = "1.21.1"
Expand All @@ -12,7 +14,7 @@ go = "1.21.6"
moon = "source:https://raw.githubusercontent.com/moonrepo/moon/master/proto-plugin.toml"
gojq = "source:https://raw.githubusercontent.com/stk0vrfl0w/proto-toml-plugins/main/plugins/gojq.toml"
cue = "source:./tools/buildsystem/plugins/cue.toml"
timoni = "source:./tools/buildsystem/plugins/timoni.toml"
timoni = "source:https://raw.githubusercontent.com/stefanprodan/timoni/main/proto-plugin.toml"
shellcheck = "source:./tools/buildsystem/plugins/shellcheck.toml"

[settings]
Expand Down
2 changes: 1 addition & 1 deletion libs/timoni-schemas/moon.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ tasks:
pull:
command: timoni artifact pull "oci://ghcr.io/stefanprodan/timoni/schemas:$TIMONI_VERSION" --output=cue.mod/pkg
env:
TIMONI_VERSION: 0.18.0
TIMONI_VERSION: 0.19.0
outputs:
- cue.mod/pkg/timoni.sh/**/*

Expand Down
59 changes: 59 additions & 0 deletions modules/postgresql/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# postgresql

A [timoni.sh](http://timoni.sh) module for deploying postgresql to Kubernetes clusters.

## Install

To create an instance using the default values:

```shell
timoni -n default apply postgresql oci://<container-registry-url>
```

To change the [default configuration](#configuration),
create one or more `values.cue` files and apply them to the instance.

For example, create a file `my-values.cue` with the following content:

```cue
values: {
resources: requests: {
cpu: "100m"
memory: "128Mi"
}
}
```

And apply the values with:

```shell
timoni -n default apply postgresql oci://<container-registry-url> \
--values ./my-values.cue
```

## Uninstall

To uninstall an instance and delete all its Kubernetes resources:

```shell
timoni -n default delete postgresql
```

## Configuration

| Key | Type | Default | Description |
|--------------------------|----------------------------------|--------------------|----------------------------------------------------------------------------------------------------------------------------------------------|
| `image: tag:` | `string` | `<latest version>` | Container image tag |
| `image: digest:` | `string` | `""` | Container image digest, takes precedence over `tag` when specified |
| `image: repository:` | `string` | `docker.io/nginx` | Container image repository |
| `image: pullPolicy:` | `string` | `IfNotPresent` | [Kubernetes image pull policy](https://kubernetes.io/docs/concepts/containers/images/#image-pull-policy) |
| `metadata: labels:` | `{[ string]: string}` | `{}` | Common labels for all resources |
| `metadata: annotations:` | `{[ string]: string}` | `{}` | Common annotations for all resources |
| `pod: annotations:` | `{[ string]: string}` | `{}` | Annotations applied to pods |
| `pod: affinity:` | `corev1.#Affinity` | `{}` | [Kubernetes affinity and anti-affinity](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#affinity-and-anti-affinity) |
| `pod: imagePullSecrets:` | `[...timoniv1.#ObjectReference]` | `[]` | [Kubernetes image pull secrets](https://kubernetes.io/docs/concepts/containers/images/#specifying-imagepullsecrets-on-a-pod) |
| `replicas:` | `int` | `1` | Kubernetes deployment replicas |
| `resources:` | `timoniv1.#ResourceRequirements` | `{}` | [Kubernetes resource requests and limits](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers) |
| `securityContext:` | `corev1.#SecurityContext` | `{}` | [Kubernetes container security context](https://kubernetes.io/docs/tasks/configure-pod-container/security-context) |
| `service: annotations:` | `{[ string]: string}` | `{}` | Annotations applied to the Kubernetes Service |
| `service: port:` | `int` | `80` | Kubernetes Service HTTP port |
1 change: 1 addition & 0 deletions modules/postgresql/cue.mod/module.cue
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module: "timoni.sh/postgresql"
6 changes: 6 additions & 0 deletions modules/postgresql/examples/minimal.cue
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package examples

// Complete the values with a minimal functional example.
values: {
password: "pg-super-secret"
}
10 changes: 10 additions & 0 deletions modules/postgresql/examples/volatile_storage.cue
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package examples

// Complete the values with a minimal functional example.
values: {
password: "super-secret"
storage: {
persistent: false
size: "5Gi"
}
}
109 changes: 109 additions & 0 deletions modules/postgresql/instance/config/config.cue
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package config

import (
"k8s.io/apimachinery/pkg/api/resource"
corev1 "k8s.io/api/core/v1"
timoniv1 "timoni.sh/core/v1alpha1"
)

// Config defines the schema and defaults for the Instance values.
#Config: {
// The kubeVersion is a required field, set at apply-time
// via timoni.cue by querying the user's Kubernetes API.
kubeVersion!: string
// Using the kubeVersion you can enforce a minimum Kubernetes minor version.
// By default, the minimum Kubernetes version is set to 1.20.
clusterVersion: timoniv1.#SemVer & {#Version: kubeVersion, #Minimum: "1.20.0"}

// The moduleVersion is set from the user-supplied module version.
// This field is used for the `app.kubernetes.io/version` label.
moduleVersion!: string

// The Kubernetes metadata common to all resources.
// The `metadata.name` and `metadata.namespace` fields are
// set from the user-supplied instance name and namespace.
metadata: timoniv1.#Metadata & {#Version: moduleVersion}

// The labels allows adding `metadata.labels` to all resources.
// The `app.kubernetes.io/name` and `app.kubernetes.io/version` labels
// are automatically generated and can't be overwritten.
metadata: labels: timoniv1.#Labels

// The annotations allows adding `metadata.annotations` to all resources.
metadata: annotations?: timoniv1.#Annotations

// The selector allows adding label selectors to Deployments and Services.
// The `app.kubernetes.io/name` label selector is automatically generated
// from the instance name and can't be overwritten.
selector: timoniv1.#Selector & {#Name: metadata.name}

// The image allows setting the container image repository,
// tag, digest and pull policy.
image: timoniv1.#Image & {
repository: *"docker.io/postgres" | string
tag: *"16" | string
digest: *"" | string
}

// The pod allows setting the Kubernetes Pod annotations, image pull secrets,
// affinity and anti-affinity rules. By default, pods are scheduled on Linux nodes.
pod: {
annotations?: timoniv1.#Annotations
affinity?: corev1.#Affinity
imagePullSecrets?: [...timoniv1.#ObjectReference]
}

// The resources allows setting the container resource requirements.
// By default, the container requests 10m CPU and 32Mi memory.
resources: timoniv1.#ResourceRequirements & {
requests: {
cpu: *"10m" | timoniv1.#CPUQuantity
memory: *"32Mi" | timoniv1.#MemoryQuantity
}
}

// The number of pods replicas.
// By default, the number of replicas is 1.
replicas: *1 | int & >0

// The securityContext allows setting the container security context.
// By default, the container is denined privilege escalation.
securityContext: corev1.#SecurityContext & {
allowPrivilegeEscalation: *false | true
privileged: *false | true
capabilities:
{
drop: *["ALL"] | [string]
add: *["CHOWN", "NET_BIND_SERVICE", "SETGID", "SETUID"] | [string]
}
}

// The service allows setting the Kubernetes Service annotations and port.
service: {
annotations?: timoniv1.#Annotations

port: *5432 | int & >0 & <=65535
}

// Postgres user
user: *"postgres" | string
// Postgres password
password!: string
// Postgres database
database: *"postgres" | string
// This optional config can be used to send arguments to postgres initdb. The value is a space separated string of arguments as postgres initdb would expect them. This is useful for adding functionality like data page checksums: "--data-checksums"
initdbArgs?: string
// This optional environment variable can be used to define another location for the Postgres transaction log. By default the transaction log is stored in a subdirectory of the main Postgres data folder
initdbWalDir?: string
// Storage configuration
storage: {
size: *"1Gi" | resource.#Quantity
persistent: *true | bool
retainPolicy: {
whenDeleted: *"Retain" | string
whenScaled: *"Retain" | string
}
labels: timoniv1.#Labels
annotations?: timoniv1.#Annotations
}
}
20 changes: 20 additions & 0 deletions modules/postgresql/instance/instance.cue
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package instance

import (
conf "timoni.sh/postgresql/instance/config"
"timoni.sh/postgresql/templates"
)

// Instance takes the config values and outputs the Kubernetes objects.
#Instance: {
config: conf.#Config

objects: {
statefulset: templates.#StatefulSet & {
#config: config
#secretname: secret.metadata.name
}
service: templates.#Service & {#config: config}
secret: templates.#Secret & {#config: config}
}
}
18 changes: 18 additions & 0 deletions modules/postgresql/moon.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
$schema: 'https://moonrepo.dev/schemas/project.json'

language: cue
type: application
platform: system

project:
name: 'postgresql'
description: 'Timoni module for postgresql'

dependsOn:
- utils
- k8s
- timoni-schemas
- buildsystem

tags:
- timoni
15 changes: 15 additions & 0 deletions modules/postgresql/templates/secret.cue
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package templates

import (
conf "timoni.sh/postgresql/instance/config"
timoniv1 "timoni.sh/core/v1alpha1"
)

#Secret: timoniv1.#ImmutableConfig & {
#config: conf.#Config
#Kind: timoniv1.#SecretKind
#Meta: #config.metadata
#Data: {
"pgpassword": #config.password
}
}
31 changes: 31 additions & 0 deletions modules/postgresql/templates/service.cue
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package templates

import (
conf "timoni.sh/postgresql/instance/config"

corev1 "k8s.io/api/core/v1"
)

#Service: corev1.#Service & {
#config: conf.#Config

apiVersion: "v1"
kind: "Service"
metadata: #config.metadata
if #config.service.annotations != _|_ {
metadata: annotations: #config.service.annotations
}

spec: corev1.#ServiceSpec & {
clusterIP: corev1.#ClusterIPNone
selector: #config.selector.labels
ports: [
{
port: #config.service.port
protocol: "TCP"
name: "psql"
targetPort: name
},
]
}
}
Loading

0 comments on commit 67d2814

Please sign in to comment.