-
Notifications
You must be signed in to change notification settings - Fork 104
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactor Provider Credentials (#2195)
* Refactor Provider Credentials WIP * rm unused function * Some cleanup * Some fixes Highlight secret row instead of open secret dialog * use composable for shared secret data show secret data in edit mode * PR Feedback * Adapted frontend tests * Adapted backend tests * Return secretbindings, secrets, quotas as separate lists * Use lodash chaining to resolve secretbinding quotas * PR Feedback 1 * - Create and Update Secret resources using `stringData` - Improved SecretDat composable - Added tests for credential store * Create Secret and SecretBinding resources in Frontend Removed secretData composable in favour of credential context composable * Fixed minor things - Renamed secretBindingNamespace variables to bindingNamespace (preparation for credentialsbinding) - Removed $reset logic in case of CUD operations - Added missing $reset before setting store credentials * PR Feedback 1 * PR Feedback 2 * PR Feedback 3 * Fixed error on details page when accessing ._secret * PR Feedback * PR Feedback - Removed secret item route - Navigate to page with highlighted secret * use useUrlSearchParams fixed secret dialog resizing reset highlighted secret on click * PR Feedback
- Loading branch information
Showing
66 changed files
with
2,521 additions
and
1,639 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
// | ||
// SPDX-FileCopyrightText: 2023 SAP SE or an SAP affiliate company and Gardener contributors | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
|
||
'use strict' | ||
|
||
const express = require('express') | ||
const { cloudProviderCredentials } = require('../services') | ||
const { metricsRoute } = require('../middleware') | ||
const { UnprocessableEntity } = require('http-errors') | ||
|
||
const router = module.exports = express.Router({ | ||
mergeParams: true, | ||
}) | ||
|
||
const metricsMiddleware = metricsRoute('cloudProviderCredentials') | ||
|
||
router.route('/') | ||
.all(metricsMiddleware) | ||
.post(async (req, res, next) => { | ||
try { | ||
const user = req.user | ||
const { method, params } = req.body | ||
|
||
let credentialOperation | ||
switch (method) { | ||
case 'list': | ||
credentialOperation = cloudProviderCredentials.list | ||
break | ||
case 'create': | ||
credentialOperation = cloudProviderCredentials.create | ||
break | ||
case 'patch': | ||
credentialOperation = cloudProviderCredentials.patch | ||
break | ||
case 'remove': | ||
credentialOperation = cloudProviderCredentials.remove | ||
break | ||
default: | ||
throw new UnprocessableEntity(`${method} not allowed for cloud provider credentials`) | ||
} | ||
res.send(await credentialOperation.call(cloudProviderCredentials, { user, params })) | ||
} catch (err) { | ||
next(err) | ||
} | ||
}) |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
// | ||
// SPDX-FileCopyrightText: 2023 SAP SE or an SAP affiliate company and Gardener contributors | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
|
||
const _ = require('lodash') | ||
const { getQuotas } = require('../cache') | ||
const createError = require('http-errors') | ||
const logger = require('../logger') | ||
|
||
exports.list = async function ({ user, params }) { | ||
const client = user.client | ||
const { bindingNamespace } = params | ||
|
||
const [ | ||
{ items: secretBindings }, | ||
{ items: secrets }, | ||
] = await Promise.all([ | ||
client['core.gardener.cloud'].secretbindings.list(bindingNamespace), | ||
client.core.secrets.list(bindingNamespace, { labelSelector: 'reference.gardener.cloud/secretbinding=true' }), | ||
]) | ||
|
||
const pickQuotaProperties = _.partialRight(_.pick, [ | ||
'apiVersion', | ||
'kind', | ||
'metadata.name', | ||
'metadata.namespace', | ||
'metadata.uid', | ||
'spec.scope', | ||
'spec.clusterLifetimeDays', | ||
]) | ||
|
||
const quotas = _ | ||
.chain(secretBindings) | ||
.flatMap(resolveQuotas) | ||
.uniqBy('metadata.uid') | ||
.filter('spec.clusterLifetimeDays') | ||
.map(pickQuotaProperties) | ||
.value() | ||
|
||
return { | ||
secretBindings, | ||
secrets, | ||
quotas, | ||
} | ||
} | ||
|
||
exports.create = async function ({ user, params }) { | ||
const client = user.client | ||
|
||
let { secret, secretBinding } = params | ||
const secretNamespace = secret.metadata.namespace | ||
const bindingNamespace = secretBinding.metadata.namespace | ||
const secretRefNamespace = secretBinding.secretRef.namespace | ||
|
||
if (bindingNamespace !== secretRefNamespace || | ||
secretRefNamespace !== secretNamespace) { | ||
throw createError(422, 'Create allowed if secret and secretBinding are in the same namespace') | ||
} | ||
|
||
secret = await client.core.secrets.create(secretNamespace, secret) | ||
|
||
try { | ||
secretBinding = await client['core.gardener.cloud'].secretbindings.create(bindingNamespace, secretBinding) | ||
} catch (err) { | ||
logger.error('failed to create SecretBinding, cleaning up secret %s/%s', secret.metadata.namespace, secret.metadata.name) | ||
await client.core.secrets.delete(secret.metadata.namespace, secret.metadata.name) | ||
|
||
throw err | ||
} | ||
|
||
return { | ||
secretBinding, | ||
secret, | ||
quotas: resolveQuotas(secretBinding), | ||
} | ||
} | ||
|
||
exports.patch = async function ({ user, params }) { | ||
const client = user.client | ||
|
||
let { secret, secretBinding } = params | ||
const secretNamespace = secret.metadata.namespace | ||
const secretName = secret.metadata.name | ||
const bindingNamespace = secretBinding.metadata.namespace | ||
const secretBindingName = secretBinding.metadata.name | ||
const secretRefNamespace = secretBinding.secretRef.namespace | ||
|
||
secretBinding = await client['core.gardener.cloud'].secretbindings.get(bindingNamespace, secretBindingName) | ||
if (!secretBinding) { | ||
throw createError(404) | ||
} | ||
if (bindingNamespace !== secretRefNamespace || | ||
secretRefNamespace !== secretNamespace) { | ||
throw createError(422, 'Patch allowed only if secret and secretBinding are in the same namespace') | ||
} | ||
secret = await client.core.secrets.update(bindingNamespace, secretName, secret) | ||
|
||
return { | ||
secretBinding, | ||
secret, | ||
quotas: resolveQuotas(secretBinding), | ||
} | ||
} | ||
|
||
exports.remove = async function ({ user, params }) { | ||
const client = user.client | ||
const { bindingNamespace, secretBindingName } = params | ||
|
||
const secretBinding = await client['core.gardener.cloud'].secretbindings.get(bindingNamespace, secretBindingName) | ||
if (!secretBinding) { | ||
throw createError(404) | ||
} | ||
if (secretBinding.metadata.namespace !== secretBinding.secretRef.namespace) { | ||
throw createError(422, 'Remove allowed only if secret and secretBinding are in the same namespace') | ||
} | ||
|
||
const secretRef = secretBinding.secretRef | ||
await Promise.all([ | ||
await client['core.gardener.cloud'].secretbindings.delete(bindingNamespace, secretBindingName), | ||
await client.core.secrets.delete(secretRef.namespace, secretRef.name), | ||
]) | ||
} | ||
|
||
function resolveQuotas (secretBinding) { | ||
const quotas = getQuotas() | ||
const findQuota = ({ namespace, name } = {}) => _.find(quotas, ({ metadata }) => metadata.namespace === namespace && metadata.name === name) | ||
try { | ||
return _ | ||
.chain(secretBinding.quotas) | ||
.map(findQuota) | ||
.compact() | ||
.value() | ||
} catch (err) { | ||
return [] | ||
} | ||
} |
Oops, something went wrong.