Merge branch 'master' into fix-deployment-instability
This commit is contained in:
commit
79819795c1
|
@ -1,9 +1,6 @@
|
|||
dependencies:
|
||||
- name: couchdb
|
||||
repository: https://apache.github.io/couchdb-helm
|
||||
version: 3.3.4
|
||||
- name: ingress-nginx
|
||||
repository: https://kubernetes.github.io/ingress-nginx
|
||||
version: 4.0.13
|
||||
digest: sha256:20892705c2d8e64c98257d181063a514ac55013e2b43399a6e54868a97f97845
|
||||
generated: "2021-12-30T18:55:30.878411Z"
|
||||
version: 4.3.0
|
||||
digest: sha256:94449a7f195b186f5af33ec5aa66d58b36bede240fae710f021ca87837b30606
|
||||
generated: "2023-11-20T17:43:02.777596Z"
|
||||
|
|
|
@ -17,10 +17,6 @@ version: 0.0.0
|
|||
appVersion: 0.0.0
|
||||
dependencies:
|
||||
- name: couchdb
|
||||
version: 3.3.4
|
||||
version: 4.3.0
|
||||
repository: https://apache.github.io/couchdb-helm
|
||||
condition: services.couchdb.enabled
|
||||
- name: ingress-nginx
|
||||
version: 4.0.13
|
||||
repository: https://kubernetes.github.io/ingress-nginx
|
||||
condition: ingress.nginx
|
||||
|
|
|
@ -1,39 +1,216 @@
|
|||
# Budibase
|
||||
# budibase
|
||||
|
||||
[Budibase](https://budibase.com/) Budibase is an open source low-code platform, helping thousands of teams build apps for their workplace in minutes.
|
||||
|
||||
## TL;DR;
|
||||
```console
|
||||
$ cd chart
|
||||
$ helm install budibase .
|
||||
```
|
||||
|
||||
## Introduction
|
||||
|
||||
This chart bootstraps a [Budibase](https://budibase.com/) deployment on a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager.
|
||||
Budibase is an open source low-code platform, helping thousands of teams build apps for their workplace in minutes.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- helm v3 or above
|
||||
- `helm` v3 or above
|
||||
- Kubernetes 1.4+
|
||||
- PV provisioner support in the underlying infrastructure (with persistence storage enabled)
|
||||
- A storage controller (if you want to use persistent storage)
|
||||
- An ingress controller (if you want to define an `Ingress` resource)
|
||||
- `metrics-server` (if you want to make use of horizontal pod autoscaling)
|
||||
|
||||
## Installing the Chart
|
||||
## Chart dependencies
|
||||
|
||||
To install the chart with the release name `budi-release`:
|
||||
This chart depends on the official Apache CouchDB chart. You can see its
|
||||
documentation here:
|
||||
<https://github.com/apache/couchdb-helm/tree/couchdb-4.3.0/couchdb>.
|
||||
|
||||
## Upgrading
|
||||
|
||||
### `2.x` to `3.0.0`
|
||||
|
||||
We made a number of breaking changes in this release to make the chart more
|
||||
idiomatic and easier to use.
|
||||
|
||||
1. We no longer bundle `ingress-nginx`. If you were relying on this to supply
|
||||
an ingress controller to your cluster, you will now need to deploy that
|
||||
separately. You'll find guidance for that here:
|
||||
<https://kubernetes.github.io/ingress-nginx/>.
|
||||
2. We've upgraded the version of the [CouchDB chart](https://github.com/apache/couchdb-helm)
|
||||
we use from `3.3.4` to `4.3.0`. The primary motivation for this was to align
|
||||
the CouchDB chart used with the CouchDB version used, which has also updated
|
||||
from 3.1.1 to 3.2.1. Additionally, we're moving away from the official CouchDB
|
||||
to one we're building ourselves.
|
||||
3. We've separated out the supplied AWS ALB ingress resource for those deploying
|
||||
into EKS. Where previously you enabled this by setting `ingress.enabled: false`
|
||||
and `ingress.aws: true`, you now set `awsAlbIngress.enabled: true` and all
|
||||
configuration for it is under `awsAlbIngress`.
|
||||
4. The `HorizontalPodAutoscaler` that was configured at `hpa.enabled: true` has
|
||||
been split into 3 separate HPAs, one for each of `apps`, `worker`, and `proxy`.
|
||||
They are configured at `services.{apps,worker,proxy}.autoscaling`.
|
||||
|
||||
## Installing
|
||||
|
||||
To install the chart from our repository:
|
||||
|
||||
```console
|
||||
$ helm install budi-release .
|
||||
$ helm repo add budibase https://budibase.github.io/budibase/
|
||||
$ helm repo update
|
||||
$ helm install --create-namespace --namespace budibase budibase budibase/budibase
|
||||
```
|
||||
|
||||
The command deploys Budibase on the Kubernetes cluster in the default configuration. The [configuration](#configuration) section lists the parameters that can be configured during installation.
|
||||
|
||||
> **Tip**: List all releases using `helm list`
|
||||
|
||||
## Uninstalling the Chart
|
||||
|
||||
To uninstall/delete the `my-release` deployment:
|
||||
To install the chart from this repo:
|
||||
|
||||
```console
|
||||
$ helm delete my-release
|
||||
$ git clone git@github.com:budibase/budibase.git
|
||||
$ cd budibase/charts/budibase
|
||||
$ helm install --create-namespace --namespace budibase budibase .
|
||||
```
|
||||
|
||||
## Example minimal configuration
|
||||
|
||||
Here's an example `values.yaml` that would get a Budibase instance running in a home
|
||||
cluster using an nginx ingress controller and NFS as cluster storage (basically one of our
|
||||
staff's homelabs).
|
||||
|
||||
<details>
|
||||
|
||||
```yaml
|
||||
ingress:
|
||||
enabled: true
|
||||
className: "nginx"
|
||||
hosts:
|
||||
- host: budibase.local # set this to whatever DNS name you'd use
|
||||
paths:
|
||||
- backend:
|
||||
service:
|
||||
name: proxy-service
|
||||
port:
|
||||
number: 10000
|
||||
path: /
|
||||
pathType: Prefix
|
||||
|
||||
couchdb:
|
||||
persistentVolume:
|
||||
enabled: true
|
||||
storageClass: "nfs-client"
|
||||
adminPassword: admin
|
||||
|
||||
objectStore:
|
||||
storageClass: "nfs-client"
|
||||
redis:
|
||||
storageClass: "nfs-client"
|
||||
```
|
||||
|
||||
If you wanted to use this when bringing up Budibase in your own cluster, you could save it
|
||||
to your hard disk and run the following:
|
||||
|
||||
```console
|
||||
$ helm install --create-namespace --namespace budibase budibase . -f values.yaml
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
## Configuring
|
||||
|
||||
| Key | Type | Default | Description |
|
||||
|-----|------|---------|-------------|
|
||||
| affinity | object | `{}` | Sets the affinity for all pods created by this chart. Should not ordinarily need to be changed. See <https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes-using-node-affinity/> for more information on affinity. |
|
||||
| awsAlbIngress.certificateArn | string | `""` | If you're wanting to use HTTPS, you'll need to create an ACM certificate and specify the ARN here. |
|
||||
| awsAlbIngress.enabled | bool | `false` | Whether to create an ALB Ingress resource pointing to the Budibase proxy. Requires the AWS ALB Ingress Controller. |
|
||||
| couchdb.clusterSize | int | `1` | The number of replicas to run in the CouchDB cluster. We set this to 1 by default to make things simpler, but you can set it to 3 if you need a high-availability CouchDB cluster. |
|
||||
| couchdb.couchdbConfig.couchdb.uuid | string | `"budibase-couchdb"` | Unique identifier for this CouchDB server instance. You shouldn't need to change this. |
|
||||
| couchdb.image | object | `{}` | We use a custom CouchDB image for running Budibase and we don't support using any other CouchDB image. You shouldn't change this, and if you do we can't guarantee that Budibase will work. |
|
||||
| globals.apiEncryptionKey | string | `""` | Used for encrypting API keys and environment variables when stored in the database. You don't need to set this if `createSecrets` is true. |
|
||||
| globals.appVersion | string | `""` | The version of Budibase to deploy. Defaults to what's specified by {{ .Chart.AppVersion }}. Ends up being used as the image version tag for the apps, proxy, and worker images. |
|
||||
| globals.automationMaxIterations | string | `"200"` | The maximum number of iterations allows for an automation loop step. You can read more about looping here: <https://docs.budibase.com/docs/looping>. |
|
||||
| globals.budibaseEnv | string | `"PRODUCTION"` | Sets the environment variable BUDIBASE_ENVIRONMENT for the apps and worker pods. Should not ordinarily need to be changed. |
|
||||
| globals.cookieDomain | string | `""` | Sets the domain attribute of the cookie that Budibase uses to store session information. See <https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#define_where_cookies_are_sent> for details on why you might want to set this. |
|
||||
| globals.createSecrets | bool | `true` | Create an internal API key, JWT secret, object store access key and secret, and store them in a Kubernetes `Secret`. |
|
||||
| globals.enableAnalytics | string | `"1"` | Whether to enable analytics or not. You can read more about our analytics here: <https://docs.budibase.com/docs/analytics>. |
|
||||
| globals.google | object | `{"clientId":"","secret":""}` | Google OAuth settings. These can also be set in the Budibase UI, see <https://docs.budibase.com/docs/sso-with-google> for details. |
|
||||
| globals.google.clientId | string | `""` | Client ID of your Google OAuth app. |
|
||||
| globals.google.secret | string | `""` | Client secret of your Google OAuth app. |
|
||||
| globals.httpMigrations | string | `"0"` | Whether or not to enable doing data migrations over the HTTP API. If this is set to "0", migrations are run on startup. You shouldn't ordinarily need to change this. |
|
||||
| globals.internalApiKey | string | `""` | API key used for internal Budibase API calls. You don't need to set this if `createSecrets` is true. |
|
||||
| globals.internalApiKeyFallback | string | `""` | A fallback value for `internalApiKey`. If you're rotating your encryption key, you can set this to the old value for the duration of the rotation. |
|
||||
| globals.jwtSecret | string | `""` | Secret used for signing JWTs. You don't need to set this if `createSecrets` is true. |
|
||||
| globals.jwtSecretFallback | string | `""` | A fallback value for `jwtSecret`. If you're rotating your JWT secret, you can set this to the old value for the duration of the rotation. |
|
||||
| globals.platformUrl | string | `""` | Set the `platformUrl` binding. You can also do this in Settings > Organisation if you are self-hosting. |
|
||||
| globals.smtp.enabled | bool | `false` | Whether to enable SMTP or not. |
|
||||
| globals.smtp.from | string | `""` | The email address to use in the "From:" field of emails sent by Budibase. |
|
||||
| globals.smtp.host | string | `""` | The hostname of your SMTP server. |
|
||||
| globals.smtp.password | string | `""` | The password to use when authenticating with your SMTP server. |
|
||||
| globals.smtp.port | string | `"587"` | The port of your SMTP server. |
|
||||
| globals.smtp.user | string | `""` | The username to use when authenticating with your SMTP server. |
|
||||
| globals.tenantFeatureFlags | string | `"*:LICENSING,*:USER_GROUPS,*:ONBOARDING_TOUR"` | Sets what feature flags are enabled and for which tenants. Should not ordinarily need to be changed. |
|
||||
| imagePullSecrets | list | `[]` | Passed to all pods created by this chart. Should not ordinarily need to be changed. |
|
||||
| ingress.className | string | `""` | What ingress class to use. |
|
||||
| ingress.enabled | bool | `true` | Whether to create an Ingress resource pointing to the Budibase proxy. |
|
||||
| ingress.hosts | list | `[]` | Standard hosts block for the Ingress resource. Defaults to pointing to the Budibase proxy. |
|
||||
| nameOverride | string | `""` | Override the name of the deploymen. Defaults to {{ .Chart.Name }}. |
|
||||
| service.port | int | `10000` | Port to expose on the service. |
|
||||
| service.type | string | `"ClusterIP"` | Service type for the service that points to the main Budibase proxy pod. |
|
||||
| serviceAccount.annotations | object | `{}` | Annotations to add to the service account |
|
||||
| serviceAccount.create | bool | `true` | Specifies whether a service account should be created |
|
||||
| serviceAccount.name | string | `""` | The name of the service account to use. If not set and create is true, a name is generated using the fullname template |
|
||||
| services.apps.autoscaling.enabled | bool | `false` | Whether to enable horizontal pod autoscaling for the apps service. |
|
||||
| services.apps.autoscaling.maxReplicas | int | `10` | |
|
||||
| services.apps.autoscaling.minReplicas | int | `1` | |
|
||||
| services.apps.autoscaling.targetCPUUtilizationPercentage | int | `80` | Target CPU utilization percentage for the apps service. Note that for autoscaling to work, you will need to have metrics-server configured, and resources set for the apps pods. |
|
||||
| services.apps.httpLogging | int | `1` | Whether or not to log HTTP requests to the apps service. |
|
||||
| services.apps.livenessProbe | object | HTTP health checks. | Liveness probe configuration for apps pods. You shouldn't need to change this, but if you want to you can find more information here: <https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/> |
|
||||
| services.apps.logLevel | string | `"info"` | The log level for the apps service. |
|
||||
| services.apps.readinessProbe | object | HTTP health checks. | Readiness probe configuration for apps pods. You shouldn't need to change this, but if you want to you can find more information here: <https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/> |
|
||||
| services.apps.replicaCount | int | `1` | The number of apps replicas to run. |
|
||||
| services.apps.resources | object | `{}` | The resources to use for apps pods. See <https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/> for more information on how to set these. |
|
||||
| services.apps.startupProbe | object | HTTP health checks. | Startup probe configuration for apps pods. You shouldn't need to change this, but if you want to you can find more information here: <https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/> |
|
||||
| services.couchdb.backup.enabled | bool | `false` | Whether or not to enable periodic CouchDB backups. This works by replicating to another CouchDB instance. |
|
||||
| services.couchdb.backup.interval | string | `""` | Backup interval in seconds |
|
||||
| services.couchdb.backup.resources | object | `{}` | The resources to use for CouchDB backup pods. See <https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/> for more information on how to set these. |
|
||||
| services.couchdb.backup.target | string | `""` | Target couchDB instance to back up to, either a hostname or an IP address. |
|
||||
| services.couchdb.enabled | bool | `true` | Whether or not to spin up a CouchDB instance in your cluster. True by default, and the configuration for the CouchDB instance is under the `couchdb` key at the root of this file. You can see what options are available to you by looking at the official CouchDB Helm chart: <https://github.com/apache/couchdb-helm/tree/couchdb-4.3.0/couchdb>. |
|
||||
| services.couchdb.port | int | `5984` | |
|
||||
| services.dns | string | `"cluster.local"` | The DNS suffix to use for service discovery. You only need to change this if you've configured your cluster to use a different DNS suffix. |
|
||||
| services.objectStore.accessKey | string | `""` | AWS_ACCESS_KEY if using S3 |
|
||||
| services.objectStore.browser | bool | `true` | Whether to enable the Minio web console or not. If you're exposing Minio to the Internet (via a custom Ingress record, for example), you should set this to false. If you're only exposing Minio to your cluster, you can leave this as true. |
|
||||
| services.objectStore.cloudfront.cdn | string | `""` | Set the url of a distribution to enable cloudfront. |
|
||||
| services.objectStore.cloudfront.privateKey64 | string | `""` | Base64 encoded private key for the above public key. |
|
||||
| services.objectStore.cloudfront.publicKeyId | string | `""` | ID of public key stored in cloudfront. |
|
||||
| services.objectStore.minio | bool | `true` | Set to false if using another object store, such as S3. You will need to set `services.objectStore.url` to point to your bucket if you do this. |
|
||||
| services.objectStore.region | string | `""` | AWS_REGION if using S3 |
|
||||
| services.objectStore.resources | object | `{}` | The resources to use for Minio pods. See <https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/> for more information on how to set these. |
|
||||
| services.objectStore.secretKey | string | `""` | AWS_SECRET_ACCESS_KEY if using S3 |
|
||||
| services.objectStore.storage | string | `"100Mi"` | How much storage to give Minio in its PersistentVolumeClaim. |
|
||||
| services.objectStore.storageClass | string | `""` | If defined, storageClassName: <storageClass> If set to "-", storageClassName: "", which disables dynamic provisioning If undefined (the default) or set to null, no storageClassName spec is set, choosing the default provisioner. |
|
||||
| services.objectStore.url | string | `"http://minio-service:9000"` | URL to use for object storage. Only change this if you're using an external object store, such as S3. Remember to set `minio: false` if you do this. |
|
||||
| services.proxy.autoscaling.enabled | bool | `false` | Whether to enable horizontal pod autoscaling for the proxy service. |
|
||||
| services.proxy.autoscaling.maxReplicas | int | `10` | |
|
||||
| services.proxy.autoscaling.minReplicas | int | `1` | |
|
||||
| services.proxy.autoscaling.targetCPUUtilizationPercentage | int | `80` | Target CPU utilization percentage for the proxy service. Note that for autoscaling to work, you will need to have metrics-server configured, and resources set for the proxy pods. |
|
||||
| services.proxy.livenessProbe | object | HTTP health checks. | Liveness probe configuration for proxy pods. You shouldn't need to change this, but if you want to you can find more information here: <https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/> |
|
||||
| services.proxy.readinessProbe | object | HTTP health checks. | Readiness probe configuration for proxy pods. You shouldn't need to change this, but if you want to you can find more information here: <https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/> |
|
||||
| services.proxy.replicaCount | int | `1` | The number of proxy replicas to run. |
|
||||
| services.proxy.resources | object | `{}` | The resources to use for proxy pods. See <https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/> for more information on how to set these. |
|
||||
| services.proxy.startupProbe | object | HTTP health checks. | Startup probe configuration for proxy pods. You shouldn't need to change this, but if you want to you can find more information here: <https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/> |
|
||||
| services.redis.enabled | bool | `true` | Whether or not to deploy a Redis pod into your cluster. |
|
||||
| services.redis.password | string | `"budibase"` | The password to use when connecting to Redis. It's recommended that you change this from the default if you're running Redis in-cluster. |
|
||||
| services.redis.port | int | `6379` | Port to expose Redis on. |
|
||||
| services.redis.resources | object | `{}` | The resources to use for Redis pods. See <https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/> for more information on how to set these. |
|
||||
| services.redis.storage | string | `"100Mi"` | How much persistent storage to allocate to Redis. |
|
||||
| services.redis.storageClass | string | `""` | If defined, storageClassName: <storageClass> If set to "-", storageClassName: "", which disables dynamic provisioning If undefined (the default) or set to null, no storageClassName spec is set, choosing the default provisioner. |
|
||||
| services.redis.url | string | `""` | If you choose to run Redis externally to this chart, you can specify the connection details here. |
|
||||
| services.worker.autoscaling.enabled | bool | `false` | Whether to enable horizontal pod autoscaling for the worker service. |
|
||||
| services.worker.autoscaling.maxReplicas | int | `10` | |
|
||||
| services.worker.autoscaling.minReplicas | int | `1` | |
|
||||
| services.worker.autoscaling.targetCPUUtilizationPercentage | int | `80` | Target CPU utilization percentage for the worker service. Note that for autoscaling to work, you will need to have metrics-server configured, and resources set for the worker pods. |
|
||||
| services.worker.httpLogging | int | `1` | Whether or not to log HTTP requests to the worker service. |
|
||||
| services.worker.livenessProbe | object | HTTP health checks. | Liveness probe configuration for worker pods. You shouldn't need to change this, but if you want to you can find more information here: <https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/> |
|
||||
| services.worker.logLevel | string | `"info"` | The log level for the worker service. |
|
||||
| services.worker.readinessProbe | object | HTTP health checks. | Readiness probe configuration for worker pods. You shouldn't need to change this, but if you want to you can find more information here: <https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/> |
|
||||
| services.worker.replicaCount | int | `1` | The number of worker replicas to run. |
|
||||
| services.worker.resources | object | `{}` | The resources to use for worker pods. See <https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/> for more information on how to set these. |
|
||||
| services.worker.startupProbe | object | HTTP health checks. | Startup probe configuration for worker pods. You shouldn't need to change this, but if you want to you can find more information here: <https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/> |
|
||||
| tolerations | list | `[]` | Sets the tolerations for all pods created by this chart. Should not ordinarily need to be changed. See <https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/> for more information on tolerations. |
|
||||
|
||||
## Uninstalling
|
||||
|
||||
To uninstall the chart, assuming you named the release `budibase` (both commands in the installation section do so):
|
||||
|
||||
```console
|
||||
$ helm uninstall --namespace budibase budibase
|
||||
```
|
||||
|
||||
----------------------------------------------
|
||||
Autogenerated from chart metadata using [helm-docs v1.11.3](https://github.com/norwoodj/helm-docs/releases/v1.11.3)
|
||||
|
|
|
@ -0,0 +1,116 @@
|
|||
{{ template "chart.header" . }}
|
||||
{{ template "chart.description" . }}
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- `helm` v3 or above
|
||||
- Kubernetes 1.4+
|
||||
- A storage controller (if you want to use persistent storage)
|
||||
- An ingress controller (if you want to define an `Ingress` resource)
|
||||
- `metrics-server` (if you want to make use of horizontal pod autoscaling)
|
||||
|
||||
## Chart dependencies
|
||||
|
||||
This chart depends on the official Apache CouchDB chart. You can see its
|
||||
documentation here:
|
||||
<https://github.com/apache/couchdb-helm/tree/couchdb-4.3.0/couchdb>.
|
||||
|
||||
## Upgrading
|
||||
|
||||
### `2.x` to `3.0.0`
|
||||
|
||||
We made a number of breaking changes in this release to make the chart more
|
||||
idiomatic and easier to use.
|
||||
|
||||
1. We no longer bundle `ingress-nginx`. If you were relying on this to supply
|
||||
an ingress controller to your cluster, you will now need to deploy that
|
||||
separately. You'll find guidance for that here:
|
||||
<https://kubernetes.github.io/ingress-nginx/>.
|
||||
2. We've upgraded the version of the [CouchDB chart](https://github.com/apache/couchdb-helm)
|
||||
we use from `3.3.4` to `4.3.0`. The primary motivation for this was to align
|
||||
the CouchDB chart used with the CouchDB version used, which has also updated
|
||||
from 3.1.1 to 3.2.1. Additionally, we're moving away from the official CouchDB
|
||||
to one we're building ourselves.
|
||||
3. We've separated out the supplied AWS ALB ingress resource for those deploying
|
||||
into EKS. Where previously you enabled this by setting `ingress.enabled: false`
|
||||
and `ingress.aws: true`, you now set `awsAlbIngress.enabled: true` and all
|
||||
configuration for it is under `awsAlbIngress`.
|
||||
4. The `HorizontalPodAutoscaler` that was configured at `hpa.enabled: true` has
|
||||
been split into 3 separate HPAs, one for each of `apps`, `worker`, and `proxy`.
|
||||
They are configured at `services.{apps,worker,proxy}.autoscaling`.
|
||||
|
||||
## Installing
|
||||
|
||||
To install the chart from our repository:
|
||||
|
||||
```console
|
||||
$ helm repo add budibase https://budibase.github.io/budibase/
|
||||
$ helm repo update
|
||||
$ helm install --create-namespace --namespace budibase budibase budibase/budibase
|
||||
```
|
||||
|
||||
To install the chart from this repo:
|
||||
|
||||
```console
|
||||
$ git clone git@github.com:budibase/budibase.git
|
||||
$ cd budibase/charts/budibase
|
||||
$ helm install --create-namespace --namespace budibase budibase .
|
||||
```
|
||||
|
||||
## Example minimal configuration
|
||||
|
||||
Here's an example `values.yaml` that would get a Budibase instance running in a home
|
||||
cluster using an nginx ingress controller and NFS as cluster storage (basically one of our
|
||||
staff's homelabs).
|
||||
|
||||
<details>
|
||||
|
||||
```yaml
|
||||
ingress:
|
||||
enabled: true
|
||||
className: "nginx"
|
||||
hosts:
|
||||
- host: budibase.local # set this to whatever DNS name you'd use
|
||||
paths:
|
||||
- backend:
|
||||
service:
|
||||
name: proxy-service
|
||||
port:
|
||||
number: 10000
|
||||
path: /
|
||||
pathType: Prefix
|
||||
|
||||
couchdb:
|
||||
persistentVolume:
|
||||
enabled: true
|
||||
storageClass: "nfs-client"
|
||||
adminPassword: admin
|
||||
|
||||
objectStore:
|
||||
storageClass: "nfs-client"
|
||||
redis:
|
||||
storageClass: "nfs-client"
|
||||
```
|
||||
|
||||
If you wanted to use this when bringing up Budibase in your own cluster, you could save it
|
||||
to your hard disk and run the following:
|
||||
|
||||
```console
|
||||
$ helm install --create-namespace --namespace budibase budibase . -f values.yaml
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
## Configuring
|
||||
|
||||
{{ template "chart.valuesTable" . }}
|
||||
|
||||
## Uninstalling
|
||||
|
||||
To uninstall the chart, assuming you named the release `budibase` (both commands in the installation section do so):
|
||||
|
||||
```console
|
||||
$ helm uninstall --namespace budibase budibase
|
||||
```
|
||||
|
||||
{{ template "helm-docs.versionFooter" . }}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,4 +1,4 @@
|
|||
{{- if .Values.ingress.aws }}
|
||||
{{- if .Values.awsAlbIngress.enabled }}
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
|
@ -9,22 +9,22 @@ metadata:
|
|||
alb.ingress.kubernetes.io/target-type: ip
|
||||
alb.ingress.kubernetes.io/success-codes: '200'
|
||||
alb.ingress.kubernetes.io/healthcheck-path: '/health'
|
||||
{{- if .Values.ingress.certificateArn }}
|
||||
{{- if .Values.awsAlbIngress.certificateArn }}
|
||||
alb.ingress.kubernetes.io/actions.ssl-redirect: '{"Type": "redirect", "RedirectConfig": { "Protocol": "HTTPS", "Port": "443", "StatusCode": "HTTP_301"}}'
|
||||
alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS":443}]'
|
||||
alb.ingress.kubernetes.io/certificate-arn: {{ .Values.ingress.certificateArn }}
|
||||
alb.ingress.kubernetes.io/certificate-arn: {{ .Values.awsAlbIngress.certificateArn }}
|
||||
{{- end }}
|
||||
{{- if .Values.ingress.sslPolicy }}
|
||||
alb.ingress.kubernetes.io/actions.ssl-policy: {{ .Values.ingress.sslPolicy }}
|
||||
{{- if .Values.awsAlbIngress.sslPolicy }}
|
||||
alb.ingress.kubernetes.io/actions.ssl-policy: {{ .Values.awsAlbIngress.sslPolicy }}
|
||||
{{- end }}
|
||||
{{- if .Values.ingress.securityGroups }}
|
||||
alb.ingress.kubernetes.io/security-groups: {{ .Values.ingress.securityGroups }}
|
||||
{{- if .Values.awsAlbIngress.securityGroups }}
|
||||
alb.ingress.kubernetes.io/security-groups: {{ .Values.awsAlbIngress.securityGroups }}
|
||||
{{- end }}
|
||||
spec:
|
||||
rules:
|
||||
- http:
|
||||
paths:
|
||||
{{- if .Values.ingress.certificateArn }}
|
||||
{{- if .Values.awsAlbIngress.certificateArn }}
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
|
|
|
@ -2,12 +2,9 @@ apiVersion: apps/v1
|
|||
kind: Deployment
|
||||
metadata:
|
||||
annotations:
|
||||
kompose.cmd: kompose convert
|
||||
kompose.version: 1.21.0 (992df58d8)
|
||||
{{ if .Values.services.apps.deploymentAnnotations }}
|
||||
{{- toYaml .Values.services.apps.deploymentAnnotations | indent 4 -}}
|
||||
{{ end }}
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
io.kompose.service: app-service
|
||||
{{ if .Values.services.apps.deploymentLabels }}
|
||||
|
@ -24,12 +21,9 @@ spec:
|
|||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
kompose.cmd: kompose convert
|
||||
kompose.version: 1.21.0 (992df58d8)
|
||||
{{ if .Values.services.apps.templateAnnotations }}
|
||||
{{- toYaml .Values.services.apps.templateAnnotations | indent 8 -}}
|
||||
{{ end }}
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
io.kompose.service: app-service
|
||||
{{ if .Values.services.apps.templateLabels }}
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
{{- if .Values.services.apps.autoscaling.enabled }}
|
||||
apiVersion: {{ ternary "autoscaling/v2" "autoscaling/v2beta2" (.Capabilities.APIVersions.Has "autoscaling/v2") }}
|
||||
kind: HorizontalPodAutoscaler
|
||||
metadata:
|
||||
name: {{ include "budibase.fullname" . }}-apps
|
||||
labels:
|
||||
{{- include "budibase.labels" . | nindent 4 }}
|
||||
spec:
|
||||
scaleTargetRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: app-service
|
||||
minReplicas: {{ .Values.services.apps.autoscaling.minReplicas }}
|
||||
maxReplicas: {{ .Values.services.apps.autoscaling.maxReplicas }}
|
||||
metrics:
|
||||
{{- if .Values.services.apps.autoscaling.targetCPUUtilizationPercentage }}
|
||||
- type: Resource
|
||||
resource:
|
||||
name: cpu
|
||||
target:
|
||||
type: Utilization
|
||||
averageUtilization: {{ .Values.services.apps.autoscaling.targetCPUUtilizationPercentage }}
|
||||
{{- end }}
|
||||
{{- if .Values.services.apps.autoscaling.targetMemoryUtilizationPercentage }}
|
||||
- type: Resource
|
||||
resource:
|
||||
name: memory
|
||||
target:
|
||||
type: Utilization
|
||||
averageUtilization: {{ .Values.services.apps.autoscaling.targetMemoryUtilizationPercentage }}
|
||||
{{- end }}
|
||||
{{- end }}
|
|
@ -1,10 +1,6 @@
|
|||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
annotations:
|
||||
kompose.cmd: kompose convert
|
||||
kompose.version: 1.21.0 (992df58d8)
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
io.kompose.service: app-service
|
||||
name: app-service
|
||||
|
|
|
@ -2,10 +2,6 @@
|
|||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
annotations:
|
||||
kompose.cmd: kompose convert
|
||||
kompose.version: 1.21.0 (992df58d8)
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
app.kubernetes.io/name: couchdb-backup
|
||||
name: couchdb-backup
|
||||
|
@ -18,10 +14,6 @@ spec:
|
|||
type: Recreate
|
||||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
kompose.cmd: kompose convert
|
||||
kompose.version: 1.21.0 (992df58d8)
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
app.kubernetes.io/name: couchdb-backup
|
||||
spec:
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
{{- if .Values.autoscaling.enabled }}
|
||||
apiVersion: autoscaling/v2beta1
|
||||
kind: HorizontalPodAutoscaler
|
||||
metadata:
|
||||
name: {{ include "budibase.fullname" . }}
|
||||
labels:
|
||||
{{- include "budibase.labels" . | nindent 4 }}
|
||||
spec:
|
||||
scaleTargetRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: {{ include "budibase.fullname" . }}
|
||||
minReplicas: {{ .Values.autoscaling.minReplicas }}
|
||||
maxReplicas: {{ .Values.autoscaling.maxReplicas }}
|
||||
metrics:
|
||||
{{- if .Values.autoscaling.targetCPUUtilizationPercentage }}
|
||||
- type: Resource
|
||||
resource:
|
||||
name: cpu
|
||||
targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }}
|
||||
{{- end }}
|
||||
{{- if .Values.autoscaling.targetMemoryUtilizationPercentage }}
|
||||
- type: Resource
|
||||
resource:
|
||||
name: memory
|
||||
targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }}
|
||||
{{- end }}
|
||||
{{- end }}
|
|
@ -2,7 +2,6 @@
|
|||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
io.kompose.service: minio-data
|
||||
name: minio-data
|
||||
|
|
|
@ -2,10 +2,6 @@
|
|||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
annotations:
|
||||
kompose.cmd: kompose convert
|
||||
kompose.version: 1.21.0 (992df58d8)
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
io.kompose.service: minio-service
|
||||
name: minio-service
|
||||
|
@ -18,10 +14,6 @@ spec:
|
|||
type: Recreate
|
||||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
kompose.cmd: kompose convert
|
||||
kompose.version: 1.21.0 (992df58d8)
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
io.kompose.service: minio-service
|
||||
spec:
|
||||
|
|
|
@ -2,10 +2,6 @@
|
|||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
annotations:
|
||||
kompose.cmd: kompose convert
|
||||
kompose.version: 1.21.0 (992df58d8)
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
io.kompose.service: minio-service
|
||||
name: minio-service
|
||||
|
|
|
@ -2,12 +2,9 @@ apiVersion: apps/v1
|
|||
kind: Deployment
|
||||
metadata:
|
||||
annotations:
|
||||
kompose.cmd: kompose convert
|
||||
kompose.version: 1.21.0 (992df58d8)
|
||||
{{ if .Values.services.proxy.deploymentAnnotations }}
|
||||
{{- toYaml .Values.services.proxy.deploymentAnnotations | indent 4 -}}
|
||||
{{ end }}
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
app.kubernetes.io/name: budibase-proxy
|
||||
{{ if .Values.services.proxy.deploymentLabels }}
|
||||
|
@ -25,12 +22,9 @@ spec:
|
|||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
kompose.cmd: kompose convert
|
||||
kompose.version: 1.21.0 (992df58d8)
|
||||
{{ if .Values.services.proxy.templateAnnotations }}
|
||||
{{- toYaml .Values.services.proxy.templateAnnotations | indent 8 -}}
|
||||
{{ end }}
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
app.kubernetes.io/name: budibase-proxy
|
||||
{{ if .Values.services.proxy.templateLabels }}
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
{{- if .Values.services.proxy.autoscaling.enabled }}
|
||||
apiVersion: {{ ternary "autoscaling/v2" "autoscaling/v2beta2" (.Capabilities.APIVersions.Has "autoscaling/v2") }}
|
||||
kind: HorizontalPodAutoscaler
|
||||
metadata:
|
||||
name: {{ include "budibase.fullname" . }}-proxy
|
||||
labels:
|
||||
{{- include "budibase.labels" . | nindent 4 }}
|
||||
spec:
|
||||
scaleTargetRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: proxy-service
|
||||
minReplicas: {{ .Values.services.proxy.autoscaling.minReplicas }}
|
||||
maxReplicas: {{ .Values.services.proxy.autoscaling.maxReplicas }}
|
||||
metrics:
|
||||
{{- if .Values.services.proxy.autoscaling.targetCPUUtilizationPercentage }}
|
||||
- type: Resource
|
||||
resource:
|
||||
name: cpu
|
||||
target:
|
||||
type: Utilization
|
||||
averageUtilization: {{ .Values.services.proxy.autoscaling.targetCPUUtilizationPercentage }}
|
||||
{{- end }}
|
||||
{{- if .Values.services.proxy.autoscaling.targetMemoryUtilizationPercentage }}
|
||||
- type: Resource
|
||||
resource:
|
||||
name: memory
|
||||
target:
|
||||
type: Utilization
|
||||
averageUtilization: {{ .Values.services.proxy.autoscaling.targetMemoryUtilizationPercentage }}
|
||||
{{- end }}
|
||||
{{- end }}
|
|
@ -1,10 +1,6 @@
|
|||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
annotations:
|
||||
kompose.cmd: kompose convert
|
||||
kompose.version: 1.21.0 (992df58d8)
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
app.kubernetes.io/name: budibase-proxy
|
||||
name: proxy-service
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
io.kompose.service: redis-data
|
||||
name: redis-data
|
||||
|
|
|
@ -2,10 +2,6 @@
|
|||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
annotations:
|
||||
kompose.cmd: kompose convert
|
||||
kompose.version: 1.21.0 (992df58d8)
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
io.kompose.service: redis-service
|
||||
name: redis-service
|
||||
|
@ -18,10 +14,6 @@ spec:
|
|||
type: Recreate
|
||||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
kompose.cmd: kompose convert
|
||||
kompose.version: 1.21.0 (992df58d8)
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
io.kompose.service: redis-service
|
||||
spec:
|
||||
|
|
|
@ -2,10 +2,6 @@
|
|||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
annotations:
|
||||
kompose.cmd: kompose convert
|
||||
kompose.version: 1.21.0 (992df58d8)
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
io.kompose.service: redis-service
|
||||
name: redis-service
|
||||
|
|
|
@ -2,12 +2,9 @@ apiVersion: apps/v1
|
|||
kind: Deployment
|
||||
metadata:
|
||||
annotations:
|
||||
kompose.cmd: kompose convert
|
||||
kompose.version: 1.21.0 (992df58d8)
|
||||
{{ if .Values.services.worker.deploymentAnnotations }}
|
||||
{{- toYaml .Values.services.worker.deploymentAnnotations | indent 4 -}}
|
||||
{{ end }}
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
io.kompose.service: worker-service
|
||||
{{ if .Values.services.worker.deploymentLabels }}
|
||||
|
@ -24,12 +21,9 @@ spec:
|
|||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
kompose.cmd: kompose convert
|
||||
kompose.version: 1.21.0 (992df58d8)
|
||||
{{ if .Values.services.worker.templateAnnotations }}
|
||||
{{- toYaml .Values.services.worker.templateAnnotations | indent 8 -}}
|
||||
{{ end }}
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
io.kompose.service: worker-service
|
||||
{{ if .Values.services.worker.templateLabels }}
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
{{- if .Values.services.worker.autoscaling.enabled }}
|
||||
apiVersion: {{ ternary "autoscaling/v2" "autoscaling/v2beta2" (.Capabilities.APIVersions.Has "autoscaling/v2") }}
|
||||
kind: HorizontalPodAutoscaler
|
||||
metadata:
|
||||
name: {{ include "budibase.fullname" . }}-worker
|
||||
labels:
|
||||
{{- include "budibase.labels" . | nindent 4 }}
|
||||
spec:
|
||||
scaleTargetRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: worker-service
|
||||
minReplicas: {{ .Values.services.worker.autoscaling.minReplicas }}
|
||||
maxReplicas: {{ .Values.services.worker.autoscaling.maxReplicas }}
|
||||
metrics:
|
||||
{{- if .Values.services.worker.autoscaling.targetCPUUtilizationPercentage }}
|
||||
- type: Resource
|
||||
resource:
|
||||
name: cpu
|
||||
target:
|
||||
type: Utilization
|
||||
averageUtilization: {{ .Values.services.worker.autoscaling.targetCPUUtilizationPercentage }}
|
||||
{{- end }}
|
||||
{{- if .Values.services.worker.autoscaling.targetMemoryUtilizationPercentage }}
|
||||
- type: Resource
|
||||
resource:
|
||||
name: memory
|
||||
target:
|
||||
type: Utilization
|
||||
averageUtilization: {{ .Values.services.worker.autoscaling.targetMemoryUtilizationPercentage }}
|
||||
{{- end }}
|
||||
{{- end }}
|
|
@ -1,10 +1,6 @@
|
|||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
annotations:
|
||||
kompose.cmd: kompose convert
|
||||
kompose.version: 1.21.0 (992df58d8)
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
io.kompose.service: worker-service
|
||||
name: worker-service
|
||||
|
|
|
@ -1,56 +1,32 @@
|
|||
# Default values for budibase.
|
||||
# This is a YAML-formatted file.
|
||||
# Declare variables to be passed into your templates.
|
||||
|
||||
image:
|
||||
pullPolicy: IfNotPresent
|
||||
# Overrides the image tag whose default is the chart appVersion.
|
||||
tag: ""
|
||||
|
||||
# -- Passed to all pods created by this chart. Should not ordinarily need to be changed.
|
||||
imagePullSecrets: []
|
||||
# -- Override the name of the deploymen. Defaults to {{ .Chart.Name }}.
|
||||
nameOverride: ""
|
||||
# fullnameOverride: ""
|
||||
|
||||
serviceAccount:
|
||||
# Specifies whether a service account should be created
|
||||
# -- Specifies whether a service account should be created
|
||||
create: true
|
||||
# Annotations to add to the service account
|
||||
# -- Annotations to add to the service account
|
||||
annotations: {}
|
||||
# The name of the service account to use.
|
||||
# -- The name of the service account to use.
|
||||
# If not set and create is true, a name is generated using the fullname template
|
||||
name: ""
|
||||
|
||||
podAnnotations: {}
|
||||
|
||||
podSecurityContext:
|
||||
{}
|
||||
# fsGroup: 2000
|
||||
|
||||
securityContext:
|
||||
{}
|
||||
# capabilities:
|
||||
# drop:
|
||||
# - ALL
|
||||
# readOnlyRootFilesystem: true
|
||||
# runAsNonRoot: true
|
||||
# runAsUser: 1000
|
||||
|
||||
service:
|
||||
# -- Service type for the service that points to the main Budibase proxy pod.
|
||||
type: ClusterIP
|
||||
# -- Port to expose on the service.
|
||||
port: 10000
|
||||
|
||||
ingress:
|
||||
# -- Whether to create an Ingress resource pointing to the Budibase proxy.
|
||||
enabled: true
|
||||
aws: false
|
||||
nginx: true
|
||||
certificateArn: ""
|
||||
# -- What ingress class to use.
|
||||
className: ""
|
||||
annotations:
|
||||
kubernetes.io/ingress.class: nginx
|
||||
nginx.ingress.kubernetes.io/client-max-body-size: 150M
|
||||
nginx.ingress.kubernetes.io/proxy-body-size: 50m
|
||||
# -- Standard hosts block for the Ingress resource. Defaults to pointing to the Budibase proxy.
|
||||
hosts:
|
||||
- host: # change if using custom domain
|
||||
# @ignore
|
||||
- host:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
|
@ -60,361 +36,426 @@ ingress:
|
|||
port:
|
||||
number: 10000
|
||||
|
||||
autoscaling:
|
||||
awsAlbIngress:
|
||||
# -- Whether to create an ALB Ingress resource pointing to the Budibase proxy. Requires the AWS ALB Ingress Controller.
|
||||
enabled: false
|
||||
minReplicas: 1
|
||||
maxReplicas: 100
|
||||
targetCPUUtilizationPercentage: 80
|
||||
# targetMemoryUtilizationPercentage: 80
|
||||
|
||||
nodeSelector: {}
|
||||
# -- If you're wanting to use HTTPS, you'll need to create an ACM certificate and specify the ARN here.
|
||||
certificateArn: ""
|
||||
|
||||
# -- Sets the tolerations for all pods created by this chart. Should not ordinarily need to be changed.
|
||||
# See <https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/> for more information
|
||||
# on tolerations.
|
||||
tolerations: []
|
||||
|
||||
# -- Sets the affinity for all pods created by this chart. Should not ordinarily
|
||||
# need to be changed. See
|
||||
# <https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes-using-node-affinity/>
|
||||
# for more information on affinity.
|
||||
affinity: {}
|
||||
|
||||
globals:
|
||||
appVersion: "" # Use as an override to .Chart.AppVersion
|
||||
# -- The version of Budibase to deploy. Defaults to what's specified by {{ .Chart.AppVersion }}.
|
||||
# Ends up being used as the image version tag for the apps, proxy, and worker images.
|
||||
appVersion: ""
|
||||
# -- Sets the environment variable BUDIBASE_ENVIRONMENT for the apps and worker pods. Should not
|
||||
# ordinarily need to be changed.
|
||||
budibaseEnv: PRODUCTION
|
||||
# -- Sets what feature flags are enabled and for which tenants. Should not ordinarily need to be
|
||||
# changed.
|
||||
tenantFeatureFlags: "*:LICENSING,*:USER_GROUPS,*:ONBOARDING_TOUR"
|
||||
# -- Whether to enable analytics or not. You can read more about our analytics here:
|
||||
# <https://docs.budibase.com/docs/analytics>.
|
||||
enableAnalytics: "1"
|
||||
# @ignore (only used if enableAnalytics is set to 1)
|
||||
posthogToken: "phc_bIjZL7oh2GEUd2vqvTBH8WvrX0fWTFQMs6H5KQxiUxU"
|
||||
selfHosted: "1" # set to 0 for budibase cloud environment, set to 1 for self-hosted setup
|
||||
multiTenancy: "0" # set to 0 to disable multiple orgs, set to 1 to enable multiple orgs
|
||||
offlineMode: "0" # set to 1 to enable offline mode
|
||||
# @ignore (should not normally need to be changed, we only set this to "0"
|
||||
# when deploying to our Cloud environment)
|
||||
selfHosted: "1"
|
||||
# @ignore (doesn't work out of the box for self-hosted users, only meant for Budicloud)
|
||||
multiTenancy: "0"
|
||||
# @ignore (only currently used to determine whether to fetch licenses offline or not, should
|
||||
# not normally need to be changed, and only applies to Enterprise customers)
|
||||
offlineMode: "0"
|
||||
# @ignore (only needs to be set in our cloud environment)
|
||||
accountPortalUrl: ""
|
||||
# @ignore (only needs to be set in our cloud environment)
|
||||
accountPortalApiKey: ""
|
||||
# -- Sets the domain attribute of the cookie that Budibase uses to store session information.
|
||||
# See <https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#define_where_cookies_are_sent>
|
||||
# for details on why you might want to set this.
|
||||
cookieDomain: ""
|
||||
# -- Set the `platformUrl` binding. You can also do this in Settings > Organisation if you are
|
||||
# self-hosting.
|
||||
platformUrl: ""
|
||||
# -- Whether or not to enable doing data migrations over the HTTP API. If this is set to "0",
|
||||
# migrations are run on startup. You shouldn't ordinarily need to change this.
|
||||
httpMigrations: "0"
|
||||
# -- Google OAuth settings. These can also be set in the Budibase UI, see
|
||||
# <https://docs.budibase.com/docs/sso-with-google> for details.
|
||||
google:
|
||||
# -- Client ID of your Google OAuth app.
|
||||
clientId: ""
|
||||
# -- Client secret of your Google OAuth app.
|
||||
secret: ""
|
||||
# -- The maximum number of iterations allows for an automation loop step. You can read more about
|
||||
# looping here: <https://docs.budibase.com/docs/looping>.
|
||||
automationMaxIterations: "200"
|
||||
|
||||
createSecrets: true # creates an internal API key, JWT secrets and redis password for you
|
||||
# -- Create an internal API key, JWT secret, object store access key and
|
||||
# secret, and store them in a Kubernetes `Secret`.
|
||||
createSecrets: true
|
||||
|
||||
# if createSecrets is set to false, you can hard-code your secrets here
|
||||
# -- Used for encrypting API keys and environment variables when stored in the database.
|
||||
# You don't need to set this if `createSecrets` is true.
|
||||
apiEncryptionKey: ""
|
||||
# -- API key used for internal Budibase API calls. You don't need to set this
|
||||
# if `createSecrets` is true.
|
||||
internalApiKey: ""
|
||||
# -- Secret used for signing JWTs. You don't need to set this if `createSecrets` is true.
|
||||
jwtSecret: ""
|
||||
cdnUrl: ""
|
||||
# fallback values used during live rotation
|
||||
|
||||
# -- A fallback value for `internalApiKey`. If you're rotating your encryption key, you can
|
||||
# set this to the old value for the duration of the rotation.
|
||||
internalApiKeyFallback: ""
|
||||
# -- A fallback value for `jwtSecret`. If you're rotating your JWT secret, you can set this
|
||||
# to the old value for the duration of the rotation.
|
||||
jwtSecretFallback: ""
|
||||
|
||||
smtp:
|
||||
# -- Whether to enable SMTP or not.
|
||||
enabled: false
|
||||
|
||||
# globalAgentHttpProxy:
|
||||
# globalAgentHttpsProxy:
|
||||
# globalAgentNoProxy:
|
||||
# -- The hostname of your SMTP server.
|
||||
host: ""
|
||||
# -- The port of your SMTP server.
|
||||
port: "587"
|
||||
# -- The email address to use in the "From:" field of emails sent by Budibase.
|
||||
from: ""
|
||||
# -- The username to use when authenticating with your SMTP server.
|
||||
user: ""
|
||||
# -- The password to use when authenticating with your SMTP server.
|
||||
password: ""
|
||||
|
||||
services:
|
||||
budibaseVersion: latest
|
||||
# -- The DNS suffix to use for service discovery. You only need to change this
|
||||
# if you've configured your cluster to use a different DNS suffix.
|
||||
dns: cluster.local
|
||||
# tlsRejectUnauthorized: 0
|
||||
|
||||
proxy:
|
||||
# @ignore (you shouldn't need to change this)
|
||||
port: 10000
|
||||
# -- The number of proxy replicas to run.
|
||||
replicaCount: 1
|
||||
# @ignore (you should never need to change this)
|
||||
upstreams:
|
||||
apps: "http://app-service.{{ .Release.Namespace }}.svc.{{ .Values.services.dns }}:{{ .Values.services.apps.port }}"
|
||||
worker: "http://worker-service.{{ .Release.Namespace }}.svc.{{ .Values.services.dns }}:{{ .Values.services.worker.port }}"
|
||||
minio: "http://minio-service.{{ .Release.Namespace }}.svc.{{ .Values.services.dns }}:{{ .Values.services.objectStore.port }}"
|
||||
couchdb: "http://{{ .Release.Name }}-svc-couchdb:{{ .Values.services.couchdb.port }}"
|
||||
# -- The resources to use for proxy pods. See
|
||||
# <https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/>
|
||||
# for more information on how to set these.
|
||||
resources: {}
|
||||
# -- Startup probe configuration for proxy pods. You shouldn't need to
|
||||
# change this, but if you want to you can find more information here:
|
||||
# <https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/>
|
||||
# @default -- HTTP health checks.
|
||||
startupProbe:
|
||||
# @ignore
|
||||
httpGet:
|
||||
path: /health
|
||||
port: 10000
|
||||
scheme: HTTP
|
||||
# @ignore
|
||||
failureThreshold: 30
|
||||
# @ignore
|
||||
periodSeconds: 3
|
||||
# -- Readiness probe configuration for proxy pods. You shouldn't need to
|
||||
# change this, but if you want to you can find more information here:
|
||||
# <https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/>
|
||||
# @default -- HTTP health checks.
|
||||
readinessProbe:
|
||||
# @ignore
|
||||
httpGet:
|
||||
path: /health
|
||||
port: 10000
|
||||
scheme: HTTP
|
||||
# @ignore
|
||||
periodSeconds: 3
|
||||
# @ignore
|
||||
failureThreshold: 1
|
||||
# -- Liveness probe configuration for proxy pods. You shouldn't need to
|
||||
# change this, but if you want to you can find more information here:
|
||||
# <https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/>
|
||||
# @default -- HTTP health checks.
|
||||
livenessProbe:
|
||||
# @ignore
|
||||
httpGet:
|
||||
path: /health
|
||||
port: 10000
|
||||
scheme: HTTP
|
||||
# @ignore
|
||||
failureThreshold: 3
|
||||
# @ignore
|
||||
periodSeconds: 5
|
||||
# annotations:
|
||||
# co.elastic.logs/module: nginx
|
||||
# co.elastic.logs/fileset.stdout: access
|
||||
# co.elastic.logs/fileset.stderr: error
|
||||
autoscaling:
|
||||
# -- Whether to enable horizontal pod autoscaling for the proxy service.
|
||||
enabled: false
|
||||
minReplicas: 1
|
||||
maxReplicas: 10
|
||||
# -- Target CPU utilization percentage for the proxy service. Note that
|
||||
# for autoscaling to work, you will need to have metrics-server
|
||||
# configured, and resources set for the proxy pods.
|
||||
targetCPUUtilizationPercentage: 80
|
||||
|
||||
apps:
|
||||
# @ignore (you shouldn't need to change this)
|
||||
port: 4002
|
||||
# -- The number of apps replicas to run.
|
||||
replicaCount: 1
|
||||
# -- The log level for the apps service.
|
||||
logLevel: info
|
||||
# -- Whether or not to log HTTP requests to the apps service.
|
||||
httpLogging: 1
|
||||
# -- The resources to use for apps pods. See
|
||||
# <https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/>
|
||||
# for more information on how to set these.
|
||||
resources: {}
|
||||
# -- Startup probe configuration for apps pods. You shouldn't need to
|
||||
# change this, but if you want to you can find more information here:
|
||||
# <https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/>
|
||||
# @default -- HTTP health checks.
|
||||
startupProbe:
|
||||
# @ignore
|
||||
httpGet:
|
||||
path: /health
|
||||
port: 4002
|
||||
scheme: HTTP
|
||||
# @ignore
|
||||
failureThreshold: 30
|
||||
# @ignore
|
||||
periodSeconds: 3
|
||||
# -- Readiness probe configuration for apps pods. You shouldn't need to
|
||||
# change this, but if you want to you can find more information here:
|
||||
# <https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/>
|
||||
# @default -- HTTP health checks.
|
||||
readinessProbe:
|
||||
# @ignore
|
||||
httpGet:
|
||||
path: /health
|
||||
port: 4002
|
||||
scheme: HTTP
|
||||
# @ignore
|
||||
periodSeconds: 3
|
||||
# @ignore
|
||||
failureThreshold: 1
|
||||
# -- Liveness probe configuration for apps pods. You shouldn't need to
|
||||
# change this, but if you want to you can find more information here:
|
||||
# <https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/>
|
||||
# @default -- HTTP health checks.
|
||||
livenessProbe:
|
||||
# @ignore
|
||||
httpGet:
|
||||
path: /health
|
||||
port: 4002
|
||||
scheme: HTTP
|
||||
# @ignore
|
||||
failureThreshold: 3
|
||||
# @ignore
|
||||
periodSeconds: 5
|
||||
# nodeDebug: "" # set the value of NODE_DEBUG
|
||||
# annotations:
|
||||
# co.elastic.logs/multiline.type: pattern
|
||||
# co.elastic.logs/multiline.pattern: '^[[:space:]]'
|
||||
# co.elastic.logs/multiline.negate: false
|
||||
# co.elastic.logs/multiline.match: after
|
||||
autoscaling:
|
||||
# -- Whether to enable horizontal pod autoscaling for the apps service.
|
||||
enabled: false
|
||||
minReplicas: 1
|
||||
maxReplicas: 10
|
||||
# -- Target CPU utilization percentage for the apps service. Note that for
|
||||
# autoscaling to work, you will need to have metrics-server configured,
|
||||
# and resources set for the apps pods.
|
||||
targetCPUUtilizationPercentage: 80
|
||||
|
||||
worker:
|
||||
# @ignore (you shouldn't need to change this)
|
||||
port: 4003
|
||||
# -- The number of worker replicas to run.
|
||||
replicaCount: 1
|
||||
# -- The log level for the worker service.
|
||||
logLevel: info
|
||||
# -- Whether or not to log HTTP requests to the worker service.
|
||||
httpLogging: 1
|
||||
# -- The resources to use for worker pods. See
|
||||
# <https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/>
|
||||
# for more information on how to set these.
|
||||
resources: {}
|
||||
# -- Startup probe configuration for worker pods. You shouldn't need to
|
||||
# change this, but if you want to you can find more information here:
|
||||
# <https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/>
|
||||
# @default -- HTTP health checks.
|
||||
startupProbe:
|
||||
# @ignore
|
||||
httpGet:
|
||||
path: /health
|
||||
port: 4003
|
||||
scheme: HTTP
|
||||
# @ignore
|
||||
failureThreshold: 30
|
||||
# @ignore
|
||||
periodSeconds: 3
|
||||
# -- Readiness probe configuration for worker pods. You shouldn't need to
|
||||
# change this, but if you want to you can find more information here:
|
||||
# <https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/>
|
||||
# @default -- HTTP health checks.
|
||||
readinessProbe:
|
||||
# @ignore
|
||||
httpGet:
|
||||
path: /health
|
||||
port: 4003
|
||||
scheme: HTTP
|
||||
# @ignore
|
||||
periodSeconds: 3
|
||||
# @ignore
|
||||
failureThreshold: 1
|
||||
# -- Liveness probe configuration for worker pods. You shouldn't need to
|
||||
# change this, but if you want to you can find more information here:
|
||||
# <https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/>
|
||||
# @default -- HTTP health checks.
|
||||
livenessProbe:
|
||||
# @ignore
|
||||
httpGet:
|
||||
path: /health
|
||||
port: 4003
|
||||
scheme: HTTP
|
||||
# @ignore
|
||||
failureThreshold: 3
|
||||
# @ignore
|
||||
periodSeconds: 5
|
||||
# annotations:
|
||||
# co.elastic.logs/multiline.type: pattern
|
||||
# co.elastic.logs/multiline.pattern: '^[[:space:]]'
|
||||
# co.elastic.logs/multiline.negate: false
|
||||
# co.elastic.logs/multiline.match: after
|
||||
autoscaling:
|
||||
# -- Whether to enable horizontal pod autoscaling for the worker service.
|
||||
enabled: false
|
||||
minReplicas: 1
|
||||
maxReplicas: 10
|
||||
# -- Target CPU utilization percentage for the worker service. Note that
|
||||
# for autoscaling to work, you will need to have metrics-server
|
||||
# configured, and resources set for the worker pods.
|
||||
targetCPUUtilizationPercentage: 80
|
||||
|
||||
couchdb:
|
||||
# -- Whether or not to spin up a CouchDB instance in your cluster. True by
|
||||
# default, and the configuration for the CouchDB instance is under the
|
||||
# `couchdb` key at the root of this file. You can see what options are
|
||||
# available to you by looking at the official CouchDB Helm chart:
|
||||
# <https://github.com/apache/couchdb-helm/tree/couchdb-4.3.0/couchdb>.
|
||||
enabled: true
|
||||
# url: "" # only change if pointing to existing couch server
|
||||
# user: "" # only change if pointing to existing couch server
|
||||
# password: "" # only change if pointing to existing couch server
|
||||
port: 5984
|
||||
backup:
|
||||
# -- Whether or not to enable periodic CouchDB backups. This works by replicating
|
||||
# to another CouchDB instance.
|
||||
enabled: false
|
||||
# target couchDB instance to back up to
|
||||
# -- Target couchDB instance to back up to, either a hostname or an IP address.
|
||||
target: ""
|
||||
# backup interval in seconds
|
||||
# -- Backup interval in seconds
|
||||
interval: ""
|
||||
# -- The resources to use for CouchDB backup pods. See
|
||||
# <https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/>
|
||||
# for more information on how to set these.
|
||||
resources: {}
|
||||
|
||||
redis:
|
||||
enabled: true # disable if using external redis
|
||||
# -- Whether or not to deploy a Redis pod into your cluster.
|
||||
enabled: true
|
||||
# -- Port to expose Redis on.
|
||||
port: 6379
|
||||
# @ignore (you should leave this as 1, we don't support clustering Redis)
|
||||
replicaCount: 1
|
||||
url: "" # only change if pointing to existing redis cluster and enabled: false
|
||||
password: "budibase" # recommended to override if using built-in redis
|
||||
# -- If you choose to run Redis externally to this chart, you can specify the
|
||||
# connection details here.
|
||||
url: ""
|
||||
# -- The password to use when connecting to Redis. It's recommended that you change
|
||||
# this from the default if you're running Redis in-cluster.
|
||||
password: "budibase"
|
||||
# -- How much persistent storage to allocate to Redis.
|
||||
storage: 100Mi
|
||||
## If defined, storageClassName: <storageClass>
|
||||
## If set to "-", storageClassName: "", which disables dynamic provisioning
|
||||
## If undefined (the default) or set to null, no storageClassName spec is
|
||||
## set, choosing the default provisioner.
|
||||
# -- If defined, storageClassName: <storageClass> If set to "-",
|
||||
# storageClassName: "", which disables dynamic provisioning If undefined
|
||||
# (the default) or set to null, no storageClassName spec is set, choosing
|
||||
# the default provisioner.
|
||||
storageClass: ""
|
||||
# -- The resources to use for Redis pods. See
|
||||
# <https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/>
|
||||
# for more information on how to set these.
|
||||
resources: {}
|
||||
|
||||
objectStore:
|
||||
# Set to false if using another object store such as S3
|
||||
# -- Set to false if using another object store, such as S3. You will need
|
||||
# to set `services.objectStore.url` to point to your bucket if you do this.
|
||||
minio: true
|
||||
# -- Whether to enable the Minio web console or not. If you're exposing
|
||||
# Minio to the Internet (via a custom Ingress record, for example), you
|
||||
# should set this to false. If you're only exposing Minio to your cluster,
|
||||
# you can leave this as true.
|
||||
browser: true
|
||||
# @ignore
|
||||
port: 9000
|
||||
# @ignore (you should leave this as 1, we don't support clustering Minio)
|
||||
replicaCount: 1
|
||||
accessKey: "" # AWS_ACCESS_KEY if using S3 or existing minio access key
|
||||
secretKey: "" # AWS_SECRET_ACCESS_KEY if using S3 or existing minio secret
|
||||
region: "" # AWS_REGION if using S3 or existing minio secret
|
||||
url: "http://minio-service:9000" # only change if pointing to existing minio cluster or S3 and minio: false
|
||||
# -- AWS_ACCESS_KEY if using S3
|
||||
accessKey: ""
|
||||
# -- AWS_SECRET_ACCESS_KEY if using S3
|
||||
secretKey: ""
|
||||
# -- AWS_REGION if using S3
|
||||
region: ""
|
||||
# -- URL to use for object storage. Only change this if you're using an
|
||||
# external object store, such as S3. Remember to set `minio: false` if you
|
||||
# do this.
|
||||
url: "http://minio-service:9000"
|
||||
# -- How much storage to give Minio in its PersistentVolumeClaim.
|
||||
storage: 100Mi
|
||||
## If defined, storageClassName: <storageClass>
|
||||
## If set to "-", storageClassName: "", which disables dynamic provisioning
|
||||
## If undefined (the default) or set to null, no storageClassName spec is
|
||||
## set, choosing the default provisioner.
|
||||
# -- If defined, storageClassName: <storageClass> If set to "-",
|
||||
# storageClassName: "", which disables dynamic provisioning If undefined
|
||||
# (the default) or set to null, no storageClassName spec is set, choosing
|
||||
# the default provisioner.
|
||||
storageClass: ""
|
||||
# -- The resources to use for Minio pods. See
|
||||
# <https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/>
|
||||
# for more information on how to set these.
|
||||
resources: {}
|
||||
cloudfront:
|
||||
# Set the url of a distribution to enable cloudfront
|
||||
# -- Set the url of a distribution to enable cloudfront.
|
||||
cdn: ""
|
||||
# ID of public key stored in cloudfront
|
||||
# -- ID of public key stored in cloudfront.
|
||||
publicKeyId: ""
|
||||
# Base64 encoded private key for the above public key
|
||||
# -- Base64 encoded private key for the above public key.
|
||||
privateKey64: ""
|
||||
|
||||
# Override values in couchDB subchart
|
||||
# Override values in couchDB subchart. We're only specifying the values we're changing.
|
||||
# If you want to see all of the available values, see:
|
||||
# https://github.com/apache/couchdb-helm/tree/couchdb-4.3.0/couchdb
|
||||
couchdb:
|
||||
## clusterSize is the initial size of the CouchDB cluster.
|
||||
# -- The number of replicas to run in the CouchDB cluster. We set this to
|
||||
# 1 by default to make things simpler, but you can set it to 3 if you need
|
||||
# a high-availability CouchDB cluster.
|
||||
clusterSize: 1
|
||||
allowAdminParty: false
|
||||
|
||||
# Secret Management
|
||||
createAdminSecret: true
|
||||
|
||||
# adminUsername: budibase
|
||||
# adminPassword: budibase
|
||||
# adminHash: -pbkdf2-this_is_not_necessarily_secure_either
|
||||
# cookieAuthSecret: admin
|
||||
|
||||
## When enabled, will deploy a networkpolicy that allows CouchDB pods to
|
||||
## communicate with each other for clustering and ingress on port 5984
|
||||
networkPolicy:
|
||||
enabled: true
|
||||
|
||||
# Use a service account
|
||||
serviceAccount:
|
||||
enabled: true
|
||||
create: true
|
||||
# name:
|
||||
# imagePullSecrets:
|
||||
# - name: myimagepullsecret
|
||||
|
||||
## The storage volume used by each Pod in the StatefulSet. If a
|
||||
## persistentVolume is not enabled, the Pods will use `emptyDir` ephemeral
|
||||
## local storage. Setting the storageClass attribute to "-" disables dynamic
|
||||
## provisioning of Persistent Volumes; leaving it unset will invoke the default
|
||||
## provisioner.
|
||||
persistentVolume:
|
||||
enabled: false
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
size: 10Gi
|
||||
storageClass: ""
|
||||
|
||||
## The CouchDB image
|
||||
# -- We use a custom CouchDB image for running Budibase and we don't support
|
||||
# using any other CouchDB image. You shouldn't change this, and if you do we
|
||||
# can't guarantee that Budibase will work.
|
||||
image:
|
||||
repository: couchdb
|
||||
tag: 3.1.1
|
||||
pullPolicy: IfNotPresent
|
||||
|
||||
## Experimental integration with Lucene-powered fulltext search
|
||||
enableSearch: true
|
||||
searchImage:
|
||||
repository: kocolosk/couchdb-search
|
||||
tag: 0.2.0
|
||||
pullPolicy: IfNotPresent
|
||||
|
||||
initImage:
|
||||
repository: busybox
|
||||
tag: latest
|
||||
# @ignore
|
||||
repository: budibase/couchdb
|
||||
# @ignore
|
||||
tag: v3.2.1
|
||||
# @ignore
|
||||
pullPolicy: Always
|
||||
|
||||
## CouchDB is happy to spin up cluster nodes in parallel, but if you encounter
|
||||
## problems you can try setting podManagementPolicy to the StatefulSet default
|
||||
## `OrderedReady`
|
||||
podManagementPolicy: Parallel
|
||||
# @ignore
|
||||
# This should remain false. We ship Clouseau ourselves as part of the
|
||||
# budibase/couchdb image, and it's not possible to disable it because it's a
|
||||
# core part of the Budibase experience.
|
||||
enableSearch: false
|
||||
|
||||
## Optional pod annotations
|
||||
annotations: {}
|
||||
|
||||
## Optional tolerations
|
||||
tolerations: []
|
||||
|
||||
affinity: {}
|
||||
|
||||
service:
|
||||
# annotations:
|
||||
enabled: true
|
||||
type: ClusterIP
|
||||
externalPort: 5984
|
||||
|
||||
## An Ingress resource can provide name-based virtual hosting and TLS
|
||||
## termination among other things for CouchDB deployments which are accessed
|
||||
## from outside the Kubernetes cluster.
|
||||
## ref: https://kubernetes.io/docs/concepts/services-networking/ingress/
|
||||
ingress:
|
||||
enabled: false
|
||||
hosts:
|
||||
- chart-example.local
|
||||
path: /
|
||||
annotations:
|
||||
[]
|
||||
# kubernetes.io/ingress.class: nginx
|
||||
# kubernetes.io/tls-acme: "true"
|
||||
tls:
|
||||
# Secrets must be manually created in the namespace.
|
||||
# - secretName: chart-example-tls
|
||||
# hosts:
|
||||
# - chart-example.local
|
||||
|
||||
## Optional resource requests and limits for the CouchDB container
|
||||
## ref: http://kubernetes.io/docs/user-guide/compute-resources/
|
||||
resources:
|
||||
{}
|
||||
# requests:
|
||||
# cpu: 100m
|
||||
# memory: 128Mi
|
||||
# limits:
|
||||
# cpu: 56
|
||||
# memory: 256Gi
|
||||
|
||||
## erlangFlags is a map that is passed to the Erlang VM as flags using the
|
||||
## ERL_FLAGS env. `name` and `setcookie` flags are minimally required to
|
||||
## establish connectivity between cluster nodes.
|
||||
## ref: http://erlang.org/doc/man/erl.html#init_flags
|
||||
erlangFlags:
|
||||
name: couchdb
|
||||
setcookie: monster
|
||||
|
||||
## couchdbConfig will override default CouchDB configuration settings.
|
||||
## The contents of this map are reformatted into a .ini file laid down
|
||||
## by a ConfigMap object.
|
||||
## ref: http://docs.couchdb.org/en/latest/config/index.html
|
||||
couchdbConfig:
|
||||
couchdb:
|
||||
uuid: budibase-couchdb # REQUIRED: Unique identifier for this CouchDB server instance
|
||||
# cluster:
|
||||
# q: 8 # Create 8 shards for each database
|
||||
chttpd:
|
||||
bind_address: any
|
||||
# chttpd.require_valid_user disables all the anonymous requests to the port
|
||||
# 5984 when is set to true.
|
||||
require_valid_user: false
|
||||
|
||||
# Kubernetes local cluster domain.
|
||||
# This is used to generate FQDNs for peers when joining the CouchDB cluster.
|
||||
dns:
|
||||
clusterDomainSuffix: cluster.local
|
||||
|
||||
## Configure liveness and readiness probe values
|
||||
## Ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes
|
||||
# FOR COUCHDB
|
||||
livenessProbe:
|
||||
failureThreshold: 3
|
||||
initialDelaySeconds: 0
|
||||
periodSeconds: 10
|
||||
successThreshold: 1
|
||||
timeoutSeconds: 1
|
||||
readinessProbe:
|
||||
failureThreshold: 3
|
||||
initialDelaySeconds: 0
|
||||
periodSeconds: 10
|
||||
successThreshold: 1
|
||||
timeoutSeconds: 1
|
||||
# -- Unique identifier for this CouchDB server instance. You shouldn't need
|
||||
# to change this.
|
||||
uuid: budibase-couchdb
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"version": "2.13.30",
|
||||
"version": "2.13.31",
|
||||
"npmClient": "yarn",
|
||||
"packages": [
|
||||
"packages/*"
|
||||
|
|
|
@ -99,6 +99,8 @@ function updateContext(updates: ContextMap): ContextMap {
|
|||
}
|
||||
|
||||
async function newContext<T>(updates: ContextMap, task: () => T) {
|
||||
guardMigration()
|
||||
|
||||
// see if there already is a context setup
|
||||
let context: ContextMap = updateContext(updates)
|
||||
return Context.run(context, task)
|
||||
|
@ -145,23 +147,27 @@ export async function doInTenant<T>(
|
|||
}
|
||||
|
||||
export async function doInAppContext<T>(
|
||||
appId: string | null,
|
||||
appId: string,
|
||||
task: () => T
|
||||
): Promise<T> {
|
||||
if (!appId && !env.isTest()) {
|
||||
return _doInAppContext(appId, task)
|
||||
}
|
||||
|
||||
async function _doInAppContext<T>(
|
||||
appId: string,
|
||||
task: () => T,
|
||||
extraContextSettings?: ContextMap
|
||||
): Promise<T> {
|
||||
if (!appId) {
|
||||
throw new Error("appId is required")
|
||||
}
|
||||
|
||||
let updates: ContextMap
|
||||
if (!appId) {
|
||||
updates = { appId: "" }
|
||||
} else {
|
||||
const tenantId = getTenantIDFromAppID(appId)
|
||||
updates = { appId }
|
||||
if (tenantId) {
|
||||
updates.tenantId = tenantId
|
||||
}
|
||||
const tenantId = getTenantIDFromAppID(appId)
|
||||
const updates: ContextMap = { appId, ...extraContextSettings }
|
||||
if (tenantId) {
|
||||
updates.tenantId = tenantId
|
||||
}
|
||||
|
||||
return newContext(updates, task)
|
||||
}
|
||||
|
||||
|
@ -182,6 +188,24 @@ export async function doInIdentityContext<T>(
|
|||
return newContext(context, task)
|
||||
}
|
||||
|
||||
function guardMigration() {
|
||||
const context = Context.get()
|
||||
if (context?.isMigrating) {
|
||||
throw new Error(
|
||||
"The context cannot be changed, a migration is currently running"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export async function doInAppMigrationContext<T>(
|
||||
appId: string,
|
||||
task: () => T
|
||||
): Promise<T> {
|
||||
return _doInAppContext(appId, task, {
|
||||
isMigrating: true,
|
||||
})
|
||||
}
|
||||
|
||||
export function getIdentity(): IdentityContext | undefined {
|
||||
try {
|
||||
const context = Context.get()
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
import { testEnv } from "../../../tests/extra"
|
||||
import * as context from "../"
|
||||
import { DEFAULT_TENANT_ID } from "../../constants"
|
||||
import { structures } from "../../../tests"
|
||||
import { db } from "../.."
|
||||
import Context from "../Context"
|
||||
import { ContextMap } from "../types"
|
||||
import { IdentityType } from "@budibase/types"
|
||||
|
||||
describe("context", () => {
|
||||
describe("doInTenant", () => {
|
||||
|
@ -144,4 +149,107 @@ describe("context", () => {
|
|||
expect(isScim).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
describe("doInAppMigrationContext", () => {
|
||||
it("the context is set correctly", async () => {
|
||||
const appId = db.generateAppID()
|
||||
|
||||
await context.doInAppMigrationContext(appId, () => {
|
||||
const context = Context.get()
|
||||
|
||||
const expected: ContextMap = {
|
||||
appId,
|
||||
isMigrating: true,
|
||||
}
|
||||
expect(context).toEqual(expected)
|
||||
})
|
||||
})
|
||||
|
||||
it("the context is set correctly when running in a tenant id", async () => {
|
||||
const tenantId = structures.tenant.id()
|
||||
const appId = db.generateAppID(tenantId)
|
||||
|
||||
await context.doInAppMigrationContext(appId, () => {
|
||||
const context = Context.get()
|
||||
|
||||
const expected: ContextMap = {
|
||||
appId,
|
||||
isMigrating: true,
|
||||
tenantId,
|
||||
}
|
||||
expect(context).toEqual(expected)
|
||||
})
|
||||
})
|
||||
|
||||
it("the context is not modified outside the delegate", async () => {
|
||||
const appId = db.generateAppID()
|
||||
|
||||
expect(Context.get()).toBeUndefined()
|
||||
|
||||
await context.doInAppMigrationContext(appId, () => {
|
||||
const context = Context.get()
|
||||
|
||||
const expected: ContextMap = {
|
||||
appId,
|
||||
isMigrating: true,
|
||||
}
|
||||
expect(context).toEqual(expected)
|
||||
})
|
||||
|
||||
expect(Context.get()).toBeUndefined()
|
||||
})
|
||||
|
||||
it.each([
|
||||
[
|
||||
"doInAppMigrationContext",
|
||||
() => context.doInAppMigrationContext(db.generateAppID(), () => {}),
|
||||
],
|
||||
[
|
||||
"doInAppContext",
|
||||
() => context.doInAppContext(db.generateAppID(), () => {}),
|
||||
],
|
||||
[
|
||||
"doInAutomationContext",
|
||||
() =>
|
||||
context.doInAutomationContext({
|
||||
appId: db.generateAppID(),
|
||||
automationId: structures.generator.guid(),
|
||||
task: () => {},
|
||||
}),
|
||||
],
|
||||
["doInContext", () => context.doInContext(db.generateAppID(), () => {})],
|
||||
[
|
||||
"doInEnvironmentContext",
|
||||
() => context.doInEnvironmentContext({}, () => {}),
|
||||
],
|
||||
[
|
||||
"doInIdentityContext",
|
||||
() =>
|
||||
context.doInIdentityContext(
|
||||
{
|
||||
account: undefined,
|
||||
type: IdentityType.USER,
|
||||
_id: structures.users.user()._id!,
|
||||
},
|
||||
() => {}
|
||||
),
|
||||
],
|
||||
["doInScimContext", () => context.doInScimContext(() => {})],
|
||||
[
|
||||
"doInTenant",
|
||||
() => context.doInTenant(structures.tenant.id(), () => {}),
|
||||
],
|
||||
])(
|
||||
"a nested context.%s function cannot run",
|
||||
async (_, otherContextCall: () => Promise<void>) => {
|
||||
await expect(
|
||||
context.doInAppMigrationContext(db.generateAppID(), async () => {
|
||||
await otherContextCall()
|
||||
})
|
||||
).rejects.toThrowError(
|
||||
"The context cannot be changed, a migration is currently running"
|
||||
)
|
||||
}
|
||||
)
|
||||
})
|
||||
})
|
||||
|
|
|
@ -8,4 +8,5 @@ export type ContextMap = {
|
|||
environmentVariables?: Record<string, string>
|
||||
isScim?: boolean
|
||||
automationId?: string
|
||||
isMigrating?: boolean
|
||||
}
|
||||
|
|
|
@ -109,7 +109,7 @@ export async function doWithLock<T>(
|
|||
): Promise<RedlockExecution<T>> {
|
||||
const redlock = await getClient(opts.type, opts.customOptions)
|
||||
let lock: Redlock.Lock | undefined
|
||||
let timeout: NodeJS.Timeout | undefined
|
||||
let timeout
|
||||
try {
|
||||
const name = getLockName(opts)
|
||||
|
||||
|
|
|
@ -93,11 +93,19 @@ export const getTenantIDFromCtx = (
|
|||
// subdomain
|
||||
if (isAllowed(TenantResolutionStrategy.SUBDOMAIN)) {
|
||||
// e.g. budibase.app or local.com:10000
|
||||
const platformHost = new URL(getPlatformURL()).host.split(":")[0]
|
||||
let platformHost
|
||||
try {
|
||||
platformHost = new URL(getPlatformURL()).host.split(":")[0]
|
||||
} catch (err: any) {
|
||||
// if invalid URL, just don't try to process subdomain
|
||||
if (err.code !== "ERR_INVALID_URL") {
|
||||
throw err
|
||||
}
|
||||
}
|
||||
// e.g. tenant.budibase.app or tenant.local.com
|
||||
const requestHost = ctx.host
|
||||
// parse the tenant id from the difference
|
||||
if (requestHost.includes(platformHost)) {
|
||||
if (platformHost && requestHost.includes(platformHost)) {
|
||||
const tenantId = requestHost.substring(
|
||||
0,
|
||||
requestHost.indexOf(`.${platformHost}`)
|
||||
|
|
|
@ -8,6 +8,7 @@ import { derived, get } from "svelte/store"
|
|||
import { findComponent, findComponentPath } from "./componentUtils"
|
||||
import { RoleUtils } from "@budibase/frontend-core"
|
||||
import { createHistoryStore } from "builderStore/store/history"
|
||||
import { cloneDeep } from "lodash/fp"
|
||||
|
||||
export const store = getFrontendStore()
|
||||
export const automationStore = getAutomationStore()
|
||||
|
@ -69,7 +70,14 @@ export const selectedComponent = derived(
|
|||
if (!$selectedScreen || !$store.selectedComponentId) {
|
||||
return null
|
||||
}
|
||||
return findComponent($selectedScreen?.props, $store.selectedComponentId)
|
||||
const selected = findComponent(
|
||||
$selectedScreen?.props,
|
||||
$store.selectedComponentId
|
||||
)
|
||||
|
||||
const clone = selected ? cloneDeep(selected) : selected
|
||||
store.actions.components.migrateSettings(clone)
|
||||
return clone
|
||||
}
|
||||
)
|
||||
|
||||
|
|
|
@ -601,6 +601,36 @@ export const getFrontendStore = () => {
|
|||
// Finally try an external table
|
||||
return validTables.find(table => table.sourceType === DB_TYPE_EXTERNAL)
|
||||
},
|
||||
migrateSettings: enrichedComponent => {
|
||||
const componentPrefix = "@budibase/standard-components"
|
||||
let migrated = false
|
||||
|
||||
if (enrichedComponent?._component == `${componentPrefix}/formblock`) {
|
||||
// Use default config if the 'buttons' prop has never been initialised
|
||||
if (!("buttons" in enrichedComponent)) {
|
||||
enrichedComponent["buttons"] =
|
||||
Utils.buildDynamicButtonConfig(enrichedComponent)
|
||||
migrated = true
|
||||
} else if (enrichedComponent["buttons"] == null) {
|
||||
// Ignore legacy config if 'buttons' has been reset by 'resetOn'
|
||||
const { _id, actionType, dataSource } = enrichedComponent
|
||||
enrichedComponent["buttons"] = Utils.buildDynamicButtonConfig({
|
||||
_id,
|
||||
actionType,
|
||||
dataSource,
|
||||
})
|
||||
migrated = true
|
||||
}
|
||||
|
||||
// Ensure existing Formblocks position their buttons at the top.
|
||||
if (!("buttonPosition" in enrichedComponent)) {
|
||||
enrichedComponent["buttonPosition"] = "top"
|
||||
migrated = true
|
||||
}
|
||||
}
|
||||
|
||||
return migrated
|
||||
},
|
||||
enrichEmptySettings: (component, opts) => {
|
||||
if (!component?._component) {
|
||||
return
|
||||
|
@ -672,7 +702,6 @@ export const getFrontendStore = () => {
|
|||
component[setting.key] = setting.defaultValue
|
||||
}
|
||||
}
|
||||
|
||||
// Validate non-empty settings
|
||||
else {
|
||||
if (setting.type === "dataProvider") {
|
||||
|
@ -722,6 +751,9 @@ export const getFrontendStore = () => {
|
|||
useDefaultValues: true,
|
||||
})
|
||||
|
||||
// Migrate nested component settings
|
||||
store.actions.components.migrateSettings(instance)
|
||||
|
||||
// Add any extra properties the component needs
|
||||
let extras = {}
|
||||
if (definition.hasChildren) {
|
||||
|
@ -845,7 +877,13 @@ export const getFrontendStore = () => {
|
|||
if (!component) {
|
||||
return false
|
||||
}
|
||||
return patchFn(component, screen)
|
||||
|
||||
// Mutates the fetched component with updates
|
||||
const updated = patchFn(component, screen)
|
||||
// Mutates the component with any required settings updates
|
||||
const migrated = store.actions.components.migrateSettings(component)
|
||||
|
||||
return updated || migrated
|
||||
}
|
||||
await store.actions.screens.patch(patchScreen, screenId)
|
||||
},
|
||||
|
@ -1247,9 +1285,13 @@ export const getFrontendStore = () => {
|
|||
const settings = getComponentSettings(component._component)
|
||||
const updatedSetting = settings.find(setting => setting.key === name)
|
||||
|
||||
const resetFields = settings.filter(
|
||||
setting => name === setting.resetOn
|
||||
)
|
||||
// Can be a single string or array of strings
|
||||
const resetFields = settings.filter(setting => {
|
||||
return (
|
||||
name === setting.resetOn ||
|
||||
(Array.isArray(setting.resetOn) && setting.resetOn.includes(name))
|
||||
)
|
||||
})
|
||||
resetFields?.forEach(setting => {
|
||||
component[setting.key] = null
|
||||
})
|
||||
|
@ -1271,6 +1313,7 @@ export const getFrontendStore = () => {
|
|||
})
|
||||
}
|
||||
component[name] = value
|
||||
return true
|
||||
}
|
||||
},
|
||||
requestEjectBlock: componentId => {
|
||||
|
@ -1278,7 +1321,6 @@ export const getFrontendStore = () => {
|
|||
},
|
||||
handleEjectBlock: async (componentId, ejectedDefinition) => {
|
||||
let nextSelectedComponentId
|
||||
|
||||
await store.actions.screens.patch(screen => {
|
||||
const block = findComponent(screen.props, componentId)
|
||||
const parent = findComponentParent(screen.props, componentId)
|
||||
|
|
|
@ -57,16 +57,11 @@
|
|||
}}
|
||||
class="buttons"
|
||||
>
|
||||
<Icon hoverable size="M" name="Play" />
|
||||
<Icon size="M" name="Play" />
|
||||
<div>Run test</div>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<Icon
|
||||
disabled={!$automationStore.testResults}
|
||||
hoverable
|
||||
size="M"
|
||||
name="Multiple"
|
||||
/>
|
||||
<Icon disabled={!$automationStore.testResults} size="M" name="Multiple" />
|
||||
<div
|
||||
class:disabled={!$automationStore.testResults}
|
||||
on:click={() => {
|
||||
|
|
|
@ -97,6 +97,7 @@
|
|||
class:typing={typing && !automationNameError}
|
||||
class:typing-error={automationNameError}
|
||||
class="blockSection"
|
||||
on:click={() => dispatch("toggle")}
|
||||
>
|
||||
<div class="splitHeader">
|
||||
<div class="center-items">
|
||||
|
@ -138,7 +139,20 @@
|
|||
on:input={e => {
|
||||
automationName = e.target.value.trim()
|
||||
}}
|
||||
on:click={startTyping}
|
||||
on:click={e => {
|
||||
e.stopPropagation()
|
||||
startTyping()
|
||||
}}
|
||||
on:keydown={async e => {
|
||||
if (e.key === "Enter") {
|
||||
typing = false
|
||||
if (automationNameError) {
|
||||
automationName = stepNames[block.id] || block?.name
|
||||
} else {
|
||||
await saveName()
|
||||
}
|
||||
}
|
||||
}}
|
||||
on:blur={async () => {
|
||||
typing = false
|
||||
if (automationNameError) {
|
||||
|
@ -168,7 +182,11 @@
|
|||
</StatusLight>
|
||||
</div>
|
||||
<Icon
|
||||
on:click={() => dispatch("toggle")}
|
||||
e.stopPropagation()
|
||||
on:click={e => {
|
||||
e.stopPropagation()
|
||||
dispatch("toggle")
|
||||
}}
|
||||
hoverable
|
||||
name={open ? "ChevronUp" : "ChevronDown"}
|
||||
/>
|
||||
|
@ -195,7 +213,10 @@
|
|||
{/if}
|
||||
{#if !showTestStatus}
|
||||
<Icon
|
||||
on:click={() => dispatch("toggle")}
|
||||
on:click={e => {
|
||||
e.stopPropagation()
|
||||
dispatch("toggle")
|
||||
}}
|
||||
hoverable
|
||||
name={open ? "ChevronUp" : "ChevronDown"}
|
||||
/>
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
<script>
|
||||
import {
|
||||
ModalContent,
|
||||
Tabs,
|
||||
Tab,
|
||||
TextArea,
|
||||
Label,
|
||||
notifications,
|
||||
ActionButton,
|
||||
} from "@budibase/bbui"
|
||||
import { automationStore, selectedAutomation } from "builderStore"
|
||||
import AutomationBlockSetup from "../../SetupPanel/AutomationBlockSetup.svelte"
|
||||
|
@ -55,50 +53,69 @@
|
|||
notifications.error(error)
|
||||
}
|
||||
}
|
||||
|
||||
const toggle = () => {
|
||||
selectedValues = !selectedValues
|
||||
selectedJSON = !selectedJSON
|
||||
}
|
||||
let selectedValues = true
|
||||
let selectedJSON = false
|
||||
</script>
|
||||
|
||||
<ModalContent
|
||||
title="Add test data"
|
||||
confirmText="Test"
|
||||
size="M"
|
||||
confirmText="Run test"
|
||||
size="L"
|
||||
showConfirmButton={true}
|
||||
disabled={isError}
|
||||
onConfirm={testAutomation}
|
||||
cancelText="Cancel"
|
||||
>
|
||||
<Tabs selected="Form" quiet>
|
||||
<Tab icon="Form" title="Form">
|
||||
<div class="tab-content-padding">
|
||||
<AutomationBlockSetup
|
||||
{testData}
|
||||
{schemaProperties}
|
||||
isTestModal
|
||||
block={trigger}
|
||||
/>
|
||||
</div></Tab
|
||||
>
|
||||
<Tab icon="FileJson" title="JSON">
|
||||
<div class="tab-content-padding">
|
||||
<Label>JSON</Label>
|
||||
<div class="text-area-container">
|
||||
<TextArea
|
||||
value={JSON.stringify($selectedAutomation.testData, null, 2)}
|
||||
error={failedParse}
|
||||
on:change={e => parseTestJSON(e)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</Tab>
|
||||
</Tabs>
|
||||
<div class="size">
|
||||
<div class="options">
|
||||
<ActionButton quiet selected={selectedValues} on:click={toggle}
|
||||
>Use values</ActionButton
|
||||
>
|
||||
<ActionButton quiet selected={selectedJSON} on:click={toggle}
|
||||
>Use JSON</ActionButton
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{#if selectedValues}
|
||||
<div class="tab-content-padding">
|
||||
<AutomationBlockSetup
|
||||
{testData}
|
||||
{schemaProperties}
|
||||
isTestModal
|
||||
block={trigger}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
{#if selectedJSON}
|
||||
<div class="text-area-container">
|
||||
<TextArea
|
||||
value={JSON.stringify($selectedAutomation.testData, null, 2)}
|
||||
error={failedParse}
|
||||
on:change={e => parseTestJSON(e)}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
</ModalContent>
|
||||
|
||||
<style>
|
||||
.text-area-container :global(textarea) {
|
||||
min-height: 200px;
|
||||
height: 200px;
|
||||
min-height: 300px;
|
||||
height: 300px;
|
||||
}
|
||||
|
||||
.tab-content-padding {
|
||||
padding: 0 var(--spacing-xl);
|
||||
padding: 0 var(--spacing-s);
|
||||
}
|
||||
|
||||
.options {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<div class="title">
|
||||
<div class="title-text">
|
||||
<Icon name="MultipleCheck" />
|
||||
<div style="padding-left: var(--spacing-l)">Test Details</div>
|
||||
<div style="padding-left: var(--spacing-l); ">Test Details</div>
|
||||
</div>
|
||||
<div style="padding-right: var(--spacing-xl)">
|
||||
<Icon
|
||||
|
@ -40,6 +40,7 @@
|
|||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
padding-top: var(--spacing-s);
|
||||
}
|
||||
|
||||
.title :global(h1) {
|
||||
|
|
|
@ -1,20 +1,44 @@
|
|||
<script>
|
||||
import AutomationList from "./AutomationList.svelte"
|
||||
import CreateAutomationModal from "./CreateAutomationModal.svelte"
|
||||
import { Modal, Button, Layout } from "@budibase/bbui"
|
||||
import { Modal, Icon } from "@budibase/bbui"
|
||||
import Panel from "components/design/Panel.svelte"
|
||||
|
||||
export let modal
|
||||
export let webhookModal
|
||||
</script>
|
||||
|
||||
<Panel title="Automations" borderRight>
|
||||
<Layout paddingX="L" paddingY="XL" gap="S">
|
||||
<Button cta on:click={modal.show}>Add automation</Button>
|
||||
</Layout>
|
||||
<Panel title="Automations" borderRight noHeaderBorder titleCSS={false}>
|
||||
<span class="panel-title-content" slot="panel-title-content">
|
||||
<div class="header">
|
||||
<div>Automations</div>
|
||||
<div on:click={modal.show} class="add-automation-button">
|
||||
<Icon name="Add" />
|
||||
</div>
|
||||
</div>
|
||||
</span>
|
||||
<AutomationList />
|
||||
</Panel>
|
||||
|
||||
<Modal bind:this={modal}>
|
||||
<CreateAutomationModal {webhookModal} />
|
||||
</Modal>
|
||||
|
||||
<style>
|
||||
.header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: var(--spacing-m);
|
||||
}
|
||||
|
||||
.add-automation-button {
|
||||
margin-left: 130px;
|
||||
color: var(--grey-7);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.add-automation-button:hover {
|
||||
color: var(--ink);
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -149,7 +149,6 @@
|
|||
}
|
||||
const initialiseField = (field, savingColumn) => {
|
||||
isCreating = !field
|
||||
|
||||
if (field && !savingColumn) {
|
||||
editableColumn = cloneDeep(field)
|
||||
originalName = editableColumn.name ? editableColumn.name + "" : null
|
||||
|
@ -171,7 +170,8 @@
|
|||
relationshipPart2 = part2
|
||||
}
|
||||
}
|
||||
} else if (!savingColumn) {
|
||||
}
|
||||
if (!savingColumn) {
|
||||
let highestNumber = 0
|
||||
Object.keys(table.schema).forEach(columnName => {
|
||||
const columnNumber = extractColumnNumber(columnName)
|
||||
|
@ -307,12 +307,6 @@
|
|||
dispatch("updatecolumns")
|
||||
gridDispatch("close-edit-column")
|
||||
|
||||
if (saveColumn.type === LINK_TYPE) {
|
||||
// Fetching the new tables
|
||||
tables.fetch()
|
||||
// Fetching the new relationships
|
||||
datasources.fetch()
|
||||
}
|
||||
if (originalName) {
|
||||
notifications.success("Column updated successfully")
|
||||
} else {
|
||||
|
@ -339,11 +333,6 @@
|
|||
confirmDeleteDialog.hide()
|
||||
dispatch("updatecolumns")
|
||||
gridDispatch("close-edit-column")
|
||||
|
||||
if (editableColumn.type === LINK_TYPE) {
|
||||
// Updating the relationships
|
||||
datasources.fetch()
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
notifications.error(`Error deleting column: ${error.message}`)
|
||||
|
@ -540,8 +529,16 @@
|
|||
<Layout noPadding gap="S">
|
||||
{#if mounted}
|
||||
<Input
|
||||
value={editableColumn.name}
|
||||
autofocus
|
||||
bind:value={editableColumn.name}
|
||||
on:input={e => {
|
||||
if (
|
||||
!uneditable &&
|
||||
!(linkEditDisabled && editableColumn.type === LINK_TYPE)
|
||||
) {
|
||||
editableColumn.name = e.target.value
|
||||
}
|
||||
}}
|
||||
disabled={uneditable ||
|
||||
(linkEditDisabled && editableColumn.type === LINK_TYPE)}
|
||||
error={errors?.name}
|
||||
|
|
|
@ -16,7 +16,8 @@
|
|||
export let wide = false
|
||||
export let extraWide = false
|
||||
export let closeButtonIcon = "Close"
|
||||
|
||||
export let noHeaderBorder = false
|
||||
export let titleCSS = true
|
||||
$: customHeaderContent = $$slots["panel-header-content"]
|
||||
$: customTitleContent = $$slots["panel-title-content"]
|
||||
</script>
|
||||
|
@ -32,6 +33,7 @@
|
|||
class="header"
|
||||
class:custom={customHeaderContent}
|
||||
class:borderBottom={borderBottomHeader}
|
||||
class:noHeaderBorder
|
||||
>
|
||||
{#if showBackButton}
|
||||
<Icon name="ArrowLeft" hoverable on:click={onClickBackButton} />
|
||||
|
@ -41,7 +43,7 @@
|
|||
<Icon name={icon} />
|
||||
</AbsTooltip>
|
||||
{/if}
|
||||
<div class="title">
|
||||
<div class:title={titleCSS}>
|
||||
{#if customTitleContent}
|
||||
<slot name="panel-title-content" />
|
||||
{:else}
|
||||
|
@ -106,6 +108,10 @@
|
|||
padding: 0 var(--spacing-l);
|
||||
gap: var(--spacing-m);
|
||||
}
|
||||
|
||||
.noHeaderBorder {
|
||||
border-bottom: none !important;
|
||||
}
|
||||
.header.borderBottom {
|
||||
border-bottom: var(--border-light);
|
||||
}
|
||||
|
|
|
@ -110,7 +110,7 @@
|
|||
}
|
||||
|
||||
.setup {
|
||||
padding-top: var(--spectrum-global-dimension-size-200);
|
||||
padding-top: 9px;
|
||||
border-left: var(--border-light);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
|
|
@ -81,13 +81,21 @@ export function createTablesStore() {
|
|||
replaceTable(savedTable._id, savedTable)
|
||||
select(savedTable._id)
|
||||
// make sure tables up to date (related)
|
||||
let tableIdsToFetch = []
|
||||
let newTableIds = []
|
||||
for (let column of Object.values(updatedTable?.schema || {})) {
|
||||
if (column.type === FIELDS.LINK.type) {
|
||||
tableIdsToFetch.push(column.tableId)
|
||||
newTableIds.push(column.tableId)
|
||||
}
|
||||
}
|
||||
tableIdsToFetch = [...new Set(tableIdsToFetch)]
|
||||
|
||||
let oldTableIds = []
|
||||
for (let column of Object.values(oldTable?.schema || {})) {
|
||||
if (column.type === FIELDS.LINK.type) {
|
||||
oldTableIds.push(column.tableId)
|
||||
}
|
||||
}
|
||||
|
||||
const tableIdsToFetch = [...new Set([...newTableIds, ...oldTableIds])]
|
||||
// too many tables to fetch, just get all
|
||||
if (tableIdsToFetch.length > 3) {
|
||||
await fetch()
|
||||
|
|
|
@ -6112,54 +6112,32 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tag": "style",
|
||||
"type": "select",
|
||||
"label": "Button position",
|
||||
"key": "buttonPosition",
|
||||
"options": [
|
||||
{
|
||||
"label": "Bottom",
|
||||
"value": "bottom"
|
||||
},
|
||||
{
|
||||
"label": "Top",
|
||||
"value": "top"
|
||||
}
|
||||
],
|
||||
"defaultValue": "bottom"
|
||||
},
|
||||
{
|
||||
"section": true,
|
||||
"name": "Buttons",
|
||||
"dependsOn": {
|
||||
"setting": "actionType",
|
||||
"value": "View",
|
||||
"invert": true
|
||||
},
|
||||
"settings": [
|
||||
{
|
||||
"type": "text",
|
||||
"key": "saveButtonLabel",
|
||||
"label": "Save button",
|
||||
"type": "buttonConfiguration",
|
||||
"key": "buttons",
|
||||
"nested": true,
|
||||
"defaultValue": "Save"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"key": "deleteButtonLabel",
|
||||
"label": "Delete button",
|
||||
"nested": true,
|
||||
"defaultValue": "Delete",
|
||||
"dependsOn": {
|
||||
"setting": "actionType",
|
||||
"value": "Update"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "url",
|
||||
"label": "Navigate after button press",
|
||||
"key": "actionUrl",
|
||||
"placeholder": "Choose a screen",
|
||||
"dependsOn": {
|
||||
"setting": "actionType",
|
||||
"value": "View",
|
||||
"invert": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"label": "Hide notifications",
|
||||
"key": "notificationOverride",
|
||||
"defaultValue": false,
|
||||
"dependsOn": {
|
||||
"setting": "actionType",
|
||||
"value": "View",
|
||||
"invert": true
|
||||
}
|
||||
"resetOn": ["actionType", "dataSource"]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
import BlockComponent from "components/BlockComponent.svelte"
|
||||
import { makePropSafe as safe } from "@budibase/string-templates"
|
||||
import { enrichSearchColumns, enrichFilter } from "utils/blocks.js"
|
||||
import { Utils } from "@budibase/frontend-core"
|
||||
|
||||
export let title
|
||||
export let dataSource
|
||||
|
@ -33,6 +34,7 @@
|
|||
export let notificationOverride
|
||||
|
||||
const { fetchDatasourceSchema, API } = getContext("sdk")
|
||||
const component = getContext("component")
|
||||
const stateKey = `ID_${generate()}`
|
||||
|
||||
let formId
|
||||
|
@ -259,16 +261,25 @@
|
|||
name="Details form block"
|
||||
type="formblock"
|
||||
bind:id={detailsFormBlockId}
|
||||
context="form-edit"
|
||||
props={{
|
||||
dataSource,
|
||||
saveButtonLabel: sidePanelSaveLabel || "Save", //always show
|
||||
deleteButtonLabel: deleteLabel,
|
||||
buttonPosition: "top",
|
||||
buttons: Utils.buildDynamicButtonConfig({
|
||||
_id: $component.id + "-form-edit",
|
||||
showDeleteButton: deleteLabel !== "",
|
||||
showSaveButton: true,
|
||||
saveButtonLabel: sidePanelSaveLabel || "Save",
|
||||
deleteButtonLabel: deleteLabel,
|
||||
notificationOverride,
|
||||
actionType: "Update",
|
||||
dataSource,
|
||||
}),
|
||||
actionType: "Update",
|
||||
rowId: `{{ ${safe("state")}.${safe(stateKey)} }}`,
|
||||
fields: sidePanelFields || normalFields,
|
||||
title: editTitle,
|
||||
labelPosition: "left",
|
||||
notificationOverride,
|
||||
}}
|
||||
/>
|
||||
</BlockComponent>
|
||||
|
@ -284,16 +295,23 @@
|
|||
<BlockComponent
|
||||
name="New row form block"
|
||||
type="formblock"
|
||||
context="form-new"
|
||||
props={{
|
||||
dataSource,
|
||||
showSaveButton: true,
|
||||
showDeleteButton: false,
|
||||
saveButtonLabel: sidePanelSaveLabel || "Save", //always show
|
||||
buttonPosition: "top",
|
||||
buttons: Utils.buildDynamicButtonConfig({
|
||||
_id: $component.id + "-form-new",
|
||||
showDeleteButton: false,
|
||||
showSaveButton: true,
|
||||
saveButtonLabel: "Save",
|
||||
notificationOverride,
|
||||
actionType: "Create",
|
||||
dataSource,
|
||||
}),
|
||||
actionType: "Create",
|
||||
fields: sidePanelFields || normalFields,
|
||||
title: "Create Row",
|
||||
labelPosition: "left",
|
||||
notificationOverride,
|
||||
}}
|
||||
/>
|
||||
</BlockComponent>
|
||||
|
|
|
@ -4,28 +4,31 @@
|
|||
import Block from "components/Block.svelte"
|
||||
import { makePropSafe as safe } from "@budibase/string-templates"
|
||||
import InnerFormBlock from "./InnerFormBlock.svelte"
|
||||
import { Utils } from "@budibase/frontend-core"
|
||||
|
||||
export let actionType
|
||||
export let dataSource
|
||||
export let size
|
||||
export let disabled
|
||||
export let fields
|
||||
export let buttons
|
||||
export let buttonPosition
|
||||
|
||||
export let title
|
||||
export let description
|
||||
export let showDeleteButton
|
||||
export let showSaveButton
|
||||
export let saveButtonLabel
|
||||
export let deleteButtonLabel
|
||||
export let rowId
|
||||
export let actionUrl
|
||||
export let noRowsMessage
|
||||
export let notificationOverride
|
||||
|
||||
// Accommodate old config to ensure delete button does not reappear
|
||||
$: deleteLabel = showDeleteButton === false ? "" : deleteButtonLabel?.trim()
|
||||
$: saveLabel = showSaveButton === false ? "" : saveButtonLabel?.trim()
|
||||
// Legacy
|
||||
export let showDeleteButton
|
||||
export let showSaveButton
|
||||
export let saveButtonLabel
|
||||
export let deleteButtonLabel
|
||||
|
||||
const { fetchDatasourceSchema } = getContext("sdk")
|
||||
const component = getContext("component")
|
||||
|
||||
const convertOldFieldFormat = fields => {
|
||||
if (!fields) {
|
||||
|
@ -98,11 +101,23 @@
|
|||
fields: fieldsOrDefault,
|
||||
title,
|
||||
description,
|
||||
saveButtonLabel: saveLabel,
|
||||
deleteButtonLabel: deleteLabel,
|
||||
schema,
|
||||
repeaterId,
|
||||
notificationOverride,
|
||||
buttons:
|
||||
buttons ||
|
||||
Utils.buildDynamicButtonConfig({
|
||||
_id: $component.id,
|
||||
showDeleteButton,
|
||||
showSaveButton,
|
||||
saveButtonLabel,
|
||||
deleteButtonLabel,
|
||||
notificationOverride,
|
||||
actionType,
|
||||
actionUrl,
|
||||
dataSource,
|
||||
}),
|
||||
buttonPosition: buttons ? buttonPosition : "top",
|
||||
}
|
||||
const fetchSchema = async () => {
|
||||
schema = (await fetchDatasourceSchema(dataSource)) || {}
|
||||
|
|
|
@ -1,22 +1,18 @@
|
|||
<script>
|
||||
import BlockComponent from "components/BlockComponent.svelte"
|
||||
import Placeholder from "components/app/Placeholder.svelte"
|
||||
import { makePropSafe as safe } from "@budibase/string-templates"
|
||||
import { getContext } from "svelte"
|
||||
|
||||
export let dataSource
|
||||
export let actionUrl
|
||||
export let actionType
|
||||
export let size
|
||||
export let disabled
|
||||
export let fields
|
||||
export let title
|
||||
export let description
|
||||
export let saveButtonLabel
|
||||
export let deleteButtonLabel
|
||||
export let buttons
|
||||
export let buttonPosition = "bottom"
|
||||
export let schema
|
||||
export let repeaterId
|
||||
export let notificationOverride
|
||||
|
||||
const FieldTypeToComponentMap = {
|
||||
string: "stringfield",
|
||||
|
@ -37,74 +33,7 @@
|
|||
|
||||
let formId
|
||||
|
||||
$: onSave = [
|
||||
{
|
||||
"##eventHandlerType": "Validate Form",
|
||||
parameters: {
|
||||
componentId: formId,
|
||||
},
|
||||
},
|
||||
{
|
||||
"##eventHandlerType": "Save Row",
|
||||
parameters: {
|
||||
providerId: formId,
|
||||
tableId: dataSource?.resourceId,
|
||||
notificationOverride,
|
||||
},
|
||||
},
|
||||
{
|
||||
"##eventHandlerType": "Close Screen Modal",
|
||||
},
|
||||
{
|
||||
"##eventHandlerType": "Close Side Panel",
|
||||
},
|
||||
// Clear a create form once submitted
|
||||
...(actionType !== "Create"
|
||||
? []
|
||||
: [
|
||||
{
|
||||
"##eventHandlerType": "Clear Form",
|
||||
parameters: {
|
||||
componentId: formId,
|
||||
},
|
||||
},
|
||||
]),
|
||||
{
|
||||
"##eventHandlerType": "Navigate To",
|
||||
parameters: {
|
||||
url: actionUrl,
|
||||
},
|
||||
},
|
||||
]
|
||||
$: onDelete = [
|
||||
{
|
||||
"##eventHandlerType": "Delete Row",
|
||||
parameters: {
|
||||
confirm: true,
|
||||
tableId: dataSource?.resourceId,
|
||||
rowId: `{{ ${safe(repeaterId)}.${safe("_id")} }}`,
|
||||
revId: `{{ ${safe(repeaterId)}.${safe("_rev")} }}`,
|
||||
notificationOverride,
|
||||
},
|
||||
},
|
||||
{
|
||||
"##eventHandlerType": "Close Screen Modal",
|
||||
},
|
||||
{
|
||||
"##eventHandlerType": "Close Side Panel",
|
||||
},
|
||||
{
|
||||
"##eventHandlerType": "Navigate To",
|
||||
parameters: {
|
||||
url: actionUrl,
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
$: renderDeleteButton = deleteButtonLabel && actionType === "Update"
|
||||
$: renderSaveButton = saveButtonLabel && actionType !== "View"
|
||||
$: renderButtons = renderDeleteButton || renderSaveButton
|
||||
$: renderHeader = renderButtons || title
|
||||
$: renderHeader = buttons || title
|
||||
|
||||
const getComponentForField = field => {
|
||||
const fieldSchemaName = field.field || field.name
|
||||
|
@ -184,42 +113,14 @@
|
|||
props={{ text: title || "" }}
|
||||
order={0}
|
||||
/>
|
||||
{#if renderButtons}
|
||||
{#if buttonPosition == "top"}
|
||||
<BlockComponent
|
||||
type="container"
|
||||
type="buttongroup"
|
||||
props={{
|
||||
direction: "row",
|
||||
hAlign: "stretch",
|
||||
vAlign: "center",
|
||||
gap: "M",
|
||||
wrap: true,
|
||||
buttons,
|
||||
}}
|
||||
order={1}
|
||||
>
|
||||
{#if renderDeleteButton}
|
||||
<BlockComponent
|
||||
type="button"
|
||||
props={{
|
||||
text: deleteButtonLabel,
|
||||
onClick: onDelete,
|
||||
quiet: true,
|
||||
type: "secondary",
|
||||
}}
|
||||
order={0}
|
||||
/>
|
||||
{/if}
|
||||
{#if renderSaveButton}
|
||||
<BlockComponent
|
||||
type="button"
|
||||
props={{
|
||||
text: saveButtonLabel,
|
||||
onClick: onSave,
|
||||
type: "cta",
|
||||
}}
|
||||
order={1}
|
||||
/>
|
||||
{/if}
|
||||
</BlockComponent>
|
||||
order={0}
|
||||
/>
|
||||
{/if}
|
||||
</BlockComponent>
|
||||
</BlockComponent>
|
||||
|
@ -245,6 +146,20 @@
|
|||
</BlockComponent>
|
||||
{/key}
|
||||
</BlockComponent>
|
||||
{#if buttonPosition === "bottom"}
|
||||
<BlockComponent
|
||||
type="buttongroup"
|
||||
props={{
|
||||
buttons,
|
||||
}}
|
||||
styles={{
|
||||
normal: {
|
||||
"margin-top": "16",
|
||||
},
|
||||
}}
|
||||
order={1}
|
||||
/>
|
||||
{/if}
|
||||
</BlockComponent>
|
||||
{:else}
|
||||
<Placeholder
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
import { makePropSafe as safe } from "@budibase/string-templates"
|
||||
import { Helpers } from "@budibase/bbui"
|
||||
|
||||
/**
|
||||
* Utility to wrap an async function and ensure all invocations happen
|
||||
* sequentially.
|
||||
|
@ -106,3 +109,135 @@ export const domDebounce = callback => {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the default FormBlock button configs per actionType
|
||||
* Parse any legacy button config and mirror its the outcome
|
||||
*
|
||||
* @param {any} props
|
||||
* */
|
||||
export const buildDynamicButtonConfig = props => {
|
||||
const {
|
||||
_id,
|
||||
actionType,
|
||||
dataSource,
|
||||
notificationOverride,
|
||||
actionUrl,
|
||||
showDeleteButton,
|
||||
deleteButtonLabel,
|
||||
showSaveButton,
|
||||
saveButtonLabel,
|
||||
} = props || {}
|
||||
|
||||
if (!_id) {
|
||||
console.log("MISSING ID")
|
||||
return
|
||||
}
|
||||
const formId = `${_id}-form`
|
||||
const repeaterId = `${_id}-repeater`
|
||||
const resourceId = dataSource?.resourceId
|
||||
|
||||
// Accommodate old config to ensure delete button does not reappear
|
||||
const deleteText = showDeleteButton === false ? "" : deleteButtonLabel?.trim()
|
||||
const saveText = showSaveButton === false ? "" : saveButtonLabel?.trim()
|
||||
|
||||
const onSave = [
|
||||
{
|
||||
"##eventHandlerType": "Validate Form",
|
||||
parameters: {
|
||||
componentId: formId,
|
||||
},
|
||||
},
|
||||
{
|
||||
"##eventHandlerType": "Save Row",
|
||||
parameters: {
|
||||
providerId: formId,
|
||||
tableId: resourceId,
|
||||
notificationOverride,
|
||||
},
|
||||
},
|
||||
{
|
||||
"##eventHandlerType": "Close Screen Modal",
|
||||
},
|
||||
{
|
||||
"##eventHandlerType": "Close Side Panel",
|
||||
},
|
||||
// Clear a create form once submitted
|
||||
...(actionType !== "Create"
|
||||
? []
|
||||
: [
|
||||
{
|
||||
"##eventHandlerType": "Clear Form",
|
||||
parameters: {
|
||||
componentId: formId,
|
||||
},
|
||||
},
|
||||
]),
|
||||
|
||||
...(actionUrl
|
||||
? [
|
||||
{
|
||||
"##eventHandlerType": "Navigate To",
|
||||
parameters: {
|
||||
url: actionUrl,
|
||||
},
|
||||
},
|
||||
]
|
||||
: []),
|
||||
]
|
||||
|
||||
const onDelete = [
|
||||
{
|
||||
"##eventHandlerType": "Delete Row",
|
||||
parameters: {
|
||||
confirm: true,
|
||||
tableId: resourceId,
|
||||
rowId: `{{ ${safe(repeaterId)}.${safe("_id")} }}`,
|
||||
revId: `{{ ${safe(repeaterId)}.${safe("_rev")} }}`,
|
||||
notificationOverride,
|
||||
},
|
||||
},
|
||||
{
|
||||
"##eventHandlerType": "Close Screen Modal",
|
||||
},
|
||||
{
|
||||
"##eventHandlerType": "Close Side Panel",
|
||||
},
|
||||
|
||||
...(actionUrl
|
||||
? [
|
||||
{
|
||||
"##eventHandlerType": "Navigate To",
|
||||
parameters: {
|
||||
url: actionUrl,
|
||||
},
|
||||
},
|
||||
]
|
||||
: []),
|
||||
]
|
||||
|
||||
const defaultButtons = []
|
||||
|
||||
if (["Update", "Create"].includes(actionType) && showSaveButton !== false) {
|
||||
defaultButtons.push({
|
||||
text: saveText || "Save",
|
||||
_id: Helpers.uuid(),
|
||||
_component: "@budibase/standard-components/button",
|
||||
onClick: onSave,
|
||||
type: "cta",
|
||||
})
|
||||
}
|
||||
|
||||
if (actionType == "Update" && showDeleteButton !== false) {
|
||||
defaultButtons.push({
|
||||
text: deleteText || "Delete",
|
||||
_id: Helpers.uuid(),
|
||||
_component: "@budibase/standard-components/button",
|
||||
onClick: onDelete,
|
||||
quiet: true,
|
||||
type: "secondary",
|
||||
})
|
||||
}
|
||||
|
||||
return defaultButtons
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import {
|
|||
tenancy,
|
||||
context,
|
||||
users,
|
||||
auth,
|
||||
} from "@budibase/backend-core"
|
||||
import { generateUserMetadataID, isDevAppID } from "../db/utils"
|
||||
import { getCachedSelf } from "../utilities/global"
|
||||
|
@ -69,28 +70,34 @@ export default async (ctx: UserCtx, next: any) => {
|
|||
return next()
|
||||
}
|
||||
|
||||
return context.doInAppContext(appId, async () => {
|
||||
// if the user not in the right tenant then make sure they have no permissions
|
||||
// need to judge this only based on the request app ID,
|
||||
if (
|
||||
env.MULTI_TENANCY &&
|
||||
ctx.user?._id &&
|
||||
requestAppId &&
|
||||
!tenancy.isUserInAppTenant(requestAppId, ctx.user)
|
||||
) {
|
||||
// don't error, simply remove the users rights (they are a public user)
|
||||
ctx.user = users.cleanseUserObject(ctx.user) as ContextUser
|
||||
ctx.isAuthenticated = false
|
||||
roleId = roles.BUILTIN_ROLE_IDS.PUBLIC
|
||||
}
|
||||
const userId = ctx.user ? generateUserMetadataID(ctx.user._id!) : undefined
|
||||
|
||||
// if the user is not in the right tenant then make sure to wipe their cookie
|
||||
// also cleanse any information about them that has been allocated
|
||||
// this avoids apps making calls to say the worker which are cross tenant,
|
||||
// we simply remove the authentication
|
||||
if (
|
||||
env.MULTI_TENANCY &&
|
||||
userId &&
|
||||
requestAppId &&
|
||||
!tenancy.isUserInAppTenant(requestAppId, ctx.user)
|
||||
) {
|
||||
// clear out the user
|
||||
ctx.user = users.cleanseUserObject(ctx.user) as ContextUser
|
||||
ctx.isAuthenticated = false
|
||||
roleId = roles.BUILTIN_ROLE_IDS.PUBLIC
|
||||
// remove the cookie, so future calls are public
|
||||
await auth.platformLogout({
|
||||
ctx,
|
||||
userId,
|
||||
})
|
||||
}
|
||||
|
||||
return context.doInAppContext(appId, async () => {
|
||||
ctx.appId = appId
|
||||
if (roleId) {
|
||||
ctx.roleId = roleId
|
||||
const globalId = ctx.user ? ctx.user._id : undefined
|
||||
const userId = ctx.user
|
||||
? generateUserMetadataID(ctx.user._id!)
|
||||
: undefined
|
||||
ctx.user = {
|
||||
...ctx.user!,
|
||||
// override userID with metadata one
|
||||
|
|
|
@ -137,6 +137,10 @@ class TestConfiguration {
|
|||
}
|
||||
|
||||
getAppId() {
|
||||
if (!this.appId) {
|
||||
throw "appId has not been initialised properly"
|
||||
}
|
||||
|
||||
return this.appId
|
||||
}
|
||||
|
||||
|
@ -510,7 +514,7 @@ class TestConfiguration {
|
|||
// create dev app
|
||||
// clear any old app
|
||||
this.appId = null
|
||||
this.app = await context.doInAppContext(null, async () => {
|
||||
this.app = await context.doInTenant(this.tenantId!, async () => {
|
||||
const app = await this._req(
|
||||
{ name: appName },
|
||||
null,
|
||||
|
@ -519,7 +523,7 @@ class TestConfiguration {
|
|||
this.appId = app.appId!
|
||||
return app
|
||||
})
|
||||
return await context.doInAppContext(this.appId, async () => {
|
||||
return await context.doInAppContext(this.getAppId(), async () => {
|
||||
// create production app
|
||||
this.prodApp = await this.publish()
|
||||
|
||||
|
@ -817,7 +821,7 @@ class TestConfiguration {
|
|||
}
|
||||
|
||||
async getAutomationLogs() {
|
||||
return context.doInAppContext(this.appId, async () => {
|
||||
return context.doInAppContext(this.getAppId(), async () => {
|
||||
const now = new Date()
|
||||
return await pro.sdk.automations.logs.logSearch({
|
||||
startDate: new Date(now.getTime() - 100000).toISOString(),
|
||||
|
|
Loading…
Reference in New Issue