Skip to content

Commit

Permalink
Remove "Check Connection" button on the ClusterAdd page.
Browse files Browse the repository at this point in the history
Add connection checking on clusters adding. (CusterAdd page)
  • Loading branch information
proAlexandr committed Jul 6, 2019
1 parent f29d693 commit 67d2733
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 34 deletions.
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ module.exports = {
'generator-star-spacing': 0,
// allow debugger during development
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
'max-len': [2, 120],

'space-before-function-paren': [2, {
"anonymous": "never",
Expand Down
63 changes: 38 additions & 25 deletions src/renderer/components/ClusterAdd.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,15 @@
<span v-else>We have detected existing <b>~/.kube/config</b> file with the following clusters:</span>
<div class="clusters-add__contexts">
<div v-for="context in contexts" :key="context.name" class="clusters-add__context">
<BaseCheckbox v-model="checkedContexts[context.name]">
<BaseCheckbox v-model="checkedContextsIndex[context.name]">
<b>{{ context.cluster }}</b>
<span v-if="nonUniqClusters[context.cluster]">(user: <b>{{ context.user }}</b>)</span>
</BaseCheckbox>
<Button layout="outline"
theme="primary"
size="s"
:loading="checkingConnection === context.name"
:disabled="checkingConnection && checkingConnection !== context.name"
@click="handleCheckConnection(context.name)"
>
Check connection
</Button>
</div>
</div>

<div class="clusters-add__actions">
<Button layout="filled" theme="primary" :disabled="!isAnySelected" @click="saveSelected">
<Button layout="filled" theme="primary" :disabled="!isAnySelected" :loading="saving" @click="handleSave">
ADD SELECTED CLUSTERS
</Button>
</div>
Expand Down Expand Up @@ -65,6 +56,7 @@ import Header from './shared/Header'
import Button from './shared/Button'
import BaseCheckbox from './shared/form/BaseCheckbox'
import { checkConnection } from '../lib/helpers/cluster'
import { showConfirmBox } from '../lib/helpers/ui'
const { app } = remote
Expand All @@ -77,16 +69,16 @@ export default {
data() {
return {
contexts: [],
checkedContexts: {},
checkingConnection: false
checkedContextsIndex: {},
saving: false
}
},
computed: {
backPath() {
return '/'
},
isAnySelected() {
return Boolean(Object.values(this.checkedContexts).find(x => x))
return this.selectedContexts.length > 0
},
// returns the index of context.names whos clusters occur al least twice.
nonUniqClusters() {
Expand All @@ -104,6 +96,9 @@ export default {
},
manualConfig() {
return this.$store.state.manualClusterConfig
},
selectedContexts() {
return this.contexts.filter(context => this.checkedContextsIndex[context.name])
}
},
async mounted() {
Expand All @@ -122,7 +117,7 @@ export default {
this.configObject = configObject
this.contexts = kubeConfig.contexts
for (const context of this.contexts) {
Vue.set(this.checkedContexts, context.name, false)
Vue.set(this.checkedContextsIndex, context.name, false)
}
},
methods: {
Expand All @@ -133,23 +128,41 @@ export default {
const kubeConfigDefaultPath = path.join(app.getPath('home'), '.kube/config')
return fs.readFile(kubeConfigDefaultPath, { encoding: 'utf8' }).catch(() => '')
},
saveSelected() {
for (const context of this.contexts) {
if (!this.checkedContexts[context.name]) continue
async handleSave() {
if (!this.kubeConfig) return
if (this.saving) return
this.saving = true
const connectionResult = await this.checkConnectionToContexts(this.selectedContexts)
const continueSaving = connectionResult.success || await this.confirmInvalidConnection(connectionResult.errors)
if (continueSaving) {
this.saveSelected()
this.$router.push('/')
}
this.saving = false
},
saveSelected() {
for (const context of this.selectedContexts) {
this.configObject['current-context'] = context.name
const name = this.nonUniqClusters[context.cluster] ? `${context.cluster}${context.user}` : context.cluster
this.createCluster({ name, config: yaml.safeDump(this.configObject) })
}
this.$router.push('/')
},
async handleCheckConnection(contextName) {
if (!this.checkingConnection && this.kubeConfig && typeof this.kubeConfig.makeApiClient === 'function') {
this.checkingConnection = contextName
await checkConnection(this.kubeConfig, contextName)
this.checkingConnection = false
async checkConnectionToContexts(contexts) {
const errors = []
for (const context of contexts) {
const error = await checkConnection(this.kubeConfig, context.name)
if (error) errors.push({ error, contextName: context.name })
}
return { success: errors.length === 0, errors }
},
async confirmInvalidConnection(errors) {
const contextNames = errors.map(x => x.contextName).join(', ')
return showConfirmBox(`Failed to connect to ${contextNames} cluster(s). Do you want to continue saving?`)
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/components/Clusters/ClusterItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
</template>

<div v-else class="cluster-item__empty">
<Button theme="primary" :to="createServicePath">Add a service</Button>
<Button theme="primary" :to="createServicePath">Add a resource</Button>
</div>
</div>
</div>
Expand Down
11 changes: 10 additions & 1 deletion src/renderer/components/shared/cluster/ClusterForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,16 @@ export default {
}
this.checkingConnection = true
await checkConnection(kubeConfig)
const error = await checkConnection(kubeConfig)
if (error) {
await showMessageBox('Connection failed', {
details: `${error.message}${error.details ? `\n${error.details}` : ''}`
})
} else {
await showMessageBox('Connection successful')
}
this.checkingConnection = false
}
}
Expand Down
10 changes: 4 additions & 6 deletions src/renderer/lib/helpers/cluster.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { Core_v1Api } from '@kubernetes/client-node' // eslint-disable-line camelcase

import { showMessageBox } from './ui'
import { k8nApiPrettyError } from './k8n-api-error'

export async function checkConnection(kubeConfig, context = null) {
if (!kubeConfig || typeof kubeConfig.makeApiClient !== 'function') return

let error = null
const currentContext = kubeConfig.getCurrentContext()

if (context) {
Expand All @@ -15,13 +15,11 @@ export async function checkConnection(kubeConfig, context = null) {
try {
const api = kubeConfig.makeApiClient(Core_v1Api)
await api.listNode()
await showMessageBox('Connection successful')
} catch (e) {
const error = k8nApiPrettyError(e)
await showMessageBox('Connection failed', {
details: `${error.message}${error.details ? `\n${error.details}` : ''}`
})
error = k8nApiPrettyError(e)
}

kubeConfig.setCurrentContext(currentContext)

return error
}
2 changes: 1 addition & 1 deletion src/renderer/lib/helpers/ui.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const { dialog, app } = require('electron').remote
export function showMessageBox(message, options = {}) {
const { details } = options
const detailsLabel = 'Details'
const buttons = ['OK']
const buttons = options.buttons ? options.buttons.slice(0) : ['OK']
if (details) buttons.push(detailsLabel)

return new Promise((resolve) => {
Expand Down

0 comments on commit 67d2733

Please sign in to comment.