From f180778f41860715bf9991b9a90704a891f0c8e3 Mon Sep 17 00:00:00 2001 From: Lukas Gross Date: Tue, 28 Feb 2023 14:47:18 +0100 Subject: [PATCH 01/12] Added error handling in case of missing cloud profile --- frontend/src/store/modules/shoots/index.js | 5 +++ frontend/src/views/NewShoot.vue | 42 +++++++++++++--------- frontend/src/views/Secrets.vue | 8 ++++- 3 files changed, 38 insertions(+), 17 deletions(-) diff --git a/frontend/src/store/modules/shoots/index.js b/frontend/src/store/modules/shoots/index.js index 0091786619..24da4de2c3 100644 --- a/frontend/src/store/modules/shoots/index.js +++ b/frontend/src/store/modules/shoots/index.js @@ -228,6 +228,11 @@ const actions = { } } + if (!rootGetters.sortedCloudProviderKindList.length) { + Vue.logger.warn('Could not reset new shoot resource as there is no supported cloud profile') + return + } + const infrastructureKind = head(rootGetters.sortedCloudProviderKindList) set(shootResource, 'spec', getSpecTemplate(infrastructureKind, rootGetters.nodesCIDR)) diff --git a/frontend/src/views/NewShoot.vue b/frontend/src/views/NewShoot.vue index 7ba9d989f5..1e7c015349 100644 --- a/frontend/src/views/NewShoot.vue +++ b/frontend/src/views/NewShoot.vue @@ -5,7 +5,7 @@ SPDX-License-Identifier: Apache-2.0 --> diff --git a/frontend/src/views/Secrets.vue b/frontend/src/views/Secrets.vue index 8cdb59cf7c..f8f9537727 100644 --- a/frontend/src/views/Secrets.vue +++ b/frontend/src/views/Secrets.vue @@ -57,7 +57,13 @@ SPDX-License-Identifier: Apache-2.0 > - + + + No supported cloud profile found. + Ensure that you have confiugred at least one cloud profile supported by the dashboard as well as a corresponding seed. + + +
Add Infrastructure Secrets to your project

