Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implemented Disable Gardener provided static admin kubeconfig #1249

Merged
merged 10 commits into from
Aug 16, 2022
13 changes: 13 additions & 0 deletions backend/lib/routes/shoots.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,19 @@ router.route('/:name')
}
})

router.route('/:name/spec/kubernetes/enableStaticTokenKubeconfig')
.put(async (req, res, next) => {
try {
const user = req.user
const namespace = req.params.namespace
const name = req.params.name
const body = req.body
res.send(await shoots.replaceEnableStaticTokenKubeconfig({ user, namespace, name, body }))
} catch (err) {
next(err)
}
})

router.route('/:name/spec/kubernetes/version')
.put(async (req, res, next) => {
try {
Expand Down
11 changes: 11 additions & 0 deletions backend/lib/services/shoots.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,17 @@ exports.replaceVersion = async function ({ user, namespace, name, body }) {
return client['core.gardener.cloud'].shoots.jsonPatch(namespace, name, patchOperations)
}

exports.replaceEnableStaticTokenKubeconfig = async function ({ user, namespace, name, body }) {
const client = user.client
const enableStaticTokenKubeconfig = body.enableStaticTokenKubeconfig === true
const patchOperations = [{
op: 'replace',
path: '/spec/kubernetes/enableStaticTokenKubeconfig',
value: enableStaticTokenKubeconfig
}]
return client['core.gardener.cloud'].shoots.jsonPatch(namespace, name, patchOperations)
}

exports.replaceHibernationEnabled = async function ({ user, namespace, name, body }) {
const client = user.client
const enabled = !!body.enabled
Expand Down
88 changes: 72 additions & 16 deletions backend/test/acceptance/__snapshots__/api.shoots.spec.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -637,6 +637,62 @@ Object {
}
`;

exports[`api shoots should replace shoot kubernetes enableStaticTokenKubeconfig 1`] = `
Array [
Array [
Object {
":authority": "kubernetes:6443",
":method": "patch",
":path": "/apis/core.gardener.cloud/v1beta1/namespaces/garden-foo/shoots/barShoot",
":scheme": "https",
"authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6ImZvb0BleGFtcGxlLm9yZyIsImlhdCI6MTU3NzgzNjgwMCwiYXVkIjpbImdhcmRlbmVyIl0sImV4cCI6MzE1NTcxNjgwMCwianRpIjoianRpIn0.k3kGjF6AgugJLdwERXEWZPaibFAPFPOnmpT3YM9H0xU",
"content-type": "application/json-patch+json",
},
Array [
Object {
"op": "replace",
"path": "/spec/kubernetes/enableStaticTokenKubeconfig",
"value": true,
},
],
],
]
`;

exports[`api shoots should replace shoot kubernetes enableStaticTokenKubeconfig 2`] = `
Object {
"metadata": Object {
"annotations": Object {
"gardener.cloud/created-by": "[email protected]",
},
"name": "barShoot",
"namespace": "garden-foo",
"resourceVersion": "43",
"uid": 2,
},
"spec": Object {
"cloudProfileName": "infra1-profileName",
"hibernation": Object {
"enabled": false,
},
"kubernetes": Object {
"enableStaticTokenKubeconfig": true,
"version": "1.16.0",
},
"provider": Object {
"type": "fooInfra",
},
"purpose": "barPurpose",
"region": "foo-west",
"secretBindingName": "foo-infra1",
"seedName": "infra1-seed",
},
"status": Object {
"technicalID": "shoot--foo--barShoot",
},
}
`;

exports[`api shoots should replace shoot kubernetes version 1`] = `
Array [
Array [
Expand Down Expand Up @@ -981,7 +1037,7 @@ users:
}
`;

exports[`api shoots should return shoot seed info when no fallback is needed 1`] = `
exports[`api shoots should return shoot seed info when need to fallback to old monitoring secret 1`] = `
grolu marked this conversation as resolved.
Show resolved Hide resolved
Array [
Array [
Object {
Expand Down Expand Up @@ -1030,17 +1086,25 @@ Array [
":scheme": "https",
},
],
Array [
Object {
":authority": "api.foo-east.infra1.seed.cluster",
":method": "get",
":path": "/api/v1/namespaces/shoot--foo--barShoot/secrets/monitoring-ingress-credentials",
":scheme": "https",
},
],
]
`;

exports[`api shoots should return shoot seed info when no fallback is needed 2`] = `
exports[`api shoots should return shoot seed info when need to fallback to old monitoring secret 2`] = `
Object {
"monitoringPassword": "pass-shoot--foo--barShoot-bar.monitoring",
"monitoringUsername": "user-shoot--foo--barShoot-bar.monitoring",
"monitoringPassword": "pass-shoot--foo--barShoot-monitoring-ingress-credentials",
"monitoringUsername": "user-shoot--foo--barShoot-monitoring-ingress-credentials",
}
`;

exports[`api shoots should return shoot seed info when need to fallback to old monitoring secret 1`] = `
exports[`api shoots should return shoot seed info when no fallback is needed 1`] = `
Array [
Array [
Object {
Expand Down Expand Up @@ -1089,21 +1153,13 @@ Array [
":scheme": "https",
},
],
Array [
Object {
":authority": "api.foo-east.infra1.seed.cluster",
":method": "get",
":path": "/api/v1/namespaces/shoot--foo--barShoot/secrets/monitoring-ingress-credentials",
":scheme": "https",
},
],
]
`;

exports[`api shoots should return shoot seed info when need to fallback to old monitoring secret 2`] = `
exports[`api shoots should return shoot seed info when no fallback is needed 2`] = `
Object {
"monitoringPassword": "pass-shoot--foo--barShoot-monitoring-ingress-credentials",
"monitoringUsername": "user-shoot--foo--barShoot-monitoring-ingress-credentials",
"monitoringPassword": "pass-shoot--foo--barShoot-bar.monitoring",
"monitoringUsername": "user-shoot--foo--barShoot-bar.monitoring",
}
`;

Expand Down
18 changes: 18 additions & 0 deletions backend/test/acceptance/api.shoots.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,24 @@ describe('api', function () {
expect(res.body).toMatchSnapshot()
})

it('should replace shoot kubernetes enableStaticTokenKubeconfig', async function () {
mockRequest.mockImplementationOnce(fixtures.shoots.mocks.patch())

const res = await agent
.put(`/api/namespaces/${namespace}/shoots/${name}/spec/kubernetes/enableStaticTokenKubeconfig`)
.set('cookie', await user.cookie)
.send({
enableStaticTokenKubeconfig: true
})
.expect('content-type', /json/)
.expect(200)

expect(mockRequest).toBeCalledTimes(1)
expect(mockRequest.mock.calls).toMatchSnapshot()

expect(res.body).toMatchSnapshot()
})

it('should replace shoot maintenance data', async function () {
mockRequest.mockImplementationOnce(fixtures.shoots.mocks.patch())

Expand Down
18 changes: 14 additions & 4 deletions frontend/src/components/NewShoot/NewShootDetails.vue
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ SPDX-License-Identifier: Apache-2.0
></purpose>
</v-col>
</v-row>
<v-row>
<v-col cols="12">
<static-token-kubeconfig-switch v-model="enableStaticTokenKubeconfig"></static-token-kubeconfig-switch>
</v-col>
</v-row>
<v-row v-if="slaDescriptionHtml">
<v-col cols="12">
<label>{{slaTitle}}</label>
Expand All @@ -80,6 +85,7 @@ import asyncRef from '@/mixins/asyncRef'

import { getValidationErrors, transformHtml, setDelayedInputFocus } from '@/utils'
import { resourceName, noStartEndHyphen, noConsecutiveHyphen } from '@/utils/validators'
import StaticTokenKubeconfigSwitch from '@/components/StaticTokenKubeconfigSwitch'

const Purpose = () => import('@/components/Purpose')

Expand All @@ -101,7 +107,8 @@ export default {
name: 'new-shoot-details',
components: {
HintColorizer,
Purpose
Purpose,
StaticTokenKubeconfigSwitch
},
mixins: [
asyncRef('purpose')
Expand All @@ -122,7 +129,8 @@ export default {
purposeValid: false,
cloudProfileName: undefined,
secret: undefined,
updateK8sMaintenance: undefined
updateK8sMaintenance: undefined,
enableStaticTokenKubeconfig: undefined
}
},
validations () {
Expand Down Expand Up @@ -236,15 +244,17 @@ export default {
return {
name: this.name,
kubernetesVersion: this.kubernetesVersion,
purpose: this.purpose
purpose: this.purpose,
enableStaticTokenKubeconfig: this.enableStaticTokenKubeconfig
}
},
async setDetailsData ({ name, kubernetesVersion, purpose, cloudProfileName, secret, updateK8sMaintenance }) {
async setDetailsData ({ name, kubernetesVersion, purpose, cloudProfileName, secret, updateK8sMaintenance, enableStaticTokenKubeconfig }) {
this.name = name
this.cloudProfileName = cloudProfileName
this.secret = secret
this.kubernetesVersion = kubernetesVersion
this.updateK8sMaintenance = updateK8sMaintenance
this.enableStaticTokenKubeconfig = enableStaticTokenKubeconfig

await this.$purpose.dispatch('setPurpose', purpose)

Expand Down
31 changes: 19 additions & 12 deletions frontend/src/components/ShootDetails/ShootAccessCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ SPDX-License-Identifier: Apache-2.0
>
</terminal-list-tile>

<v-divider v-if="isTerminalTileVisible && (isTerminalShortcutsTileVisible || isDashboardTileVisible || isCredentialsTileVisible || isKubeconfigTileVisible || isGardenctlTileVisible)" inset></v-divider>
<v-divider v-if="isTerminalTileVisible" inset></v-divider>
grolu marked this conversation as resolved.
Show resolved Hide resolved

<terminal-shortcuts-tile
v-if="isTerminalShortcutsTileVisible"
Expand All @@ -37,7 +37,7 @@ SPDX-License-Identifier: Apache-2.0
class="mt-3"
></terminal-shortcuts-tile>

<v-divider v-if="isTerminalShortcutsTileVisible && (isDashboardTileVisible || isCredentialsTileVisible || isKubeconfigTileVisible || isGardenctlTileVisible)" inset></v-divider>
<v-divider v-if="isTerminalShortcutsTileVisible" inset></v-divider>

<link-list-tile v-if="isDashboardTileVisible && !hasDashboardTokenAuth" icon="mdi-developer-board" app-title="Dashboard" :url="dashboardUrl" :url-text="dashboardUrlText" :is-shoot-status-hibernated="isShootStatusHibernated"></link-list-tile>

Expand Down Expand Up @@ -88,20 +88,22 @@ SPDX-License-Identifier: Apache-2.0
</v-list-item>
</template>

<v-divider v-if="isDashboardTileVisible && (isCredentialsTileVisible || isKubeconfigTileVisible || isGardenctlTileVisible)" inset></v-divider>
<v-divider v-if="isDashboardTileVisible" inset></v-divider>

<username-password v-if="isCredentialsTileVisible" :username="username" :password="password"></username-password>

<v-divider v-if="isCredentialsTileVisible && (isKubeconfigTileVisible || isGardenctlTileVisible)" inset></v-divider>
<v-divider v-if="isCredentialsTileVisible" inset></v-divider>

<v-list-item v-if="isKubeconfigTileVisible">
<v-list-item>
<v-list-item-icon>
<v-icon color="primary">mdi-file</v-icon>
</v-list-item-icon>
<v-list-item-content>
<v-list-item-title>Kubeconfig</v-list-item-title>
<v-list-item-subtitle v-if="!shootEnableStaticTokenKubeconfig">Static token kubeconfig is disabled for this cluster</v-list-item-subtitle>
<v-list-item-subtitle v-else-if="!isKubeconfigAvailable">Static token kubeconfig currently not available</v-list-item-subtitle>
petersutter marked this conversation as resolved.
Show resolved Hide resolved
</v-list-item-content>
<v-list-item-action class="mx-0">
<v-list-item-action class="mx-0" v-if="isKubeconfigAvailable">
<v-tooltip top>
<template v-slot:activator="{ on }">
<v-btn v-on="on" icon @click.native.stop="onDownload" color="action-button">
Expand All @@ -111,10 +113,10 @@ SPDX-License-Identifier: Apache-2.0
<span>Download Kubeconfig</span>
</v-tooltip>
</v-list-item-action>
<v-list-item-action class="mx-0">
<v-list-item-action class="mx-0" v-if="isKubeconfigAvailable">
<copy-btn :clipboard-text="kubeconfig"></copy-btn>
</v-list-item-action>
<v-list-item-action class="mx-0">
<v-list-item-action class="mx-0" v-if="isKubeconfigAvailable">
<v-tooltip top>
<template v-slot:activator="{ on }">
<v-btn v-on="on" icon @click.native.stop="expansionPanelKubeconfig = !expansionPanelKubeconfig" color="action-button">
Expand All @@ -124,14 +126,17 @@ SPDX-License-Identifier: Apache-2.0
<span>{{kubeconfigVisibilityTitle}}</span>
</v-tooltip>
</v-list-item-action>
<v-list-item-action class="mx-0">
<static-token-kubeconfig-configuration :shootItem="shootItem"></static-token-kubeconfig-configuration>
</v-list-item-action>
</v-list-item>
<v-expand-transition>
<v-card v-if="expansionPanelKubeconfig" flat>
<code-block lang="yaml" :content="shootInfo.kubeconfig" :show-copy-button="false"></code-block>
</v-card>
</v-expand-transition>

<v-divider v-if="isKubeconfigTileVisible && isGardenctlTileVisible" inset></v-divider>
<v-divider v-if="isGardenctlTileVisible" inset></v-divider>

<gardenctl-commands v-if="isGardenctlTileVisible" :shoot-item="shootItem"></gardenctl-commands>
</v-list>
Expand All @@ -145,6 +150,7 @@ import TerminalListTile from '@/components/TerminalListTile'
import TerminalShortcutsTile from '@/components/ShootDetails/TerminalShortcutsTile'
import GardenctlCommands from '@/components/ShootDetails/GardenctlCommands'
import LinkListTile from '@/components/LinkListTile'
import StaticTokenKubeconfigConfiguration from '@/components/StaticTokenKubeconfigConfiguration'
import get from 'lodash/get'
import isEmpty from 'lodash/isEmpty'
import download from 'downloadjs'
Expand All @@ -159,7 +165,8 @@ export default {
TerminalListTile,
LinkListTile,
GardenctlCommands,
TerminalShortcutsTile
TerminalShortcutsTile,
StaticTokenKubeconfigConfiguration
},
props: {
hideTerminalShortcuts: {
Expand Down Expand Up @@ -242,15 +249,15 @@ export default {
return this.hasControlPlaneTerminalAccess ? 'Open terminal into cluster or cluster\'s control plane' : 'Open terminal into cluster'
},
isAnyTileVisible () {
return this.isDashboardTileVisible || this.isCredentialsTileVisible || this.isKubeconfigTileVisible || this.isTerminalTileVisible
return this.isDashboardTileVisible || this.isCredentialsTileVisible || this.isTerminalTileVisible
},
isDashboardTileVisible () {
return !!this.dashboardUrl
},
isCredentialsTileVisible () {
return !!this.username && !!this.password
},
isKubeconfigTileVisible () {
isKubeconfigAvailable () {
return !!this.kubeconfig
},
isGardenctlTileVisible () {
Expand Down
Loading