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