From 5a6b777cf8413f5b9cd47657dd9a767e351865a2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 18 Apr 2023 09:15:36 -0600 Subject: [PATCH 01/11] build(deps-dev): bump @typescript-eslint/eslint-plugin from 5.58.0 to 5.59.0 in /superset-websocket (#23719) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- superset-websocket/package-lock.json | 352 ++++++++++++++++++++++++--- superset-websocket/package.json | 2 +- 2 files changed, 318 insertions(+), 36 deletions(-) diff --git a/superset-websocket/package-lock.json b/superset-websocket/package-lock.json index 0753101e7f3df..7d72e39e2e49e 100644 --- a/superset-websocket/package-lock.json +++ b/superset-websocket/package-lock.json @@ -25,7 +25,7 @@ "@types/node": "^18.15.11", "@types/uuid": "^9.0.1", "@types/ws": "^8.5.4", - "@typescript-eslint/eslint-plugin": "^5.58.0", + "@typescript-eslint/eslint-plugin": "^5.59.0", "@typescript-eslint/parser": "^5.58.0", "eslint": "^8.38.0", "eslint-config-prettier": "^8.8.0", @@ -1372,15 +1372,15 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.58.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.58.0.tgz", - "integrity": "sha512-vxHvLhH0qgBd3/tW6/VccptSfc8FxPQIkmNTVLWcCOVqSBvqpnKkBTYrhcGlXfSnd78azwe+PsjYFj0X34/njA==", + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.0.tgz", + "integrity": "sha512-p0QgrEyrxAWBecR56gyn3wkG15TJdI//eetInP3zYRewDh0XS+DhB3VUAd3QqvziFsfaQIoIuZMxZRB7vXYaYw==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.58.0", - "@typescript-eslint/type-utils": "5.58.0", - "@typescript-eslint/utils": "5.58.0", + "@typescript-eslint/scope-manager": "5.59.0", + "@typescript-eslint/type-utils": "5.59.0", + "@typescript-eslint/utils": "5.59.0", "debug": "^4.3.4", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", @@ -1405,6 +1405,53 @@ } } }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.0.tgz", + "integrity": "sha512-tsoldKaMh7izN6BvkK6zRMINj4Z2d6gGhO2UsI8zGZY3XhLq1DndP3Ycjhi1JwdwPRwtLMW4EFPgpuKhbCGOvQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.59.0", + "@typescript-eslint/visitor-keys": "5.59.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.0.tgz", + "integrity": "sha512-yR2h1NotF23xFFYKHZs17QJnB51J/s+ud4PYU4MqdZbzeNxpgUr05+dNeCN/bb6raslHvGdd6BFCkVhpPk/ZeA==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.0.tgz", + "integrity": "sha512-qZ3iXxQhanchCeaExlKPV3gDQFxMUmU35xfd5eCXB6+kUw1TUAbIy2n7QIrwz9s98DQLzNWyHp61fY0da4ZcbA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.59.0", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, "node_modules/@typescript-eslint/parser": { "version": "5.58.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.58.0.tgz", @@ -1450,13 +1497,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.58.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.58.0.tgz", - "integrity": "sha512-FF5vP/SKAFJ+LmR9PENql7fQVVgGDOS+dq3j+cKl9iW/9VuZC/8CFmzIP0DLKXfWKpRHawJiG70rVH+xZZbp8w==", + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.0.tgz", + "integrity": "sha512-d/B6VSWnZwu70kcKQSCqjcXpVH+7ABKH8P1KNn4K7j5PXXuycZTPXF44Nui0TEm6rbWGi8kc78xRgOC4n7xFgA==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "5.58.0", - "@typescript-eslint/utils": "5.58.0", + "@typescript-eslint/typescript-estree": "5.59.0", + "@typescript-eslint/utils": "5.59.0", "debug": "^4.3.4", "tsutils": "^3.21.0" }, @@ -1476,6 +1523,63 @@ } } }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.0.tgz", + "integrity": "sha512-yR2h1NotF23xFFYKHZs17QJnB51J/s+ud4PYU4MqdZbzeNxpgUr05+dNeCN/bb6raslHvGdd6BFCkVhpPk/ZeA==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.0.tgz", + "integrity": "sha512-sUNnktjmI8DyGzPdZ8dRwW741zopGxltGs/SAPgGL/AAgDpiLsCFLcMNSpbfXfmnNeHmK9h3wGmCkGRGAoUZAg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.59.0", + "@typescript-eslint/visitor-keys": "5.59.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.0.tgz", + "integrity": "sha512-qZ3iXxQhanchCeaExlKPV3gDQFxMUmU35xfd5eCXB6+kUw1TUAbIy2n7QIrwz9s98DQLzNWyHp61fY0da4ZcbA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.59.0", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, "node_modules/@typescript-eslint/types": { "version": "5.58.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.58.0.tgz", @@ -1517,17 +1621,17 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "5.58.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.58.0.tgz", - "integrity": "sha512-gAmLOTFXMXOC+zP1fsqm3VceKSBQJNzV385Ok3+yzlavNHZoedajjS4UyS21gabJYcobuigQPs/z71A9MdJFqQ==", + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.0.tgz", + "integrity": "sha512-GGLFd+86drlHSvPgN/el6dRQNYYGOvRSDVydsUaQluwIW3HvbXuxyuD5JETvBt/9qGYe+lOrDk6gRrWOHb/FvA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.58.0", - "@typescript-eslint/types": "5.58.0", - "@typescript-eslint/typescript-estree": "5.58.0", + "@typescript-eslint/scope-manager": "5.59.0", + "@typescript-eslint/types": "5.59.0", + "@typescript-eslint/typescript-estree": "5.59.0", "eslint-scope": "^5.1.1", "semver": "^7.3.7" }, @@ -1542,6 +1646,80 @@ "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/scope-manager": { + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.0.tgz", + "integrity": "sha512-tsoldKaMh7izN6BvkK6zRMINj4Z2d6gGhO2UsI8zGZY3XhLq1DndP3Ycjhi1JwdwPRwtLMW4EFPgpuKhbCGOvQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.59.0", + "@typescript-eslint/visitor-keys": "5.59.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/types": { + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.0.tgz", + "integrity": "sha512-yR2h1NotF23xFFYKHZs17QJnB51J/s+ud4PYU4MqdZbzeNxpgUr05+dNeCN/bb6raslHvGdd6BFCkVhpPk/ZeA==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree": { + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.0.tgz", + "integrity": "sha512-sUNnktjmI8DyGzPdZ8dRwW741zopGxltGs/SAPgGL/AAgDpiLsCFLcMNSpbfXfmnNeHmK9h3wGmCkGRGAoUZAg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.59.0", + "@typescript-eslint/visitor-keys": "5.59.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/visitor-keys": { + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.0.tgz", + "integrity": "sha512-qZ3iXxQhanchCeaExlKPV3gDQFxMUmU35xfd5eCXB6+kUw1TUAbIy2n7QIrwz9s98DQLzNWyHp61fY0da4ZcbA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.59.0", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, "node_modules/@typescript-eslint/visitor-keys": { "version": "5.58.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.58.0.tgz", @@ -6980,21 +7158,49 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "5.58.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.58.0.tgz", - "integrity": "sha512-vxHvLhH0qgBd3/tW6/VccptSfc8FxPQIkmNTVLWcCOVqSBvqpnKkBTYrhcGlXfSnd78azwe+PsjYFj0X34/njA==", + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.0.tgz", + "integrity": "sha512-p0QgrEyrxAWBecR56gyn3wkG15TJdI//eetInP3zYRewDh0XS+DhB3VUAd3QqvziFsfaQIoIuZMxZRB7vXYaYw==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.58.0", - "@typescript-eslint/type-utils": "5.58.0", - "@typescript-eslint/utils": "5.58.0", + "@typescript-eslint/scope-manager": "5.59.0", + "@typescript-eslint/type-utils": "5.59.0", + "@typescript-eslint/utils": "5.59.0", "debug": "^4.3.4", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", "natural-compare-lite": "^1.4.0", "semver": "^7.3.7", "tsutils": "^3.21.0" + }, + "dependencies": { + "@typescript-eslint/scope-manager": { + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.0.tgz", + "integrity": "sha512-tsoldKaMh7izN6BvkK6zRMINj4Z2d6gGhO2UsI8zGZY3XhLq1DndP3Ycjhi1JwdwPRwtLMW4EFPgpuKhbCGOvQ==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.59.0", + "@typescript-eslint/visitor-keys": "5.59.0" + } + }, + "@typescript-eslint/types": { + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.0.tgz", + "integrity": "sha512-yR2h1NotF23xFFYKHZs17QJnB51J/s+ud4PYU4MqdZbzeNxpgUr05+dNeCN/bb6raslHvGdd6BFCkVhpPk/ZeA==", + "dev": true + }, + "@typescript-eslint/visitor-keys": { + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.0.tgz", + "integrity": "sha512-qZ3iXxQhanchCeaExlKPV3gDQFxMUmU35xfd5eCXB6+kUw1TUAbIy2n7QIrwz9s98DQLzNWyHp61fY0da4ZcbA==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.59.0", + "eslint-visitor-keys": "^3.3.0" + } + } } }, "@typescript-eslint/parser": { @@ -7020,15 +7226,48 @@ } }, "@typescript-eslint/type-utils": { - "version": "5.58.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.58.0.tgz", - "integrity": "sha512-FF5vP/SKAFJ+LmR9PENql7fQVVgGDOS+dq3j+cKl9iW/9VuZC/8CFmzIP0DLKXfWKpRHawJiG70rVH+xZZbp8w==", + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.0.tgz", + "integrity": "sha512-d/B6VSWnZwu70kcKQSCqjcXpVH+7ABKH8P1KNn4K7j5PXXuycZTPXF44Nui0TEm6rbWGi8kc78xRgOC4n7xFgA==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "5.58.0", - "@typescript-eslint/utils": "5.58.0", + "@typescript-eslint/typescript-estree": "5.59.0", + "@typescript-eslint/utils": "5.59.0", "debug": "^4.3.4", "tsutils": "^3.21.0" + }, + "dependencies": { + "@typescript-eslint/types": { + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.0.tgz", + "integrity": "sha512-yR2h1NotF23xFFYKHZs17QJnB51J/s+ud4PYU4MqdZbzeNxpgUr05+dNeCN/bb6raslHvGdd6BFCkVhpPk/ZeA==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.0.tgz", + "integrity": "sha512-sUNnktjmI8DyGzPdZ8dRwW741zopGxltGs/SAPgGL/AAgDpiLsCFLcMNSpbfXfmnNeHmK9h3wGmCkGRGAoUZAg==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.59.0", + "@typescript-eslint/visitor-keys": "5.59.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.0.tgz", + "integrity": "sha512-qZ3iXxQhanchCeaExlKPV3gDQFxMUmU35xfd5eCXB6+kUw1TUAbIy2n7QIrwz9s98DQLzNWyHp61fY0da4ZcbA==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.59.0", + "eslint-visitor-keys": "^3.3.0" + } + } } }, "@typescript-eslint/types": { @@ -7053,19 +7292,62 @@ } }, "@typescript-eslint/utils": { - "version": "5.58.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.58.0.tgz", - "integrity": "sha512-gAmLOTFXMXOC+zP1fsqm3VceKSBQJNzV385Ok3+yzlavNHZoedajjS4UyS21gabJYcobuigQPs/z71A9MdJFqQ==", + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.0.tgz", + "integrity": "sha512-GGLFd+86drlHSvPgN/el6dRQNYYGOvRSDVydsUaQluwIW3HvbXuxyuD5JETvBt/9qGYe+lOrDk6gRrWOHb/FvA==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.58.0", - "@typescript-eslint/types": "5.58.0", - "@typescript-eslint/typescript-estree": "5.58.0", + "@typescript-eslint/scope-manager": "5.59.0", + "@typescript-eslint/types": "5.59.0", + "@typescript-eslint/typescript-estree": "5.59.0", "eslint-scope": "^5.1.1", "semver": "^7.3.7" + }, + "dependencies": { + "@typescript-eslint/scope-manager": { + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.0.tgz", + "integrity": "sha512-tsoldKaMh7izN6BvkK6zRMINj4Z2d6gGhO2UsI8zGZY3XhLq1DndP3Ycjhi1JwdwPRwtLMW4EFPgpuKhbCGOvQ==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.59.0", + "@typescript-eslint/visitor-keys": "5.59.0" + } + }, + "@typescript-eslint/types": { + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.0.tgz", + "integrity": "sha512-yR2h1NotF23xFFYKHZs17QJnB51J/s+ud4PYU4MqdZbzeNxpgUr05+dNeCN/bb6raslHvGdd6BFCkVhpPk/ZeA==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.0.tgz", + "integrity": "sha512-sUNnktjmI8DyGzPdZ8dRwW741zopGxltGs/SAPgGL/AAgDpiLsCFLcMNSpbfXfmnNeHmK9h3wGmCkGRGAoUZAg==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.59.0", + "@typescript-eslint/visitor-keys": "5.59.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.0.tgz", + "integrity": "sha512-qZ3iXxQhanchCeaExlKPV3gDQFxMUmU35xfd5eCXB6+kUw1TUAbIy2n7QIrwz9s98DQLzNWyHp61fY0da4ZcbA==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.59.0", + "eslint-visitor-keys": "^3.3.0" + } + } } }, "@typescript-eslint/visitor-keys": { diff --git a/superset-websocket/package.json b/superset-websocket/package.json index c00ccb16461f4..cf764ad0b9d77 100644 --- a/superset-websocket/package.json +++ b/superset-websocket/package.json @@ -31,7 +31,7 @@ "@types/node": "^18.15.11", "@types/uuid": "^9.0.1", "@types/ws": "^8.5.4", - "@typescript-eslint/eslint-plugin": "^5.58.0", + "@typescript-eslint/eslint-plugin": "^5.59.0", "@typescript-eslint/parser": "^5.58.0", "eslint": "^8.38.0", "eslint-config-prettier": "^8.8.0", From 37a78b14be206bba8b1fdc2b65fdd46875e55c4b Mon Sep 17 00:00:00 2001 From: Ville Brofeldt <33317356+villebro@users.noreply.github.com> Date: Tue, 18 Apr 2023 18:56:15 +0300 Subject: [PATCH 02/11] feat(sqllab): add headers when copying results to clipboard (#23720) --- .../test/DataTablesPane.test.tsx | 2 +- superset-frontend/src/utils/common.js | 10 ++++++-- superset-frontend/src/utils/common.test.jsx | 24 +++++++++---------- 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/superset-frontend/src/explore/components/DataTablesPane/test/DataTablesPane.test.tsx b/superset-frontend/src/explore/components/DataTablesPane/test/DataTablesPane.test.tsx index 4a4a5203f5af9..34dcf01bca7d1 100644 --- a/superset-frontend/src/explore/components/DataTablesPane/test/DataTablesPane.test.tsx +++ b/superset-frontend/src/explore/components/DataTablesPane/test/DataTablesPane.test.tsx @@ -108,7 +108,7 @@ describe('DataTablesPane', () => { userEvent.click(screen.getByLabelText('Copy')); expect(copyToClipboardSpy).toHaveBeenCalledTimes(1); const value = await copyToClipboardSpy.mock.calls[0][0](); - expect(value).toBe('2009-01-01 00:00:00\tAction\n'); + expect(value).toBe('__timestamp\tgenre\n2009-01-01 00:00:00\tAction\n'); copyToClipboardSpy.mockRestore(); fetchMock.restore(); }); diff --git a/superset-frontend/src/utils/common.js b/superset-frontend/src/utils/common.js index 4bc702d447584..e9418f9d31d2d 100644 --- a/superset-frontend/src/utils/common.js +++ b/superset-frontend/src/utils/common.js @@ -78,14 +78,20 @@ export function optionFromValue(opt) { return { value: optionValue(opt), label: optionLabel(opt) }; } +function getColumnName(column) { + return column.name || column; +} + export function prepareCopyToClipboardTabularData(data, columns) { - let result = ''; + let result = columns.length + ? `${columns.map(getColumnName).join('\t')}\n` + : ''; for (let i = 0; i < data.length; i += 1) { const row = {}; for (let j = 0; j < columns.length; j += 1) { // JavaScript does not maintain the order of a mixed set of keys (i.e integers and strings) // the below function orders the keys based on the column names. - const key = columns[j].name || columns[j]; + const key = getColumnName(columns[j]); if (key in data[i]) { row[j] = data[i][key]; } else { diff --git a/superset-frontend/src/utils/common.test.jsx b/superset-frontend/src/utils/common.test.jsx index 59cba6e7b2d0c..a334b342c296d 100644 --- a/superset-frontend/src/utils/common.test.jsx +++ b/superset-frontend/src/utils/common.test.jsx @@ -50,28 +50,28 @@ describe('utils/common', () => { }); describe('prepareCopyToClipboardTabularData', () => { it('converts empty array', () => { - const array = []; - const column = []; - expect(prepareCopyToClipboardTabularData(array, column)).toEqual(''); + const data = []; + const columns = []; + expect(prepareCopyToClipboardTabularData(data, columns)).toEqual(''); }); it('converts non empty array', () => { - const array = [ + const data = [ { column1: 'lorem', column2: 'ipsum' }, { column1: 'dolor', column2: 'sit', column3: 'amet' }, ]; - const column = ['column1', 'column2', 'column3']; - expect(prepareCopyToClipboardTabularData(array, column)).toEqual( - 'lorem\tipsum\t\ndolor\tsit\tamet\n', + const columns = ['column1', 'column2', 'column3']; + expect(prepareCopyToClipboardTabularData(data, columns)).toEqual( + 'column1\tcolumn2\tcolumn3\nlorem\tipsum\t\ndolor\tsit\tamet\n', ); }); - it('includes 0 values', () => { - const array = [ + it('includes 0 values and handle column objects', () => { + const data = [ { column1: 0, column2: 0 }, { column1: 1, column2: -1, 0: 0 }, ]; - const column = ['column1', 'column2', '0']; - expect(prepareCopyToClipboardTabularData(array, column)).toEqual( - '0\t0\t\n1\t-1\t0\n', + const columns = [{ name: 'column1' }, { name: 'column2' }, { name: '0' }]; + expect(prepareCopyToClipboardTabularData(data, columns)).toEqual( + 'column1\tcolumn2\t0\n0\t0\t\n1\t-1\t0\n', ); }); }); From e9b4022787897be3e628f5cd18c4787130c9ae8e Mon Sep 17 00:00:00 2001 From: Francisco Muniz de Paula Neto Date: Tue, 18 Apr 2023 12:59:50 -0300 Subject: [PATCH 03/11] fix: is_select check for lowercase select with "WITH" clauses (#22370) --- superset/sql_parse.py | 4 ++-- tests/unit_tests/sql_parse_tests.py | 22 ++++++++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/superset/sql_parse.py b/superset/sql_parse.py index f84d73bef032a..03c9926a44a55 100644 --- a/superset/sql_parse.py +++ b/superset/sql_parse.py @@ -228,7 +228,7 @@ def is_select(self) -> bool: # for `UNKNOWN`, check all DDL/DML explicitly: only `SELECT` DML is allowed, # and no DDL is allowed if any(token.ttype == DDL for token in parsed[0]) or any( - token.ttype == DML and token.value != "SELECT" for token in parsed[0] + token.ttype == DML and token.normalized != "SELECT" for token in parsed[0] ): return False @@ -237,7 +237,7 @@ def is_select(self) -> bool: return False return any( - token.ttype == DML and token.value == "SELECT" for token in parsed[0] + token.ttype == DML and token.normalized == "SELECT" for token in parsed[0] ) def is_valid_ctas(self) -> bool: diff --git a/tests/unit_tests/sql_parse_tests.py b/tests/unit_tests/sql_parse_tests.py index ba3da69aaefaf..f6d63cf465236 100644 --- a/tests/unit_tests/sql_parse_tests.py +++ b/tests/unit_tests/sql_parse_tests.py @@ -1008,6 +1008,28 @@ def test_cte_is_select() -> None: assert sql.is_select() +def test_cte_is_select_lowercase() -> None: + """ + Some CTEs with lowercase select are not correctly identified as SELECTS. + """ + sql = ParsedQuery( + """WITH foo AS( +select + FLOOR(__time TO WEEK) AS "week", + name, + COUNT(DISTINCT user_id) AS "unique_users" +FROM "druid"."my_table" +GROUP BY 1,2 +) +select + f.week, + f.name, + f.unique_users +FROM foo f""" + ) + assert sql.is_select() + + def test_unknown_select() -> None: """ Test that `is_select` works when sqlparse fails to identify the type. From 0ad6c879b3be44b6cb220dd1a03a541d2fe65d9b Mon Sep 17 00:00:00 2001 From: Daniel Vaz Gaspar Date: Tue, 18 Apr 2023 17:07:37 +0100 Subject: [PATCH 04/11] feat: add enforce URI query params with a specific for MySQL (#23723) --- superset/db_engine_specs/base.py | 11 +++--- superset/db_engine_specs/mysql.py | 6 +++- tests/integration_tests/model_tests.py | 15 ++++++++ .../unit_tests/db_engine_specs/test_mysql.py | 34 +++++++++++++++++-- 4 files changed, 59 insertions(+), 7 deletions(-) diff --git a/superset/db_engine_specs/base.py b/superset/db_engine_specs/base.py index ed58e8cb86b38..93df7c72168e9 100644 --- a/superset/db_engine_specs/base.py +++ b/superset/db_engine_specs/base.py @@ -357,6 +357,8 @@ class BaseEngineSpec: # pylint: disable=too-many-public-methods top_keywords: Set[str] = {"TOP"} # A set of disallowed connection query parameters disallow_uri_query_params: Set[str] = set() + # A Dict of query parameters that will always be used on every connection + enforce_uri_query_params: Dict[str, Any] = {} force_column_alias_quotes = False arraysize = 0 @@ -1089,11 +1091,12 @@ def adjust_engine_params( # pylint: disable=unused-argument ``supports_dynamic_schema`` set to true, so that Superset knows in which schema a given query is running in order to enforce permissions (see #23385 and #23401). - Currently, changing the catalog is not supported. The method acceps a catalog so - that when catalog support is added to Superse the interface remains the same. This - is important because DB engine specs can be installed from 3rd party packages. + Currently, changing the catalog is not supported. The method accepts a catalog so + that when catalog support is added to Superset the interface remains the same. + This is important because DB engine specs can be installed from 3rd party + packages. """ - return uri, connect_args + return uri, {**connect_args, **cls.enforce_uri_query_params} @classmethod def patch(cls) -> None: diff --git a/superset/db_engine_specs/mysql.py b/superset/db_engine_specs/mysql.py index e5ff964f868da..07d2aea36286e 100644 --- a/superset/db_engine_specs/mysql.py +++ b/superset/db_engine_specs/mysql.py @@ -176,6 +176,7 @@ class MySQLEngineSpec(BaseEngineSpec, BasicParametersMixin): ), } disallow_uri_query_params = {"local_infile"} + enforce_uri_query_params = {"local_infile": 0} @classmethod def convert_dttm( @@ -198,10 +199,13 @@ def adjust_engine_params( catalog: Optional[str] = None, schema: Optional[str] = None, ) -> Tuple[URL, Dict[str, Any]]: + uri, new_connect_args = super( + MySQLEngineSpec, MySQLEngineSpec + ).adjust_engine_params(uri, connect_args, catalog, schema) if schema: uri = uri.set(database=parse.quote(schema, safe="")) - return uri, connect_args + return uri, new_connect_args @classmethod def get_schema_from_engine_params( diff --git a/tests/integration_tests/model_tests.py b/tests/integration_tests/model_tests.py index da6c5e6a3c254..35dbcc0a6bb3a 100644 --- a/tests/integration_tests/model_tests.py +++ b/tests/integration_tests/model_tests.py @@ -188,6 +188,21 @@ def test_impersonate_user_presto(self, mocked_create_engine): "password": "original_user_password", } + @unittest.skipUnless( + SupersetTestCase.is_module_installed("MySQLdb"), "mysqlclient not installed" + ) + @mock.patch("superset.models.core.create_engine") + def test_adjust_engine_params_mysql(self, mocked_create_engine): + model = Database( + database_name="test_database", + sqlalchemy_uri="mysql://user:password@localhost", + ) + model._get_sqla_engine() + call_args = mocked_create_engine.call_args + + assert str(call_args[0][0]) == "mysql://user:password@localhost" + assert call_args[1]["connect_args"]["local_infile"] == 0 + @mock.patch("superset.models.core.create_engine") def test_impersonate_user_trino(self, mocked_create_engine): principal_user = security_manager.find_user(username="gamma") diff --git a/tests/unit_tests/db_engine_specs/test_mysql.py b/tests/unit_tests/db_engine_specs/test_mysql.py index 091cdb3b46305..31e01ace58552 100644 --- a/tests/unit_tests/db_engine_specs/test_mysql.py +++ b/tests/unit_tests/db_engine_specs/test_mysql.py @@ -16,7 +16,7 @@ # under the License. from datetime import datetime -from typing import Any, Dict, Optional, Type +from typing import Any, Dict, Optional, Tuple, Type from unittest.mock import Mock, patch import pytest @@ -33,7 +33,7 @@ TINYINT, TINYTEXT, ) -from sqlalchemy.engine.url import make_url +from sqlalchemy.engine.url import make_url, URL from superset.utils.core import GenericDataType from tests.unit_tests.db_engine_specs.utils import ( @@ -119,6 +119,36 @@ def test_validate_database_uri(sqlalchemy_uri: str, error: bool) -> None: MySQLEngineSpec.validate_database_uri(url) +@pytest.mark.parametrize( + "sqlalchemy_uri,connect_args,returns", + [ + ("mysql://user:password@host/db1", {"local_infile": 1}, {"local_infile": 0}), + ("mysql://user:password@host/db1", {"local_infile": -1}, {"local_infile": 0}), + ("mysql://user:password@host/db1", {"local_infile": 0}, {"local_infile": 0}), + ( + "mysql://user:password@host/db1", + {"param1": "some_value"}, + {"local_infile": 0, "param1": "some_value"}, + ), + ( + "mysql://user:password@host/db1", + {"local_infile": 1, "param1": "some_value"}, + {"local_infile": 0, "param1": "some_value"}, + ), + ], +) +def test_adjust_engine_params( + sqlalchemy_uri: str, connect_args: Dict[str, Any], returns: Dict[str, Any] +) -> None: + from superset.db_engine_specs.mysql import MySQLEngineSpec + + url = make_url(sqlalchemy_uri) + returned_url, returned_connect_args = MySQLEngineSpec.adjust_engine_params( + url, connect_args + ) + assert returned_connect_args == returns + + @patch("sqlalchemy.engine.Engine.connect") def test_get_cancel_query_id(engine_mock: Mock) -> None: from superset.db_engine_specs.mysql import MySQLEngineSpec From 70f3cc0b27ee7a9801b3341701b939e8a4bdd2e8 Mon Sep 17 00:00:00 2001 From: Denis Krivenko Date: Tue, 18 Apr 2023 18:37:23 +0200 Subject: [PATCH 05/11] chore(helm): Reformat helm chart templates (#23681) --- helm/superset/templates/NOTES.txt | 4 +- helm/superset/templates/_helpers.tpl | 45 ++++----- .../templates/configmap-superset.yaml | 8 +- helm/superset/templates/deployment-beat.yaml | 75 +++++++-------- .../superset/templates/deployment-flower.yaml | 76 +++++++-------- .../superset/templates/deployment-worker.yaml | 95 +++++++++--------- helm/superset/templates/deployment-ws.yaml | 68 ++++++------- helm/superset/templates/deployment.yaml | 96 +++++++++---------- helm/superset/templates/ingress.yaml | 21 ++-- helm/superset/templates/init-job.yaml | 48 ++++------ helm/superset/templates/secret-env.yaml | 2 +- .../templates/secret-superset-config.yaml | 18 ++-- helm/superset/templates/secret-ws.yaml | 6 +- helm/superset/templates/service-account.yaml | 2 +- helm/superset/templates/service.yaml | 19 ++-- helm/superset/values.yaml | 51 ++++------ 16 files changed, 284 insertions(+), 350 deletions(-) diff --git a/helm/superset/templates/NOTES.txt b/helm/superset/templates/NOTES.txt index 07fcba38102a8..6a686d2c40439 100644 --- a/helm/superset/templates/NOTES.txt +++ b/helm/superset/templates/NOTES.txt @@ -18,9 +18,9 @@ */}} 1. Get the application URL by running these commands: {{- if .Values.ingress.enabled }} -{{- range .Values.ingress.hosts }} + {{- range .Values.ingress.hosts }} http{{ if $.Values.ingress.tls }}s{{ end }}://{{ . }}{{ $.Values.ingress.path }} -{{- end }} + {{- end }} {{- else if contains "NodePort" .Values.service.type }} export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "superset.fullname" . }}) export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") diff --git a/helm/superset/templates/_helpers.tpl b/helm/superset/templates/_helpers.tpl index d551fcf6e82c7..67f018095d8ee 100644 --- a/helm/superset/templates/_helpers.tpl +++ b/helm/superset/templates/_helpers.tpl @@ -21,7 +21,7 @@ Expand the name of the chart. */}} {{- define "superset.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} + {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} {{- end -}} {{/* @@ -30,34 +30,34 @@ We truncate at 63 chars because some Kubernetes name fields are limited to this If release name contains chart name it will be used as a full name. */}} {{- define "superset.fullname" -}} -{{- if .Values.fullnameOverride -}} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- $name := default .Chart.Name .Values.nameOverride -}} -{{- if contains $name .Release.Name -}} -{{- .Release.Name | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} -{{- end -}} -{{- end -}} + {{- if .Values.fullnameOverride -}} + {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} + {{- else -}} + {{- $name := default .Chart.Name .Values.nameOverride -}} + {{- if contains $name .Release.Name -}} + {{- .Release.Name | trunc 63 | trimSuffix "-" -}} + {{- else -}} + {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} + {{- end -}} + {{- end -}} {{- end -}} {{/* Create the name of the service account to use */}} {{- define "superset.serviceAccountName" -}} -{{- if .Values.serviceAccount.create -}} -{{- default (include "superset.fullname" .) .Values.serviceAccountName -}} -{{- else -}} -{{- default "default" .Values.serviceAccountName -}} -{{- end -}} + {{- if .Values.serviceAccount.create -}} + {{- default (include "superset.fullname" .) .Values.serviceAccountName -}} + {{- else -}} + {{- default "default" .Values.serviceAccountName -}} + {{- end -}} {{- end -}} {{/* Create chart name and version as used by the chart label. */}} {{- define "superset.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} + {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} {{- end -}} {{- define "superset-config" }} @@ -86,20 +86,20 @@ SECRET_KEY = env('SECRET_KEY', 'thisISaSECRET_1234') class CeleryConfig(object): CELERY_IMPORTS = ('superset.sql_lab', ) CELERY_ANNOTATIONS = {'tasks.add': {'rate_limit': '10/s'}} -{{- if .Values.supersetNode.connections.redis_password }} + {{- if .Values.supersetNode.connections.redis_password }} BROKER_URL = f"redis://:{env('REDIS_PASSWORD')}@{env('REDIS_HOST')}:{env('REDIS_PORT')}/0" CELERY_RESULT_BACKEND = f"redis://:{env('REDIS_PASSWORD')}@{env('REDIS_HOST')}:{env('REDIS_PORT')}/0" -{{- else }} + {{- else }} BROKER_URL = f"redis://{env('REDIS_HOST')}:{env('REDIS_PORT')}/0" CELERY_RESULT_BACKEND = f"redis://{env('REDIS_HOST')}:{env('REDIS_PORT')}/0" -{{- end }} + {{- end }} CELERY_CONFIG = CeleryConfig RESULTS_BACKEND = RedisCache( host=env('REDIS_HOST'), -{{- if .Values.supersetNode.connections.redis_password }} + {{- if .Values.supersetNode.connections.redis_password }} password=env('REDIS_PASSWORD'), -{{- end }} + {{- end }} port=env('REDIS_PORT'), key_prefix='superset_results' ) @@ -111,6 +111,7 @@ RESULTS_BACKEND = RedisCache( {{ tpl $value $ }} {{- end }} {{- end }} + {{ if .Values.configOverridesFiles }} # Overrides from files {{- $files := .Files }} diff --git a/helm/superset/templates/configmap-superset.yaml b/helm/superset/templates/configmap-superset.yaml index eb8564619b187..fee59cbbd895e 100644 --- a/helm/superset/templates/configmap-superset.yaml +++ b/helm/superset/templates/configmap-superset.yaml @@ -19,15 +19,15 @@ apiVersion: v1 kind: ConfigMap metadata: name: {{ template "superset.fullname" . }}-extra-config + namespace: {{ .Release.Namespace }} labels: app: {{ template "superset.name" . }} chart: {{ template "superset.chart" . }} release: {{ .Release.Name }} heritage: {{ .Release.Service }} - namespace: {{ .Release.Namespace }} data: -{{- range $path, $config := .Values.extraConfigs }} + {{- range $path, $config := .Values.extraConfigs }} {{ $path }}: | -{{- tpl $config $ | nindent 4 -}} -{{- end -}} + {{- tpl $config $ | nindent 4 -}} + {{- end -}} {{- end -}} diff --git a/helm/superset/templates/deployment-beat.yaml b/helm/superset/templates/deployment-beat.yaml index 72de7ab204784..628ba6195a9df 100644 --- a/helm/superset/templates/deployment-beat.yaml +++ b/helm/superset/templates/deployment-beat.yaml @@ -19,16 +19,15 @@ apiVersion: apps/v1 kind: Deployment metadata: name: {{ template "superset.fullname" . }}-celerybeat + namespace: {{ .Release.Namespace }} labels: app: {{ template "superset.name" . }}-celerybeat chart: {{ template "superset.chart" . }} release: {{ .Release.Name }} heritage: {{ .Release.Service }} -{{- if .Values.supersetCeleryBeat.deploymentAnnotations }} - annotations: - {{- toYaml .Values.supersetCeleryBeat.deploymentAnnotations | nindent 4 }} -{{- end }} - namespace: {{ .Release.Namespace }} + {{- if .Values.supersetCeleryBeat.deploymentAnnotations }} + annotations: {{- toYaml .Values.supersetCeleryBeat.deploymentAnnotations | nindent 4 }} + {{- end }} spec: # This must be a singleton replicas: 1 @@ -46,31 +45,30 @@ spec: checksum/extraSecretEnv: {{ .Values.extraSecretEnv | toYaml | sha256sum }} checksum/configOverrides: {{ .Values.configOverrides | toYaml | sha256sum }} checksum/configOverridesFiles: {{ .Values.configOverridesFiles | toYaml | sha256sum }} - {{ if .Values.supersetCeleryBeat.forceReload }} + {{- if .Values.supersetCeleryBeat.forceReload }} # Optionally force the thing to reload force-reload: {{ randAlphaNum 5 | quote }} - {{ end }} - {{- if .Values.supersetCeleryBeat.podAnnotations }} - {{- toYaml .Values.supersetCeleryBeat.podAnnotations | nindent 8 }} - {{- end }} + {{- end }} + {{- if .Values.supersetCeleryBeat.podAnnotations }} + {{- toYaml .Values.supersetCeleryBeat.podAnnotations | nindent 8 }} + {{- end }} labels: app: "{{ template "superset.name" . }}-celerybeat" release: {{ .Release.Name }} - {{- if .Values.supersetCeleryBeat.podLabels }} - {{- toYaml .Values.supersetCeleryBeat.podLabels | nindent 8 }} - {{- end }} + {{- if .Values.supersetCeleryBeat.podLabels }} + {{- toYaml .Values.supersetCeleryBeat.podLabels | nindent 8 }} + {{- end }} spec: {{- if or (.Values.serviceAccount.create) (.Values.serviceAccountName) }} serviceAccountName: {{ template "superset.serviceAccountName" . }} {{- end }} securityContext: runAsUser: {{ .Values.runAsUser }} - {{- if .Values.supersetCeleryBeat.podSecurityContext }} - {{- toYaml .Values.supersetCeleryBeat.podSecurityContext | nindent 8 }} - {{- end }} + {{- if .Values.supersetCeleryBeat.podSecurityContext }} + {{- toYaml .Values.supersetCeleryBeat.podSecurityContext | nindent 8 }} + {{- end }} {{- if .Values.supersetCeleryBeat.initContainers }} - initContainers: - {{- tpl (toYaml .Values.supersetCeleryBeat.initContainers) . | nindent 6 }} + initContainers: {{- tpl (toYaml .Values.supersetCeleryBeat.initContainers) . | nindent 6 }} {{- end }} {{- with .Values.hostAliases }} hostAliases: {{- toYaml . | nindent 6 }} @@ -91,7 +89,7 @@ spec: value: {{ $value | quote }} {{- end }} {{- if .Values.extraEnvRaw }} - {{- toYaml .Values.extraEnvRaw | nindent 12 }} + {{- toYaml .Values.extraEnvRaw | nindent 12 }} {{- end }} envFrom: - secretRef: @@ -109,44 +107,41 @@ spec: mountPath: {{ .Values.extraConfigMountPath | quote }} readOnly: true {{- end }} - {{- with .Values.extraVolumeMounts }} - {{- tpl (toYaml .) $ | nindent 12 -}} - {{- end }} + {{- with .Values.extraVolumeMounts }} + {{- tpl (toYaml .) $ | nindent 12 }} + {{- end }} resources: - {{- if .Values.supersetCeleryBeat.resources }} - {{- toYaml .Values.supersetCeleryBeat.resources | nindent 12 }} - {{- else }} - {{- toYaml .Values.resources | nindent 12 }} - {{- end }} + {{- if .Values.supersetCeleryBeat.resources }} + {{- toYaml .Values.supersetCeleryBeat.resources | nindent 12 }} + {{- else }} + {{- toYaml .Values.resources | nindent 12 }} + {{- end }} {{- with .Values.nodeSelector }} - nodeSelector: - {{- toYaml . | nindent 8 }} + nodeSelector: {{- toYaml . | nindent 8 }} {{- end }} {{- if or .Values.affinity .Values.supersetCeleryBeat.affinity }} affinity: {{- with .Values.affinity }} - {{- toYaml . | nindent 8 }} + {{- toYaml . | nindent 8 }} {{- end }} {{- with .Values.supersetCeleryBeat.affinity }} - {{- toYaml . | nindent 8 }} + {{- toYaml . | nindent 8 }} {{- end }} {{- end }} {{- if or .Values.topologySpreadConstraints .Values.supersetCeleryBeat.topologySpreadConstraints }} topologySpreadConstraints: {{- with .Values.topologySpreadConstraints }} - {{- toYaml . | nindent 8 }} + {{- toYaml . | nindent 8 }} {{- end }} {{- with .Values.supersetCeleryBeat.topologySpreadConstraints }} - {{- toYaml . | nindent 8 }} + {{- toYaml . | nindent 8 }} {{- end }} {{- end }} {{- with .Values.tolerations }} - tolerations: - {{- toYaml . | nindent 8 }} + tolerations: {{- toYaml . | nindent 8 }} {{- end }} {{- if .Values.imagePullSecrets }} - imagePullSecrets: - {{- toYaml .Values.imagePullSecrets | nindent 8 }} + imagePullSecrets: {{- toYaml .Values.imagePullSecrets | nindent 8 }} {{- end }} volumes: - name: superset-config @@ -157,7 +152,7 @@ spec: configMap: name: {{ template "superset.fullname" . }}-extra-config {{- end }} - {{- with .Values.extraVolumes }} - {{- tpl (toYaml .) $ | nindent 8 -}} - {{- end }} + {{- with .Values.extraVolumes }} + {{- tpl (toYaml .) $ | nindent 8 -}} + {{- end }} {{- end -}} diff --git a/helm/superset/templates/deployment-flower.yaml b/helm/superset/templates/deployment-flower.yaml index aefdf0f7dec61..3b3091c819508 100644 --- a/helm/superset/templates/deployment-flower.yaml +++ b/helm/superset/templates/deployment-flower.yaml @@ -19,16 +19,15 @@ apiVersion: apps/v1 kind: Deployment metadata: name: {{ template "superset.fullname" . }}-flower + namespace: {{ .Release.Namespace }} labels: app: {{ template "superset.name" . }}-flower chart: {{ template "superset.chart" . }} release: {{ .Release.Name }} heritage: {{ .Release.Service }} {{- if .Values.supersetCeleryFlower.deploymentAnnotations }} - annotations: - {{- toYaml .Values.supersetCeleryFlower.deploymentAnnotations | nindent 4 }} + annotations: {{- toYaml .Values.supersetCeleryFlower.deploymentAnnotations | nindent 4 }} {{- end }} - namespace: {{ .Release.Namespace }} spec: replicas: {{ .Values.supersetCeleryFlower.replicaCount }} selector: @@ -40,27 +39,26 @@ spec: annotations: checksum/config: {{ include "superset-config" . | sha256sum }} checksum/secrets: {{ tpl (toJson .Values.extraSecretEnv) . | sha256sum }} - {{- if .Values.supersetCeleryFlower.podAnnotations }} - {{- toYaml .Values.supersetCeleryFlower.podAnnotations | nindent 8 }} - {{- end }} + {{- if .Values.supersetCeleryFlower.podAnnotations }} + {{- toYaml .Values.supersetCeleryFlower.podAnnotations | nindent 8 }} + {{- end }} labels: app: "{{ template "superset.name" . }}-flower" release: {{ .Release.Name }} - {{- if .Values.supersetCeleryFlower.podLabels }} - {{- toYaml .Values.supersetCeleryFlower.podLabels | nindent 8 }} - {{- end }} + {{- if .Values.supersetCeleryFlower.podLabels }} + {{- toYaml .Values.supersetCeleryFlower.podLabels | nindent 8 }} + {{- end }} spec: {{- if or (.Values.serviceAccount.create) (.Values.serviceAccountName) }} serviceAccountName: {{ template "superset.serviceAccountName" . }} {{- end }} securityContext: runAsUser: {{ .Values.runAsUser }} - {{- if .Values.supersetCeleryFlower.podSecurityContext }} - {{- toYaml .Values.supersetCeleryFlower.podSecurityContext | nindent 8 }} - {{- end }} + {{- if .Values.supersetCeleryFlower.podSecurityContext }} + {{- toYaml .Values.supersetCeleryFlower.podSecurityContext | nindent 8 }} + {{- end }} {{- if .Values.supersetCeleryFlower.initContainers }} - initContainers: - {{- tpl (toYaml .Values.supersetCeleryFlower.initContainers) . | nindent 6 }} + initContainers: {{- tpl (toYaml .Values.supersetCeleryFlower.initContainers) . | nindent 6 }} {{- end }} {{- with .Values.hostAliases }} hostAliases: {{- toYaml . | nindent 6 }} @@ -79,7 +77,7 @@ spec: value: {{ $value | quote }} {{- end }} {{- if .Values.extraEnvRaw }} - {{- toYaml .Values.extraEnvRaw | nindent 12 }} + {{- toYaml .Values.extraEnvRaw | nindent 12 }} {{- end }} envFrom: - secretRef: @@ -96,62 +94,56 @@ spec: - name: superset-config mountPath: {{ .Values.configMountPath | quote }} readOnly: true - {{- with .Values.extraVolumeMounts }} - {{- tpl (toYaml .) $ | nindent 12 -}} - {{- end }} + {{- with .Values.extraVolumeMounts }} + {{- tpl (toYaml .) $ | nindent 12 -}} + {{- end }} {{- if .Values.supersetCeleryFlower.startupProbe }} - startupProbe: - {{- .Values.supersetCeleryFlower.startupProbe | toYaml | nindent 12 }} + startupProbe: {{- .Values.supersetCeleryFlower.startupProbe | toYaml | nindent 12 }} {{- end }} {{- if .Values.supersetCeleryFlower.readinessProbe }} - readinessProbe: - {{- .Values.supersetCeleryFlower.readinessProbe | toYaml | nindent 12 }} + readinessProbe: {{- .Values.supersetCeleryFlower.readinessProbe | toYaml | nindent 12 }} {{- end }} {{- if .Values.supersetCeleryFlower.livenessProbe }} - livenessProbe: - {{- .Values.supersetCeleryFlower.livenessProbe | toYaml | nindent 12 }} + livenessProbe: {{- .Values.supersetCeleryFlower.livenessProbe | toYaml | nindent 12 }} {{- end }} resources: - {{- if .Values.supersetCeleryFlower.resources }} - {{- toYaml .Values.supersetCeleryFlower.resources | nindent 12 }} - {{- else }} - {{- toYaml .Values.resources | nindent 12 }} - {{- end }} + {{- if .Values.supersetCeleryFlower.resources }} + {{- toYaml .Values.supersetCeleryFlower.resources | nindent 12 }} + {{- else }} + {{- toYaml .Values.resources | nindent 12 }} + {{- end }} {{- with .Values.nodeSelector }} - nodeSelector: - {{- toYaml . | nindent 8 }} + nodeSelector: {{- toYaml . | nindent 8 }} {{- end }} {{- if or .Values.affinity .Values.supersetCeleryFlower.affinity }} affinity: {{- with .Values.affinity }} - {{- toYaml . | nindent 8 }} + {{- toYaml . | nindent 8 }} {{- end }} {{- with .Values.supersetCeleryFlower.affinity }} - {{- toYaml . | nindent 8 }} + {{- toYaml . | nindent 8 }} {{- end }} {{- end }} {{- if or .Values.topologySpreadConstraints .Values.supersetCeleryFlower.topologySpreadConstraints }} topologySpreadConstraints: {{- with .Values.topologySpreadConstraints }} - {{- toYaml . | nindent 8 }} + {{- toYaml . | nindent 8 }} {{- end }} {{- with .Values.supersetCeleryFlower.topologySpreadConstraints }} - {{- toYaml . | nindent 8 }} + {{- toYaml . | nindent 8 }} {{- end }} {{- end }} {{- with .Values.tolerations }} - tolerations: - {{- toYaml . | nindent 8 }} + tolerations: {{- toYaml . | nindent 8 }} {{- end }} {{- if .Values.imagePullSecrets }} - imagePullSecrets: - {{- toYaml .Values.imagePullSecrets | nindent 8 }} + imagePullSecrets: {{- toYaml .Values.imagePullSecrets | nindent 8 }} {{- end }} volumes: - name: superset-config secret: secretName: {{ tpl .Values.configFromSecret . }} - {{- with .Values.extraVolumes }} - {{- tpl (toYaml .) $ | nindent 8 -}} - {{- end }} + {{- with .Values.extraVolumes }} + {{- tpl (toYaml .) $ | nindent 8 -}} + {{- end }} {{- end -}} diff --git a/helm/superset/templates/deployment-worker.yaml b/helm/superset/templates/deployment-worker.yaml index 543fa19acb6b8..610d2fe5049a3 100644 --- a/helm/superset/templates/deployment-worker.yaml +++ b/helm/superset/templates/deployment-worker.yaml @@ -18,19 +18,18 @@ apiVersion: apps/v1 kind: Deployment metadata: name: {{ template "superset.fullname" . }}-worker + namespace: {{ .Release.Namespace }} labels: app: {{ template "superset.name" . }}-worker chart: {{ template "superset.chart" . }} release: {{ .Release.Name }} heritage: {{ .Release.Service }} -{{- if .Values.supersetWorker.deploymentLabels }} - {{- toYaml .Values.supersetWorker.deploymentLabels | nindent 4 }} -{{- end }} -{{- if .Values.supersetWorker.deploymentAnnotations }} - annotations: - {{- toYaml .Values.supersetWorker.deploymentAnnotations | nindent 4 }} -{{- end }} - namespace: {{ .Release.Namespace }} + {{- if .Values.supersetWorker.deploymentLabels }} + {{- toYaml .Values.supersetWorker.deploymentLabels | nindent 4 }} + {{- end }} + {{- if .Values.supersetWorker.deploymentAnnotations }} + annotations: {{- toYaml .Values.supersetWorker.deploymentAnnotations | nindent 4 }} + {{- end }} spec: replicas: {{ .Values.supersetWorker.replicaCount }} selector: @@ -38,8 +37,7 @@ spec: app: {{ template "superset.name" . }}-worker release: {{ .Release.Name }} {{- if .Values.supersetWorker.strategy }} - strategy: - {{- toYaml .Values.supersetWorker.strategy | nindent 4 }} + strategy: {{- toYaml .Values.supersetWorker.strategy | nindent 4 }} {{- end }} template: metadata: @@ -51,31 +49,30 @@ spec: checksum/extraSecretEnv: {{ .Values.extraSecretEnv | toYaml | sha256sum }} checksum/configOverrides: {{ .Values.configOverrides | toYaml | sha256sum }} checksum/configOverridesFiles: {{ .Values.configOverridesFiles | toYaml | sha256sum }} - {{ if .Values.supersetWorker.forceReload }} + {{- if .Values.supersetWorker.forceReload }} # Optionally force the thing to reload force-reload: {{ randAlphaNum 5 | quote }} - {{ end }} - {{- if .Values.supersetWorker.podAnnotations }} - {{- toYaml .Values.supersetWorker.podAnnotations | nindent 8 }} - {{- end }} + {{- end }} + {{- if .Values.supersetWorker.podAnnotations }} + {{- toYaml .Values.supersetWorker.podAnnotations | nindent 8 }} + {{- end }} labels: app: {{ template "superset.name" . }}-worker release: {{ .Release.Name }} - {{- if .Values.supersetWorker.podLabels }} - {{- toYaml .Values.supersetWorker.podLabels | nindent 8 }} - {{- end }} + {{- if .Values.supersetWorker.podLabels }} + {{- toYaml .Values.supersetWorker.podLabels | nindent 8 }} + {{- end }} spec: {{- if or (.Values.serviceAccount.create) (.Values.serviceAccountName) }} serviceAccountName: {{ template "superset.serviceAccountName" . }} {{- end }} securityContext: runAsUser: {{ .Values.runAsUser }} - {{- if .Values.supersetWorker.podSecurityContext }} - {{- toYaml .Values.supersetWorker.podSecurityContext | nindent 8 }} - {{- end }} + {{- if .Values.supersetWorker.podSecurityContext }} + {{- toYaml .Values.supersetWorker.podSecurityContext | nindent 8 }} + {{- end }} {{- if .Values.supersetWorker.initContainers }} - initContainers: - {{- tpl (toYaml .Values.supersetWorker.initContainers) . | nindent 6 }} + initContainers: {{- tpl (toYaml .Values.supersetWorker.initContainers) . | nindent 6 }} {{- end }} {{- with .Values.hostAliases }} hostAliases: {{- toYaml . | nindent 6 }} @@ -109,64 +106,58 @@ spec: - name: superset-config mountPath: {{ .Values.configMountPath | quote }} readOnly: true - {{- if .Values.extraConfigs }} + {{- if .Values.extraConfigs }} - name: superset-extra-config mountPath: {{ .Values.extraConfigMountPath | quote }} readOnly: true - {{- end }} - {{- with .Values.extraVolumeMounts }} - {{- tpl (toYaml .) $ | nindent 12 -}} - {{- end }} + {{- end }} + {{- with .Values.extraVolumeMounts }} + {{- tpl (toYaml .) $ | nindent 12 -}} + {{- end }} {{- if .Values.supersetWorker.startupProbe }} - startupProbe: - {{- .Values.supersetWorker.startupProbe | toYaml | nindent 12 }} + startupProbe: {{- .Values.supersetWorker.startupProbe | toYaml | nindent 12 }} {{- end }} {{- if .Values.supersetWorker.readinessProbe }} - readinessProbe: - {{- .Values.supersetWorker.readinessProbe | toYaml | nindent 12 }} + readinessProbe: {{- .Values.supersetWorker.readinessProbe | toYaml | nindent 12 }} {{- end }} {{- if .Values.supersetWorker.livenessProbe }} - livenessProbe: - {{- .Values.supersetWorker.livenessProbe | toYaml | nindent 12 }} + livenessProbe: {{- .Values.supersetWorker.livenessProbe | toYaml | nindent 12 }} {{- end }} resources: - {{- if .Values.supersetWorker.resources }} + {{- if .Values.supersetWorker.resources }} {{- toYaml .Values.supersetWorker.resources | nindent 12 }} - {{- else }} - {{- toYaml .Values.resources | nindent 12 }} - {{- end }} -{{- if .Values.supersetWorker.extraContainers }} -{{- toYaml .Values.supersetWorker.extraContainers | nindent 8 }} -{{- end }} + {{- else }} + {{- toYaml .Values.resources | nindent 12 }} + {{- end }} + {{- if .Values.supersetWorker.extraContainers }} + {{- toYaml .Values.supersetWorker.extraContainers | nindent 8 }} + {{- end }} {{- with .Values.nodeSelector }} - nodeSelector: - {{- toYaml . | nindent 8 }} + nodeSelector: {{- toYaml . | nindent 8 }} {{- end }} {{- if or .Values.affinity .Values.supersetWorker.affinity }} affinity: {{- with .Values.affinity }} - {{- toYaml . | nindent 8 }} + {{- toYaml . | nindent 8 }} {{- end }} {{- with .Values.supersetWorker.affinity }} - {{- toYaml . | nindent 8 }} + {{- toYaml . | nindent 8 }} {{- end }} {{- end }} {{- if or .Values.topologySpreadConstraints .Values.supersetWorker.topologySpreadConstraints }} topologySpreadConstraints: {{- with .Values.topologySpreadConstraints }} - {{- toYaml . | nindent 8 }} + {{- toYaml . | nindent 8 }} {{- end }} {{- with .Values.supersetWorker.topologySpreadConstraints }} - {{- toYaml . | nindent 8 }} + {{- toYaml . | nindent 8 }} {{- end }} {{- end }} {{- with .Values.tolerations }} - tolerations: - {{- toYaml . | nindent 8 }} + tolerations: {{- toYaml . | nindent 8 }} {{- end }} {{- if .Values.imagePullSecrets }} - imagePullSecrets: - {{- toYaml .Values.imagePullSecrets | nindent 8 }} + imagePullSecrets: {{- toYaml .Values.imagePullSecrets | nindent 8 }} {{- end }} volumes: - name: superset-config @@ -178,5 +169,5 @@ spec: name: {{ template "superset.fullname" . }}-extra-config {{- end }} {{- with .Values.extraVolumes }} - {{- tpl (toYaml .) $ | nindent 8 -}} + {{- tpl (toYaml .) $ | nindent 8 -}} {{- end }} diff --git a/helm/superset/templates/deployment-ws.yaml b/helm/superset/templates/deployment-ws.yaml index 0bbc822ef9150..4d684e83e6069 100644 --- a/helm/superset/templates/deployment-ws.yaml +++ b/helm/superset/templates/deployment-ws.yaml @@ -19,16 +19,15 @@ apiVersion: apps/v1 kind: Deployment metadata: name: "{{ template "superset.fullname" . }}-ws" + namespace: {{ .Release.Namespace }} labels: app: "{{ template "superset.name" . }}-ws" chart: {{ template "superset.chart" . }} release: {{ .Release.Name }} heritage: {{ .Release.Service }} -{{- if .Values.supersetWebsockets.deploymentAnnotations }} - annotations: - {{- toYaml .Values.supersetWebsockets.deploymentAnnotations | nindent 4 }} -{{- end }} - namespace: {{ .Release.Namespace }} + {{- if .Values.supersetWebsockets.deploymentAnnotations }} + annotations: {{- toYaml .Values.supersetWebsockets.deploymentAnnotations | nindent 4 }} + {{- end }} spec: replicas: {{ .Values.supersetWebsockets.replicaCount }} selector: @@ -36,32 +35,31 @@ spec: app: "{{ template "superset.name" . }}-ws" release: {{ .Release.Name }} {{- if .Values.supersetWebsockets.strategy }} - strategy: - {{- toYaml .Values.supersetWebsockets.strategy | nindent 4 }} + strategy: {{- toYaml .Values.supersetWebsockets.strategy | nindent 4 }} {{- end }} template: metadata: annotations: checksum/wsconfig: {{ tpl (toJson .Values.supersetWebsockets.config) . | sha256sum }} checksum/secrets: {{ tpl (toJson .Values.extraSecretEnv) . | sha256sum }} - {{- if .Values.supersetWebsockets.podAnnotations }} - {{- toYaml .Values.supersetWebsockets.podAnnotations | nindent 8 }} - {{- end }} + {{- if .Values.supersetWebsockets.podAnnotations }} + {{- toYaml .Values.supersetWebsockets.podAnnotations | nindent 8 }} + {{- end }} labels: app: "{{ template "superset.name" . }}-ws" release: {{ .Release.Name }} - {{- if .Values.supersetWebsockets.podLabels }} - {{- toYaml .Values.supersetWebsockets.podLabels | nindent 8 }} - {{- end }} + {{- if .Values.supersetWebsockets.podLabels }} + {{- toYaml .Values.supersetWebsockets.podLabels | nindent 8 }} + {{- end }} spec: {{- if or (.Values.serviceAccount.create) (.Values.serviceAccountName) }} serviceAccountName: {{ template "superset.serviceAccountName" . }} {{- end }} securityContext: runAsUser: {{ .Values.runAsUser }} - {{- if .Values.supersetWebsockets.podSecurityContext }} - {{- toYaml .Values.supersetWebsockets.podSecurityContext | nindent 8 }} - {{- end }} + {{- if .Values.supersetWebsockets.podSecurityContext }} + {{- toYaml .Values.supersetWebsockets.podSecurityContext | nindent 8 }} + {{- end }} {{- with .Values.hostAliases }} hostAliases: {{- toYaml . | nindent 6 }} {{- end }} @@ -80,7 +78,7 @@ spec: value: {{ $value | quote }} {{- end }} {{- if .Values.extraEnvRaw }} - {{- toYaml .Values.extraEnvRaw | nindent 12 }} + {{- toYaml .Values.extraEnvRaw | nindent 12 }} {{- end }} envFrom: - secretRef: @@ -99,52 +97,46 @@ spec: subPath: config.json readOnly: true resources: - {{- if .Values.supersetWebsockets.resources }} - {{- toYaml .Values.supersetWebsockets.resources | nindent 12 }} - {{- else }} - {{- toYaml .Values.resources | nindent 12 }} - {{- end }} + {{- if .Values.supersetWebsockets.resources }} + {{- toYaml .Values.supersetWebsockets.resources | nindent 12 }} + {{- else }} + {{- toYaml .Values.resources | nindent 12 }} + {{- end }} {{- if .Values.supersetWebsockets.startupProbe }} - startupProbe: - {{- .Values.supersetWebsockets.startupProbe | toYaml | nindent 12 }} + startupProbe: {{- .Values.supersetWebsockets.startupProbe | toYaml | nindent 12 }} {{- end }} {{- if .Values.supersetWebsockets.readinessProbe }} - readinessProbe: - {{- .Values.supersetWebsockets.readinessProbe | toYaml | nindent 12 }} + readinessProbe: {{- .Values.supersetWebsockets.readinessProbe | toYaml | nindent 12 }} {{- end }} {{- if .Values.supersetWebsockets.livenessProbe }} - livenessProbe: - {{- .Values.supersetWebsockets.livenessProbe | toYaml | nindent 12 }} + livenessProbe: {{- .Values.supersetWebsockets.livenessProbe | toYaml | nindent 12 }} {{- end }} {{- with .Values.nodeSelector }} - nodeSelector: - {{- toYaml . | nindent 8 }} + nodeSelector: {{- toYaml . | nindent 8 }} {{- end }} {{- if or .Values.affinity .Values.supersetWebsockets.affinity }} affinity: {{- with .Values.affinity }} - {{- toYaml . | nindent 8 }} + {{- toYaml . | nindent 8 }} {{- end }} {{- with .Values.supersetWebsockets.affinity }} - {{- toYaml . | nindent 8 }} + {{- toYaml . | nindent 8 }} {{- end }} {{- end }} {{- if or .Values.topologySpreadConstraints .Values.supersetWebsockets.topologySpreadConstraints }} topologySpreadConstraints: {{- with .Values.topologySpreadConstraints }} - {{- toYaml . | nindent 8 }} + {{- toYaml . | nindent 8 }} {{- end }} {{- with .Values.supersetWebsockets.topologySpreadConstraints }} - {{- toYaml . | nindent 8 }} + {{- toYaml . | nindent 8 }} {{- end }} {{- end }} {{- with .Values.tolerations }} - tolerations: - {{- toYaml . | nindent 8 }} + tolerations: {{- toYaml . | nindent 8 }} {{- end }} {{- if .Values.imagePullSecrets }} - imagePullSecrets: - {{- toYaml .Values.imagePullSecrets | nindent 8 }} + imagePullSecrets: {{- toYaml .Values.imagePullSecrets | nindent 8 }} {{- end }} volumes: - name: superset-ws-config diff --git a/helm/superset/templates/deployment.yaml b/helm/superset/templates/deployment.yaml index d993b934ce104..e989b896d46aa 100644 --- a/helm/superset/templates/deployment.yaml +++ b/helm/superset/templates/deployment.yaml @@ -18,24 +18,22 @@ apiVersion: apps/v1 kind: Deployment metadata: name: {{ template "superset.fullname" . }} + namespace: {{ .Release.Namespace }} labels: app: {{ template "superset.name" . }} chart: {{ template "superset.chart" . }} release: {{ .Release.Name }} heritage: {{ .Release.Service }} -{{- if .Values.supersetNode.deploymentLabels }} - {{- toYaml .Values.supersetNode.deploymentLabels | nindent 4 }} -{{- end }} -{{- if .Values.supersetNode.deploymentAnnotations }} - annotations: - {{- toYaml .Values.supersetNode.deploymentAnnotations | nindent 4 }} -{{- end }} - namespace: {{ .Release.Namespace }} + {{- if .Values.supersetNode.deploymentLabels }} + {{- toYaml .Values.supersetNode.deploymentLabels | nindent 4 }} + {{- end }} + {{- if .Values.supersetNode.deploymentAnnotations }} + annotations: {{- toYaml .Values.supersetNode.deploymentAnnotations | nindent 4 }} + {{- end }} spec: replicas: {{ .Values.supersetNode.replicaCount }} {{- if .Values.supersetNode.strategy }} - strategy: - {{- toYaml .Values.supersetNode.strategy | nindent 4 }} + strategy: {{- toYaml .Values.supersetNode.strategy | nindent 4 }} {{- end }} selector: matchLabels: @@ -58,27 +56,26 @@ spec: # Optionally force the thing to reload force-reload: {{ randAlphaNum 5 | quote }} {{- end }} - {{- if .Values.supersetNode.podAnnotations }} - {{- toYaml .Values.supersetNode.podAnnotations | nindent 8 }} - {{- end }} + {{- if .Values.supersetNode.podAnnotations }} + {{- toYaml .Values.supersetNode.podAnnotations | nindent 8 }} + {{- end }} labels: app: {{ template "superset.name" . }} release: {{ .Release.Name }} - {{- if .Values.supersetNode.podLabels }} - {{- toYaml .Values.supersetNode.podLabels | nindent 8 }} - {{- end }} + {{- if .Values.supersetNode.podLabels }} + {{- toYaml .Values.supersetNode.podLabels | nindent 8 }} + {{- end }} spec: {{- if or (.Values.serviceAccount.create) (.Values.serviceAccountName) }} serviceAccountName: {{ template "superset.serviceAccountName" . }} {{- end }} securityContext: runAsUser: {{ .Values.runAsUser }} - {{- if .Values.supersetNode.podSecurityContext }} - {{- toYaml .Values.supersetNode.podSecurityContext | nindent 8 }} - {{- end }} + {{- if .Values.supersetNode.podSecurityContext }} + {{- toYaml .Values.supersetNode.podSecurityContext | nindent 8 }} + {{- end }} {{- if .Values.supersetNode.initContainers }} - initContainers: - {{- tpl (toYaml .Values.supersetNode.initContainers) . | nindent 6 }} + initContainers: {{- tpl (toYaml .Values.supersetNode.initContainers) . | nindent 6 }} {{- end }} {{- with .Values.hostAliases }} hostAliases: {{- toYaml . | nindent 6 }} @@ -103,7 +100,7 @@ spec: value: {{ $value | quote }} {{- end }} {{- if .Values.extraEnvRaw }} - {{- toYaml .Values.extraEnvRaw | nindent 12 }} + {{- toYaml .Values.extraEnvRaw | nindent 12 }} {{- end }} envFrom: - secretRef: @@ -116,70 +113,63 @@ spec: - name: superset-config mountPath: {{ .Values.configMountPath | quote }} readOnly: true - {{- if .Values.extraConfigs }} + {{- if .Values.extraConfigs }} - name: superset-extra-config mountPath: {{ .Values.extraConfigMountPath | quote }} readOnly: true - {{- end }} - {{- with .Values.extraVolumeMounts }} - {{- tpl (toYaml .) $ | nindent 12 -}} - {{- end }} + {{- end }} + {{- with .Values.extraVolumeMounts }} + {{- tpl (toYaml .) $ | nindent 12 -}} + {{- end }} ports: - name: http containerPort: {{ .Values.service.port }} protocol: TCP {{- if .Values.supersetNode.startupProbe }} - startupProbe: - {{- .Values.supersetNode.startupProbe | toYaml | nindent 12 }} + startupProbe: {{- .Values.supersetNode.startupProbe | toYaml | nindent 12 }} {{- end }} {{- if .Values.supersetNode.readinessProbe }} - readinessProbe: - {{- .Values.supersetNode.readinessProbe | toYaml | nindent 12 }} + readinessProbe: {{- .Values.supersetNode.readinessProbe | toYaml | nindent 12 }} {{- end }} {{- if .Values.supersetNode.livenessProbe }} - livenessProbe: - {{- .Values.supersetNode.livenessProbe | toYaml | nindent 12 }} + livenessProbe: {{- .Values.supersetNode.livenessProbe | toYaml | nindent 12 }} {{- end }} resources: - {{- if .Values.supersetNode.resources }} - {{- toYaml .Values.supersetNode.resources | nindent 12 }} - {{- else }} - {{- toYaml .Values.resources | nindent 12 }} - {{- end }} -{{- if .Values.supersetNode.extraContainers }} -{{- toYaml .Values.supersetNode.extraContainers | nindent 8 }} -{{- end }} + {{- if .Values.supersetNode.resources }} + {{- toYaml .Values.supersetNode.resources | nindent 12 }} + {{- else }} + {{- toYaml .Values.resources | nindent 12 }} + {{- end }} + {{- if .Values.supersetNode.extraContainers }} + {{- toYaml .Values.supersetNode.extraContainers | nindent 8 }} + {{- end }} {{- with .Values.nodeSelector }} - nodeSelector: - {{- toYaml . | nindent 8 }} + nodeSelector: {{- toYaml . | nindent 8 }} {{- end }} {{- if or .Values.affinity .Values.supersetNode.affinity }} affinity: {{- with .Values.affinity }} - {{- toYaml . | nindent 8 }} + {{- toYaml . | nindent 8 }} {{- end }} {{- with .Values.supersetNode.affinity }} - {{- toYaml . | nindent 8 }} + {{- toYaml . | nindent 8 }} {{- end }} {{- end }} {{- if or .Values.topologySpreadConstraints .Values.supersetNode.topologySpreadConstraints }} topologySpreadConstraints: {{- with .Values.topologySpreadConstraints }} - {{- toYaml . | nindent 8 }} + {{- toYaml . | nindent 8 }} {{- end }} {{- with .Values.supersetNode.topologySpreadConstraints }} - {{- toYaml . | nindent 8 }} + {{- toYaml . | nindent 8 }} {{- end }} {{- end }} {{- with .Values.tolerations }} - tolerations: - {{- toYaml . | nindent 8 }} + tolerations: {{- toYaml . | nindent 8 }} {{- end }} {{- if .Values.imagePullSecrets }} - imagePullSecrets: - {{- toYaml .Values.imagePullSecrets | nindent 8 }} + imagePullSecrets: {{- toYaml .Values.imagePullSecrets | nindent 8 }} {{- end }} - volumes: - name: superset-config secret: @@ -190,5 +180,5 @@ spec: name: {{ template "superset.fullname" . }}-extra-config {{- end }} {{- with .Values.extraVolumes }} - {{- tpl (toYaml .) $ | nindent 8 -}} + {{- tpl (toYaml .) $ | nindent 8 -}} {{- end }} diff --git a/helm/superset/templates/ingress.yaml b/helm/superset/templates/ingress.yaml index 44e1e48374d72..cec2562f7859e 100644 --- a/helm/superset/templates/ingress.yaml +++ b/helm/superset/templates/ingress.yaml @@ -20,32 +20,31 @@ apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: {{ $fullName }} + namespace: {{ .Release.Namespace }} labels: app: {{ template "superset.name" . }} chart: {{ template "superset.chart" . }} release: {{ .Release.Name }} heritage: {{ .Release.Service }} {{- with .Values.ingress.annotations }} - annotations: - {{- toYaml . | nindent 4 }} + annotations: {{- toYaml . | nindent 4 }} {{- end }} - namespace: {{ .Release.Namespace }} spec: -{{- if .Values.ingress.ingressClassName }} + {{- if .Values.ingress.ingressClassName }} ingressClassName: {{ .Values.ingress.ingressClassName }} -{{- end }} -{{- if .Values.ingress.tls }} + {{- end }} + {{- if .Values.ingress.tls }} tls: - {{- range .Values.ingress.tls }} + {{- range .Values.ingress.tls }} - hosts: {{- range .hosts }} - {{ . }} {{- end }} secretName: {{ .secretName }} + {{- end }} {{- end }} -{{- end }} rules: - {{- range .Values.ingress.hosts }} + {{- range .Values.ingress.hosts }} - host: {{ . }} http: paths: @@ -65,8 +64,8 @@ spec: port: name: ws {{- end }} - {{- end }} + {{- end }} {{- if .Values.ingress.extraHostsRaw }} - {{- toYaml .Values.ingress.extraHostsRaw | nindent 4 }} + {{- toYaml .Values.ingress.extraHostsRaw | nindent 4 }} {{- end }} {{- end }} diff --git a/helm/superset/templates/init-job.yaml b/helm/superset/templates/init-job.yaml index 1f4ba57ae54ea..e225600fefc7c 100644 --- a/helm/superset/templates/init-job.yaml +++ b/helm/superset/templates/init-job.yaml @@ -19,19 +19,18 @@ apiVersion: batch/v1 kind: Job metadata: name: {{ template "superset.name" . }}-init-db + namespace: {{ .Release.Namespace }} {{- if .Values.init.helmHook }} annotations: "helm.sh/hook": post-install,post-upgrade "helm.sh/hook-delete-policy": "before-hook-creation" {{- end }} - namespace: {{ .Release.Namespace }} spec: template: metadata: name: {{ template "superset.name" . }}-init-db {{- if .Values.init.podAnnotations }} - annotations: - {{- toYaml .Values.init.podAnnotations | nindent 8 }} + annotations: {{- toYaml .Values.init.podAnnotations | nindent 8 }} {{- end }} spec: {{- if or (.Values.serviceAccount.create) (.Values.serviceAccountName) }} @@ -39,12 +38,11 @@ spec: {{- end }} securityContext: runAsUser: {{ .Values.runAsUser }} - {{- if .Values.init.podSecurityContext }} - {{- toYaml .Values.init.podSecurityContext | nindent 8 }} - {{- end }} + {{- if .Values.init.podSecurityContext }} + {{- toYaml .Values.init.podSecurityContext | nindent 8 }} + {{- end }} {{- if .Values.init.initContainers }} - initContainers: - {{- tpl (toYaml .Values.init.initContainers) . | nindent 6 }} + initContainers: {{- tpl (toYaml .Values.init.initContainers) . | nindent 6 }} {{- end }} containers: - name: {{ template "superset.name" . }}-init-db @@ -56,7 +54,7 @@ spec: value: {{ $value | quote }} {{- end }} {{- if .Values.extraEnvRaw }} - {{- toYaml .Values.extraEnvRaw | nindent 10 }} + {{- toYaml .Values.extraEnvRaw | nindent 10 }} {{- end }} {{- end }} envFrom: @@ -74,46 +72,42 @@ spec: - name: superset-config mountPath: {{ .Values.configMountPath | quote }} readOnly: true - {{- if .Values.extraConfigs }} + {{- if .Values.extraConfigs }} - name: superset-extra-config mountPath: {{ .Values.extraConfigMountPath | quote }} readOnly: true - {{- end }} - {{- with .Values.extraVolumeMounts }} - {{- tpl (toYaml .) $ | nindent 10 -}} - {{- end }} + {{- end }} + {{- with .Values.extraVolumeMounts }} + {{- tpl (toYaml .) $ | nindent 10 -}} + {{- end }} command: {{ tpl (toJson .Values.init.command) . }} - resources: - {{- toYaml .Values.init.resources | nindent 10 }} + resources: {{- toYaml .Values.init.resources | nindent 10 }} {{- with .Values.nodeSelector }} - nodeSelector: - {{- toYaml . | nindent 8 }} + nodeSelector: {{- toYaml . | nindent 8 }} {{- end }} {{- if or .Values.affinity .Values.init.affinity }} affinity: {{- with .Values.affinity }} - {{- toYaml . | nindent 8 }} + {{- toYaml . | nindent 8 }} {{- end }} {{- with .Values.init.affinity }} - {{- toYaml . | nindent 8 }} + {{- toYaml . | nindent 8 }} {{- end }} {{- end }} {{- if or .Values.topologySpreadConstraints .Values.init.topologySpreadConstraints }} topologySpreadConstraints: {{- with .Values.topologySpreadConstraints }} - {{- toYaml . | nindent 8 }} + {{- toYaml . | nindent 8 }} {{- end }} {{- with .Values.init.topologySpreadConstraints }} - {{- toYaml . | nindent 8 }} + {{- toYaml . | nindent 8 }} {{- end }} {{- end }} {{- with .Values.tolerations }} - tolerations: - {{- toYaml . | nindent 8 }} + tolerations: {{- toYaml . | nindent 8 }} {{- end }} {{- if .Values.imagePullSecrets }} - imagePullSecrets: - {{- toYaml .Values.imagePullSecrets | nindent 8 }} + imagePullSecrets: {{- toYaml .Values.imagePullSecrets | nindent 8 }} {{- end }} volumes: - name: superset-config @@ -125,7 +119,7 @@ spec: name: {{ template "superset.fullname" . }}-extra-config {{- end }} {{- with .Values.extraVolumes }} - {{- tpl (toYaml .) $ | nindent 8 -}} + {{- tpl (toYaml .) $ | nindent 8 -}} {{- end }} restartPolicy: Never {{- end }} diff --git a/helm/superset/templates/secret-env.yaml b/helm/superset/templates/secret-env.yaml index 0164d96a8c129..41fac42bdaf1a 100644 --- a/helm/superset/templates/secret-env.yaml +++ b/helm/superset/templates/secret-env.yaml @@ -18,12 +18,12 @@ apiVersion: v1 kind: Secret metadata: name: {{ template "superset.fullname" . }}-env + namespace: {{ .Release.Namespace }} labels: app: {{ template "superset.fullname" . }} chart: {{ template "superset.chart" . }} release: "{{ .Release.Name }}" heritage: "{{ .Release.Service }}" - namespace: {{ .Release.Namespace }} type: Opaque stringData: REDIS_HOST: {{ tpl .Values.supersetNode.connections.redis_host . | quote }} diff --git a/helm/superset/templates/secret-superset-config.yaml b/helm/superset/templates/secret-superset-config.yaml index c1f4102858d93..165d00356b6c7 100644 --- a/helm/superset/templates/secret-superset-config.yaml +++ b/helm/superset/templates/secret-superset-config.yaml @@ -18,24 +18,24 @@ apiVersion: v1 kind: Secret metadata: name: {{ template "superset.fullname" . }}-config + namespace: {{ .Release.Namespace }} labels: app: {{ template "superset.fullname" . }} chart: {{ template "superset.chart" . }} release: "{{ .Release.Name }}" heritage: "{{ .Release.Service }}" - namespace: {{ .Release.Namespace }} type: Opaque stringData: superset_config.py: | -{{- include "superset-config" . | nindent 4 }} + {{- include "superset-config" . | nindent 4 }} superset_init.sh: | -{{- tpl .Values.init.initscript . | nindent 4 }} + {{- tpl .Values.init.initscript . | nindent 4 }} superset_bootstrap.sh: | -{{- tpl .Values.bootstrapScript . | nindent 4 }} + {{- tpl .Values.bootstrapScript . | nindent 4 }} -{{- if .Values.extraSecrets }} -{{- range $path, $config := .Values.extraSecrets }} + {{- if .Values.extraSecrets }} + {{- range $path, $config := .Values.extraSecrets }} {{ $path }}: | -{{- tpl $config $ | nindent 4 -}} -{{- end -}} -{{- end -}} + {{- tpl $config $ | nindent 4 -}} + {{- end -}} + {{- end -}} diff --git a/helm/superset/templates/secret-ws.yaml b/helm/superset/templates/secret-ws.yaml index c3ac55d96cb07..27f15b784118f 100644 --- a/helm/superset/templates/secret-ws.yaml +++ b/helm/superset/templates/secret-ws.yaml @@ -19,14 +19,14 @@ apiVersion: v1 kind: Secret metadata: name: "{{ template "superset.fullname" . }}-ws-config" + namespace: {{ .Release.Namespace }} labels: app: {{ template "superset.fullname" . }} chart: {{ template "superset.chart" . }} release: "{{ .Release.Name }}" heritage: "{{ .Release.Service }}" - namespace: {{ .Release.Namespace }} type: Opaque stringData: - config.json: | - {{- tpl (toJson .Values.supersetWebsockets.config) . | nindent 6 }} + config.json: | + {{- tpl (toJson .Values.supersetWebsockets.config) . | nindent 4 }} {{- end }} diff --git a/helm/superset/templates/service-account.yaml b/helm/superset/templates/service-account.yaml index 994ad8333afd8..fb8a16d4d8bc0 100755 --- a/helm/superset/templates/service-account.yaml +++ b/helm/superset/templates/service-account.yaml @@ -19,6 +19,7 @@ apiVersion: v1 kind: ServiceAccount metadata: name: {{ include "superset.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} labels: app.kubernetes.io/name: {{ include "superset.name" . }} helm.sh/chart: {{ include "superset.chart" . }} @@ -31,5 +32,4 @@ metadata: {{- if .Values.serviceAccount.annotations }} annotations: {{- toYaml .Values.serviceAccount.annotations | nindent 4 }} {{- end }} - namespace: {{ .Release.Namespace }} {{- end -}} diff --git a/helm/superset/templates/service.yaml b/helm/superset/templates/service.yaml index 97db594a23958..5850e5732b57b 100644 --- a/helm/superset/templates/service.yaml +++ b/helm/superset/templates/service.yaml @@ -18,16 +18,15 @@ apiVersion: v1 kind: Service metadata: name: {{ template "superset.fullname" . }} + namespace: {{ .Release.Namespace }} labels: app: {{ template "superset.name" . }} chart: {{ template "superset.chart" . }} release: {{ .Release.Name }} heritage: {{ .Release.Service }} -{{- with .Values.service.annotations }} - annotations: -{{- toYaml . | nindent 4 }} -{{- end }} - namespace: {{ .Release.Namespace }} + {{- with .Values.service.annotations }} + annotations: {{- toYaml . | nindent 4 }} + {{- end }} spec: type: {{ .Values.service.type }} ports: @@ -50,16 +49,15 @@ apiVersion: v1 kind: Service metadata: name: "{{ template "superset.fullname" . }}-flower" + namespace: {{ .Release.Namespace }} labels: app: {{ template "superset.name" . }} chart: {{ template "superset.chart" . }} release: {{ .Release.Name }} heritage: {{ .Release.Service }} {{- with .Values.supersetCeleryFlower.service.annotations }} - annotations: - {{- toYaml . | nindent 4 }} + annotations: {{- toYaml . | nindent 4 }} {{- end }} - namespace: {{ .Release.Namespace }} spec: type: {{ .Values.supersetCeleryFlower.service.type }} ports: @@ -83,16 +81,15 @@ apiVersion: v1 kind: Service metadata: name: "{{ template "superset.fullname" . }}-ws" + namespace: {{ .Release.Namespace }} labels: app: {{ template "superset.name" . }} chart: {{ template "superset.chart" . }} release: {{ .Release.Name }} heritage: {{ .Release.Service }} {{- with .Values.supersetWebsockets.service.annotations }} - annotations: - {{- toYaml . | nindent 4 }} + annotations: {{- toYaml . | nindent 4 }} {{- end }} - namespace: {{ .Release.Namespace }} spec: type: {{ .Values.supersetWebsockets.service.type }} ports: diff --git a/helm/superset/values.yaml b/helm/superset/values.yaml index b04dc6693497b..339833237939d 100644 --- a/helm/superset/values.yaml +++ b/helm/superset/values.yaml @@ -50,8 +50,7 @@ envFromSecret: '{{ template "superset.fullname" . }}-env' envFromSecrets: [] # -- Extra environment variables that will be passed into pods -extraEnv: - {} +extraEnv: {} # Different gunicorn settings, refer to the gunicorn documentation # https://docs.gunicorn.org/en/stable/settings.html# # These variables are used as Flags at the gunicorn startup @@ -74,8 +73,7 @@ extraEnv: # OAUTH_WHITELIST_REGEX: ... # -- Extra environment variables in RAW format that will be passed into pods -extraEnvRaw: - [] +extraEnvRaw: [] # Load DB password from other secret (e.g. for zalando operator) # - name: DB_PASS # valueFrom: @@ -84,16 +82,14 @@ extraEnvRaw: # key: password # -- Extra environment variables to pass as secrets -extraSecretEnv: - {} +extraSecretEnv: {} # MAPBOX_API_KEY: ... # # Google API Keys: https://console.cloud.google.com/apis/credentials # GOOGLE_KEY: ... # GOOGLE_SECRET: ... # -- Extra files to mount on `/app/pythonpath` -extraConfigs: - {} +extraConfigs: {} # import_datasources.yaml: | # databases: # - allow_file_upload: true @@ -109,8 +105,7 @@ extraConfigs: # -- Extra files to mount on `/app/pythonpath` as secrets extraSecrets: {} -extraVolumes: - [] +extraVolumes: [] # - name: customConfig # configMap: # name: '{{ template "superset.fullname" . }}-custom-config' @@ -119,8 +114,7 @@ extraVolumes: # secretName: my-secret # defaultMode: 0600 -extraVolumeMounts: - [] +extraVolumeMounts: [] # - name: customConfig # mountPath: /mnt/config # readOnly: true @@ -130,8 +124,7 @@ extraVolumeMounts: # -- 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 -configOverrides: - {} +configOverrides: {} # extend_timeout: | # # Extend timeout to allow long running queries. # SUPERSET_WEBSERVER_TIMEOUT = ... @@ -168,8 +161,7 @@ configOverrides: # SECRET_KEY = 'YOUR_OWN_RANDOM_GENERATED_SECRET_KEY' # -- Same as above but the values are files -configOverridesFiles: - {} +configOverridesFiles: {} # extend_timeout: extend_timeout.py # enable_oauth: enable_oauth.py @@ -203,8 +195,7 @@ service: ingress: enabled: false # ingressClassName: nginx - annotations: - {} + annotations: {} # kubernetes.io/tls-acme: "true" ## Extend timeout to allow long running queries. # nginx.ingress.kubernetes.io/proxy-connect-timeout: "300" @@ -220,8 +211,7 @@ ingress: # hosts: # - chart-example.local -resources: - {} +resources: {} # We usually recommend not to specify default resources and to leave this as a conscious # choice for the user. This also increases chances charts run on environments with little # resources, such as Minikube. If you do want to specify resources, uncomment the following @@ -321,8 +311,7 @@ supersetNode: periodSeconds: 15 successThreshold: 1 # -- Resource settings for the supersetNode pods - these settings overwrite might existing values from the global resources object defined above. - resources: - {} + resources: {} # limits: # cpu: 100m # memory: 128Mi @@ -331,8 +320,7 @@ supersetNode: # memory: 128Mi podSecurityContext: {} containerSecurityContext: {} - strategy: - {} + strategy: {} # type: RollingUpdate # rollingUpdate: # maxSurge: 25% @@ -373,8 +361,7 @@ supersetWorker: # -- Labels to be added to supersetWorker pods podLabels: {} # -- Resource settings for the supersetWorker pods - these settings overwrite might existing values from the global resources object defined above. - resources: - {} + resources: {} # limits: # cpu: 100m # memory: 128Mi @@ -383,8 +370,7 @@ supersetWorker: # memory: 128Mi podSecurityContext: {} containerSecurityContext: {} - strategy: - {} + strategy: {} # type: RollingUpdate # rollingUpdate: # maxSurge: 25% @@ -443,8 +429,7 @@ supersetCeleryBeat: # -- Labels to be added to supersetCeleryBeat pods podLabels: {} # -- Resource settings for the CeleryBeat pods - these settings overwrite might existing values from the global resources object defined above. - resources: - {} + resources: {} # limits: # cpu: 100m # memory: 128Mi @@ -524,8 +509,7 @@ supersetCeleryFlower: # -- Labels to be added to supersetCeleryFlower pods podLabels: {} # -- Resource settings for the CeleryBeat pods - these settings overwrite might existing values from the global resources object defined above. - resources: - {} + resources: {} # limits: # cpu: 100m # memory: 128Mi @@ -623,8 +607,7 @@ init: # cause the process to be killed due to OOM if it exceeds limit # Make sure you are giving a strong password for the admin user creation( else make sure you are changing after setup) # Also change the admin email to your own custom email. - resources: - {} + resources: {} # limits: # cpu: # memory: From 2a01aa66d5aa3e465e2b9db932caf0205e4f3638 Mon Sep 17 00:00:00 2001 From: Jack Fragassi Date: Tue, 18 Apr 2023 10:00:14 -0700 Subject: [PATCH 06/11] feat: Add loading state to sqllab save/overwrite dataset modal (#23697) --- .../src/SqlLab/components/SaveDatasetModal/index.tsx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/superset-frontend/src/SqlLab/components/SaveDatasetModal/index.tsx b/superset-frontend/src/SqlLab/components/SaveDatasetModal/index.tsx index 402e26462e041..b1ab18eb09a94 100644 --- a/superset-frontend/src/SqlLab/components/SaveDatasetModal/index.tsx +++ b/superset-frontend/src/SqlLab/components/SaveDatasetModal/index.tsx @@ -174,6 +174,7 @@ export const SaveDatasetModal = ({ const [selectedDatasetToOverwrite, setSelectedDatasetToOverwrite] = useState< SelectValue | undefined >(undefined); + const [loading, setLoading] = useState(false); const user = useSelector(user => getInitialState(user), @@ -197,6 +198,7 @@ export const SaveDatasetModal = ({ setShouldOverwriteDataset(true); return; } + setLoading(true); const [, key] = await Promise.all([ updateDataset( datasource?.dbId, @@ -220,6 +222,7 @@ export const SaveDatasetModal = ({ }), }), ]); + setLoading(false); const url = mountExploreUrl(null, { [URL_PARAMS.formDataKey.name]: key, @@ -269,6 +272,7 @@ export const SaveDatasetModal = ({ ); const handleSaveInDataset = () => { + setLoading(true); const selectedColumns = datasource?.columns ?? []; // The filters param is only used to test jinja templates. @@ -306,6 +310,7 @@ export const SaveDatasetModal = ({ }), ) .then((key: string) => { + setLoading(false); const url = mountExploreUrl(null, { [URL_PARAMS.formDataKey.name]: key, }); @@ -314,6 +319,7 @@ export const SaveDatasetModal = ({ onHide(); }) .catch(() => { + setLoading(false); addDangerToast(t('An error occurred saving dataset')); }); }; @@ -356,6 +362,7 @@ export const SaveDatasetModal = ({ disabled={disableSaveAndExploreBtn} buttonStyle="primary" onClick={handleSaveInDataset} + loading={loading} > {buttonTextOnSave} @@ -370,6 +377,7 @@ export const SaveDatasetModal = ({ buttonStyle="primary" onClick={handleOverwriteDataset} disabled={disableSaveAndExploreBtn} + loading={loading} > {buttonTextOnOverwrite} From 8bd432274a0eed58187473f8c0845fb34a10353e Mon Sep 17 00:00:00 2001 From: Jack Fragassi Date: Tue, 18 Apr 2023 11:09:39 -0700 Subject: [PATCH 07/11] chore(api v1): Deprecate superset/override_role_permissions endpoint (#23714) --- superset/security/manager.py | 1 - superset/views/core.py | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/superset/security/manager.py b/superset/security/manager.py index 754a91d9077aa..c54fdac87adc1 100644 --- a/superset/security/manager.py +++ b/superset/security/manager.py @@ -207,7 +207,6 @@ class SupersetSecurityManager( # pylint: disable=too-many-public-methods } ADMIN_ONLY_PERMISSIONS = { - "can_override_role_permissions", "can_sync_druid_source", "can_override_role_permissions", "can_approve", diff --git a/superset/views/core.py b/superset/views/core.py index 72e1627331635..774c045992c55 100755 --- a/superset/views/core.py +++ b/superset/views/core.py @@ -229,6 +229,7 @@ def datasources(self) -> FlaskResponse: @has_access_api @event_logger.log_this @expose("/override_role_permissions/", methods=["POST"]) + @deprecated() def override_role_permissions(self) -> FlaskResponse: """Updates the role with the give datasource permissions. From 0c0d2b38a672bd2fef8dad75d0bffe78e8a5b80e Mon Sep 17 00:00:00 2001 From: "JUST.in DO IT" Date: Tue, 18 Apr 2023 12:26:29 -0700 Subject: [PATCH 08/11] fix(sqllab): infinite running state on disconnect (#23669) --- .../src/SqlLab/actions/sqlLab.js | 5 + .../src/SqlLab/components/App/index.jsx | 3 +- .../QueryAutoRefresh.test.tsx | 127 +++++++++++++++--- .../components/QueryAutoRefresh/index.tsx | 46 ++++--- .../src/SqlLab/reducers/sqlLab.js | 15 +++ 5 files changed, 158 insertions(+), 38 deletions(-) diff --git a/superset-frontend/src/SqlLab/actions/sqlLab.js b/superset-frontend/src/SqlLab/actions/sqlLab.js index 260f9944f9b04..e4cc78ef0f94c 100644 --- a/superset-frontend/src/SqlLab/actions/sqlLab.js +++ b/superset-frontend/src/SqlLab/actions/sqlLab.js @@ -80,6 +80,7 @@ export const STOP_QUERY = 'STOP_QUERY'; export const REQUEST_QUERY_RESULTS = 'REQUEST_QUERY_RESULTS'; export const QUERY_SUCCESS = 'QUERY_SUCCESS'; export const QUERY_FAILED = 'QUERY_FAILED'; +export const CLEAR_INACTIVE_QUERIES = 'CLEAR_INACTIVE_QUERIES'; export const CLEAR_QUERY_RESULTS = 'CLEAR_QUERY_RESULTS'; export const REMOVE_DATA_PREVIEW = 'REMOVE_DATA_PREVIEW'; export const CHANGE_DATA_PREVIEW_ID = 'CHANGE_DATA_PREVIEW_ID'; @@ -219,6 +220,10 @@ export function estimateQueryCost(queryEditor) { }; } +export function clearInactiveQueries() { + return { type: CLEAR_INACTIVE_QUERIES }; +} + export function startQuery(query) { Object.assign(query, { id: query.id ? query.id : shortid.generate(), diff --git a/superset-frontend/src/SqlLab/components/App/index.jsx b/superset-frontend/src/SqlLab/components/App/index.jsx index 4689f8ec21912..bbd1bba9aead2 100644 --- a/superset-frontend/src/SqlLab/components/App/index.jsx +++ b/superset-frontend/src/SqlLab/components/App/index.jsx @@ -168,7 +168,7 @@ class App extends React.PureComponent { } render() { - const { queries, actions, queriesLastUpdate } = this.props; + const { queries, queriesLastUpdate } = this.props; if (this.state.hash && this.state.hash === '#search') { return window.location.replace('/superset/sqllab/history/'); } @@ -176,7 +176,6 @@ class App extends React.PureComponent { diff --git a/superset-frontend/src/SqlLab/components/QueryAutoRefresh/QueryAutoRefresh.test.tsx b/superset-frontend/src/SqlLab/components/QueryAutoRefresh/QueryAutoRefresh.test.tsx index 32bf401f22139..9b2c1feaefdaf 100644 --- a/superset-frontend/src/SqlLab/components/QueryAutoRefresh/QueryAutoRefresh.test.tsx +++ b/superset-frontend/src/SqlLab/components/QueryAutoRefresh/QueryAutoRefresh.test.tsx @@ -16,15 +16,26 @@ * specific language governing permissions and limitations * under the License. */ +import fetchMock from 'fetch-mock'; import React from 'react'; -import { render } from '@testing-library/react'; +import configureStore from 'redux-mock-store'; +import thunk from 'redux-thunk'; +import { render, waitFor } from 'spec/helpers/testing-library'; +import { + CLEAR_INACTIVE_QUERIES, + REFRESH_QUERIES, +} from 'src/SqlLab/actions/sqlLab'; import QueryAutoRefresh, { isQueryRunning, shouldCheckForQueries, + QUERY_UPDATE_FREQ, } from 'src/SqlLab/components/QueryAutoRefresh'; import { successfulQuery, runningQuery } from 'src/SqlLab/fixtures'; import { QueryDictionary } from 'src/SqlLab/types'; +const middlewares = [thunk]; +const mockStore = configureStore(middlewares); + // NOTE: The uses of @ts-ignore in this file is to enable testing of bad inputs to verify the // function / component handles bad data elegantly describe('QueryAutoRefresh', () => { @@ -34,10 +45,14 @@ describe('QueryAutoRefresh', () => { const successfulQueries: QueryDictionary = {}; successfulQueries[successfulQuery.id] = successfulQuery; - const refreshQueries = jest.fn(); - const queriesLastUpdate = Date.now(); + const refreshApi = 'glob:*/api/v1/query/updated_since?*'; + + afterEach(() => { + fetchMock.reset(); + }); + it('isQueryRunning returns true for valid running query', () => { const running = isQueryRunning(runningQuery); expect(running).toBe(true); @@ -91,43 +106,119 @@ describe('QueryAutoRefresh', () => { ).toBe(false); }); - it('Attempts to refresh when given pending query', () => { + it('Attempts to refresh when given pending query', async () => { + const store = mockStore(); + fetchMock.get(refreshApi, { + result: [ + { + id: runningQuery.id, + status: 'success', + }, + ], + }); + render( , + { useRedux: true, store }, + ); + await waitFor( + () => + expect(store.getActions()).toContainEqual( + expect.objectContaining({ + type: REFRESH_QUERIES, + }), + ), + { timeout: QUERY_UPDATE_FREQ + 100 }, ); - setTimeout(() => { - expect(refreshQueries).toHaveBeenCalled(); - }, 1000); }); - it('Does not fail and attempts to refresh when given pending query and invlaid query', () => { + it('Attempts to clear inactive queries when updated queries are empty', async () => { + const store = mockStore(); + fetchMock.get(refreshApi, { + result: [], + }); + + render( + , + { useRedux: true, store }, + ); + await waitFor( + () => + expect(store.getActions()).toContainEqual( + expect.objectContaining({ + type: CLEAR_INACTIVE_QUERIES, + }), + ), + { timeout: QUERY_UPDATE_FREQ + 100 }, + ); + expect( + store.getActions().filter(({ type }) => type === REFRESH_QUERIES), + ).toHaveLength(0); + expect(fetchMock.calls(refreshApi)).toHaveLength(1); + }); + + it('Does not fail and attempts to refresh when given pending query and invlaid query', async () => { + const store = mockStore(); + fetchMock.get(refreshApi, { + result: [ + { + id: runningQuery.id, + status: 'success', + }, + ], + }); + render( , + { useRedux: true, store }, + ); + await waitFor( + () => + expect(store.getActions()).toContainEqual( + expect.objectContaining({ + type: REFRESH_QUERIES, + }), + ), + { timeout: QUERY_UPDATE_FREQ + 100 }, ); - setTimeout(() => { - expect(refreshQueries).toHaveBeenCalled(); - }, 1000); }); - it('Does NOT Attempt to refresh when given only completed queries', () => { + it('Does NOT Attempt to refresh when given only completed queries', async () => { + const store = mockStore(); + fetchMock.get(refreshApi, { + result: [ + { + id: runningQuery.id, + status: 'success', + }, + ], + }); render( , + { useRedux: true, store }, + ); + await waitFor( + () => + expect(store.getActions()).toContainEqual( + expect.objectContaining({ + type: CLEAR_INACTIVE_QUERIES, + }), + ), + { timeout: QUERY_UPDATE_FREQ + 100 }, ); - setTimeout(() => { - expect(refreshQueries).not.toHaveBeenCalled(); - }, 1000); + expect(fetchMock.calls(refreshApi)).toHaveLength(0); }); }); diff --git a/superset-frontend/src/SqlLab/components/QueryAutoRefresh/index.tsx b/superset-frontend/src/SqlLab/components/QueryAutoRefresh/index.tsx index 2d01e724e2479..65a6d11a1d1a8 100644 --- a/superset-frontend/src/SqlLab/components/QueryAutoRefresh/index.tsx +++ b/superset-frontend/src/SqlLab/components/QueryAutoRefresh/index.tsx @@ -16,7 +16,8 @@ * specific language governing permissions and limitations * under the License. */ -import { useState } from 'react'; +import { useRef } from 'react'; +import { useDispatch } from 'react-redux'; import { isObject } from 'lodash'; import rison from 'rison'; import { @@ -27,19 +28,18 @@ import { } from '@superset-ui/core'; import { QueryDictionary } from 'src/SqlLab/types'; import useInterval from 'src/SqlLab/utils/useInterval'; +import { + refreshQueries, + clearInactiveQueries, +} from 'src/SqlLab/actions/sqlLab'; -const QUERY_UPDATE_FREQ = 2000; +export const QUERY_UPDATE_FREQ = 2000; const QUERY_UPDATE_BUFFER_MS = 5000; const MAX_QUERY_AGE_TO_POLL = 21600000; const QUERY_TIMEOUT_LIMIT = 10000; -interface RefreshQueriesFunc { - (alteredQueries: any): any; -} - export interface QueryAutoRefreshProps { queries: QueryDictionary; - refreshQueries: RefreshQueriesFunc; queriesLastUpdate: number; } @@ -61,20 +61,22 @@ export const shouldCheckForQueries = (queryList: QueryDictionary): boolean => { function QueryAutoRefresh({ queries, - refreshQueries, queriesLastUpdate, }: QueryAutoRefreshProps) { // We do not want to spam requests in the case of slow connections and potentially receive responses out of order // pendingRequest check ensures we only have one active http call to check for query statuses - const [pendingRequest, setPendingRequest] = useState(false); + const pendingRequestRef = useRef(false); + const cleanInactiveRequestRef = useRef(false); + const dispatch = useDispatch(); const checkForRefresh = () => { - if (!pendingRequest && shouldCheckForQueries(queries)) { + const shouldRequestChecking = shouldCheckForQueries(queries); + if (!pendingRequestRef.current && shouldRequestChecking) { const params = rison.encode({ last_updated_ms: queriesLastUpdate - QUERY_UPDATE_BUFFER_MS, }); - setPendingRequest(true); + pendingRequestRef.current = true; SupersetClient.get({ endpoint: `/api/v1/query/updated_since?q=${params}`, timeout: QUERY_TIMEOUT_LIMIT, @@ -82,19 +84,27 @@ function QueryAutoRefresh({ .then(({ json }) => { if (json) { const jsonPayload = json as { result?: QueryResponse[] }; - const queries = - jsonPayload?.result?.reduce((acc, current) => { - acc[current.id] = current; - return acc; - }, {}) ?? {}; - refreshQueries?.(queries); + if (jsonPayload?.result?.length) { + const queries = + jsonPayload?.result?.reduce((acc, current) => { + acc[current.id] = current; + return acc; + }, {}) ?? {}; + dispatch(refreshQueries(queries)); + } else { + dispatch(clearInactiveQueries()); + } } }) .catch(() => {}) .finally(() => { - setPendingRequest(false); + pendingRequestRef.current = false; }); } + if (!cleanInactiveRequestRef.current && !shouldRequestChecking) { + dispatch(clearInactiveQueries()); + cleanInactiveRequestRef.current = true; + } }; // Solves issue where direct usage of setInterval in function components diff --git a/superset-frontend/src/SqlLab/reducers/sqlLab.js b/superset-frontend/src/SqlLab/reducers/sqlLab.js index ff2cb340bbd08..03b239e56b69c 100644 --- a/superset-frontend/src/SqlLab/reducers/sqlLab.js +++ b/superset-frontend/src/SqlLab/reducers/sqlLab.js @@ -742,6 +742,21 @@ export default function sqlLabReducer(state = {}, action) { } return { ...state, queries: newQueries, queriesLastUpdate }; }, + [actions.CLEAR_INACTIVE_QUERIES]() { + const { queries } = state; + const cleanedQueries = Object.fromEntries( + Object.entries(queries).filter(([, query]) => { + if ( + ['running', 'pending'].includes(query.state) && + query.progress === 0 + ) { + return false; + } + return true; + }), + ); + return { ...state, queries: cleanedQueries }; + }, [actions.SET_USER_OFFLINE]() { return { ...state, offline: action.offline }; }, From d6b6d9eae654d7d57a20b9c52d9b9b956627877a Mon Sep 17 00:00:00 2001 From: "Michael S. Molina" <70410625+michael-s-molina@users.noreply.github.com> Date: Tue, 18 Apr 2023 16:31:09 -0300 Subject: [PATCH 09/11] feat: Makes "Add to dashboard" in Save chart modal paginated (#23634) --- .../cypress/integration/dashboard/utils.ts | 4 - .../cypress/integration/explore/utils.ts | 7 +- .../src/explore/actions/saveModalActions.js | 37 --- .../explore/actions/saveModalActions.test.js | 68 ---- .../src/explore/components/SaveModal.test.jsx | 24 +- .../src/explore/components/SaveModal.tsx | 294 ++++++++++-------- 6 files changed, 170 insertions(+), 264 deletions(-) diff --git a/superset-frontend/cypress-base/cypress/integration/dashboard/utils.ts b/superset-frontend/cypress-base/cypress/integration/dashboard/utils.ts index 0b8776b06c1a5..44322e1c42ceb 100644 --- a/superset-frontend/cypress-base/cypress/integration/dashboard/utils.ts +++ b/superset-frontend/cypress-base/cypress/integration/dashboard/utils.ts @@ -163,10 +163,6 @@ export function interceptDatasets() { cy.intercept('GET', `/api/v1/dashboard/*/datasets`).as('getDatasets'); } -export function interceptDashboardasync() { - cy.intercept('GET', `/dashboardasync/api/read*`).as('getDashboardasync'); -} - export function interceptFilterState() { cy.intercept('POST', `/api/v1/dashboard/*/filter_state*`).as( 'postFilterState', diff --git a/superset-frontend/cypress-base/cypress/integration/explore/utils.ts b/superset-frontend/cypress-base/cypress/integration/explore/utils.ts index 15e7dcba1b6f5..04cf1f1819986 100644 --- a/superset-frontend/cypress-base/cypress/integration/explore/utils.ts +++ b/superset-frontend/cypress-base/cypress/integration/explore/utils.ts @@ -17,10 +17,7 @@ * under the License. */ -import { - interceptGet as interceptDashboardGet, - interceptDashboardasync, -} from '../dashboard/utils'; +import { interceptGet as interceptDashboardGet } from '../dashboard/utils'; export function interceptFiltering() { cy.intercept('GET', `/api/v1/chart/?q=*`).as('filtering'); @@ -61,12 +58,10 @@ export function setFilter(filter: string, option: string) { export function saveChartToDashboard(dashboardName: string) { interceptDashboardGet(); - interceptDashboardasync(); interceptUpdate(); interceptExploreGet(); cy.getBySel('query-save-button').click(); - cy.wait('@getDashboardasync'); cy.getBySelLike('chart-modal').should('be.visible'); cy.get( '[data-test="save-chart-modal-select-dashboard-form"] [aria-label="Select a dashboard"]', diff --git a/superset-frontend/src/explore/actions/saveModalActions.js b/superset-frontend/src/explore/actions/saveModalActions.js index 1c3c3b765f781..9bd5161391539 100644 --- a/superset-frontend/src/explore/actions/saveModalActions.js +++ b/superset-frontend/src/explore/actions/saveModalActions.js @@ -40,29 +40,6 @@ export function setSaveChartModalVisibility(isVisible) { return { type: SET_SAVE_CHART_MODAL_VISIBILITY, isVisible }; } -export function fetchDashboards(userId) { - return function fetchDashboardsThunk(dispatch) { - return SupersetClient.get({ - endpoint: `/dashboardasync/api/read?_flt_0_owners=${userId}`, - }) - .then(({ json }) => { - const choices = json.pks.map((id, index) => ({ - value: id, - label: (json.result[index] || {}).dashboard_title, - })); - choices.sort((a, b) => - a.label.localeCompare(b.label, { - sensitivity: 'base', - numeric: true, - }), - ); - - return dispatch(fetchDashboardsSucceeded(choices)); - }) - .catch(() => dispatch(fetchDashboardsFailed(userId))); - }; -} - export const SAVE_SLICE_FAILED = 'SAVE_SLICE_FAILED'; export function saveSliceFailed() { return { type: SAVE_SLICE_FAILED }; @@ -241,20 +218,6 @@ export const createDashboard = dashboardName => async dispatch => { } }; -// Get existing dashboard from ID -export const getDashboard = dashboardId => async dispatch => { - try { - const response = await SupersetClient.get({ - endpoint: `/api/v1/dashboard/${dashboardId}`, - }); - - return response.json; - } catch (error) { - dispatch(saveSliceFailed()); - throw error; - } -}; - // Get dashboards the slice is added to export const getSliceDashboards = slice => async dispatch => { try { diff --git a/superset-frontend/src/explore/actions/saveModalActions.test.js b/superset-frontend/src/explore/actions/saveModalActions.test.js index f89729f5ff981..1662ead63e5f0 100644 --- a/superset-frontend/src/explore/actions/saveModalActions.test.js +++ b/superset-frontend/src/explore/actions/saveModalActions.test.js @@ -23,10 +23,6 @@ import { ADD_TOAST } from 'src/components/MessageToasts/actions'; import { createDashboard, createSlice, - fetchDashboards, - FETCH_DASHBOARDS_FAILED, - FETCH_DASHBOARDS_SUCCEEDED, - getDashboard, getSliceDashboards, SAVE_SLICE_FAILED, SAVE_SLICE_SUCCESS, @@ -34,37 +30,6 @@ import { getSlicePayload, } from './saveModalActions'; -/** - * Tests fetchDashboards action - */ - -const userId = 1; -const fetchDashboardsEndpoint = `glob:*/dashboardasync/api/read?_flt_0_owners=${1}`; -const mockDashboardData = { - pks: ['id'], - result: [{ id: 'id', dashboard_title: 'dashboard title' }], -}; - -test('fetchDashboards handles success', async () => { - fetchMock.reset(); - fetchMock.get(fetchDashboardsEndpoint, mockDashboardData); - const dispatch = sinon.spy(); - await fetchDashboards(userId)(dispatch); - expect(fetchMock.calls(fetchDashboardsEndpoint)).toHaveLength(1); - expect(dispatch.callCount).toBe(1); - expect(dispatch.getCall(0).args[0].type).toBe(FETCH_DASHBOARDS_SUCCEEDED); -}); - -test('fetchDashboards handles failure', async () => { - fetchMock.reset(); - fetchMock.get(fetchDashboardsEndpoint, { throws: 'error' }); - const dispatch = sinon.spy(); - await fetchDashboards(userId)(dispatch); - expect(fetchMock.calls(fetchDashboardsEndpoint)).toHaveLength(4); // 3 retries - expect(dispatch.callCount).toBe(1); - expect(dispatch.getCall(0).args[0].type).toBe(FETCH_DASHBOARDS_FAILED); -}); - const sliceId = 10; const sliceName = 'New chart'; const vizType = 'sample_viz_type'; @@ -176,7 +141,6 @@ test('createSlice handles failure', async () => { expect(dispatch.getCall(0).args[0].type).toBe(SAVE_SLICE_FAILED); }); -const dashboardId = 14; const dashboardName = 'New dashboard'; const dashboardResponsePayload = { id: 14, @@ -214,38 +178,6 @@ test('createDashboard handles failure', async () => { expect(dispatch.getCall(0).args[0].type).toBe(SAVE_SLICE_FAILED); }); -/** - * Tests getDashboard action - */ - -const getDashboardEndpoint = `glob:*/api/v1/dashboard/${dashboardId}`; -test('getDashboard handles success', async () => { - fetchMock.reset(); - fetchMock.get(getDashboardEndpoint, dashboardResponsePayload); - const dispatch = sinon.spy(); - const dashboard = await getDashboard(dashboardId)(dispatch); - expect(fetchMock.calls(getDashboardEndpoint)).toHaveLength(1); - expect(dispatch.callCount).toBe(0); - expect(dashboard).toEqual(dashboardResponsePayload); -}); - -test('getDashboard handles failure', async () => { - fetchMock.reset(); - fetchMock.get(getDashboardEndpoint, { throws: sampleError }); - const dispatch = sinon.spy(); - let caughtError; - try { - await getDashboard(dashboardId)(dispatch); - } catch (error) { - caughtError = error; - } - - expect(caughtError).toEqual(sampleError); - expect(fetchMock.calls(getDashboardEndpoint)).toHaveLength(4); - expect(dispatch.callCount).toBe(1); - expect(dispatch.getCall(0).args[0].type).toBe(SAVE_SLICE_FAILED); -}); - test('updateSlice with add to new dashboard handles success', async () => { fetchMock.reset(); fetchMock.put(updateSliceEndpoint, sliceResponsePayload); diff --git a/superset-frontend/src/explore/components/SaveModal.test.jsx b/superset-frontend/src/explore/components/SaveModal.test.jsx index 15bfc64e7588b..74d1c1199c75e 100644 --- a/superset-frontend/src/explore/components/SaveModal.test.jsx +++ b/superset-frontend/src/explore/components/SaveModal.test.jsx @@ -20,10 +20,8 @@ import React from 'react'; import configureStore from 'redux-mock-store'; import thunk from 'redux-thunk'; import { bindActionCreators } from 'redux'; -import { Provider } from 'react-redux'; import { shallow } from 'enzyme'; -import { styledMount as mount } from 'spec/helpers/theming'; import { Radio } from 'src/components/Radio'; import Button from 'src/components/Button'; import sinon from 'sinon'; @@ -39,6 +37,7 @@ const initialState = { chart: {}, saveModal: { dashboards: [], + isVisible: true, }, explore: { datasource: {}, @@ -57,6 +56,7 @@ const initialState = { const initialStore = mockStore(initialState); const defaultProps = { + addDangerToast: jest.fn(), onHide: () => ({}), actions: bindActionCreators(saveModalActions, arg => { if (typeof arg === 'function') { @@ -83,6 +83,7 @@ const queryStore = mockStore({ chart: {}, saveModal: { dashboards: [], + isVisible: true, }, explore: { datasource: { name: 'test', type: 'query' }, @@ -144,8 +145,7 @@ test('renders the right footer buttons when existing dashboard selected', () => test('renders the right footer buttons when new dashboard selected', () => { const wrapper = getWrapper(); wrapper.setState({ - saveToDashboardId: null, - newDashboardName: 'Test new dashboard', + dashboard: { label: 'Test new dashboard', value: 'Test new dashboard' }, }); const footerWrapper = shallow(wrapper.find(StyledModal).props().footer); const saveAndGoDash = footerWrapper @@ -186,18 +186,6 @@ test('sets action when overwriting slice', () => { expect(wrapperForOverwrite.state().action).toBe('overwrite'); }); -test('fetches dashboards on component mount', () => { - sinon.spy(defaultProps.actions, 'fetchDashboards'); - mount( - - - , - ); - expect(defaultProps.actions.fetchDashboards.calledOnce).toBe(true); - - defaultProps.actions.fetchDashboards.restore(); -}); - test('updates slice name and selected dashboard', () => { const wrapper = getWrapper(); const dashboardId = mockEvent.value; @@ -205,8 +193,8 @@ test('updates slice name and selected dashboard', () => { wrapper.instance().onSliceNameChange(mockEvent); expect(wrapper.state().newSliceName).toBe(mockEvent.target.value); - wrapper.instance().onDashboardSelectChange(dashboardId); - expect(wrapper.state().saveToDashboardId).toBe(dashboardId); + wrapper.instance().onDashboardChange({ value: dashboardId }); + expect(wrapper.state().dashboard.value).toBe(dashboardId); }); test('removes alert', () => { diff --git a/superset-frontend/src/explore/components/SaveModal.tsx b/superset-frontend/src/explore/components/SaveModal.tsx index 9e63f10b61488..849baa1417b01 100644 --- a/superset-frontend/src/explore/components/SaveModal.tsx +++ b/superset-frontend/src/explore/components/SaveModal.tsx @@ -19,17 +19,18 @@ /* eslint camelcase: 0 */ import React from 'react'; import { Dispatch } from 'redux'; -import { SelectValue } from 'antd/lib/select'; +import { isFeatureEnabled } from 'src/featureFlags'; +import rison from 'rison'; import { connect } from 'react-redux'; import { withRouter, RouteComponentProps } from 'react-router-dom'; import { InfoTooltipWithTrigger } from '@superset-ui/chart-controls'; import { css, DatasourceType, - ensureIsArray, FeatureFlag, isDefined, styled, + SupersetClient, t, } from '@superset-ui/core'; import { Input } from 'src/components/Input'; @@ -38,11 +39,10 @@ import Alert from 'src/components/Alert'; import Modal from 'src/components/Modal'; import { Radio } from 'src/components/Radio'; import Button from 'src/components/Button'; -import { Select } from 'src/components'; +import { AsyncSelect } from 'src/components'; import Loading from 'src/components/Loading'; import { setSaveChartModalVisibility } from 'src/explore/actions/saveModalActions'; import { SaveActionType } from 'src/explore/types'; -import { isFeatureEnabled } from 'src/featureFlags'; // Session storage key for recent dashboard const SK_DASHBOARD_ID = 'save_chart_recent_dashboard'; @@ -52,7 +52,6 @@ interface SaveModalProps extends RouteComponentProps { actions: Record; form_data?: Record; userId: number; - dashboards: Array; alert?: string; sliceName?: string; slice?: Record; @@ -63,15 +62,14 @@ interface SaveModalProps extends RouteComponentProps { } type SaveModalState = { - saveToDashboardId: number | string | null; newSliceName?: string; - newDashboardName?: string; datasetName: string; alert: string | null; action: SaveActionType; isLoading: boolean; saveStatus?: string | null; vizType?: string; + dashboard?: { label: string; value: string | number }; }; export const StyledModal = styled(Modal)` @@ -89,15 +87,15 @@ class SaveModal extends React.Component { constructor(props: SaveModalProps) { super(props); this.state = { - saveToDashboardId: null, newSliceName: props.sliceName, datasetName: props.datasource?.name, alert: null, action: this.canOverwriteSlice() ? 'overwrite' : 'saveas', isLoading: false, vizType: props.form_data?.viz_type, + dashboard: undefined, }; - this.onDashboardSelectChange = this.onDashboardSelectChange.bind(this); + this.onDashboardChange = this.onDashboardChange.bind(this); this.onSliceNameChange = this.onSliceNameChange.bind(this); this.changeAction = this.changeAction.bind(this); this.saveOrOverwrite = this.saveOrOverwrite.bind(this); @@ -107,7 +105,8 @@ class SaveModal extends React.Component { } isNewDashboard(): boolean { - return !!(!this.state.saveToDashboardId && this.state.newDashboardName); + const { dashboard } = this.state; + return typeof dashboard?.value === 'string'; } canOverwriteSlice(): boolean { @@ -117,30 +116,26 @@ class SaveModal extends React.Component { ); } - componentDidMount() { - this.props.actions.fetchDashboards(this.props.userId).then(() => { - if (ensureIsArray(this.props.dashboards).length === 0) { - return; - } - const dashboardIds = this.props.dashboards?.map( - dashboard => dashboard.value, - ); + async componentDidMount() { + let { dashboardId } = this.props; + if (!dashboardId) { const lastDashboard = sessionStorage.getItem(SK_DASHBOARD_ID); - let recentDashboard = lastDashboard && parseInt(lastDashboard, 10); - - if (this.props.dashboardId) { - recentDashboard = this.props.dashboardId; - } - - if ( - recentDashboard !== null && - dashboardIds.indexOf(recentDashboard) !== -1 - ) { - this.setState({ - saveToDashboardId: recentDashboard, - }); + dashboardId = lastDashboard && parseInt(lastDashboard, 10); + } + if (dashboardId) { + try { + const result = await this.loadDashboard(dashboardId); + if (result) { + this.setState({ + dashboard: { label: result.dashboard_title, value: result.id }, + }); + } + } catch (error) { + this.props.actions.addDangerToast( + t('An error occurred while loading dashboard information.'), + ); } - }); + } } handleDatasetNameChange = (e: React.FormEvent) => { @@ -152,11 +147,8 @@ class SaveModal extends React.Component { this.setState({ newSliceName: event.target.value }); } - onDashboardSelectChange(selected: SelectValue) { - const newDashboardName = selected ? String(selected) : undefined; - const saveToDashboardId = - selected && typeof selected === 'number' ? selected : null; - this.setState({ saveToDashboardId, newDashboardName }); + onDashboardChange(dashboard: { label: string; value: string | number }) { + this.setState({ dashboard }); } changeAction(action: SaveActionType) { @@ -206,19 +198,22 @@ class SaveModal extends React.Component { delete formData.url_params; let dashboard: DashboardGetResponse | null = null; - if (this.state.newDashboardName || this.state.saveToDashboardId) { - let saveToDashboardId = this.state.saveToDashboardId || null; - if (!this.state.saveToDashboardId) { + if (this.state.dashboard) { + let validId = this.state.dashboard.value; + if (this.isNewDashboard()) { const response = await this.props.actions.createDashboard( - this.state.newDashboardName, + this.state.dashboard.label, ); - saveToDashboardId = response.id; + validId = response.id; + } + + try { + dashboard = await this.loadDashboard(validId as number); + } catch (error) { + this.props.actions.saveSliceFailed(); + return; } - const response = await this.props.actions.getDashboard( - saveToDashboardId, - ); - dashboard = response.result; if (isDefined(dashboard) && isDefined(dashboard?.id)) { sliceDashboards = sliceDashboards.includes(dashboard.id) ? sliceDashboards @@ -240,7 +235,7 @@ class SaveModal extends React.Component { dashboard ? { title: dashboard.dashboard_title, - new: !this.state.saveToDashboardId, + new: this.isNewDashboard(), } : null, ); @@ -251,7 +246,7 @@ class SaveModal extends React.Component { dashboard ? { title: dashboard.dashboard_title, - new: !this.state.saveToDashboardId, + new: this.isNewDashboard(), } : null, ); @@ -284,94 +279,131 @@ class SaveModal extends React.Component { } } - renderSaveChartModal = () => { - const dashboardSelectValue = - this.state.saveToDashboardId || this.state.newDashboardName; + loadDashboard = async (id: number) => { + const response = await SupersetClient.get({ + endpoint: `/api/v1/dashboard/${id}`, + }); + return response.json.result; + }; - return ( -
- {(this.state.alert || this.props.alert) && ( - { + const queryParams = rison.encode({ + columns: ['id', 'dashboard_title'], + filters: [ + { + col: 'dashboard_title', + opr: 'ct', + value: search, + }, + { + col: 'owners', + opr: 'rel_m_m', + value: this.props.userId, + }, + ], + page, + page_size: pageSize, + order_column: 'dashboard_title', + }); + + const { json } = await SupersetClient.get({ + endpoint: `/api/v1/dashboard/?q=${queryParams}`, + }); + const { result, count } = json; + return { + data: result.map( + (dashboard: { id: number; dashboard_title: string }) => ({ + value: dashboard.id, + label: dashboard.dashboard_title, + }), + ), + totalCount: count, + }; + }; + + renderSaveChartModal = () => ( + + {(this.state.alert || this.props.alert) && ( + + )} + + this.changeAction('overwrite')} + data-test="save-overwrite-radio" + > + {t('Save (Overwrite)')} + + this.changeAction('saveas')} + > + {t('Save as...')} + + +
+ + + + {this.props.datasource?.type === 'query' && ( + + - )} - - this.changeAction('overwrite')} - data-test="save-overwrite-radio" - > - {t('Save (Overwrite)')} - - this.changeAction('saveas')} - > - {t('Save as...')} - - -
- - {this.props.datasource?.type === 'query' && ( - - - - - )} - {!( - isFeatureEnabled(FeatureFlag.DASHBOARD_NATIVE_FILTERS) && - this.state.vizType === 'filter_box' - ) && ( - -