mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
cleaning-up renderer/_vue, moi-moi vue.js
Signed-off-by: Roman <ixrock@gmail.com>
This commit is contained in:
parent
ec095cac8e
commit
cf5b3b4ea6
@ -1,141 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="settings-section">
|
|
||||||
<b>Metrics</b>
|
|
||||||
<p class="description">
|
|
||||||
Enable timeseries data visualization (Prometheus stack) for your cluster. Install this only if you don't have existing Prometheus stack installed. You can see preview of manifests <a href="https://github.com/lensapp/lens/tree/master/src/features/metrics">here</a>.
|
|
||||||
</p>
|
|
||||||
<div class="actions">
|
|
||||||
<b-button @click="install" v-if="!settings.installed" :disabled="!cluster.isAdmin || isProcessing || !canInstall" variant="primary">
|
|
||||||
<b-spinner small v-if="isProcessing" label="Small Spinner" />
|
|
||||||
Install
|
|
||||||
</b-button>
|
|
||||||
<b-button @click="upgrade" v-if="isUpgradeAvailable" :disabled="!cluster.isAdmin || isProcessing || isUpgrading" variant="primary">
|
|
||||||
<b-spinner small v-if="isUpgrading" label="Small Spinner" />
|
|
||||||
Upgrade
|
|
||||||
</b-button>
|
|
||||||
<b-button @click="uninstall" v-if="settings.installed" :disabled="!cluster.isAdmin || isProcessing || isUpgrading" variant="danger">
|
|
||||||
<b-spinner small v-if="isProcessing" label="Small Spinner" />
|
|
||||||
Uninstall
|
|
||||||
</b-button>
|
|
||||||
<b-alert show variant="danger" v-if="status === 'ERROR'">
|
|
||||||
{{ errorMsg }}
|
|
||||||
</b-alert>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
const semver = require('semver');
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'Metrics',
|
|
||||||
components: {},
|
|
||||||
props: {
|
|
||||||
cluster: {
|
|
||||||
type: Object,
|
|
||||||
required: true,
|
|
||||||
default: null
|
|
||||||
},
|
|
||||||
feature: {
|
|
||||||
type: String,
|
|
||||||
required: true,
|
|
||||||
default: null
|
|
||||||
},
|
|
||||||
settings: {
|
|
||||||
type: Object,
|
|
||||||
required: false,
|
|
||||||
default: Object
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data(){
|
|
||||||
return {
|
|
||||||
status: "",
|
|
||||||
errorMsg: "",
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed:{
|
|
||||||
isUpgradeAvailable: function() {
|
|
||||||
return this.cluster.features.metrics.canUpgrade;
|
|
||||||
},
|
|
||||||
isProcessing: function() {
|
|
||||||
return this.status === "PROCESSING";
|
|
||||||
},
|
|
||||||
isUpgrading: function() {
|
|
||||||
return this.status === "UPGRADING";
|
|
||||||
},
|
|
||||||
canInstall: function() {
|
|
||||||
return !this.cluster.preferences.prometheus
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
install: async function(){
|
|
||||||
this.status="PROCESSING";
|
|
||||||
let error = null;
|
|
||||||
let result = await this.$store.dispatch("installClusterFeature", {
|
|
||||||
name: this.feature,
|
|
||||||
clusterId: this.cluster.id,
|
|
||||||
config: null,
|
|
||||||
}).catch(e => {
|
|
||||||
error = e;
|
|
||||||
return false; // just returning false to promise
|
|
||||||
})
|
|
||||||
|
|
||||||
// handle exceptions here; but oh why, why do we have to???
|
|
||||||
if(error){
|
|
||||||
this.status = "ERROR";
|
|
||||||
this.errorMsg = error;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// now let's look at result...
|
|
||||||
if(result.success === false) {
|
|
||||||
this.status = "ERROR"
|
|
||||||
this.errorMsg = result.message
|
|
||||||
} else {
|
|
||||||
this.$store.dispatch("refineCluster", this.cluster.id);
|
|
||||||
this.status = "";
|
|
||||||
this.errorMsg = "";
|
|
||||||
}
|
|
||||||
},
|
|
||||||
uninstall: async function(){
|
|
||||||
this.status = "PROCESSING";
|
|
||||||
let error = null;
|
|
||||||
try {
|
|
||||||
let result = await this.$store.dispatch("uninstallClusterFeature", {
|
|
||||||
name: this.feature,
|
|
||||||
clusterId: this.cluster.id,
|
|
||||||
})
|
|
||||||
console.log("uninstall result:", result);
|
|
||||||
this.$store.dispatch("refineCluster", this.cluster.id);
|
|
||||||
this.status = "SUCCESS";
|
|
||||||
this.errorMsg = "";
|
|
||||||
} catch(error) {
|
|
||||||
this.status = "ERROR"
|
|
||||||
this.errorMsg = error
|
|
||||||
console.log("Error uninstalling:", error);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
upgrade: async function(){
|
|
||||||
this.status = "UPGRADING";
|
|
||||||
try {
|
|
||||||
let result = await this.$store.dispatch("upgradeClusterFeature", {
|
|
||||||
name: this.feature,
|
|
||||||
clusterId: this.cluster.id,
|
|
||||||
config: null,
|
|
||||||
})
|
|
||||||
this.$store.dispatch("refineCluster", this.cluster.id);
|
|
||||||
this.status = "";
|
|
||||||
this.errorMsg = "";
|
|
||||||
} catch(error) {
|
|
||||||
this.status = "ERROR"
|
|
||||||
this.errorMsg = error.message
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<style scoped lang="scss">
|
|
||||||
</style>
|
|
||||||
@ -1,128 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="settings-section">
|
|
||||||
<b>User Mode</b>
|
|
||||||
<p class="description">
|
|
||||||
User Mode feature enables non-admin users to see namespaces they have access to. This is achieved by configuring RBAC rules so that every authenticated user is granted to list namespaces.
|
|
||||||
</p>
|
|
||||||
<div class="actions">
|
|
||||||
<b-button @click="install" v-if="!settings.installed" :disabled="!cluster.isAdmin || isProcessing" variant="primary">
|
|
||||||
<b-spinner small v-if="isProcessing" label="Small Spinner" />
|
|
||||||
Install
|
|
||||||
</b-button>
|
|
||||||
<b-button @click="uninstall" v-if="settings.installed" :disabled="!cluster.isAdmin || isProcessing" variant="danger">
|
|
||||||
<b-spinner small v-if="isProcessing" label="Small Spinner" />
|
|
||||||
Uninstall
|
|
||||||
</b-button>
|
|
||||||
<b-button @click="upgrade" v-if="isUpgradeAvailable" :disabled="!cluster.isAdmin" variant="primary">
|
|
||||||
Upgrade
|
|
||||||
</b-button>
|
|
||||||
<b-alert show variant="danger" v-if="status === 'ERROR'">
|
|
||||||
{{ errorMsg }}
|
|
||||||
</b-alert>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
const semver = require('semver');
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'UserMode',
|
|
||||||
components: {},
|
|
||||||
props: {
|
|
||||||
cluster: {
|
|
||||||
type: Object,
|
|
||||||
required: true,
|
|
||||||
default: null
|
|
||||||
},
|
|
||||||
feature: {
|
|
||||||
type: String,
|
|
||||||
required: true,
|
|
||||||
default: null
|
|
||||||
},
|
|
||||||
settings: {
|
|
||||||
type: Object,
|
|
||||||
required: false,
|
|
||||||
default: Object
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data(){
|
|
||||||
return {
|
|
||||||
status: "",
|
|
||||||
errorMsg: "",
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed:{
|
|
||||||
isProcessing: function() {
|
|
||||||
return this.status === "PROCESSING";
|
|
||||||
},
|
|
||||||
isUpgradeAvailable: function() {
|
|
||||||
if(!this.settings.installed) return false;
|
|
||||||
if(!this.settings.currentVersion) return false;
|
|
||||||
if(!this.settings.latestVersion) return false;
|
|
||||||
let currentVersion = (this.settings.currentVersion.charAt(0) === "v") ? this.settings.currentVersion.substr(1) : this.settings.currentVersion;
|
|
||||||
let latestVersion = (this.settings.latestVersion.charAt(0) === "v") ? this.settings.latestVersion.substr(1) : this.settings.latestVersion;
|
|
||||||
return semver.gt(latestVersion, currentVersion)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
install: async function(){
|
|
||||||
this.status="PROCESSING";
|
|
||||||
let error = null;
|
|
||||||
let result = await this.$store.dispatch("installClusterFeature", {
|
|
||||||
name: this.feature,
|
|
||||||
clusterId: this.cluster.id,
|
|
||||||
config: null,
|
|
||||||
}).catch(e => {
|
|
||||||
error = e;
|
|
||||||
return false; // just returning false to promise
|
|
||||||
})
|
|
||||||
|
|
||||||
// handle exceptions here; but oh why, why do we have to???
|
|
||||||
if(error){
|
|
||||||
this.status = "ERROR";
|
|
||||||
this.errorMsg = error;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// now let's look at result...
|
|
||||||
if(result.success === false) {
|
|
||||||
this.status = "ERROR"
|
|
||||||
this.errorMsg = result.message
|
|
||||||
} else {
|
|
||||||
this.$store.dispatch("refineCluster", this.cluster.id);
|
|
||||||
this.status = "";
|
|
||||||
this.errorMsg = "";
|
|
||||||
}
|
|
||||||
},
|
|
||||||
uninstall: async function(){
|
|
||||||
this.status="PROCESSING";
|
|
||||||
let error = null;
|
|
||||||
try {
|
|
||||||
let result = await this.$store.dispatch("uninstallClusterFeature", {
|
|
||||||
name: this.feature,
|
|
||||||
clusterId: this.cluster.id,
|
|
||||||
})
|
|
||||||
console.log("uninstall result:", result);
|
|
||||||
this.$store.dispatch("refineCluster", this.cluster.id);
|
|
||||||
this.status="SUCCESS";
|
|
||||||
this.errorMsg = "";
|
|
||||||
} catch(error) {
|
|
||||||
this.status = "ERROR"
|
|
||||||
this.errorMsg = error
|
|
||||||
console.log("Error uninstalling:", error);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
|
|
||||||
},
|
|
||||||
upgrade: async function(){
|
|
||||||
// todo
|
|
||||||
return true;
|
|
||||||
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<style scoped lang="scss">
|
|
||||||
</style>
|
|
||||||
@ -1,7 +0,0 @@
|
|||||||
import Metrics from './Metrics'
|
|
||||||
import UserMode from './UserMode'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
Metrics,
|
|
||||||
UserMode
|
|
||||||
}
|
|
||||||
@ -1,51 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="cluster-features" class="row">
|
|
||||||
<div class="col-12">
|
|
||||||
<h2>Features</h2>
|
|
||||||
<component
|
|
||||||
v-for="featureName in features"
|
|
||||||
:key="featureName"
|
|
||||||
:is="featureName"
|
|
||||||
:cluster="cluster"
|
|
||||||
:feature="featureName"
|
|
||||||
:settings="feature(featureName)"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
// register all sub components
|
|
||||||
import components from './Components'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'ClusterFeatures',
|
|
||||||
components: components,
|
|
||||||
props: {
|
|
||||||
cluster: {
|
|
||||||
type: Object,
|
|
||||||
default: null,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data(){
|
|
||||||
return {
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed:{
|
|
||||||
features: function() {
|
|
||||||
if (!this.cluster) return []
|
|
||||||
if (!this.cluster.features) return []
|
|
||||||
|
|
||||||
return Object.keys(this.cluster.features)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
feature: function( name ){ return this.cluster.features[name] }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<style scoped lang="scss">
|
|
||||||
h2{
|
|
||||||
margin-top: 20px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@ -1,148 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="settings-section">
|
|
||||||
<b>Cluster Icon</b>
|
|
||||||
<p>
|
|
||||||
Define cluster icon. By default automatically generated.
|
|
||||||
</p>
|
|
||||||
<div class="row">
|
|
||||||
<span class="cluster-settings-icon">
|
|
||||||
<img v-if="preferences.icon" :src="preferences.icon" class="cluster-icon">
|
|
||||||
<hashicon v-else :name="cluster.preferences.clusterName" size="38" />
|
|
||||||
</span>
|
|
||||||
<div class="col">
|
|
||||||
<b-form-file
|
|
||||||
ref="fileUpload"
|
|
||||||
v-model="file"
|
|
||||||
accept="image/jpeg, image/png, image/gif"
|
|
||||||
:state="Boolean(file)"
|
|
||||||
placeholder="Browse for new icon..."
|
|
||||||
drop-placeholder="Drop file here..."
|
|
||||||
browse-text=""
|
|
||||||
@input="upload"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="mt-3">
|
|
||||||
<a href="#" @click.prevent="reset" v-if="preferences.icon" class="text-muted">
|
|
||||||
Use automatically generated icon
|
|
||||||
</a>
|
|
||||||
<b-alert show variant="danger" v-if="status === 'ERROR'">
|
|
||||||
{{ errorMsg }}
|
|
||||||
</b-alert>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import hashicon from "../../hashicon/hashicon";
|
|
||||||
export default {
|
|
||||||
name: 'ClusterIcon',
|
|
||||||
components: {
|
|
||||||
hashicon
|
|
||||||
},
|
|
||||||
props: {
|
|
||||||
cluster: {
|
|
||||||
type: Object,
|
|
||||||
required: true,
|
|
||||||
default: null
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data(){
|
|
||||||
return {
|
|
||||||
status: "",
|
|
||||||
errorMsg: "",
|
|
||||||
file: null,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed:{
|
|
||||||
preferences: function() {
|
|
||||||
return this.cluster.preferences;
|
|
||||||
},
|
|
||||||
isProcessing: function() {
|
|
||||||
return this.status === "PROCESSING";
|
|
||||||
},
|
|
||||||
isResetProcessing: function() {
|
|
||||||
return this.resetStatus === "PROCESSING";
|
|
||||||
},
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
reset: async function(){
|
|
||||||
this.resetStatus = "PROCESSING";
|
|
||||||
let error = null;
|
|
||||||
|
|
||||||
let result = await this.$store.dispatch("resetClusterIcon", {
|
|
||||||
clusterId: this.cluster.id
|
|
||||||
}).catch(e => {
|
|
||||||
error = e;
|
|
||||||
return false; // just returning false to promise
|
|
||||||
})
|
|
||||||
|
|
||||||
// handle exceptions here; but oh why, why do we have to???
|
|
||||||
if(error){
|
|
||||||
this.resetStatus = "ERROR";
|
|
||||||
this.errorMsg = error;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// now let's look at result...
|
|
||||||
if(result.success === false) {
|
|
||||||
this.resetStatus = "ERROR"
|
|
||||||
this.errorMsg = result.message
|
|
||||||
} else {
|
|
||||||
this.resetStatus = "";
|
|
||||||
this.errorMsg = "";
|
|
||||||
}
|
|
||||||
},
|
|
||||||
upload: async function(file){
|
|
||||||
if(!file) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.status="PROCESSING";
|
|
||||||
let error = null;
|
|
||||||
|
|
||||||
let result = await this.$store.dispatch("uploadClusterIcon", {
|
|
||||||
clusterId: this.cluster.id,
|
|
||||||
name: file.name,
|
|
||||||
path: file.path
|
|
||||||
}).catch(e => {
|
|
||||||
error = e;
|
|
||||||
return false; // just returning false to promise
|
|
||||||
})
|
|
||||||
// handle exceptions here; but oh why, why do we have to???
|
|
||||||
if(error){
|
|
||||||
this.status = "ERROR";
|
|
||||||
this.errorMsg = error;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// now let's look at result...
|
|
||||||
if(result.success === false) {
|
|
||||||
this.status = "ERROR"
|
|
||||||
this.errorMsg = result.message
|
|
||||||
} else {
|
|
||||||
this.status = "";
|
|
||||||
this.errorMsg = "";
|
|
||||||
this.file = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
},
|
|
||||||
mounted: function(){
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<style scoped lang="scss">
|
|
||||||
.description{
|
|
||||||
padding: 0.75rem;
|
|
||||||
}
|
|
||||||
.actions{
|
|
||||||
border-top: 1px solid rgba(255,255,255,0.10);
|
|
||||||
padding: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cluster-settings-icon {
|
|
||||||
background: #252729;
|
|
||||||
margin-left: 15px;
|
|
||||||
padding: 5px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@ -1,49 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="settings-section">
|
|
||||||
<b>Cluster Name</b>
|
|
||||||
<p>
|
|
||||||
Define cluster name.
|
|
||||||
</p>
|
|
||||||
<b-form-input v-model="cluster.preferences.clusterName"
|
|
||||||
:placeholder="cluster.preferences.clusterName"
|
|
||||||
:state="errors.name"
|
|
||||||
trim
|
|
||||||
@blur="onSave"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: 'ClusterName',
|
|
||||||
props: {
|
|
||||||
cluster: {
|
|
||||||
type: Object,
|
|
||||||
required: true,
|
|
||||||
default: null
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data(){
|
|
||||||
return {
|
|
||||||
errors: {
|
|
||||||
name: null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
onSave: function() {
|
|
||||||
if(this.cluster.preferences.clusterName === "") {
|
|
||||||
this.errors.name = false
|
|
||||||
return
|
|
||||||
} else {
|
|
||||||
this.errors.name = true
|
|
||||||
}
|
|
||||||
this.$store.dispatch("storeCluster", this.cluster);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
|
|
||||||
</style>
|
|
||||||
@ -1,52 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="settings-section">
|
|
||||||
<b>Cluster Workspace</b>
|
|
||||||
<p>
|
|
||||||
Define cluster <a href="/#/workspaces">workspace</a>.
|
|
||||||
</p>
|
|
||||||
<b-form-select
|
|
||||||
v-model="cluster.workspace"
|
|
||||||
:options="workspaces"
|
|
||||||
@change="onSave"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: 'ClusterWorkspace',
|
|
||||||
props: {
|
|
||||||
cluster: {
|
|
||||||
type: Object,
|
|
||||||
required: true,
|
|
||||||
default: null
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
workspaces: function() {
|
|
||||||
return this.$store.getters.workspaces.map((ws) => {
|
|
||||||
return {
|
|
||||||
value: ws.id,
|
|
||||||
text: ws.name
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
onSave: async function(workspaceId) {
|
|
||||||
this.cluster.workspace = workspaceId
|
|
||||||
await this.$store.dispatch("storeCluster", this.cluster);
|
|
||||||
const ws = this.$store.getters.workspaceById(this.cluster.workspace);
|
|
||||||
if (ws) {
|
|
||||||
this.$store.commit("setCurrentWorkspace", ws);
|
|
||||||
await this.$store.dispatch("clearClusters");
|
|
||||||
await this.$store.dispatch("refreshClusters", ws);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
|
|
||||||
</style>
|
|
||||||
@ -1,35 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="cluster-general" class="row">
|
|
||||||
<div class="col-12">
|
|
||||||
<h2>General</h2>
|
|
||||||
<cluster-name :cluster="cluster" />
|
|
||||||
<cluster-workspace :cluster="cluster" />
|
|
||||||
<cluster-icon :cluster="cluster" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import ClusterIcon from "./ClusterIcon";
|
|
||||||
import ClusterName from "./ClusterName"
|
|
||||||
import ClusterWorkspace from "./ClusterWorkspace"
|
|
||||||
export default {
|
|
||||||
name: "ClusterSettingsGeneral",
|
|
||||||
props: {
|
|
||||||
cluster: {
|
|
||||||
type: Object,
|
|
||||||
required: true,
|
|
||||||
default: null
|
|
||||||
}
|
|
||||||
},
|
|
||||||
components: {
|
|
||||||
ClusterIcon,
|
|
||||||
ClusterName,
|
|
||||||
ClusterWorkspace
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
|
|
||||||
</style>
|
|
||||||
@ -1,69 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="cluster-status" class="cluster-settings-overview row">
|
|
||||||
<div class="col-12">
|
|
||||||
<h2>Status</h2>
|
|
||||||
<div class="settings-section">
|
|
||||||
<b>Cluster Status</b>
|
|
||||||
<p>
|
|
||||||
Cluster status information including detected distribution, kernel version and online status
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<table class="table">
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">
|
|
||||||
Online Status
|
|
||||||
</th>
|
|
||||||
<td>{{ cluster.online ? "online" : "offline (" + (cluster.failureReason || "unknown reason") + ")" }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">
|
|
||||||
Distribution
|
|
||||||
</th>
|
|
||||||
<td>{{ cluster.distribution }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">
|
|
||||||
Kernel Version
|
|
||||||
</th>
|
|
||||||
<td>{{ cluster.version }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">
|
|
||||||
API Address
|
|
||||||
</th>
|
|
||||||
<td>{{ cluster.apiUrl }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr v-if="cluster.nodes">
|
|
||||||
<th scope="row">
|
|
||||||
Nodes Count
|
|
||||||
</th>
|
|
||||||
<td>{{ cluster.nodes }}</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: 'ClusterSettingsOverview',
|
|
||||||
props: {
|
|
||||||
cluster: {
|
|
||||||
type: Object,
|
|
||||||
default: null,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data(){
|
|
||||||
return {
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
</style>
|
|
||||||
@ -1,196 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-12">
|
|
||||||
<div class="cluster-settings-section">
|
|
||||||
<b>HTTP Proxy</b>
|
|
||||||
|
|
||||||
<b-form-group
|
|
||||||
label="HTTP Proxy server. Used for communicating with Kubernetes API."
|
|
||||||
description="A HTTP proxy server URL (format: http://<address>:<port>)."
|
|
||||||
>
|
|
||||||
<b-form-input
|
|
||||||
v-model="cluster.preferences.httpsProxy"
|
|
||||||
id="input-httpsproxy"
|
|
||||||
@blur="onHttpsProxySave"
|
|
||||||
/>
|
|
||||||
</b-form-group>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-12">
|
|
||||||
<div class="cluster-settings-section">
|
|
||||||
<b>Prometheus</b>
|
|
||||||
<p>Use pre-installed Prometheus service for metrics. Please refer to the <a href="https://github.com/lensapp/lens/blob/master/troubleshooting/custom-prometheus.md">guide</a> for possible configuration changes.</p>
|
|
||||||
|
|
||||||
<b-form-group
|
|
||||||
label="Prometheus installation method."
|
|
||||||
description="What query format is used to fetch metrics from Prometheus"
|
|
||||||
>
|
|
||||||
<b-form-select
|
|
||||||
v-model="prometheusProvider"
|
|
||||||
:options="prometheusProviders"
|
|
||||||
@change="onPrometheusProviderSave"
|
|
||||||
/>
|
|
||||||
</b-form-group>
|
|
||||||
<b-form-group
|
|
||||||
label="Prometheus service address."
|
|
||||||
description="An address to an existing Prometheus installation (<namespace>/<service>:<port>). Lens tries to auto-detect address if left empty."
|
|
||||||
v-if="canEditPrometheusPath"
|
|
||||||
>
|
|
||||||
<b-form-input
|
|
||||||
v-model="prometheusPath"
|
|
||||||
placeholder="<namespace>/<service>:<port>"
|
|
||||||
id="input-prometheuspath"
|
|
||||||
@blur="onPrometheusSave"
|
|
||||||
:state="errors.prometheusPath"
|
|
||||||
/>
|
|
||||||
</b-form-group>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-12">
|
|
||||||
<div class="cluster-settings-section">
|
|
||||||
<b>Working Directory</b>
|
|
||||||
|
|
||||||
<b-form-group
|
|
||||||
label="Terminal working directory."
|
|
||||||
description="An explicit start path where the terminal will be launched, this is used as the current working directory (cwd) for the shell process."
|
|
||||||
>
|
|
||||||
<b-form-input
|
|
||||||
v-model="cluster.preferences.terminalCWD"
|
|
||||||
placeholder="$HOME"
|
|
||||||
id="input-terminalcwd"
|
|
||||||
@blur="onTerminalCwdSave"
|
|
||||||
:state="errors.terminalcwd"
|
|
||||||
:formatter="expandPath"
|
|
||||||
/>
|
|
||||||
</b-form-group>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { lstatSync } from "fs"
|
|
||||||
import { prometheusProviders } from '../../../../../common/prometheus-providers';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'ClusterSettingsPreferences',
|
|
||||||
props: {
|
|
||||||
cluster: {
|
|
||||||
type: Object,
|
|
||||||
default: null,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data(){
|
|
||||||
return {
|
|
||||||
errors: {
|
|
||||||
prometheusPath: null,
|
|
||||||
terminalcwd: null
|
|
||||||
},
|
|
||||||
prometheusPath: "",
|
|
||||||
prometheusProvider: "",
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
prometheusProviders: function() {
|
|
||||||
const providers = prometheusProviders.map((provider) => {
|
|
||||||
return { text: provider.name, value: provider.id }
|
|
||||||
})
|
|
||||||
providers.unshift({text: "Auto detect", value: ""})
|
|
||||||
|
|
||||||
return providers;
|
|
||||||
},
|
|
||||||
canEditPrometheusPath: function() {
|
|
||||||
if (this.prometheusProvider === "") return false
|
|
||||||
if (this.prometheusProvider === "lens") return false
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted: async function() {
|
|
||||||
this.updateValues()
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
updateValues: function(){
|
|
||||||
if (this.cluster.preferences.prometheus) {
|
|
||||||
const prom = this.cluster.preferences.prometheus
|
|
||||||
if (!prom.prefix) prom.prefix = ""
|
|
||||||
this.prometheusPath = `${prom.namespace}/${prom.service}:${prom.port}${prom.prefix}`
|
|
||||||
} else {
|
|
||||||
this.prometheusPath = ""
|
|
||||||
}
|
|
||||||
if (this.cluster.preferences.prometheusProvider) {
|
|
||||||
this.prometheusProvider = this.cluster.preferences.prometheusProvider.type
|
|
||||||
} else {
|
|
||||||
this.prometheusProvider = ""
|
|
||||||
}
|
|
||||||
},
|
|
||||||
parsePrometheusPath: function(path) {
|
|
||||||
const parsed = path.split(/\/|:/, 3)
|
|
||||||
const apiPrefix = path.substring(parsed.join("/").length)
|
|
||||||
if (parsed[0] && parsed[1] && parsed[2]) {
|
|
||||||
this.errors.prometheusPath = true;
|
|
||||||
} else {
|
|
||||||
this.errors.prometheusPath = false;
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
namespace: parsed[0],
|
|
||||||
service: parsed[1],
|
|
||||||
port: parsed[2],
|
|
||||||
prefix: apiPrefix
|
|
||||||
}
|
|
||||||
},
|
|
||||||
expandPath: function(value, event) {
|
|
||||||
if(value === "") {
|
|
||||||
this.errors.terminalcwd = null
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
if(value.substr(0, 1) == "~") {
|
|
||||||
value = process.env.HOME + value.substr(1);
|
|
||||||
} else if(value.substr(0, 5) == "$HOME") {
|
|
||||||
value = process.env.HOME + value.substr(5);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
this.errors.terminalcwd = lstatSync(value).isDirectory()
|
|
||||||
} catch(_err) {
|
|
||||||
this.errors.terminalcwd = false
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
},
|
|
||||||
onHttpsProxySave: function() {
|
|
||||||
if(this.cluster.preferences.httpsProxy === "") this.cluster.preferences.httpsProxy = null
|
|
||||||
this.$store.dispatch("storeCluster", this.cluster);
|
|
||||||
},
|
|
||||||
onPrometheusSave: function() {
|
|
||||||
if (this.prometheusPath === "") {
|
|
||||||
this.cluster.preferences.prometheus = null;
|
|
||||||
} else {
|
|
||||||
this.cluster.preferences.prometheus = this.parsePrometheusPath(this.prometheusPath);
|
|
||||||
}
|
|
||||||
this.$store.dispatch("storeCluster", this.cluster);
|
|
||||||
},
|
|
||||||
onPrometheusProviderSave: function() {
|
|
||||||
if (this.prometheusProvider === "") {
|
|
||||||
this.cluster.preferences.prometheusProvider = null;
|
|
||||||
this.cluster.preferences.prometheus = null;
|
|
||||||
} else {
|
|
||||||
this.cluster.preferences.prometheusProvider = { type: this.prometheusProvider }
|
|
||||||
}
|
|
||||||
this.$store.dispatch("storeCluster", this.cluster);
|
|
||||||
},
|
|
||||||
onTerminalCwdSave: function() {
|
|
||||||
if(this.cluster.preferences.terminalCWD === "") this.cluster.preferences.terminalCWD = null
|
|
||||||
this.$store.dispatch("storeCluster", this.cluster);
|
|
||||||
},
|
|
||||||
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
"cluster": "updateValues",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
|
|
||||||
</style>
|
|
||||||
@ -1,185 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="content">
|
|
||||||
<ClosePageButton />
|
|
||||||
<div class="container-fluid settings">
|
|
||||||
<div v-if="cluster" class="header sticky-top">
|
|
||||||
<h2>
|
|
||||||
<div class="icon d-inline">
|
|
||||||
<img v-if="preferences.icon" :src="preferences.icon" class="cluster-icon">
|
|
||||||
<hashicon v-else :name="cluster.preferences.clusterName" size="30" />
|
|
||||||
</div>
|
|
||||||
{{ cluster.preferences.clusterName }}
|
|
||||||
</h2>
|
|
||||||
</div>
|
|
||||||
<div v-if="cluster" class="row">
|
|
||||||
<div class="col-3" />
|
|
||||||
<div ref="content" id="cluster-settings" class="col-6">
|
|
||||||
<cluster-settings-overview :cluster="cluster" />
|
|
||||||
<cluster-settings-general :cluster="cluster" />
|
|
||||||
<cluster-settings-preferences :cluster="cluster" />
|
|
||||||
<cluster-settings-features :cluster="cluster" />
|
|
||||||
|
|
||||||
<div id="cluster-remove" class="settings-section">
|
|
||||||
<h2>Remove Cluster</h2>
|
|
||||||
<b-button v-b-modal.bv-modal-confirm variant="danger" type="submit">
|
|
||||||
Remove Cluster
|
|
||||||
</b-button>
|
|
||||||
<!-- Modal confirmation -->
|
|
||||||
<b-modal id="bv-modal-confirm" @ok="removeCluster" ok-title="Remove" ok-variant="danger" title-class="confirm-header" hide-backdrop title="Confirm cluster delete">
|
|
||||||
<p>Are you sure you want to delete <strong>{{ preferences.clusterName }}</strong> cluster from Lens?</p>
|
|
||||||
</b-modal>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div v-if="!cluster">
|
|
||||||
<cube-spinner text="Loading..." />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import CubeSpinner from "@/_vue/components/CubeSpinner";
|
|
||||||
import ClusterSettingsGeneral from "./General/index";
|
|
||||||
import ClusterSettingsOverview from "./Overview/index";
|
|
||||||
import ClusterSettingsPreferences from "./Preferences/index";
|
|
||||||
import ClusterSettingsFeatures from "./Features/index";
|
|
||||||
import hashicon from "../hashicon/hashicon";
|
|
||||||
import ClosePageButton from "@/_vue/components/common/ClosePageButton";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'ClusterSettingsPage',
|
|
||||||
components: {
|
|
||||||
CubeSpinner,
|
|
||||||
ClosePageButton,
|
|
||||||
ClusterSettingsGeneral,
|
|
||||||
ClusterSettingsOverview,
|
|
||||||
ClusterSettingsPreferences,
|
|
||||||
ClusterSettingsFeatures,
|
|
||||||
hashicon
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
cluster: function() {
|
|
||||||
return this.$store.getters.clusterById(this.$route.params.id);
|
|
||||||
},
|
|
||||||
preferences: function() {
|
|
||||||
return this.cluster.preferences;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
loadLens: function() {
|
|
||||||
this.$store.dispatch("refineCluster", this.cluster.id);
|
|
||||||
},
|
|
||||||
removeCluster: async function(){
|
|
||||||
let res = await this.$store.dispatch('removeCluster', this.cluster.id);
|
|
||||||
if(!res) return false;
|
|
||||||
|
|
||||||
this.$router.push({
|
|
||||||
name: "landing-page"
|
|
||||||
}).catch(err => {})
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
this.loadLens()
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
"$route": "loadLens"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
.header {
|
|
||||||
& h2 {
|
|
||||||
padding: 0.5rem
|
|
||||||
}
|
|
||||||
padding-top: 5px;
|
|
||||||
padding-left: 15px;
|
|
||||||
border-bottom: 1px solid rgb(53, 58, 62);
|
|
||||||
background-color: #1e2124;
|
|
||||||
& img {
|
|
||||||
margin-right: 10px;
|
|
||||||
height: 35px;
|
|
||||||
}
|
|
||||||
.hashicon {
|
|
||||||
position: relative;
|
|
||||||
height: 40px;
|
|
||||||
margin-right: 10px;
|
|
||||||
& canvas{
|
|
||||||
position: relative;
|
|
||||||
bottom: -6px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.settings {
|
|
||||||
height: 100%;
|
|
||||||
overflow-y: scroll;
|
|
||||||
}
|
|
||||||
.settings-section {
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#cluster-settings {
|
|
||||||
& input {
|
|
||||||
background-color: #252729 !important;
|
|
||||||
border: 0px !important;
|
|
||||||
color: #87909c !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.cluster-icon {
|
|
||||||
width: 38px;
|
|
||||||
}
|
|
||||||
|
|
||||||
h2{
|
|
||||||
padding: 0.75rem;
|
|
||||||
padding-left: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table th, .table td{
|
|
||||||
padding-bottom: 0px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.custom-select {
|
|
||||||
-webkit-appearance: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
.collapsed > .when-opened, :not(.collapsed) > .when-closed {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.confirm-header{
|
|
||||||
color: #dc3545;
|
|
||||||
}
|
|
||||||
|
|
||||||
.navbar {
|
|
||||||
align-items: flex-start !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-link {
|
|
||||||
padding: 0px !important;
|
|
||||||
&.active {
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.custom-file-label{
|
|
||||||
background: transparent !important;
|
|
||||||
color: #3d90ce !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.was-validated .custom-file-input:invalid ~ .custom-file-label, .custom-file-input.is-invalid ~ .custom-file-label {
|
|
||||||
border-color: transparent !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.custom-file-label::after {
|
|
||||||
content: "" !important;
|
|
||||||
width: 0px;
|
|
||||||
padding: 0px !important;
|
|
||||||
background-color: transparent !important;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
Loading…
Reference in New Issue
Block a user