diff --git a/.husky.toml b/.husky.toml new file mode 100644 index 0000000..6b70cba --- /dev/null +++ b/.husky.toml @@ -0,0 +1,23 @@ +[hooks] + +# git hook pre commit +pre-commit = [ + "go mod tidy -go=1.23", + "go run mage.go FetchImageMeta", + "go run mage.go CRDs", + "go run mage.go CRDDocs", + "husky lint-staged", + # "golangci-lint run", +] + +# git hook commit msg +commit-msg = [ + "husky lint-commit", +] + +# list staged files do some pre-process and git add +[lint-staged] +"*.go" = [ + "goimports -l -w", + "gofumpt -l -w", +] diff --git a/assets/migrations/migrations/20241215003910_backfill_pgmq_metadata.sql b/assets/migrations/migrations/20241215003910_backfill_pgmq_metadata.sql new file mode 100644 index 0000000..5785272 --- /dev/null +++ b/assets/migrations/migrations/20241215003910_backfill_pgmq_metadata.sql @@ -0,0 +1,79 @@ +-- migrate:up +do $$ +begin + -- Check if the pgmq.meta table exists + if exists ( + select + 1 + from + pg_catalog.pg_class c + join pg_catalog.pg_namespace n + on c.relnamespace = n.oid + where + n.nspname = 'pgmq' + and c.relname = 'meta' + and c.relkind = 'r' -- regular table + -- Make sure only expected columns exist and are correctly named + and ( + select array_agg(attname::text order by attname) + from pg_catalog.pg_attribute a + where + a.attnum > 0 + and a.attrelid = c.oid + ) = array['created_at', 'is_partitioned', 'is_unlogged', 'queue_name']::text[] + ) then + -- Insert data into pgmq.meta for all tables matching the naming pattern 'pgmq.q_' + insert into pgmq.meta (queue_name, is_partitioned, is_unlogged, created_at) + select + substring(c.relname from 3) as queue_name, + false as is_partitioned, + case when c.relpersistence = 'u' then true else false end as is_unlogged, + now() as created_at + from + pg_catalog.pg_class c + join pg_catalog.pg_namespace n + on c.relnamespace = n.oid + where + n.nspname = 'pgmq' + and c.relname like 'q_%' + and c.relkind in ('r', 'p', 'u') + on conflict (queue_name) do nothing; + end if; +end $$; + +-- For logical backups we detach the queue and archive tables from the pgmq extension +-- prior to pausing. Once detached, pgmq.drop_queue breaks. This re-attaches them +-- when a project is unpaused and allows pgmq.drop_queue to work normally. +do $$ +declare + ext_exists boolean; + tbl record; +begin + -- check if pgmq extension is installed + select exists(select 1 from pg_extension where extname = 'pgmq') into ext_exists; + + if ext_exists then + for tbl in + select c.relname as table_name + from pg_class c + join pg_namespace n on c.relnamespace = n.oid + where n.nspname = 'pgmq' + and c.relkind in ('r', 'u') -- include ordinary and unlogged tables + and (c.relname like 'q\_%' or c.relname like 'a\_%') + and c.oid not in ( + select d.objid + from pg_depend d + join pg_extension e on d.refobjid = e.oid + where e.extname = 'pgmq' + and d.classid = 'pg_class'::regclass + and d.deptype = 'e' + ) + loop + execute format('alter extension pgmq add table pgmq.%I', tbl.table_name); + end loop; + end if; +end; +$$; + + +-- migrate:down diff --git a/docs/api/supabase.k8s.icb4dc0.de.md b/docs/api/supabase.k8s.icb4dc0.de.md index 16d1906..9fb7b48 100644 --- a/docs/api/supabase.k8s.icb4dc0.de.md +++ b/docs/api/supabase.k8s.icb4dc0.de.md @@ -13,6 +13,8 @@ Package v1alpha1 contains API Schema definitions for the supabase v1alpha1 API g - [APIGatewayList](#apigatewaylist) - [Core](#core) - [CoreList](#corelist) +- [Dashboard](#dashboard) +- [DashboardList](#dashboardlist) @@ -168,7 +170,7 @@ _Appears in:_ | `image` _string_ | | | | | `pullPolicy` _[PullPolicy](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#pullpolicy-v1-core)_ | | | | | `imagePullSecrets` _[LocalObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#localobjectreference-v1-core) array_ | | | | -| `securityContext` _[SecurityContext](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#securitycontext-v1-core)_ | | | | +| `securityContext` _[SecurityContext](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#securitycontext-v1-core)_ | SecurityContext - | | | | `resources` _[ResourceRequirements](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#resourcerequirements-v1-core)_ | | | | | `volumeMounts` _[VolumeMount](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#volumemount-v1-core) array_ | | | | | `additionalEnv` _[EnvVar](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#envvar-v1-core) array_ | | | | @@ -282,6 +284,82 @@ _Appears in:_ +#### Dashboard + + + +Dashboard is the Schema for the dashboards API. + + + +_Appears in:_ +- [DashboardList](#dashboardlist) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `apiVersion` _string_ | `supabase.k8s.icb4dc0.de/v1alpha1` | | | +| `kind` _string_ | `Dashboard` | | | +| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | | | +| `spec` _[DashboardSpec](#dashboardspec)_ | | | | + + +#### DashboardDbSpec + + + + + + + +_Appears in:_ +- [DashboardSpec](#dashboardspec) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `host` _string_ | | | | +| `port` _integer_ | Port - Database port, typically 5432 | 5432 | | +| `dbName` _string_ | | | | +| `dbCredentialsRef` _[LocalObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#localobjectreference-v1-core)_ | DBCredentialsRef - reference to a Secret key where the DB credentials can be retrieved from
Credentials need to be stored in basic auth form | | | + + +#### DashboardList + + + +DashboardList contains a list of Dashboard. + + + + + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `apiVersion` _string_ | `supabase.k8s.icb4dc0.de/v1alpha1` | | | +| `kind` _string_ | `DashboardList` | | | +| `metadata` _[ListMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#listmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | | | +| `items` _[Dashboard](#dashboard) array_ | | | | + + +#### DashboardSpec + + + +DashboardSpec defines the desired state of Dashboard. + + + +_Appears in:_ +- [Dashboard](#dashboard) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `db` _[DashboardDbSpec](#dashboarddbspec)_ | | | | +| `pgMeta` _[PGMetaSpec](#pgmetaspec)_ | PGMeta | \{ \} | | +| `studio` _[StudioSpec](#studiospec)_ | Studio | \{ \} | | + + + + #### Database @@ -330,10 +408,11 @@ _Appears in:_ | Field | Description | Default | Validation | | --- | --- | --- | --- | -| `authenticator` _[SecretReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#secretreference-v1-core)_ | | | | -| `supabaseAuthAdmin` _[SecretReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#secretreference-v1-core)_ | | | | -| `supabaseFunctionsAdmin` _[SecretReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#secretreference-v1-core)_ | | | | -| `supabaseStorageAdmin` _[SecretReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#secretreference-v1-core)_ | | | | +| `supabaseAdmin` _[LocalObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#localobjectreference-v1-core)_ | | | | +| `authenticator` _[LocalObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#localobjectreference-v1-core)_ | | | | +| `supabaseAuthAdmin` _[LocalObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#localobjectreference-v1-core)_ | | | | +| `supabaseFunctionsAdmin` _[LocalObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#localobjectreference-v1-core)_ | | | | +| `supabaseStorageAdmin` _[LocalObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#localobjectreference-v1-core)_ | | | | #### DatabaseStatus @@ -501,6 +580,22 @@ _Appears in:_ | `url` _string_ | | | | +#### PGMetaSpec + + + + + + + +_Appears in:_ +- [DashboardSpec](#dashboardspec) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `workloadTemplate` _[WorkloadTemplate](#workloadtemplate)_ | WorkloadTemplate - customize the pg-meta deployment | | | + + #### PhoneAuthProvider @@ -530,13 +625,29 @@ _Appears in:_ | Field | Description | Default | Validation | | --- | --- | --- | --- | -| `schemas` _string array_ | Schemas - schema where PostgREST is looking for objects (tables, views, functions, ...) | [public graphql_public] | UniqueItems: true
| -| `extraSearchPath` _string array_ | ExtraSearchPath - Extra schemas to add to the search_path of every request.
These schemas tables, views and functions don’t get API endpoints, they can only be referred from the database objects inside your db-schemas. | [public extensions] | UniqueItems: true
| +| `schemas` _string array_ | Schemas - schema where PostgREST is looking for objects (tables, views, functions, ...) | [public graphql_public] | | +| `extraSearchPath` _string array_ | ExtraSearchPath - Extra schemas to add to the search_path of every request.
These schemas tables, views and functions don’t get API endpoints, they can only be referred from the database objects inside your db-schemas. | [public extensions] | | | `anonRole` _string_ | AnonRole - name of the anon role | anon | | | `maxRows` _integer_ | MaxRows - maximum number of rows PostgREST will load at a time | 1000 | | | `workloadTemplate` _[WorkloadTemplate](#workloadtemplate)_ | WorkloadTemplate - customize the PostgREST workload | | | +#### StudioSpec + + + + + + + +_Appears in:_ +- [DashboardSpec](#dashboardspec) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `workloadTemplate` _[WorkloadTemplate](#workloadtemplate)_ | WorkloadTemplate - customize the studio deployment | | | + + #### WorkloadTemplate @@ -548,13 +659,15 @@ _Appears in:_ _Appears in:_ - [AuthSpec](#authspec) - [EnvoySpec](#envoyspec) +- [PGMetaSpec](#pgmetaspec) - [PostgrestSpec](#postgrestspec) +- [StudioSpec](#studiospec) | Field | Description | Default | Validation | | --- | --- | --- | --- | | `replicas` _integer_ | | | | | `securityContext` _[PodSecurityContext](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#podsecuritycontext-v1-core)_ | | | | | `additionalLabels` _object (keys:string, values:string)_ | | | | -| `workload` _[ContainerTemplate](#containertemplate)_ | | | | +| `workload` _[ContainerTemplate](#containertemplate)_ | Workload - customize the container template of the workload | | | diff --git a/go.mod b/go.mod index 10b7ee2..a9567af 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,8 @@ module code.icb4dc0.de/prskr/supabase-operator -go 1.23.4 +go 1.23 + +toolchain go1.23.4 require ( github.com/alecthomas/kong v1.6.0