Before you can provision and access a Kubernetes cluster, you need to add infrastructure account credentials. The Gardener needs the credentials to provision and operate the infrastructure for your Kubernetes cluster. From 859ce481c4131d6736bd05e646d053ec14a0743a Mon Sep 17 00:00:00 2001 From: Lukas Gross Date: Wed, 1 Mar 2023 10:50:41 +0100 Subject: [PATCH 02/12] Added support for local cloud provider by adding generic secret dialog --- .../dialogs/SecretDialogGeneric.vue | 154 ++++++++++++++++++ .../dialogs/SecretDialogWrapper.vue | 39 +++-- frontend/src/mixins/shootItem.js | 3 +- frontend/src/store/index.js | 2 +- frontend/src/utils/createShoot.js | 4 + frontend/src/utils/index.js | 2 + frontend/src/views/Secrets.vue | 7 + 7 files changed, 194 insertions(+), 17 deletions(-) create mode 100644 frontend/src/components/dialogs/SecretDialogGeneric.vue diff --git a/frontend/src/components/dialogs/SecretDialogGeneric.vue b/frontend/src/components/dialogs/SecretDialogGeneric.vue new file mode 100644 index 0000000000..6207531a7e --- /dev/null +++ b/frontend/src/components/dialogs/SecretDialogGeneric.vue @@ -0,0 +1,154 @@ + + + + + + + diff --git a/frontend/src/components/dialogs/SecretDialogWrapper.vue b/frontend/src/components/dialogs/SecretDialogWrapper.vue index 10890c991f..1fc94a1a2a 100644 --- a/frontend/src/components/dialogs/SecretDialogWrapper.vue +++ b/frontend/src/components/dialogs/SecretDialogWrapper.vue @@ -21,26 +21,30 @@ import InfobloxDialog from '@/components/dialogs/SecretDialogInfoblox' import NetlifyDialog from '@/components/dialogs/SecretDialogNetlify' import DeleteDialog from '@/components/dialogs/SecretDialogDelete' import HcloudDialog from '@/components/dialogs/SecretDialogHCloud' +import GenericDialog from '@/components/dialogs/SecretDialogGeneric' import upperFirst from 'lodash/upperFirst' import split from 'lodash/split' import head from 'lodash/head' +const components = { + GcpDialog, + AzureDialog, + AwsDialog, + OpenstackDialog, + AlicloudDialog, + MetalDialog, + VsphereDialog, + CloudflareDialog, + InfobloxDialog, + NetlifyDialog, + HcloudDialog, + GenericDialog, + DeleteDialog +} + export default { - components: { - GcpDialog, - AzureDialog, - AwsDialog, - OpenstackDialog, - AlicloudDialog, - MetalDialog, - VsphereDialog, - CloudflareDialog, - InfobloxDialog, - NetlifyDialog, - HcloudDialog, - DeleteDialog - }, + components, data () { return { visibleDialogState: false @@ -63,7 +67,12 @@ export default { return 'GcpDialog' default: { const name = upperFirst(head(split(this.visibleDialog, '-'))) - return `${name}Dialog` + const componentName = `${name}Dialog` + const componentNames = Object.keys(components) + if (componentNames.includes(componentName)) { + return componentName + } + return 'GenericDialog' } } } diff --git a/frontend/src/mixins/shootItem.js b/frontend/src/mixins/shootItem.js index 1d19bffd4a..1a72602496 100644 --- a/frontend/src/mixins/shootItem.js +++ b/frontend/src/mixins/shootItem.js @@ -11,6 +11,7 @@ import cloneDeep from 'lodash/cloneDeep' import find from 'lodash/find' import some from 'lodash/some' import filter from 'lodash/filter' +import compact from 'lodash/compact' import { mapGetters } from 'vuex' import { @@ -129,7 +130,7 @@ export const shootItem = { return this.shootSpec.region }, shootZones () { - return uniq(flatMap(get(this.shootSpec, 'provider.workers'), 'zones')) + return compact(uniq(flatMap(get(this.shootSpec, 'provider.workers'), 'zones'))) }, podsCidr () { return get(this.shootSpec, 'networking.pods') diff --git a/frontend/src/store/index.js b/frontend/src/store/index.js index ddaaa7edf3..a28ccf51fe 100644 --- a/frontend/src/store/index.js +++ b/frontend/src/store/index.js @@ -740,7 +740,7 @@ const getters = { return uniq(map(state.cloudProfiles.all, 'metadata.cloudProviderKind')) }, sortedCloudProviderKindList (state, getters) { - return intersection(['aws', 'azure', 'gcp', 'openstack', 'alicloud', 'metal', 'vsphere', 'hcloud'], getters.cloudProviderKindList) + return intersection(['aws', 'azure', 'gcp', 'openstack', 'alicloud', 'metal', 'vsphere', 'hcloud', 'local'], getters.cloudProviderKindList) }, sortedDnsProviderList (state, getters) { const supportedProviderTypes = ['aws-route53', 'azure-dns', 'azure-private-dns', 'google-clouddns', 'openstack-designate', 'alicloud-dns', 'infoblox-dns', 'netlify-dns'] diff --git a/frontend/src/utils/createShoot.js b/frontend/src/utils/createShoot.js index 1d397676a9..7af9055e14 100644 --- a/frontend/src/utils/createShoot.js +++ b/frontend/src/utils/createShoot.js @@ -180,6 +180,10 @@ function getProviderTemplate (infrastructureKind, defaultWorkerCIDR) { kind: 'ControlPlaneConfig' } } + default: + return { + type: infrastructureKind + } } } diff --git a/frontend/src/utils/index.js b/frontend/src/utils/index.js index aa9aec1071..66c66886ab 100644 --- a/frontend/src/utils/index.js +++ b/frontend/src/utils/index.js @@ -533,6 +533,8 @@ export function isZonedCluster ({ cloudProviderKind, shootSpec, isNewCluster }) return get(shootSpec, 'provider.infrastructureConfig.zoned', false) case 'metal': return false // metal clusters do not support zones for worker groups + case 'local': + return false // local development provider does not support zones default: return true } diff --git a/frontend/src/views/Secrets.vue b/frontend/src/views/Secrets.vue index f8f9537727..566b19513d 100644 --- a/frontend/src/views/Secrets.vue +++ b/frontend/src/views/Secrets.vue @@ -457,6 +457,13 @@ export default { value: secretData.hcloudToken } ] + default: + return [ + { + label: 'Secret Data', + value: JSON.stringify(secretData) + } + ] } }, getSecretDetailsDns (secret) { From 91a854bd8fd910bfcbdc8eb1cf46fe8db245f7cb Mon Sep 17 00:00:00 2001 From: Lukas Gross Date: Wed, 1 Mar 2023 11:32:13 +0100 Subject: [PATCH 03/12] Add generic secret data as yaml Use key insensitive whitelist keys for secret data --- backend/lib/services/cloudProviderSecrets.js | 4 ++-- .../src/components/dialogs/SecretDialogGeneric.vue | 14 ++++++++------ 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/backend/lib/services/cloudProviderSecrets.js b/backend/lib/services/cloudProviderSecrets.js index f9398d1c44..75e9c39c51 100644 --- a/backend/lib/services/cloudProviderSecrets.js +++ b/backend/lib/services/cloudProviderSecrets.js @@ -10,7 +10,7 @@ const { Resources } = require('@gardener-dashboard/kube-client') const createError = require('http-errors') const { format: fmt } = require('util') const { decodeBase64, encodeBase64 } = require('../utils') -const whitelistedPropertyKeys = ['accessKeyID', 'subscriptionID', 'project', 'domainName', 'tenantName', 'authUrl', 'vsphereUsername', 'nsxtUsername', 'USERNAME', 'metalAPIURL'] +const whitelistedPropertyKeys = ['accesskeyid', 'subscriptionID', 'project', 'domainName', 'tenantName', 'authUrl', 'vsphereUsername', 'nsxtUsername', 'username', 'metalAPIURL'] const cloudprofiles = require('./cloudprofiles') const shoots = require('./shoots') const { getQuotas, findProjectByNamespace } = require('../cache') @@ -44,7 +44,7 @@ function fromResource ({ secretBinding, cloudProviderKind, secret, quotas = [], const iteratee = (value, key) => { value = decodeBase64(value) - if (!_.includes(whitelistedPropertyKeys, key)) { + if (!_.includes(_.map(whitelistedPropertyKeys, _.toLower), _.toLower(key))) { value = '****************' } return value diff --git a/frontend/src/components/dialogs/SecretDialogGeneric.vue b/frontend/src/components/dialogs/SecretDialogGeneric.vue index 6207531a7e..a530e78ba3 100644 --- a/frontend/src/components/dialogs/SecretDialogGeneric.vue +++ b/frontend/src/components/dialogs/SecretDialogGeneric.vue @@ -48,11 +48,13 @@ SPDX-License-Identifier: Apache-2.0 import SecretDialog from '@/components/dialogs/SecretDialog' import { required } from 'vuelidate/lib/validators' import { getValidationErrors, setDelayedInputFocus } from '@/utils' +import isObject from 'lodash/isObject' +const yaml = require('js-yaml') const validationErrors = { data: { required: 'You can\'t leave this empty.', - isJSON: 'You need to enter secret data as JSON Object' + isYAML: 'You need to enter secret data as valid YAML object' } } @@ -90,7 +92,7 @@ export default { const validators = { data: { required, - isJSON: () => { return this.secretJSON !== undefined } + isYAML: () => isObject(this.secretYAML) } } return validators @@ -98,15 +100,15 @@ export default { isCreateMode () { return !this.secret }, - secretJSON () { + secretYAML () { try { - return JSON.parse(this.data) - } catch (err) { + return yaml.load(this.data) + } catch (e) { return undefined } }, secretData () { - return this.secretJSON ?? {} + return isObject(this.secretYAML) ? this.secretYAML : {} } }, methods: { From 94212d12fc4923568be003ac685d26aaada8d242 Mon Sep 17 00:00:00 2001 From: Lukas Gross Date: Wed, 1 Mar 2023 14:06:07 +0100 Subject: [PATCH 04/12] added support for seedSelector providerType '*' --- backend/__fixtures__/cloudprofiles.js | 10 +++++- backend/lib/services/cloudprofiles.js | 2 +- .../api.cloudprofiles.spec.js.snap | 33 +++++++++++++++++++ 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/backend/__fixtures__/cloudprofiles.js b/backend/__fixtures__/cloudprofiles.js index a445ef9731..cee58a4437 100644 --- a/backend/__fixtures__/cloudprofiles.js +++ b/backend/__fixtures__/cloudprofiles.js @@ -62,7 +62,15 @@ const cloudProfileList = [ uid: 5, name: 'infra3-profileName2', kind: 'infra3' - }) + }), + getCloudProfile({ + uid: 6, + name: 'infra4-profileName', + kind: 'infra4', + seedSelector: { + providerTypes: ['*'] + } + }), ] const cloudprofiles = { diff --git a/backend/lib/services/cloudprofiles.js b/backend/lib/services/cloudprofiles.js index f560c8659d..eccaebbd6e 100644 --- a/backend/lib/services/cloudprofiles.js +++ b/backend/lib/services/cloudprofiles.js @@ -30,7 +30,7 @@ function assignSeedsToCloudProfileIteratee (seeds) { return cloudProfileResource => { function filterProviderType (seed) { const seedProviderType = _.get(seed, 'spec.provider.type') - return _.includes(providerTypes, seedProviderType) + return _.includes(providerTypes, seedProviderType) || _.includes(providerTypes, '*') } const providerType = cloudProfileResource.spec.type const matchLabels = _.get(cloudProfileResource, 'spec.seedSelector.matchLabels') diff --git a/backend/test/acceptance/__snapshots__/api.cloudprofiles.spec.js.snap b/backend/test/acceptance/__snapshots__/api.cloudprofiles.spec.js.snap index 4d3cfd8c9d..324e8150d0 100644 --- a/backend/test/acceptance/__snapshots__/api.cloudprofiles.spec.js.snap +++ b/backend/test/acceptance/__snapshots__/api.cloudprofiles.spec.js.snap @@ -139,5 +139,38 @@ Array [ "name": "infra3-profileName2", }, }, + Object { + "data": Object { + "kubernetes": Object { + "versions": Array [ + Object { + "version": "1.9.0", + }, + Object { + "version": "1.8.5", + }, + ], + }, + "seedNames": Array [ + "infra1-seed", + "infra1-seed2", + "infra3-seed", + "infra4-seed-without-secretRef", + "infra3-seed-with-selector", + "infra3-seed-without-selector", + ], + "seedSelector": Object { + "providerTypes": Array [ + "*", + ], + }, + "type": "infra4", + }, + "metadata": Object { + "cloudProviderKind": "infra4", + "displayName": "infra4-profileName", + "name": "infra4-profileName", + }, + }, ] `; From 243af7961cbfc6f8f5dd6c0bd6b7b5038a70a284 Mon Sep 17 00:00:00 2001 From: Lukas Gross Date: Wed, 1 Mar 2023 14:23:57 +0100 Subject: [PATCH 05/12] Fixed: Seeds in other regions than the shoot did not show up if no `seedCandidateDeterminationStrategy` set in dashboard config --- .../src/components/NewShoot/NewShootInfrastructureDetails.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/components/NewShoot/NewShootInfrastructureDetails.vue b/frontend/src/components/NewShoot/NewShootInfrastructureDetails.vue index fd68530557..c9120cda2a 100644 --- a/frontend/src/components/NewShoot/NewShootInfrastructureDetails.vue +++ b/frontend/src/components/NewShoot/NewShootInfrastructureDetails.vue @@ -342,7 +342,7 @@ export default { return this.regionsWithoutSeedByCloudProfileName(this.cloudProfileName) }, showAllRegions () { - return this.cfg.seedCandidateDeterminationStrategy && this.cfg.seedCandidateDeterminationStrategy !== 'SameRegion' + return this.cfg.seedCandidateDeterminationStrategy !== 'SameRegion' }, regionItems () { const regionItems = [] From c92f994551b0edef7afcd89fc1f1d32934307fbc Mon Sep 17 00:00:00 2001 From: Lukas Gross Date: Wed, 1 Mar 2023 14:31:37 +0100 Subject: [PATCH 06/12] fixed lint error --- backend/__fixtures__/cloudprofiles.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/__fixtures__/cloudprofiles.js b/backend/__fixtures__/cloudprofiles.js index cee58a4437..e6a5577bf2 100644 --- a/backend/__fixtures__/cloudprofiles.js +++ b/backend/__fixtures__/cloudprofiles.js @@ -70,7 +70,7 @@ const cloudProfileList = [ seedSelector: { providerTypes: ['*'] } - }), + }) ] const cloudprofiles = { From 24761c3956aad11285fc354b4acfd5bfa560c185 Mon Sep 17 00:00:00 2001 From: Lukas Gross Date: Wed, 1 Mar 2023 15:57:52 +0100 Subject: [PATCH 07/12] updated documentation --- docs/development/local-setup.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/development/local-setup.md b/docs/development/local-setup.md index 44fe641628..3577415960 100644 --- a/docs/development/local-setup.md +++ b/docs/development/local-setup.md @@ -57,6 +57,7 @@ frontend: The Gardener Dashboard [`backend`](https://github.com/gardener/dashboard/tree/master/backend) server requires a kubeconfig for the Garden cluster. You can set it e.g. by using the `KUBECONFIG` environment variable. If you want to run the Garden cluster locally, follow the [getting started locally](https://github.com/gardener/gardener/blob/master/docs/development/getting_started_locally.md) documentation. +Gardener Dashboard supports the `local` infrastructure provider that comes with the local Gardener cluster setup. Please login to the Dashboard with a token of a service account that has cluster admin permission. Concurrently run the `backend` server (port `3030`) and the [`frontend`](https://github.com/gardener/dashboard/tree/master/frontend) server (port `8080`) with hot reload enabled. From 99f13c57e86e4376564301db9c9391959f728551 Mon Sep 17 00:00:00 2001 From: Lukas Gross Date: Mon, 6 Mar 2023 17:04:02 +0100 Subject: [PATCH 08/12] Proposal for configuring custom cloudprofiles via configuration --- backend/lib/routes/config.js | 7 +- .../components/ShootWorkers/ManageWorkers.vue | 7 +- .../ShootWorkers/WorkerConfiguration.vue | 6 +- frontend/src/components/VendorIcon.vue | 57 ++----- .../dialogs/SecretDialogGeneric.vue | 152 +++++++++++------- frontend/src/store/index.js | 3 +- frontend/src/store/modules/shoots/index.js | 2 +- frontend/src/utils/createShoot.js | 30 +++- frontend/src/utils/index.js | 6 +- frontend/src/views/NewShoot.vue | 4 +- 10 files changed, 163 insertions(+), 111 deletions(-) diff --git a/backend/lib/routes/config.js b/backend/lib/routes/config.js index dc10664a15..29ec422e30 100644 --- a/backend/lib/routes/config.js +++ b/backend/lib/routes/config.js @@ -54,7 +54,8 @@ function sanitizeFrontendConfig (frontendConfig) { } = {}, vendorHints = [], resourceQuotaHelp = '', - controlPlaneHighAvailabilityHelp = '' + controlPlaneHighAvailabilityHelp = '', + customCloudProviders = {} } = sanitizedFrontendConfig convertAndSanitize(alert, 'message') @@ -86,5 +87,9 @@ function sanitizeFrontendConfig (frontendConfig) { convertAndSanitize(vendorHint, 'message') } + for (const key of Object.keys(customCloudProviders)) { + convertAndSanitize(customCloudProviders[key]?.secret, 'help') + } + return sanitizedFrontendConfig } diff --git a/frontend/src/components/ShootWorkers/ManageWorkers.vue b/frontend/src/components/ShootWorkers/ManageWorkers.vue index 8e53c736cb..e52dfc9d1d 100644 --- a/frontend/src/components/ShootWorkers/ManageWorkers.vue +++ b/frontend/src/components/ShootWorkers/ManageWorkers.vue @@ -62,7 +62,7 @@ SPDX-License-Identifier: Apache-2.0 diff --git a/frontend/src/store/index.js b/frontend/src/store/index.js index a28ccf51fe..52a9c6b656 100644 --- a/frontend/src/store/index.js +++ b/frontend/src/store/index.js @@ -740,7 +740,8 @@ const getters = { return uniq(map(state.cloudProfiles.all, 'metadata.cloudProviderKind')) }, sortedCloudProviderKindList (state, getters) { - return intersection(['aws', 'azure', 'gcp', 'openstack', 'alicloud', 'metal', 'vsphere', 'hcloud', 'local'], getters.cloudProviderKindList) + const cloudProviderList = state.cfg.cloudProviderList ?? ['aws', 'azure', 'gcp', 'openstack', 'alicloud', 'metal', 'vsphere', 'hcloud', 'local'] + return intersection(cloudProviderList, getters.cloudProviderKindList) }, sortedDnsProviderList (state, getters) { const supportedProviderTypes = ['aws-route53', 'azure-dns', 'azure-private-dns', 'google-clouddns', 'openstack-designate', 'alicloud-dns', 'infoblox-dns', 'netlify-dns'] diff --git a/frontend/src/store/modules/shoots/index.js b/frontend/src/store/modules/shoots/index.js index 24da4de2c3..0c5fa0de15 100644 --- a/frontend/src/store/modules/shoots/index.js +++ b/frontend/src/store/modules/shoots/index.js @@ -234,7 +234,7 @@ const actions = { } const infrastructureKind = head(rootGetters.sortedCloudProviderKindList) - set(shootResource, 'spec', getSpecTemplate(infrastructureKind, rootGetters.nodesCIDR)) + set(shootResource, 'spec', getSpecTemplate(infrastructureKind, rootGetters.nodesCIDR, rootState.cfg.customCloudProviders)) const cloudProfileName = get(head(rootGetters.cloudProfilesByCloudProviderKind(infrastructureKind)), 'metadata.name') set(shootResource, 'spec.cloudProfileName', cloudProfileName) diff --git a/frontend/src/utils/createShoot.js b/frontend/src/utils/createShoot.js index 7af9055e14..72d58c4eb3 100644 --- a/frontend/src/utils/createShoot.js +++ b/frontend/src/utils/createShoot.js @@ -17,8 +17,30 @@ import filter from 'lodash/filter' import range from 'lodash/range' import pick from 'lodash/pick' import values from 'lodash/values' +import get from 'lodash/get' +import template from 'lodash/template' -export function getSpecTemplate (infrastructureKind, defaultWorkerCIDR) { +export function getSpecTemplate (infrastructureKind, defaultWorkerCIDR, customCloudProviders) { + const defaultShootSpec = { + networking: { + nodes: defaultWorkerCIDR + } + } + + const customCloudProviderSpec = get(customCloudProviders, [infrastructureKind, 'shoot', 'specTemplate']) + if (customCloudProviderSpec !== undefined) { + const customCloudProviderSpecJson = JSON.stringify(customCloudProviderSpec) + const compiled = template(customCloudProviderSpecJson) + const data = compiled({ + workerCIDR: defaultWorkerCIDR + }) + + const shootSpec = JSON.parse(data) + return { + ...defaultShootSpec, + ...shootSpec + } + } switch (infrastructureKind) { case 'metal': return { // TODO: Remove when metal extension sets this config via mutating webhook, see https://github.com/metal-stack/gardener-extension-provider-metal/issues/32 @@ -52,10 +74,8 @@ export function getSpecTemplate (infrastructureKind, defaultWorkerCIDR) { } default: return { - provider: getProviderTemplate(infrastructureKind, defaultWorkerCIDR), - networking: { - nodes: defaultWorkerCIDR - } + ...defaultShootSpec, + provider: getProviderTemplate(infrastructureKind, defaultWorkerCIDR) } } } diff --git a/frontend/src/utils/index.js b/frontend/src/utils/index.js index 66c66886ab..8918523164 100644 --- a/frontend/src/utils/index.js +++ b/frontend/src/utils/index.js @@ -524,7 +524,11 @@ export function defaultCriNameByKubernetesVersion (criNames, kubernetesVersion) ? criName : head(criNames) } -export function isZonedCluster ({ cloudProviderKind, shootSpec, isNewCluster }) { +export function isZonedCluster ({ cloudProviderKind, shootSpec, isNewCluster, customCloudProviders }) { + const customCloudProviderZone = get(customCloudProviders, [cloudProviderKind, 'zoned']) + if (customCloudProviderZone !== undefined) { + return customCloudProviderZone + } switch (cloudProviderKind) { case 'azure': if (isNewCluster) { diff --git a/frontend/src/views/NewShoot.vue b/frontend/src/views/NewShoot.vue index 1e7c015349..12f53ea311 100644 --- a/frontend/src/views/NewShoot.vue +++ b/frontend/src/views/NewShoot.vue @@ -286,7 +286,7 @@ export default { const oldInfrastructureKind = get(shootResource, 'spec.provider.type') if (oldInfrastructureKind !== infrastructureKind) { // Infrastructure changed - set(shootResource, 'spec', getSpecTemplate(infrastructureKind, this.nodesCIDR)) + set(shootResource, 'spec', getSpecTemplate(infrastructureKind, this.nodesCIDR, this.cfg.customCloudProviders)) } set(shootResource, 'spec.cloudProfileName', cloudProfileName) set(shootResource, 'spec.region', region) @@ -462,7 +462,7 @@ export default { }) const workers = get(shootResource, 'spec.provider.workers') - const zonedCluster = isZonedCluster({ cloudProviderKind: infrastructureKind, isNewCluster: true }) + const zonedCluster = isZonedCluster({ cloudProviderKind: infrastructureKind, isNewCluster: true, customCloudProviders: this.cfg.customCloudProviders }) const newShootWorkerCIDR = get(shootResource, 'spec.networking.nodes', this.nodesCIDR) await this.$manageWorkers.dispatch('setWorkersData', { workers, cloudProfileName, region, updateOSMaintenance: osUpdates, zonedCluster, kubernetesVersion, newShootWorkerCIDR }) From cb042347b90cbe1000e0fa526bfadb69b9b2f48a Mon Sep 17 00:00:00 2001 From: Lukas Gross Date: Wed, 15 Mar 2023 08:36:48 +0100 Subject: [PATCH 09/12] Configure custom cloud provider icons via asset configuration --- backend/lib/routes/config.js | 2 +- .../components/ShootWorkers/ManageWorkers.vue | 6 +++++- .../ShootWorkers/WorkerConfiguration.vue | 17 +++++++++++++++-- frontend/src/components/VendorIcon.vue | 2 +- 4 files changed, 22 insertions(+), 5 deletions(-) diff --git a/backend/lib/routes/config.js b/backend/lib/routes/config.js index 29ec422e30..e50ccfc80d 100644 --- a/backend/lib/routes/config.js +++ b/backend/lib/routes/config.js @@ -87,7 +87,7 @@ function sanitizeFrontendConfig (frontendConfig) { convertAndSanitize(vendorHint, 'message') } - for (const key of Object.keys(customCloudProviders)) { + for (const key of Object.keys(customCloudProviders)) { convertAndSanitize(customCloudProviders[key]?.secret, 'help') } diff --git a/frontend/src/components/ShootWorkers/ManageWorkers.vue b/frontend/src/components/ShootWorkers/ManageWorkers.vue index e52dfc9d1d..2061bf4e6b 100644 --- a/frontend/src/components/ShootWorkers/ManageWorkers.vue +++ b/frontend/src/components/ShootWorkers/ManageWorkers.vue @@ -314,7 +314,11 @@ export default { * do not pass shootspec as we do not have it available in this component and it is (currently) not required to determine isZoned for new clusters. This event handler is only called for new clusters, as the * userInterActionBus is only set for the create cluster use case */ - this.zonedCluster = isZonedCluster({ cloudProviderKind: this.cloudProviderKind, isNewCluster: this.isNewCluster, customCloudProviders: this.cfg.customCloudProviders }) + this.zonedCluster = isZonedCluster({ + cloudProviderKind: this.cloudProviderKind, + isNewCluster: this.isNewCluster, + customCloudProviders: this.cfg.customCloudProviders + }) this.setDefaultWorker() }) this.userInterActionBus.on('updateRegion', region => { diff --git a/frontend/src/components/ShootWorkers/WorkerConfiguration.vue b/frontend/src/components/ShootWorkers/WorkerConfiguration.vue index e3f94b315a..6a8af572c0 100644 --- a/frontend/src/components/ShootWorkers/WorkerConfiguration.vue +++ b/frontend/src/components/ShootWorkers/WorkerConfiguration.vue @@ -167,10 +167,23 @@ export default { const zonesNetworkConfiguration = get(this.shootItem, 'spec.provider.infrastructureConfig.networks.zones') const cloudProfileName = this.shootCloudProfileName const region = this.shootRegion - const zonedCluster = isZonedCluster({ cloudProviderKind: this.shootCloudProviderKind, shootSpec: this.shootSpec, customCloudProviders: this.cfg.customCloudProviders }) + const zonedCluster = isZonedCluster({ + cloudProviderKind: this.shootCloudProviderKind, + shootSpec: this.shootSpec, + customCloudProviders: this.cfg.customCloudProviders + }) const existingWorkerCIDR = get(this.shootItem, 'spec.networking.nodes') - await this.$manageWorkers.dispatch('setWorkersData', { workers, cloudProfileName, region, zonesNetworkConfiguration, zonedCluster, existingWorkerCIDR, kubernetesVersion: this.shootK8sVersion }) + await this.$manageWorkers.dispatch('setWorkersData', { + workers, + cloudProfileName, + region, + zonesNetworkConfiguration, + zonedCluster, + existingWorkerCIDR, + kubernetesVersion: + this.shootK8sVersion + }) this.tabValue = 'overview' }, onWorkersValid (value) { diff --git a/frontend/src/components/VendorIcon.vue b/frontend/src/components/VendorIcon.vue index 7f79ca0482..a790700f69 100644 --- a/frontend/src/components/VendorIcon.vue +++ b/frontend/src/components/VendorIcon.vue @@ -38,7 +38,7 @@ export default { iconSrc () { const customCloudProviderIcon = get(this.cfg, ['customCloudProviders', this.value, 'icon']) if (customCloudProviderIcon) { - return customCloudProviderIcon + return `/static/assets/${customCloudProviderIcon}` } // If filename is different from value you need to specify this below From 63724f19558a453f8b6a592d1e5a39d828161ba4 Mon Sep 17 00:00:00 2001 From: Lukas Gross Date: Fri, 17 Mar 2023 16:52:34 +0100 Subject: [PATCH 10/12] Added possibility to configure different validator types Added possibility to configure required dependencies between multiple fields Added possibility to configure yaml and json textarea inputs Removed hard-coded fallback yaml input field. Now this is also generated --- backend/lib/routes/config.js | 5 +- frontend/src/components/Purpose.vue | 2 +- .../dialogs/SecretDialogGeneric.vue | 118 ++++++++++++------ 3 files changed, 83 insertions(+), 42 deletions(-) diff --git a/backend/lib/routes/config.js b/backend/lib/routes/config.js index 7a35c411cb..e77cf53c0d 100644 --- a/backend/lib/routes/config.js +++ b/backend/lib/routes/config.js @@ -91,7 +91,10 @@ function sanitizeFrontendConfig (frontendConfig) { } for (const key of Object.keys(customCloudProviders)) { - convertAndSanitize(customCloudProviders[key]?.secret, 'help') + const secret = customCloudProviders[key]?.secret + if (secret) { + convertAndSanitize(secret, 'help') + } } return sanitizedFrontendConfig diff --git a/frontend/src/components/Purpose.vue b/frontend/src/components/Purpose.vue index f35893a2f7..e1f6b60107 100644 --- a/frontend/src/components/Purpose.vue +++ b/frontend/src/components/Purpose.vue @@ -39,7 +39,7 @@ import head from 'lodash/head' const validationErrors = { internalPurpose: { - required: 'Purpose is required.' + required: 'Purpose is required' } } diff --git a/frontend/src/components/dialogs/SecretDialogGeneric.vue b/frontend/src/components/dialogs/SecretDialogGeneric.vue index 23f4e0a3aa..6707ec226b 100644 --- a/frontend/src/components/dialogs/SecretDialogGeneric.vue +++ b/frontend/src/components/dialogs/SecretDialogGeneric.vue @@ -17,32 +17,33 @@ SPDX-License-Identifier: Apache-2.0