zeus
4 years ago
20 changed files with 2768 additions and 733 deletions
File diff suppressed because one or more lines are too long
@ -1 +1 @@ |
|||||
<!DOCTYPE html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Vue App</title><link href="/css/app.53b4e610.css" rel="preload" as="style"><link href="/css/chunk-vendors.e469b508.css" rel="preload" as="style"><link href="/js/app.9bdd4243.js" rel="preload" as="script"><link href="/js/chunk-vendors.d8d18fe6.js" rel="preload" as="script"><link href="/css/chunk-vendors.e469b508.css" rel="stylesheet"><link href="/css/app.53b4e610.css" rel="stylesheet"></head><body><div id="app"></div><script src="/js/chunk-vendors.d8d18fe6.js"></script><script src="/js/app.9bdd4243.js"></script></body></html> |
<!DOCTYPE html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Vue App</title><link href="/css/app.10423c10.css" rel="preload" as="style"><link href="/css/chunk-vendors.e469b508.css" rel="preload" as="style"><link href="/js/app.de882020.js" rel="preload" as="script"><link href="/js/chunk-vendors.d8d18fe6.js" rel="preload" as="script"><link href="/css/chunk-vendors.e469b508.css" rel="stylesheet"><link href="/css/app.10423c10.css" rel="stylesheet"></head><body><div id="app"></div><script src="/js/chunk-vendors.d8d18fe6.js"></script><script src="/js/app.de882020.js"></script></body></html> |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1,16 @@ |
|||||
|
#!/bin/sh |
||||
|
|
||||
|
REPOSRC=$1 |
||||
|
LOCALREPO=$2 |
||||
|
|
||||
|
# We do it this way so that we can abstract if from just git later on |
||||
|
LOCALREPO_VC_DIR=$LOCALREPO/.git |
||||
|
|
||||
|
cd builders |
||||
|
if [ ! -d $LOCALREPO_VC_DIR ] |
||||
|
then |
||||
|
git clone $REPOSRC $LOCALREPO |
||||
|
else |
||||
|
cd $LOCALREPO |
||||
|
git pull $REPOSRC |
||||
|
fi |
@ -0,0 +1 @@ |
|||||
|
Subproject commit 00608a32bd57f24ef78500458e700c1fb5bafc0c |
File diff suppressed because it is too large
@ -0,0 +1,62 @@ |
|||||
|
<template> |
||||
|
<card class="card-user" style="max-height:100%"> |
||||
|
|
||||
|
<div class="row" > |
||||
|
<div class="col-7 order-first " > |
||||
|
<br> |
||||
|
<view-network> |
||||
|
|
||||
|
</view-network> |
||||
|
|
||||
|
<builder-services> |
||||
|
|
||||
|
</builder-services> |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
<div class="col-5 order-last" > |
||||
|
<br> |
||||
|
<adhoc-view> |
||||
|
|
||||
|
</adhoc-view> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
|
||||
|
</card> |
||||
|
</template> |
||||
|
<script> |
||||
|
import {mapState, mapGetters, mapActions} from 'vuex' |
||||
|
import ViewNetwork from "./mynetwork/mybuilder.vue"; |
||||
|
import AdhocView from "./mynetwork/AdhocView.vue"; |
||||
|
import BuilderServices from "./mynetwork/builderservices.vue"; |
||||
|
import card from '@/components/Card.vue' |
||||
|
//import AvailableServices from "./mynetwork/availableservices.vue"; |
||||
|
export default { |
||||
|
components: { |
||||
|
ViewNetwork, |
||||
|
AdhocView, |
||||
|
card, |
||||
|
BuilderServices |
||||
|
// AvailableServices |
||||
|
}, |
||||
|
data () { |
||||
|
return { |
||||
|
loading: false, |
||||
|
consoleView: 'off', |
||||
|
productIndex: 1 |
||||
|
} |
||||
|
}, |
||||
|
mounted() { |
||||
|
}, |
||||
|
beforeDestroy () { |
||||
|
}, |
||||
|
|
||||
|
|
||||
|
created () { |
||||
|
} |
||||
|
}; |
||||
|
</script> |
||||
|
<style> |
||||
|
</style> |
||||
|
|
@ -0,0 +1,501 @@ |
|||||
|
<template> |
||||
|
<card class="card-user" style="max-height:100%"> |
||||
|
|
||||
|
|
||||
|
<v-wait for="myRunInstancetutor"> |
||||
|
<template slot="waiting"> |
||||
|
<div> |
||||
|
<img src="@/assets/loading.gif" /> |
||||
|
Enter Lab_room... |
||||
|
</div> |
||||
|
</template> |
||||
|
</v-wait> |
||||
|
|
||||
|
<b-container fluid class="bv-example-row"> |
||||
|
|
||||
|
<div class="input-group input-group-sm sm-3"> |
||||
|
<div class="input-group-append"> |
||||
|
<button |
||||
|
class="btn btn-outline-info" |
||||
|
round |
||||
|
type="button" |
||||
|
@click="setRefresh"> |
||||
|
Refresh table</button> |
||||
|
</div> |
||||
|
|
||||
|
<input type="text" |
||||
|
class="form-control" |
||||
|
aria-label="Small" aria-describedby="inputGroup-sizing-sm" |
||||
|
placeholder="Search by Name" |
||||
|
v-model="searchFor" |
||||
|
@keyup.enter="setFilter" |
||||
|
> |
||||
|
|
||||
|
<div class="input-group-append"> |
||||
|
<button |
||||
|
class="btn btn-outline-primary" |
||||
|
round |
||||
|
type="button" |
||||
|
@click="setFilter"> |
||||
|
Go</button> |
||||
|
</div> |
||||
|
|
||||
|
<div class="input-group-append"> |
||||
|
<button class="btn btn-outline-secondary" |
||||
|
round |
||||
|
type="button" |
||||
|
@click="resetFilter"> |
||||
|
Reset</button> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="white h-100 flex-fixed-width-item" |
||||
|
<vuetable |
||||
|
ref="vuetable" |
||||
|
:key="vuetablekey" |
||||
|
:api-url='apiurl' |
||||
|
:api-mode="true" |
||||
|
:http-options="httpOptions" |
||||
|
:fields="fields" |
||||
|
:item-actions="itemActions" |
||||
|
:sort-order="sortOrder" |
||||
|
:show-sort-icons="true" |
||||
|
:multi-sort="multiSort" |
||||
|
:per-page="perpage" |
||||
|
pagination-path="links.pagination" |
||||
|
:pagination-component="paginationComponent" |
||||
|
:append-params="moreParams" |
||||
|
wrapper-class="vuetable-wrapper" |
||||
|
loading-class="loading" |
||||
|
detail-row-id="id" |
||||
|
@vuetable:pagination-data="onPaginationData" |
||||
|
@vuetable:load-success="loadsuccess" |
||||
|
@vuetable:load-error="onLoadError" |
||||
|
:css="css.table" |
||||
|
> |
||||
|
|
||||
|
<div slot="actions" slot-scope="props"> |
||||
|
<button |
||||
|
v-if="actionrowindex == props.rowIndex" |
||||
|
class="ti-more-alt btn btn-secondary btn-sm" |
||||
|
round |
||||
|
@click="onAction('run-more', props.rowData, props.rowIndex)"> |
||||
|
</button> |
||||
|
<button |
||||
|
v-else |
||||
|
class="ti-more btn btn-outline-secondary btn-sm" |
||||
|
round |
||||
|
@click="onAction('run-more', props.rowData, props.rowIndex)"> |
||||
|
</button> |
||||
|
</div> |
||||
|
|
||||
|
|
||||
|
<div slot="actionslocal" slot-scope="props"> |
||||
|
<div class="d-flex justify-content-center"> |
||||
|
<button |
||||
|
v-if="build_file[props.rowData.name] == props.rowData.name" |
||||
|
class="ti-trash btn btn-info btn-sm" |
||||
|
title="Remove Lab_Instance" |
||||
|
@click="onAction('view-item', props.rowData, props.rowIndex)" |
||||
|
round |
||||
|
> |
||||
|
</button> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
</vuetable> |
||||
|
<div class="vuetable-pagination ui basic segment grid"> |
||||
|
<vuetable-pagination-info |
||||
|
ref="paginationInfo" |
||||
|
:css="css.paginationInfo" |
||||
|
> |
||||
|
</vuetable-pagination-info> |
||||
|
<vuetable-pagination |
||||
|
:css="css.pagination" |
||||
|
ref="pagination" |
||||
|
@vuetable-pagination:change-page="onChangePage" |
||||
|
> |
||||
|
</vuetable-pagination> |
||||
|
</div> |
||||
|
</div> |
||||
|
</b-container> |
||||
|
</card> |
||||
|
</template> |
||||
|
<script> |
||||
|
import store from '@/store/index' |
||||
|
import {mapState, mapGetters, mapActions,dispatch} from 'vuex' |
||||
|
import Vue from 'vue' |
||||
|
import {Vuetable, VuetablePaginationDropdown} from 'vuetable-2' |
||||
|
import VuetablePaginationInfo from 'vuetable-2/src/components/VuetablePaginationInfo' |
||||
|
import VuetablePagination from 'vuetable-2/src/components/VuetablePagination' |
||||
|
import CssConfig from 'vuetable-2/src/components/VuetableCssConfig.js' |
||||
|
import card from '@/components/Card.vue' |
||||
|
import {ApiConfig} from "@/config/index"; |
||||
|
export default { |
||||
|
components: { |
||||
|
card, |
||||
|
Vuetable, |
||||
|
VuetablePagination, |
||||
|
VuetablePaginationInfo, |
||||
|
VuetablePaginationDropdown |
||||
|
}, |
||||
|
props: { |
||||
|
}, |
||||
|
data() { |
||||
|
return{ |
||||
|
actionrowindex:'', |
||||
|
playbookInfo: {}, |
||||
|
token: '', |
||||
|
build_file :{}, |
||||
|
playbook: { |
||||
|
'title':'', |
||||
|
'name':'', |
||||
|
'description':'' |
||||
|
}, |
||||
|
container:{ |
||||
|
name:'', |
||||
|
view:0 |
||||
|
}, |
||||
|
pipeline:{}, |
||||
|
selected: 'hybrid', |
||||
|
options: [ |
||||
|
{ text: 'Packages', value: 'packages' }, |
||||
|
{ text: 'Images', value: 'images' }, |
||||
|
{ text: 'Scripts', value: 'scripts' } |
||||
|
], |
||||
|
showModal: false, |
||||
|
visibility: [], |
||||
|
active:false, |
||||
|
vuetablekey:0, |
||||
|
fielddata:{}, |
||||
|
fields: [ |
||||
|
{ |
||||
|
name: 'name', |
||||
|
title: '<span class="orange"></span>Name', |
||||
|
sortField: 'name', |
||||
|
visible:true, |
||||
|
dataClass: 'text-left text-wrap text-break break-word', |
||||
|
width: '65%' |
||||
|
}, |
||||
|
{ |
||||
|
name: 'Image', |
||||
|
title: '<span class="orange"></span>Image', |
||||
|
//sortField: 'Image', |
||||
|
visible:false, |
||||
|
dataClass: 'left aligned w-25', |
||||
|
width: '15%', |
||||
|
formatter (value) { |
||||
|
const result = /^ondemand_playground/.test(value); |
||||
|
if (result) { |
||||
|
var v = '<p class="text-warning">Playground</p>' |
||||
|
return v |
||||
|
}else{ |
||||
|
var v = '<p class="text-info">Lab</p>' |
||||
|
return v |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
}, |
||||
|
{ |
||||
|
name: '_id', |
||||
|
title: '<span class="orange"></span>mongo', |
||||
|
visible:false |
||||
|
}, |
||||
|
{ |
||||
|
name: 'Status', |
||||
|
title: '<span class="orange"></span>Status', |
||||
|
sortField: 'Status', |
||||
|
titleClass: 'center aligned', |
||||
|
visible:true, |
||||
|
width: '10%' |
||||
|
}, |
||||
|
{ |
||||
|
name: 'ID', |
||||
|
sortField: 'ID', |
||||
|
titleClass: 'center aligned', |
||||
|
dataClass: 'left aligned w-25', |
||||
|
visible:false, |
||||
|
width: '15%' |
||||
|
}, |
||||
|
{ |
||||
|
name: '__slot:actionslocal', // <---- |
||||
|
title: 'Box', |
||||
|
titleClass: 'center', |
||||
|
dataClass: 'center aligned', |
||||
|
width: '5%' |
||||
|
}, |
||||
|
{ |
||||
|
name: '__slot:actions', // <---- |
||||
|
title: 'Actions', |
||||
|
titleClass: 'center aligned', |
||||
|
dataClass: 'center aligned', |
||||
|
width: '5%' |
||||
|
}, |
||||
|
], |
||||
|
apiurl:ApiConfig.url_80+"/buildservices", |
||||
|
//apiurl:ApiConfig.swarmlab_url_80+"/swarmlabhybridservices", |
||||
|
css: CssConfig, |
||||
|
perpage: 5, |
||||
|
searchFor: '', |
||||
|
sortOrder: [{ |
||||
|
field: 'name', |
||||
|
direction: 'asc' |
||||
|
}], |
||||
|
multiSort: true, |
||||
|
paginationComponent: 'vuetable-pagination', |
||||
|
itemActions: [ |
||||
|
{ name: 'view-item', label: '', icon: 'glyphicon glyphicon-zoom-in', class: 'btn btn-info', extra: {'title': 'View', 'data-toggle':"tooltip", 'data-placement': "left"} }, |
||||
|
{ name: 'edit-item', label: '', icon: 'glyphicon glyphicon-pencil', class: 'btn btn-warning', extra: {title: 'Edit', 'data-toggle':"tooltip", 'data-placement': "top"} }, |
||||
|
{ name: 'delete-item', label: '', icon: 'glyphicon glyphicon-remove', class: 'btn btn-danger', extra: {title: 'Delete', 'data-toggle':"tooltip", 'data-placement': "right" } } |
||||
|
], |
||||
|
moreParams: { |
||||
|
'filter': '', |
||||
|
'type': 'scripts', |
||||
|
'tutor': 'yes' |
||||
|
}, |
||||
|
|
||||
|
} |
||||
|
}, |
||||
|
mounted() { |
||||
|
this.$root.$on('SERVER_build_close_build', (v) => { |
||||
|
console.log('build from server '+JSON.stringify(v)) |
||||
|
if(v.build == "ok" && v.file !== 'false'){ |
||||
|
Vue.set(this.build_file, v.name, v.name) |
||||
|
// this.$set(this.user, 'last_name', 'Doe') |
||||
|
console.log('build ok '+JSON.stringify(this.build_file)) |
||||
|
}else{ |
||||
|
Vue.delete(this.build_file, v.name) |
||||
|
console.log('build no '+JSON.stringify(this.build_file)) |
||||
|
} |
||||
|
if( v.homefile_exist == 'yes'){ |
||||
|
console.log('build no '+JSON.stringify(v.homefile)) |
||||
|
var info = ` |
||||
|
<b-container fluid> |
||||
|
<div class="row text-center"> |
||||
|
<div class="col-12"> |
||||
|
|
||||
|
<h5> <b>File exists</b> </h5> |
||||
|
<h5> Error: You cannot Create a VM that already exists.</h5> |
||||
|
<h5> Please rename or remove the file and Retry </h5> |
||||
|
<p class="mb-1 list-group-item list-group-item-success"> |
||||
|
${v.homefile} |
||||
|
</p> |
||||
|
</div> <!-- col --> |
||||
|
</div> <!-- row --> |
||||
|
</b-container fluid> |
||||
|
` |
||||
|
this.$swal({ |
||||
|
type: 'info', |
||||
|
html: info, |
||||
|
icon: 'info', |
||||
|
showCloseButton: true, |
||||
|
showLoaderOnConfirm: false, |
||||
|
allowOutsideClick: false, |
||||
|
cancelButtonText: 'No, cancel!', |
||||
|
showCancelButton: false, |
||||
|
showLoaderOnConfirm: false, |
||||
|
reverseButtons: true, |
||||
|
focusCancel: false, |
||||
|
confirmButtonText: 'ok! ' |
||||
|
}) |
||||
|
} |
||||
|
Vue.nextTick( () => this.$refs.vuetable.refresh()) |
||||
|
}) |
||||
|
}, |
||||
|
created() { |
||||
|
var url_string = window.location.href |
||||
|
var url = new URL(url_string); |
||||
|
this.token = url.searchParams.get("token"); |
||||
|
//console.log("token "+ this.token); |
||||
|
|
||||
|
}, |
||||
|
beforeDestroy () { |
||||
|
this.$root.$off('SERVER_build_close_build') |
||||
|
}, |
||||
|
computed: { |
||||
|
httpOptions() { |
||||
|
var token = this.token |
||||
|
var p="headers: {Authorization: token}}"; //table props -> :http-options="httpOptions" |
||||
|
return {headers: {Authorization: 'Bearer ' + token}} //table props -> :http-options="httpOptions" |
||||
|
}, |
||||
|
|
||||
|
}, |
||||
|
|
||||
|
methods: { |
||||
|
onError (type,description) { |
||||
|
var winfo=description |
||||
|
var info='<h5>Bootstrap '+type+'</h5>' |
||||
|
this.$swal({ |
||||
|
type: type, |
||||
|
html: info+winfo, |
||||
|
showCloseButton: true, |
||||
|
showLoaderOnConfirm: false, |
||||
|
allowOutsideClick: false, |
||||
|
cancelButtonText: 'No, cancel!', |
||||
|
showCancelButton: false, |
||||
|
showLoaderOnConfirm: false, |
||||
|
reverseButtons: true, |
||||
|
focusCancel: true, |
||||
|
confirmButtonText: 'Ok!' |
||||
|
}) |
||||
|
}, |
||||
|
|
||||
|
|
||||
|
setRefresh () { |
||||
|
this.moreParams = { |
||||
|
'filter': '', |
||||
|
'type': this.selected |
||||
|
} |
||||
|
Vue.nextTick( () => this.$refs.vuetable.refresh()) |
||||
|
}, |
||||
|
setFilter () { |
||||
|
this.moreParams = { |
||||
|
'filter': this.searchFor, |
||||
|
'type': this.selected |
||||
|
} |
||||
|
Vue.nextTick( () => this.$refs.vuetable.refresh()) |
||||
|
}, |
||||
|
resetFilter () { |
||||
|
this.moreParams = {} |
||||
|
this.searchFor = '' |
||||
|
Vue.nextTick( () => this.$refs.vuetable.refresh()) |
||||
|
}, |
||||
|
onPaginationData (paginationData) { |
||||
|
this.$refs.pagination.setPaginationData(paginationData) |
||||
|
this.$refs.paginationInfo.setPaginationData(paginationData) |
||||
|
}, |
||||
|
onChangePage (page) { |
||||
|
this.$refs.vuetable.changePage(page) |
||||
|
}, |
||||
|
editRow(rowData) { |
||||
|
alert("You clicked edit on"+ JSON.stringify(rowData)); |
||||
|
}, |
||||
|
async onAction (action, data, index) { |
||||
|
this.actionrowindex = index |
||||
|
var obj = {} |
||||
|
obj.name = data.name |
||||
|
obj.dir = data.dir |
||||
|
obj.config = data.config |
||||
|
this.$root.$emit('BUILD_hybrid_show_info',data) |
||||
|
console.log('index '+this.actionrowindex) |
||||
|
console.log('data '+JSON.stringify(obj)) |
||||
|
if(action == 'view-item' ){ |
||||
|
console.log('data' + JSON.stringify(data)) |
||||
|
console.log('index '+JSON.stringify(index)) |
||||
|
console.log('build info '+JSON.stringify(this.build_file)) |
||||
|
}else if(action == 'delete-item' ){ |
||||
|
this.$swal({ |
||||
|
type: 'info', |
||||
|
html: info+winfo, |
||||
|
showCloseButton: true, |
||||
|
showLoaderOnConfirm: false, |
||||
|
allowOutsideClick: false, |
||||
|
cancelButtonText: 'No, cancel!', |
||||
|
showCancelButton: true, |
||||
|
showLoaderOnConfirm: false, |
||||
|
reverseButtons: true, |
||||
|
focusCancel: true, |
||||
|
confirmButtonText: 'Yes, Delete it!' |
||||
|
}) |
||||
|
}else if(action == 'run-item' ){ |
||||
|
} |
||||
|
}, |
||||
|
refreshVuetable() { |
||||
|
this.$nextTick(()=>{ |
||||
|
this.vuetablekey += 1 |
||||
|
}) |
||||
|
}, |
||||
|
playbookinfoShow(value) { |
||||
|
return this.visibility[value]=true |
||||
|
}, |
||||
|
playbookinfo(value) { |
||||
|
return this.playbookInfo=value |
||||
|
}, |
||||
|
rowClicked(row, event) { |
||||
|
return { |
||||
|
html: true, |
||||
|
title: () => { return 'Hello <b>Popover:</b> ' + (++this.counter) }, |
||||
|
content: () => { return 'The date is:<br><em>' + new Date() + '</em>' } |
||||
|
} |
||||
|
}, |
||||
|
loadsuccess(response) { |
||||
|
var data = response.data.data |
||||
|
this.fielddata=data |
||||
|
var n = data.length |
||||
|
n=n-1 |
||||
|
}, |
||||
|
onLoadError(payload) { |
||||
|
/* |
||||
|
//error2 "invalid_token" join-service.vue:684 |
||||
|
//error2 "The access token provided has expired" join-service.vue:685 |
||||
|
//error2 "Unauthorized" join-service.vue:686 |
||||
|
//error2 401 |
||||
|
console.log('error2 '+JSON.stringify(payload.response.data.error)) |
||||
|
console.log('error2 '+JSON.stringify(payload.response.data.error_description)) |
||||
|
console.log('error2 '+JSON.stringify(payload.response.statusText)) |
||||
|
console.log('error2 '+JSON.stringify(payload.response.status)) |
||||
|
*/ |
||||
|
if(payload.response.status == '401'){ |
||||
|
window.location.href = 'https://api-login.swarmlab.io:8089'; |
||||
|
Vue.nextTick( () => window.location.href = 'https://api-login.swarmlab.io:8089') |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
}, |
||||
|
|
||||
|
|
||||
|
actions: { |
||||
|
|
||||
|
|
||||
|
} |
||||
|
|
||||
|
}; |
||||
|
</script> |
||||
|
<style> |
||||
|
.flex-fixed-width-item { |
||||
|
flex: 0 0 100px; |
||||
|
} |
||||
|
.modalinfo { |
||||
|
z-index: 10000000 !important; |
||||
|
position:fixed; |
||||
|
} |
||||
|
/* a container with flex-direction column */ |
||||
|
|
||||
|
.vue-notifyjs.notifications{ |
||||
|
.alert{ |
||||
|
z-index: 100; |
||||
|
} |
||||
|
.list-move { |
||||
|
transition: transform 0.3s, opacity 0.4s; |
||||
|
} |
||||
|
.list-item { |
||||
|
display: inline-block; |
||||
|
margin-right: 10px; |
||||
|
|
||||
|
} |
||||
|
.list-enter-active { |
||||
|
transition: transform 0.2s ease-in, opacity 0.4s ease-in; |
||||
|
} |
||||
|
.list-leave-active { |
||||
|
transition: transform 1s ease-out, opacity 0.4s ease-out; |
||||
|
} |
||||
|
|
||||
|
.list-enter { |
||||
|
opacity: 0; |
||||
|
transform: scale(1.1); |
||||
|
|
||||
|
} |
||||
|
.list-leave-to { |
||||
|
opacity: 0; |
||||
|
transform: scale(1.2, 0.7); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
pre { |
||||
|
//background-color: rgb(255, 247, 229); |
||||
|
background-color: #eff0f1; |
||||
|
border: 1px solid blue; |
||||
|
//white-space: pre-line; |
||||
|
} |
||||
|
|
||||
|
</style> |
@ -0,0 +1,589 @@ |
|||||
|
<template> |
||||
|
<card class="card-user" style="max-height:100%"> |
||||
|
<div class="author"> |
||||
|
<img class="avatar border-white" src="@/assets/img/docker.png" alt="..."> |
||||
|
</div> |
||||
|
|
||||
|
<b-container fluid class="bv-example-row"> |
||||
|
<div class="row text-center"> |
||||
|
<div class="col-12"> |
||||
|
<b>View and Manage your builds</b> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<br> |
||||
|
<div class="input-group input-group-sm sm-3"> |
||||
|
<div class="input-group-prepend"> |
||||
|
<button |
||||
|
v-if="$socket.disconnected" |
||||
|
class="ti-unlink btn btn-outline-danger" |
||||
|
round |
||||
|
type="button" |
||||
|
title="You are disconnected from Swarmlab-hybrid" |
||||
|
disabled |
||||
|
> |
||||
|
</button> |
||||
|
<button |
||||
|
v-else |
||||
|
class="ti-link btn btn-outline-success" |
||||
|
round |
||||
|
type="button" |
||||
|
title="You are connected swarmlab-hybrid" |
||||
|
disabled |
||||
|
> |
||||
|
</button> |
||||
|
</div> |
||||
|
<div class="input-group-prepend"> |
||||
|
<!-- |
||||
|
<button |
||||
|
class="btn btn-outline-success" |
||||
|
round |
||||
|
type="button" |
||||
|
@click="onAction('start')" |
||||
|
> |
||||
|
Start</button> |
||||
|
--> |
||||
|
</div> |
||||
|
<div class="input-group-prepend"> |
||||
|
<button |
||||
|
v-if="hybridshowdata.name" |
||||
|
class="btn btn-outline-success" |
||||
|
round |
||||
|
type="button" |
||||
|
@click="onAction('container-build')" |
||||
|
> |
||||
|
Build</button> |
||||
|
<button |
||||
|
v-if="hybridshowdata.name" |
||||
|
class="btn btn-outline-secondary ti-info" |
||||
|
round |
||||
|
type="button" |
||||
|
@click="onAction('container-build-info')" |
||||
|
> |
||||
|
</button> |
||||
|
<button |
||||
|
v-else |
||||
|
class="btn btn-outline-secondary" |
||||
|
round |
||||
|
type="button" |
||||
|
disabled |
||||
|
> |
||||
|
Connect</button> |
||||
|
<button |
||||
|
class="btn btn-outline-danger" |
||||
|
round |
||||
|
type="button" |
||||
|
@click="onAction('container-stop')" |
||||
|
> |
||||
|
Stop</button> |
||||
|
</div> |
||||
|
|
||||
|
<div class="input-group-append"> |
||||
|
</div> |
||||
|
|
||||
|
</div> |
||||
|
</b-container> |
||||
|
<b-container fluid> |
||||
|
<div class="row" > |
||||
|
<div class="col-2 text-info" > |
||||
|
ID |
||||
|
</div> |
||||
|
<div class="col-3 text-secondary" > |
||||
|
{{ hybridshowdata.ID }} |
||||
|
</div> |
||||
|
<div class="col-2 text-info" > |
||||
|
Image |
||||
|
</div> |
||||
|
<div class="col-4 text-secondary" > |
||||
|
{{ hybridshowdata.Image }} |
||||
|
</div> |
||||
|
</div> <!-- row --> |
||||
|
<div class="row" > |
||||
|
<div class="col-2 text-info" > |
||||
|
Names |
||||
|
</div> |
||||
|
<div class="col-3 text-secondary" > |
||||
|
{{ hybridshowdata.name }} |
||||
|
</div> |
||||
|
<div class="col-2 text-info" > |
||||
|
RunningFor |
||||
|
</div> |
||||
|
<div class="col-4 text-secondary" > |
||||
|
{{ hybridshowdata.RunningFor }} |
||||
|
</div> |
||||
|
</div> <!-- row --> |
||||
|
<div class="row" > |
||||
|
|
||||
|
<div class="col-2 text-info" > |
||||
|
Status |
||||
|
</div> |
||||
|
<div class="col-3 text-secondary" > |
||||
|
{{ hybridshowdata.Status }} |
||||
|
</div> |
||||
|
|
||||
|
<div class="col-2 text-info" > |
||||
|
CreatedAt |
||||
|
</div> |
||||
|
<div class="col-4 text-secondary" > |
||||
|
{{ hybridshowdata.CreatedAt }} |
||||
|
</div> |
||||
|
</div> <!-- row --> |
||||
|
<div class="row" > |
||||
|
|
||||
|
<div class="col-2 text-info" > |
||||
|
<button |
||||
|
v-if="hybridshowdata.Networks&&addNetworkMenou==false" |
||||
|
class="btn btn-outline-info btn-sm" |
||||
|
round |
||||
|
type="button" |
||||
|
@click="addNetwork(hybridshowdata,'on')" |
||||
|
> |
||||
|
Networks</button> |
||||
|
<button |
||||
|
v-if="hybridshowdata.Networks&&addNetworkMenou==true" |
||||
|
class="btn btn-outline-warning btn-sm" |
||||
|
round |
||||
|
type="button" |
||||
|
@click="addNetwork(hybridshowdata,'off')" |
||||
|
> |
||||
|
Networks</button> |
||||
|
</div> |
||||
|
<div class="col-3 text-secondary" > |
||||
|
{{ hybridshowdata.Networks }} |
||||
|
</div> |
||||
|
|
||||
|
<div class="col-2 text-info" > |
||||
|
Ports |
||||
|
</div> |
||||
|
<div class="col-4 text-secondary" > |
||||
|
{{ hybridshowdata.Ports }} |
||||
|
</div> |
||||
|
</div> <!-- row --> |
||||
|
<!-- |
||||
|
'{"ID":"{{ .ID }}", "Image": "{{ .Image }}", "Names":"{{ .Names }}", "Ports":"{{.Ports}}", |
||||
|
"Networks":"{{.Networks}}", "Status":"{{.Status}}","RunningFor":"{{.RunningFor}}","CreatedAt":"{{.CreatedAt}}"}' |
||||
|
--> |
||||
|
</b-container> |
||||
|
|
||||
|
<!-- Networks --> |
||||
|
|
||||
|
<div class="card border-success bg-light mb-3" style="max-width: 100%;" |
||||
|
v-if="addNetworkMenou==true" |
||||
|
> |
||||
|
<div class="card-header"></div> |
||||
|
<div class="card-body text-info"> |
||||
|
<div class="row"> |
||||
|
<div class="col-6 text-info"> |
||||
|
<h5 class="card-title">Select network</h5> |
||||
|
</div> |
||||
|
<div class="col-6 text-info"> |
||||
|
Connect a running container to multiple networks |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="row"> |
||||
|
<div class="col-6 text-info"> |
||||
|
<b-form-select v-model="selectedNetworks" :options="localNetworkoptions" multiple :select-size="4"></b-form-select> |
||||
|
<div class="mt-3">Selected: <strong>{{ selectedNetworks }}</strong></div> |
||||
|
</div> |
||||
|
<div class="col-6 text-info"> |
||||
|
<img class="border-white img-thumbnail" src="@/assets/img/dockernetwork.png" alt="..."> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="row"> |
||||
|
<div class="col-6 text-info"> |
||||
|
<button |
||||
|
class="btn btn-outline-warning btn-sm" |
||||
|
round |
||||
|
type="button" |
||||
|
@click="updateNetwork(hybridshowdata,'update')" |
||||
|
> |
||||
|
Update</button> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
|
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
|
||||
|
|
||||
|
</card> |
||||
|
</template> |
||||
|
<script> |
||||
|
import store from '@/store/index' |
||||
|
import {mapState, mapGetters, mapActions,dispatch} from 'vuex' |
||||
|
import Vue from 'vue' |
||||
|
import card from '@/components/Card.vue' |
||||
|
import {ApiConfig} from "@/config/index"; |
||||
|
import { extend } from 'vee-validate'; |
||||
|
import { required, alpha_num } from 'vee-validate/dist/rules'; |
||||
|
|
||||
|
// No message specified. |
||||
|
extend('alpha_num', alpha_num); |
||||
|
|
||||
|
// Override the default message. |
||||
|
extend('required', { |
||||
|
...required, |
||||
|
message: 'This field is required' |
||||
|
}); |
||||
|
|
||||
|
export default { |
||||
|
components: { |
||||
|
card |
||||
|
}, |
||||
|
props: { |
||||
|
}, |
||||
|
data() { |
||||
|
return{ |
||||
|
addNetworkMenou:false, |
||||
|
selectedNetworks:[], |
||||
|
localNetworkoptions:[], |
||||
|
localNetworkdefault:'', |
||||
|
STATUS:{}, |
||||
|
CONFIG:{ |
||||
|
'status':'', |
||||
|
'workerkey':'', |
||||
|
'swarmlab_public_wgkey':'', |
||||
|
'server_ip':'', |
||||
|
'allowed_ips':'', |
||||
|
'wg_port':'', |
||||
|
'wg_ip':'', |
||||
|
'swarm_ip':'', |
||||
|
'privatekey':'', |
||||
|
'publickey':'', |
||||
|
'workerkey':'', |
||||
|
'privatekey':'', |
||||
|
'publickey':'', |
||||
|
'server_ip':'' |
||||
|
}, |
||||
|
sshpid:0, |
||||
|
buildpid:0, |
||||
|
CONFIGallowed_ips:'', |
||||
|
swarmlabname:'swarmlab-sec', |
||||
|
swarmlabname_port:'', |
||||
|
swarmlabname_size:3, |
||||
|
swarmlabname_git:'', |
||||
|
// run on |
||||
|
hybridshowdata:{}, |
||||
|
issocket:'close', |
||||
|
setFilter: {}, |
||||
|
searchFor: {}, |
||||
|
resetFilter: {} |
||||
|
|
||||
|
} |
||||
|
}, |
||||
|
beforeMount () { |
||||
|
this.socketopen(); |
||||
|
this.socketauthenticate() |
||||
|
//console.log('send') |
||||
|
}, |
||||
|
mounted() { |
||||
|
// this.$root.$on('SERVER_build_set_sshpid', (data) => { |
||||
|
// this.sshpid = data.pid |
||||
|
// }) |
||||
|
this.$root.$on('SERVER_build_set_buildpid', (data) => { |
||||
|
this.buildpid = data.pid |
||||
|
}) |
||||
|
this.$root.$on('BUILD_hybrid_show_info', (data) => { |
||||
|
this.$nextTick(function () { |
||||
|
this.hybridshowdata = data |
||||
|
this.addNetworkMenou = false |
||||
|
this.selectedNetworks = [] |
||||
|
this.localNetworkoptions = [] |
||||
|
this.localNetworkdefault = '' |
||||
|
//console.log(JSON.stringify(this.hybridshowdata)) |
||||
|
}) |
||||
|
}) |
||||
|
}, |
||||
|
created() { |
||||
|
var url_string = window.location.href |
||||
|
var url = new URL(url_string); |
||||
|
this.token = url.searchParams.get("token"); |
||||
|
//console.log("token "+ this.token); |
||||
|
var log = store.dispatch("pipelineLLO/settoken",{ |
||||
|
token:this.token |
||||
|
}) |
||||
|
this.socketopen(); |
||||
|
|
||||
|
}, |
||||
|
beforeDestroy () { |
||||
|
this.$root.$off('BUILD_hybrid_show_info') |
||||
|
this.$root.$off('SERVER_build_set_buildpid') |
||||
|
//this.$root.$off('SERVER_build_set_sshpid') |
||||
|
}, |
||||
|
computed: { |
||||
|
httpOptions() { |
||||
|
var token = this.token |
||||
|
var p="headers: {Authorization: token}}"; //table props -> :http-options="httpOptions" |
||||
|
return {headers: {Authorization: 'Bearer ' + token}} //table props -> :http-options="httpOptions" |
||||
|
}, |
||||
|
|
||||
|
}, |
||||
|
|
||||
|
methods: { |
||||
|
async onAction(action){ |
||||
|
if(action == 'container-logs'){ |
||||
|
//this.$socket.client.open(); |
||||
|
//this.$socket.client.emit('build-vmlist', 'test'); |
||||
|
//this.$root.$emit('SERVER_build_vmlist') |
||||
|
console.log('logs---------- ' + JSON.stringify(this.hybridshowdata)) |
||||
|
}else if(action == 'container-build-info'){ |
||||
|
var info = ` |
||||
|
<b-container fluid> |
||||
|
<div class="row text-center"> |
||||
|
<div class="col-12"> |
||||
|
<h4><b>Tips and caveats</b></h4> |
||||
|
|
||||
|
<div class="list-group"> |
||||
|
<div class="d-flex w-100 justify-content-between"> |
||||
|
<h5 class="mb-1"><b>Install software</b></h5> |
||||
|
</div> |
||||
|
<p class="mb-1 list-group-item list-group-item-info"> |
||||
|
<b>Vagrant, Packer</b> and <b>VirtualBox</b> must be installed |
||||
|
</p> |
||||
|
<p class="mb-1 list-group-item list-group-item-info"> |
||||
|
You can find installation instructions <a href="https://git.swarmlab.io:3000/swarmlab/swarmlab-build-install" target="new">here</a> |
||||
|
</p> |
||||
|
|
||||
|
|
||||
|
</div> <!-- list --> |
||||
|
|
||||
|
</div> <!-- col --> |
||||
|
</div> <!-- row --> |
||||
|
</b-container fluid> |
||||
|
` |
||||
|
this.$swal({ |
||||
|
type: 'info', |
||||
|
html: info, |
||||
|
showCloseButton: true, |
||||
|
showLoaderOnConfirm: false, |
||||
|
allowOutsideClick: false, |
||||
|
cancelButtonText: 'No, cancel!', |
||||
|
showCancelButton: false, |
||||
|
showLoaderOnConfirm: false, |
||||
|
reverseButtons: true, |
||||
|
focusCancel: false, |
||||
|
confirmButtonText: 'ok! ' |
||||
|
}) |
||||
|
}else if(action == 'container-build'){ |
||||
|
var info = ` |
||||
|
<b-container fluid> |
||||
|
<div class="row text-center"> |
||||
|
<div class="col-12"> |
||||
|
<h4><b>Tips and caveats</b></h4> |
||||
|
|
||||
|
<div class="list-group"> |
||||
|
<div class="d-flex w-100 justify-content-between"> |
||||
|
<h5 class="mb-1"><b>Disk space</b></h5> |
||||
|
</div> |
||||
|
<p class="mb-1 list-group-item list-group-item-info"> |
||||
|
You need to run Builder on a machine with a <b>lot of free disk space</b> (sometimes 50 GB or more). <br> The installation media, VM(s) and box(es) take considerable amounts of space, at least temporarily. |
||||
|
</p> |
||||
|
</div> <!-- list --> |
||||
|
|
||||
|
<div class="list-group"> |
||||
|
<div class="d-flex w-100 justify-content-between"> |
||||
|
<h5 class="mb-1"><b>Time</b></h5> |
||||
|
</div> |
||||
|
<p class="mb-1 list-group-item list-group-item-info"> |
||||
|
Building a box <b>can easily take several hours</b>, most notably because installing OS updates is time-consuming. |
||||
|
</p> |
||||
|
</div> <!-- list --> |
||||
|
|
||||
|
<div class="list-group"> |
||||
|
<div class="d-flex w-100 justify-content-between"> |
||||
|
<h5 class="mb-1"><b>Incompatibilities</b></h5> |
||||
|
</div> |
||||
|
<p class="mb-1 list-group-item list-group-item-info"> |
||||
|
Beware of version incompatibilities of hypervisors. |
||||
|
<small class="text-left list-group-item list-group-item-info"> |
||||
|
For example a box built with VirtualBox 6.0 refusing to run on VirtualBox 5.<br> |
||||
|
</small> |
||||
|
If in doubt, deliberately use older hypervisor versions on the build machine. |
||||
|
</p> |
||||
|
</div> <!-- list --> |
||||
|
|
||||
|
<div class="list-group"> |
||||
|
<div class="d-flex w-100 justify-content-between"> |
||||
|
<h5 class="mb-1"><b>Output</b></h5> |
||||
|
</div> |
||||
|
<p class="mb-1 list-group-item list-group-item-success"> |
||||
|
The output of a successful build is a .box file. |
||||
|
</p> |
||||
|
</div> <!-- list --> |
||||
|
|
||||
|
<div class="list-group"> |
||||
|
<div class="d-flex w-100 justify-content-between"> |
||||
|
<h5 class="mb-1"><b>Install software</b></h5> |
||||
|
</div> |
||||
|
<p class="mb-1 list-group-item list-group-item-success"> |
||||
|
With ansible you can install additional software into the box, |
||||
|
</p> |
||||
|
</div> <!-- list --> |
||||
|
|
||||
|
|
||||
|
</div> <!-- col --> |
||||
|
</div> <!-- row --> |
||||
|
</b-container fluid> |
||||
|
` |
||||
|
this.$swal({ |
||||
|
type: 'info', |
||||
|
html: info, |
||||
|
showCloseButton: true, |
||||
|
showLoaderOnConfirm: false, |
||||
|
allowOutsideClick: false, |
||||
|
cancelButtonText: 'No, cancel!', |
||||
|
showCancelButton: true, |
||||
|
showLoaderOnConfirm: false, |
||||
|
reverseButtons: true, |
||||
|
focusCancel: false, |
||||
|
confirmButtonText: 'Create the box! ' |
||||
|
}).then((result)=> { |
||||
|
this.buildAndClose(result); |
||||
|
}) |
||||
|
|
||||
|
}else if(action == 'container-stop'){ |
||||
|
var obj = {} |
||||
|
obj.pid = this.buildpid |
||||
|
console.log('PID '+ this.buildpid) |
||||
|
this.$root.$emit('SERVER_build_kill',obj) |
||||
|
}else if(action == 'stop'){ |
||||
|
this.$socket.client.emit('stop', this.swarmlabname); |
||||
|
} |
||||
|
}, |
||||
|
async buildAndClose(result){ |
||||
|
var obj = {} |
||||
|
obj.name = this.hybridshowdata.name |
||||
|
obj.dir = this.hybridshowdata.dir |
||||
|
obj.config = this.hybridshowdata.config |
||||
|
console.log('value result '+ JSON.stringify(result)) |
||||
|
console.log('value obj '+ JSON.stringify(obj)) |
||||
|
if (result.isConfirmed) { |
||||
|
console.log('yes') |
||||
|
this.$root.$emit('SERVER_build_image',obj) |
||||
|
// run on mytable.vue |
||||
|
//refresh table |
||||
|
//this.$root.$emit('hybrid_stop_instance', value) |
||||
|
var info = ` |
||||
|
<b-container fluid> |
||||
|
<div class="row text-center"> |
||||
|
<div class="col-12"> |
||||
|
|
||||
|
<p class="mb-1 list-group-item list-group-item-success"> |
||||
|
You can track the pending box creation from the embeded console or the graphical interface that will open. |
||||
|
</p> |
||||
|
|
||||
|
<p class="mb-1 list-group-item list-group-item-info"> |
||||
|
There will also be a spinny wheel above the console indicating work in proccess. |
||||
|
</p> |
||||
|
|
||||
|
<p class="mb-1 list-group-item list-group-item-success"> |
||||
|
Please note that closing the window(graphical) WILL NOT terminate the process. |
||||
|
</p> |
||||
|
|
||||
|
<p class="mb-1 list-group-item list-group-item-info"> |
||||
|
If you wish to forcefully stop you should use the STOP button. |
||||
|
</p> |
||||
|
|
||||
|
<p class="mb-1 list-group-item list-group-item-success"> |
||||
|
Note that the stop operation itself may take a little time. |
||||
|
</p> |
||||
|
|
||||
|
<p class="mb-1 list-group-item list-group-item-light"> |
||||
|
When the proccess is done you should see something like this: |
||||
|
|
||||
|
<br> |
||||
|
==> Builds finished. The artifacts of successful builds are: |
||||
|
<br> |
||||
|
--> virtualbox-iso: 'virtualbox' provider box: ../../builds/ubuntu-18.04.virtualbox.box |
||||
|
<br> |
||||
|
Build 'virtualbox-iso' finished after 1 hour 30 minutes 28 seconds |
||||
|
</p> |
||||
|
|
||||
|
|
||||
|
</div> <!-- col --> |
||||
|
</div> <!-- row --> |
||||
|
</b-container fluid> |
||||
|
` |
||||
|
this.$swal({ |
||||
|
type: 'info', |
||||
|
html: info, |
||||
|
icon: 'info', |
||||
|
showCloseButton: true, |
||||
|
showLoaderOnConfirm: false, |
||||
|
allowOutsideClick: false, |
||||
|
cancelButtonText: 'No, cancel!', |
||||
|
showCancelButton: false, |
||||
|
showLoaderOnConfirm: false, |
||||
|
reverseButtons: true, |
||||
|
focusCancel: false, |
||||
|
confirmButtonText: 'ok! ' |
||||
|
}) |
||||
|
}else { |
||||
|
console.log('no') |
||||
|
} |
||||
|
}, |
||||
|
}, |
||||
|
|
||||
|
|
||||
|
actions: { |
||||
|
|
||||
|
} |
||||
|
|
||||
|
}; |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss"> |
||||
|
|
||||
|
|
||||
|
|
||||
|
.flex-fixed-width-item { |
||||
|
flex: 0 0 100px; |
||||
|
} |
||||
|
.modalinfo { |
||||
|
z-index: 10000000 !important; |
||||
|
position:fixed; |
||||
|
} |
||||
|
/* a container with flex-direction column */ |
||||
|
|
||||
|
.vue-notifyjs.notifications{ |
||||
|
.alert{ |
||||
|
z-index: 100; |
||||
|
} |
||||
|
.list-move { |
||||
|
transition: transform 0.3s, opacity 0.4s; |
||||
|
} |
||||
|
.list-item { |
||||
|
display: inline-block; |
||||
|
margin-right: 10px; |
||||
|
|
||||
|
} |
||||
|
.list-enter-active { |
||||
|
transition: transform 0.2s ease-in, opacity 0.4s ease-in; |
||||
|
} |
||||
|
.list-leave-active { |
||||
|
transition: transform 1s ease-out, opacity 0.4s ease-out; |
||||
|
} |
||||
|
|
||||
|
.list-enter { |
||||
|
opacity: 0; |
||||
|
transform: scale(1.1); |
||||
|
|
||||
|
} |
||||
|
.list-leave-to { |
||||
|
opacity: 0; |
||||
|
transform: scale(1.2, 0.7); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
pre { |
||||
|
//background-color: rgb(255, 247, 229); |
||||
|
background-color: #eff0f1; |
||||
|
border: 1px solid blue; |
||||
|
//white-space: pre-line; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
</style> |
Loading…
Reference in new issue