diff --git a/helm/superset/Chart.yaml b/helm/superset/Chart.yaml index 23ab47dc6ae6c..d6915090dd819 100644 --- a/helm/superset/Chart.yaml +++ b/helm/superset/Chart.yaml @@ -15,7 +15,7 @@ # limitations under the License. # apiVersion: v2 -appVersion: "3.0.2" +appVersion: "3.0.3" description: Apache Superset is a modern, enterprise-ready business intelligence web application name: superset icon: https://artifacthub.io/image/68c1d717-0e97-491f-b046-754e46f46922@2x diff --git a/helm/superset/README.md b/helm/superset/README.md index 56f2323cd8fcf..333f74d78949b 100644 --- a/helm/superset/README.md +++ b/helm/superset/README.md @@ -31,7 +31,7 @@ Apache Superset is a modern, enterprise-ready business intelligence web applicat ## Source Code -- +* ## TL;DR @@ -48,242 +48,242 @@ On helm this can be set on `extraSecretEnv.SUPERSET_SECRET_KEY` or `configOverri ## Requirements -| Repository | Name | Version | -| ---------------------------------- | ---------- | ------- | -| https://charts.bitnami.com/bitnami | postgresql | 12.1.6 | -| https://charts.bitnami.com/bitnami | redis | 17.9.4 | +| Repository | Name | Version | +|------------|------|---------| +| https://charts.bitnami.com/bitnami | postgresql | 12.1.6 | +| https://charts.bitnami.com/bitnami | redis | 17.9.4 | ## Values -| Key | Type | Default | Description | -| ------------------------------------------------------- | ------ | -------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| affinity | object | `{}` | | -| bootstrapScript | string | see `values.yaml` | Install additional packages and do any other bootstrap configuration in this script For production clusters it's recommended to build own image with this step done in CI | -| configFromSecret | string | `"{{ template \"superset.fullname\" . }}-config"` | The name of the secret which we will use to generate a superset_config.py file Note: this secret must have the key superset_config.py in it and can include other files as well | -| configMountPath | string | `"/app/pythonpath"` | | -| configOverrides | object | `{}` | A dictionary of overrides to append at the end of superset_config.py - the name does not matter WARNING: the order is not guaranteed Files can be passed as helm --set-file configOverrides.my-override=my-file.py | -| configOverridesFiles | object | `{}` | Same as above but the values are files | -| envFromSecret | string | `"{{ template \"superset.fullname\" . }}-env"` | The name of the secret which we will use to populate env vars in deployed pods This can be useful for secret keys, etc. | -| envFromSecrets | list | `[]` | This can be a list of templated strings | -| extraConfigMountPath | string | `"/app/configs"` | | -| extraConfigs | object | `{}` | Extra files to mount on `/app/pythonpath` | -| extraEnv | object | `{}` | Extra environment variables that will be passed into pods | -| extraEnvRaw | list | `[]` | Extra environment variables in RAW format that will be passed into pods | -| extraSecretEnv | object | `{}` | Extra environment variables to pass as secrets | -| extraSecrets | object | `{}` | Extra files to mount on `/app/pythonpath` as secrets | -| extraVolumeMounts | list | `[]` | | -| extraVolumes | list | `[]` | | -| fullnameOverride | string | `nil` | Provide a name to override the full names of resources | -| hostAliases | list | `[]` | Custom hostAliases for all superset pods # https://kubernetes.io/docs/tasks/network/customize-hosts-file-for-pods/ | -| image.pullPolicy | string | `"IfNotPresent"` | | -| image.repository | string | `"apachesuperset.docker.scarf.sh/apache/superset"` | | -| image.tag | string | `""` | | -| imagePullSecrets | list | `[]` | | -| ingress.annotations | object | `{}` | | -| ingress.enabled | bool | `false` | | -| ingress.extraHostsRaw | list | `[]` | | -| ingress.hosts[0] | string | `"chart-example.local"` | | -| ingress.ingressClassName | string | `nil` | | -| ingress.path | string | `"/"` | | -| ingress.pathType | string | `"ImplementationSpecific"` | | -| ingress.tls | list | `[]` | | -| init.adminUser.email | string | `"admin@superset.com"` | | -| init.adminUser.firstname | string | `"Superset"` | | -| init.adminUser.lastname | string | `"Admin"` | | -| init.adminUser.password | string | `"admin"` | | -| init.adminUser.username | string | `"admin"` | | -| init.affinity | object | `{}` | | -| init.command | list | a `superset_init.sh` command | Command | -| init.containerSecurityContext | object | `{}` | | -| init.createAdmin | bool | `true` | | -| init.enabled | bool | `true` | | -| init.initContainers | list | a container waiting for postgres | List of initContainers | -| init.initscript | string | a script to create admin user and initailize roles | A Superset init script | -| init.jobAnnotations."helm.sh/hook" | string | `"post-install,post-upgrade"` | | -| init.jobAnnotations."helm.sh/hook-delete-policy" | string | `"before-hook-creation"` | | -| init.loadExamples | bool | `false` | | -| init.podAnnotations | object | `{}` | | -| init.podSecurityContext | object | `{}` | | -| init.resources | object | `{}` | | -| init.tolerations | list | `[]` | | -| init.topologySpreadConstraints | list | `[]` | TopologySpreadConstrains to be added to init job | -| initImage.pullPolicy | string | `"IfNotPresent"` | | -| initImage.repository | string | `"apache/superset"` | | -| initImage.tag | string | `"dockerize"` | | -| nameOverride | string | `nil` | Provide a name to override the name of the chart | -| nodeSelector | object | `{}` | | -| postgresql | object | see `values.yaml` | Configuration values for the postgresql dependency. ref: https://github.com/kubernetes/charts/blob/master/stable/postgresql/README.md | -| redis | object | see `values.yaml` | Configuration values for the Redis dependency. ref: https://github.com/bitnami/charts/blob/master/bitnami/redis More documentation can be found here: https://artifacthub.io/packages/helm/bitnami/redis | -| resources | object | `{}` | | -| runAsUser | int | `0` | User ID directive. This user must have enough permissions to run the bootstrap script Running containers as root is not recommended in production. Change this to another UID - e.g. 1000 to be more secure | -| service.annotations | object | `{}` | | -| service.loadBalancerIP | string | `nil` | | -| service.nodePort.http | int | `"nil"` | | -| service.port | int | `8088` | | -| service.type | string | `"ClusterIP"` | | -| serviceAccount.annotations | object | `{}` | | -| serviceAccount.create | bool | `false` | Create custom service account for Superset. If create: true and serviceAccountName is not provided, `superset.fullname` will be used. | -| serviceAccountName | string | `nil` | Specify service account name to be used | -| supersetCeleryBeat.affinity | object | `{}` | Affinity to be added to supersetCeleryBeat deployment | -| supersetCeleryBeat.command | list | a `celery beat` command | Command | -| supersetCeleryBeat.containerSecurityContext | object | `{}` | | -| supersetCeleryBeat.deploymentAnnotations | object | `{}` | Annotations to be added to supersetCeleryBeat deployment | -| supersetCeleryBeat.enabled | bool | `false` | This is only required if you intend to use alerts and reports | -| supersetCeleryBeat.forceReload | bool | `false` | If true, forces deployment to reload on each upgrade | -| supersetCeleryBeat.initContainers | list | a container waiting for postgres | List of init containers | -| supersetCeleryBeat.podAnnotations | object | `{}` | Annotations to be added to supersetCeleryBeat pods | -| supersetCeleryBeat.podLabels | object | `{}` | Labels to be added to supersetCeleryBeat pods | -| supersetCeleryBeat.podSecurityContext | object | `{}` | | -| supersetCeleryBeat.resources | object | `{}` | Resource settings for the CeleryBeat pods - these settings overwrite might existing values from the global resources object defined above. | -| supersetCeleryBeat.topologySpreadConstraints | list | `[]` | TopologySpreadConstrains to be added to supersetCeleryBeat deployments | -| supersetCeleryFlower.affinity | object | `{}` | Affinity to be added to supersetCeleryFlower deployment | -| supersetCeleryFlower.command | list | a `celery flower` command | Command | -| supersetCeleryFlower.containerSecurityContext | object | `{}` | | -| supersetCeleryFlower.deploymentAnnotations | object | `{}` | Annotations to be added to supersetCeleryFlower deployment | -| supersetCeleryFlower.enabled | bool | `false` | Enables a Celery flower deployment (management UI to monitor celery jobs) WARNING: on superset 1.x, this requires a Superset image that has `flower<1.0.0` installed (which is NOT the case of the default images) flower>=1.0.0 requires Celery 5+ which Superset 1.5 does not support | -| supersetCeleryFlower.initContainers | list | a container waiting for postgres and redis | List of init containers | -| supersetCeleryFlower.livenessProbe.failureThreshold | int | `3` | | -| supersetCeleryFlower.livenessProbe.httpGet.path | string | `"/api/workers"` | | -| supersetCeleryFlower.livenessProbe.httpGet.port | string | `"flower"` | | -| supersetCeleryFlower.livenessProbe.initialDelaySeconds | int | `5` | | -| supersetCeleryFlower.livenessProbe.periodSeconds | int | `5` | | -| supersetCeleryFlower.livenessProbe.successThreshold | int | `1` | | -| supersetCeleryFlower.livenessProbe.timeoutSeconds | int | `1` | | -| supersetCeleryFlower.podAnnotations | object | `{}` | Annotations to be added to supersetCeleryFlower pods | -| supersetCeleryFlower.podLabels | object | `{}` | Labels to be added to supersetCeleryFlower pods | -| supersetCeleryFlower.podSecurityContext | object | `{}` | | -| supersetCeleryFlower.readinessProbe.failureThreshold | int | `3` | | -| supersetCeleryFlower.readinessProbe.httpGet.path | string | `"/api/workers"` | | -| supersetCeleryFlower.readinessProbe.httpGet.port | string | `"flower"` | | -| supersetCeleryFlower.readinessProbe.initialDelaySeconds | int | `5` | | -| supersetCeleryFlower.readinessProbe.periodSeconds | int | `5` | | -| supersetCeleryFlower.readinessProbe.successThreshold | int | `1` | | -| supersetCeleryFlower.readinessProbe.timeoutSeconds | int | `1` | | -| supersetCeleryFlower.replicaCount | int | `1` | | -| supersetCeleryFlower.resources | object | `{}` | Resource settings for the CeleryBeat pods - these settings overwrite might existing values from the global resources object defined above. | -| supersetCeleryFlower.service.annotations | object | `{}` | | -| supersetCeleryFlower.service.loadBalancerIP | string | `nil` | | -| supersetCeleryFlower.service.nodePort.http | int | `"nil"` | | -| supersetCeleryFlower.service.port | int | `5555` | | -| supersetCeleryFlower.service.type | string | `"ClusterIP"` | | -| supersetCeleryFlower.startupProbe.failureThreshold | int | `60` | | -| supersetCeleryFlower.startupProbe.httpGet.path | string | `"/api/workers"` | | -| supersetCeleryFlower.startupProbe.httpGet.port | string | `"flower"` | | -| supersetCeleryFlower.startupProbe.initialDelaySeconds | int | `5` | | -| supersetCeleryFlower.startupProbe.periodSeconds | int | `5` | | -| supersetCeleryFlower.startupProbe.successThreshold | int | `1` | | -| supersetCeleryFlower.startupProbe.timeoutSeconds | int | `1` | | -| supersetCeleryFlower.topologySpreadConstraints | list | `[]` | TopologySpreadConstrains to be added to supersetCeleryFlower deployments | -| supersetNode.affinity | object | `{}` | Affinity to be added to supersetNode deployment | -| supersetNode.command | list | See `values.yaml` | Startup command | -| supersetNode.connections.db_host | string | `"{{ .Release.Name }}-postgresql"` | | -| supersetNode.connections.db_name | string | `"superset"` | | -| supersetNode.connections.db_pass | string | `"superset"` | | -| supersetNode.connections.db_port | string | `"5432"` | | -| supersetNode.connections.db_user | string | `"superset"` | | -| supersetNode.connections.redis_host | string | `"{{ .Release.Name }}-redis-headless"` | Change in case of bringing your own redis and then also set redis.enabled:false | -| supersetNode.connections.redis_port | string | `"6379"` | | -| supersetNode.containerSecurityContext | object | `{}` | | -| supersetNode.deploymentAnnotations | object | `{}` | Annotations to be added to supersetNode deployment | -| supersetNode.deploymentLabels | object | `{}` | Labels to be added to supersetNode deployment | -| supersetNode.env | object | `{}` | | -| supersetNode.extraContainers | list | `[]` | Launch additional containers into supersetNode pod | -| supersetNode.forceReload | bool | `false` | If true, forces deployment to reload on each upgrade | -| supersetNode.initContainers | list | a container waiting for postgres | Init containers | -| supersetNode.livenessProbe.failureThreshold | int | `3` | | -| supersetNode.livenessProbe.httpGet.path | string | `"/health"` | | -| supersetNode.livenessProbe.httpGet.port | string | `"http"` | | -| supersetNode.livenessProbe.initialDelaySeconds | int | `15` | | -| supersetNode.livenessProbe.periodSeconds | int | `15` | | -| supersetNode.livenessProbe.successThreshold | int | `1` | | -| supersetNode.livenessProbe.timeoutSeconds | int | `1` | | -| supersetNode.podAnnotations | object | `{}` | Annotations to be added to supersetNode pods | -| supersetNode.podLabels | object | `{}` | Labels to be added to supersetNode pods | -| supersetNode.podSecurityContext | object | `{}` | | -| supersetNode.readinessProbe.failureThreshold | int | `3` | | -| supersetNode.readinessProbe.httpGet.path | string | `"/health"` | | -| supersetNode.readinessProbe.httpGet.port | string | `"http"` | | -| supersetNode.readinessProbe.initialDelaySeconds | int | `15` | | -| supersetNode.readinessProbe.periodSeconds | int | `15` | | -| supersetNode.readinessProbe.successThreshold | int | `1` | | -| supersetNode.readinessProbe.timeoutSeconds | int | `1` | | -| supersetNode.replicaCount | int | `1` | | -| supersetNode.resources | object | `{}` | Resource settings for the supersetNode pods - these settings overwrite might existing values from the global resources object defined above. | -| supersetNode.startupProbe.failureThreshold | int | `60` | | -| supersetNode.startupProbe.httpGet.path | string | `"/health"` | | -| supersetNode.startupProbe.httpGet.port | string | `"http"` | | -| supersetNode.startupProbe.initialDelaySeconds | int | `15` | | -| supersetNode.startupProbe.periodSeconds | int | `5` | | -| supersetNode.startupProbe.successThreshold | int | `1` | | -| supersetNode.startupProbe.timeoutSeconds | int | `1` | | -| supersetNode.strategy | object | `{}` | | -| supersetNode.topologySpreadConstraints | list | `[]` | TopologySpreadConstrains to be added to supersetNode deployments | -| supersetWebsockets.affinity | object | `{}` | Affinity to be added to supersetWebsockets deployment | -| supersetWebsockets.command | list | `[]` | | -| supersetWebsockets.config | object | see `values.yaml` | The config.json to pass to the server, see https://github.com/apache/superset/tree/master/superset-websocket Note that the configuration can also read from environment variables (which will have priority), see https://github.com/apache/superset/blob/master/superset-websocket/src/config.ts for a list of supported variables | -| supersetWebsockets.containerSecurityContext | object | `{}` | | -| supersetWebsockets.deploymentAnnotations | object | `{}` | | -| supersetWebsockets.enabled | bool | `false` | This is only required if you intend to use `GLOBAL_ASYNC_QUERIES` in `ws` mode see https://github.com/apache/superset/blob/master/CONTRIBUTING.md#async-chart-queries | -| supersetWebsockets.image.pullPolicy | string | `"IfNotPresent"` | | -| supersetWebsockets.image.repository | string | `"oneacrefund/superset-websocket"` | There is no official image (yet), this one is community-supported | -| supersetWebsockets.image.tag | string | `"latest"` | | -| supersetWebsockets.ingress.path | string | `"/ws"` | | -| supersetWebsockets.ingress.pathType | string | `"Prefix"` | | -| supersetWebsockets.livenessProbe.failureThreshold | int | `3` | | -| supersetWebsockets.livenessProbe.httpGet.path | string | `"/health"` | | -| supersetWebsockets.livenessProbe.httpGet.port | string | `"ws"` | | -| supersetWebsockets.livenessProbe.initialDelaySeconds | int | `5` | | -| supersetWebsockets.livenessProbe.periodSeconds | int | `5` | | -| supersetWebsockets.livenessProbe.successThreshold | int | `1` | | -| supersetWebsockets.livenessProbe.timeoutSeconds | int | `1` | | -| supersetWebsockets.podAnnotations | object | `{}` | | -| supersetWebsockets.podLabels | object | `{}` | | -| supersetWebsockets.podSecurityContext | object | `{}` | | -| supersetWebsockets.readinessProbe.failureThreshold | int | `3` | | -| supersetWebsockets.readinessProbe.httpGet.path | string | `"/health"` | | -| supersetWebsockets.readinessProbe.httpGet.port | string | `"ws"` | | -| supersetWebsockets.readinessProbe.initialDelaySeconds | int | `5` | | -| supersetWebsockets.readinessProbe.periodSeconds | int | `5` | | -| supersetWebsockets.readinessProbe.successThreshold | int | `1` | | -| supersetWebsockets.readinessProbe.timeoutSeconds | int | `1` | | -| supersetWebsockets.replicaCount | int | `1` | | -| supersetWebsockets.resources | object | `{}` | | -| supersetWebsockets.service.annotations | object | `{}` | | -| supersetWebsockets.service.loadBalancerIP | string | `nil` | | -| supersetWebsockets.service.nodePort.http | int | `"nil"` | | -| supersetWebsockets.service.port | int | `8080` | | -| supersetWebsockets.service.type | string | `"ClusterIP"` | | -| supersetWebsockets.startupProbe.failureThreshold | int | `60` | | -| supersetWebsockets.startupProbe.httpGet.path | string | `"/health"` | | -| supersetWebsockets.startupProbe.httpGet.port | string | `"ws"` | | -| supersetWebsockets.startupProbe.initialDelaySeconds | int | `5` | | -| supersetWebsockets.startupProbe.periodSeconds | int | `5` | | -| supersetWebsockets.startupProbe.successThreshold | int | `1` | | -| supersetWebsockets.startupProbe.timeoutSeconds | int | `1` | | -| supersetWebsockets.strategy | object | `{}` | | -| supersetWebsockets.topologySpreadConstraints | list | `[]` | TopologySpreadConstrains to be added to supersetWebsockets deployments | -| supersetWorker.affinity | object | `{}` | Affinity to be added to supersetWorker deployment | -| supersetWorker.command | list | a `celery worker` command | Worker startup command | -| supersetWorker.containerSecurityContext | object | `{}` | | -| supersetWorker.deploymentAnnotations | object | `{}` | Annotations to be added to supersetWorker deployment | -| supersetWorker.deploymentLabels | object | `{}` | Labels to be added to supersetWorker deployment | -| supersetWorker.extraContainers | list | `[]` | Launch additional containers into supersetWorker pod | -| supersetWorker.forceReload | bool | `false` | If true, forces deployment to reload on each upgrade | -| supersetWorker.initContainers | list | a container waiting for postgres and redis | Init container | -| supersetWorker.livenessProbe.exec.command | list | a `celery inspect ping` command | Liveness probe command | -| supersetWorker.livenessProbe.failureThreshold | int | `3` | | -| supersetWorker.livenessProbe.initialDelaySeconds | int | `120` | | -| supersetWorker.livenessProbe.periodSeconds | int | `60` | | -| supersetWorker.livenessProbe.successThreshold | int | `1` | | -| supersetWorker.livenessProbe.timeoutSeconds | int | `60` | | -| supersetWorker.podAnnotations | object | `{}` | Annotations to be added to supersetWorker pods | -| supersetWorker.podLabels | object | `{}` | Labels to be added to supersetWorker pods | -| supersetWorker.podSecurityContext | object | `{}` | | -| supersetWorker.readinessProbe | object | `{}` | No startup/readiness probes by default since we don't really care about its startup time (it doesn't serve traffic) | -| supersetWorker.replicaCount | int | `1` | | -| supersetWorker.resources | object | `{}` | Resource settings for the supersetWorker pods - these settings overwrite might existing values from the global resources object defined above. | -| supersetWorker.startupProbe | object | `{}` | No startup/readiness probes by default since we don't really care about its startup time (it doesn't serve traffic) | -| supersetWorker.strategy | object | `{}` | | -| supersetWorker.topologySpreadConstraints | list | `[]` | TopologySpreadConstrains to be added to supersetWorker deployments | -| tolerations | list | `[]` | | -| topologySpreadConstraints | list | `[]` | TopologySpreadConstrains to be added to all deployments | +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| affinity | object | `{}` | | +| bootstrapScript | string | see `values.yaml` | Install additional packages and do any other bootstrap configuration in this script For production clusters it's recommended to build own image with this step done in CI | +| configFromSecret | string | `"{{ template \"superset.fullname\" . }}-config"` | The name of the secret which we will use to generate a superset_config.py file Note: this secret must have the key superset_config.py in it and can include other files as well | +| configMountPath | string | `"/app/pythonpath"` | | +| configOverrides | object | `{}` | A dictionary of overrides to append at the end of superset_config.py - the name does not matter WARNING: the order is not guaranteed Files can be passed as helm --set-file configOverrides.my-override=my-file.py | +| configOverridesFiles | object | `{}` | Same as above but the values are files | +| envFromSecret | string | `"{{ template \"superset.fullname\" . }}-env"` | The name of the secret which we will use to populate env vars in deployed pods This can be useful for secret keys, etc. | +| envFromSecrets | list | `[]` | This can be a list of templated strings | +| extraConfigMountPath | string | `"/app/configs"` | | +| extraConfigs | object | `{}` | Extra files to mount on `/app/pythonpath` | +| extraEnv | object | `{}` | Extra environment variables that will be passed into pods | +| extraEnvRaw | list | `[]` | Extra environment variables in RAW format that will be passed into pods | +| extraSecretEnv | object | `{}` | Extra environment variables to pass as secrets | +| extraSecrets | object | `{}` | Extra files to mount on `/app/pythonpath` as secrets | +| extraVolumeMounts | list | `[]` | | +| extraVolumes | list | `[]` | | +| fullnameOverride | string | `nil` | Provide a name to override the full names of resources | +| hostAliases | list | `[]` | Custom hostAliases for all superset pods # https://kubernetes.io/docs/tasks/network/customize-hosts-file-for-pods/ | +| image.pullPolicy | string | `"IfNotPresent"` | | +| image.repository | string | `"apachesuperset.docker.scarf.sh/apache/superset"` | | +| image.tag | string | `""` | | +| imagePullSecrets | list | `[]` | | +| ingress.annotations | object | `{}` | | +| ingress.enabled | bool | `false` | | +| ingress.extraHostsRaw | list | `[]` | | +| ingress.hosts[0] | string | `"chart-example.local"` | | +| ingress.ingressClassName | string | `nil` | | +| ingress.path | string | `"/"` | | +| ingress.pathType | string | `"ImplementationSpecific"` | | +| ingress.tls | list | `[]` | | +| init.adminUser.email | string | `"admin@superset.com"` | | +| init.adminUser.firstname | string | `"Superset"` | | +| init.adminUser.lastname | string | `"Admin"` | | +| init.adminUser.password | string | `"admin"` | | +| init.adminUser.username | string | `"admin"` | | +| init.affinity | object | `{}` | | +| init.command | list | a `superset_init.sh` command | Command | +| init.containerSecurityContext | object | `{}` | | +| init.createAdmin | bool | `true` | | +| init.enabled | bool | `true` | | +| init.initContainers | list | a container waiting for postgres | List of initContainers | +| init.initscript | string | a script to create admin user and initailize roles | A Superset init script | +| init.jobAnnotations."helm.sh/hook" | string | `"post-install,post-upgrade"` | | +| init.jobAnnotations."helm.sh/hook-delete-policy" | string | `"before-hook-creation"` | | +| init.loadExamples | bool | `false` | | +| init.podAnnotations | object | `{}` | | +| init.podSecurityContext | object | `{}` | | +| init.resources | object | `{}` | | +| init.tolerations | list | `[]` | | +| init.topologySpreadConstraints | list | `[]` | TopologySpreadConstrains to be added to init job | +| initImage.pullPolicy | string | `"IfNotPresent"` | | +| initImage.repository | string | `"apache/superset"` | | +| initImage.tag | string | `"dockerize"` | | +| nameOverride | string | `nil` | Provide a name to override the name of the chart | +| nodeSelector | object | `{}` | | +| postgresql | object | see `values.yaml` | Configuration values for the postgresql dependency. ref: https://github.com/kubernetes/charts/blob/master/stable/postgresql/README.md | +| redis | object | see `values.yaml` | Configuration values for the Redis dependency. ref: https://github.com/bitnami/charts/blob/master/bitnami/redis More documentation can be found here: https://artifacthub.io/packages/helm/bitnami/redis | +| resources | object | `{}` | | +| runAsUser | int | `0` | User ID directive. This user must have enough permissions to run the bootstrap script Running containers as root is not recommended in production. Change this to another UID - e.g. 1000 to be more secure | +| service.annotations | object | `{}` | | +| service.loadBalancerIP | string | `nil` | | +| service.nodePort.http | int | `"nil"` | | +| service.port | int | `8088` | | +| service.type | string | `"ClusterIP"` | | +| serviceAccount.annotations | object | `{}` | | +| serviceAccount.create | bool | `false` | Create custom service account for Superset. If create: true and serviceAccountName is not provided, `superset.fullname` will be used. | +| serviceAccountName | string | `nil` | Specify service account name to be used | +| supersetCeleryBeat.affinity | object | `{}` | Affinity to be added to supersetCeleryBeat deployment | +| supersetCeleryBeat.command | list | a `celery beat` command | Command | +| supersetCeleryBeat.containerSecurityContext | object | `{}` | | +| supersetCeleryBeat.deploymentAnnotations | object | `{}` | Annotations to be added to supersetCeleryBeat deployment | +| supersetCeleryBeat.enabled | bool | `false` | This is only required if you intend to use alerts and reports | +| supersetCeleryBeat.forceReload | bool | `false` | If true, forces deployment to reload on each upgrade | +| supersetCeleryBeat.initContainers | list | a container waiting for postgres | List of init containers | +| supersetCeleryBeat.podAnnotations | object | `{}` | Annotations to be added to supersetCeleryBeat pods | +| supersetCeleryBeat.podLabels | object | `{}` | Labels to be added to supersetCeleryBeat pods | +| supersetCeleryBeat.podSecurityContext | object | `{}` | | +| supersetCeleryBeat.resources | object | `{}` | Resource settings for the CeleryBeat pods - these settings overwrite might existing values from the global resources object defined above. | +| supersetCeleryBeat.topologySpreadConstraints | list | `[]` | TopologySpreadConstrains to be added to supersetCeleryBeat deployments | +| supersetCeleryFlower.affinity | object | `{}` | Affinity to be added to supersetCeleryFlower deployment | +| supersetCeleryFlower.command | list | a `celery flower` command | Command | +| supersetCeleryFlower.containerSecurityContext | object | `{}` | | +| supersetCeleryFlower.deploymentAnnotations | object | `{}` | Annotations to be added to supersetCeleryFlower deployment | +| supersetCeleryFlower.enabled | bool | `false` | Enables a Celery flower deployment (management UI to monitor celery jobs) WARNING: on superset 1.x, this requires a Superset image that has `flower<1.0.0` installed (which is NOT the case of the default images) flower>=1.0.0 requires Celery 5+ which Superset 1.5 does not support | +| supersetCeleryFlower.initContainers | list | a container waiting for postgres and redis | List of init containers | +| supersetCeleryFlower.livenessProbe.failureThreshold | int | `3` | | +| supersetCeleryFlower.livenessProbe.httpGet.path | string | `"/api/workers"` | | +| supersetCeleryFlower.livenessProbe.httpGet.port | string | `"flower"` | | +| supersetCeleryFlower.livenessProbe.initialDelaySeconds | int | `5` | | +| supersetCeleryFlower.livenessProbe.periodSeconds | int | `5` | | +| supersetCeleryFlower.livenessProbe.successThreshold | int | `1` | | +| supersetCeleryFlower.livenessProbe.timeoutSeconds | int | `1` | | +| supersetCeleryFlower.podAnnotations | object | `{}` | Annotations to be added to supersetCeleryFlower pods | +| supersetCeleryFlower.podLabels | object | `{}` | Labels to be added to supersetCeleryFlower pods | +| supersetCeleryFlower.podSecurityContext | object | `{}` | | +| supersetCeleryFlower.readinessProbe.failureThreshold | int | `3` | | +| supersetCeleryFlower.readinessProbe.httpGet.path | string | `"/api/workers"` | | +| supersetCeleryFlower.readinessProbe.httpGet.port | string | `"flower"` | | +| supersetCeleryFlower.readinessProbe.initialDelaySeconds | int | `5` | | +| supersetCeleryFlower.readinessProbe.periodSeconds | int | `5` | | +| supersetCeleryFlower.readinessProbe.successThreshold | int | `1` | | +| supersetCeleryFlower.readinessProbe.timeoutSeconds | int | `1` | | +| supersetCeleryFlower.replicaCount | int | `1` | | +| supersetCeleryFlower.resources | object | `{}` | Resource settings for the CeleryBeat pods - these settings overwrite might existing values from the global resources object defined above. | +| supersetCeleryFlower.service.annotations | object | `{}` | | +| supersetCeleryFlower.service.loadBalancerIP | string | `nil` | | +| supersetCeleryFlower.service.nodePort.http | int | `"nil"` | | +| supersetCeleryFlower.service.port | int | `5555` | | +| supersetCeleryFlower.service.type | string | `"ClusterIP"` | | +| supersetCeleryFlower.startupProbe.failureThreshold | int | `60` | | +| supersetCeleryFlower.startupProbe.httpGet.path | string | `"/api/workers"` | | +| supersetCeleryFlower.startupProbe.httpGet.port | string | `"flower"` | | +| supersetCeleryFlower.startupProbe.initialDelaySeconds | int | `5` | | +| supersetCeleryFlower.startupProbe.periodSeconds | int | `5` | | +| supersetCeleryFlower.startupProbe.successThreshold | int | `1` | | +| supersetCeleryFlower.startupProbe.timeoutSeconds | int | `1` | | +| supersetCeleryFlower.topologySpreadConstraints | list | `[]` | TopologySpreadConstrains to be added to supersetCeleryFlower deployments | +| supersetNode.affinity | object | `{}` | Affinity to be added to supersetNode deployment | +| supersetNode.command | list | See `values.yaml` | Startup command | +| supersetNode.connections.db_host | string | `"{{ .Release.Name }}-postgresql"` | | +| supersetNode.connections.db_name | string | `"superset"` | | +| supersetNode.connections.db_pass | string | `"superset"` | | +| supersetNode.connections.db_port | string | `"5432"` | | +| supersetNode.connections.db_user | string | `"superset"` | | +| supersetNode.connections.redis_host | string | `"{{ .Release.Name }}-redis-headless"` | Change in case of bringing your own redis and then also set redis.enabled:false | +| supersetNode.connections.redis_port | string | `"6379"` | | +| supersetNode.containerSecurityContext | object | `{}` | | +| supersetNode.deploymentAnnotations | object | `{}` | Annotations to be added to supersetNode deployment | +| supersetNode.deploymentLabels | object | `{}` | Labels to be added to supersetNode deployment | +| supersetNode.env | object | `{}` | | +| supersetNode.extraContainers | list | `[]` | Launch additional containers into supersetNode pod | +| supersetNode.forceReload | bool | `false` | If true, forces deployment to reload on each upgrade | +| supersetNode.initContainers | list | a container waiting for postgres | Init containers | +| supersetNode.livenessProbe.failureThreshold | int | `3` | | +| supersetNode.livenessProbe.httpGet.path | string | `"/health"` | | +| supersetNode.livenessProbe.httpGet.port | string | `"http"` | | +| supersetNode.livenessProbe.initialDelaySeconds | int | `15` | | +| supersetNode.livenessProbe.periodSeconds | int | `15` | | +| supersetNode.livenessProbe.successThreshold | int | `1` | | +| supersetNode.livenessProbe.timeoutSeconds | int | `1` | | +| supersetNode.podAnnotations | object | `{}` | Annotations to be added to supersetNode pods | +| supersetNode.podLabels | object | `{}` | Labels to be added to supersetNode pods | +| supersetNode.podSecurityContext | object | `{}` | | +| supersetNode.readinessProbe.failureThreshold | int | `3` | | +| supersetNode.readinessProbe.httpGet.path | string | `"/health"` | | +| supersetNode.readinessProbe.httpGet.port | string | `"http"` | | +| supersetNode.readinessProbe.initialDelaySeconds | int | `15` | | +| supersetNode.readinessProbe.periodSeconds | int | `15` | | +| supersetNode.readinessProbe.successThreshold | int | `1` | | +| supersetNode.readinessProbe.timeoutSeconds | int | `1` | | +| supersetNode.replicaCount | int | `1` | | +| supersetNode.resources | object | `{}` | Resource settings for the supersetNode pods - these settings overwrite might existing values from the global resources object defined above. | +| supersetNode.startupProbe.failureThreshold | int | `60` | | +| supersetNode.startupProbe.httpGet.path | string | `"/health"` | | +| supersetNode.startupProbe.httpGet.port | string | `"http"` | | +| supersetNode.startupProbe.initialDelaySeconds | int | `15` | | +| supersetNode.startupProbe.periodSeconds | int | `5` | | +| supersetNode.startupProbe.successThreshold | int | `1` | | +| supersetNode.startupProbe.timeoutSeconds | int | `1` | | +| supersetNode.strategy | object | `{}` | | +| supersetNode.topologySpreadConstraints | list | `[]` | TopologySpreadConstrains to be added to supersetNode deployments | +| supersetWebsockets.affinity | object | `{}` | Affinity to be added to supersetWebsockets deployment | +| supersetWebsockets.command | list | `[]` | | +| supersetWebsockets.config | object | see `values.yaml` | The config.json to pass to the server, see https://github.com/apache/superset/tree/master/superset-websocket Note that the configuration can also read from environment variables (which will have priority), see https://github.com/apache/superset/blob/master/superset-websocket/src/config.ts for a list of supported variables | +| supersetWebsockets.containerSecurityContext | object | `{}` | | +| supersetWebsockets.deploymentAnnotations | object | `{}` | | +| supersetWebsockets.enabled | bool | `false` | This is only required if you intend to use `GLOBAL_ASYNC_QUERIES` in `ws` mode see https://github.com/apache/superset/blob/master/CONTRIBUTING.md#async-chart-queries | +| supersetWebsockets.image.pullPolicy | string | `"IfNotPresent"` | | +| supersetWebsockets.image.repository | string | `"oneacrefund/superset-websocket"` | There is no official image (yet), this one is community-supported | +| supersetWebsockets.image.tag | string | `"latest"` | | +| supersetWebsockets.ingress.path | string | `"/ws"` | | +| supersetWebsockets.ingress.pathType | string | `"Prefix"` | | +| supersetWebsockets.livenessProbe.failureThreshold | int | `3` | | +| supersetWebsockets.livenessProbe.httpGet.path | string | `"/health"` | | +| supersetWebsockets.livenessProbe.httpGet.port | string | `"ws"` | | +| supersetWebsockets.livenessProbe.initialDelaySeconds | int | `5` | | +| supersetWebsockets.livenessProbe.periodSeconds | int | `5` | | +| supersetWebsockets.livenessProbe.successThreshold | int | `1` | | +| supersetWebsockets.livenessProbe.timeoutSeconds | int | `1` | | +| supersetWebsockets.podAnnotations | object | `{}` | | +| supersetWebsockets.podLabels | object | `{}` | | +| supersetWebsockets.podSecurityContext | object | `{}` | | +| supersetWebsockets.readinessProbe.failureThreshold | int | `3` | | +| supersetWebsockets.readinessProbe.httpGet.path | string | `"/health"` | | +| supersetWebsockets.readinessProbe.httpGet.port | string | `"ws"` | | +| supersetWebsockets.readinessProbe.initialDelaySeconds | int | `5` | | +| supersetWebsockets.readinessProbe.periodSeconds | int | `5` | | +| supersetWebsockets.readinessProbe.successThreshold | int | `1` | | +| supersetWebsockets.readinessProbe.timeoutSeconds | int | `1` | | +| supersetWebsockets.replicaCount | int | `1` | | +| supersetWebsockets.resources | object | `{}` | | +| supersetWebsockets.service.annotations | object | `{}` | | +| supersetWebsockets.service.loadBalancerIP | string | `nil` | | +| supersetWebsockets.service.nodePort.http | int | `"nil"` | | +| supersetWebsockets.service.port | int | `8080` | | +| supersetWebsockets.service.type | string | `"ClusterIP"` | | +| supersetWebsockets.startupProbe.failureThreshold | int | `60` | | +| supersetWebsockets.startupProbe.httpGet.path | string | `"/health"` | | +| supersetWebsockets.startupProbe.httpGet.port | string | `"ws"` | | +| supersetWebsockets.startupProbe.initialDelaySeconds | int | `5` | | +| supersetWebsockets.startupProbe.periodSeconds | int | `5` | | +| supersetWebsockets.startupProbe.successThreshold | int | `1` | | +| supersetWebsockets.startupProbe.timeoutSeconds | int | `1` | | +| supersetWebsockets.strategy | object | `{}` | | +| supersetWebsockets.topologySpreadConstraints | list | `[]` | TopologySpreadConstrains to be added to supersetWebsockets deployments | +| supersetWorker.affinity | object | `{}` | Affinity to be added to supersetWorker deployment | +| supersetWorker.command | list | a `celery worker` command | Worker startup command | +| supersetWorker.containerSecurityContext | object | `{}` | | +| supersetWorker.deploymentAnnotations | object | `{}` | Annotations to be added to supersetWorker deployment | +| supersetWorker.deploymentLabels | object | `{}` | Labels to be added to supersetWorker deployment | +| supersetWorker.extraContainers | list | `[]` | Launch additional containers into supersetWorker pod | +| supersetWorker.forceReload | bool | `false` | If true, forces deployment to reload on each upgrade | +| supersetWorker.initContainers | list | a container waiting for postgres and redis | Init container | +| supersetWorker.livenessProbe.exec.command | list | a `celery inspect ping` command | Liveness probe command | +| supersetWorker.livenessProbe.failureThreshold | int | `3` | | +| supersetWorker.livenessProbe.initialDelaySeconds | int | `120` | | +| supersetWorker.livenessProbe.periodSeconds | int | `60` | | +| supersetWorker.livenessProbe.successThreshold | int | `1` | | +| supersetWorker.livenessProbe.timeoutSeconds | int | `60` | | +| supersetWorker.podAnnotations | object | `{}` | Annotations to be added to supersetWorker pods | +| supersetWorker.podLabels | object | `{}` | Labels to be added to supersetWorker pods | +| supersetWorker.podSecurityContext | object | `{}` | | +| supersetWorker.readinessProbe | object | `{}` | No startup/readiness probes by default since we don't really care about its startup time (it doesn't serve traffic) | +| supersetWorker.replicaCount | int | `1` | | +| supersetWorker.resources | object | `{}` | Resource settings for the supersetWorker pods - these settings overwrite might existing values from the global resources object defined above. | +| supersetWorker.startupProbe | object | `{}` | No startup/readiness probes by default since we don't really care about its startup time (it doesn't serve traffic) | +| supersetWorker.strategy | object | `{}` | | +| supersetWorker.topologySpreadConstraints | list | `[]` | TopologySpreadConstrains to be added to supersetWorker deployments | +| tolerations | list | `[]` | | +| topologySpreadConstraints | list | `[]` | TopologySpreadConstrains to be added to all deployments | diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/transformProps.ts b/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/transformProps.ts index 25b7e5364aad7..00466c607a768 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/transformProps.ts +++ b/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/transformProps.ts @@ -53,7 +53,7 @@ import { ForecastSeriesEnum, Refs, } from '../types'; -import { parseYAxisBound } from '../utils/controls'; +import { parseAxisBound } from '../utils/controls'; import { getOverMaxHiddenFormatter, dedupSeries, @@ -343,9 +343,9 @@ export default function transformProps( }); // yAxisBounds need to be parsed to replace incompatible values with undefined - let [min, max] = (yAxisBounds || []).map(parseYAxisBound); + let [min, max] = (yAxisBounds || []).map(parseAxisBound); let [minSecondary, maxSecondary] = (yAxisBoundsSecondary || []).map( - parseYAxisBound, + parseAxisBound, ); const array = ensureIsArray(chartProps.rawFormData?.time_compare); diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Area/controlPanel.tsx b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Area/controlPanel.tsx index 5a5975c66b978..018038772c092 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Area/controlPanel.tsx +++ b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Area/controlPanel.tsx @@ -37,6 +37,8 @@ import { richTooltipSection, seriesOrderSection, percentageThresholdControl, + truncateXAxis, + xAxisBounds, } from '../../controls'; import { AreaChartStackControlOptions } from '../../constants'; @@ -241,6 +243,8 @@ const config: ControlPanelConfig = { }, }, ], + [truncateXAxis], + [xAxisBounds], [ { name: 'truncateYAxis', diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/Bar/controlPanel.tsx b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/Bar/controlPanel.tsx index af482da1b479d..c3002a24980c8 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/Bar/controlPanel.tsx +++ b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/Bar/controlPanel.tsx @@ -35,6 +35,8 @@ import { richTooltipSection, seriesOrderSection, showValueSection, + truncateXAxis, + xAxisBounds, } from '../../../controls'; import { OrientationType } from '../../types'; @@ -224,6 +226,8 @@ function createAxisControl(axis: 'x' | 'y'): ControlSetRow[] { }, }, ], + [truncateXAxis], + [xAxisBounds], [ { name: 'truncateYAxis', diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/Line/controlPanel.tsx b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/Line/controlPanel.tsx index 124ab1e935487..5c5f7a0ab1cb3 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/Line/controlPanel.tsx +++ b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/Line/controlPanel.tsx @@ -38,6 +38,8 @@ import { richTooltipSection, seriesOrderSection, showValueSection, + truncateXAxis, + xAxisBounds, } from '../../../controls'; const { @@ -229,6 +231,8 @@ const config: ControlPanelConfig = { }, }, ], + [truncateXAxis], + [xAxisBounds], [ { name: 'truncateYAxis', diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/Scatter/controlPanel.tsx b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/Scatter/controlPanel.tsx index bc813127caade..6701647694b4e 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/Scatter/controlPanel.tsx +++ b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/Scatter/controlPanel.tsx @@ -37,6 +37,8 @@ import { richTooltipSection, seriesOrderSection, showValueSection, + truncateXAxis, + xAxisBounds, } from '../../../controls'; const { @@ -173,6 +175,8 @@ const config: ControlPanelConfig = { }, }, ], + [truncateXAxis], + [xAxisBounds], [ { name: 'truncateYAxis', diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/SmoothLine/controlPanel.tsx b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/SmoothLine/controlPanel.tsx index 2a8fbfb0afe9e..0c6623f216ec4 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/SmoothLine/controlPanel.tsx +++ b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/SmoothLine/controlPanel.tsx @@ -37,6 +37,8 @@ import { richTooltipSection, seriesOrderSection, showValueSectionWithoutStack, + truncateXAxis, + xAxisBounds, } from '../../../controls'; const { @@ -173,6 +175,8 @@ const config: ControlPanelConfig = { }, }, ], + [truncateXAxis], + [xAxisBounds], [ { name: 'truncateYAxis', diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Step/controlPanel.tsx b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Step/controlPanel.tsx index 9333cb48a1a88..021c306d05cb8 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Step/controlPanel.tsx +++ b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Step/controlPanel.tsx @@ -35,6 +35,8 @@ import { richTooltipSection, seriesOrderSection, showValueSection, + truncateXAxis, + xAxisBounds, } from '../../controls'; const { @@ -223,6 +225,8 @@ const config: ControlPanelConfig = { }, }, ], + [truncateXAxis], + [xAxisBounds], [ { name: 'truncateYAxis', diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/constants.ts b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/constants.ts index 17629c0996b77..a95a14077d8e8 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/constants.ts +++ b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/constants.ts @@ -57,6 +57,7 @@ export const DEFAULT_FORM_DATA: EchartsTimeseriesFormData = { seriesType: EchartsTimeseriesSeriesType.Line, stack: false, tooltipTimeFormat: 'smart_date', + truncateXAxis: true, truncateYAxis: false, yAxisBounds: [null, null], zoomable: false, diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/transformProps.ts b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/transformProps.ts index d59da861a0a58..e81f13b784926 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/transformProps.ts +++ b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/transformProps.ts @@ -54,7 +54,7 @@ import { } from './types'; import { DEFAULT_FORM_DATA } from './constants'; import { ForecastSeriesEnum, ForecastValue, Refs } from '../types'; -import { parseYAxisBound } from '../utils/controls'; +import { parseAxisBound } from '../utils/controls'; import { calculateLowerLogTick, dedupSeries, @@ -64,6 +64,7 @@ import { getAxisType, getColtypesMapping, getLegendProps, + getMinAndMaxFromBounds, } from '../utils/series'; import { extractAnnotationLabels, @@ -159,8 +160,10 @@ export default function transformProps( stack, tooltipTimeFormat, tooltipSortByMetric, + truncateXAxis, truncateYAxis, xAxis: xAxisOrig, + xAxisBounds, xAxisLabelRotation, xAxisSortSeries, xAxisSortSeriesAscending, @@ -386,15 +389,20 @@ export default function transformProps( } }); - // yAxisBounds need to be parsed to replace incompatible values with undefined - let [min, max] = (yAxisBounds || []).map(parseYAxisBound); + // axis bounds need to be parsed to replace incompatible values with undefined + const [xAxisMin, xAxisMax] = (xAxisBounds || []).map(parseAxisBound); + let [yAxisMin, yAxisMax] = (yAxisBounds || []).map(parseAxisBound); // default to 0-100% range when doing row-level contribution chart if ((contributionMode === 'row' || isAreaExpand) && stack) { - if (min === undefined) min = 0; - if (max === undefined) max = 1; - } else if (logAxis && min === undefined && minPositiveValue !== undefined) { - min = calculateLowerLogTick(minPositiveValue); + if (yAxisMin === undefined) yAxisMin = 0; + if (yAxisMax === undefined) yAxisMax = 1; + } else if ( + logAxis && + yAxisMin === undefined && + minPositiveValue !== undefined + ) { + yAxisMin = calculateLowerLogTick(minPositiveValue); } const tooltipFormatter = @@ -450,12 +458,14 @@ export default function transformProps( xAxisType === AxisType.time && timeGrainSqla ? TIMEGRAIN_TO_TIMESTAMP[timeGrainSqla] : 0, + ...getMinAndMaxFromBounds(xAxisType, truncateXAxis, xAxisMin, xAxisMax), }; + let yAxis: any = { ...defaultYAxis, type: logAxis ? AxisType.log : AxisType.value, - min, - max, + min: yAxisMin, + max: yAxisMax, minorTick: { show: true }, minorSplitLine: { show: minorSplitLine }, axisLabel: { diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/types.ts b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/types.ts index 1873086d99122..65da981e496a5 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/types.ts +++ b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/types.ts @@ -75,10 +75,12 @@ export type EchartsTimeseriesFormData = QueryFormData & { stack: StackType; timeCompare?: string[]; tooltipTimeFormat?: string; + truncateXAxis: boolean; truncateYAxis: boolean; yAxisFormat?: string; xAxisTimeFormat?: string; timeGrainSqla?: TimeGranularity; + xAxisBounds: [number | undefined | null, number | undefined | null]; yAxisBounds: [number | undefined | null, number | undefined | null]; zoomable: boolean; richTooltip: boolean; diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/controls.tsx b/superset-frontend/plugins/plugin-chart-echarts/src/controls.tsx index 8f311e47e5676..093617446a659 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/src/controls.tsx +++ b/superset-frontend/plugins/plugin-chart-echarts/src/controls.tsx @@ -248,3 +248,34 @@ export const seriesOrderSection: ControlSetRow[] = [ [sortSeriesType], [sortSeriesAscending], ]; + +export const truncateXAxis: ControlSetItem = { + name: 'truncateXAxis', + config: { + type: 'CheckboxControl', + label: t('Truncate X Axis'), + default: DEFAULT_FORM_DATA.truncateXAxis, + renderTrigger: true, + description: t( + 'Truncate X Axis. Can be overridden by specifying a min or max bound. Only applicable for numercal X axis.', + ), + }, +}; + +export const xAxisBounds: ControlSetItem = { + name: 'xAxisBounds', + config: { + type: 'BoundsControl', + label: t('X Axis Bounds'), + renderTrigger: true, + default: DEFAULT_FORM_DATA.xAxisBounds, + description: t( + 'Bounds for numerical X axis. Not applicable for temporal or categorical axes. ' + + 'When left empty, the bounds are dynamically defined based on the min/max of the data. ' + + "Note that this feature will only expand the axis range. It won't " + + "narrow the data's extent.", + ), + visibility: ({ controls }: ControlPanelsContainerProps) => + Boolean(controls?.truncateXAxis?.value), + }, +}; diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/utils/controls.ts b/superset-frontend/plugins/plugin-chart-echarts/src/utils/controls.ts index af91596b5e081..e5ba4c95d1e95 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/src/utils/controls.ts +++ b/superset-frontend/plugins/plugin-chart-echarts/src/utils/controls.ts @@ -20,7 +20,7 @@ import { validateNumber } from '@superset-ui/core'; // eslint-disable-next-line import/prefer-default-export -export function parseYAxisBound( +export function parseAxisBound( bound?: string | number | null, ): number | undefined { if (bound === undefined || bound === null || Number.isNaN(Number(bound))) { diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/utils/series.ts b/superset-frontend/plugins/plugin-chart-echarts/src/utils/series.ts index bd4e329d0b72b..aa353f66d1a2e 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/src/utils/series.ts +++ b/superset-frontend/plugins/plugin-chart-echarts/src/utils/series.ts @@ -543,3 +543,17 @@ export function calculateLowerLogTick(minPositiveValue: number) { const logBase10 = Math.floor(Math.log10(minPositiveValue)); return Math.pow(10, logBase10); } + +export function getMinAndMaxFromBounds( + axisType: AxisType, + truncateAxis: boolean, + min?: number, + max?: number, +): { min: number | 'dataMin'; max: number | 'dataMax' } | {} { + return truncateAxis && axisType === AxisType.value + ? { + min: min === undefined ? 'dataMin' : min, + max: max === undefined ? 'dataMax' : max, + } + : {}; +} diff --git a/superset-frontend/plugins/plugin-chart-echarts/test/utils/controls.test.ts b/superset-frontend/plugins/plugin-chart-echarts/test/utils/controls.test.ts index 60ced57739342..cb0faac5959c1 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/test/utils/controls.test.ts +++ b/superset-frontend/plugins/plugin-chart-echarts/test/utils/controls.test.ts @@ -16,22 +16,22 @@ * specific language governing permissions and limitations * under the License. */ -import { parseYAxisBound } from '../../src/utils/controls'; +import { parseAxisBound } from '../../src/utils/controls'; describe('parseYAxisBound', () => { it('should return undefined for invalid values', () => { - expect(parseYAxisBound(null)).toBeUndefined(); - expect(parseYAxisBound(undefined)).toBeUndefined(); - expect(parseYAxisBound(NaN)).toBeUndefined(); - expect(parseYAxisBound('abc')).toBeUndefined(); + expect(parseAxisBound(null)).toBeUndefined(); + expect(parseAxisBound(undefined)).toBeUndefined(); + expect(parseAxisBound(NaN)).toBeUndefined(); + expect(parseAxisBound('abc')).toBeUndefined(); }); it('should return numeric value for valid values', () => { - expect(parseYAxisBound(0)).toEqual(0); - expect(parseYAxisBound('0')).toEqual(0); - expect(parseYAxisBound(1)).toEqual(1); - expect(parseYAxisBound('1')).toEqual(1); - expect(parseYAxisBound(10.1)).toEqual(10.1); - expect(parseYAxisBound('10.1')).toEqual(10.1); + expect(parseAxisBound(0)).toEqual(0); + expect(parseAxisBound('0')).toEqual(0); + expect(parseAxisBound(1)).toEqual(1); + expect(parseAxisBound('1')).toEqual(1); + expect(parseAxisBound(10.1)).toEqual(10.1); + expect(parseAxisBound('10.1')).toEqual(10.1); }); }); diff --git a/superset-frontend/plugins/plugin-chart-echarts/test/utils/series.test.ts b/superset-frontend/plugins/plugin-chart-echarts/test/utils/series.test.ts index 927ee49e8cc7f..b445dceabbd47 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/test/utils/series.test.ts +++ b/superset-frontend/plugins/plugin-chart-echarts/test/utils/series.test.ts @@ -36,6 +36,7 @@ import { getChartPadding, getLegendProps, getOverMaxHiddenFormatter, + getMinAndMaxFromBounds, sanitizeHtml, sortAndFilterSeries, sortRows, @@ -879,3 +880,30 @@ test('getAxisType', () => { expect(getAxisType(GenericDataType.BOOLEAN)).toEqual(AxisType.category); expect(getAxisType(GenericDataType.STRING)).toEqual(AxisType.category); }); + +test('getMinAndMaxFromBounds returns empty object when not truncating', () => { + expect(getMinAndMaxFromBounds(AxisType.value, false, 10, 100)).toEqual({}); +}); + +test('getMinAndMaxFromBounds returns automatic bounds when truncating', () => { + expect( + getMinAndMaxFromBounds(AxisType.value, true, undefined, undefined), + ).toEqual({ + min: 'dataMin', + max: 'dataMax', + }); +}); + +test('getMinAndMaxFromBounds returns automatic upper bound when truncating', () => { + expect(getMinAndMaxFromBounds(AxisType.value, true, 10, undefined)).toEqual({ + min: 10, + max: 'dataMax', + }); +}); + +test('getMinAndMaxFromBounds returns automatic lower bound when truncating', () => { + expect(getMinAndMaxFromBounds(AxisType.value, true, undefined, 100)).toEqual({ + min: 'dataMin', + max: 100, + }); +}); diff --git a/superset/dashboards/schemas.py b/superset/dashboards/schemas.py index 9a6bcfb456925..ab4ec819b416b 100644 --- a/superset/dashboards/schemas.py +++ b/superset/dashboards/schemas.py @@ -203,7 +203,7 @@ class DashboardGetResponseSchema(Schema): changed_on_humanized = fields.String(data_key="changed_on_delta_humanized") is_managed_externally = fields.Boolean(allow_none=True, dump_default=False) - # pylint: disable=unused-argument + # pylint: disable=unused-argument, no-self-use @post_dump() def post_dump(self, serialized: dict[str, Any], **kwargs: Any) -> dict[str, Any]: if security_manager.is_guest_user(): @@ -260,7 +260,7 @@ class DashboardDatasetSchema(Schema): granularity_sqla = fields.List(fields.List(fields.Str())) normalize_columns = fields.Bool() - # pylint: disable=unused-argument + # pylint: disable=unused-argument, no-self-use @post_dump() def post_dump(self, serialized: dict[str, Any], **kwargs: Any) -> dict[str, Any]: if security_manager.is_guest_user(): @@ -270,7 +270,7 @@ def post_dump(self, serialized: dict[str, Any], **kwargs: Any) -> dict[str, Any] class BaseDashboardSchema(Schema): - # pylint: disable=no-self-use,unused-argument + # pylint: disable=no-self-use, unused-argument @post_load def post_load(self, data: dict[str, Any], **kwargs: Any) -> dict[str, Any]: if data.get("slug"):