diff --git a/client/src/views/Clone/List/ListClones.js b/client/src/views/Clone/List/ListClones.js
index 3dcfeda24..433890125 100644
--- a/client/src/views/Clone/List/ListClones.js
+++ b/client/src/views/Clone/List/ListClones.js
@@ -88,7 +88,7 @@ class ListClones extends Component {
Last Execution:
- { (clone.kind === 'TRADER') &&
+ { (clone.kind === 'TRADER' && isDefined(clone.assetA) ) &&
Buy Average:
Sell Average:
@@ -100,7 +100,7 @@ class ListClones extends Component {
{isDefined(clone.summaryDate) ? toLocalTime(clone.summaryDate): 'waiting update...'}
- { (clone.kind === 'INDICATOR' || clone.kind === 'EXTRACTOR') &&
+ { ((clone.kind === 'INDICATOR' || clone.kind === 'EXTRACTOR') && isDefined(clone.assetA) ) &&
{clone.buyAverage}
{clone.sellAverage}
@@ -188,19 +188,23 @@ class ListClones extends Component {
Last clone logs
-
+
+ Here you can check the clone output directly from the virtual machine.
+ The last 20 lines are displayed, but you can check the Logs Module for more details.
+
+
+
+
({
marginRight: theme.spacing.unit,
},
textArea: {
+ width:'1750px',
marginLeft: theme.spacing.unit,
marginRight: theme.spacing.unit,
whiteSpace: 'pre',
- overflowY:'auto',
- overflowX:'hidden'
},
heading: {
fontSize: theme.typography.pxToRem(18),
@@ -52,10 +51,13 @@ const styles = theme => ({
padding: `0px ${theme.spacing.unit * 2}px`,
},
logsDialog:{
- width:'1750px',
- overflowY:'auto',
+ overflowY:'hidden',
overflowX:'hidden'
},
+ logsWrapper:{
+ overflowY:'auto',
+ overflowX:'auto'
+ },
details:{
display:'flex'
},
diff --git a/server/src/kubernetes/getClonePodLogs.js b/server/src/kubernetes/getClonePodLogs.js
index af6c3c134..9730f300c 100644
--- a/server/src/kubernetes/getClonePodLogs.js
+++ b/server/src/kubernetes/getClonePodLogs.js
@@ -2,9 +2,9 @@ import logger from '../config/logger'
import { KubernateError } from '../errors'
import { Client, config } from 'kubernetes-client'
-const getClonePodStatus = async (cloneName) => {
+const getClonePodLogs = async (cloneName) => {
try {
- logger.debug("getClonePodStatus on kubernates started.")
+ logger.debug("getClonePodLogs on kubernates started.")
const client = new Client({config: config.fromKubeconfig(), version: '1.9'})
let query = {
@@ -12,23 +12,23 @@ const getClonePodStatus = async (cloneName) => {
"labelSelector": "job-name="+cloneName
}
}
-
+
const pod = await client.api.v1.namespaces('default').pods.get(query)
let queryLogs = {
"qs":{
- "tailLines": "15"
+ "tailLines": "20"
}
}
const logs = await client.api.v1.namespaces('default')
.pods(pod.body.items[0].metadata.name).log.get(queryLogs)
let logsArray = logs.body.split('\n')
- logger.debug("getClonePodStatus on kubernates successful.")
+ logger.debug("getClonePodLogs on kubernates successful.")
return JSON.stringify(logsArray, null, 2)
} catch (err) {
throw new KubernateError(err)
}
}
-export default getClonePodStatus
+export default getClonePodLogs
diff --git a/server/src/kubernetes/removeClone.js b/server/src/kubernetes/removeClone.js
index 536eac16a..2ec404572 100644
--- a/server/src/kubernetes/removeClone.js
+++ b/server/src/kubernetes/removeClone.js
@@ -1,9 +1,11 @@
import logger from '../config/logger'
import { KubernateError } from '../errors'
import { Client, config } from 'kubernetes-client'
+import { getJobNameFromClone } from '../config/utils'
-const removeClone = async (cloneName) => {
+const removeClone = async (clone, teamSlug, botSlug) => {
try {
+ let cloneName = getJobNameFromClone(teamSlug, botSlug, clone.mode)
logger.info("removeClone %s", cloneName)
const client = new Client({config: config.fromKubeconfig(), version: '1.9'})
@@ -15,7 +17,7 @@ const removeClone = async (cloneName) => {
const removed = await client.apis.batch.v1.namespaces('default').jobs(
cloneName).delete()
-
+
const pod = await client.api.v1.namespaces('default').pods.get(query)
const podRemoved = await client.api.v1.namespaces('default')
.pods(pod.body.items[0].metadata.name).delete()
diff --git a/server/src/schema/mutations/AddCloneMutation.js b/server/src/schema/mutations/AddCloneMutation.js
index 47577519f..5aceb940b 100644
--- a/server/src/schema/mutations/AddCloneMutation.js
+++ b/server/src/schema/mutations/AddCloneMutation.js
@@ -45,8 +45,8 @@ const resolve = async(parent, { clone }, context) => {
}
try{
+ // Authorization is handled by the teams module
let botsByUser = await teams_FbByTeamMember(context.authorization)
- console.log("botsByUser: ", botsByUser)
let selectedBot = getSelectedBot(botsByUser.data.data.teams_FbByTeamMember, clone.botId)
clone.teamId = botsByUser.data.data.teams_FbByTeamMember.id
clone.botId = selectedBot.id
diff --git a/server/src/schema/mutations/RemoveCloneMutation.js b/server/src/schema/mutations/RemoveCloneMutation.js
index 88152cf54..dcd51faae 100644
--- a/server/src/schema/mutations/RemoveCloneMutation.js
+++ b/server/src/schema/mutations/RemoveCloneMutation.js
@@ -12,6 +12,8 @@ import {
import { Clone } from '../../models'
import logger from '../../config/logger'
import removeKuberneteClone from '../../kubernetes/removeClone'
+import teams_FbByTeamMember from '../../graphQLCalls/teams_FbByTeamMember'
+import { isDefined, getSelectedBot } from '../../config/utils'
const args = {
id: { type: new GraphQLNonNull(GraphQLID) }
@@ -24,7 +26,22 @@ const resolve = async (parent, { id }, context) => {
throw new AuthentificationError()
}
- await removeKuberneteClone(id)
+ let clone = await Clone.findOne({
+ _id: id,
+ authId: context.userId,
+ active: true
+ })
+
+ if(!isDefined(clone)){
+ throw new CustomError('You are not authorized to remove this clone.')
+ }
+
+ // Authorization is also handled by the teams module
+ let botsByUser = await teams_FbByTeamMember(context.authorization)
+ let selectedBot = getSelectedBot(botsByUser.data.data.teams_FbByTeamMember, clone.botId)
+
+ logger.debug('removeClone -> Removing Clone from Kubernates.')
+ await removeKuberneteClone(clone, botsByUser.data.data.teams_FbByTeamMember.slug, selectedBot.slug)
const query = {
_id: id,
@@ -33,12 +50,13 @@ const resolve = async (parent, { id }, context) => {
const options = { new: true }
const update = { active: false }
- logger.debug('removeClone -> Removing Clone from DB.')
Clone.findOneAndUpdate(query, update, options, (err, doc) => {
if (err){
+ logger.error('removeClone -> Error removing clone from the DB. %s', err.stack)
throw new OperationsError(err)
}else{
- resolve('Clone Removed.')
+ logger.debug('removeClone -> Clone Removed from the DB.')
+ return('Clone Removed.')
}
})
}
diff --git a/server/src/schema/queries/HistoryClones.js b/server/src/schema/queries/HistoryClones.js
index e413997ec..5c20df2bb 100644
--- a/server/src/schema/queries/HistoryClones.js
+++ b/server/src/schema/queries/HistoryClones.js
@@ -11,6 +11,8 @@ import { Clone } from '../../models'
import logger from '../../config/logger'
import getKuberneteClonePodStatus from '../../kubernetes/getClonePodStatus'
import getKuberneteClonePodLogs from '../../kubernetes/getClonePodLogs'
+import teams_FbByTeamMember from '../../graphQLCalls/teams_FbByTeamMember'
+import cloneDetails from './cloneDetails'
const args = {}
@@ -26,6 +28,14 @@ const resolve = async(parent, args, context) => {
active: false
})
+ // TODO Refactor this code once financial beings api is ready
+ // Authorization is handled by the teams module
+ let botsByUser = await teams_FbByTeamMember(context.authorization)
+
+ for (var i = 0; i < clones.length; i++) {
+ clones[i] = await cloneDetails(context.authorization, botsByUser, clones[i])
+ }
+
return clones
}
diff --git a/server/src/schema/queries/ListClones.js b/server/src/schema/queries/ListClones.js
index 5a1292e56..c6cbe9500 100644
--- a/server/src/schema/queries/ListClones.js
+++ b/server/src/schema/queries/ListClones.js
@@ -12,9 +12,8 @@ import { Clone } from '../../models'
import logger from '../../config/logger'
import getCloneStatus from '../../kubernetes/getClonePodStatus'
import getCloneLogs from '../../kubernetes/getClonePodLogs'
-import { getJobNameFromClone, getSelectedBot } from '../../config/utils'
import teams_FbByTeamMember from '../../graphQLCalls/teams_FbByTeamMember'
-import teamAvatar from '../../graphQLCalls/teamAvatar'
+import cloneDetails from './cloneDetails'
const args = {}
@@ -30,24 +29,16 @@ const resolve = async(parent, args, context) => {
active: true
})
+ // TODO Refactor this code once financial beings api is ready
+ // Authorization is handled by the teams module
let botsByUser = await teams_FbByTeamMember(context.authorization)
for (var i = 0; i < clones.length; i++) {
- logger.debug('List Clones -> clone: %j', clones[i])
-
- // TODO Refactor this code once financial beings api is ready
- let selectedBot = getSelectedBot(botsByUser.data.data.teams_FbByTeamMember, clones[i].botId)
- let cloneName = getJobNameFromClone(botsByUser.data.data.teams_FbByTeamMember.slug, selectedBot.slug, clones[i].mode)
- clones[i].kind = selectedBot.kind
- clones[i].teamName = botsByUser.data.data.teams_FbByTeamMember.name
- clones[i].botName = selectedBot.name
- clones[i].botAvatar = selectedBot.avatar
-
- let team = await teamAvatar(context.authorization, botsByUser.data.data.teams_FbByTeamMember.id)
- clones[i].teamAvatar = team.data.data.teams_TeamById.profile.avatar
-
- clones[i].state = await getCloneStatus(cloneName)
- clones[i].lastLogs = await getCloneLogs(cloneName)
+ clones[i] = await cloneDetails(context.authorization, botsByUser, clones[i])
+ let state = await getCloneStatus(clones[i].cloneName)
+ clones[i].state = state.substring(1, state.length-1)
+ let lastLogs = await getCloneLogs(clones[i].cloneName)
+ clones[i].lastLogs = lastLogs.substring(1, lastLogs.length-1)
}
return clones
} catch (err){
diff --git a/server/src/schema/queries/cloneDetails.js b/server/src/schema/queries/cloneDetails.js
new file mode 100644
index 000000000..06c3ed99c
--- /dev/null
+++ b/server/src/schema/queries/cloneDetails.js
@@ -0,0 +1,21 @@
+import logger from '../../config/logger'
+import { getJobNameFromClone, getSelectedBot } from '../../config/utils'
+import teamAvatar from '../../graphQLCalls/teamAvatar'
+
+const cloneDetails = async(authorization, botsByUser, clone) => {
+ logger.debug('Retrieving clone details.')
+ // TODO Refactor this code once financial beings api is ready
+ let selectedBot = getSelectedBot(botsByUser.data.data.teams_FbByTeamMember, clone.botId)
+ clone.cloneName = getJobNameFromClone(botsByUser.data.data.teams_FbByTeamMember.slug, selectedBot.slug, clone.mode)
+ clone.kind = selectedBot.kind
+ clone.teamName = botsByUser.data.data.teams_FbByTeamMember.name
+ clone.botName = selectedBot.name
+ clone.botAvatar = selectedBot.avatar
+
+ let team = await teamAvatar(authorization, botsByUser.data.data.teams_FbByTeamMember.id)
+ clone.teamAvatar = team.data.data.teams_TeamById.profile.avatar
+ logger.debug('Retrieving clone details complete.')
+ return clone
+};
+
+export default cloneDetails