Skip to content

Commit

Permalink
* Fix connection to gcloud
Browse files Browse the repository at this point in the history
* Better error messages if gcloud or aws cli doesn't found
* "Not found" message for Autocomplete select
* Fix bugs with long option names in the Select
  • Loading branch information
proAlexandr committed Jul 22, 2019
1 parent 7ecd040 commit 2a6745f
Show file tree
Hide file tree
Showing 8 changed files with 53 additions and 17 deletions.
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,13 @@ Use import and export functionality to share bookmarked services with your team

Use port-forwarding without installing kubectl and avoid explanations to developers on how to use it

## Functionality walkthrough
## Optional dependencies

* [Google Cloud SDK](https://cloud.google.com/sdk/)
* [AWS CLI](https://docs.aws.amazon.com/cli/)

## Functionality walk-through

### Add a cluster(s)

Before you start forwarding interal resources to your local machine, you have to add cluster configuration. To do this we have 3 different options in the app:
Expand Down
22 changes: 20 additions & 2 deletions src/renderer/components/ClusterAdd.vue
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,26 @@ export default {
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?`)
const messages = errors.map(this.getConnectionErrorMessage)
const message = messages.concat(['Do you want to continue saving?']).join('\n\n')
return showConfirmBox(message)
},
getConnectionErrorMessage({ error, contextName }) {
const awsNotFoundMatch = error.details.match(/\s(aws: command not found)/)
if (awsNotFoundMatch) {
return `Failed to connect to ${contextName}: ${awsNotFoundMatch[1]}. ` +
'Please make sure you have installed AWS CLI. (https://docs.aws.amazon.com/cli/)'
}
const gcloudNotFoundMatch = error.details.match(/\W(gcloud: No such file or directory)/)
if (gcloudNotFoundMatch) {
return `Failed to connect to ${contextName}: ${gcloudNotFoundMatch[1]}. ` +
'Please make sure you have installed Google Cloud SDK. (https://cloud.google.com/sdk)'
}
console.error(error.parentError)
return `Failed to connect to ${contextName}: ${error.details}`
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion src/renderer/components/shared/Popup.vue
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export default {
}
</script>

<style scoped lang="scss">
<style lang="scss">
@import "../../assets/styles/variables";
.popup {
Expand Down Expand Up @@ -87,6 +87,8 @@ export default {
line-height: 36px;
display: block;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
transition: background-color $hover-transition-speed;
Expand Down
23 changes: 19 additions & 4 deletions src/renderer/components/shared/form/AutocompleteInput.vue
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
<template>
<div class="autocomplete-input">
<BaseInput v-bind="$attrs" :value="value" v-on="listeners" />
<Popup v-if="(matchedOptions.length || loading) && focused" :position="'bottom'" :align="'both'">
<div v-if="loading" class="autocomplete-input__loader-container">
<Popup v-if="focused" :position="'bottom'" :align="'both'">
<div v-if="loading" class="autocomplete-input__content">
<Loader size="s" />
</div>

<div v-else-if="matchedOptions.length === 0" class="autocomplete-input__content">
{{ notFoundMessage }}
</div>

<ul v-else class="popup__actions">
<li v-for="option in matchedOptions" :key="option">
<Action @mousedown="handleOptionClick(option)">{{ option }}</Action>
Expand All @@ -27,7 +31,8 @@ export default {
props: {
loading: { type: Boolean, default: false },
options: { type: Array, default: () => [] },
value: BaseInput.props.value // eslint-disable-line vue/require-default-prop
value: BaseInput.props.value, // eslint-disable-line vue/require-default-prop
notFoundMessage: { type: String, default: 'Not found' }
},
data() {
return {
Expand Down Expand Up @@ -65,6 +70,8 @@ export default {
</script>

<style lang="scss">
@import "../../../assets/styles/variables";
.autocomplete-input {
position: relative;
Expand All @@ -78,7 +85,15 @@ export default {
}
}
.autocomplete-input__loader-container {
.autocomplete-input__content {
height: 40px;
display: flex;
align-items: center;
justify-content: center;
color: $color-text-secondary;
.loader {
position: static;
}
}
</style>
1 change: 1 addition & 0 deletions src/renderer/components/shared/form/BaseSelect.vue
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ export default {
.base-select {
.base-input {
width: 100%;
padding-right: 40px;
}
&.dropdown_opened {
Expand Down
10 changes: 1 addition & 9 deletions src/renderer/lib/helpers/cluster.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { CoreV1Api, KubeConfig } from '@kubernetes/client-node'

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

export async function checkConnection(kubeConfig, context = null) {
if (!kubeConfig || typeof kubeConfig.makeApiClient !== 'function') return
Expand All @@ -17,14 +16,7 @@ export async function checkConnection(kubeConfig, context = null) {
const api = kubeConfig.makeApiClient(CoreV1Api)
await api.listNode()
} catch (e) {
const commandNotFoundMatch = e.message.match(/\s([a-zA-Z0-9]+: command not found)/)

if (commandNotFoundMatch) {
await showMessageBox(`${commandNotFoundMatch[1]}.`)
error = e
} else {
error = k8nApiPrettyError(e)
}
error = k8nApiPrettyError(e)
}

kubeConfig.setCurrentContext(currentContext)
Expand Down
1 change: 1 addition & 0 deletions src/renderer/lib/helpers/k8n-api-error.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export function k8nApiPrettyError(error, messages = {}) {
const messageKey = getMessageKey(error)
const prettyError = new Error(buildMessage(error, messages, messageKey))

prettyError.parentError = error
prettyError.details = error.message

if (error.response || error.code) {
Expand Down
1 change: 1 addition & 0 deletions src/renderer/lib/k8s-shelljs-replace-patch.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { execSync } from 'child_process'
import * as jsonpath from 'jsonpath-plus'

import { ExecAuth } from '@kubernetes/client-node/dist/exec_auth'
import { CloudAuth } from '@kubernetes/client-node/dist/cloud_auth'
Expand Down

0 comments on commit 2a6745f

Please sign in to comment.