Add stackgres chart

This commit is contained in:
Jonny Ervine 2024-05-30 20:42:52 +08:00
parent 1026f0ea9b
commit db34ed82a3
49 changed files with 21734 additions and 0 deletions

View File

@ -0,0 +1,2 @@
README-crds.md
target

View File

@ -0,0 +1,23 @@
annotations:
charts.openshift.io/name: stackgres-operator
apiVersion: v2
appVersion: 1.10.0
description: StackGres Operator
home: https://stackgres.io
icon: https://gitlab.com/uploads/-/system/project/avatar/12584701/logo-stackgres.png?width=64
keywords:
- stackgres
- postgresql
- postgres
- cluster
- stack
- opinionated
kubeVersion: 1.18.0-0 - 1.29.x-O
maintainers:
- email: info@ongres.com
name: OnGres Inc.
url: https://ongres.com
name: stackgres-operator
sources:
- https://gitlab.com/ongresinc/stackgres
version: 1.10.0

View File

@ -0,0 +1,29 @@
[StackGres](https://stackgres.io) is the **Stack** required for enterprise production Post**Gres**. A fully-featured platform to run Postgres on Kubernetes. Fully Open Source, StackGres supports both a declarative approach suitable for GitOps workflows and a complete Web Console for the best user experience.
Built by [OnGres](https://ongres.com) ("**On** Post**Gres**"), StackGres requires little to no prior Postgres experience. StackGres can perform fully automated deployments; fully automated database operations ("Day 2 operations") and comes with advanced database tuning by default. Yet remaining highly customizable for Postgres expert DBAs.
[StackGres features](https://stackgres.io/features/) include, among others:
* **High Availability with automated failover**. StackGres relies on [Patroni](https://github.com/zalando/patroni), and its built-in and fully automatic.
* **Integrated connection pooling**. Built-in, by default, like it should be for production workloads.
* **Automatic backups with lifecycle policies**. Backup your clusters automatically to any object store. Apply retention policies. Restoration supports PITR.
* **Advanced replication modes**, including async, sync and group replication. It also supports cascading replication and standby clusters on separate Kubernetes clusters for disaster recovery.
* **More than 150 Postgres extensions**. The Postgres platform with [the largest number of extensions in the world](https://stackgres.io/extensions/). With new extensions added continuously.
* **Observability**. Fully integrated with the Prometheus stack. Includes pre-defined, Postgres-specific dashboards and alerts.
* **Fully-featured Web Console**. Perform any operation from the Web Console. Supports SSO, fine-grained RBAC and a REST API.
* **Distributed Logs**. StackGres developed a mechanism to ship logs from all pods to a central log server, managed by StackGres, that store logs in Postgres. Query your logs with SQL or from the Web Console!
* **Automated Day 2 Operations**. Minor and major version upgrades, container upgrades, controlled restart, vacuum, repack, even benchmarks!
* **Expertly tuned by default**. From the creators of [CONF](https://postgresqlco.nf), StackGres pre-tunes your Postgres servers with more than 40 parameters tuned by default.
* **100% Open Source**. No "premium version with advanced features", no production usage restrictions. Just Open Source.
* **[24/7 Support](https://stackgres.io/pricing/) Available from OnGres**
## Installation and documentation
Installation:
* For a quick test, you can follow our [quickstart](https://stackgres.io/doc/latest/demo/quickstart/).
* [Production installations](https://stackgres.io/doc/latest/install/).
All the documentation is available at [stackgres.io/doc](https://stackgres.io/doc/latest/install/).
Join the [Slack](https://slack.stackgres.io) and/or [Discord](https://discord.stackgres.io) Public Communities for Community support.

View File

@ -0,0 +1,31 @@
<table>
<thead>
<tr>
<th><div style="width:12rem">Key</div></th>
<th><div style="width:5rem">Type</div></th>
<th><div style="width:5rem">Default</div></th>
<th>Description</th>
</tr>
</thead>
<tbody><tr style="display:none;">
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td>
Workaround for hugo bug not rendering first table row
<br/>
</td>
</tr>
{{- range .Values }}
<tr>
<td id="{{ .Key | replace "." "--" }}">{{ .Key }}</td>
<td>{{ .Type }}</td>
<td>{{ default .Default .AutoDefault }}</td>
<td>{{ if .Description }}{{ .Description }}{{ else }}{{ .AutoDescription }}{{ end }}</td>
</tr>
{{- end }}
</tbody>
</table>

View File

@ -0,0 +1,665 @@
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: sgbackups.stackgres.io
spec:
group: stackgres.io
scope: Namespaced
names:
kind: SGBackup
listKind: SGBackupList
plural: sgbackups
singular: sgbackup
shortNames:
- sgbkp
versions:
- name: v1
served: true
storage: true
additionalPrinterColumns:
- name: cluster
type: string
jsonPath: .spec.sgCluster
- name: managed
type: string
jsonPath: .spec.managedLifecycle
- name: status
type: string
jsonPath: .status.process.status
- name: pg-version
type: string
jsonPath: .status.backupInformation.postgresVersion
priority: 1
- name: compressed-size
type: integer
format: byte
jsonPath: .status.backupInformation.size.compressed
priority: 1
- name: timeline
type: string
jsonPath: .status.backupInformation.timeline
priority: 1
schema:
openAPIV3Schema:
type: object
required: [metadata, spec]
description: |
A manual or automatically generated backup of an SGCluster configured with backups.
When a SGBackup is created a Job will perform a full backup of the database and update the status of the SGBackup
with the all the information required to restore it and some stats (or a failure message in case something unexpected
happened).
Backup generated by SGBackup are stored in the object storage configured with an SGObjectStorage together with the WAL
files or in a [VolumeSnapshot](https://kubernetes.io/docs/concepts/storage/volume-snapshots/) (separated from the WAL files that will be still stored in an object storage)
depending on the backup configuration of the targeted SGCluster.
After an SGBackup is created the same Job performs a reconciliation of the backups by applying the retention window
that has been configured in the SGCluster and removing the backups with managed lifecycle and the WAL files older
than the ones that fit in the retention window. The reconciliation also removes backups (excluding WAL files) that do
not belongs to any SGBackup (including copies). If the target storage is changed deletion of an SGBackup backups with
managed lifecycle and the WAL files older than the ones that fit in the retention window and of backups that do not
belongs to any SGBackup will not be performed anymore on the previous storage, only on the new target storage.
If the reconciliation of backups fails the backup itself do not fail and will be re-tried the next time a SGBackup
or shecduled backup Job take place.
properties:
metadata:
type: object
properties:
name:
type: string
maxLength: 56
pattern: "^[a-z]([-a-z0-9]*[a-z0-9])?$"
description: |
Name of the backup. Following [Kubernetes naming conventions](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/architecture/identifiers.md), it must be an rfc1035/rfc1123 subdomain, that is, up to 253 characters consisting of one or more lowercase labels separated by `.`. Where each label is an alphanumeric (a-z, and 0-9) string, with the `-` character allowed anywhere except the first or last character.
The name must be unique across all StackGres backups in the same namespace.
spec:
type: object
properties:
sgCluster:
type: string
description: |
The name of the `SGCluster` from which this backup is/will be taken.
If this is a copy of an existing completed backup in a different namespace
the value must be prefixed with the namespace of the source backup and a
dot `.` (e.g. `<cluster namespace>.<cluster name>`) or have the same value
if the source backup is also a copy.
managedLifecycle:
type: boolean
description: |
Indicate if this backup is not permanent and should be removed by the automated
retention policy. Default is `false`.
timeout:
type: integer
description: |
Allow to set a timeout for the backup creation.
If not set it will be disabled and the backup operation will continue until the backup completes or fail. If set to 0 is the same as not being set.
Make sure to set a reasonable high value in order to allow for any unexpected delays during backup creation (network low bandwidth, disk low throughput and so forth).
reconciliationTimeout:
type: integer
default: 300
description: |
Allow to set a timeout for the reconciliation process that take place after the backup.
If not set defaults to 300 (5 minutes). If set to 0 it will disable timeout.
Failure of reconciliation will not make the backup fail and will be re-tried the next time a SGBackup
or shecduled backup Job take place.
status:
type: object
properties:
internalName:
type: string
description: |
The name of the backup.
backupPath:
type: string
description: |
The path were the backup is stored.
process:
type: object
properties:
status:
type: string
description: |
Status of the backup.
failure:
type: string
description: |
If the status is `failed` this field will contain a message indicating the failure reason.
jobPod:
type: string
description: |
Name of the pod assigned to the backup. StackGres utilizes internally a locking mechanism based on the pod name of the job that creates the backup.
managedLifecycle:
type: boolean
description: |
Status (may be transient) until converging to `spec.managedLifecycle`.
timing:
type: object
properties:
start:
type: string
# format: date-time
description: |
Start time of backup.
end:
type: string
# format: date-time
description: |
End time of backup.
stored:
type: string
# format: date-time
description: |
Time at which the backup is safely stored in the object storage.
backupInformation:
type: object
properties:
hostname:
type: string
description: |
Hostname of the instance where the backup is taken from.
sourcePod:
type: string
description: |
Pod where the backup is taken from.
systemIdentifier:
type: string
description: |
Postgres *system identifier* of the cluster this backup is taken from.
postgresVersion:
type: string
description: |
Postgres version of the server where the backup is taken from.
pgData:
type: string
description: |
Data directory where the backup is taken from.
size:
type: object
properties:
uncompressed:
type: integer
format: int64
description: |
Size (in bytes) of the uncompressed backup.
compressed:
type: integer
format: int64
description: |
Size (in bytes) of the compressed backup.
lsn:
type: object
properties:
start:
type: string
description: |
LSN of when the backup started.
end:
type: string
description: |
LSN of when the backup finished.
startWalFile:
type: string
description: |
WAL segment file name when the backup was started.
timeline:
type: string
description: |
Backup timeline.
controlData:
type: object
description: |
An object containing data from the output of pg_controldata on the backup.
properties:
pg_control version number:
type: string
Catalog version number:
type: string
Database system identifier:
type: string
Database cluster state:
type: string
pg_control last modified:
type: string
Latest checkpoint location:
type: string
Latest checkpoint's REDO location:
type: string
Latest checkpoint's REDO WAL file:
type: string
Latest checkpoint's TimeLineID:
type: string
Latest checkpoint's PrevTimeLineID:
type: string
Latest checkpoint's full_page_writes:
type: string
Latest checkpoint's NextXID:
type: string
Latest checkpoint's NextOID:
type: string
Latest checkpoint's NextMultiXactId:
type: string
Latest checkpoint's NextMultiOffset:
type: string
Latest checkpoint's oldestXID:
type: string
Latest checkpoint's oldestXID's DB:
type: string
Latest checkpoint's oldestActiveXID:
type: string
Latest checkpoint's oldestMultiXid:
type: string
Latest checkpoint's oldestMulti's DB:
type: string
"Latest checkpoint's oldestCommitTsXid":
type: string
"Latest checkpoint's newestCommitTsXid":
type: string
Time of latest checkpoint:
type: string
Fake LSN counter for unlogged rels:
type: string
Minimum recovery ending location:
type: string
Min recovery ending loc's timeline:
type: string
Backup start location:
type: string
Backup end location:
type: string
End-of-backup record required:
type: string
wal_level setting:
type: string
wal_log_hints setting:
type: string
max_connections setting:
type: string
max_worker_processes setting:
type: string
max_wal_senders setting:
type: string
max_prepared_xacts setting:
type: string
max_locks_per_xact setting:
type: string
track_commit_timestamp setting:
type: string
Maximum data alignment:
type: string
Database block size:
type: string
Blocks per segment of large relation:
type: string
WAL block size:
type: string
Bytes per WAL segment:
type: string
Maximum length of identifiers:
type: string
Maximum columns in an index:
type: string
Maximum size of a TOAST chunk:
type: string
Size of a large-object chunk:
type: string
Date/time type storage:
type: string
Float4 argument passing:
type: string
Float8 argument passing:
type: string
Data page checksum version:
type: string
Mock authentication nonce:
type: string
sgBackupConfig:
type: object
description: The backup configuration used to perform this backup.
properties:
baseBackups:
type: object
description: |
Back backups configuration.
properties:
cronSchedule:
type: string
description: |
Continuous Archiving backups are composed of periodic *base backups* and all the WAL segments produced in between those base backups. This parameter specifies at what time and with what frequency to start performing a new base backup.
Use cron syntax (`m h dom mon dow`) for this parameter, i.e., 5 values separated by spaces:
* `m`: minute, 0 to 59
* `h`: hour, 0 to 23
* `dom`: day of month, 1 to 31 (recommended not to set it higher than 28)
* `mon`: month, 1 to 12
* `dow`: day of week, 0 to 7 (0 and 7 both represent Sunday)
Also ranges of values (`start-end`), the symbol `*` (meaning `first-last`) or even `*/N`, where `N` is a number, meaning every `N`, may be used. All times are UTC. It is recommended to avoid 00:00 as base backup time, to avoid overlapping with any other external operations happening at this time.
retention:
type: integer
minimum: 1
description: |
Based on this parameter, an automatic retention policy is defined to delete old base backups.
This parameter specifies the number of base backups to keep, in a sliding window.
Consequently, the time range covered by backups is `periodicity*retention`, where `periodicity` is the separation between backups as specified by the `cronSchedule` property.
Default is 5.
compression:
type: string
description: |
Select the backup compression algorithm. Possible options are: lz4, lzma, brotli. The default method is `lz4`. LZ4 is the fastest method, but compression ratio is the worst. LZMA is way slower, but it compresses backups about 6 times better than LZ4. Brotli is a good trade-off between speed and compression ratio, being about 3 times better than LZ4.
enum: [ lz4, lzma, brotli ]
performance:
type: object
properties:
maxNetworkBandwitdh:
type: integer
description: |
**Deprecated**: use instead maxNetworkBandwidth.
Maximum storage upload bandwidth to be used when storing the backup. In bytes (per second).
maxDiskBandwitdh:
type: integer
description: |
**Deprecated**: use instead maxDiskBandwidth.
Maximum disk read I/O when performing a backup. In bytes (per second).
maxNetworkBandwidth:
type: integer
description: |
Maximum storage upload bandwidth to be used when storing the backup. In bytes (per second).
maxDiskBandwidth:
type: integer
description: |
Maximum disk read I/O when performing a backup. In bytes (per second).
uploadDiskConcurrency:
type: integer
minimum: 1
description: |
Backup storage may use several concurrent streams to store the data. This parameter configures the number of parallel streams to use to reading from disk. By default, it's set to 1 (use one stream).
uploadConcurrency:
type: integer
minimum: 1
description: |
Backup storage may use several concurrent streams to store the data. This parameter configures the number of parallel streams to use. By default, it's set to 1 (use one stream).
compression:
type: string
description: |
Select the backup compression algorithm. Possible options are: lz4, lzma, brotli. The default method is `lz4`. LZ4 is the fastest method, but compression ratio is the worst. LZMA is way slower, but it compresses backups about 6 times better than LZ4. Brotli is a good trade-off between speed and compression ratio, being about 3 times better than LZ4.
enum: [lz4, lzma, brotli]
storage:
type: object
description: |
Backup storage configuration.
properties:
type:
type: string
enum: [s3, s3Compatible, gcs, azureBlob]
description: |
Specifies the type of object storage used for storing the base backups and WAL segments.
Possible values:
* `s3`: Amazon Web Services S3 (Simple Storage Service).
* `s3Compatible`: non-AWS services that implement a compatibility API with AWS S3.
* `gcs`: Google Cloud Storage.
* `azureBlob`: Microsoft Azure Blob Storage.
s3:
type: object
description: |
Amazon Web Services S3 configuration.
properties:
bucket:
type: string
pattern: ^[^/]+(/[^/]*)*$
description: |
AWS S3 bucket name.
path:
type: string
pattern: ^(/[^/]*)*$
description: |
Optional path within the S3 bucket. Note that StackGres generates in any case a folder per
StackGres cluster, using the `SGCluster.metadata.name`.
region:
type: string
description: |
AWS S3 region. The Region may be detected using s3:GetBucketLocation, but to avoid giving permissions to this API call or forbid it from the applicable IAM policy, this property must be explicitely specified.
storageClass:
type: string
description: |
[Amazon S3 Storage Class](https://aws.amazon.com/s3/storage-classes/) used for the backup object storage. By default, the `STANDARD` storage class is used. Other supported values include `STANDARD_IA` for Infrequent Access and `REDUCED_REDUNDANCY`.
awsCredentials:
type: object
description: |
Credentials to access AWS S3 for writing and reading.
properties:
secretKeySelectors:
type: object
description: |
Kubernetes [SecretKeySelector](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#secretkeyselector-v1-core)s to reference the Secrets that contain the information about the `awsCredentials`.
properties:
accessKeyId:
type: object
description: |
[SecretKeySelector](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#secretkeyselector-v1-core) containing the AWS Access Key ID secret.
properties:
key:
type: string
description: |
The key of the secret to select from. Must be a valid secret key.
name:
type: string
description: |
Name of the referent. [More information](https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names).
required: [key, name]
secretAccessKey:
type: object
description: |
[SecretKeySelector](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#secretkeyselector-v1-core) containing the AWS Secret Access Key secret.
properties:
key:
type: string
description: |
The key of the secret to select from. Must be a valid secret key.
name:
type: string
description: |
Name of the referent. [More information](https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names).
required: [key, name]
required: [accessKeyId, secretAccessKey]
required: [secretKeySelectors]
required: [bucket, awsCredentials]
s3Compatible:
type: object
description: AWS S3-Compatible API configuration
properties:
bucket:
type: string
pattern: ^[^/]+(/[^/]*)*$
description: |
Bucket name.
path:
type: string
pattern: ^(/[^/]*)*$
description: |
Optional path within the S3 bucket. Note that StackGres generates in any case a folder per StackGres cluster, using the `SGCluster.metadata.name`.
enablePathStyleAddressing:
type: boolean
description: |
Enable path-style addressing (i.e. `http://s3.amazonaws.com/BUCKET/KEY`) when connecting to an S3-compatible service that lacks support for sub-domain style bucket URLs (i.e. `http://BUCKET.s3.amazonaws.com/KEY`). Defaults to false.
endpoint:
type: string
description: |
Overrides the default url to connect to an S3-compatible service.
For example: `http://s3-like-service:9000`.
region:
type: string
description: |
AWS S3 region. The Region may be detected using s3:GetBucketLocation, but to avoid giving permissions to this API call or forbid it from the applicable IAM policy, this property must be explicitely specified.
storageClass:
type: string
description: |
[Amazon S3 Storage Class](https://aws.amazon.com/s3/storage-classes/) used for the backup object storage. By default, the `STANDARD` storage class is used. Other supported values include `STANDARD_IA` for Infrequent Access and `REDUCED_REDUNDANCY`.
awsCredentials:
type: object
description: |
Credentials to access AWS S3 for writing and reading.
properties:
secretKeySelectors:
type: object
description: |
A Kubernetes [SecretKeySelector](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#secretkeyselector-v1-core) to reference the Secrets that contain the information about the `awsCredentials`.
properties:
accessKeyId:
type: object
description: |
[SecretKeySelector](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#secretkeyselector-v1-core) containing the AWS Access Key ID secret.
properties:
key:
type: string
description: |
The key of the secret to select from. Must be a valid secret key.
name:
type: string
description: |
Name of the referent. [More information](https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names).
required: [key, name]
secretAccessKey:
type: object
description: |
[SecretKeySelector](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#secretkeyselector-v1-core) containing the AWS Secret Access Key secret.
properties:
key:
type: string
description: |
The key of the secret to select from. Must be a valid secret key.
name:
type: string
description: |
Name of the referent. [More information](https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names).
required: [key, name]
required: [accessKeyId, secretAccessKey]
required: [secretKeySelectors]
required: [bucket, awsCredentials]
gcs:
type: object
description: |
Google Cloud Storage configuration.
properties:
bucket:
type: string
pattern: ^[^/]+(/[^/]*)*$
description: |
GCS bucket name.
path:
type: string
pattern: ^(/[^/]*)*$
description: |
Optional path within the GCS bucket. Note that StackGres generates in any case a folder per StackGres cluster, using the `SGCluster.metadata.name`.
gcpCredentials:
type: object
description: |
Credentials to access GCS for writing and reading.
properties:
fetchCredentialsFromMetadataService:
type: boolean
description: |
If true, the credentials will be fetched from the GCE/GKE metadata service and the credentials from `secretKeySelectors` field will not be used.
This is useful when running StackGres inside a GKE cluster using [Workload Identity](https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity).
secretKeySelectors:
type: object
description: |
A Kubernetes [SecretKeySelector](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#secretkeyselector-v1-core) to reference the Secrets that contain the information about the Service Account to access GCS.
properties:
serviceAccountJSON:
type: object
description: |
A service account key from GCP. In JSON format, as downloaded from the GCP Console.
properties:
key:
type: string
description: |
The key of the secret to select from. Must be a valid secret key.
name:
type: string
description: |
Name of the referent. [More information](https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names).
required: [key, name]
required: [serviceAccountJSON]
required: [bucket, gcpCredentials]
azureBlob:
type: object
description: |
Azure Blob Storage configuration.
properties:
bucket:
type: string
pattern: ^[^/]+(/[^/]*)*$
description: |
Azure Blob Storage bucket name.
path:
type: string
pattern: ^(/[^/]*)*$
description: |
Optional path within the Azure Blobk bucket. Note that StackGres generates in any case a folder per StackGres cluster, using the `SGCluster.metadata.name`.
azureCredentials:
type: object
description: |
Credentials to access Azure Blob Storage for writing and reading.
properties:
secretKeySelectors:
type: object
description: |
Kubernetes [SecretKeySelector](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#secretkeyselector-v1-core)s to reference the Secrets that contain the information about the `azureCredentials`.
properties:
storageAccount:
type: object
description: |
[SecretKeySelector](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#secretkeyselector-v1-core) containing the name of the storage account.
properties:
key:
type: string
description: |
The key of the secret to select from. Must be a valid secret key.
name:
type: string
description: |
Name of the referent. [More information](https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names).
required: [key, name]
accessKey:
type: object
description: |
[SecretKeySelector](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#secretkeyselector-v1-core) containing the primary or secondary access key for the storage account.
properties:
key:
type: string
description: |
The key of the secret to select from. Must be a valid secret key.
name:
type: string
description: |
Name of the referent. [More information](https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names).
required: [key, name]
required: [storageAccount, accessKey]
required: [bucket, azureCredentials]
required: [type]
required: [storage]
volumeSnapshot:
type: object
description: The volume snapshot configuration used to restore this backup.
properties:
name:
type: string
description: |
The volume snapshot used to store this backup.
backupLabel:
type: string
description: |
The content of `backup_label` column returned by `pg_backup_stop` encoded in Base64
tablespaceMap:
type: string
description: |
The content of `tablespace_map` column returned by `pg_backup_stop` encoded in Base64

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,906 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: sgconfigs.stackgres.io
spec:
group: stackgres.io
names:
kind: SGConfig
listKind: SGConfigList
plural: sgconfigs
singular: sgconfig
scope: Namespaced
versions:
- name: v1
served: true
storage: true
subresources:
status: {}
additionalPrinterColumns:
- jsonPath: .metadata.annotations.stackgres\.io/lockPod
name: operator-pod
type: string
- jsonPath: .status.version
name: operator-version
type: string
schema:
openAPIV3Schema:
type: object
description: |
SGConfig stores the configuration of the StackGres Operator
> **WARNING**: Creating more than one SGConfig is forbidden in order to avoid misbehaviours. The single SGConfig should be created automatically during installation.
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: Spec defines the desired state of SGConfig
type: object
x-kubernetes-preserve-unknown-fields: true
properties:
containerRegistry:
type: string
default: quay.io
description: The container registry host (and port) where the images will be pulled from.
imagePullPolicy:
type: string
default: "IfNotPresent"
description: Image pull policy used for images loaded by the Operator
serviceAccount:
type: object
description: Section to configure Operator Installation ServiceAccount
properties:
create:
type: boolean
default: true
description: If `true` the Operator Installation ServiceAccount will be created
annotations:
type: object
x-kubernetes-preserve-unknown-fields: true
description: Section to configure Installation ServiceAccount annotations
repoCredentials:
type: array
description: Repositories credentials Secret names
items:
type: string
description: Repository credentials Secret name
operator:
type: object
description: Section to configure Operator Pod
properties:
image:
type: object
description: Section to configure Operator image
properties:
name:
type: string
default: "stackgres/operator"
description: Operator image name
tag:
type: string
description: Operator image tag
pullPolicy:
type: string
default: "IfNotPresent"
description: Operator image pull policy
annotations:
type: object
description: Operator Pod annotations
x-kubernetes-preserve-unknown-fields: true
resources:
type: object
description: Operator Pod resources. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#resourcerequirements-v1-core
x-kubernetes-preserve-unknown-fields: true
nodeSelector:
type: object
x-kubernetes-preserve-unknown-fields: true
description: Operator Pod node selector
tolerations:
type: array
description: Operator Pod tolerations. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#toleration-v1-core
items:
type: object
x-kubernetes-preserve-unknown-fields: true
affinity:
type: object
x-kubernetes-preserve-unknown-fields: true
description: Operator Pod affinity. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#affinity-v1-core
serviceAccount:
type: object
description: Section to configure Operator ServiceAccount
properties:
annotations:
type: object
x-kubernetes-preserve-unknown-fields: true
description: Section to configure Operator ServiceAccount annotations
repoCredentials:
type: array
description: Repositories credentials Secret names
items:
type: string
description: Repository credentials Secret name
service:
type: object
description: Section to configure Operator Service
properties:
annotations:
type: object
x-kubernetes-preserve-unknown-fields: true
description: Section to configure Operator Service annotations
restapi:
type: object
description: Section to configure REST API Pod
properties:
name:
type: string
default: stackgres-restapi
description: REST API container name
image:
type: object
description: Section to configure REST API image
properties:
name:
type: string
default: "stackgres/restapi"
description: REST API image name
tag:
type: string
description: REST API image tag
pullPolicy:
type: string
default: "IfNotPresent"
description: REST API image pull policy
annotations:
type: object
x-kubernetes-preserve-unknown-fields: true
description: REST API Pod annotations
resources:
type: object
x-kubernetes-preserve-unknown-fields: true
description: REST API Pod resources. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#resourcerequirements-v1-core
nodeSelector:
type: object
x-kubernetes-preserve-unknown-fields: true
description: REST API Pod node selector
tolerations:
type: array
description: REST API Pod tolerations. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#toleration-v1-core
items:
type: object
x-kubernetes-preserve-unknown-fields: true
affinity:
type: object
x-kubernetes-preserve-unknown-fields: true
description: REST API Pod affinity. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#affinity-v1-core
serviceAccount:
type: object
description: Section to configure REST API ServiceAccount
properties:
annotations:
type: object
x-kubernetes-preserve-unknown-fields: true
description: REST API ServiceAccount annotations
repoCredentials:
type: array
description: Repositories credentials Secret names
items:
type: string
description: Repository credentials Secret name
service:
type: object
description: Section to configure REST API Service
properties:
annotations:
type: object
x-kubernetes-preserve-unknown-fields: true
description: REST API Service annotations
adminui:
type: object
description: Section to configure Web Console container
properties:
image:
type: object
description: Section to configure Web Console image
properties:
name:
type: string
default: "stackgres/admin-ui"
description: Web Console image name
tag:
type: string
description: Web Console image tag
pullPolicy:
type: string
default: "IfNotPresent"
description: Web Console image pull policy
resources:
type: object
x-kubernetes-preserve-unknown-fields: true
description: Web Console resources. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#resourcerequirements-v1-core
service:
type: object
description: Section to configure Web Console service.
properties:
exposeHTTP:
type: boolean
default: false
description: When set to `true` the HTTP port will be exposed in the Web Console Service
type:
type: string
default: ClusterIP
description: |
The type used for the service of the UI:
* Set to LoadBalancer to create a load balancer (if supported by the kubernetes cluster)
to allow connect from Internet to the UI. Note that enabling this feature will probably incurr in
some fee that depend on the host of the kubernetes cluster (for example this is true for EKS, GKE
and AKS).
* Set to NodePort to expose admin UI from kubernetes nodes.
loadBalancerIP:
type: string
description: |
LoadBalancer will get created with the IP specified in
this field. This feature depends on whether the underlying cloud-provider supports specifying
the loadBalancerIP when a load balancer is created. This field will be ignored if the
cloud-provider does not support the feature.
loadBalancerSourceRanges:
type: array
description: |
If specified and supported by the platform,
this will restrict traffic through the cloud-provider load-balancer will be restricted to the
specified client IPs. This field will be ignored if the cloud-provider does not support the
feature.
More info: https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/
items:
type: string
nodePort:
type: integer
description: The HTTPS port used to expose the Service on Kubernetes nodes
nodePortHTTP:
type: integer
description: The HTTP port used to expose the Service on Kubernetes nodes
jobs:
type: object
description: Section to configure Operator Installation Jobs
properties:
image:
type: object
description: Section to configure Operator Installation Jobs image
properties:
name:
type: string
default: "stackgres/jobs"
description: Operator Installation Jobs image name
tag:
type: string
description: Operator Installation Jobs image tag
pullPolicy:
type: string
default: "IfNotPresent"
description: Operator Installation Jobs image pull policy
annotations:
type: object
x-kubernetes-preserve-unknown-fields: true
description: Operator Installation Jobs annotations
resources:
type: object
x-kubernetes-preserve-unknown-fields: true
description: Operator Installation Jobs resources. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#resourcerequirements-v1-core
nodeSelector:
type: object
x-kubernetes-preserve-unknown-fields: true
description: Operator Installation Jobs node selector
tolerations:
type: array
description: Operator Installation Jobs tolerations. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#toleration-v1-core
items:
type: object
x-kubernetes-preserve-unknown-fields: true
affinity:
type: object
x-kubernetes-preserve-unknown-fields: true
description: Operator Installation Jobs affinity. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#affinity-v1-core
serviceAccount:
type: object
description: Section to configure Jobs ServiceAccount
properties:
annotations:
type: object
x-kubernetes-preserve-unknown-fields: true
description: Jobs ServiceAccount annotations
repoCredentials:
type: array
description: Repositories credentials Secret names
items:
type: string
description: Repository credentials Secret name
deploy:
type: object
description: Section to configure deployment aspects.
properties:
operator:
type: boolean
default: true
description: When set to `true` the Operator will be deployed.
restapi:
type: boolean
default: true
description: When set to `true` the Web Console / REST API will be deployed.
cert:
type: object
description: Section to configure the Operator, REST API and Web Console certificates and JWT RSA key-pair.
properties:
autoapprove:
type: boolean
default: true
description: |
If set to `true` the CertificateSigningRequest used to generate the certificate used by
Webhooks will be approved by the Operator Installation Job.
createForOperator:
type: boolean
default: true
description: When set to `true` the Operator certificate will be created.
createForWebApi:
type: boolean
default: true
description: When set to `true` the Web Console / REST API certificate will be created.
secretName:
type: string
description: |
The Secret name with the Operator Webhooks certificate issued by the Kubernetes cluster CA
of type kubernetes.io/tls. See https://kubernetes.io/docs/concepts/configuration/secret/#tls-secrets
regenerateCert:
type: boolean
description: |
When set to `true` the Operator certificates will be regenerated if `createForOperator` is set to `true`, and the certificate is expired or invalid.
default: true
certDuration:
type: integer
description: |
The duration in days of the generated certificate for the Operator after which it will expire and be regenerated.
If not specified it will be set to 730 (2 years) by default.
webSecretName:
type: string
description: |
The Secret name with the Web Console / REST API certificate
of type kubernetes.io/tls. See https://kubernetes.io/docs/concepts/configuration/secret/#tls-secrets
regenerateWebCert:
type: boolean
description: |
When set to `true` the Web Console / REST API certificates will be regenerated if `createForWebApi` is set to `true`, and the certificate is expired or invalid.
default: true
regenerateWebRsa:
type: boolean
description: |
When set to `true` the Web Console / REST API RSA key pair will be regenerated if `createForWebApi` is set to `true`, and the certificate is expired or invalid.
default: true
webCertDuration:
type: integer
description: |
The duration in days of the generated certificate for the Web Console / REST API after which it will expire and be regenerated.
If not specified it will be set to 730 (2 years) by default.
webRsaDuration:
type: integer
description: |
The duration in days of the generated RSA key pair for the Web Console / REST API after which it will expire and be regenerated.
If not specified it will be set to 730 (2 years) by default.
certManager:
type: object
description: Section to configure cert-manager integration to generate Operator certificates
properties:
autoConfigure:
type: boolean
default: false
description: |
When set to `true` then Issuer and Certificate for Operator and Web Console / REST API
Pods will be generated
duration:
type: string
default: "2160h"
description: The requested duration (i.e. lifetime) of the Certificates. See https://cert-manager.io/docs/reference/api-docs/#cert-manager.io%2fv1
renewBefore:
type: string
default: "360h"
description: How long before the currently issued certificates expiry cert-manager should renew the certificate. See https://cert-manager.io/docs/reference/api-docs/#cert-manager.io%2fv1
encoding:
type: string
default: PKCS1
description: The private key cryptography standards (PKCS) encoding for this certificates private key to be encoded in. See https://cert-manager.io/docs/reference/api-docs/#cert-manager.io/v1.CertificatePrivateKey
size:
type: integer
default: 2048
description: Size is the key bit size of the corresponding private key for this certificate. See https://cert-manager.io/docs/reference/api-docs/#cert-manager.io/v1.CertificatePrivateKey
rbac:
type: object
description: Section to configure RBAC for Web Console admin user
properties:
create:
type: boolean
default: true
description: |
When set to `true` the admin user is assigned the `cluster-admin` ClusterRole by creating
ClusterRoleBinding.
authentication:
type: object
description: Section to configure Web Console authentication
properties:
type:
type: string
default: jwt
description: |
Specify the authentication mechanism to use. By default is `jwt`, see https://stackgres.io/doc/latest/api/rbac#local-secret-mechanism.
If set to `oidc` then see https://stackgres.io/doc/latest/api/rbac/#openid-connect-provider-mechanism.
createAdminSecret:
type: boolean
description: |
When `true` will create the secret used to store the admin user credentials to access the UI.
default: true
user:
type: string
default: admin
description: |
The admin username that will be created for the Web Console
Operator bundle installation can not change the default value of this field.
password:
type: string
description: |
The admin password that will be created for the Web Console.
If not specified a random password will be generated.
secretRef:
type: object
description: |
Allow to specify a reference to a Secret with the admin user credentials for the Web Console.
In order to assign properly permissions. Make sure the `user` field match the value of the `k8sUsername` key in the referenced Secret.
properties:
name:
description: The name of the Secret.
type: string
oidc:
type: object
description: Section to configure Web Console OIDC authentication
properties:
tlsVerification:
type: string
description: Can be one of `required`, `certificate-validation` or `none`
authServerUrl:
type: string
clientId:
type: string
credentialsSecret:
type: string
clientIdSecretRef:
type: object
properties:
name:
type: string
key:
type: string
credentialsSecretSecretRef:
type: object
properties:
name:
type: string
key:
type: string
prometheus:
type: object
description: Section to configure Prometheus integration.
properties:
allowAutobind:
type: boolean
default: true
description: |
If set to false disable automatic bind to Prometheus
created using the [Prometheus Operator](https://github.com/prometheus-operator/prometheus-operator).
If disabled the cluster will not be binded to Prometheus automatically and will require manual
intervention by the Kubernetes cluster administrator.
grafana:
type: object
description: Section to configure Grafana integration
properties:
autoEmbed:
type: boolean
default: false
description: |
When set to `true` embed automatically Grafana into the Web Console by creating the
StackGres dashboard and the read-only role used to read it from the Web Console
schema:
type: string
default: http
description: |
The schema to access Grafana. By default http. (used to embed manually and
automatically grafana)
webHost:
type: string
description: |
The service host name to access grafana (used to embed manually and
automatically Grafana).
The parameter value should point to the grafana service following the
[DNS reference](https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/) `svc_name.namespace`
datasourceName:
type: string
default: Prometheus
description: The datasource name used to create the StackGres Dashboard into Grafana
user:
type: string
default: admin
description: |
The username to access Grafana. By default admin. (used to embed automatically
Grafana)
password:
type: string
default: prom-operator
description: |
The password to access Grafana. By default prom-operator (the default in for
kube-prometheus-stack helm chart). (used to embed automatically Grafana)
secretNamespace:
type: string
description: |
The namespace of secret with credentials to access Grafana. (used to
embed automatically Grafana, alternative to use `user` and `password`)
secretName:
type: string
description: |
The name of secret with credentials to access Grafana. (used to embed
automatically Grafana, alternative to use `user` and `password`)
secretUserKey:
type: string
description: |
The key of secret with username used to access Grafana. (used to embed
automatically Grafana, alternative to use `user` and `password`)
secretPasswordKey:
type: string
description: |
The key of secret with password used to access Grafana. (used to
embed automatically Grafana, alternative to use `user` and `password`)
dashboardConfigMap:
type: string
description: |
The ConfigMap name with the dashboard JSON in the key `grafana-dashboard.json`
that will be created in Grafana. If not set the default
dashboardId:
type: string
description: |
The dashboard id that will be create in Grafana
(see https://grafana.com/grafana/dashboards). By default 9628. (used to embed automatically
Grafana)
Manual Steps:
Create grafana dashboard for postgres exporter and copy/paste share URL:
- Grafana > Create > Import > Grafana.com Dashboard 9628
Copy/paste grafana dashboard URL for postgres exporter:
- Grafana > Dashboard > Manage > Select postgres exporter dashboard > Copy URL
url:
type: string
description: |
The URL of the PostgreSQL dashboard created in Grafana (used to embed manually
Grafana)
token:
type: string
description: |
The Grafana API token to access the PostgreSQL dashboard created
in Grafana (used to embed manually Grafana)
Manual Steps:
Create and copy/paste grafana API token:
- Grafana > Configuration > API Keys > Add API key (for viewer) > Copy key value
extensions:
type: object
description: Section to configure extensions
properties:
repositoryUrls:
type: array
default:
- https://extensions.stackgres.io/postgres/repository
description: |
A list of extensions repository URLs used to retrieve extensions
To set a proxy for extensions repository add parameter proxyUrl to the URL:
`https://extensions.stackgres.io/postgres/repository?proxyUrl=<proxy scheme>%3A%2F%2F<proxy host>[%3A<proxy port>]` (URL encoded)
Other URL parameters are:
* `skipHostnameVerification`: set it to `true` in order to use a server or a proxy with a self signed certificate
* `retry`: set it to `<max retriex>[:<sleep before next retry>]` in order to retry a request on failure
* `setHttpScheme`: set it to `true` in order to force using HTTP scheme
items:
type: string
cache:
type: object
description: |
Section to configure extensions cache (experimental).
This feature is in beta and may cause failures, please use with caution and report any
error to https://gitlab.com/ongresinc/stackgres/-/issues/new
properties:
enabled:
type: boolean
default: false
description: |
When set to `true` enable the extensions cache.
This feature is in beta and may cause failures, please use with caution and report any
error to https://gitlab.com/ongresinc/stackgres/-/issues/new
preloadedExtensions:
type: array
default:
- x86_64/linux/timescaledb-1\.7\.4-pg12
description: An array of extensions pattern used to pre-loaded estensions into the extensions cache
items:
type: string
description: An extension pattern used to pre-loaded estensions into the extensions cache
persistentVolume:
type: object
description: Section to configure the extensions cache PersistentVolume
properties:
size:
type: string
default: 1Gi
description: |
The PersistentVolume size for the extensions cache
Only use whole numbers (e.g. not 1e6) and K/Ki/M/Mi/G/Gi as units
storageClass:
type: string
description: |
If defined set storage class
If set to "-" (equivalent to storageClass: "" in a PV spec) disables
dynamic provisioning
If undefined (the default) or set to null, no storageClass spec is
set, choosing the default provisioner. (gp2 on AWS, standard on
GKE, AWS & OpenStack)
hostPath:
type: string
description: |
If set, will use a host path volume with the specified path for the extensions cache
instead of a PersistentVolume
shardingSphere:
type: object
description: Section to configure integration with ShardingSphere operator
properties:
serviceAccount:
type: object
description: |
Section to configure ServiceAccount used by ShardingSphere operator.
You may configure a specific value for a sharded cluster under section
`SGShardedCluster.speccoordinator.configurations.shardingSphere.serviceAccount`.
required: [namespace,name]
properties:
namespace:
type: string
description: The namespace of the ServiceAccount used by ShardingSphere operator
name:
type: string
description: The name of the ServiceAccount used by ShardingSphere operator
developer:
type: object
x-kubernetes-preserve-unknown-fields: true
description: |
Section to configure developer options.
Following options are for developers only, but can also be useful in some cases ;)
properties:
version:
type: string
description: Set the operator version (used for testing)
logLevel:
type: string
description: Set `quarkus.log.level`. See https://quarkus.io/guides/logging#root-logger-configuration
showDebug:
type: boolean
default: false
description: If set to `true` add extra debug to any script controlled by the reconciliation cycle of the operator configuration
showStackTraces:
type: boolean
default: false
description: Set `quarkus.log.console.format` to `%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p [%c{4.}] (%t) %s%e%n`. See https://quarkus.io/guides/logging#logging-format
useJvmImages:
type: boolean
default: false
description: |
The operator will use JVM version of the images
enableJvmDebug:
type: boolean
default: false
description: |
Only work with JVM version and allow connect
on port 8000 of operator Pod with jdb or similar
enableJvmDebugSuspend:
type: boolean
default: false
description: |
Only work with JVM version and if `enableJvmDebug` is `true`
suspend the JVM until a debugger session is started
externalOperatorIp:
type: string
description: Set the external Operator IP
externalOperatorPort:
type: integer
description: Set the external Operator port
externalRestApiIp:
type: string
description: Set the external REST API IP
externalRestApiPort:
type: integer
description: Set the external REST API port
allowPullExtensionsFromImageRepository:
type: boolean
default: false
description: |
If set to `true` and `extensions.cache.enabled` is also `true`
it will try to download extensions from images (experimental)
disableArbitraryUser:
type: boolean
default: false
description: |
It set to `true` disable arbitrary user that is set for OpenShift clusters
patches:
type: object
description: |
Section to define patches for some StackGres Pods
properties:
operator:
type: object
description: |
Section to define volumes to be used by the operator container
properties:
volumes:
type: array
description: Pod volumes. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#volume-v1-core
items:
type: object
x-kubernetes-preserve-unknown-fields: true
volumeMounts:
type: array
description: Pod's container volume mounts. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#volumemount-v1-core
items:
type: object
x-kubernetes-preserve-unknown-fields: true
restapi:
type: object
description: |
Section to define volumes to be used by the restapi container
properties:
volumes:
type: array
description: Pod volumes. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#volume-v1-core
items:
type: object
x-kubernetes-preserve-unknown-fields: true
volumeMounts:
type: array
description: Pod's container volume mounts. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#volumemount-v1-core
items:
type: object
x-kubernetes-preserve-unknown-fields: true
adminui:
type: object
description: |
Section to define volumes to be used by the adminui container
properties:
volumes:
type: array
description: Pod volumes. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#volume-v1-core
items:
type: object
x-kubernetes-preserve-unknown-fields: true
volumeMounts:
type: array
description: Pod's container volume mounts. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#volumemount-v1-core
items:
type: object
x-kubernetes-preserve-unknown-fields: true
jobs:
type: object
description: |
Section to define volumes to be used by the jobs container
properties:
volumes:
type: array
description: Pod volumes. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#volume-v1-core
items:
type: object
x-kubernetes-preserve-unknown-fields: true
volumeMounts:
type: array
description: Pod's container volume mounts. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#volumemount-v1-core
items:
type: object
x-kubernetes-preserve-unknown-fields: true
clusterController:
type: object
description: |
Section to define volumes to be used by the cluster controller container
properties:
volumes:
type: array
description: Pod volumes. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#volume-v1-core
items:
type: object
x-kubernetes-preserve-unknown-fields: true
volumeMounts:
type: array
description: Pod's container volume mounts. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#volumemount-v1-core
items:
type: object
x-kubernetes-preserve-unknown-fields: true
distributedlogsController:
type: object
description: |
Section to define volumes to be used by the distributedlogs controller container
properties:
volumes:
type: array
description: Pod volumes. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#volume-v1-core
items:
type: object
x-kubernetes-preserve-unknown-fields: true
volumeMounts:
type: array
description: Pod's container volume mounts. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#volumemount-v1-core
items:
type: object
x-kubernetes-preserve-unknown-fields: true
status:
type: object
description: Status defines the observed state of SGConfig
x-kubernetes-preserve-unknown-fields: true
properties:
conditions:
type: array
items:
type: object
properties:
lastTransitionTime:
description: Last time the condition transitioned from one status to another.
type: string
message:
description: A human readable message indicating details about the transition.
type: string
reason:
description: The reason for the condition's last transition.
type: string
status:
description: Status of the condition, one of True, False, Unknown.
type: string
type:
description: Type of deployment condition.
type: string
version:
type: string
description: Latest version of the operator used to check for updates
removeOldOperatorBundleResources:
type: boolean
description: Indicate when the old operator bundle resources has been removed
grafana:
type: object
properties:
urls:
description: Grafana URLs to StackGres dashboards
type: array
items:
type: string
description: Grafana URL to StackGres dashboards preceded by the dashboard name and a semicolon `:`
token:
description: Grafana Token that allow to access dashboards
type: string
configHash:
description: Grafana configuration hash
type: string

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,271 @@
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: sginstanceprofiles.stackgres.io
spec:
group: stackgres.io
scope: Namespaced
names:
kind: SGInstanceProfile
listKind: SGInstanceProfileList
plural: sginstanceprofiles
singular: sginstanceprofile
shortNames:
- sginp
versions:
- name: v1
served: true
storage: true
additionalPrinterColumns:
- name: cpu
type: string
jsonPath: .spec.cpu
- name: memory
type: string
jsonPath: .spec.memory
schema:
openAPIV3Schema:
required: ["metadata", "spec"]
type: object
properties:
metadata:
type: object
properties:
name:
type: string
description: |
Name of the Instance Profile. An instance profile represents a "kind" of
server (CPU and RAM) where you may run StackGres Pods, classified by a given name.
The profile may be referenced by zero or more SGClusters, and if so it would
be referenced by its name. Following [Kubernetes naming conventions](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/architecture/identifiers.md), it must be an rfc1035/rfc1123 subdomain, that is, up to 253 characters consisting of one or more lowercase labels separated by `.`. Where each label is an alphanumeric (a-z, and 0-9) string, with the `-` character allowed anywhere except the first or last character.
The name must be unique across all instance profiles in the same namespace.
spec:
type: object
properties:
cpu:
type: string
pattern: '^[1-9][0-9]*[m]?$'
description: |
CPU(s) (cores) limits for every resource's Pod that reference this SGInstanceProfile. The suffix `m`
specifies millicpus (where 1000m is equals to 1).
The number of cpu limits is assigned to the patroni container (that runs both Patroni and PostgreSQL).
A minimum of 2 cpu is recommended.
memory:
type: string
pattern: '^[0-9]+(\.[0-9]+)?(Mi|Gi)$'
description: |
RAM limits for every resource's Pod that reference this SGInstanceProfile. The suffix `Mi` or `Gi`
specifies Mebibytes or Gibibytes, respectively.
The amount of RAM limits is assigned to the patroni container (that runs both Patroni and PostgreSQL).
A minimum of 2Gi is recommended.
hugePages:
type: object
description: |
RAM limits allocated for huge pages of the patroni container (that runs both Patroni and PostgreSQL).
properties:
hugepages-2Mi:
type: string
pattern: '^[0-9]+(\.[0-9]+)?(Mi|Gi)$'
description: |
RAM limits allocated for huge pages of the patroni container (that runs both Patroni and PostgreSQL) with a size of 2Mi. The suffix `Mi` or `Gi`
specifies Mebibytes or Gibibytes, respectively.
hugepages-1Gi:
type: string
pattern: '^[0-9]+(\.[0-9]+)?(Mi|Gi)$'
description: |
RAM limits allocated for huge pages of the patroni container (that runs both Patroni and PostgreSQL) with a size of 1Gi. The suffix `Mi` or `Gi`
specifies Mebibytes or Gibibytes, respectively.
containers:
type: object
description: |
The CPU(s) (cores) and RAM limits assigned to containers other than patroni container.
additionalProperties:
type: object
description: |
The CPU(s) (cores) and RAM limits assigned to a container.
This section, if left empty, will be filled automatically by the operator with
some defaults that can be proportional to the resources limits assigned to patroni
container (except for the huge pages that are always left untouched).
properties:
cpu:
type: string
pattern: '^[1-9][0-9]*[m]?$'
description: |
CPU(s) (cores) limits for the specified container. The suffix `m`
specifies millicpus (where 1000m is equals to 1).
memory:
type: string
pattern: '^[0-9]+(\.[0-9]+)?(Mi|Gi)$'
description: |
RAM limits for the specified container. The suffix `Mi` or `Gi`
specifies Mebibytes or Gibibytes, respectively.
hugePages:
type: object
description: |
RAM limits for huge pages for the specified container.
properties:
hugepages-2Mi:
type: string
pattern: '^[0-9]+(\.[0-9]+)?(Mi|Gi)$'
description: |
RAM limits for huge pages of the specified container with a size of 2Mi. The suffix `Mi`
or `Gi` specifies Mebibytes or Gibibytes, respectively.
hugepages-1Gi:
type: string
pattern: '^[0-9]+(\.[0-9]+)?(Mi|Gi)$'
description: |
RAM limits for huge pages of the specified container with a size of 1Gi. The suffix `Mi`
or `Gi` specifies Mebibytes or Gibibytes, respectively.
initContainers:
type: object
description: The CPU(s) (cores) and RAM limits assigned to the init containers.
additionalProperties:
type: object
description: |
The CPU(s) (cores) and RAM limits assigned to a init container.
This section will be filled automatically by the operator with
the same values of the resources limits assigned to patroni
container (except for the huge pages that are always left untouched).
properties:
cpu:
type: string
pattern: '^[1-9][0-9]*[m]?$'
description: |
CPU(s) (cores) limits for the specified init container. The suffix
`m` specifies millicpus (where 1000m is equals to 1).
memory:
type: string
pattern: '^[0-9]+(\.[0-9]+)?(Mi|Gi)$'
description: |
RAM limits for the specified init container. The suffix `Mi`
or `Gi` specifies Mebibytes or Gibibytes, respectively.
hugePages:
type: object
description: |
RAM limits for huge pages of the specified init container
properties:
hugepages-2Mi:
type: string
pattern: '^[0-9]+(\.[0-9]+)?(Mi|Gi)$'
description: |
RAM limits for huge pages of the specified init container with a size of 2Mi. The suffix `Mi`
or `Gi` specifies Mebibytes or Gibibytes, respectively.
hugepages-1Gi:
type: string
pattern: '^[0-9]+(\.[0-9]+)?(Mi|Gi)$'
description: |
RAM limits for huge pages of the specified init container with a size of 1Gi. The suffix `Mi` or `Gi`
specifies Mebibytes or Gibibytes, respectively.
requests:
type: object
description: |
This section allow to configure the resources requests for each container and, if not specified, it is filled with some defaults based on the fields `.spec.cpu` and `.spec.memory` will be set.
On containerized environments, when running production workloads, enforcing container's resources requirements requests to be equals to the limits in order to achieve the highest level of performance. Doing so, reduces the chances of leaving
the workload with less resources than it requires. It also allow to set [static CPU management policy](https://kubernetes.io/docs/tasks/administer-cluster/cpu-management-policies/#static-policy) that allows to guarantee a pod the usage exclusive CPUs on the node.
There are cases where you may need to set cpu requests to the same value as cpu limits in order to achieve static CPU management policy.
By default the resources requests values in fields `.spec.requests.cpu` and `.spec.requests.memory` represent the total resources requests assigned to each resource's Pod that reference this SGInstanceProfile.
The resources requests of the patroni container (that runs both Patroni and PostgreSQL) is calculated by subtracting from the total resources requests the resources requests of other containers that are present in the Pod.
To change this behavior and having the resources requests values in fields `.spec.requests.cpu` and `.spec.requests.memory` to represent the resources requests of the patroni container and the total resources requests
calculated by adding the resources requests of all the containers (including the patroni container) you may set one or more of the following fields to `true`
(depending on the resource's Pods you need this behaviour to be changed):
* `SGCluster.spec.pods.resources.disableResourcesRequestsSplitFromTotal`
* `SGShardedCluster.spec.coordinator.pods.resources.disableResourcesRequestsSplitFromTotal`
* `SGShardedCluster.spec.shards.pods.resources.disableResourcesRequestsSplitFromTotal`
* `SGShardedCluster.spec.shards.ovewrites.pods.resources.disableResourcesRequestsSplitFromTotal`
* `SGDistributedLogs.spec.resources.disableResourcesRequestsSplitFromTotal`
properties:
cpu:
type: string
pattern: '^[1-9][0-9]*[m]?$'
description: |
CPU(s) (cores) requests for every resource's Pod that reference this SGInstanceProfile. The suffix `m`
specifies millicpus (where 1000m is equals to 1).
By default the cpu requests values in field `.spec.requests.cpu` represent the total cpu requests assigned to each resource's Pod that reference this SGInstanceProfile.
The cpu requests of the patroni container (that runs both Patroni and PostgreSQL) is calculated by subtracting from the total cpu requests the cpu requests of other containers that are present in the Pod.
To change this behavior and having the cpu requests values in field `.spec.requests.cpu` to represent the cpu requests of the patroni container and the total cpu requests
calculated by adding the cpu requests of all the containers (including the patroni container) you may set one or more of the following fields to `true`
(depending on the resource's Pods you need this behaviour to be changed):
* `SGCluster.spec.pods.resources.disableResourcesRequestsSplitFromTotal`
* `SGShardedCluster.spec.coordinator.pods.resources.disableResourcesRequestsSplitFromTotal`
* `SGShardedCluster.spec.shards.pods.resources.disableResourcesRequestsSplitFromTotal`
* `SGShardedCluster.spec.shards.ovewrites.pods.resources.disableResourcesRequestsSplitFromTotal`
* `SGDistributedLogs.spec.resources.disableResourcesRequestsSplitFromTotal`
memory:
type: string
pattern: '^[0-9]+(\.[0-9]+)?(Mi|Gi)$'
description: |
RAM requests for every resource's Pod that reference this SGInstanceProfile. The suffix `Mi` or `Gi`
specifies Mebibytes or Gibibytes, respectively.
By default the memory requests values in field `.spec.requests.memory` represent the total memory requests assigned to each resource's Pod that reference this SGInstanceProfile.
The memory requests of the patroni container (that runs both Patroni and PostgreSQL) is calculated by subtracting from the total memory requests the memory requests of other containers that are present in the Pod.
To change this behavior and having the memory requests values in field `.spec.requests.memory` to represent the memory requests of the patroni container and the total memory requests
calculated by adding the memory requests of all the containers (including the patroni container) you may set one or more of the following fields to `true`
(depending on the resource's Pods you need this behaviour to be changed):
* `SGCluster.spec.pods.resources.disableResourcesRequestsSplitFromTotal`
* `SGShardedCluster.spec.coordinator.pods.resources.disableResourcesRequestsSplitFromTotal`
* `SGShardedCluster.spec.shards.pods.resources.disableResourcesRequestsSplitFromTotal`
* `SGShardedCluster.spec.shards.ovewrites.pods.resources.disableResourcesRequestsSplitFromTotal`
* `SGDistributedLogs.spec.resources.disableResourcesRequestsSplitFromTotal`
containers:
type: object
description: |
The CPU(s) (cores) and RAM requests assigned to containers other than patroni container.
additionalProperties:
type: object
description: |
The CPU(s) (cores) and RAM requests assigned to a container.
This section, if left empty, will be filled automatically by the operator with
some defaults that can be proportional to the resources assigned to patroni
container (except for the huge pages that are always left untouched).
properties:
cpu:
type: string
pattern: '^[1-9][0-9]*[m]?$'
description: |
CPU(s) (cores) requests for the specified container. The suffix `m`
specifies millicpus (where 1000m is equals to 1).
memory:
type: string
pattern: '^[0-9]+(\.[0-9]+)?(Mi|Gi)$'
description: |
RAM requests for the specified container. The suffix `Mi` or `Gi`
specifies Mebibytes or Gibibytes, respectively.
initContainers:
type: object
description: The CPU(s) (cores) and RAM requests assigned to init containers.
additionalProperties:
type: object
description: |
The CPU(s) (cores) and RAM requests assigned to a init container.
This section will be filled automatically by the operator with
the same values of the resources requests assigned to patroni
container (except for the huge pages that are always left untouched).
properties:
cpu:
type: string
pattern: '^[1-9][0-9]*[m]?$'
description: |
CPU(s) (cores) requests for the specified init container. The suffix
`m` specifies millicpus (where 1000m is equals to 1).
memory:
type: string
pattern: '^[0-9]+(\.[0-9]+)?(Mi|Gi)$'
description: |
RAM requests for the specified init container. The suffix `Mi`
or `Gi` specifies Mebibytes or Gibibytes, respectively.

View File

@ -0,0 +1,285 @@
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: sgobjectstorages.stackgres.io
spec:
group: stackgres.io
scope: Namespaced
names:
kind: SGObjectStorage
listKind: SGObjectStorageList
plural: sgobjectstorages
singular: sgobjectstorage
shortNames:
- sgobjs
versions:
- name: v1beta1
served: true
storage: true
additionalPrinterColumns:
- name: type
type: string
jsonPath: .spec.type
schema:
openAPIV3Schema:
type: object
required: ["metadata", "spec"]
properties:
metadata:
type: object
properties:
name:
type: string
description: |
Name of the Object Storage configuration.
The name must be unique across all object storage configurations in the same namespace.
spec:
type: object
description: |
Object Storage configuration
properties:
type:
type: string
enum: ["s3", "s3Compatible", "gcs", "azureBlob"]
description: |
Determine the type of object storage used for storing the base backups and WAL segments.
Possible values:
* `s3`: Amazon Web Services S3 (Simple Storage Service).
* `s3Compatible`: non-AWS services that implement a compatibility API with AWS S3.
* `gcs`: Google Cloud Storage.
* `azureBlob`: Microsoft Azure Blob Storage.
s3:
type: object
description: |
Amazon Web Services S3 configuration.
properties:
bucket:
type: string
pattern: '^((s3|https?)://)?[^/]+(/[^/]*)*$'
description: |
AWS S3 bucket name.
region:
type: string
description: |
The AWS S3 region. The Region may be detected using s3:GetBucketLocation, but if you wish to avoid giving permissions to this API call or forbid it from the applicable IAM policy, you must then specify this property.
storageClass:
type: string
description: |
The [Amazon S3 Storage Class](https://aws.amazon.com/s3/storage-classes/) to use for the backup object storage. By default, the `STANDARD` storage class is used. Other supported values include `STANDARD_IA` for Infrequent Access and `REDUCED_REDUNDANCY`.
awsCredentials:
type: object
description: |
The credentials to access AWS S3 for writing and reading.
properties:
secretKeySelectors:
type: object
description: |
Kubernetes [SecretKeySelector](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#secretkeyselector-v1-core)(s) to reference the Secrets that contain the information about the `awsCredentials`. Note that you may use the same or different Secrets for the `accessKeyId` and the `secretAccessKey`. In the former case, the `keys` that identify each must be, obviously, different.
properties:
accessKeyId:
type: object
description: |
AWS [access key ID](https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys). For example, `AKIAIOSFODNN7EXAMPLE`.
properties:
key:
type: string
description: |
The key of the secret to select from. Must be a valid secret key.
name:
type: string
description: |
Name of the referent. [More information](https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names).
required: ["key", "name"]
secretAccessKey:
type: object
description: |
AWS [secret access key](https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys). For example, `wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY`.
properties:
key:
type: string
description: |
The key of the secret to select from. Must be a valid secret key.
name:
type: string
description: |
Name of the referent. [More information](https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names).
required: ["key", "name"]
required: ["accessKeyId", "secretAccessKey"]
required: ["secretKeySelectors"]
required: ["bucket", "awsCredentials"]
s3Compatible:
type: object
description: "AWS S3-Compatible API configuration"
properties:
bucket:
type: string
pattern: '^((s3|https?)://)?[^/]+(/[^/]*)*$'
description: |
Bucket name.
enablePathStyleAddressing:
type: boolean
description: |
Enable path-style addressing (i.e. `http://s3.amazonaws.com/BUCKET/KEY`) when connecting to an S3-compatible service that lacks support for sub-domain style bucket URLs (i.e. `http://BUCKET.s3.amazonaws.com/KEY`).
Defaults to false.
endpoint:
type: string
description: |
Overrides the default url to connect to an S3-compatible service.
For example: `http://s3-like-service:9000`.
region:
type: string
description: |
The AWS S3 region. The Region may be detected using s3:GetBucketLocation, but if you wish to avoid giving permissions to this API call or forbid it from the applicable IAM policy, you must then specify this property.
storageClass:
type: string
description: |
The [Amazon S3 Storage Class](https://aws.amazon.com/s3/storage-classes/) to use for the backup object storage. By default, the `STANDARD` storage class is used. Other supported values include `STANDARD_IA` for Infrequent Access and `REDUCED_REDUNDANCY`.
awsCredentials:
type: object
description: |
The credentials to access AWS S3 for writing and reading.
properties:
secretKeySelectors:
type: object
description: |
Kubernetes [SecretKeySelector](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#secretkeyselector-v1-core)(s) to reference the Secret(s) that contain the information about the `awsCredentials`. Note that you may use the same or different Secrets for the `accessKeyId` and the `secretAccessKey`. In the former case, the `keys` that identify each must be, obviously, different.
properties:
accessKeyId:
type: object
description: |
AWS [access key ID](https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys). For example, `AKIAIOSFODNN7EXAMPLE`.
properties:
key:
type: string
description: |
The key of the secret to select from. Must be a valid secret key.
name:
type: string
description: |
Name of the referent. [More information](https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names).
required: ["key", "name"]
secretAccessKey:
type: object
description: |
AWS [secret access key](https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys). For example, `wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY`.
properties:
key:
type: string
description: |
The key of the secret to select from. Must be a valid secret key.
name:
type: string
description: |
Name of the referent. [More information](https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names).
required: ["key", "name"]
caCertificate:
type: object
description: |
CA Certificate file to be used when connecting to the S3 Compatible Service.
properties:
key:
type: string
description: |
The key of the secret to select from. Must be a valid secret key.
name:
type: string
description: |
Name of the referent. [More information](https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names).
required: ["key", "name"]
required: ["accessKeyId", "secretAccessKey"]
required: ["secretKeySelectors"]
required: ["bucket", "awsCredentials"]
gcs:
type: object
description: |
Google Cloud Storage configuration.
properties:
bucket:
type: string
pattern: "^(gs://)?[^/]+(/[^/]*)*$"
description: |
GCS bucket name.
gcpCredentials:
type: object
description: |
The credentials to access GCS for writing and reading.
properties:
fetchCredentialsFromMetadataService:
type: boolean
description: |
If true, the credentials will be fetched from the GCE/GKE metadata service and the field `secretKeySelectors` have to be set to null or omitted.
This is useful when running StackGres inside a GKE cluster using [Workload Identity](https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity).
secretKeySelectors:
type: object
description: |
A Kubernetes [SecretKeySelector](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#secretkeyselector-v1-core) to reference the Secrets that contain the information about the Service Account to access GCS.
properties:
serviceAccountJSON:
type: object
description: |
A service account key from GCP. In JSON format, as downloaded from the GCP Console.
properties:
key:
type: string
description: |
The key of the secret to select from. Must be a valid secret key.
name:
type: string
description: |
Name of the referent. [More information](https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names).
required: [ "key", "name" ]
required: [ "serviceAccountJSON" ]
required: [ "bucket", "gcpCredentials" ]
azureBlob:
type: object
description: |
Azure Blob Storage configuration.
properties:
bucket:
type: string
pattern: "^(azure://)?[^/]+(/[^/]*)*$"
description: |
Azure Blob Storage bucket name.
azureCredentials:
type: object
description: |
The credentials to access Azure Blob Storage for writing and reading.
properties:
secretKeySelectors:
type: object
description: |
Kubernetes [SecretKeySelector](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#secretkeyselector-v1-core)(s) to reference the Secret(s) that contain the information about the `azureCredentials`. . Note that you may use the same or different Secrets for the `storageAccount` and the `accessKey`. In the former case, the `keys` that identify each must be, obviously, different.
properties:
storageAccount:
type: object
description: |
The [Storage Account](https://docs.microsoft.com/en-us/azure/storage/common/storage-account-overview?toc=/azure/storage/blobs/toc.json) that contains the Blob bucket to be used.
properties:
key:
type: string
description: |
The key of the secret to select from. Must be a valid secret key.
name:
type: string
description: |
Name of the referent. [More information](https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names).
required: [ "key", "name" ]
accessKey:
type: object
description: |
The [storage account access key](https://docs.microsoft.com/en-us/azure/storage/common/storage-account-keys-manage?tabs=azure-portal).
properties:
key:
type: string
description: |
The key of the secret to select from. Must be a valid secret key.
name:
type: string
description: |
Name of the referent. [More information](https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names).
required: [ "key", "name" ]
required: [ "storageAccount", "accessKey" ]
required: [ "bucket", "azureCredentials" ]
required: [ "type" ]

View File

@ -0,0 +1,89 @@
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: sgpoolconfigs.stackgres.io
spec:
group: stackgres.io
scope: Namespaced
names:
kind: SGPoolingConfig
listKind: SGPoolingConfigList
plural: sgpoolconfigs
singular: sgpoolconfig
shortNames:
- sgpoc
- sgpoolingconfig
- sgpoolingconfigs
versions:
- name: v1
served: true
storage: true
schema:
openAPIV3Schema:
type: object
required: ["metadata", "spec"]
properties:
metadata:
type: object
properties:
name:
type: string
description: |
Name of the Connection Pooling Configuration. The configuration may be referenced by zero or more SGClusters, and if so it would be referenced by its name. Following [Kubernetes naming conventions](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/architecture/identifiers.md), it must be an rfc1035/rfc1123 subdomain, that is, up to 253 characters consisting of one or more lowercase labels separated by `.`. Where each label is an alphanumeric (a-z, and 0-9) string, with the `-` character allowed anywhere except the first or last character.
The name must be unique across all Connection Pooling configurations in the same namespace.
spec:
type: object
properties:
pgBouncer:
type: object
description: |
Connection pooling configuration based on PgBouncer.
properties:
pgbouncer.ini:
type: object
description: |
The `pgbouncer.ini` parameters the configuration contains, represented as an object where the keys are valid names for the `pgbouncer.ini` configuration file parameters.
Check [pgbouncer configuration](https://www.pgbouncer.org/config.html#generic-settings) for more information about supported parameters.
properties:
pgbouncer:
type: object
additionalProperties: true
description: |
The `pgbouncer.ini` (Section [pgbouncer]) parameters the configuration contains, represented as an object where the keys are valid names for the `pgbouncer.ini` configuration file parameters.
Check [pgbouncer configuration](https://www.pgbouncer.org/config.html#generic-settings) for more information about supported parameters
databases:
type: object
additionalProperties:
type: object
additionalProperties: true
description: |
The `pgbouncer.ini` (Section [databases]) parameters the configuration contains, represented as an object where the keys are valid names for the `pgbouncer.ini` configuration file parameters.
Check [pgbouncer configuration](https://www.pgbouncer.org/config.html#section-databases) for more information about supported parameters.
users:
type: object
additionalProperties:
type: object
additionalProperties: true
description: |
The `pgbouncer.ini` (Section [users]) parameters the configuration contains, represented as an object where the keys are valid names for the `pgbouncer.ini` configuration file parameters.
Check [pgbouncer configuration](https://www.pgbouncer.org/config.html#section-users) for more information about supported parameters.
status:
type: object
properties:
pgBouncer:
type: object
description: |
Connection pooling configuration status based on PgBouncer.
properties:
defaultParameters:
type: object
additionalProperties:
type: string
description: |
The `pgbouncer.ini` default parameters parameters which are used if not set.
required: ["defaultParameters"]

View File

@ -0,0 +1,66 @@
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: sgpgconfigs.stackgres.io
spec:
group: stackgres.io
scope: Namespaced
names:
kind: SGPostgresConfig
listKind: SGPostgresConfigList
plural: sgpgconfigs
singular: sgpgconfig
shortNames:
- sgpgc
- sgpostgresconfig
- sgpostgresconfigs
versions:
- name: v1
served: true
storage: true
additionalPrinterColumns:
- name: version
type: string
jsonPath: .spec.postgresVersion
schema:
openAPIV3Schema:
type: object
required: ["metadata", "spec"]
properties:
metadata:
type: object
properties:
name:
type: string
description: |
Name of the Postgres Configuration. The configuration may be referenced by zero or more SGClusters, and if so it would be referenced by its name. Following [Kubernetes naming conventions](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/architecture/identifiers.md), it must be an rfc1035/rfc1123 subdomain, that is, up to 253 characters consisting of one or more lowercase labels separated by `.`. Where each label is an alphanumeric (a-z, and 0-9) string, with the `-` character allowed anywhere except the first or last character.
The name must be unique across all Postgres configurations in the same namespace.
spec:
type: object
properties:
postgresVersion:
type: string
description: |
The **major** Postgres version the configuration is for. Postgres major versions contain one number starting with version 10 (`10`, `11`, `12`, etc), and two numbers separated by a dot for previous versions (`9.6`, `9.5`, etc).
Note that Postgres maintains full compatibility across minor versions, and hence a configuration for a given major version will work for any minor version of that same major version.
Check [StackGres component versions](https://stackgres.io/doc/latest/intro/versions) to see the Postgres versions supported by this version of StackGres.
postgresql.conf:
type: object
additionalProperties:
type: string
description: |
The `postgresql.conf` parameters the configuration contains, represented as an object where the keys are valid names for the `postgresql.conf` configuration file parameters of the given `postgresVersion`. You may check [postgresqlco.nf](https://postgresqlco.nf) as a reference on how to tune and find the valid parameters for a given major version.
required: ["postgresVersion", "postgresql.conf"]
status:
type: object
properties:
defaultParameters:
type: object
additionalProperties:
type: string
description: |
The `postgresql.conf` default parameters which are used if not set.
required: ["defaultParameters"]

View File

@ -0,0 +1,163 @@
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: sgscripts.stackgres.io
spec:
group: stackgres.io
scope: Namespaced
names:
kind: SGScript
listKind: SGScriptList
plural: sgscripts
singular: sgscript
shortNames:
- sgscr
versions:
- name: v1
served: true
storage: true
additionalPrinterColumns:
- name: scripts
type: string
jsonPath: .spec.scripts.length
schema:
openAPIV3Schema:
type: object
required: ["metadata", "spec"]
properties:
metadata:
type: object
properties:
name:
type: string
maxLength: 52
pattern: "^[a-z]([-a-z0-9]*[a-z0-9])?$"
description: |
Name of the StackGres script. Following [Kubernetes naming conventions](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/architecture/identifiers.md), it must be an rfc1035/rfc1123 subdomain, that is, up to 253 characters consisting of one or more lowercase labels separated by `.`. Where each label is an alphanumeric (a-z, and 0-9) string, with the `-` character allowed anywhere except the first or last character.
The name must be unique across all StackGres scripts in the same namespace. The full script name includes the namespace in which the script is created.
spec:
type: object
properties:
managedVersions:
type: boolean
description: |
If `true` the versions will be managed by the operator automatically. The user will still be able to update them if needed. `true` by default.
continueOnError:
type: boolean
description: |
If `true`, when any script entry fail will not prevent subsequent script entries from being executed. `false` by default.
scripts:
type: array
description: |
A list of SQL scripts.
items:
type: object
description: |
Scripts are executed in auto-commit mode with the user `postgres` in the specified database (or in database `postgres` if not specified).
Fields `script` and `scriptFrom` are mutually exclusive and only one of them is required.
properties:
name:
type: string
description: |
Name of the script. Must be unique across this SGScript.
id:
type: integer
description: |
The id is immutable and must be unique across all the script entries. It is replaced by the operator and is used to identify the script for the whole life of the `SGScript` object.
version:
type: integer
description: |
Version of the script. It will allow to identify if this script entry has been changed.
database:
type: string
description: |
Database where the script is executed. Defaults to the `postgres` database, if not specified.
user:
type: string
description: |
User that will execute the script. Defaults to the `postgres` user.
wrapInTransaction:
type: string
description: |
Wrap the script in a transaction using the specified transaction mode:
* `read-committed`: The script will be wrapped in a transaction using [READ COMMITTED](https://www.postgresql.org/docs/current/transaction-iso.html#XACT-READ-COMMITTED) isolation level.
* `repeatable-read`: The script will be wrapped in a transaction using [REPEATABLE READ](https://www.postgresql.org/docs/current/transaction-iso.html#XACT-REPEATABLE-READ) isolation level.
* `serializable`: The script will be wrapped in a transaction using [SERIALIZABLE](https://www.postgresql.org/docs/current/transaction-iso.html#XACT-SERIALIZABLE) isolation level.
If not set the script entry will not be wrapped in a transaction
storeStatusInDatabase:
type: boolean
description: |
When set to `true` the script entry execution will include storing the status of the execution of this
script entry in the table `managed_sql.status` that will be created in the specified `database`. This
will avoid an operation that fails partially to be unrecoverable requiring the intervention from the user
if user in conjunction with `retryOnError`.
If set to `true` then `wrapInTransaction` field must be set.
This is `false` by default.
retryOnError:
type: boolean
description: |
If not set or set to `false` the script entry will not be retried if it fails.
When set to `true` the script execution will be retried with an exponential backoff of 5 minutes,
starting from 10 seconds and a standard deviation of 10 seconds.
This is `false` by default.
script:
type: string
description: |
Raw SQL script to execute. This field is mutually exclusive with `scriptFrom` field.
scriptFrom:
type: object
description: |
Reference to either a Kubernetes [Secret](https://kubernetes.io/docs/concepts/configuration/secret/) or a [ConfigMap](https://kubernetes.io/docs/concepts/configuration/configmap/) that contains the SQL script to execute. This field is mutually exclusive with `script` field.
Fields `secretKeyRef` and `configMapKeyRef` are mutually exclusive, and one of them is required.
properties:
secretKeyRef:
type: object
description: |
A Kubernetes [SecretKeySelector](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#secretkeyselector-v1-core) that contains the SQL script to execute. This field is mutually exclusive with `configMapKeyRef` field.
properties:
name:
type: string
description: Name of the referent. [More information](https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names).
key:
type: string
description: The key of the secret to select from. Must be a valid secret key.
configMapKeyRef:
type: object
description: |
A [ConfigMap](https://kubernetes.io/docs/concepts/configuration/configmap/) reference that contains the SQL script to execute. This field is mutually exclusive with `secretKeyRef` field.
properties:
name:
type: string
description: |
The name of the ConfigMap that contains the SQL script to execute.
key:
type: string
description: |
The key name within the ConfigMap that contains the SQL script to execute.
status:
type: object
properties:
scripts:
type: array
description: |
A list of script entry statuses where a script entry under `.spec.scripts` is identified by the `id` field.
items:
type: object
properties:
id:
type: integer
description: |
The id that identifies a script entry.
hash:
type: string
description: |
The hash of a ConfigMap or Secret referenced with the associated script entry.

View File

@ -0,0 +1,146 @@
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: sgshardedbackups.stackgres.io
spec:
group: stackgres.io
scope: Namespaced
names:
kind: SGShardedBackup
listKind: SGShardedBackupList
plural: sgshardedbackups
singular: sgshardedbackup
shortNames:
- sgsbk
versions:
- name: v1
served: true
storage: true
additionalPrinterColumns:
- name: cluster
type: string
jsonPath: .spec.sgShardedCluster
- name: managed
type: string
jsonPath: .spec.managedLifecycle
- name: status
type: string
jsonPath: .status.process.status
- name: pg-version
type: string
jsonPath: .status.backupInformation.postgresVersion
priority: 1
- name: compressed-size
type: integer
format: byte
jsonPath: .status.backupInformation.size.compressed
priority: 1
schema:
openAPIV3Schema:
type: object
required: [metadata, spec]
description: |
A manual or automatically generated sharded backup of an SGCluster configured with an SGBackupConfig.
When a SGBackup is created a Job will perform a full sharded backup of the database and update the status of the SGBackup
with the all the information required to restore it and some stats (or a failure message in case something unexpected
happened).
After an SGBackup is created the same Job performs a reconciliation of the sharded backups by applying the retention window
that has been configured in the SGBackupConfig and removing the sharded backups with managed lifecycle and the WAL files older
than the ones that fit in the retention window. The reconciliation also removes sharded backups (excluding WAL files) that do
not belongs to any SGBackup. If the target storage of the SGBackupConfig is changed deletion of an SGBackup sharded backups
with managed lifecycle and the WAL files older than the ones that fit in the retention window and of sharded backups that do
not belongs to any SGBackup will not be performed anymore on the previous storage, only on the new target storage.
properties:
metadata:
type: object
properties:
name:
type: string
maxLength: 56
pattern: "^[a-z]([-a-z0-9]*[a-z0-9])?$"
description: |
Name of the sharded backup. Following [Kubernetes naming conventions](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/architecture/identifiers.md), it must be an rfc1035/rfc1123 subdomain, that is, up to 253 characters consisting of one or more lowercase labels separated by `.`. Where each label is an alphanumeric (a-z, and 0-9) string, with the `-` character allowed anywhere except the first or last character.
The name must be unique across all StackGres sharded backups in the same namespace."
spec:
type: object
properties:
sgShardedCluster:
type: string
description: |
The name of the `SGShardedCluster` from which this sharded backup is/will be taken.
If this is a copy of an existing completed sharded backup in a different namespace
the value must be prefixed with the namespace of the source backup and a
dot `.` (e.g. `<sharded cluster namespace>.<sharded cluster name>`) or have the same value
if the source sharded backup is also a copy.
managedLifecycle:
type: boolean
description: |
Indicate if this sharded backup is permanent and should not be removed by the automated
retention policy. Default is `false`.
status:
type: object
properties:
sgBackups:
type: array
description: |
The list of SGBackups that compose the SGShardedBackup used to restore the sharded cluster.
items:
type: string
description: |
One of the SGBackups that compose the SGShardedBackup used to restore the sharded cluster.
process:
type: object
properties:
status:
type: string
description: |
Status of the sharded backup.
failure:
type: string
description: |
If the status is `failed` this field will contain a message indicating the failure reason.
jobPod:
type: string
description: |
Name of the pod assigned to the sharded backup. StackGres utilizes internally a locking mechanism based on the pod name of the job that creates the sharded backup.
timing:
type: object
properties:
start:
type: string
# format: date-time
description: |
Start time of sharded backup.
end:
type: string
# format: date-time
description: |
End time of sharded backup.
stored:
type: string
# format: date-time
description: |
Time at which the sharded backup is safely stored in the object storage.
backupInformation:
type: object
properties:
postgresVersion:
type: string
description: |
Postgres version of the server where the sharded backup is taken from.
size:
type: object
properties:
uncompressed:
type: integer
format: int64
description: |
Size (in bytes) of the uncompressed sharded backup.
compressed:
type: integer
format: int64
description: |
Size (in bytes) of the compressed sharded backup.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,949 @@
#!/bin/sh
# shellcheck disable=SC2039
# shellcheck disable=SC2010
# shellcheck disable=SC2012
set -e
{ [ "$EXTENSIONS_CACHE_LOG_LEVEL" != DEBUG ] && [ "$EXTENSIONS_CACHE_LOG_LEVEL" != TRACE ]; } || set -x
run () {
# shellcheck disable=SC2153
[ -n "$EXTENSIONS_REPOSITORY_URLS" ]
[ -n "$1" ]
[ -n "$2" ]
NAMESPACE="$1"
STATEFULSET_NAME="$2"
SERVICEACCOUNT_NAME="${3:-$2}"
PERSISTENTVOLUMECLAIM_NAME="${4:-$2}"
SERVICEACCOUNT_JSON_FILE=serviceaccount.json
STATEFULSET_JSON_FILE=statefulset.json
ANY_IMAGE_REPOSITORY_URL="$(any_image_repository_url && echo true || echo false)"
EXTENSION_METADATA_VERSION=v2
DEFAULT_FLAVOR=pg
DEFAULT_BUILD_ARCH=x86_64
DEFAULT_BUILD_OS=linux
NOT_FOUND_URL_REGEXP='^[^ ]\+ - - \[\([^]]\+\)\] "GET \([^ ]\+\) HTTP\/1\.1" 404 [^ ]\+ "[^"]*" "[^"]*" "[^"]*"$'
while true
do
set +e
(
set -e
echo "Updating indexes..."
pull_indexes
echo "done"
echo
if [ "$ANY_IMAGE_REPOSITORY_URL" = true ]
then
echo "Updating repositories credentials..."
(
[ "$EXTENSIONS_CACHE_LOG_LEVEL" = TRACE ] || set +x
SERVICEACCOUNT="$(kubectl get serviceaccount -n "$NAMESPACE" "$SERVICEACCOUNT_NAME" -o json)"
printf '%s' "$SERVICEACCOUNT" > "$SERVICEACCOUNT_JSON_FILE"
)
update_repositories_credentials
(
[ "$EXTENSIONS_CACHE_LOG_LEVEL" = TRACE ] || set +x
kubectl patch serviceaccount -n "$NAMESPACE" "$SERVICEACCOUNT_NAME" --type merge -p "$(cat "$SERVICEACCOUNT_JSON_FILE")"
)
echo "done"
echo
fi
echo "Updating extensions..."
(
[ "$EXTENSIONS_CACHE_LOG_LEVEL" = TRACE ] || set +x
STATEFULSET="$(kubectl get statefulset -n "$NAMESPACE" "$STATEFULSET_NAME" -o json)"
printf '%s' "$STATEFULSET" > "$STATEFULSET_JSON_FILE"
)
(
[ "$EXTENSIONS_CACHE_LOG_LEVEL" = TRACE ] || set +x
get_to_install_extensions > full_to_install_extensions
sort full_to_install_extensions \
| uniq | { grep -v '^$' || true; } > to_install_extensions
TO_INSTALL_EXTENSIONS_JSON_STRING="$(jq -sR . to_install_extensions)"
PULLED_TO_INSTALL_EXTENSIONS_JSON_STRING="$(
jq '.metadata.annotations
| if . != null then .pulled_extensions else "" end
| if . != null then . else "" end' "$STATEFULSET_JSON_FILE")"
printf '%s' "$PULLED_TO_INSTALL_EXTENSIONS_JSON_STRING" | jq -r . > already_pulled_to_install_extensions
if [ "$TO_INSTALL_EXTENSIONS_JSON_STRING" != "$PULLED_TO_INSTALL_EXTENSIONS_JSON_STRING" ]
then
while read -r LINE
do
grep -q -xF "$LINE" already_pulled_to_install_extensions || printf '%s\n' "$LINE"
done < to_install_extensions > pull_to_install_extensions
else
true > pull_to_install_extensions
fi
get_not_found_to_install_extensions > not_found_to_install_extensions
)
rm -f pulled_to_install_extensions
touch pulled_to_install_extensions
cat pull_to_install_extensions not_found_to_install_extensions \
| while read -r TO_INSTALL_REPOSITORY PUBLISHER NAME VERSION POSTGRES_VERSION FLAVOR BUILD_ARCH BUILD_OS BUILD
do
try_function pull_extension "$TO_INSTALL_REPOSITORY" "$PUBLISHER" "$NAME" \
"$VERSION" "$POSTGRES_VERSION" "$FLAVOR" "$BUILD_ARCH" "$BUILD_OS" "$BUILD"
if "$RESULT"
then
echo "$TO_INSTALL_REPOSITORY" "$PUBLISHER" "$NAME" \
"$VERSION" "$POSTGRES_VERSION" "$FLAVOR" "$BUILD_ARCH" "$BUILD_OS" "$BUILD" >> pulled_to_install_extensions
else
echo "Warning: error while trying to pull extension " \
"$NAME-$VERSION-$FLAVOR$POSTGRES_VERSION$([ -z "$BUILD" ] || printf '%s' "-build-$BUILD")" \
"(publisher $PUBLISHER from $TO_INSTALL_REPOSITORY for $BUILD_ARCH/$BUILD_OS)" >&2
fi
done
(
[ "$EXTENSIONS_CACHE_LOG_LEVEL" = TRACE ] || set +x
ALREADY_PULLED_TO_INSTALL_EXTENSIONS_JSON_STRING="$(
jq '.metadata.annotations.pulled_extensions' "$STATEFULSET_JSON_FILE")"
PULLED_TO_INSTALL_EXTENSIONS_JSON_STRING="$(
cat pulled_to_install_extensions already_pulled_to_install_extensions \
| sort | uniq | jq -sR .)"
if [ "$ALREADY_PULLED_TO_INSTALL_EXTENSIONS_JSON_STRING" != "$PULLED_TO_INSTALL_EXTENSIONS_JSON_STRING" ]
then
RUNNING_IMAGES="$(kubectl get statefulset -n "$NAMESPACE" "$STATEFULSET_NAME" \
--template '{{ range .spec.template.spec.containers }}{{ printf "%s\n" .image }}{{ end }}')"
RUNNING_IMAGES="$(printf '%s' "$RUNNING_IMAGES" | sort)"
REQUIRED_IMAGES="$(jq '.spec.template.spec.containers[].image' "$STATEFULSET_JSON_FILE")"
REQUIRED_IMAGES="$(printf '%s' "$REQUIRED_IMAGES" | sort)"
if [ "$RUNNING_IMAGES" != "$REQUIRED_IMAGES" ]
then
touch /tmp/need-restart
fi
STATEFULSET="$(cat "$STATEFULSET_JSON_FILE")"
printf '%s' "$STATEFULSET" \
| jq ".metadata.annotations.pulled_extensions = $PULLED_TO_INSTALL_EXTENSIONS_JSON_STRING" \
> "$STATEFULSET_JSON_FILE"
cp "$STATEFULSET_JSON_FILE" "$STATEFULSET_JSON_FILE.new"
until kubectl replace statefulset -n "$NAMESPACE" "$STATEFULSET_NAME" \
--cascade orphan -f "$STATEFULSET_JSON_FILE.new"
do
sleep 5
STATEFULSET="$(kubectl get statefulset -n "$NAMESPACE" "$STATEFULSET_NAME" -o json)"
printf '%s' "$STATEFULSET" > "$STATEFULSET_JSON_FILE.lastest"
jq -s '.[0].spec.template = .[1].spec.template | .[0]' \
"$STATEFULSET_JSON_FILE.lastest" "$STATEFULSET_JSON_FILE" > "$STATEFULSET_JSON_FILE.new"
done
fi
if ! any_image_repository_url && test -f /tmp/need-restart
then
kubectl delete pod -n "$NAMESPACE" "$STATEFULSET_NAME-0"
fi
)
echo "done"
echo
)
EXIT_CODE="$?"
if [ "$EXIT_CODE" = 0 ]
then
if ! test -f /tmp/need-restart
then
touch /tmp/extensions-cache-ready
fi
echo
echo "...wait for next reconciliation cycle"
echo
sleep 10
else
echo
echo "...an error occurred during reconciliation cycle, retrying in 10 seconds"
echo
sleep 10
fi
done
}
any_image_repository_url() {
local EXTENSIONS_REPOSITORY_URL
for EXTENSIONS_REPOSITORY_URL in $(echo "$EXTENSIONS_REPOSITORY_URLS" | tr ',' '\n')
do
if is_image_repository_url "$EXTENSIONS_REPOSITORY_URL"
then
return
fi
done
return 1
}
is_image_repository_url() {
printf '%s' "$1" | grep -q "[?&]imageTemplate="
}
is_image_repository_with_regcred_secret_url() {
printf '%s' "$1" | grep "[?&]imageTemplate=" | grep -q "[?&]imageRegcredSecret="
}
is_proxied_repository_url() {
printf '%s' "$1" | grep -q "[?&]proxyUrl="
}
is_cache_timeout_repository_url() {
printf '%s' "$1" | grep -q "[?&]cacheTimeout="
}
is_skip_hostname_verification_repository_url() {
printf '%s' "$1" | grep -q "[?&]skipHostnameVerification="
}
is_set_http_scheme_url() {
printf '%s' "$1" | grep -q "[?&]setHttpScheme="
}
get_image_template_from_url() {
local IMAGE_TEMPLATE
IMAGE_TEMPLATE="$(printf '%s' "$1" | grep "[?&]imageTemplate=")"
IMAGE_TEMPLATE="$(printf '%s' "$IMAGE_TEMPLATE" \
| sed 's/^.*[?&]imageTemplate=\([^?&]\+\)\([?&].*\)\?$/\1/')"
IMAGE_TEMPLATE="$(printf '%s' "$IMAGE_TEMPLATE" | urldecode)"
# shellcheck disable=SC2016
if printf '%s' "$IMAGE_TEMPLATE" | grep -q '\([`;"]\|\$(\)'
then
# shellcheck disable=SC2016
echo 'Forbidden strings [`|;|"|$(] found in parameter imageTemplate of URL '"$1" >&2
return 1
fi
printf '%s' "$IMAGE_TEMPLATE"
}
get_image_regcred_secret_from_url() {
local REPOSITORY_CREDENTIAL_SECRET
REPOSITORY_CREDENTIAL_SECRET="$(printf '%s' "$1" | grep "[?&]imageRegcredSecret=")"
REPOSITORY_CREDENTIAL_SECRET="$(printf '%s' "$REPOSITORY_CREDENTIAL_SECRET" \
| sed 's/^.*[?&]imageRegcredSecret=\([^?&]\+\)\([?&].*\)\?$/\1/')"
REPOSITORY_CREDENTIAL_SECRET="$(printf '%s' "$REPOSITORY_CREDENTIAL_SECRET" | urldecode)"
printf '%s' "$REPOSITORY_CREDENTIAL_SECRET"
}
get_proxy_from_url() {
local PROXY_URL
PROXY_URL="$(printf '%s' "$1" | grep "[?&]proxyUrl=")"
PROXY_URL="$(printf '%s' "$PROXY_URL" \
| sed 's/^.*[?&]proxyUrl=\([^?&]\+\)\([?&].*\)\?$/\1/')"
PROXY_URL="$(printf '%s' "$PROXY_URL" | urldecode)"
printf '%s' "$PROXY_URL"
}
get_cache_timeout_from_url() {
local CACHE_TIMEOUT
CACHE_TIMEOUT="$(printf '%s' "$1" | grep "[?&]cacheTimeout=")"
CACHE_TIMEOUT="$(printf '%s' "$CACHE_TIMEOUT" \
| sed 's/^.*[?&]cacheTimeout=\([^?&]\+\)\([?&].*\)\?$/\1/')"
CACHE_TIMEOUT="$(printf '%s' "$CACHE_TIMEOUT" | urldecode)"
printf '%s' "$CACHE_TIMEOUT"
}
get_skip_hostname_verification_from_url() {
local SKIP_HOSTNAME_VERIFICATION
SKIP_HOSTNAME_VERIFICATION="$(printf '%s' "$1" | grep "[?&]skipHostnameVerification=")"
SKIP_HOSTNAME_VERIFICATION="$(printf '%s' "$SKIP_HOSTNAME_VERIFICATION" \
| sed 's/^.*[?&]skipHostnameVerification=\([^?&]\+\)\([?&].*\)\?$/\1/')"
SKIP_HOSTNAME_VERIFICATION="$(printf '%s' "$SKIP_HOSTNAME_VERIFICATION" | urldecode)"
printf '%s' "$SKIP_HOSTNAME_VERIFICATION"
}
get_set_http_scheme_from_url() {
local SET_HTTP_SCHEME
SET_HTTP_SCHEME="$(printf '%s' "$1" | grep "[?&]setHttpScheme=")"
SET_HTTP_SCHEME="$(printf '%s' "$SET_HTTP_SCHEME" \
| sed 's/^.*[?&]setHttpScheme=\([^?&]\+\)\([?&].*\)\?$/\1/')"
SET_HTTP_SCHEME="$(printf '%s' "$SET_HTTP_SCHEME" | urldecode)"
printf '%s' "$SET_HTTP_SCHEME"
}
pull_indexes() {
local INDEX_NAME EXTENSIONS_REPOSITORY_URL
local INDEX
for INDEX_NAME in index hashes
do
if ! test -s "unwrapped-${INDEX_NAME}.json"
then
echo '{}' > "unwrapped-${INDEX_NAME}.json"
fi
INDEX=-1
for EXTENSIONS_REPOSITORY_URL in $(echo "$EXTENSIONS_REPOSITORY_URLS" | tr ',' '\n')
do
INDEX="$((INDEX + 1))"
if ! is_index_cache_expired "$EXTENSIONS_REPOSITORY_URL" "$INDEX_NAME" "$INDEX"
then
continue
fi
local CURL_EXTRA_OPTS=""
if is_proxied_repository_url "$EXTENSIONS_REPOSITORY_URL"
then
local PROXY_URL
PROXY_URL="$(get_proxy_from_url "$EXTENSIONS_REPOSITORY_URL")"
CURL_EXTRA_OPTS="$CURL_EXTRA_OPTS --proxy $PROXY_URL"
fi
if is_skip_hostname_verification_repository_url "$EXTENSIONS_REPOSITORY_URL"
then
local SKIP_HOSTNAME_VERIFICATION
SKIP_HOSTNAME_VERIFICATION="$(get_skip_hostname_verification_from_url "$EXTENSIONS_REPOSITORY_URL")"
if [ "$SKIP_HOSTNAME_VERIFICATION" = true ]
then
CURL_EXTRA_OPTS="$CURL_EXTRA_OPTS -k"
fi
fi
curl -f -s -L $CURL_EXTRA_OPTS "${EXTENSIONS_REPOSITORY_URL%%\?*}/${EXTENSION_METADATA_VERSION}/${INDEX_NAME}.json" > "last-${INDEX_NAME}.json"
jq -s '.[0] as $last | .[1] as $current_unwrapped
| $last
| .publishers = (.publishers | map(
{
key: .id,
value: .
}
) | from_entries)
| .extensions = (.extensions | map(
{
key: .name,
value: (.repository = "'"${EXTENSIONS_REPOSITORY_URL%%\?*}"'")
}
) | from_entries)
| . as $last_unwrapped
| $current_unwrapped * $last_unwrapped
' "last-${INDEX_NAME}.json" "unwrapped-${INDEX_NAME}.json" > "new-unwrapped-${INDEX_NAME}.json"
local EXTENSIONS_REPOSITORY_PATH="${EXTENSIONS_REPOSITORY_URL#*://}"
EXTENSIONS_REPOSITORY_PATH="${EXTENSIONS_REPOSITORY_PATH%%\?*}"
mkdir -p "$EXTENSIONS_REPOSITORY_PATH/$EXTENSION_METADATA_VERSION/"
mv "last-${INDEX_NAME}.json" "$EXTENSIONS_REPOSITORY_PATH/$EXTENSION_METADATA_VERSION/${INDEX_NAME}.json"
mv "new-unwrapped-${INDEX_NAME}.json" "unwrapped-${INDEX_NAME}.json"
date +%s > "${INDEX_NAME}-${INDEX}.timestamp"
done
jq '.extensions = (.extensions | to_entries | map(.value))
| .publishers = (.publishers | to_entries | map(.value))
' "unwrapped-${INDEX_NAME}.json" > "merged-${INDEX_NAME}.json"
mv "merged-${INDEX_NAME}.json" "${INDEX_NAME}.json"
done
}
is_any_index_expired() {
local INDEX_NAME
for INDEX_NAME in index hashes
do
local INDEX=-1
for EXTENSIONS_REPOSITORY_URL in $(echo "$EXTENSIONS_REPOSITORY_URLS" | tr ',' '\n')
do
INDEX="$((INDEX + 1))"
if is_index_cache_expired "$EXTENSIONS_REPOSITORY_URL" "$INDEX_NAME" "$INDEX"
then
return
fi
done
done
return 1
}
is_index_cache_expired() {
[ -n "$1" ] && [ -n "$2" ] && [ -n "$3" ] \
&& true || false
local EXTENSIONS_REPOSITORY_URL="$1"
local INDEX_NAME="$2"
local INDEX="$3"
local CACHE_TIMEOUT=3600
if is_cache_timeout_repository_url "$EXTENSIONS_REPOSITORY_URL"
then
CACHE_TIMEOUT="$(get_cache_timeout_from_url "$EXTENSIONS_REPOSITORY_URL")"
fi
! test -f "${INDEX_NAME}-${INDEX}.timestamp" \
|| [ "$(date +%s)" -ge "$(( $(cat "${INDEX_NAME}-${INDEX}.timestamp") + CACHE_TIMEOUT ))" ]
}
update_repositories_credentials() {
local EXTENSIONS_REPOSITORY_URL SERVICEACCOUNT
for EXTENSIONS_REPOSITORY_URL in $(echo "$EXTENSIONS_REPOSITORY_URLS" | tr ',' '\n')
do
if is_image_repository_with_regcred_secret_url "$EXTENSIONS_REPOSITORY_URL"
then
REPOSITORY_CREDENTIAL_SECRET="$(get_image_regcred_secret_from_url "$EXTENSIONS_REPOSITORY_URL")"
if jq '([] + .imagePullSecrets)|any(.name == "'"$REPOSITORY_CREDENTIAL_SECRET"'")' "$SERVICEACCOUNT_JSON_FILE" | grep -q false
then
(
[ "$EXTENSIONS_CACHE_LOG_LEVEL" = TRACE ] || set +x
SERVICEACCOUNT="$(jq ".imagePullSecrets = .imagePullSecrets + [{name: \"$REPOSITORY_CREDENTIAL_SECRET\"}]" "$SERVICEACCOUNT_JSON_FILE")"
printf '%s' "$SERVICEACCOUNT" > "$SERVICEACCOUNT_JSON_FILE"
)
fi
fi
done
}
get_to_install_extensions() {
(
CLUSTER_EXTENSIONS="$(kubectl get sgcluster -A -o json)"
DISTRIBUTEDLOGS_EXTENSIONS="$(kubectl get sgdistributedlogs -A -o json)"
printf '%s' "$CLUSTER_EXTENSIONS" | jq '.items[]'
printf '%s' "$DISTRIBUTEDLOGS_EXTENSIONS" | jq '.items[]'
) | jq -r -s '.[]
| select(has("status") and (.status | has("arch") and has("os")))
| .status as $status
| .spec.toInstallPostgresExtensions
| if . != null then . else [] end
| .[]
| .repository + " "
+ .publisher + " "
+ .name + " "
+ .version + " "
+ .postgresVersion
+ " " + (.flavor | if . != null then . else "'"$DEFAULT_FLAVOR"'" end)
+ " " + $status.arch
+ " " + $status.os
+ " " + (.build | if . != null then . else "" end)
'
jq -r '
.extensions[] | . as $extension
| .versions[] | . as $version
| .availableFor = (.availableFor
| sort_by(if .build == null then 0 else (.build | split(".")
| (.[0] | tonumber | . * 10000) + (.[1] | split("-")[0] | tonumber)) end)
| reduce .[] as $availableFor ({};
. as $result | ($availableFor.postgresVersion | if . != null then . else "any" end)
+ "-" + ($availableFor.arch | if . != null then . else "'"$DEFAULT_BUILD_ARCH"'" end)
+ "-" + ($availableFor.os | if . != null then . else "'"$DEFAULT_BUILD_OS"'" end) | . as $key
| $result | .[$key] = $availableFor) | to_entries | map(.value))
| .availableFor[] | . as $availableFor
| select('"$EXTENSIONS_CACHE_PRELOADED_EXTENSIONS"' | any(. as $test
| $extension.publisher
+ "/" + ($availableFor.arch | if . != null then . else "'"$DEFAULT_BUILD_ARCH"'" end)
+ "/" + ($availableFor.os | if . != null then . else "'"$DEFAULT_BUILD_OS"'" end)
+ "/" + $extension.name + "-" + $version.version + "-"
+ ($availableFor.flavor | if . != null then . else "'"$DEFAULT_FLAVOR"'" end)
+ $availableFor.postgresVersion
+ ($availableFor.build | if . != null then "-build-" + . else "" end)
| test($test; "")))
| $extension.repository + " "
+ $extension.publisher + " "
+ $extension.name + " "
+ $version.version + " "
+ $availableFor.postgresVersion
+ " " + ($availableFor.flavor | if . != null then . else "'"$DEFAULT_FLAVOR"'" end)
+ " " + ($availableFor.arch | if . != null then . else "'"$DEFAULT_BUILD_ARCH"'" end)
+ " " + ($availableFor.os | if . != null then . else "'"$DEFAULT_BUILD_OS"'" end)
+ " " + ($availableFor.build | if . != null then . else "" end)' \
index.json || echo "Error while applying filter $EXTENSIONS_CACHE_PRELOADED_EXTENSIONS to preload extensions" >&2
}
get_not_found_to_install_extensions() {
rm -f last_date_time_found
grep "$NOT_FOUND_URL_REGEXP" /var/log/nginx/access.log \
| sed -u "s/$NOT_FOUND_URL_REGEXP/\1 \2/" \
| while read -r DATE_TIME TIME_ZONE NOT_FOUND_URL
do
if test -f last_date_time \
&& [ "$DATE_TIME $TIME_ZONE" = "$(cat last_date_time)" ] \
&& ! test -f last_date_time_found
then
touch last_date_time_found
continue
fi
try_function get_extension_from_url "$NOT_FOUND_URL"
if "$RESULT"
then
printf '%s %s' "$DATE_TIME" "$TIME_ZONE" > last_date_time
else
echo "Warning: error while trying to extract extension from $NOT_FOUND_URL" >&2
fi
done
}
get_extension_from_url() {
[ -n "$1" ] && true || false
local NOT_FOUND_URL="$1"
local EXTENSIONS_REPOSITORY_URL NOT_FOUND_URL_PATH EXTENSIONS_REPOSITORY_URL_PATH
local REPOSITORY PUBLISHER BUILD_ARCH BUILD_OS EXTENSION_PACKAGE EXTENSION_ID_JSON
EXTENSIONS_REPOSITORY_URL="$(find_repository_base_url "$NOT_FOUND_URL")"
if is_image_repository_url "$EXTENSIONS_REPOSITORY_URL"
then
return
fi
NOT_FOUND_URL_PATH="${NOT_FOUND_URL#*://}"
NOT_FOUND_URL_PATH="${NOT_FOUND_URL_PATH%%\?*}"
EXTENSIONS_REPOSITORY_URL_PATH="${EXTENSIONS_REPOSITORY_URL%%\?*}"
EXTENSIONS_REPOSITORY_URL_PATH="${EXTENSIONS_REPOSITORY_URL_PATH#*://}"
NOT_FOUND_URL_RESOURCE_PATH="${NOT_FOUND_URL_PATH#${EXTENSIONS_REPOSITORY_URL_PATH}}"
NOT_FOUND_URL_RESOURCE_PATH="${NOT_FOUND_URL_RESOURCE_PATH#/}"
if [ "$(printf '%s' "$NOT_FOUND_URL_RESOURCE_PATH" | fold -w 1 | grep -c /)" -eq 3 ]
then
REPOSITORY="${NOT_FOUND_URL%%$NOT_FOUND_URL_RESOURCE_PATH\?*}"
PUBLISHER="$(printf '%s' "$NOT_FOUND_URL_RESOURCE_PATH" | cut -d '/' -f 1)"
BUILD_ARCH="$(printf '%s' "$NOT_FOUND_URL_RESOURCE_PATH" | cut -d '/' -f 2)"
BUILD_OS="$(printf '%s' "$NOT_FOUND_URL_RESOURCE_PATH" | cut -d '/' -f 3)"
EXTENSION_PACKAGE="$(printf '%s' "$NOT_FOUND_URL_RESOURCE_PATH" | cut -d '/' -f 4)"
EXTENSION_PACKAGE="${EXTENSION_PACKAGE%.tar}"
EXTENSION_ID_JSON="$(printf '%s' "$PUBLISHER/$BUILD_ARCH/$BUILD_OS/$EXTENSION_PACKAGE" | jq -sR .)"
jq -r '
.extensions[] | . as $extension
| .versions[] | . as $version
| .availableFor | map(. as $availableFor
| select('"$EXTENSION_ID_JSON"' ==
$extension.publisher + "/"
+ ($availableFor.arch | if . != null then . else "'"$DEFAULT_BUILD_ARCH"'" end) + "/"
+ ($availableFor.os | if . != null then . else "'"$DEFAULT_BUILD_OS"'" end) + "/"
+ $extension.name + "-" + $version.version + "-"
+ ($availableFor.flavor | if . != null then . else "'"$DEFAULT_FLAVOR"'" end)
+ $availableFor.postgresVersion
+ ($availableFor.build | if . != null then "-build-" + . else "" end))
| $extension.repository + " "
+ $extension.publisher + " "
+ $extension.name + " "
+ $version.version + " "
+ $availableFor.postgresVersion
+ " " + ($availableFor.flavor | if . != null then . else "'"$DEFAULT_FLAVOR"'" end)
+ " " + ($availableFor.arch | if . != null then . else "'"$DEFAULT_BUILD_ARCH"'" end)
+ " " + ($availableFor.os | if . != null then . else "'"$DEFAULT_BUILD_OS"'" end)
+ " " + ($availableFor.build | if . != null then . else "" end))
| .[]' \
index.json
fi
}
pull_extension() {
[ -n "$1" ] && [ -n "$2" ] && [ -n "$3" ] && [ -n "$4" ] \
&& [ -n "$5" ] && [ -n "$6" ] && [ -n "$7" ] && [ -n "$8" ] \
&& true || false
local TO_INSTALL_REPOSITORY="$1"
local PUBLISHER="$2"
local NAME="$3"
local VERSION="$4"
local POSTGRES_VERSION="$5"
local FLAVOR="$6"
local BUILD_ARCH="$7"
local BUILD_OS="$8"
local BUILD="$9"
local REPOSITORY="$TO_INSTALL_REPOSITORY"
local EXTENSION_PACKAGE
EXTENSION_PACKAGE="$NAME-$VERSION-$FLAVOR$POSTGRES_VERSION$([ -z "$BUILD" ] || printf '%s' "-build-$BUILD")"
echo " * Required extension $EXTENSION_PACKAGE"
EXTENSIONS_REPOSITORY_URL="$(find_repository_base_url "$REPOSITORY")"
if [ "$ANY_IMAGE_REPOSITORY_URL" != true ] \
|| ! is_image_repository_url "$EXTENSIONS_REPOSITORY_URL"
then
download_extension "$EXTENSIONS_REPOSITORY_URL" "$REPOSITORY" "$PUBLISHER" "$BUILD_ARCH" "$BUILD_OS"\
"$EXTENSION_PACKAGE"
else
add_extension_image_to_statefulset "$EXTENSIONS_REPOSITORY_URL" "$REPOSITORY" "$PUBLISHER" "$NAME" \
"$VERSION" "$POSTGRES_VERSION" "$FLAVOR" "$BUILD_ARCH" "$BUILD_OS" "$BUILD"
fi
}
find_repository_base_url() {
[ -n "$1" ] && true || false
local REPOSITORY="$1"
local IS_PROXY_URL_AND_SET_HTTP_SCHEME=false
if is_proxied_repository_url "$REPOSITORY"
then
local PROXY_URL
PROXY_URL="$(get_proxy_from_url "$REPOSITORY")"
if is_set_http_scheme_url "$PROXY_URL"
then
IS_PROXY_URL_AND_SET_HTTP_SCHEME="$(get_set_http_scheme_from_url "$PROXY_URL")"
fi
fi
! test -f "${INDEX_NAME}-${INDEX}.timestamp" \
|| [ "$(date +%s)" -ge "$(( $(cat "${INDEX_NAME}-${INDEX}.timestamp") + CACHE_TIMEOUT ))" ]
local EXTENSIONS_REPOSITORY_URL
for EXTENSIONS_REPOSITORY_URL in $(echo "$EXTENSIONS_REPOSITORY_URLS" | tr ',' '\n')
do
local TEST_EXTENSIONS_REPOSITORY_URL="$EXTENSIONS_REPOSITORY_URL"
if [ "$IS_PROXY_URL_AND_SET_HTTP_SCHEME" = true ]
then
TEST_EXTENSIONS_REPOSITORY_URL="http://${EXTENSIONS_REPOSITORY_URL#*://}"
fi
if printf '%s' "$TEST_EXTENSIONS_REPOSITORY_URL" | grep -q "^${REPOSITORY%%\?*}" \
|| printf '%s' "$REPOSITORY" | grep -q "^${TEST_EXTENSIONS_REPOSITORY_URL%%\?*}"
then
printf '%s' "$EXTENSIONS_REPOSITORY_URL"
return
fi
done
echo "Warning: Could not found repository $REPOSITORY between following repositories:" >&2
echo >&2
echo "$EXTENSIONS_REPOSITORY_URLS" | tr ',' '\n' >&2
echo >&2
return 1
}
download_extension() {
[ -n "$1" ] && [ -n "$2" ] && [ -n "$3" ] && [ -n "$4" ] \
&& [ -n "$5" ] && [ -n "$6" ] && true || false
local EXTENSIONS_REPOSITORY_URL="$1"
local REPOSITORY="$2"
local PUBLISHER="$3"
local BUILD_ARCH="$4"
local BUILD_OS="$5"
local EXTENSION_PACKAGE="$6"
local TEMP="$(shuf -i 0-65535 -n 1)"
local REPOSITORY_PATH="${REPOSITORY#*://}"
if ! test -f "$REPOSITORY_PATH/$PUBLISHER/$BUILD_ARCH/$BUILD_OS/$EXTENSION_PACKAGE.tar"
then
echo " + Downloading from $REPOSITORY/$PUBLISHER/$BUILD_ARCH/$BUILD_OS/$EXTENSION_PACKAGE.tar"
mkdir -p "$REPOSITORY_PATH/$PUBLISHER/$BUILD_ARCH/$BUILD_OS"
local CURL_EXTRA_OPTS=""
if is_proxied_repository_url "$EXTENSIONS_REPOSITORY_URL"
then
local PROXY_URL
PROXY_URL="$(get_proxy_from_url "$EXTENSIONS_REPOSITORY_URL")"
CURL_EXTRA_OPTS="--proxy $PROXY_URL"
fi
if is_skip_hostname_verification_repository_url "$EXTENSIONS_REPOSITORY_URL"
then
local SKIP_HOSTNAME_VERIFICATION
SKIP_HOSTNAME_VERIFICATION="$(get_skip_hostname_verification_from_url "$EXTENSIONS_REPOSITORY_URL")"
if [ "$SKIP_HOSTNAME_VERIFICATION" = true ]
then
CURL_EXTRA_OPTS="$CURL_EXTRA_OPTS -k"
fi
fi
curl -f -s -L -I $CURL_EXTRA_OPTS "$REPOSITORY/$PUBLISHER/$BUILD_ARCH/$BUILD_OS/$EXTENSION_PACKAGE.tar" \
> "$REPOSITORY_PATH/$PUBLISHER/$BUILD_ARCH/$BUILD_OS/$EXTENSION_PACKAGE.headers.$TEMP"
CONTENT_LENGTH="$(grep -i 'Content-Length' "$REPOSITORY_PATH/$PUBLISHER/$BUILD_ARCH/$BUILD_OS/$EXTENSION_PACKAGE.headers.$TEMP")"
CONTENT_LENGTH="$(printf '%s' "$CONTENT_LENGTH" | tr -d '[:space:]' | cut -d ':' -f 2)"
if [ "$CONTENT_LENGTH" -ge 0 ]
then
apply_extension_cache_retention_policy "$CONTENT_LENGTH"
else
echo "Warning: Can not determine Content-Length for URL $REPOSITORY/$PUBLISHER/$BUILD_ARCH/$BUILD_OS/$EXTENSION_PACKAGE.tar"
fi
curl -f -s -L $CURL_EXTRA_OPTS "$REPOSITORY/$PUBLISHER/$BUILD_ARCH/$BUILD_OS/$EXTENSION_PACKAGE.tar" \
-o "$REPOSITORY_PATH/$PUBLISHER/$BUILD_ARCH/$BUILD_OS/$EXTENSION_PACKAGE.tar.tmp.$TEMP"
mv "$REPOSITORY_PATH/$PUBLISHER/$BUILD_ARCH/$BUILD_OS/$EXTENSION_PACKAGE.tar.tmp.$TEMP" \
"$REPOSITORY_PATH/$PUBLISHER/$BUILD_ARCH/$BUILD_OS/$EXTENSION_PACKAGE.tar"
else
echo " . Already downloaded from $REPOSITORY/$PUBLISHER/$BUILD_ARCH/$BUILD_OS/$EXTENSION_PACKAGE.tar"
fi
}
apply_extension_cache_retention_policy() {
[ "$1" -ge 0 ] && true || false
local REQUIRED_BYTES="$1"
local AVAILABLE_BYTES BLOCK_SIZE REQUIRED_BYTES_WITH_BLOCK_SIZE
AVAILABLE_BYTES="$(df -B 1 . | tail -n 1 | tr -s '[:space:]' ':' | cut -d : -f 4)"
BLOCK_SIZE="$(stat -fc '%s' .)"
REQUIRED_BYTES_WITH_BLOCK_SIZE="$((REQUIRED_BYTES + BLOCK_SIZE))"
if [ "$AVAILABLE_BYTES" -lt "$REQUIRED_BYTES_WITH_BLOCK_SIZE" ]
then
echo "Required $REQUIRED_BYTES_WITH_BLOCK_SIZE bytes but available $AVAILABLE_BYTES, removing files with oldest last access..."
while true
do
if ! ls -R -- * 2>&1 | grep ':$' | sed 's/:$//' \
| while read -r DIR
do
ls -1 "$DIR"
done \
| grep -q .
then
echo "Warning: Can not free more space on device!"
break
fi
ls -R -- * 2>&1 | grep ':$' | sed 's/:$//' \
| while read -r DIR
do
ls -1 "$DIR" \
| while read -r FILE
do
! test -f "$DIR/$FILE" || stat --format '%X:%n' "$DIR/$FILE"
done
done \
| sort -t : -k 1n | grep -v '\.json$' | head -n 1 | cut -d : -f 2 \
| while read -r FILE
do
echo "Removing $FILE of $(stat '%s' "$FILE")"
rm -f "$FILE"
done
AVAILABLE_BYTES="$(df -B 1 . | tail -n 1 | tr '[:space:]' ':' | cut -d : -f 4)"
if [ "$AVAILABLE_BYTES" -lt "$REQUIRED_BYTES_WITH_BLOCK_SIZE" ]
then
break
fi
done
echo "done"
echo
fi
}
add_extension_image_to_statefulset() {
[ -n "$1" ] && [ -n "$2" ] && [ -n "$3" ] && [ -n "$4" ] \
&& [ -n "$5" ] && [ -n "$6" ] && [ -n "$7" ] && [ -n "$8" ] \
&& [ -n "$9" ] && true || false
local EXTENSIONS_REPOSITORY_URL="$1"
local REPOSITORY="$2"
local PUBLISHER="$3"
local NAME="$4"
local VERSION="$5"
local POSTGRES_VERSION="$6"
local FLAVOR="$7"
local BUILD_ARCH="$8"
local BUILD_OS="$9"
local BUILD="$10"
local IMAGE_TEMPLATE COMPONENT COMPONENT_VERSION HASH IMAGE_NAME CONTAINER STATEFULSET
IMAGE_TEMPLATE="$(get_image_template_from_url "$EXTENSIONS_REPOSITORY_URL")"
COMPONENT="$(jq -r ".extensions[\"$NAME\"]
| .component" unwrapped-hashes.json)"
# shellcheck disable=SC2034
COMPONENT_VERSION="$(jq -r ".extensions[\"$NAME\"]
| .versions[] | select(.version == \"$VERSION\")
| .componentVersion | if . != null then . else \"\" end" unwrapped-hashes.json)"
if [ -z "$COMPONENT_VERSION" ]
then
# TODO: this is a mock that have to be fixed
# in the extensions repository by adding a
# .extensions[].versions[].componentVersion field
# in the hashes.json index
COMPONENT_VERSION="$VERSION"
case "$COMPONENT" in
(core|contrib)
COMPONENT_VERSION="$COMPONENT"
;;
(citus)
COMPONENT_VERSION="10.1.2"
;;
(healpix)
# shellcheck disable=SC2034
COMPONENT_VERSION="1.0"
;;
esac
fi
if [ -z "$COMPONENT_VERSION" ]
then
echo " ! Can not retrieve component version for extension $REPOSITORY $PUBLISHER $NAME $VERSION $FLAVOR$POSTGRES_VERSION $BUILD $BUILD_ARCH $BUILD_OS"
return 1
fi
# shellcheck disable=SC2034
HASH="$(jq -r ".extensions[\"$NAME\"]
| .versions[] | select(.version == \"$VERSION\")
| .availableFor[] | select(.postgresVersion == \"$POSTGRES_VERSION\"
and (.flavor == \"$FLAVOR\" or (.flavor == null and \"$FLAVOR\" == \"$DEFAULT_FLAVOR\"))
and (.build == \"$BUILD\" or (.build == null and \"$BUILD\" == \"\")))
| .buildHash" unwrapped-hashes.json)"
if [ -z "$HASH" ]
then
echo " ! Can not retrieve hash for extension $REPOSITORY $PUBLISHER $NAME $VERSION $FLAVOR$POSTGRES_VERSION $BUILD $BUILD_ARCH $BUILD_OS"
return 1
fi
# shellcheck disable=SC2034
POSTGRES_EXACT_VERSION="$(jq -r ".extensions[\"plpgsql\"]
| .versions[]
| .availableFor[] | select(.postgresVersion == \"$POSTGRES_VERSION\"
and (.flavor == \"$FLAVOR\" or (.flavor == null and \"$FLAVOR\" == \"$DEFAULT_FLAVOR\"))
and (.build == \"$BUILD\" or (.build == null and \"$BUILD\" == \"\")))
| .postgresVersion" unwrapped-hashes.json)"
if [ -z "$POSTGRES_EXACT_VERSION" ]
then
# TODO: this is a mock that have to be fixed
# in the extensions repository by adding a
# .extensions[].versions[].availableFor[].postgresExactVersion field
# in the hashes.json index
POSTGRES_EXACT_VERSION="$POSTGRES_VERSION"
case "$POSTGRES_VERSION" in
(11)
POSTGRES_EXACT_VERSION="11.13"
;;
(12)
POSTGRES_EXACT_VERSION="12.8"
;;
(13)
# shellcheck disable=SC2034
POSTGRES_EXACT_VERSION="13.4"
;;
esac
fi
if [ -z "$POSTGRES_EXACT_VERSION" ]
then
echo " ! Can not retrieve postgres exact version for extension $REPOSITORY $PUBLISHER $NAME $VERSION $FLAVOR$POSTGRES_VERSION $BUILD $BUILD_ARCH $BUILD_OS"
return 1
fi
IMAGE_NAME="$(eval "echo \"$IMAGE_TEMPLATE\"")"
if jq '.spec.template.spec.containers|any(.image == "'"$IMAGE_NAME"'")' "$STATEFULSET_JSON_FILE" | grep -q false
then
echo " + Add extension image $IMAGE_NAME"
CONTAINER="$(get_extension_container_as_yaml "$IMAGE_NAME" "$REPOSITORY" "$PUBLISHER" "$BUILD_ARCH" "$BUILD_OS")"
(
[ "$EXTENSIONS_CACHE_LOG_LEVEL" = TRACE ] || set +x
STATEFULSET="$(jq ".spec.template.spec.containers = .spec.template.spec.containers + [$CONTAINER]" "$STATEFULSET_JSON_FILE")"
printf '%s' "$STATEFULSET" > "$STATEFULSET_JSON_FILE"
)
else
echo " . Already added image $IMAGE_NAME"
fi
}
get_extension_container_as_yaml() {
[ -n "$1" ] && [ -n "$2" ] && [ -n "$3" ] && [ -n "$4" ] \
&& [ -n "$5" ] && true || false
local IMAGE_NAME="$1"
local REPOSITORY="$2"
local PUBLISHER="$3"
local BUILD_ARCH="$4"
local BUILD_OS="$5"
local REPOSITORY_PATH="${REPOSITORY#*://}"
cat << EOF
{
name: "extension-$(jq -r '(.spec.template.spec.containers | length) - 2' "$STATEFULSET_JSON_FILE")",
image: "$IMAGE_NAME",
env: [{
name: "EXTENSIONS_CACHE_LOG_LEVEL",
value: "$EXTENSIONS_CACHE_LOG_LEVEL"
}],
command: [ "sh", "-ec", $(cat << INNER_EOF | jq -sR .
cd /opt/app-root/src
sh /usr/local/bin/extensions-cache-conciliator.sh provide '$REPOSITORY_PATH' '$PUBLISHER' '$BUILD_ARCH' '$BUILD_OS'
INNER_EOF
) ],
volumeMounts: [{
name: "extensions-cache-config",
mountPath: "/usr/local/bin/extensions-cache-conciliator.sh",
subPath: "extensions-cache-conciliator.sh",
readOnly: true
}, {
name: "$PERSISTENTVOLUMECLAIM_NAME",
subPath: "repository",
mountPath: "/opt/app-root/src",
readOnly: false
}]
}
EOF
}
provide() {
[ -n "$1" ] && [ -n "$2" ] && [ -n "$3" ] && [ -n "$4" ] \
&& true || false
local REPOSITORY_PATH="$1"
local PUBLISHER="$2"
local BUILD_ARCH="$3"
local BUILD_OS="$4"
# TODO: This code have to be refactored when generated images will have real realease
# packages without -dev. This could be achieved by adding an aditional step to the
# release process where the packages are extracted from the packaged images and
# re-packaged in a new tick release packaged image.
mkdir -p "/opt/app-root/src/$REPOSITORY_PATH/$PUBLISHER/$BUILD_ARCH/$BUILD_OS"
for BASE_EXTENSION_TAR in "/var/lib/postgresql/extensions/$PUBLISHER/$BUILD_ARCH/$BUILD_OS/"*.tar
do
BASE_EXTENSION_TAR_NAME="${BASE_EXTENSION_TAR##*/}"
for EXTENSION_TAR in "$BASE_EXTENSION_TAR" "${BASE_EXTENSION_TAR%-dev.tar}.tar"
do
EXTENSION_TAR_NAME="${EXTENSION_TAR##*/}"
if [ "${BASE_EXTENSION_TAR_NAME%-dev.tar}.tar" = "$EXTENSION_TAR_NAME" ]
then
if [ "$BASE_EXTENSION_TAR_NAME" = "${BASE_EXTENSION_TAR_NAME%-dev.tar}.tar" ]
then
continue
fi
if ! test -f "$EXTENSION_TAR"
then
rm -f "${EXTENSION_TAR%.*}.sha256" "${EXTENSION_TAR%.*}.tgz"
tar xCf "${BASE_EXTENSION_TAR%/*}" "$BASE_EXTENSION_TAR"
mv "${BASE_EXTENSION_TAR%.*}".sha256 "${EXTENSION_TAR%.*}".sha256
mv "${BASE_EXTENSION_TAR%.*}".tgz "${EXTENSION_TAR%.*}".tgz
tar cCf "${BASE_EXTENSION_TAR%/*}" "$EXTENSION_TAR" \
"${EXTENSION_TAR_NAME%.*}.sha256" "${EXTENSION_TAR_NAME%.*}.tgz"
fi
rm -f "${EXTENSION_TAR%.*}.sha256" "${EXTENSION_TAR%.*}.tgz"
fi
rm -f "/opt/app-root/src/$REPOSITORY_PATH/$PUBLISHER/$BUILD_ARCH/$BUILD_OS/$EXTENSION_TAR_NAME.tmp"
ln -s "/proc/$$/root/$EXTENSION_TAR" \
"/opt/app-root/src/$REPOSITORY_PATH/$PUBLISHER/$BUILD_ARCH/$BUILD_OS/$EXTENSION_TAR_NAME.tmp"
mv "/opt/app-root/src/$REPOSITORY_PATH/$PUBLISHER/$BUILD_ARCH/$BUILD_OS/$EXTENSION_TAR_NAME.tmp" \
"/opt/app-root/src/$REPOSITORY_PATH/$PUBLISHER/$BUILD_ARCH/$BUILD_OS/$EXTENSION_TAR_NAME"
done
done
while true
do
sleep 300
done
}
urlencode() {
sed 's/\(.\)/\1\n/g' \
| {
[ "$EXTENSIONS_CACHE_LOG_LEVEL" = TRACE ] || set +x
NEWLINE="$(printf '\n')"
while IFS="$NEWLINE" read -r C
do
case "$C" in
[-_.~a-zA-Z0-9]) printf %c "$C" ;;
"") printf %%0A ;;
*) printf %%%02X "'$C'" ;;
esac
done
}
}
urldecode() {
sed 's/\(.\)/\1\n/g' \
| {
[ "$EXTENSIONS_CACHE_LOG_LEVEL" = TRACE ] || set +x
NEWLINE="$(printf '\n')"
CODE=
while IFS="$NEWLINE" read -r C
do
case "$C" in
\+)
if [ -n "$CODE" ]
then
>&2 echo "Wrong code $CODE$C"
exit 1
fi
printf ' '
;;
%)
if [ -n "$CODE" ]
then
>&2 echo "Wrong code $CODE$C"
exit 1
fi
CODE='0x'
;;
*)
if [ -z "$CODE" ]
then
printf %c "$C"
else
CODE="$CODE$C"
if [ -z "${CODE#0x??}" ]
then
# shellcheck disable=SC2059
printf "$(printf '\\%03o' "$CODE")"
CODE=
fi
fi
;;
esac
done
}
}
try_function() {
local E_UNSET=true
if echo "$-" | grep -q e
then
E_UNSET=false
fi
"$E_UNSET" || set +e
(set -e; "$@")
EXIT_CODE="$?"
"$E_UNSET" || set -e
RESULT=false
if [ "$EXIT_CODE" = 0 ]
then
RESULT=true
fi
}
if [ -n "$1" ]
then
"$@"
fi

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,58 @@
Release Name: {{ .Release.Name }}
StackGres Version: {{ .Chart.Version }}
_____ _ _ _____
/ ____| | | | / ____|
| (___ | |_ __ _ ___| | _| | __ _ __ ___ ___
\___ \| __/ _` |/ __| |/ / | |_ | '__/ _ \/ __|
____) | || (_| | (__| <| |__| | | | __/\__ \
|_____/ \__\__,_|\___|_|\_\\_____|_| \___||___/
by OnGres, Inc.
{{- if not .Values.cert.autoapprove }}
To complete the process approve operator certificate signing request:
kubectl certificate approve {{ .Release.Name }}
{{- end }}
Check if the operator was successfully deployed and is available:
kubectl describe deployment -n {{ .Release.Namespace }} {{ .Release.Name }}
kubectl wait -n {{ .Release.Namespace }} deployment/{{ .Release.Name }} --for condition=Available
Check if the restapi was successfully deployed and is available:
kubectl describe deployment -n {{ .Release.Namespace }} {{ .Values.restapi.name }}
kubectl wait -n {{ .Release.Namespace }} deployment/{{ .Values.restapi.name }} --for condition=Available
{{- if .Values.deploy.restapi }}
To access StackGres Operator UI from localhost, run the below commands:
POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "stackgres.io/restapi=true" -o jsonpath="{.items[0].metadata.name}")
kubectl port-forward "$POD_NAME" 8443:9443 --namespace {{ .Release.Namespace }}
Read more about port forwarding here: http://kubernetes.io/docs/user-guide/kubectl/kubectl_port-forward/
Now you can access the StackGres Operator UI on:
https://localhost:8443
{{- if (eq .Values.authentication.type "jwt") }}
To get the username, run the command:
kubectl get secret -n {{ .Release.Namespace }} stackgres-restapi-admin --template '{{ "{{" }} printf "username = %s\n" (.data.k8sUsername | base64decode) {{ "}}" }}'
{{- if and (not .Values.authentication.password) (not (.Values.authentication.secretRef).name) }}
To get the generated password, run the command:
kubectl get secret -n {{ .Release.Namespace }} stackgres-restapi-admin --template '{{ "{{" }} printf "password = %s\n" (.data.clearPassword | base64decode) {{ "}}" }}'
Remember to remove the generated password hint from the secret to avoid security flaws:
kubectl patch secret --namespace {{ .Release.Namespace }} stackgres-restapi-admin --type json -p '[{"op":"remove","path":"/data/clearPassword"}]'
{{- end }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,65 @@
{{- define "kubectl.image" }}
{{- if semverCompare ">=1.27" .Capabilities.KubeVersion.Version -}}
{{- printf "%s/ongres/kubectl:v1.28.8-build-6.31" .Values.containerRegistry -}}
{{- else if semverCompare ">=1.24" .Capabilities.KubeVersion.Version -}}
{{- printf "%s/ongres/kubectl:v1.25.16-build-6.31" .Values.containerRegistry -}}
{{- else if semverCompare ">=1.21" .Capabilities.KubeVersion.Version -}}
{{- printf "%s/ongres/kubectl:v1.22.17-build-6.31" .Values.containerRegistry -}}
{{- else if semverCompare ">=1.18" .Capabilities.KubeVersion.Version -}}
{{- printf "%s/ongres/kubectl:v1.19.16-build-6.31" .Values.containerRegistry -}}
{{- else -}}
{{- printf "%s/ongres/kubectl:v1.28.8-build-6.31" .Values.containerRegistry -}}
{{- end -}}
{{- end -}}
{{- define "operator-image" }}
{{- if not (regexMatch "^[^/]+\\.[^/]+/.*$" .Values.operator.image.name) }}{{ .Values.containerRegistry }}/{{ end }}{{ .Values.operator.image.name }}:{{ .Values.operator.image.tag }}
{{- end }}
{{- define "restapi-image" }}
{{- if not (regexMatch "^[^/]+\\.[^/]+/.*$" .Values.restapi.image.name ) }}{{ .Values.containerRegistry }}/{{ end }}{{ .Values.restapi.image.name }}:{{ .Values.restapi.image.tag }}
{{- end }}
{{- define "adminui-image" }}
{{- if not (regexMatch "^[^/]+\\.[^/]+/.*$" .Values.adminui.image.name ) }}{{ .Values.containerRegistry }}/{{ end }}{{ .Values.adminui.image.name }}:{{ .Values.adminui.image.tag }}
{{- end }}
{{- define "jobs-image" }}
{{- if not (regexMatch "^[^/]+\\.[^/]+/.*$" .Values.jobs.image.name ) }}{{ .Values.containerRegistry }}/{{ end }}{{ .Values.jobs.image.name }}:{{ .Values.jobs.image.tag }}
{{- end }}
{{- define "cert-name" }}
{{- .Values.cert.secretName | default (printf "%s-%s" .Release.Name "certs") }}
{{- end }}
{{- define "web-cert-name" }}
{{- .Values.cert.webSecretName | default (printf "%s-%s" .Release.Name "web-certs") }}
{{- end }}
{{- define "stackgres.operator.missingSGConfigCrd" }}
{{- if .Release.IsUpgrade }}
{{- $missingSGConfigCrd := true }}
{{- $configCrd := lookup "apiextensions.k8s.io/v1" "CustomResourceDefinition" "" "sgconfigs.stackgres.io" }}
{{- if $configCrd }}
{{- $missingSGConfigCrd = false }}
{{- end }}
{{- if $missingSGConfigCrd }}true{{- else }}false{{- end }}
{{- else }}
false
{{- end }}
{{- end }}
{{- define "stackgres.operator.unmodificableWebapiAdminClusterRoleBinding" }}
{{- if .Release.IsUpgrade }}
{{- $unmodificableWebapiAdminClusterRoleBinding := false }}
{{- $webapiAdminClusterRoleBinding := lookup "rbac.authorization.k8s.io/v1" "ClusterRoleBinding" "" "stackgres-restapi-admin" }}
{{- if $webapiAdminClusterRoleBinding }}
{{- if not (eq $webapiAdminClusterRoleBinding.roleRef.name "stackgres-restapi-admin") }}
{{- $unmodificableWebapiAdminClusterRoleBinding = true }}
{{- end }}
{{- end }}
{{- if $unmodificableWebapiAdminClusterRoleBinding }}true{{- else }}false{{- end }}
{{- else }}
false
{{- end }}
{{- end }}

View File

@ -0,0 +1,12 @@
{{ if and .Release.IsInstall .Values.deploy.operator }}
{{ $deployments := lookup "apps/v1" "Deployment" "" "" }}
{{ range $deployments.items }}
{{ if .metadata.labels }}
{{ if .metadata.labels.group }}
{{ if eq .metadata.labels.group "stackgres.io" }}
{{ fail (print "StackGres Operator Helm Chart can only install one operator instance. Multiple operator instances is not supported.") }}
{{ end }}
{{ end }}
{{ end }}
{{ end }}
{{ end }}

View File

@ -0,0 +1,34 @@
{{ if .Release.IsUpgrade }}
{{ $chart := .Chart }}
{{ $crd := lookup "apiextensions.k8s.io/v1" "CustomResourceDefinition" "" "sgclusters.stackgres.io" }}
{{ if $crd }}
{{ $deployment := lookup "apps/v1" "Deployment" .Release.Namespace .Release.Name }}
{{ if $deployment }}
{{ if $deployment.metadata.labels }}
{{ if $deployment.metadata.labels.version }}
{{ $version := $deployment.metadata.labels.version }}
{{ if not .Values.forceUpgradeFromUnsupportedVersion }}
{{ if or (not (regexMatch "^(1\\.8\\.|1\\.9\\.|1\\.10\\.)" $version)) (and (not (eq $version $chart.Version)) (regexMatch "(-alpha[0-9]|-beta[0-9])" $version)) }}
{{ fail (print "Upgrading from version " $version " version is not supported. You may force upgrading from an unsupported version setting the parameter \"forceUpgradeFromUnsupportedVersion\" to \"true\". If you do so do it at your own risk. It has not been tested and some functionality may break. We recommend to perform security upgrades all your SGCluster as soon as possible after upgrading from an unsupported version of the operator") }}
{{ end }}
{{ end }}
{{ end }}
{{ end }}
{{ end }}
{{ $clusters := lookup "stackgres.io/v1" "SGCluster" "" "" }}
{{ if $clusters }}
{{ if $clusters.items }}
{{ range $cluster := $clusters.items }}
{{ if $cluster.metadata.annotations }}
{{ if (index $cluster.metadata.annotations "stackgres.io/operatorVersion") }}
{{ $version := (index $cluster.metadata.annotations "stackgres.io/operatorVersion") }}
{{ if (not (regexMatch "^(1\\.8\\.|1\\.9\\.|1\\.10\\.)" $version)) }}
{{ fail (print "Can not upgrade due to some SGCluster still at version " $version ". You have to run a SGDbOps of type securityUpgrade on those SGClusters first.") }}
{{ end }}
{{ end }}
{{ end }}
{{ end }}
{{ end }}
{{ end }}
{{ end }}
{{ end }}

View File

@ -0,0 +1,40 @@
{{- if .Values.cert.certManager.autoConfigure }}
---
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: "{{ .Release.Name }}-self-signed-issuer"
namespace: "{{ .Release.Namespace }}"
spec:
selfSigned: {}
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: "{{ .Release.Name }}-certs"
namespace: "{{ .Release.Namespace }}"
spec:
secretName: "{{ include "cert-name" . }}"
duration: "{{ .Values.cert.certManager.duration }}"
renewBefore: "{{ .Values.cert.certManager.renewBefore }}"
subject:
organizations:
- OnGres
isCA: true
privateKey:
algorithm: RSA
encoding: "{{ .Values.cert.certManager.encoding }}"
size: {{ .Values.cert.certManager.size }}
usages:
- server auth
- client auth
dnsNames:
- {{ .Release.Name }}
- {{ .Release.Name }}.{{ .Release.Namespace }}
- {{ .Release.Name }}.{{ .Release.Namespace }}.svc
- {{ .Release.Name }}.{{ .Release.Namespace }}.svc.cluster.local
issuerRef:
name: "{{ .Release.Name }}-self-signed-issuer"
kind: Issuer
group: cert-manager.io
{{ end }}

View File

@ -0,0 +1,46 @@
{{- if .Values.extensions.cache.enabled }}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-extensions-cache
namespace: {{ .Release.Namespace }}
{{- if .Values.qutePreprocess }}#comment.preprocess.start{{- end }}
data:
nginx.conf: |
pid /var/run/nginx.pid;
error_log /dev/stdout;
error_log /var/log/nginx/error.log;
events{
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /dev/stdout main;
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
include /etc/nginx/conf.d/*.conf;
}
stackgres-operator-extensions-cache.conf: |
server {
server_name localhost;
listen 8080;
root /opt/app-root/src;
location / {
try_files /$host$uri =404;
}
}
extensions-cache-conciliator.sh: |
{{ .Files.Get "extensions-cache-conciliator.sh" | indent 4 }}
{{- if .Values.qutePreprocess }}#comment.preprocess.end{{- end }}
{{- end }}

View File

@ -0,0 +1,102 @@
{{- if .Values.extensions.cache.enabled }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ .Release.Name }}-extensions-cache
namespace: {{ .Release.Namespace }}
annotations:
meta.helm.sh/release-name: {{ .Release.Name }}
meta.helm.sh/release-namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/managed-by: Helm
{{- if .Values.serviceAccount.repoCredentials }}
imagePullSecrets:
{{- range .Values.serviceAccount.repoCredentials }}
- name: {{ . }}
{{- end }}
{{- end }}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: {{ .Release.Name }}-extensions-cache
annotations:
meta.helm.sh/release-name: {{ .Release.Name }}
meta.helm.sh/release-namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/managed-by: Helm
rules:
- apiGroups: ["stackgres.io"]
resources:
- sgclusters
- sgdistributedlogs
verbs:
- list
- get
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: {{ .Release.Name }}-extensions-cache
annotations:
meta.helm.sh/release-name: {{ .Release.Name }}
meta.helm.sh/release-namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/managed-by: Helm
subjects:
- kind: ServiceAccount
name: {{ .Release.Name }}-extensions-cache
namespace: {{ .Release.Namespace }}
roleRef:
kind: ClusterRole
name: {{ .Release.Name }}-extensions-cache
apiGroup: rbac.authorization.k8s.io
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: {{ .Release.Namespace }}
name: {{ .Release.Name }}-extensions-cache
annotations:
meta.helm.sh/release-name: {{ .Release.Name }}
meta.helm.sh/release-namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/managed-by: Helm
rules:
- apiGroups: ["", "apps"]
resources:
- serviceaccounts
- statefulsets
verbs:
- get
- patch
- update
resourceNames:
- {{ .Release.Name }}-extensions-cache
- apiGroups: [""]
resources:
- pods
verbs:
- delete
resourceNames:
- {{ .Release.Name }}-extensions-cache-0
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
namespace: {{ .Release.Namespace }}
name: {{ .Release.Name }}-extensions-cache
annotations:
meta.helm.sh/release-name: {{ .Release.Name }}
meta.helm.sh/release-namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/managed-by: Helm
subjects:
- kind: ServiceAccount
name: {{ .Release.Name }}-extensions-cache
namespace: {{ .Release.Namespace }}
roleRef:
kind: Role
name: {{ .Release.Name }}-extensions-cache
apiGroup: rbac.authorization.k8s.io
{{- end }}

View File

@ -0,0 +1,21 @@
{{- if .Values.extensions.cache.enabled }}
apiVersion: v1
kind: Service
metadata:
namespace: {{ .Release.Namespace }}
name: {{ .Release.Name }}-extensions-cache
annotations:
meta.helm.sh/release-name: {{ .Release.Name }}
meta.helm.sh/release-namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/managed-by: Helm
spec:
type: ClusterIP
selector:
app: {{ .Release.Name }}-extensions-cache
ports:
- name: http
protocol: TCP
port: 80
targetPort: http
{{- end }}

View File

@ -0,0 +1,201 @@
{{- if .Values.extensions.cache.enabled }}
apiVersion: "apps/v1"
kind: "StatefulSet"
metadata:
annotations:
meta.helm.sh/release-name: {{ .Release.Name }}
meta.helm.sh/release-namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/managed-by: Helm
app: {{ .Release.Name }}-extensions-cache
version: "{{ .Chart.Version }}"
group: stackgres.io
name: {{ .Release.Name }}-extensions-cache
namespace: {{ .Release.Namespace }}
spec:
replicas: 1
selector:
matchLabels:
app: {{ .Release.Name }}-extensions-cache
group: stackgres.io
serviceName: {{ .Release.Name }}-extensions-cache
template:
metadata:
labels:
app: {{ .Release.Name }}-extensions-cache
group: stackgres.io
spec:
securityContext:
{{- if or (not (.Capabilities.APIVersions.Has "project.openshift.io/v1")) .Values.developer.disableArbitraryUser }}
fsGroup: 1000
{{- end }}
serviceAccountName: {{ .Release.Name }}-extensions-cache
shareProcessNamespace: true
terminationGracePeriodSeconds: 0
restartPolicy: Always
containers:
- name: http
image: "registry.access.redhat.com/ubi8/nginx-120:1-92.1679484498"
imagePullPolicy: {{ .Values.imagePullPolicy }}
securityContext:
{{- if and (or (not (.Capabilities.APIVersions.Has "project.openshift.io/v1")) .Values.developer.disableArbitraryUser) (not .Values.extensions.cache.hostPath) }}
runAsNonRoot: true
runAsUser: 998
runAsGroup: 1000
{{- end }}
{{- if .Values.extensions.cache.hostPath }}
runAsUser: 0
{{- end }}
args:
- '/bin/sh'
- '-ec'
{{- if .Values.developer.showDebug }}
- '-x'
{{- end }}
- |
mkdir -p /var/lib/nginx/tmp
exec nginx -g 'daemon off;'
ports:
- containerPort: 8080
name: "http"
protocol: "TCP"
readinessProbe:
tcpSocket:
port: 8080
volumeMounts:
- name: extensions-cache-config
mountPath: /etc/nginx/nginx.conf
subPath: nginx.conf
readOnly: true
- name: extensions-cache-config
mountPath: /etc/nginx/conf.d/stackgres-operator-extensions-cache.conf
subPath: stackgres-operator-extensions-cache.conf
readOnly: true
- name: extensions-cache-nginx-var
subPath: var/cache/nginx
mountPath: /var/cache/nginx
readOnly: false
- name: extensions-cache-nginx-var
subPath: var/run
mountPath: /var/run
readOnly: false
- name: extensions-cache-nginx-var
subPath: var/lib/nginx
mountPath: /var/lib/nginx
readOnly: false
- name: extensions-cache-nginx-var
subPath: var/log/nginx
mountPath: /var/log/nginx
readOnly: false
- name: {{ .Release.Name }}-extensions-cache
subPath: repository
mountPath: /opt/app-root/src
readOnly: true
- name: "controller"
image: {{ template "kubectl.image" . }}
imagePullPolicy: {{ .Values.imagePullPolicy }}
securityContext:
{{- if and (or (not (.Capabilities.APIVersions.Has "project.openshift.io/v1")) .Values.developer.disableArbitraryUser) (not .Values.extensions.cache.hostPath) }}
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
{{- end }}
{{- if .Values.extensions.cache.hostPath }}
runAsUser: 0
{{- end }}
env:
- name: HOME
value: /tmp
- name: EXTENSIONS_REPOSITORY_URLS
value: "{{ range $index, $element := .Values.extensions.repositoryUrls }}{{ if $index }},{{ end }}{{ $element }}{{ end }}"
- name: OPERATOR_NAMESPACE
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.namespace
{{- if .Values.developer.logLevel }}
- name: EXTENSIONS_CACHE_LOG_LEVEL
value: "{{ .Values.developer.logLevel }}"
{{- end }}
{{- range .Values.developer.extraOpts }}
{{- if . | hasPrefix "-Dquarkus.log.category.\"stackgres-extensions-cache\".level=" }}
- name: EXTENSIONS_CACHE_LOG_LEVEL
value: "{{ . | trimPrefix "-Dquarkus.log.category.\"stackgres-extensions-cache\".level=" }}"
{{- end }}
{{- end }}
{{- if .Values.extensions.cache.preloadedExtensions }}
- name: EXTENSIONS_CACHE_PRELOADED_EXTENSIONS
value: {{ .Values.extensions.cache.preloadedExtensions | toJson | squote }}
{{- end }}
command:
- "/bin/bash"
- "-ec"
- |
echo "$EXTENSIONS_CACHE_LOG_LEVEL" | grep -v -q '^\(DEBUG\|TRACE\)$' || set -x
cd /opt/app-root/src
sh /usr/local/bin/extensions-cache-conciliator.sh run "$OPERATOR_NAMESPACE" '{{ .Release.Name }}-extensions-cache'
readinessProbe:
exec:
command:
- test
- -f
- /tmp/extensions-cache-ready
volumeMounts:
- name: extensions-cache-config
mountPath: /usr/local/bin/extensions-cache-conciliator.sh
subPath: extensions-cache-conciliator.sh
readOnly: true
- name: {{ .Release.Name }}-extensions-cache
subPath: repository
mountPath: /opt/app-root/src
readOnly: false
- name: extensions-cache-nginx-var
subPath: var/log/nginx
mountPath: /var/log/nginx
readOnly: true
volumes:
{{- if .Values.extensions.cache.hostPath }}
- name: {{ .Release.Name }}-extensions-cache
hostPath:
path: "{{ .Values.extensions.cache.hostPath }}"
type: DirectoryOrCreate
{{- end }}
- name: extensions-cache-config
configMap:
name: {{ .Release.Name }}-extensions-cache
optional: false
items:
- key: nginx.conf
path: nginx.conf
- key: stackgres-operator-extensions-cache.conf
path: stackgres-operator-extensions-cache.conf
- key: extensions-cache-conciliator.sh
path: extensions-cache-conciliator.sh
- name: extensions-cache-nginx-var
emptyDir: {}
{{- if not .Values.extensions.cache.hostPath }}
volumeClaimTemplates:
- metadata:
annotations:
meta.helm.sh/release-name: {{ .Release.Name }}
meta.helm.sh/release-namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/managed-by: Helm
app: {{ .Release.Name }}-extensions-cache
version: "{{ .Chart.Version }}"
group: stackgres.io
name: {{ .Release.Name }}-extensions-cache
spec:
accessModes: [ "ReadWriteOnce" ]
{{- if .Values.extensions.cache.persistentVolume.storageClass }}
{{- if eq "-" .Values.extensions.cache.persistentVolume.storageClass }}
storageClassName: ""
{{- else }}
storageClassName: "{{ .Values.extensions.cache.persistentVolume.storageClass }}"
{{- end }}
{{- end }}
resources:
requests:
storage: "{{ .Values.extensions.cache.persistentVolume.size }}"
{{- end }}
{{- end }}

View File

@ -0,0 +1,116 @@
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ .Release.Name }}-init
namespace: {{ .Release.Namespace }}
annotations:
"helm.sh/hook": pre-install,pre-upgrade
"helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
"helm.sh/hook-weight": "-100"
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
annotations:
"helm.sh/hook": pre-install,pre-upgrade
"helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
"helm.sh/hook-weight": "-100"
name: {{ .Release.Name }}-init
rules:
- apiGroups: ["apiextensions.k8s.io"]
resources:
- customresourcedefinitions
- clusterrolebinding
verbs:
- create
- apiGroups: ["apiextensions.k8s.io"]
resources:
- customresourcedefinitions
resourceNames:
- sgconfigs.stackgres.io
verbs:
- get
- apiGroups: ["apiextensions.k8s.io"]
resources:
- customresourcedefinitions
resourceNames:
- sgconfigs.stackgres.io
verbs:
- get
- apiGroups: ["rbac.authorization.k8s.io"]
resources:
- clusterrolebindings
resourceNames:
- stackgres-restapi-admin
verbs:
- get
- delete
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
{{- with .Values.clusterOwnerRefereces }}
ownerReferences:
{{- toYaml . | nindent 4 }}
{{- end }}
name: {{ .Release.Name }}-init
annotations:
"helm.sh/hook": pre-install,pre-upgrade
"helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
"helm.sh/hook-weight": "-100"
subjects:
- kind: ServiceAccount
name: {{ .Release.Name }}-init
namespace: {{ .Release.Namespace }}
roleRef:
kind: ClusterRole
name: {{ .Release.Name }}-init
apiGroup: rbac.authorization.k8s.io
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
annotations:
"helm.sh/hook": pre-install,pre-upgrade
"helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
"helm.sh/hook-weight": "-100"
name: {{ .Release.Name }}-init
namespace: {{ .Release.Namespace }}
rules:
- apiGroups: ["stackgres.io"]
resources:
- sgconfigs
verbs:
- create
- apiGroups: ["stackgres.io"]
resources:
- sgconfigs
resourceNames:
- {{ .Release.Name }}
verbs:
- get
- update
- patch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
{{- with .Values.clusterOwnerRefereces }}
ownerReferences:
{{- toYaml . | nindent 4 }}
{{- end }}
name: {{ .Release.Name }}-init
namespace: {{ .Release.Namespace }}
annotations:
"helm.sh/hook": pre-install,pre-upgrade
"helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
"helm.sh/hook-weight": "-100"
subjects:
- kind: ServiceAccount
name: {{ .Release.Name }}-init
namespace: {{ .Release.Namespace }}
roleRef:
kind: Role
name: {{ .Release.Name }}-init
apiGroup: rbac.authorization.k8s.io

View File

@ -0,0 +1,217 @@
{{- $cert := "Cg==" }}
{{- $certSecret := lookup "v1" "Secret" .Release.Namespace (include "cert-name" .) }}
{{- if $certSecret }}
{{- if (index $certSecret.data "tls.crt") }}
{{- $cert = (index $certSecret.data "tls.crt") }}
{{- end }}
{{- end }}
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
{{- with .Values.clusterOwnerRefereces }}
ownerReferences:
{{- toYaml . | nindent 4 }}
{{- end }}
name: {{ .Release.Name }}
namespace: {{ .Release.Namespace }}
annotations:
meta.helm.sh/release-name: {{ .Release.Name }}
meta.helm.sh/release-namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/managed-by: Helm
webhooks:
- name: sgcluster.mutating-webhook.stackgres.io
sideEffects: None
rules:
- operations: ["CREATE", "UPDATE"]
apiGroups: ["stackgres.io"]
apiVersions: ["*"]
resources: ["sgclusters"]
failurePolicy: Fail
clientConfig:
service:
namespace: {{ .Release.Namespace }}
name: {{ .Release.Name }}
path: '/stackgres/mutation/sgcluster'
caBundle: {{ $cert }}
admissionReviewVersions: ["v1"]
- name: sgpgconfig.mutating-webhook.stackgres.io
sideEffects: None
rules:
- operations: ["CREATE", "UPDATE"]
apiGroups: ["stackgres.io"]
apiVersions: ["*"]
resources: ["sgpgconfigs"]
failurePolicy: Fail
clientConfig:
service:
namespace: {{ .Release.Namespace }}
name: {{ .Release.Name }}
path: '/stackgres/mutation/sgpgconfig'
caBundle: {{ $cert }}
admissionReviewVersions: ["v1"]
- name: sgpoolconfig.mutating-webhook.stackgres.io
sideEffects: None
rules:
- operations: ["CREATE", "UPDATE"]
apiGroups: ["stackgres.io"]
apiVersions: ["*"]
resources: ["sgpoolconfigs"]
failurePolicy: Fail
clientConfig:
service:
namespace: {{ .Release.Namespace }}
name: {{ .Release.Name }}
path: '/stackgres/mutation/sgpoolconfig'
caBundle: {{ $cert }}
admissionReviewVersions: ["v1"]
- name: sginstanceprofile.mutating-webhook.stackgres.io
sideEffects: None
rules:
- operations: ["CREATE", "UPDATE"]
apiGroups: ["stackgres.io"]
apiVersions: ["*"]
resources: ["sginstanceprofiles"]
failurePolicy: Fail
clientConfig:
service:
namespace: {{ .Release.Namespace }}
name: {{ .Release.Name }}
path: '/stackgres/mutation/sginstanceprofile'
caBundle: {{ $cert }}
admissionReviewVersions: ["v1"]
- name: sgbackupconfig.mutating-webhook.stackgres.io
sideEffects: None
rules:
- operations: ["CREATE", "UPDATE"]
apiGroups: ["stackgres.io"]
apiVersions: ["*"]
resources: ["sgbackupconfigs"]
failurePolicy: Fail
clientConfig:
service:
namespace: {{ .Release.Namespace }}
name: {{ .Release.Name }}
path: '/stackgres/mutation/sgbackupconfig'
caBundle: {{ $cert }}
admissionReviewVersions: ["v1"]
- name: sgbackup.mutating-webhook.stackgres.io
sideEffects: None
rules:
- operations: ["CREATE", "UPDATE"]
apiGroups: ["stackgres.io"]
apiVersions: ["*"]
resources: ["sgbackups"]
failurePolicy: Fail
clientConfig:
service:
namespace: {{ .Release.Namespace }}
name: {{ .Release.Name }}
path: '/stackgres/mutation/sgbackup'
caBundle: {{ $cert }}
admissionReviewVersions: ["v1"]
- name: sgdistributedlogs.mutating-webhook.stackgres.io
sideEffects: None
rules:
- operations: ["CREATE", "UPDATE"]
apiGroups: ["stackgres.io"]
apiVersions: ["*"]
resources: ["sgdistributedlogs"]
failurePolicy: Fail
clientConfig:
service:
namespace: {{ .Release.Namespace }}
name: {{ .Release.Name }}
path: '/stackgres/mutation/sgdistributedlogs'
caBundle: {{ $cert }}
admissionReviewVersions: ["v1"]
- name: sgdbops.mutating-webhook.stackgres.io
sideEffects: None
rules:
- operations: ["CREATE", "UPDATE"]
apiGroups: ["stackgres.io"]
apiVersions: ["*"]
resources: ["sgdbops"]
failurePolicy: Fail
clientConfig:
service:
namespace: {{ .Release.Namespace }}
name: {{ .Release.Name }}
path: '/stackgres/mutation/sgdbops'
caBundle: {{ $cert }}
admissionReviewVersions: ["v1"]
- name: sgobjectstorage.mutating-webhook.stackgres.io
sideEffects: None
rules:
- operations: ["CREATE", "UPDATE"]
apiGroups: ["stackgres.io"]
apiVersions: ["*"]
resources: ["sgobjectstorages"]
failurePolicy: Fail
clientConfig:
service:
namespace: {{ .Release.Namespace }}
name: {{ .Release.Name }}
path: '/stackgres/mutation/sgobjectstorage'
caBundle: {{ $cert }}
admissionReviewVersions: ["v1"]
- name: sgscripts.mutating-webhook.stackgres.io
sideEffects: None
rules:
- operations: ["CREATE", "UPDATE"]
apiGroups: ["stackgres.io"]
apiVersions: ["*"]
resources: ["sgscripts"]
failurePolicy: Fail
clientConfig:
service:
namespace: {{ .Release.Namespace }}
name: {{ .Release.Name }}
path: '/stackgres/mutation/sgscript'
caBundle: {{ $cert }}
admissionReviewVersions: ["v1"]
- name: sgshardedclusters.mutating-webhook.stackgres.io
sideEffects: None
rules:
- operations: ["CREATE", "UPDATE"]
apiGroups: ["stackgres.io"]
apiVersions: ["*"]
resources: ["sgshardedclusters"]
failurePolicy: Fail
clientConfig:
service:
namespace: {{ .Release.Namespace }}
name: {{ .Release.Name }}
path: '/stackgres/mutation/sgshardedcluster'
caBundle: {{ $cert }}
admissionReviewVersions: ["v1"]
- name: sgshardedbackups.mutating-webhook.stackgres.io
sideEffects: None
rules:
- operations: ["CREATE", "UPDATE"]
apiGroups: ["stackgres.io"]
apiVersions: ["*"]
resources: ["sgshardedbackups"]
failurePolicy: Fail
clientConfig:
service:
namespace: {{ .Release.Namespace }}
name: {{ .Release.Name }}
path: '/stackgres/mutation/sgshardedbackup'
caBundle: {{ $cert }}
admissionReviewVersions: ["v1"]
- name: sgshardeddbops.mutating-webhook.stackgres.io
sideEffects: None
rules:
- operations: ["CREATE", "UPDATE"]
apiGroups: ["stackgres.io"]
apiVersions: ["*"]
resources: ["sgshardeddbops"]
failurePolicy: Fail
clientConfig:
service:
namespace: {{ .Release.Namespace }}
name: {{ .Release.Name }}
path: '/stackgres/mutation/sgshardeddbops'
caBundle: {{ $cert }}
admissionReviewVersions: ["v1"]

View File

@ -0,0 +1,18 @@
{{- if .Values.serviceAccount.create }}
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: {{ .Release.Name }}
{{- with .Values.clusterOwnerRefereces }}
ownerReferences:
{{- toYaml . | nindent 4 }}
{{- end }}
subjects:
- kind: ServiceAccount
name: {{ .Release.Name }}
namespace: {{ .Release.Namespace }}
roleRef:
kind: ClusterRole
name: {{ .Release.Name }}
apiGroup: rbac.authorization.k8s.io
{{- end }}

View File

@ -0,0 +1,239 @@
{{- if .Values.serviceAccount.create }}
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
{{- with .Values.clusterOwnerRefereces }}
ownerReferences:
{{- toYaml . | nindent 4 }}
{{- end }}
name: {{ .Release.Name }}
rules:
- apiGroups: ["", "apps", "extensions", "rbac.authorization.k8s.io", "batch"]
resources:
- pods
- pods/exec
- pods/log
- services
- endpoints
- endpoints/restricted
- persistentvolumeclaims
- configmaps
- secrets
- deployments
- statefulsets
- serviceaccounts
- namespaces
- roles
- rolebindings
- events
- cronjobs
- jobs
verbs:
- get
- list
- watch
- update
- create
- delete
- deletecollection
- patch
- apiGroups: ["storage.k8s.io"]
resources: ["storageclasses"]
verbs: ["get", "list"]
- apiGroups: ["stackgres.io"]
resources:
- sgclusters
- sgpgconfigs
- sginstanceprofiles
- sgpoolconfigs
- sgbackupconfigs
- sgbackups
- sgdistributedlogs
- sgdbops
- sgobjectstorages
- sgscripts
- sgshardedclusters
- sgshardedbackups
- sgshardeddbops
- sgconfigs
verbs:
- create
- watch
- list
- get
- update
- patch
- delete
- apiGroups: ["stackgres.io"]
resources:
- sgconfigs/status
- sgclusters/status
- sgdistributedlogs/status
- sgclusters/finalizers
- sgpgconfigs/finalizers
- sginstanceprofiles/finalizers
- sgpoolconfigs/finalizers
- sgbackupconfigs/finalizers
- sgbackups/finalizers
- sgdistributedlogs/finalizers
- sgdbops/finalizers
- sgobjectstorages/finalizers
- sgscripts/finalizers
- sgshardedclusters/finalizers
- sgshardedbackups/finalizers
- sgshardeddbops/finalizers
- sgconfigs/finalizers
verbs:
- update
- apiGroups: ["", "apps", "batch"]
resources:
- statefulsets/finalizers
- persistentvolumeclaims/finalizers
- deployments/finalizers
- services/finalizers
- endpoints/finalizers
- cronjobs/finalizers
- jobs/finalizers
- pods/finalizers
verbs:
- update
- apiGroups: ["apiextensions.k8s.io"]
resources:
- customresourcedefinitions
resourceNames:
- sgconfigs.stackgres.io
- sgclusters.stackgres.io
- sginstanceprofiles.stackgres.io
- sgpgconfigs.stackgres.io
- sgpoolconfigs.stackgres.io
- sgbackups.stackgres.io
- sgbackupconfigs.stackgres.io
- sgobjectstorages.stackgres.io
- sgdbops.stackgres.io
- sgdistributedlogs.stackgres.io
- sgshardedclusters.stackgres.io
- sgshardedbackups.stackgres.io
- sgshardeddbops.stackgres.io
- sgscripts.stackgres.io
verbs:
- get
- apiGroups: ["apiextensions.k8s.io"]
resources:
- customresourcedefinitions
verbs:
- list
- apiGroups: ["snapshot.storage.k8s.io"]
resources:
- volumesnapshots
verbs:
- list
- get
- watch
- create
{{- if .Values.prometheus.allowAutobind }}
- apiGroups: ["apiextensions.k8s.io"]
resources:
- customresourcedefinitions
resourceNames:
- prometheuses.monitoring.coreos.com
verbs:
- get
- apiGroups: ["apiextensions.k8s.io"]
resources:
- customresourcedefinitions
verbs:
- list
- apiGroups: ["monitoring.coreos.com"]
resources:
- servicemonitors
- podmonitors
verbs:
- list
- get
- create
- delete
- update
- patch
- apiGroups: ["monitoring.coreos.com"]
resources:
- prometheus
- prometheuses
- podmonitors
verbs:
- list
- get
{{- end }}
{{- if not .Values.disableCRDcreation }}
- apiGroups:
- admissionregistration.k8s.io
resources:
- mutatingwebhookconfigurations
- validatingwebhookconfigurations
resourceNames:
- {{ .Release.Name }}
verbs:
- get
- patch
- apiGroups: ["apiextensions.k8s.io"]
resources:
- customresourcedefinitions
verbs:
- create
- apiGroups: ["apiextensions.k8s.io"]
resources:
- customresourcedefinitions
resourceNames:
- sgconfigs.stackgres.io
- sgclusters.stackgres.io
- sginstanceprofiles.stackgres.io
- sgpgconfigs.stackgres.io
- sgpoolconfigs.stackgres.io
- sgbackups.stackgres.io
- sgbackupconfigs.stackgres.io
- sgobjectstorages.stackgres.io
- sgdbops.stackgres.io
- sgdistributedlogs.stackgres.io
- sgshardedclusters.stackgres.io
- sgshardedbackups.stackgres.io
- sgshardeddbops.stackgres.io
- sgscripts.stackgres.io
verbs:
- patch
- update
{{- end }}
{{- end }}
- apiGroups: ["shardingsphere.apache.org"]
resources:
- computenodes
verbs:
- get
- list
- watch
- update
- create
- delete
- patch
- apiGroups: ["keda.sh"]
resources:
- scaledobjects
- triggerauthentications
verbs:
- get
- list
- watch
- update
- create
- delete
- patch
- apiGroups: ["autoscaling.k8s.io"]
resources:
- verticalpodautoscalers
verbs:
- get
- list
- watch
- update
- create
- delete
- patch

View File

@ -0,0 +1,239 @@
{{- if .Values.deploy.operator }}
apiVersion: "apps/v1"
kind: "Deployment"
metadata:
{{- with .Values.operator.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
labels:
app: {{ .Release.Name }}
version: "{{ .Chart.Version }}"
group: stackgres.io
name: {{ .Release.Name }}
namespace: {{ .Release.Namespace }}
spec:
replicas: 1
selector:
matchLabels:
app: {{ .Release.Name }}
group: stackgres.io
template:
metadata:
labels:
app: {{ .Release.Name }}
group: stackgres.io
spec:
{{- with .Values.operator.affinity}}
affinity:
{{- toYaml . | nindent 8 }}
{{- end}}
serviceAccountName: {{ .Release.Name }}
{{- if .Values.serviceAccount.create }}
{{- if .Values.serviceAccount.repoCredentials }}
imagePullSecrets:
{{- range .Values.serviceAccount.repoCredentials }}
- name: {{ . }}
{{- end }}
{{- end }}
{{- end }}
{{- with .Values.operator.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end}}
securityContext:
{{- if or (not (.Capabilities.APIVersions.Has "project.openshift.io/v1")) .Values.developer.disableArbitraryUser }}
runAsNonRoot: true
{{- if .Values.operator.image.tag | hasSuffix "-jvm" }}
runAsUser: 185
runAsGroup: 185
fsGroup: 185
{{- else }}
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
{{- end }}
{{- end }}
containers:
{{- if not (and .Values.developer.externalOperatorIp .Values.developer.externalOperatorPort) }}
- name: {{ .Release.Name }}
image: "{{ include "operator-image" . }}"
imagePullPolicy: {{ .Values.operator.image.pullPolicy }}
env:
- name: OPERATOR_NAME
value: "{{ .Release.Name }}"
- name: OPERATOR_NAMESPACE
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.namespace
- name: OPERATOR_IMAGE_VERSION
value: "{{ .Values.operator.image.tag }}"
- name: DISABLE_RECONCILIATION
value: "false"
- name: INSTALL_CRDS
value: "true"
- name: INSTALL_WEBHOOKS
value: "true"
{{- if not .Values.cert.certManager.autoConfigure }}
- name: INSTALL_CERTS
value: "true"
{{- end }}
- name: PROMETHEUS_AUTOBIND
value: "{{ .Values.prometheus.allowAutobind }}"
{{- if and (.Capabilities.APIVersions.Has "project.openshift.io/v1") (not .Values.developer.disableArbitraryUser) }}
- name: USE_ARBITRARY_USER
value: "true"
{{- end }}
{{- if .Values.developer.logLevel }}
- name: OPERATOR_LOG_LEVEL
value: "{{ .Values.developer.logLevel }}"
{{- end }}
{{- if .Values.developer.showStackTraces }}
- name: OPERATOR_SHOW_STACK_TRACES
value: "{{ .Values.developer.showStackTraces }}"
{{- end }}
{{- if .Values.developer.extraOpts }}
- name: APP_OPTS
value: '{{ range .Values.developer.extraOpts }}{{ . }} {{ end }}'
{{- end }}
{{- if .Values.developer.extraOpts }}
- name: JAVA_OPTS
value: '{{ range .Values.developer.extraOpts }}{{ . }} {{ end }}'
{{- end }}
{{- if .Values.developer.enableJvmDebug }}
- name: DEBUG_OPERATOR
value: "{{ .Values.developer.enableJvmDebug }}"
{{- end }}
{{- if .Values.developer.enableJvmDebugSuspend }}
- name: DEBUG_OPERATOR_SUSPEND
value: "{{ .Values.developer.enableJvmDebugSuspend }}"
{{- end }}
- name: OPERATOR_SERVICE_ACCOUNT
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: spec.serviceAccountName
- name: OPERATOR_POD_NAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.name
- name: OPERATOR_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
{{- if and .Values.grafana.url .Values.grafana.token .Values.grafana.webHost }}
- name: GRAFANA_EMBEDDED
value: "true"
{{ end }}
- name: SG_CONTAINER_REGISTRY
value: "{{ .Values.containerRegistry }}"
- name: SG_IMAGE_PULL_POLICY
value: "{{ .Values.imagePullPolicy }}"
{{- if .Values.extensions.cache.enabled }}
- name: EXTENSIONS_REPOSITORY_URLS
value: "{{ range $index, $element := .Values.extensions.repositoryUrls }}{{ if $index }},{{ end }}{{ $element := regexReplaceAll "([?&])proxyUrl=[^&]+[&]" $element "${1}" }}{{ $element := regexReplaceAll "([?&])proxyUrl=[^&]+$" $element "" }}{{ $element }}{{ if $element | contains "?" }}&{{ else }}?{{ end }}proxyUrl=http%3A%2F%2F{{ $.Release.Name }}-extensions-cache.{{ $.Release.Namespace }}%3FsetHttpScheme%3Dtrue&retry=3%3A5{{ end }}"
{{- else }}
- name: EXTENSIONS_REPOSITORY_URLS
value: "{{ range $index, $element := .Values.extensions.repositoryUrls }}{{ if $index }},{{ end }}{{ $element }}{{ end }}"
{{- end }}
{{- if .Values.developer.extraEnv }}
{{- range $name,$value := .Values.developer.extraEnv }}
- name: {{ $name }}
value: {{ $value }}
{{- end }}
{{- end }}
{{- with .Values.developer.version }}
- name: OPERATOR_VERSION
value: {{ . | quote }}
{{- end }}
ports:
- containerPort: 8080
name: "http"
protocol: "TCP"
- containerPort: 8443
name: "https"
protocol: "TCP"
livenessProbe:
httpGet:
path: "/q/health/live"
port: 8080
scheme: "HTTP"
initialDelaySeconds: 10
periodSeconds: 60
timeoutSeconds: 10
readinessProbe:
httpGet:
path: "/q/health/ready"
port: 8080
scheme: "HTTP"
initialDelaySeconds: 0
periodSeconds: 2
timeoutSeconds: 1
{{- with .Values.operator.resources }}
resources:
{{- toYaml . | nindent 10 }}
{{- end }}
volumeMounts:
- name: operator-certs
mountPath: /etc/operator/certs
readOnly: true
{{- with ((.Values.developer.patches).operator).volumeMounts }}
{{- toYaml . | nindent 10 }}
{{- end }}
{{- else }}
- name: {{ .Release.Name }}-nginx
image: "registry.access.redhat.com/ubi8/nginx-120:1-92"
imagePullPolicy: IfNotPresent
args:
- '/bin/sh'
- '-ec'
{{- if .Values.developer.showDebug }}
- '-x'
{{- end }}
- exec nginx -g 'daemon off;'
ports:
- containerPort: 9443
name: "proxyhttps"
protocol: "TCP"
volumeMounts:
- name: operator-certs
mountPath: /etc/operator/certs
readOnly: true
- name: operator-nginx-conf
mountPath: /etc/nginx/conf.d
readOnly: true
- name: operator-nginx
subPath: var/cache/nginx
mountPath: /var/cache/nginx
readOnly: false
- name: operator-nginx
subPath: var/run
mountPath: /var/run
readOnly: false
{{- end }}
volumes:
- name: operator-certs
secret:
secretName: {{ include "cert-name" . }}
optional: true
{{- if and .Values.developer.externalOperatorIp .Values.developer.externalOperatorPort }}
- name: operator-nginx-conf
configMap:
name: {{ .Release.Name }}-nginx
optional: false
items:
- key: stackgres-operator.conf
path: stackgres-operator.conf
- name: operator-nginx
emptyDir: {}
{{- end }}
{{- with ((.Values.developer.patches).operator).volumes }}
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.operator.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,28 @@
{{ if and .Values.developer.externalOperatorIp .Values.developer.externalOperatorPort }}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-nginx
namespace: {{ .Release.Namespace }}
{{- if .Values.qutePreprocess }}#comment.preprocess.start{{- end }}
data:
stackgres-operator.conf: |
server {
server_name localhost;
listen 9443 ssl;
ssl_certificate /etc/operator/certs/server.crt;
ssl_certificate_key /etc/operator/certs/root.key;
location ~ ^/stackgres {
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://{{ .Release.Name }}-api:8080;
}
}
{{- if .Values.qutePreprocess }}#comment.preprocess.end{{- end}}
{{- end }}

View File

@ -0,0 +1,17 @@
{{- if .Values.serviceAccount.create }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ .Release.Name }}
namespace: {{ .Release.Namespace }}
{{- with .Values.operator.serviceAccount.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- if .Values.serviceAccount.repoCredentials }}
imagePullSecrets:
{{- range .Values.serviceAccount.repoCredentials }}
- name: {{ . }}
{{- end }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,41 @@
{{ if and .Values.deploy.operator (not (and .Values.developer.externalOperatorIp .Values.developer.externalOperatorPort)) }}
apiVersion: v1
kind: Service
metadata:
{{- with .Values.operator.service.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
namespace: {{ .Release.Namespace }}
name: {{ .Release.Name }}
spec:
type: ClusterIP
selector:
app: {{ .Release.Name }}
ports:
- name: https
protocol: TCP
port: 443
targetPort: https
{{ else }}
apiVersion: v1
kind: Service
metadata:
namespace: {{ .Release.Namespace }}
name: {{ .Release.Name }}
spec:
ports:
- port: 443
targetPort: {{ .Values.developer.externalOperatorPort }}
---
kind: Endpoints
apiVersion: v1
metadata:
namespace: {{ .Release.Namespace }}
name: {{ .Release.Name }}
subsets:
- addresses:
- ip: "{{ .Values.developer.externalOperatorIp }}"
ports:
- port: {{ .Values.developer.externalOperatorPort }}
{{ end }}

View File

@ -0,0 +1,78 @@
{{- if eq "true" (include "stackgres.operator.missingSGConfigCrd" .) }}
apiVersion: batch/v1
kind: Job
metadata:
namespace: {{ .Release.Namespace }}
name: "{{ .Release.Name }}-install-crd-and-sgconfig"
labels:
app: stackgres-operator-init
job: install-crd-and-sgconfig
annotations:
"helm.sh/hook": pre-upgrade
"helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
"helm.sh/hook-weight": "10"
{{- with .Values.jobs.annotations }}
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
ttlSecondsAfterFinished: 3600
template:
metadata:
labels:
app: stackgres-operator-init
job: install-crd-and-sgconfig
spec:
serviceAccountName: {{ .Release.Name }}-init
restartPolicy: OnFailure
terminationGracePeriodSeconds: 0
{{- with .Values.jobs.affinity}}
affinity:
{{- toYaml . | nindent 8 }}
{{- end}}
{{- with .Values.jobs.nodeSelector}}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.jobs.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
containers:
- name: "install-crd-and-sgconfig"
image: {{ template "kubectl.image" . }}
imagePullPolicy: "IfNotPresent"
{{- with .Values.jobs.resources }}
resources:
{{- toYaml . | nindent 10 }}
{{- end }}
command:
- "/bin/bash"
- "-ecx"
- |
cat << 'EOF' > /tmp/SGConfig.yaml
{{ .Files.Get "crds/SGConfig.yaml" | nindent 12 }}
EOF
kubectl create -f /tmp/SGConfig.yaml || kubectl get -f /tmp/SGConfig.yaml -o name > /dev/null
cat << 'EOF' | kubectl apply -f -
apiVersion: stackgres.io/v1
kind: SGConfig
metadata:
annotations:
meta.helm.sh/release-name: {{ .Release.Name }}
meta.helm.sh/release-namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/managed-by: Helm
name: {{ .Release.Name }}
namespace: {{ .Release.Namespace }}
spec:
{{ regexReplaceAll "[^ ]+: null" (toYaml .Values | nindent 14) "" }}
EOF
{{- else }}
apiVersion: stackgres.io/v1
kind: SGConfig
metadata:
name: {{ .Release.Name }}
namespace: {{ .Release.Namespace }}
spec:
{{ regexReplaceAll "[^ ]+: null" (toYaml .Values | nindent 2) "" }}
{{- end }}

View File

@ -0,0 +1,47 @@
---
{{ if and .Values.deploy.operator (not (and .Values.developer.externalOperatorIp .Values.developer.externalOperatorPort)) }}
apiVersion: v1
kind: Pod
metadata:
name: "{{ .Release.Name }}-test-connection"
labels:
app: "{{ .Release.Name }}"
group: helm-tests
annotations:
"helm.sh/hook": test
spec:
{{- with .Values.jobs.affinity}}
affinity:
{{- toYaml . | nindent 8 }}
{{- end}}
{{- with .Values.jobs.nodeSelector}}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
serviceAccountName: {{ .Release.Name }}
restartPolicy: Never
terminationGracePeriodSeconds: 0
{{- with .Values.jobs.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
securityContext:
{{- if or (not (.Capabilities.APIVersions.Has "project.openshift.io/v1")) .Values.developer.disableArbitraryUser }}
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
{{- end }}
containers:
- name: conn-check
image: '{{ template "kubectl.image" . }}'
imagePullPolicy: "IfNotPresent"
command:
- "bash"
- "-xe"
- "-c"
- |
POD_NAME=$(kubectl get pod -n {{ .Release.Namespace }} -o name | grep -v {{ .Release.Name }}-test-connection | grep {{ .Release.Name }})
POD_IP=$(kubectl get ${POD_NAME} -n {{ .Release.Namespace }} -o jsonpath="{ .status.podIP }")
curl -v ${POD_IP}:8080/q/health/live
{{ end }}

View File

@ -0,0 +1,217 @@
{{- $cert := "Cg==" }}
{{- $certSecret := lookup "v1" "Secret" .Release.Namespace (include "cert-name" .) }}
{{- if $certSecret }}
{{- if (index ($certSecret.data) "tls.crt") }}
{{- $cert = (index $certSecret.data "tls.crt") }}
{{- end }}
{{- end }}
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
{{- with .Values.clusterOwnerRefereces }}
ownerReferences:
{{- toYaml . | nindent 4 }}
{{- end }}
name: {{ .Release.Name }}
namespace: {{ .Release.Namespace }}
annotations:
meta.helm.sh/release-name: {{ .Release.Name }}
meta.helm.sh/release-namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/managed-by: Helm
webhooks:
- name: sgcluster.validating-webhook.stackgres.io
sideEffects: None
rules:
- operations: ["CREATE", "UPDATE"]
apiGroups: ["stackgres.io"]
apiVersions: ["*"]
resources: ["sgclusters"]
failurePolicy: Fail
clientConfig:
service:
namespace: {{ .Release.Namespace }}
name: {{ .Release.Name }}
path: '/stackgres/validation/sgcluster'
caBundle: {{ $cert }}
admissionReviewVersions: ["v1"]
- name: sgpgconfig.validating-webhook.stackgres.io
sideEffects: None
rules:
- operations: ["CREATE", "UPDATE", "DELETE"]
apiGroups: ["stackgres.io"]
apiVersions: ["*"]
resources: ["sgpgconfigs"]
failurePolicy: Fail
clientConfig:
service:
namespace: {{ .Release.Namespace }}
name: {{ .Release.Name }}
path: '/stackgres/validation/sgpgconfig'
caBundle: {{ $cert }}
admissionReviewVersions: ["v1"]
- name: sgpoolconfig.validating-webhook.stackgres.io
sideEffects: None
rules:
- operations: ["CREATE", "UPDATE", "DELETE"]
apiGroups: ["stackgres.io"]
apiVersions: ["*"]
resources: ["sgpoolconfigs"]
failurePolicy: Fail
clientConfig:
service:
namespace: {{ .Release.Namespace }}
name: {{ .Release.Name }}
path: '/stackgres/validation/sgpoolconfig'
caBundle: {{ $cert }}
admissionReviewVersions: ["v1"]
- name: sginstanceprofile.validating-webhook.stackgres.io
sideEffects: None
rules:
- operations: ["CREATE", "UPDATE", "DELETE"]
apiGroups: ["stackgres.io"]
apiVersions: ["*"]
resources: ["sginstanceprofiles"]
failurePolicy: Fail
clientConfig:
service:
namespace: {{ .Release.Namespace }}
name: {{ .Release.Name }}
path: '/stackgres/validation/sginstanceprofile'
caBundle: {{ $cert }}
admissionReviewVersions: ["v1"]
- name: sgbackupconfig.validating-webhook.stackgres.io
sideEffects: None
rules:
- operations: ["CREATE", "UPDATE", "DELETE"]
apiGroups: ["stackgres.io"]
apiVersions: ["*"]
resources: ["sgbackupconfigs"]
failurePolicy: Fail
clientConfig:
service:
namespace: {{ .Release.Namespace }}
name: {{ .Release.Name }}
path: '/stackgres/validation/sgbackupconfig'
caBundle: {{ $cert }}
admissionReviewVersions: ["v1"]
- name: sgbackup.validating-webhook.stackgres.io
sideEffects: None
rules:
- operations: ["CREATE", "UPDATE", "DELETE"]
apiGroups: ["stackgres.io"]
apiVersions: ["*"]
resources: ["sgbackups"]
failurePolicy: Fail
clientConfig:
service:
namespace: {{ .Release.Namespace }}
name: {{ .Release.Name }}
path: '/stackgres/validation/sgbackup'
caBundle: {{ $cert }}
admissionReviewVersions: ["v1"]
- name: sgdistributedlogs.validating-webhook.stackgres.io
sideEffects: None
rules:
- operations: ["CREATE", "UPDATE", "DELETE"]
apiGroups: ["stackgres.io"]
apiVersions: ["*"]
resources: ["sgdistributedlogs"]
failurePolicy: Fail
clientConfig:
service:
namespace: {{ .Release.Namespace }}
name: {{ .Release.Name }}
path: '/stackgres/validation/sgdistributedlogs'
caBundle: {{ $cert }}
admissionReviewVersions: ["v1"]
- name: sgdbops.validating-webhook.stackgres.io
sideEffects: None
rules:
- operations: ["CREATE", "UPDATE", "DELETE"]
apiGroups: ["stackgres.io"]
apiVersions: ["*"]
resources: ["sgdbops"]
failurePolicy: Fail
clientConfig:
service:
namespace: {{ .Release.Namespace }}
name: {{ .Release.Name }}
path: '/stackgres/validation/sgdbops'
caBundle: {{ $cert }}
admissionReviewVersions: ["v1"]
- name: sgobjectstorage.validating-webhook.stackgres.io
sideEffects: None
rules:
- operations: ["CREATE", "UPDATE", "DELETE"]
apiGroups: ["stackgres.io"]
apiVersions: ["*"]
resources: ["sgobjectstorages"]
failurePolicy: Fail
clientConfig:
service:
namespace: {{ .Release.Namespace }}
name: {{ .Release.Name }}
path: '/stackgres/validation/sgobjectstorage'
caBundle: {{ $cert }}
admissionReviewVersions: ["v1"]
- name: sgscripts.validating-webhook.stackgres.io
sideEffects: None
rules:
- operations: ["CREATE", "UPDATE", "DELETE"]
apiGroups: ["stackgres.io"]
apiVersions: ["*"]
resources: ["sgscripts"]
failurePolicy: Fail
clientConfig:
service:
namespace: {{ .Release.Namespace }}
name: {{ .Release.Name }}
path: '/stackgres/validation/sgscript'
caBundle: {{ $cert }}
admissionReviewVersions: ["v1"]
- name: sgshardedclusters.validating-webhook.stackgres.io
sideEffects: None
rules:
- operations: ["CREATE", "UPDATE", "DELETE"]
apiGroups: ["stackgres.io"]
apiVersions: ["*"]
resources: ["sgshardedclusters"]
failurePolicy: Fail
clientConfig:
service:
namespace: {{ .Release.Namespace }}
name: {{ .Release.Name }}
path: '/stackgres/validation/sgshardedcluster'
caBundle: {{ $cert }}
admissionReviewVersions: ["v1"]
- name: sgshardedbackups.validating-webhook.stackgres.io
sideEffects: None
rules:
- operations: ["CREATE", "UPDATE", "DELETE"]
apiGroups: ["stackgres.io"]
apiVersions: ["*"]
resources: ["sgshardedbackups"]
failurePolicy: Fail
clientConfig:
service:
namespace: {{ .Release.Namespace }}
name: {{ .Release.Name }}
path: '/stackgres/validation/sgshardedbackup'
caBundle: {{ $cert }}
admissionReviewVersions: ["v1"]
- name: sgshardeddbops.validating-webhook.stackgres.io
sideEffects: None
rules:
- operations: ["CREATE", "UPDATE", "DELETE"]
apiGroups: ["stackgres.io"]
apiVersions: ["*"]
resources: ["sgshardeddbops"]
failurePolicy: Fail
clientConfig:
service:
namespace: {{ .Release.Namespace }}
name: {{ .Release.Name }}
path: '/stackgres/validation/sgshardeddbops'
caBundle: {{ $cert }}
admissionReviewVersions: ["v1"]

View File

@ -0,0 +1,67 @@
{{- if and .Values.deploy.restapi }}
{{- if eq "true" (include "stackgres.operator.unmodificableWebapiAdminClusterRoleBinding" .) }}
apiVersion: batch/v1
kind: Job
metadata:
namespace: {{ .Release.Namespace }}
name: "{{ .Release.Name }}-delete-webapi-admin-clusterrolebinding"
labels:
app: stackgres-operator-init
job: delete-webapi-admin-clusterrolebinding
annotations:
"helm.sh/hook": pre-upgrade
"helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
"helm.sh/hook-weight": "10"
{{- with .Values.jobs.annotations }}
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
ttlSecondsAfterFinished: 3600
template:
metadata:
labels:
app: stackgres-operator-init
job: delete-webapi-admin-clusterrolebinding
spec:
serviceAccountName: {{ .Release.Name }}-init
restartPolicy: OnFailure
terminationGracePeriodSeconds: 0
{{- with .Values.jobs.affinity}}
affinity:
{{- toYaml . | nindent 8 }}
{{- end}}
{{- with .Values.jobs.nodeSelector}}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.jobs.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
containers:
- name: "delete-webapi-admin-clusterrolebinding"
image: {{ template "kubectl.image" . }}
imagePullPolicy: "IfNotPresent"
{{- with .Values.jobs.resources }}
resources:
{{- toYaml . | nindent 10 }}
{{- end }}
command:
- "/bin/bash"
- "-ecx"
- |
kubectl delete clusterrolebinding stackgres-restapi-admin --ignore-not-found
{{- end }}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: stackgres-restapi-admin
subjects:
- kind: User
name: {{ .Values.authentication.user | quote }}
roleRef:
kind: ClusterRole
name: stackgres-restapi-admin
apiGroup: rbac.authorization.k8s.io
{{- end }}

View File

@ -0,0 +1,119 @@
{{- if and .Values.deploy.restapi }}
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
api.stackgres.io/auth: user
name: stackgres-restapi-admin
rules:
- apiGroups: ["", "batch"]
resources:
- pods/exec
- configmaps
- secrets
- jobs
verbs:
- create
- apiGroups: [""]
resources:
- pods/exec
verbs:
- get
- apiGroups: ["", "batch"]
resources:
- configmaps
- secrets
- jobs
verbs:
- delete
- apiGroups: [""]
resources:
- configmaps
- secrets
verbs:
- patch
- update
- apiGroups: ["", "batch", "storage.k8s.io"]
resources:
- namespaces
- storageclasses
- pods
- services
- configmaps
- secrets
- persistentvolumes
- persistentvolumeclaims
- events
- jobs
verbs:
- get
- list
- watch
- apiGroups: ["stackgres.io"]
resources:
- sgclusters
- sgpgconfigs
- sginstanceprofiles
- sgpoolconfigs
- sgbackupconfigs
- sgbackups
- sgdistributedlogs
- sgdbops
- sgobjectstorages
- sgscripts
- sgshardedclusters
verbs:
- create
- watch
- list
- get
- update
- patch
- delete
- apiGroups: ["stackgres.io"]
resources:
- sgconfigs
verbs:
- watch
- list
- get
- update
- patch
- apiGroups: ["apiextensions.k8s.io"]
resources:
- customresourcedefinitions
resourceNames:
- sgconfigs.stackgres.io
- sgclusters.stackgres.io
- sginstanceprofiles.stackgres.io
- sgpgconfigs.stackgres.io
- sgpoolconfigs.stackgres.io
- sgbackups.stackgres.io
- sgbackupconfigs.stackgres.io
- sgobjectstorages.stackgres.io
- sgdbops.stackgres.io
- sgdistributedlogs.stackgres.io
- sgshardedclusters.stackgres.io
- sgscripts.stackgres.io
verbs:
- get
- apiGroups: ["apiextensions.k8s.io"]
resources:
- customresourcedefinitions
verbs:
- list
- apiGroups: ["rbac.authorization.k8s.io"]
resources:
- roles
- rolebindings
- clusterroles
- clusterrolebindings
verbs:
- get
- list
- watch
- create
- update
- patch
- delete
{{- end }}

View File

@ -0,0 +1,19 @@
{{- if and .Values.deploy.restapi .Values.serviceAccount.create }}
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: {{ .Values.restapi.name }}
annotations:
meta.helm.sh/release-name: {{ .Release.Name }}
meta.helm.sh/release-namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/managed-by: Helm
subjects:
- kind: ServiceAccount
name: {{ .Values.restapi.name }}
namespace: {{ .Release.Namespace }}
roleRef:
kind: ClusterRole
name: {{ .Values.restapi.name }}
apiGroup: rbac.authorization.k8s.io
{{- end }}

View File

@ -0,0 +1,33 @@
{{- if and .Values.deploy.restapi .Values.serviceAccount.create }}
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: {{ .Values.restapi.name }}
annotations:
meta.helm.sh/release-name: {{ .Release.Name }}
meta.helm.sh/release-namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/managed-by: Helm
rules:
- apiGroups:
- ""
resources:
- users
- groups
- serviceaccount
verbs:
- impersonate
- apiGroups:
- authorization.k8s.io
resources:
- subjectaccessreviews
verbs:
- create
- apiGroups:
- ""
resources:
- secrets # Secret Verification authentication
verbs:
- get
- list
{{- end }}

View File

@ -0,0 +1,82 @@
{{- if and .Values.deploy.restapi }}
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
api.stackgres.io/auth: user
name: stackgres-restapi-reader
rules:
- apiGroups: ["", "batch"]
resources:
- pods/exec
verbs:
- create
- apiGroups: [""]
resources:
- pods/exec
verbs:
- get
- apiGroups: ["", "batch", "storage.k8s.io"]
resources:
- namespaces
- storageclasses
- pods
- services
- configmaps
- secrets
- persistentvolumes
- persistentvolumeclaims
- events
- jobs
verbs:
- get
- list
- watch
- apiGroups: ["stackgres.io"]
resources:
- sgclusters
- sgpgconfigs
- sginstanceprofiles
- sgpoolconfigs
- sgbackupconfigs
- sgbackups
- sgdistributedlogs
- sgdbops
- sgobjectstorages
- sgscripts
- sgshardedclusters
verbs:
- watch
- list
- get
- apiGroups: ["stackgres.io"]
resources:
- sgconfigs
verbs:
- watch
- list
- get
- apiGroups: ["apiextensions.k8s.io"]
resources:
- customresourcedefinitions
resourceNames:
- sgconfigs.stackgres.io
- sgclusters.stackgres.io
- sginstanceprofiles.stackgres.io
- sgpgconfigs.stackgres.io
- sgpoolconfigs.stackgres.io
- sgbackups.stackgres.io
- sgbackupconfigs.stackgres.io
- sgobjectstorages.stackgres.io
- sgdbops.stackgres.io
- sgdistributedlogs.stackgres.io
- sgshardedclusters.stackgres.io
- sgscripts.stackgres.io
verbs:
- get
- apiGroups: ["apiextensions.k8s.io"]
resources:
- customresourcedefinitions
verbs:
- list
{{- end }}

View File

@ -0,0 +1,105 @@
{{- if and .Values.deploy.restapi }}
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
api.stackgres.io/auth: user
name: stackgres-restapi-writer
rules:
- apiGroups: ["", "batch"]
resources:
- pods/exec
- configmaps
- secrets
- jobs
verbs:
- create
- apiGroups: [""]
resources:
- pods/exec
verbs:
- get
- apiGroups: ["", "batch"]
resources:
- configmaps
- secrets
- jobs
verbs:
- delete
- apiGroups: [""]
resources:
- configmaps
- secrets
verbs:
- patch
- update
- apiGroups: ["", "batch", "storage.k8s.io"]
resources:
- namespaces
- storageclasses
- pods
- services
- configmaps
- secrets
- persistentvolumes
- persistentvolumeclaims
- events
- jobs
verbs:
- get
- list
- watch
- apiGroups: ["stackgres.io"]
resources:
- sgclusters
- sgpgconfigs
- sginstanceprofiles
- sgpoolconfigs
- sgbackupconfigs
- sgbackups
- sgdistributedlogs
- sgdbops
- sgobjectstorages
- sgscripts
- sgshardedclusters
verbs:
- create
- watch
- list
- get
- update
- patch
- delete
- apiGroups: ["stackgres.io"]
resources:
- sgconfigs
verbs:
- watch
- list
- get
- update
- patch
- apiGroups: ["apiextensions.k8s.io"]
resources:
- customresourcedefinitions
resourceNames:
- sgconfigs.stackgres.io
- sgclusters.stackgres.io
- sginstanceprofiles.stackgres.io
- sgpgconfigs.stackgres.io
- sgpoolconfigs.stackgres.io
- sgbackups.stackgres.io
- sgbackupconfigs.stackgres.io
- sgobjectstorages.stackgres.io
- sgdbops.stackgres.io
- sgdistributedlogs.stackgres.io
- sgshardedclusters.stackgres.io
- sgscripts.stackgres.io
verbs:
- get
- apiGroups: ["apiextensions.k8s.io"]
resources:
- customresourcedefinitions
verbs:
- list
{{- end }}

View File

@ -0,0 +1,413 @@
# -- The container registry host (and port) where the images will be pulled from.
containerRegistry: quay.io
# -- Image pull policy used for images loaded by the Operator
imagePullPolicy: "IfNotPresent"
# Section to configure Operator Installation ServiceAccount
serviceAccount:
# -- If `true` the Operator Installation ServiceAccount will be created
create: true
# -- Section to configure Operator ServiceAccount annotations
annotations: {}
# -- Repositories credentials Secret names to attach to ServiceAccounts and Pods
repoCredentials: []
# Section to configure Operator Pod
operator:
# Section to configure Operator image
image:
# -- Operator image name
name: "stackgres/operator"
# -- Operator image tag
tag: "1.10.0"
# -- Operator image pull policy
pullPolicy: "IfNotPresent"
# -- Operator Pod annotations
annotations: {}
# -- Operator Pod resources. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#resourcerequirements-v1-core
resources: {}
# -- Operator Pod node selector
nodeSelector: {}
# -- Operator Pod tolerations. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#toleration-v1-core
tolerations: []
# -- Operator Pod affinity. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#affinity-v1-core
affinity: {}
# Section to configure Operator ServiceAccount
serviceAccount:
# -- Section to configure Operator ServiceAccount annotations
annotations: {}
# -- Repositories credentials Secret names to attach to ServiceAccounts and Pods
repoCredentials: []
# Section to configure Operator Service
service:
# -- Section to configure Operator Service annotations
annotations: {}
# Section to configure REST API Pod
restapi:
# -- REST API Pod name
name: stackgres-restapi
# Section to configure REST API image
image:
# -- REST API image name
name: "stackgres/restapi"
# -- REST API image tag
tag: "1.10.0"
# -- REST API image pull policy
pullPolicy: "IfNotPresent"
# -- REST API Pod annotations
annotations: {}
# -- REST API Pod resources. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#resourcerequirements-v1-core
resources: {}
# -- REST API Pod node selector
nodeSelector: {}
# -- REST API Pod tolerations. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#toleration-v1-core
tolerations: []
# -- REST API Pod affinity. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#affinity-v1-core
affinity: {}
# Section to configure REST API ServiceAccount
serviceAccount:
# -- REST API ServiceAccount annotations
annotations: {}
# -- Repositories credentials Secret names to attach to ServiceAccounts and Pods
repoCredentials: []
# Section to configure REST API Service
service:
# -- REST API Service annotations
annotations: {}
# Section to configure Web Console container
adminui:
# Section to configure Web Console image
image:
# -- Web Console image name
name: "stackgres/admin-ui"
# -- Web Console image tag
tag: "1.10.0"
# -- Web Console image pull policy
pullPolicy: "IfNotPresent"
# -- Web Console resources. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#resourcerequirements-v1-core
resources: {}
# Section to configure Web Console service.
service:
# -- When set to `true` the HTTP port will be exposed in the Web Console Service
exposeHTTP: false
# -- The type used for the service of the UI:
# * Set to LoadBalancer to create a load balancer (if supported by the kubernetes cluster)
# to allow connect from Internet to the UI. Note that enabling this feature will probably incurr in
# some fee that depend on the host of the kubernetes cluster (for example this is true for EKS, GKE
# and AKS).
# * Set to NodePort to expose admin UI from kubernetes nodes.
type: ClusterIP
# -- (string) LoadBalancer will get created with the IP specified in
# this field. This feature depends on whether the underlying cloud-provider supports specifying
# the loadBalancerIP when a load balancer is created. This field will be ignored if the
# cloud-provider does not support the feature.
loadBalancerIP:
# -- (array) If specified and supported by the platform,
# this will restrict traffic through the cloud-provider load-balancer will be restricted to the
# specified client IPs. This field will be ignored if the cloud-provider does not support the
# feature.
# More info: https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/
loadBalancerSourceRanges:
# -- (integer) The HTTPS port used to expose the Service on Kubernetes nodes
nodePort:
# -- (integer) The HTTP port used to expose the Service on Kubernetes nodes
nodePortHTTP:
# Section to configure Operator Installation Jobs
jobs:
# Section to configure Operator Installation Jobs image
image:
# -- Operator Installation Jobs image name
name: "stackgres/jobs"
# -- Operator Installation Jobs image tag
tag: "1.10.0"
# -- Operator Installation Jobs image pull policy
pullPolicy: "IfNotPresent"
# -- Operator Installation Jobs annotations
annotations: {}
# -- Operator Installation Jobs resources. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#resourcerequirements-v1-core
resources: {}
# -- Operator Installation Jobs node selector
nodeSelector: {}
# -- Operator Installation Jobs tolerations. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#toleration-v1-core
tolerations: []
# -- Operator Installation Jobs affinity. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#affinity-v1-core
affinity: {}
# Section to configure deployment aspects.
deploy:
# -- When set to `true` the Operator will be deployed.
operator: true
# -- When set to `true` the Web Console / REST API will be deployed.
restapi: true
# Section to configure the Operator, REST API and Web Console certificates and JWT RSA key-pair.
cert:
# -- If set to `true` the CertificateSigningRequest used to generate the certificate used by
# Webhooks will be approved by the Operator Installation Job.
autoapprove: true
# -- When set to `true` the Operator certificate will be created.
createForOperator: true
# -- When set to `true` the Web Console / REST API certificate will be created.
createForWebApi: true
# -- (string) The Secret name with the Operator Webhooks certificate issued by the Kubernetes cluster CA
# of type kubernetes.io/tls. See https://kubernetes.io/docs/concepts/configuration/secret/#tls-secrets
secretName:
# -- When set to `true` the Operator certificates will be regenerated if `createForOperator` is set to `true`, and the certificate is expired or invalid.
regenerateCert: true
# -- (integer) The duration in days of the generated certificate for the Operator after which it will expire and be regenerated.
# If not specified it will be set to 730 (2 years) by default.
certDuration: 730
# -- (string) The Secret name with the Web Console / REST API certificate
# of type kubernetes.io/tls. See https://kubernetes.io/docs/concepts/configuration/secret/#tls-secrets
webSecretName:
# -- When set to `true` the Web Console / REST API certificates will be regenerated if `createForWebApi` is set to `true`, and the certificate is expired or invalid.
regenerateWebCert: true
# -- When set to `true` the Web Console / REST API RSA key pair will be regenerated if `createForWebApi` is set to `true`, and the certificate is expired or invalid.
regenerateWebRsa: true
# -- (integer) The duration in days of the generated certificate for the Web Console / REST API after which it will expire and be regenerated.
# If not specified it will be set to 730 (2 years) by default.
webCertDuration:
# -- (integer) The duration in days of the generated RSA key pair for the Web Console / REST API after which it will expire and be regenerated.
# If not specified it will be set to 730 (2 years) by default.
webRsaDuration:
# -- (string) The private RSA key used to create the Operator Webhooks certificate issued by the
# Kubernetes cluster CA.
key:
# -- (string) The Operator Webhooks certificate issued by Kubernetes cluster CA.
crt:
# -- (string) The private RSA key used to generate JWTs used in REST API authentication.
jwtRsaKey:
# -- (string) The public RSA key used to verify JWTs used in REST API authentication.
jwtRsaPub:
# -- (string) The private RSA key used to create the Web Console / REST API certificate
webKey:
# -- (string) The Web Console / REST API certificate
webCrt:
# Section to configure cert-manager integration to generate Operator certificates
certManager:
# -- When set to `true` then Issuer and Certificate for Operator and Web Console / REST API
# Pods will be generated
autoConfigure: false
# -- The requested duration (i.e. lifetime) of the Certificates. See https://cert-manager.io/docs/reference/api-docs/#cert-manager.io%2fv1
duration: "2160h"
# -- How long before the currently issued certificates expiry cert-manager should renew the certificate. See https://cert-manager.io/docs/reference/api-docs/#cert-manager.io%2fv1
renewBefore: "360h"
# -- The private key cryptography standards (PKCS) encoding for this certificates private key to be encoded in. See https://cert-manager.io/docs/reference/api-docs/#cert-manager.io/v1.CertificatePrivateKey
encoding: PKCS1
# -- Size is the key bit size of the corresponding private key for this certificate. See https://cert-manager.io/docs/reference/api-docs/#cert-manager.io/v1.CertificatePrivateKey
size: 2048
# Section to configure RBAC for Web Console admin user
rbac:
# -- When set to `true` the admin user is assigned the `cluster-admin` ClusterRole by creating
# ClusterRoleBinding.
create: true
# Section to configure Web Console authentication
authentication:
# -- Specify the authentication mechanism to use. By default is `jwt`, see https://stackgres.io/doc/latest/api/rbac#local-secret-mechanism.
# If set to `oidc` then see https://stackgres.io/doc/latest/api/rbac/#openid-connect-provider-mechanism.
type: jwt
# -- (boolean) When `true` will create the secret used to store the `admin` user credentials to access the UI.
createAdminSecret: true
# -- The admin username that will be required to access the UI
user: admin
# -- (string) The admin password that will be required to access the UI
password:
# Section to configure Web Console OIDC authentication
oidc:
# tlsVerification -- (string) Can be one of `required`, `certificate-validation` or `none`
# tlsVerification:
# authServerUrl -- (string)
# authServerUrl:
# clientId -- (string)
# clientId:
# credentialsSecret -- (string)
# credentialsSecret:
# clientIdSecretRef -- (object)
# clientIdSecretRef:
# name -- (string)
# name:
# key -- (string)
# key:
# credentialsSecretSecretRef -- (object)
# credentialsSecretSecretRef:
# name -- (string)
# name:
# key -- (string)
# key:
# Section to configure Prometheus integration.
prometheus:
# -- If set to false disable automatic bind to Prometheus
# created using the [Prometheus Operator](https://github.com/prometheus-operator/prometheus-operator).
# If disabled the cluster will not be binded to Prometheus automatically and will require manual
# intervention by the Kubernetes cluster administrator.
allowAutobind: true
# Section to configure Grafana integration
grafana:
# -- When set to `true` embed automatically Grafana into the Web Console by creating the
# StackGres dashboards and the read-only role used to read it from the Web Console
autoEmbed: false
# -- The schema to access Grafana. By default http. (used to embed manually and
# automatically grafana)
schema: http
# -- (string) The service host name to access grafana (used to embed manually and
# automatically Grafana).
# The parameter value should point to the grafana service following the
# [DNS reference](https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/) `svc_name.namespace`
webHost:
# -- The datasource name used to create the StackGres Dashboards into Grafana
datasourceName: Prometheus
# -- The username to access Grafana. By default admin. (used to embed automatically
# Grafana)
user: admin
# -- The password to access Grafana. By default prom-operator (the default in for
# kube-prometheus-stack helm chart). (used to embed automatically Grafana)
password: prom-operator
# -- Use follwing fields to indicate a secret where the grafana admin credentials are stored (replace user/password)
# -- (string) The namespace of secret with credentials to access Grafana. (used to
# embed automatically Grafana, alternative to use `user` and `password`)
secretNamespace:
# -- (string) The name of secret with credentials to access Grafana. (used to embed
# automatically Grafana, alternative to use `user` and `password`)
secretName:
# -- (string) The key of secret with username used to access Grafana. (used to embed
# automatically Grafana, alternative to use `user` and `password`)
secretUserKey:
# -- (string) The key of secret with password used to access Grafana. (used to
# embed automatically Grafana, alternative to use `user` and `password`)
secretPasswordKey:
# -- (string) The ConfigMap name with the dashboard JSONs
# that will be created in Grafana. If not set the default
# StackGres dashboards will be created. (used to embed automatically Grafana)
dashboardConfigMap:
# -- (array) The URLs of the PostgreSQL dashboards created in Grafana (used to embed manually
# Grafana). It must contain an entry for each JSON file under `grafana-dashboards` folder: `archiving.json`,
# `connection-pooling.json`, `current-activity.json`, `db-info.json`, `db-objects.json`, `db-os.json`, `queries.json`
# and `replication.json`
urls:
# Create and copy/paste grafana API token:
# - Grafana > Configuration > API Keys > Add API key (for viewer) > Copy key value
# -- (string) The Grafana API token to access the PostgreSQL dashboards created
# in Grafana (used to embed manually Grafana)
token:
# Section to configure extensions
extensions:
# -- A list of extensions repository URLs used to retrieve extensions
#
# To set a proxy for extensions repository add parameter proxyUrl to the URL:
# `https://extensions.stackgres.io/postgres/repository?proxyUrl=<proxy scheme>%3A%2F%2F<proxy host>[%3A<proxy port>]` (URL encoded)
#
# Other URL parameters are:
#
# * `skipHostnameVerification`: set it to `true` in order to use a server or a proxy with a self signed certificate
# * `retry`: set it to `<max retriex>[:<sleep before next retry>]` in order to retry a request on failure
# * `setHttpScheme`: set it to `true` in order to force using HTTP scheme
repositoryUrls:
- https://extensions.stackgres.io/postgres/repository
# Section to configure extensions cache (experimental).
#
# This feature is in beta and may cause failures, please use with caution and report any
# error to https://gitlab.com/ongresinc/stackgres/-/issues/new
cache:
# -- When set to `true` enable the extensions cache.
#
# This feature is in beta and may cause failures, please use with caution and report any
# error to https://gitlab.com/ongresinc/stackgres/-/issues/new
enabled: false
# -- An array of extensions pattern used to pre-loaded estensions into the extensions cache
preloadedExtensions:
- x86_64/linux/timescaledb-1\.7\.4-pg12
# Section to configure the extensions cache PersistentVolume
persistentVolume:
# -- The PersistentVolume size for the extensions cache
#
# Only use whole numbers (e.g. not 1e6) and K/Ki/M/Mi/G/Gi as units
size: 1Gi
# -- (string) If defined set storage class
# If set to "-" (equivalent to storageClass: "" in a PV spec) disables
# dynamic provisioning
# If undefined (the default) or set to null, no storageClass spec is
# set, choosing the default provisioner. (gp2 on AWS, standard on
# GKE, AWS & OpenStack)
storageClass:
# -- (string) If set, will use a host path volume with the specified path for the extensions cache
# instead of a PersistentVolume
hostPath:
# Following options are for developers only, but can also be useful in some cases ;)
# Section to configure developer options.
developer:
# -- (string) Set the operator version (used for testing)
version:
# -- (string) Set `quarkus.log.level`. See https://quarkus.io/guides/logging#root-logger-configuration
logLevel:
# -- If set to `true` add extra debug to any script controlled by the reconciliation cycle of the operator configuration
showDebug: false
# -- Set `quarkus.log.console.format` to `%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p [%c{4.}] (%t) %s%e%n`. See https://quarkus.io/guides/logging#logging-format
showStackTraces: false
# -- Only work with JVM version and allow connect
# on port 8000 of operator Pod with jdb or similar
enableJvmDebug: false
# -- Only work with JVM version and if `enableJvmDebug` is `true`
# suspend the JVM until a debugger session is started
enableJvmDebugSuspend: false
# -- (string) Set the external Operator IP
externalOperatorIp:
# -- (integer) Set the external Operator port
externalOperatorPort:
# -- (string) Set the external REST API IP
externalRestApiIp:
# -- (integer) Set the external REST API port
externalRestApiPort:
# -- If set to `true` and `extensions.cache.enabled` is also `true`
# it will try to download extensions from images (experimental)
allowPullExtensionsFromImageRepository: false
# -- It set to `true` disable arbitrary user that is set for OpenShift clusters
disableArbitraryUser: false
# Section to define patches for some StackGres Pods
patches:
# Section to define volumes to be used by the operator container
operator:
# -- Pod volumes. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#volume-v1-core
volumes: []
# -- Pod's container volume mounts. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#volumemount-v1-core
volumeMounts: []
# Section to define volumes to be used by the restapi container
restapi:
# -- Pod volumes. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#volume-v1-core
volumes: []
# -- Pod's container volume mounts. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#volumemount-v1-core
volumeMounts: []
# Section to define volumes to be used by the adminui container
adminui:
# -- Pod volumes. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#volume-v1-core
volumes: []
# -- Pod's container volume mounts. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#volumemount-v1-core
volumeMounts: []
# Section to define volumes to be used by the jobs container
jobs:
# -- Pod volumes. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#volume-v1-core
volumes: []
# -- Pod's container volume mounts. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#volumemount-v1-core
volumeMounts: []
# Section to define volumes to be used by the cluster controller container
clusterController:
# -- Pod volumes. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#volume-v1-core
volumes: []
# -- Pod's container volume mounts. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#volumemount-v1-core
volumeMounts: []
# Section to define volumes to be used by the distributedlogs controller container
distributedlogsController:
# -- Pod volumes. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#volume-v1-core
volumes: []
# -- Pod's container volume mounts. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#volumemount-v1-core
volumeMounts: []

View File

@ -0,0 +1,4 @@
{
"$schema": "http://json-schema.org/schema#",
"type": "object"
}

View File

@ -0,0 +1,413 @@
# -- The container registry host (and port) where the images will be pulled from.
containerRegistry: quay.io
# -- Image pull policy used for images loaded by the Operator
imagePullPolicy: "IfNotPresent"
# Section to configure Operator Installation ServiceAccount
serviceAccount:
# -- If `true` the Operator Installation ServiceAccount will be created
create: true
# -- Section to configure Operator ServiceAccount annotations
annotations: {}
# -- Repositories credentials Secret names to attach to ServiceAccounts and Pods
repoCredentials: []
# Section to configure Operator Pod
operator:
# Section to configure Operator image
image:
# -- Operator image name
name: "stackgres/operator"
# -- Operator image tag
tag: "1.10.0"
# -- Operator image pull policy
pullPolicy: "IfNotPresent"
# -- Operator Pod annotations
annotations: {}
# -- Operator Pod resources. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#resourcerequirements-v1-core
resources: {}
# -- Operator Pod node selector
nodeSelector: {}
# -- Operator Pod tolerations. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#toleration-v1-core
tolerations: []
# -- Operator Pod affinity. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#affinity-v1-core
affinity: {}
# Section to configure Operator ServiceAccount
serviceAccount:
# -- Section to configure Operator ServiceAccount annotations
annotations: {}
# -- Repositories credentials Secret names to attach to ServiceAccounts and Pods
repoCredentials: []
# Section to configure Operator Service
service:
# -- Section to configure Operator Service annotations
annotations: {}
# Section to configure REST API Pod
restapi:
# -- REST API Pod name
name: stackgres-restapi
# Section to configure REST API image
image:
# -- REST API image name
name: "stackgres/restapi"
# -- REST API image tag
tag: "1.10.0"
# -- REST API image pull policy
pullPolicy: "IfNotPresent"
# -- REST API Pod annotations
annotations: {}
# -- REST API Pod resources. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#resourcerequirements-v1-core
resources: {}
# -- REST API Pod node selector
nodeSelector: {}
# -- REST API Pod tolerations. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#toleration-v1-core
tolerations: []
# -- REST API Pod affinity. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#affinity-v1-core
affinity: {}
# Section to configure REST API ServiceAccount
serviceAccount:
# -- REST API ServiceAccount annotations
annotations: {}
# -- Repositories credentials Secret names to attach to ServiceAccounts and Pods
repoCredentials: []
# Section to configure REST API Service
service:
# -- REST API Service annotations
annotations: {}
# Section to configure Web Console container
adminui:
# Section to configure Web Console image
image:
# -- Web Console image name
name: "stackgres/admin-ui"
# -- Web Console image tag
tag: "1.10.0"
# -- Web Console image pull policy
pullPolicy: "IfNotPresent"
# -- Web Console resources. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#resourcerequirements-v1-core
resources: {}
# Section to configure Web Console service.
service:
# -- When set to `true` the HTTP port will be exposed in the Web Console Service
exposeHTTP: false
# -- The type used for the service of the UI:
# * Set to LoadBalancer to create a load balancer (if supported by the kubernetes cluster)
# to allow connect from Internet to the UI. Note that enabling this feature will probably incurr in
# some fee that depend on the host of the kubernetes cluster (for example this is true for EKS, GKE
# and AKS).
# * Set to NodePort to expose admin UI from kubernetes nodes.
type: ClusterIP
# -- (string) LoadBalancer will get created with the IP specified in
# this field. This feature depends on whether the underlying cloud-provider supports specifying
# the loadBalancerIP when a load balancer is created. This field will be ignored if the
# cloud-provider does not support the feature.
loadBalancerIP:
# -- (array) If specified and supported by the platform,
# this will restrict traffic through the cloud-provider load-balancer will be restricted to the
# specified client IPs. This field will be ignored if the cloud-provider does not support the
# feature.
# More info: https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/
loadBalancerSourceRanges:
# -- (integer) The HTTPS port used to expose the Service on Kubernetes nodes
nodePort:
# -- (integer) The HTTP port used to expose the Service on Kubernetes nodes
nodePortHTTP:
# Section to configure Operator Installation Jobs
jobs:
# Section to configure Operator Installation Jobs image
image:
# -- Operator Installation Jobs image name
name: "stackgres/jobs"
# -- Operator Installation Jobs image tag
tag: "1.10.0"
# -- Operator Installation Jobs image pull policy
pullPolicy: "IfNotPresent"
# -- Operator Installation Jobs annotations
annotations: {}
# -- Operator Installation Jobs resources. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#resourcerequirements-v1-core
resources: {}
# -- Operator Installation Jobs node selector
nodeSelector: {}
# -- Operator Installation Jobs tolerations. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#toleration-v1-core
tolerations: []
# -- Operator Installation Jobs affinity. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#affinity-v1-core
affinity: {}
# Section to configure deployment aspects.
deploy:
# -- When set to `true` the Operator will be deployed.
operator: true
# -- When set to `true` the Web Console / REST API will be deployed.
restapi: true
# Section to configure the Operator, REST API and Web Console certificates and JWT RSA key-pair.
cert:
# -- If set to `true` the CertificateSigningRequest used to generate the certificate used by
# Webhooks will be approved by the Operator Installation Job.
autoapprove: true
# -- When set to `true` the Operator certificate will be created.
createForOperator: true
# -- When set to `true` the Web Console / REST API certificate will be created.
createForWebApi: true
# -- (string) The Secret name with the Operator Webhooks certificate issued by the Kubernetes cluster CA
# of type kubernetes.io/tls. See https://kubernetes.io/docs/concepts/configuration/secret/#tls-secrets
secretName:
# -- When set to `true` the Operator certificates will be regenerated if `createForOperator` is set to `true`, and the certificate is expired or invalid.
regenerateCert: true
# -- (integer) The duration in days of the generated certificate for the Operator after which it will expire and be regenerated.
# If not specified it will be set to 730 (2 years) by default.
certDuration: 730
# -- (string) The Secret name with the Web Console / REST API certificate
# of type kubernetes.io/tls. See https://kubernetes.io/docs/concepts/configuration/secret/#tls-secrets
webSecretName:
# -- When set to `true` the Web Console / REST API certificates will be regenerated if `createForWebApi` is set to `true`, and the certificate is expired or invalid.
regenerateWebCert: true
# -- When set to `true` the Web Console / REST API RSA key pair will be regenerated if `createForWebApi` is set to `true`, and the certificate is expired or invalid.
regenerateWebRsa: true
# -- (integer) The duration in days of the generated certificate for the Web Console / REST API after which it will expire and be regenerated.
# If not specified it will be set to 730 (2 years) by default.
webCertDuration:
# -- (integer) The duration in days of the generated RSA key pair for the Web Console / REST API after which it will expire and be regenerated.
# If not specified it will be set to 730 (2 years) by default.
webRsaDuration:
# -- (string) The private RSA key used to create the Operator Webhooks certificate issued by the
# Kubernetes cluster CA.
key:
# -- (string) The Operator Webhooks certificate issued by Kubernetes cluster CA.
crt:
# -- (string) The private RSA key used to generate JWTs used in REST API authentication.
jwtRsaKey:
# -- (string) The public RSA key used to verify JWTs used in REST API authentication.
jwtRsaPub:
# -- (string) The private RSA key used to create the Web Console / REST API certificate
webKey:
# -- (string) The Web Console / REST API certificate
webCrt:
# Section to configure cert-manager integration to generate Operator certificates
certManager:
# -- When set to `true` then Issuer and Certificate for Operator and Web Console / REST API
# Pods will be generated
autoConfigure: false
# -- The requested duration (i.e. lifetime) of the Certificates. See https://cert-manager.io/docs/reference/api-docs/#cert-manager.io%2fv1
duration: "2160h"
# -- How long before the currently issued certificates expiry cert-manager should renew the certificate. See https://cert-manager.io/docs/reference/api-docs/#cert-manager.io%2fv1
renewBefore: "360h"
# -- The private key cryptography standards (PKCS) encoding for this certificates private key to be encoded in. See https://cert-manager.io/docs/reference/api-docs/#cert-manager.io/v1.CertificatePrivateKey
encoding: PKCS1
# -- Size is the key bit size of the corresponding private key for this certificate. See https://cert-manager.io/docs/reference/api-docs/#cert-manager.io/v1.CertificatePrivateKey
size: 2048
# Section to configure RBAC for Web Console admin user
rbac:
# -- When set to `true` the admin user is assigned the `cluster-admin` ClusterRole by creating
# ClusterRoleBinding.
create: true
# Section to configure Web Console authentication
authentication:
# -- Specify the authentication mechanism to use. By default is `jwt`, see https://stackgres.io/doc/latest/api/rbac#local-secret-mechanism.
# If set to `oidc` then see https://stackgres.io/doc/latest/api/rbac/#openid-connect-provider-mechanism.
type: jwt
# -- (boolean) When `true` will create the secret used to store the `admin` user credentials to access the UI.
createAdminSecret: true
# -- The admin username that will be required to access the UI
user: admin
# -- (string) The admin password that will be required to access the UI
password:
# Section to configure Web Console OIDC authentication
oidc:
# tlsVerification -- (string) Can be one of `required`, `certificate-validation` or `none`
# tlsVerification:
# authServerUrl -- (string)
# authServerUrl:
# clientId -- (string)
# clientId:
# credentialsSecret -- (string)
# credentialsSecret:
# clientIdSecretRef -- (object)
# clientIdSecretRef:
# name -- (string)
# name:
# key -- (string)
# key:
# credentialsSecretSecretRef -- (object)
# credentialsSecretSecretRef:
# name -- (string)
# name:
# key -- (string)
# key:
# Section to configure Prometheus integration.
prometheus:
# -- If set to false disable automatic bind to Prometheus
# created using the [Prometheus Operator](https://github.com/prometheus-operator/prometheus-operator).
# If disabled the cluster will not be binded to Prometheus automatically and will require manual
# intervention by the Kubernetes cluster administrator.
allowAutobind: true
# Section to configure Grafana integration
grafana:
# -- When set to `true` embed automatically Grafana into the Web Console by creating the
# StackGres dashboards and the read-only role used to read it from the Web Console
autoEmbed: false
# -- The schema to access Grafana. By default http. (used to embed manually and
# automatically grafana)
schema: http
# -- (string) The service host name to access grafana (used to embed manually and
# automatically Grafana).
# The parameter value should point to the grafana service following the
# [DNS reference](https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/) `svc_name.namespace`
webHost:
# -- The datasource name used to create the StackGres Dashboards into Grafana
datasourceName: Prometheus
# -- The username to access Grafana. By default admin. (used to embed automatically
# Grafana)
user: admin
# -- The password to access Grafana. By default prom-operator (the default in for
# kube-prometheus-stack helm chart). (used to embed automatically Grafana)
password: prom-operator
# -- Use follwing fields to indicate a secret where the grafana admin credentials are stored (replace user/password)
# -- (string) The namespace of secret with credentials to access Grafana. (used to
# embed automatically Grafana, alternative to use `user` and `password`)
secretNamespace:
# -- (string) The name of secret with credentials to access Grafana. (used to embed
# automatically Grafana, alternative to use `user` and `password`)
secretName:
# -- (string) The key of secret with username used to access Grafana. (used to embed
# automatically Grafana, alternative to use `user` and `password`)
secretUserKey:
# -- (string) The key of secret with password used to access Grafana. (used to
# embed automatically Grafana, alternative to use `user` and `password`)
secretPasswordKey:
# -- (string) The ConfigMap name with the dashboard JSONs
# that will be created in Grafana. If not set the default
# StackGres dashboards will be created. (used to embed automatically Grafana)
dashboardConfigMap:
# -- (array) The URLs of the PostgreSQL dashboards created in Grafana (used to embed manually
# Grafana). It must contain an entry for each JSON file under `grafana-dashboards` folder: `archiving.json`,
# `connection-pooling.json`, `current-activity.json`, `db-info.json`, `db-objects.json`, `db-os.json`, `queries.json`
# and `replication.json`
urls:
# Create and copy/paste grafana API token:
# - Grafana > Configuration > API Keys > Add API key (for viewer) > Copy key value
# -- (string) The Grafana API token to access the PostgreSQL dashboards created
# in Grafana (used to embed manually Grafana)
token:
# Section to configure extensions
extensions:
# -- A list of extensions repository URLs used to retrieve extensions
#
# To set a proxy for extensions repository add parameter proxyUrl to the URL:
# `https://extensions.stackgres.io/postgres/repository?proxyUrl=<proxy scheme>%3A%2F%2F<proxy host>[%3A<proxy port>]` (URL encoded)
#
# Other URL parameters are:
#
# * `skipHostnameVerification`: set it to `true` in order to use a server or a proxy with a self signed certificate
# * `retry`: set it to `<max retriex>[:<sleep before next retry>]` in order to retry a request on failure
# * `setHttpScheme`: set it to `true` in order to force using HTTP scheme
repositoryUrls:
- https://extensions.stackgres.io/postgres/repository
# Section to configure extensions cache (experimental).
#
# This feature is in beta and may cause failures, please use with caution and report any
# error to https://gitlab.com/ongresinc/stackgres/-/issues/new
cache:
# -- When set to `true` enable the extensions cache.
#
# This feature is in beta and may cause failures, please use with caution and report any
# error to https://gitlab.com/ongresinc/stackgres/-/issues/new
enabled: false
# -- An array of extensions pattern used to pre-loaded estensions into the extensions cache
preloadedExtensions:
- x86_64/linux/timescaledb-1\.7\.4-pg12
# Section to configure the extensions cache PersistentVolume
persistentVolume:
# -- The PersistentVolume size for the extensions cache
#
# Only use whole numbers (e.g. not 1e6) and K/Ki/M/Mi/G/Gi as units
size: 1Gi
# -- (string) If defined set storage class
# If set to "-" (equivalent to storageClass: "" in a PV spec) disables
# dynamic provisioning
# If undefined (the default) or set to null, no storageClass spec is
# set, choosing the default provisioner. (gp2 on AWS, standard on
# GKE, AWS & OpenStack)
storageClass:
# -- (string) If set, will use a host path volume with the specified path for the extensions cache
# instead of a PersistentVolume
hostPath:
# Following options are for developers only, but can also be useful in some cases ;)
# Section to configure developer options.
developer:
# -- (string) Set the operator version (used for testing)
version:
# -- (string) Set `quarkus.log.level`. See https://quarkus.io/guides/logging#root-logger-configuration
logLevel:
# -- If set to `true` add extra debug to any script controlled by the reconciliation cycle of the operator configuration
showDebug: false
# -- Set `quarkus.log.console.format` to `%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p [%c{4.}] (%t) %s%e%n`. See https://quarkus.io/guides/logging#logging-format
showStackTraces: false
# -- Only work with JVM version and allow connect
# on port 8000 of operator Pod with jdb or similar
enableJvmDebug: false
# -- Only work with JVM version and if `enableJvmDebug` is `true`
# suspend the JVM until a debugger session is started
enableJvmDebugSuspend: false
# -- (string) Set the external Operator IP
externalOperatorIp:
# -- (integer) Set the external Operator port
externalOperatorPort:
# -- (string) Set the external REST API IP
externalRestApiIp:
# -- (integer) Set the external REST API port
externalRestApiPort:
# -- If set to `true` and `extensions.cache.enabled` is also `true`
# it will try to download extensions from images (experimental)
allowPullExtensionsFromImageRepository: false
# -- It set to `true` disable arbitrary user that is set for OpenShift clusters
disableArbitraryUser: false
# Section to define patches for some StackGres Pods
patches:
# Section to define volumes to be used by the operator container
operator:
# -- Pod volumes. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#volume-v1-core
volumes: []
# -- Pod's container volume mounts. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#volumemount-v1-core
volumeMounts: []
# Section to define volumes to be used by the restapi container
restapi:
# -- Pod volumes. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#volume-v1-core
volumes: []
# -- Pod's container volume mounts. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#volumemount-v1-core
volumeMounts: []
# Section to define volumes to be used by the adminui container
adminui:
# -- Pod volumes. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#volume-v1-core
volumes: []
# -- Pod's container volume mounts. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#volumemount-v1-core
volumeMounts: []
# Section to define volumes to be used by the jobs container
jobs:
# -- Pod volumes. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#volume-v1-core
volumes: []
# -- Pod's container volume mounts. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#volumemount-v1-core
volumeMounts: []
# Section to define volumes to be used by the cluster controller container
clusterController:
# -- Pod volumes. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#volume-v1-core
volumes: []
# -- Pod's container volume mounts. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#volumemount-v1-core
volumeMounts: []
# Section to define volumes to be used by the distributedlogs controller container
distributedlogsController:
# -- Pod volumes. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#volume-v1-core
volumes: []
# -- Pod's container volume mounts. See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#volumemount-v1-core
volumeMounts: []