asimov-deploy-ui
Advanced tools
Comparing version 0.8.7 to 0.9.0
@@ -29,3 +29,6 @@ /******************************************************************************* | ||
name: agent.name, | ||
group: agent.group, | ||
agentGroup: agent.group, | ||
unitGroup: agent.unitGroup, | ||
unitType: agent.unitTypes, | ||
tags: agent.tags, | ||
dead: agent.dead, | ||
@@ -62,5 +65,6 @@ version: agent.version, | ||
app.post("/agent/heartbeat", function(req,res) { | ||
var existing = true; | ||
var agent = config.getAgentByGroup(req.body.name, req.body.group); | ||
if (!agent) { | ||
existing = false; | ||
agent = { | ||
@@ -70,3 +74,4 @@ name: req.body.name, | ||
}; | ||
config.agents.push(agent); | ||
config.registerAgent(agent); | ||
} | ||
@@ -82,4 +87,25 @@ | ||
handleNewLoadBalancerState(agent, req.body.loadBalancerState); | ||
res.json('ok'); | ||
if (!existing) { | ||
agentApiClient.getAgentUnitGroups(agent.name, function (unitGroups) { | ||
config.addUnitGroups(unitGroups); | ||
agentApiClient.getAgentUnitTypes(agent.name, function (unitTypes) { | ||
config.addUnitTypes(unitTypes); | ||
agentApiClient.getAgentUnitTags(agent.name, function (unitTags) { | ||
config.addUnitTags(unitTags); | ||
agentApiClient.getAgentUnitStatuses(agent.name, function (unitStatuses) { | ||
config.addUnitStatuses(unitStatuses); | ||
res.json('ok'); | ||
}); | ||
}); | ||
}); | ||
}); | ||
} | ||
else { | ||
res.json('ok'); | ||
} | ||
}); | ||
@@ -86,0 +112,0 @@ |
@@ -29,3 +29,3 @@ /******************************************************************************* | ||
when(_getUnitListForAgentGroup()).then(function (agents) { | ||
when(_getUnits()).then(function (agents) { | ||
var agentUnits = _.flatten(_.map(agents, function (agent) { | ||
@@ -83,6 +83,6 @@ var result = []; | ||
var _getUnitListForAgentGroup = function () { | ||
var _getUnits = function () { | ||
var deferred = when.defer(); | ||
agentApiClient.getUnitListForAgentGroup(null, function (results) { | ||
agentApiClient.getUnits(null, function (results) { | ||
var agents = []; | ||
@@ -89,0 +89,0 @@ |
@@ -24,2 +24,7 @@ /******************************************************************************* | ||
this.agents = []; | ||
this.agentGroups = []; | ||
this.unitGroups = []; | ||
this.unitTypes = []; | ||
this.unitTags = []; | ||
this.unitStatuses = []; | ||
} | ||
@@ -58,2 +63,7 @@ | ||
Config.prototype.registerAgent = function (agent) { | ||
this.agents.push(agent); | ||
this.addAgentGroup(agent.group); | ||
}; | ||
Config.prototype.getAgent = function(name) { | ||
@@ -83,4 +93,90 @@ return _.find(this.agents, function(agent) { return agent.name === name; }); | ||
Config.prototype.addAgentGroup = function (agentGroup) { | ||
var existing = _.find(this.agentGroups, function (g) { | ||
return g === agentGroup; | ||
}); | ||
if (!existing) { | ||
this.agentGroups.push(agentGroup); | ||
} | ||
}; | ||
Config.prototype.getAgentGroups = function () { | ||
return _.sortBy(this.agentGroups, function (value) { return value; }); | ||
}; | ||
Config.prototype.addUnitGroups = function (unitGroups) { | ||
unitGroups = unitGroups || []; | ||
unitGroups.forEach(function (unitGroup) { | ||
var existing = _.find(this.unitGroups, function (g) { | ||
return g === unitGroup; | ||
}); | ||
if (!existing) { | ||
this.unitGroups.push(unitGroup); | ||
} | ||
}, this); | ||
}; | ||
Config.prototype.getUnitGroups = function () { | ||
return _.sortBy(this.unitGroups, function (value) { return value; }); | ||
}; | ||
Config.prototype.addUnitTypes = function (unitTypes) { | ||
unitTypes = unitTypes || []; | ||
unitTypes.forEach(function (unitType) { | ||
var existing = _.find(this.unitTypes, function (u) { | ||
return u === unitType; | ||
}); | ||
if (!existing) { | ||
this.unitTypes.push(unitType); | ||
} | ||
}, this); | ||
}; | ||
Config.prototype.getUnitTypes = function () { | ||
return _.sortBy(this.unitTypes, function (value) { return value; }); | ||
}; | ||
Config.prototype.addUnitTags = function (tags) { | ||
tags = tags || []; | ||
tags.forEach(function (tag) { | ||
var existing = _.find(this.unitTags, function (t) { | ||
return t === tag; | ||
}); | ||
if (!existing) { | ||
this.unitTags.push(tag); | ||
} | ||
}, this); | ||
}; | ||
Config.prototype.getUnitTags = function () { | ||
return _.sortBy(this.unitTags, function (value) { return value; }); | ||
}; | ||
Config.prototype.addUnitStatuses = function (unitStatuses) { | ||
unitStatuses = unitStatuses || []; | ||
unitStatuses.forEach(function (unitStatus) { | ||
var existing = _.find(this.unitStatuses, function (s) { | ||
return s === unitStatus; | ||
}); | ||
if (!existing) { | ||
this.unitStatuses.push(unitStatus); | ||
} | ||
}, this); | ||
}; | ||
Config.prototype.getUnitStatuses = function () { | ||
return _.sortBy(this.unitStatuses, function (value) { return value; }); | ||
}; | ||
module.exports = { | ||
Config: Config | ||
}; |
@@ -17,218 +17,467 @@ /******************************************************************************* | ||
var _ = require('underscore'); | ||
var utils = require('./demo-utils'); | ||
var agents = []; | ||
var units = []; | ||
var versions = {}; | ||
var registerWebfrontAgents = function (config) { | ||
for (var i = 1; i <= 5; i++) { | ||
var agent = { | ||
name: "SE1-WEBFRONT-0" + i, | ||
group: 'Web servers', | ||
dead: false, | ||
version: "0.6.12", | ||
configVersion: 43, | ||
loadBalancerState: { | ||
enabled: true, | ||
connectionCount: Math.floor((Math.random()*580)), | ||
serverId: "SE1-WEBFRONT-0" + i | ||
} | ||
}; | ||
for(var i = 1; i <= 5; i++) { | ||
agents.push({ | ||
name: "SE1-WEBFRONT-0" + i, | ||
group: 'Web servers', | ||
dead: false, | ||
version: "0.6.12", | ||
configVersion: 43, | ||
loadBalancerState: { | ||
enabled: true, | ||
connectionCount: Math.floor((Math.random()*580)), | ||
serverId: "SE1-WEBFRONT-0" + i | ||
} | ||
}); | ||
} | ||
config.registerAgent(agent); | ||
} | ||
}; | ||
for(var i = 1; i <= 3; i++) { | ||
agents.push({ | ||
name: "SE1-APPSRV-0" + i, | ||
group: 'Application servers', | ||
dead: false, | ||
version: "0.6.12", | ||
configVersion: 43, | ||
loadBalancerState: { | ||
enabled: true, | ||
connectionCount: Math.floor((Math.random()*580)), | ||
serverId: "SE1-APPSRV-0" + i | ||
var registerAppServerAgents = function (config) { | ||
for (var i = 1; i <= 5; i++) { | ||
var agent = { | ||
name: "SE1-APPSRV-0" + i, | ||
group: 'Application servers', | ||
dead: false, | ||
version: "0.6.12", | ||
configVersion: 43, | ||
loadBalancerState: { | ||
enabled: true, | ||
connectionCount: Math.floor((Math.random()*580)), | ||
serverId: "SE1-APPSRV-0" + i | ||
} | ||
}; | ||
config.registerAgent(agent); | ||
} | ||
}; | ||
var registerUnits = function (config) { | ||
var units = []; | ||
config.agents.forEach(function (agent) { | ||
if (agent.name.indexOf('WEBFRONT') !== -1) { | ||
units.push({ | ||
name: agent.name, | ||
group: agent.group, | ||
loadBalancerState: agent.loadBalancerState, | ||
units: [ | ||
{ | ||
name: 'asimov-demo.com', | ||
group: 'Webfront', | ||
type: 'WebSite', | ||
tags: [ 'host:' + agent.name, 'os:Windows' ], | ||
url: 'http://' + agent.name + '.prod.asimov-demo.com', | ||
version: '7.1.0', | ||
branch: 'master', | ||
status: 'Running', | ||
lastDeployed: 'Deployed 1 hour ago', | ||
hasDeployParameters: false, | ||
actions: [ | ||
'Verify', | ||
'Start', | ||
'Stop' | ||
] | ||
}, | ||
{ | ||
name: 'api.asimov-demo.com', | ||
group: 'Webfront', | ||
type: 'WebSite', | ||
tags: [ 'host:' + agent.name, 'os:Windows' ], | ||
url: 'http://' + agent.name + '.prod.api.asimov-demo.com', | ||
version: '3.0.0', | ||
branch: 'master', | ||
status: 'Running', | ||
lastDeployed: 'Deployed 2 days ago', | ||
hasDeployParameters: false, | ||
actions: [ | ||
'Verify', | ||
'Start', | ||
'Stop' | ||
] | ||
} | ||
] | ||
}); | ||
} | ||
if (agent.name.indexOf('SE1-APPSRV') !== -1) { | ||
units.push({ | ||
name: agent.name, | ||
group: agent.group, | ||
loadBalancerId: agent.loadBalancerId, | ||
loadBalancerState: agent.loadBalancerState, | ||
units: [ | ||
{ | ||
name: 'backend.queue-handler', | ||
group: 'Backend', | ||
type: 'WindowsService', | ||
tags: [ 'host:' + agent.name, 'os:Linux' ], | ||
version: '2.1.0', | ||
branch: 'master', | ||
status: 'Running', | ||
lastDeployed: 'Deployed 10 days ago', | ||
hasDeployParameters: false, | ||
actions: [ | ||
'Start', | ||
'Stop' | ||
] | ||
}, | ||
{ | ||
name: 'backend.member-notification', | ||
group: 'Backend', | ||
type: 'WindowsService', | ||
tags: [ 'host:' + agent.name, 'os:Linux' ], | ||
version: '2.1.0', | ||
branch: 'master', | ||
status: 'Running', | ||
lastDeployed: 'Deployed 2 days ago', | ||
hasDeployParameters: false, | ||
actions: [ | ||
'Start', | ||
'Stop' | ||
] | ||
} | ||
] | ||
}); | ||
} | ||
units.forEach(function (agentUnits) { | ||
config.addUnitGroups(_.pluck(agentUnits.units, 'group')); | ||
config.addUnitTypes(_.pluck(agentUnits.units, 'type')); | ||
config.addUnitTags(_.flatten(_.map(agentUnits.units, function (u) { | ||
return u.tags; | ||
}))); | ||
}); | ||
}); | ||
} | ||
agents.forEach(function(agent) { | ||
config.addUnitStatuses([ | ||
'DeployFailed', | ||
'Deploying', | ||
'NA', | ||
'NotFound', | ||
'Running', | ||
'Starting', | ||
'Stopped', | ||
'Stopping' | ||
]); | ||
if (agent.name.indexOf('WEBFRONT') !== -1) { | ||
units.push({ | ||
name: agent.name, | ||
group: agent.group, | ||
loadBalancerState: agent.loadBalancerState, | ||
units: [ | ||
{ | ||
name: 'asimov-demo.com', | ||
url: 'http://' + agent.name + '.prod.asimov-demo.com', | ||
version: '7.1.0', | ||
branch: 'master', | ||
status: 'Running', | ||
lastDeployed: 'Deployed 1 hour ago', | ||
hasDeployParameters: false, | ||
actions: [ | ||
'Verify', | ||
'Start', | ||
'Stop' | ||
] | ||
}, | ||
{ | ||
name: 'api.asimov-demo.com', | ||
url: 'http://' + agent.name + '.prod.api.asimov-demo.com', | ||
version: '3.0.0', | ||
branch: 'master', | ||
status: 'Running', | ||
lastDeployed: 'Deployed 2 days ago', | ||
hasDeployParameters: false, | ||
actions: [ | ||
'Verify', | ||
'Start', | ||
'Stop' | ||
] | ||
return units; | ||
}; | ||
var DemodataGenerator = function (config) { | ||
registerWebfrontAgents(config); | ||
registerAppServerAgents(config); | ||
var units = registerUnits(config); | ||
var versions = {}; | ||
versions["asimov-demo.com"] = [ | ||
{ "version": "7.1.0", "timestamp": "2013-06-28 16:26:11", "branch": "master", "commit": "14cbf27", "id": "mykillerapp-v7.1.0-[master]-[14cbf27].prod.zip" }, | ||
{ "version": "6.9.0", "timestamp": "2013-06-25 16:26:11", "branch": "master", "commit": "14cbf25", "id": "mykillerapp-v6.9.0-[master]-[14cbf25].prod.zip" }, | ||
{ "version": "6.8.0", "timestamp": "2013-06-24 15:26:11", "branch": "master", "commit": "14cbf25", "id": "mykillerapp-v6.8.0-[master]-[14cbf25].prod.zip" }, | ||
{ "version": "6.7.0", "timestamp": "2013-06-24 15:26:11", "branch": "my-new-feature", "commit": "14cbf25", "id": "mykillerapp-v6.7.0-[master]-[14cbf25].prod.zip" }, | ||
{ "version": "5.0.0", "timestamp": "2013-06-24 15:26:11", "branch": "master", "commit": "14cbf25", "id": "mykillerapp-v5.0.0-[master]-[14cbf25].prod.zip" } | ||
]; | ||
versions["api.asimov-demo.com"] = [ | ||
{ "version": "3.0.0", "timestamp": "2013-06-28 16:26:11", "branch": "master", "commit": "14cbf27", "id": "mykillerapp-v3.0.0-[master]-[14cbf27].prod.zip" }, | ||
{ "version": "2.9.0", "timestamp": "2013-06-25 16:26:11", "branch": "master", "commit": "14cbf25", "id": "mykillerapp-v2.9.0-[master]-[14cbf25].prod.zip" }, | ||
{ "version": "2.8.0", "timestamp": "2013-06-24 15:26:11", "branch": "master", "commit": "14cbf25", "id": "mykillerapp-v2.8.0-[master]-[14cbf25].prod.zip" }, | ||
{ "version": "2.7.0", "timestamp": "2013-06-24 15:26:11", "branch": "my-new-feature", "commit": "14cbf25", "id": "mykillerapp-v2.7.0-[master]-[14cbf25].prod.zip" }, | ||
{ "version": "1.5.0", "timestamp": "2013-06-24 15:26:11", "branch": "master", "commit": "14cbf25", "id": "mykillerapp-v1.5.0-[master]-[14cbf25].prod.zip" } | ||
]; | ||
versions["backend.queue-handler"] = versions["backend.member-notification"] = [ | ||
{ "version": "2.1.0", "timestamp": "2013-06-28 16:26:11", "branch": "master", "commit": "14cbf27", "id": "mykillerapp-v3.0.0-[master]-[14cbf27].prod.zip" }, | ||
{ "version": "2.0.0", "timestamp": "2013-06-25 16:26:11", "branch": "develop", "commit": "14cbf25", "id": "mykillerapp-v2.9.0-[master]-[14cbf25].prod.zip" }, | ||
{ "version": "1.8.0", "timestamp": "2013-06-23 15:26:11", "branch": "master", "commit": "14cbf25", "id": "mykillerapp-v2.8.0-[master]-[14cbf25].prod.zip" }, | ||
{ "version": "1.7.0", "timestamp": "2013-06-20 13:26:11", "branch": "my-new-feature", "commit": "14cbf25", "id": "mykillerapp-v2.7.0-[master]-[14cbf25].prod.zip" }, | ||
{ "version": "1.5.0", "timestamp": "2013-06-21 12:26:11", "branch": "poc", "commit": "14cbf25", "id": "mykillerapp-v1.5.0-[master]-[14cbf25].prod.zip" } | ||
]; | ||
var deployLog = [ | ||
{ timestamp: "2013-06-14 16:25:11", username: "BlameMe", version: "2.1.0", branch: "master", commit: "14cbf27", status: "Success" }, | ||
{ timestamp: "2013-06-13 12:21:11", username: "Torkel Ödegaard", version: "2.0.0", branch: "master", commit: "14cbf27", status: "Success" }, | ||
{ timestamp: "2013-06-12 11:21:11", username: "Test User", version: "1.8.0", branch: "uber-feature", commit: "14cbf27", status: "DeployFailed" }, | ||
{ timestamp: "2013-06-10 07:25:11", username: "Test User", version: "1.6.0", branch: "master", commit: "14cbf27", status: "Success" }, | ||
{ timestamp: "2013-06-10 07:15:01", username: "Demo User", version: "1.1.0", branch: "develop", commit: "14cbf27", status: "Success" } | ||
]; | ||
var autopilot = { | ||
preferredBranch: 'master', | ||
deployableUnitSets: [ | ||
{ | ||
"id": "api_asimov_demo_com", | ||
"name": "Api", | ||
"description": "Automatic deploy of api.asimov-demo.com", | ||
"units": [ "api.asimov-demo.com" ], | ||
"defaultDeployToMaximumAgentsSimultaneously": 2, | ||
"defaultVerificationIterationCount": 1, | ||
"verificationSteps": [ "DisableLoadBalancerForAgents", "Deploy", "Verify", "Prompt", "EnableLoadBalancerForAgents" ], | ||
"steps": [ "DisableLoadBalancerForAgents", "Deploy", "Verify", "EnableLoadBalancerForAgents" ] | ||
}, | ||
{ | ||
"id": "asimov_demo_com", | ||
"name": "Site", | ||
"description": "Automatic deploy of asimov-demo.com", | ||
"units": [ "asimov-demo.com" ], | ||
"defaultDeployToMaximumAgentsSimultaneously": 2, | ||
"defaultVerificationIterationCount": 1, | ||
"verificationSteps": [ "DisableLoadBalancerForAgents", "Deploy", "Prompt", "EnableLoadBalancerForAgents" ], | ||
"steps": [ "DisableLoadBalancerForAgents", "Deploy", "EnableLoadBalancerForAgents" ] | ||
}, | ||
{ | ||
"id": "api_asimov_demo_com_and_asimov_demo_com", | ||
"name": "Api + Site", | ||
"description": "Automatic deploy of api.asimov-demo.com and asimov-demo.com", | ||
"units": [ "asimov-demo.com", "api.asimov-demo.com" ], | ||
"defaultDeployToMaximumAgentsSimultaneously": 2, | ||
"defaultVerificationIterationCount": 1, | ||
"verificationSteps": [ "DisableLoadBalancerForAgents", "Deploy", "Prompt", "EnableLoadBalancerForAgents" ], | ||
"steps": [ "DisableLoadBalancerForAgents", "Deploy", "EnableLoadBalancerForAgents" ] | ||
}, | ||
{ | ||
"id": "backend_member_notification", | ||
"name": "Member Notification", | ||
"description": "Automatic deploy of backend.member-notification", | ||
"units": [ "backend.member-notification" ], | ||
"defaultDeployToMaximumAgentsSimultaneously": 1, | ||
"defaultVerificationIterationCount": 1, | ||
"verificationSteps": [ "Deploy", "Prompt" ], | ||
"steps": [ "Deploy" ] | ||
}, | ||
{ | ||
"id": "backend_queue_handler", | ||
"name": "Queue Handler", | ||
"description": "Automatic deploy of backend.queue-handler", | ||
"units": [ "backend.queue-handler" ], | ||
"defaultDeployToMaximumAgentsSimultaneously": 1, | ||
"defaultVerificationIterationCount": 1, | ||
"verificationSteps": [ "Deploy", "Prompt" ], | ||
"steps": [ "Deploy" ] | ||
}, | ||
{ | ||
"id": "backend_member_notification_and_backend_queue_handler", | ||
"name": "Member Notification + Queue Handler", | ||
"description": "Automatic deploy of backend.member-notification and backend.queue-handler", | ||
"units": [ "backend.member-notification", "backend.queue-handler" ], | ||
"defaultDeployToMaximumAgentsSimultaneously": 1, | ||
"defaultVerificationIterationCount": 1, | ||
"verificationSteps": [ "Deploy", "Prompt" ], | ||
"steps": [ "Deploy" ] | ||
} | ||
] | ||
}; | ||
var _getUnits = function (filters) { | ||
/*jshint maxcomplexity:7 */ | ||
var unitsByAgentGroup = utils.getUnitsByAgentGroup(units); | ||
var unitsByUnitGroup = utils.getUnitsByUnitGroup(units); | ||
var unitsByUnitType = utils.getUnitsByUnitType(units); | ||
var unitsByUnitStatus = utils.getUnitsByUnitStatus(units); | ||
var unitsByTags = utils.getUnitsByTags(units); | ||
var unitList = _ | ||
.chain(units) | ||
.map(function (agentUnits) { | ||
return _.map(agentUnits.units, function (u) { | ||
return { | ||
agentName: agentUnits.name, | ||
unitName: u.name | ||
}; | ||
}); | ||
}) | ||
.flatten() | ||
.sortBy('unitName') | ||
.value(); | ||
var filteredUnits = unitList; | ||
var filteredByAgentGroups = []; | ||
if (filters.agentGroups) { | ||
_.each(filters.agentGroups, function (g) { | ||
if (unitsByAgentGroup[g]) { | ||
filteredByAgentGroups.push(unitsByAgentGroup[g]); | ||
} | ||
] | ||
}); | ||
} | ||
}); | ||
if (agent.name.indexOf('SE1-APPSRV') !== -1) { | ||
units.push({ | ||
name: agent.name, | ||
group: agent.group, | ||
loadBalancerId: agent.loadBalancerId, | ||
loadBalancerState: agent.loadBalancerState, | ||
units: [ | ||
{ | ||
name: 'backend.queue-handler', | ||
version: '2.1.0', | ||
branch: 'master', | ||
status: 'Running', | ||
lastDeployed: 'Deployed 10 days ago', | ||
hasDeployParameters: false, | ||
actions: [ | ||
'Start', | ||
'Stop' | ||
] | ||
}, | ||
{ | ||
name: 'backend.member-notification', | ||
version: '2.1.0', | ||
branch: 'master', | ||
status: 'Running', | ||
lastDeployed: 'Deployed 2 days ago', | ||
hasDeployParameters: false, | ||
actions: [ | ||
'Start', | ||
'Stop' | ||
] | ||
filteredByAgentGroups = _.flatten(filteredByAgentGroups); | ||
filteredUnits = utils.intersectionObjects(filteredUnits, filteredByAgentGroups, function (item1, item2) { | ||
return item1.unitName === item2.unitName && | ||
item1.agentName === item2.agentName; | ||
}); | ||
} | ||
var filteredByUnitGroups = []; | ||
if (filters.unitGroups) { | ||
_.each(filters.unitGroups, function (g) { | ||
if (unitsByUnitGroup[g]) { | ||
filteredByUnitGroups.push(unitsByUnitGroup[g]); | ||
} | ||
] | ||
}); | ||
filteredByUnitGroups = _.flatten(filteredByUnitGroups); | ||
filteredUnits = utils.intersectionObjects(filteredUnits, filteredByUnitGroups, function (item1, item2) { | ||
return item1.unitName === item2.unitName && | ||
item1.agentName === item2.agentName; | ||
}); | ||
} | ||
var filteredByUnitTypes = []; | ||
if (filters.unitTypes) { | ||
_.each(filters.unitTypes, function (g) { | ||
if (unitsByUnitType[g]) { | ||
filteredByUnitTypes.push(unitsByUnitType[g]); | ||
} | ||
}); | ||
filteredByUnitTypes = _.flatten(filteredByUnitTypes); | ||
filteredUnits = utils.intersectionObjects(filteredUnits, filteredByUnitTypes, function (item1, item2) { | ||
return item1.unitName === item2.unitName && | ||
item1.agentName === item2.agentName; | ||
}); | ||
} | ||
var filteredByTags = []; | ||
if (filters.tags) { | ||
_.each(filters.tags, function (g) { | ||
if (unitsByTags[g]) { | ||
filteredByTags.push(unitsByTags[g]); | ||
} | ||
}); | ||
filteredByTags = _.flatten(filteredByTags); | ||
filteredUnits = utils.intersectionObjects(filteredUnits, filteredByTags, function (item1, item2) { | ||
return item1.unitName === item2.unitName && | ||
item1.agentName === item2.agentName; | ||
}); | ||
} | ||
var filteredByUnitStatus = []; | ||
if (filters.unitStatus) { | ||
_.each(filters.unitStatus, function (g) { | ||
if (unitsByUnitStatus[g]) { | ||
filteredByUnitStatus.push(unitsByUnitStatus[g]); | ||
} | ||
}); | ||
filteredByUnitStatus = _.flatten(filteredByUnitStatus); | ||
filteredUnits = utils.intersectionObjects(filteredByUnitStatus, filteredUnits, function (item1, item2) { | ||
return item1.unitName === item2.unitName && | ||
item1.agentName === item2.agentName; | ||
}); | ||
} | ||
var filteredByUnitNames = []; | ||
if (filters.units) { | ||
_.each(filters.units, function (unitName) { | ||
if (!unitName.startsWith('^')) | ||
{ | ||
unitName = '^' + unitName; | ||
} | ||
if (!unitName.endsWith('$')) | ||
{ | ||
unitName = unitName + '$'; | ||
} | ||
_ | ||
.chain(unitList) | ||
.filter(function (u) { | ||
var regex = new RegExp(unitName, 'gi'); | ||
return regex.test(u.unitName); | ||
}) | ||
.each(function (unit) { | ||
var existing = _.find(filteredByUnitNames, function (f) { | ||
return f.unitName === unit.unitName && | ||
f.agentName === unit.agentName; | ||
}) !== undefined; | ||
if (!existing) { | ||
filteredByUnitNames.push(unit); | ||
} | ||
}) | ||
.value(); | ||
}); | ||
filteredByUnitNames = _.flatten(filteredByUnitNames); | ||
filteredUnits = utils.intersectionObjects(filteredUnits, filteredByUnitNames, function (item1, item2) { | ||
return item1.unitName === item2.unitName && | ||
item1.agentName === item2.agentName; | ||
}); | ||
} | ||
var result = []; | ||
_.each(units, function (agentUnits) { | ||
var existingAgent = _.find(filteredUnits, function (filteredUnit) { | ||
return filteredUnit.agentName === agentUnits.name; | ||
}); | ||
if (existingAgent !== undefined) { | ||
result.push({ | ||
name: agentUnits.name, | ||
group: agentUnits.group, | ||
loadBalancerState: agentUnits.loadBalancerState, | ||
units: _.filter(agentUnits.units, function (u) { | ||
var existingUnit = _.find(filteredUnits, function (filteredUnit) { | ||
return filteredUnit.agentName === agentUnits.name && | ||
filteredUnit.unitName === u.name; | ||
}); | ||
return existingUnit !== undefined; | ||
}) | ||
}); | ||
} | ||
}); | ||
} | ||
}); | ||
return result; | ||
}; | ||
versions["asimov-demo.com"] = [ | ||
{ "version": "7.1.0", "timestamp": "2013-06-28 16:26:11", "branch": "master", "commit": "14cbf27", "id": "mykillerapp-v7.1.0-[master]-[14cbf27].prod.zip" }, | ||
{ "version": "6.9.0", "timestamp": "2013-06-25 16:26:11", "branch": "master", "commit": "14cbf25", "id": "mykillerapp-v6.9.0-[master]-[14cbf25].prod.zip" }, | ||
{ "version": "6.8.0", "timestamp": "2013-06-24 15:26:11", "branch": "master", "commit": "14cbf25", "id": "mykillerapp-v6.8.0-[master]-[14cbf25].prod.zip" }, | ||
{ "version": "6.7.0", "timestamp": "2013-06-24 15:26:11", "branch": "my-new-feature", "commit": "14cbf25", "id": "mykillerapp-v6.7.0-[master]-[14cbf25].prod.zip" }, | ||
{ "version": "5.0.0", "timestamp": "2013-06-24 15:26:11", "branch": "master", "commit": "14cbf25", "id": "mykillerapp-v5.0.0-[master]-[14cbf25].prod.zip" } | ||
]; | ||
var _updateUnitStatus = function (agentName, unitName, status) { | ||
// jshint maxdepth:4 | ||
versions["api.asimov-demo.com"] = [ | ||
{ "version": "3.0.0", "timestamp": "2013-06-28 16:26:11", "branch": "master", "commit": "14cbf27", "id": "mykillerapp-v3.0.0-[master]-[14cbf27].prod.zip" }, | ||
{ "version": "2.9.0", "timestamp": "2013-06-25 16:26:11", "branch": "master", "commit": "14cbf25", "id": "mykillerapp-v2.9.0-[master]-[14cbf25].prod.zip" }, | ||
{ "version": "2.8.0", "timestamp": "2013-06-24 15:26:11", "branch": "master", "commit": "14cbf25", "id": "mykillerapp-v2.8.0-[master]-[14cbf25].prod.zip" }, | ||
{ "version": "2.7.0", "timestamp": "2013-06-24 15:26:11", "branch": "my-new-feature", "commit": "14cbf25", "id": "mykillerapp-v2.7.0-[master]-[14cbf25].prod.zip" }, | ||
{ "version": "1.5.0", "timestamp": "2013-06-24 15:26:11", "branch": "master", "commit": "14cbf25", "id": "mykillerapp-v1.5.0-[master]-[14cbf25].prod.zip" } | ||
]; | ||
for (var n = 0; n < units.length; n++) { | ||
var agent = units[n]; | ||
versions["backend.queue-handler"] = versions["backend.member-notification"] = [ | ||
{ "version": "2.1.0", "timestamp": "2013-06-28 16:26:11", "branch": "master", "commit": "14cbf27", "id": "mykillerapp-v3.0.0-[master]-[14cbf27].prod.zip" }, | ||
{ "version": "2.0.0", "timestamp": "2013-06-25 16:26:11", "branch": "develop", "commit": "14cbf25", "id": "mykillerapp-v2.9.0-[master]-[14cbf25].prod.zip" }, | ||
{ "version": "1.8.0", "timestamp": "2013-06-23 15:26:11", "branch": "master", "commit": "14cbf25", "id": "mykillerapp-v2.8.0-[master]-[14cbf25].prod.zip" }, | ||
{ "version": "1.7.0", "timestamp": "2013-06-20 13:26:11", "branch": "my-new-feature", "commit": "14cbf25", "id": "mykillerapp-v2.7.0-[master]-[14cbf25].prod.zip" }, | ||
{ "version": "1.5.0", "timestamp": "2013-06-21 12:26:11", "branch": "poc", "commit": "14cbf25", "id": "mykillerapp-v1.5.0-[master]-[14cbf25].prod.zip" } | ||
]; | ||
if (agent.name === agentName) { | ||
for (var i = 0; i < agent.units.length; i++) { | ||
var unit = agent.units[i]; | ||
var deployLog = [ | ||
{ timestamp: "2013-06-14 16:25:11", username: "BlameMe", version: "2.1.0", branch: "master", commit: "14cbf27", status: "Success" }, | ||
{ timestamp: "2013-06-13 12:21:11", username: "Torkel Ödegaard", version: "2.0.0", branch: "master", commit: "14cbf27", status: "Success" }, | ||
{ timestamp: "2013-06-12 11:21:11", username: "Test User", version: "1.8.0", branch: "uber-feature", commit: "14cbf27", status: "DeployFailed" }, | ||
{ timestamp: "2013-06-10 07:25:11", username: "Test User", version: "1.6.0", branch: "master", commit: "14cbf27", status: "Success" }, | ||
{ timestamp: "2013-06-10 07:15:01", username: "Demo User", version: "1.1.0", branch: "develop", commit: "14cbf27", status: "Success" } | ||
]; | ||
if (unit.name === unitName) { | ||
unit.status = status; | ||
} | ||
} | ||
} | ||
} | ||
}; | ||
var autopilot = { | ||
preferredBranch: 'master', | ||
deployableUnitSets: [ | ||
{ | ||
"id": "api_asimov_demo_com", | ||
"name": "Api", | ||
"description": "Automatic deploy of api.asimov-demo.com", | ||
"units": [ "api.asimov-demo.com" ], | ||
"defaultDeployToMaximumAgentsSimultaneously": 2, | ||
"defaultVerificationIterationCount": 1, | ||
"verificationSteps": [ "DisableLoadBalancerForAgents", "Deploy", "Verify", "Prompt", "EnableLoadBalancerForAgents" ], | ||
"steps": [ "DisableLoadBalancerForAgents", "Deploy", "Verify", "EnableLoadBalancerForAgents" ] | ||
}, | ||
{ | ||
"id": "asimov_demo_com", | ||
"name": "Site", | ||
"description": "Automatic deploy of asimov-demo.com", | ||
"units": [ "asimov-demo.com" ], | ||
"defaultDeployToMaximumAgentsSimultaneously": 2, | ||
"defaultVerificationIterationCount": 1, | ||
"verificationSteps": [ "DisableLoadBalancerForAgents", "Deploy", "Prompt", "EnableLoadBalancerForAgents" ], | ||
"steps": [ "DisableLoadBalancerForAgents", "Deploy", "EnableLoadBalancerForAgents" ] | ||
}, | ||
{ | ||
"id": "api_asimov_demo_com_and_asimov_demo_com", | ||
"name": "Api + Site", | ||
"description": "Automatic deploy of api.asimov-demo.com and asimov-demo.com", | ||
"units": [ "asimov-demo.com", "api.asimov-demo.com" ], | ||
"defaultDeployToMaximumAgentsSimultaneously": 2, | ||
"defaultVerificationIterationCount": 1, | ||
"verificationSteps": [ "DisableLoadBalancerForAgents", "Deploy", "Prompt", "EnableLoadBalancerForAgents" ], | ||
"steps": [ "DisableLoadBalancerForAgents", "Deploy", "EnableLoadBalancerForAgents" ] | ||
}, | ||
{ | ||
"id": "backend_member_notification", | ||
"name": "Member Notification", | ||
"description": "Automatic deploy of backend.member-notification", | ||
"units": [ "backend.member-notification" ], | ||
"defaultDeployToMaximumAgentsSimultaneously": 1, | ||
"defaultVerificationIterationCount": 1, | ||
"verificationSteps": [ "Deploy", "Prompt" ], | ||
"steps": [ "Deploy" ] | ||
}, | ||
{ | ||
"id": "backend_queue_handler", | ||
"name": "Queue Handler", | ||
"description": "Automatic deploy of backend.queue-handler", | ||
"units": [ "backend.queue-handler" ], | ||
"defaultDeployToMaximumAgentsSimultaneously": 1, | ||
"defaultVerificationIterationCount": 1, | ||
"verificationSteps": [ "Deploy", "Prompt" ], | ||
"steps": [ "Deploy" ] | ||
}, | ||
{ | ||
"id": "backend_member_notification_and_backend_queue_handler", | ||
"name": "Member Notification + Queue Handler", | ||
"description": "Automatic deploy of backend.member-notification and backend.queue-handler", | ||
"units": [ "backend.member-notification", "backend.queue-handler" ], | ||
"defaultDeployToMaximumAgentsSimultaneously": 1, | ||
"defaultVerificationIterationCount": 1, | ||
"verificationSteps": [ "Deploy", "Prompt" ], | ||
"steps": [ "Deploy" ] | ||
} | ||
] | ||
return { | ||
units: units, | ||
versions: versions, | ||
deployLog: deployLog, | ||
autopilot: autopilot, | ||
getUnits: _getUnits, | ||
updateUnitStatus: _updateUnitStatus | ||
}; | ||
}; | ||
module.exports = { | ||
agents: agents, | ||
units: units, | ||
versions: versions, | ||
deployLog: deployLog, | ||
autopilot: autopilot | ||
}; | ||
module.exports = DemodataGenerator; |
@@ -18,9 +18,8 @@ /******************************************************************************* | ||
module.exports = function(app, config) { | ||
var demodata = require('./demo-data-generator.js'); | ||
var _ = require('underscore'); | ||
var demoDataGenerator = require('./demo-data-generator.js'); | ||
var demoUtils = require('./demo-utils.js'); | ||
var _ = require('underscore'); | ||
var demodata = demoDataGenerator(config); | ||
config.agents = demodata.agents; | ||
function emitLog(agentName, message) { | ||
@@ -44,10 +43,13 @@ | ||
app.get('/agents/list', app.ensureLoggedIn, function(req, res) { | ||
res.json(_.sortBy(demodata.agents, 'name')); | ||
}); | ||
app.get('/units/list', app.ensureLoggedIn, function(req, res) { | ||
var group = req.query.group; | ||
var filters = { | ||
agentGroups: req.query.agentGroups, | ||
unitGroups: req.query.unitGroups, | ||
unitTypes: req.query.unitTypes, | ||
tags: req.query.unitTags, | ||
units: req.query.units, | ||
unitStatus: req.query.unitStatuses | ||
}; | ||
res.json(_.where(demodata.units, { group: group })); | ||
res.json(demodata.getUnits(filters)); | ||
}); | ||
@@ -74,3 +76,3 @@ | ||
var agent = _.find(demodata.agents, function(agent) { | ||
var agent = _.find(config.agents, function(agent) { | ||
return agent.name === req.body.agentName; | ||
@@ -95,3 +97,3 @@ }); | ||
app.get("/loadbalancer/servers", app.ensureLoggedIn, function(req, res) { | ||
var hosts = _.map(demodata.agents, function(agent) { | ||
var hosts = _.map(config.agents, function(agent) { | ||
return { | ||
@@ -120,2 +122,4 @@ name: agent.name, | ||
demodata.updateUnitStatus(req.body.agentName, req.body.unitName, 'Deploying'); | ||
emitLog(req.body.agentName, "Starting deploy... (just demo text, the actual deploy agent will output meaningfull deploy info)"); | ||
@@ -132,2 +136,4 @@ | ||
}); | ||
demodata.updateUnitStatus(req.body.agentName, req.body.unitName, 'Running'); | ||
}, 3000); | ||
@@ -189,2 +195,4 @@ | ||
demodata.updateUnitStatus(req.body.agentName, req.body.unitName, 'Stopping'); | ||
setTimeout(function() { | ||
@@ -197,2 +205,4 @@ emitAgentEvent({ | ||
}); | ||
demodata.updateUnitStatus(req.body.agentName, req.body.unitName, 'Stopped'); | ||
}, 3000); | ||
@@ -209,2 +219,4 @@ } | ||
demodata.updateUnitStatus(req.body.agentName, req.body.unitName, 'Starting'); | ||
setTimeout(function() { | ||
@@ -217,2 +229,4 @@ emitAgentEvent({ | ||
}); | ||
demodata.updateUnitStatus(req.body.agentName, req.body.unitName, 'Running'); | ||
}, 3000); | ||
@@ -225,3 +239,3 @@ } | ||
_.each(demodata.agents, function (agent) { | ||
_.each(config.agents, function (agent) { | ||
if (!agent.loadBalancerState.enabled) { | ||
@@ -228,0 +242,0 @@ agent.loadBalancerState.connectionCount = 0; |
@@ -0,18 +1,242 @@ | ||
var _ = require('underscore'); | ||
module.exports = { | ||
getCurrentTimeString: function() { | ||
function getCurrentTimeString() { | ||
var date = new Date(); | ||
var hh = date.getHours(); | ||
var mm = date.getMinutes(); | ||
var ss = date.getSeconds(); | ||
var date = new Date(); | ||
var hh = date.getHours(); | ||
var mm = date.getMinutes(); | ||
var ss = date.getSeconds(); | ||
if (hh > 12) {hh = hh - 12;} | ||
if (hh > 12) {hh = hh - 12;} | ||
if (hh < 10) {hh = "0"+hh;} | ||
if (mm < 10) {mm = "0"+mm;} | ||
if (ss < 10) {ss = "0"+ss;} | ||
if (hh < 10) {hh = "0"+hh;} | ||
if (mm < 10) {mm = "0"+mm;} | ||
if (ss < 10) {ss = "0"+ss;} | ||
return hh+":"+mm+":"+ss; | ||
} | ||
return hh+":"+mm+":"+ss; | ||
function intersectionObjects2(a, b, areEqualFunction) { | ||
/*jshint loopfunc: true */ | ||
var results = []; | ||
for (var i = 0; i < a.length; i++) { | ||
var aElement = a[i]; | ||
var existsInB = _.any(b, function(bElement) { return areEqualFunction(bElement, aElement); }); | ||
if (existsInB) { | ||
results.push(aElement); | ||
} | ||
} | ||
return results; | ||
} | ||
function intersectionObjects() { | ||
var results = arguments[0]; | ||
var lastArgument = arguments[arguments.length - 1]; | ||
var arrayCount = arguments.length; | ||
var areEqualFunction = _.isEqual; | ||
if (typeof lastArgument === "function") { | ||
areEqualFunction = lastArgument; | ||
arrayCount--; | ||
} | ||
for (var i = 1; i < arrayCount ; i++) { | ||
var array = arguments[i]; | ||
results = intersectionObjects2(results, array, areEqualFunction); | ||
if (results.length === 0) { | ||
break; | ||
} | ||
} | ||
return results; | ||
} | ||
var _getUnitsByAgentGroup = function (units) { | ||
var unitsByAgentGroup = {}; | ||
_ | ||
.chain(units) | ||
.map(function (agentUnits) { | ||
return _.map(agentUnits.units, function (u) { | ||
return { | ||
agentGroup: agentUnits.group, | ||
agentName: agentUnits.name, | ||
unitName: u.name | ||
}; | ||
}); | ||
}) | ||
.flatten() | ||
.groupBy('agentGroup') | ||
.map(function (value, key) { | ||
return { | ||
agentGroup: key, | ||
units: _.map(value, function (v) { | ||
return { | ||
agentName: v.agentName, | ||
unitName: v.unitName | ||
}; | ||
}) | ||
}; | ||
}) | ||
.sortBy('agentGroup') | ||
.each(function (x) { | ||
unitsByAgentGroup[x.agentGroup] = x.units; | ||
}) | ||
.value(); | ||
return unitsByAgentGroup; | ||
}; | ||
var _getUnitsByUnitGroup = function (units) { | ||
var unitsByUnitGroup = {}; | ||
_ | ||
.chain(units) | ||
.map(function (agentUnits) { | ||
return _.map(agentUnits.units, function (u) { | ||
return { | ||
agentName: agentUnits.name, | ||
unitName: u.name, | ||
unitGroup: u.group | ||
}; | ||
}); | ||
}) | ||
.flatten() | ||
.groupBy('unitGroup') | ||
.map(function (value, key) { | ||
return { | ||
unitGroup: key, | ||
units: _.map(value, function (v) { | ||
return { | ||
agentName: v.agentName, | ||
unitName: v.unitName | ||
}; | ||
}) | ||
}; | ||
}) | ||
.sortBy('unitGroup') | ||
.each(function (x) { | ||
unitsByUnitGroup[x.unitGroup] = x.units; | ||
}) | ||
.value(); | ||
return unitsByUnitGroup; | ||
}; | ||
var _getUnitsByUnitType = function (units) { | ||
var unitsByUnitType = {}; | ||
_ | ||
.chain(units) | ||
.map(function (agentUnits) { | ||
return _.map(agentUnits.units, function (u) { | ||
return { | ||
agentName: agentUnits.name, | ||
unitName: u.name, | ||
unitType: u.type | ||
}; | ||
}); | ||
}) | ||
.flatten() | ||
.groupBy('unitType') | ||
.map(function (value, key) { | ||
return { | ||
unitType: key, | ||
units: _.map(value, function (v) { | ||
return { | ||
agentName: v.agentName, | ||
unitName: v.unitName | ||
}; | ||
}) | ||
}; | ||
}) | ||
.sortBy('unitType') | ||
.each(function (x) { | ||
unitsByUnitType[x.unitType] = x.units; | ||
}) | ||
.value(); | ||
return unitsByUnitType; | ||
}; | ||
var _getUnitsByUnitStatus = function (units) { | ||
var unitsByUnitStatus = {}; | ||
_ | ||
.chain(units) | ||
.map(function (agentUnits) { | ||
return _.map(agentUnits.units, function (u) { | ||
return { | ||
agentName: agentUnits.name, | ||
unitName: u.name, | ||
status: u.status | ||
}; | ||
}); | ||
}) | ||
.flatten() | ||
.groupBy('status') | ||
.map(function (value, key) { | ||
return { | ||
status: key, | ||
units: _.map(value, function (v) { | ||
return { | ||
agentName: v.agentName, | ||
unitName: v.unitName | ||
}; | ||
}) | ||
}; | ||
}) | ||
.sortBy('status') | ||
.each(function (x) { | ||
unitsByUnitStatus[x.status] = x.units; | ||
}) | ||
.value(); | ||
return unitsByUnitStatus; | ||
}; | ||
var _getUnitsByTags = function (units) { | ||
var unitsByTags = {}; | ||
_ | ||
.chain(units) | ||
.map(function (agentUnits) { | ||
return _.map(agentUnits.units, function (u) { | ||
return _.map(u.tags, function (v) { | ||
return { | ||
tag: v, | ||
agentName: agentUnits.name, | ||
unitName: u.name | ||
}; | ||
}); | ||
}); | ||
}) | ||
.flatten() | ||
.groupBy('tag') | ||
.map(function (value, key) { | ||
return { | ||
tag: key, | ||
units: _.map(value, function (v) { | ||
return { | ||
agentName: v.agentName, | ||
unitName: v.unitName | ||
}; | ||
}) | ||
}; | ||
}) | ||
.sortBy('tag') | ||
.each(function (x) { | ||
unitsByTags[x.tag] = x.units; | ||
}) | ||
.value(); | ||
return unitsByTags; | ||
}; | ||
module.exports = { | ||
getCurrentTimeString: getCurrentTimeString, | ||
intersectionObjects: intersectionObjects, | ||
getUnitsByAgentGroup: _getUnitsByAgentGroup, | ||
getUnitsByUnitGroup: _getUnitsByUnitGroup, | ||
getUnitsByUnitType: _getUnitsByUnitType, | ||
getUnitsByUnitStatus: _getUnitsByUnitStatus, | ||
getUnitsByTags: _getUnitsByTags | ||
}; |
@@ -25,3 +25,2 @@ /******************************************************************************* | ||
this.get = function(agentName, url, dataCallback) { | ||
var agent = config.getAgent(agentName); | ||
@@ -39,15 +38,35 @@ var client = restify.createJsonClient({ url: agent.url, connectTimeout: 200 }); | ||
this.getUnitListForAgentGroup = function(group, dataCallback) { | ||
var _getUnitListUrl = function (filters) { | ||
var url = '/units/list'; | ||
var queryStrings = []; | ||
_.forEach(Object.keys(filters), function (key) { | ||
var values = filters[key]; | ||
if (values && values.length > 0) { | ||
queryStrings.push((key + '=') + _.map(values, function (v) { | ||
return encodeURIComponent(v); | ||
}).join('&' + key + '=')); | ||
} | ||
}); | ||
if (queryStrings.length > 0) { | ||
url += '?'; | ||
} | ||
return url + queryStrings.join('&'); | ||
}; | ||
this.getUnits = function(filters, dataCallback) { | ||
filters = filters || {}; | ||
var result = []; | ||
var agents = config.agents; | ||
var distinctAgents = []; | ||
var encodedGroup = ''; | ||
if (group) { | ||
agents = _.where(agents, { group: group }); | ||
encodedGroup = '/' + encodeURIComponent(group); | ||
if (filters.agentGroups) { | ||
agents = _.filter(agents, function (agent) { | ||
return filters.agentGroups.indexOf(agent.group) !== -1; | ||
}); | ||
} | ||
else { | ||
var distinctAgents = []; | ||
_.forEach(agents, function (agent) { | ||
@@ -63,2 +82,4 @@ if (_.findWhere(distinctAgents, { name: agent.name }) === undefined) { | ||
var url = _getUnitListUrl(filters); | ||
async.forEach(agents, function(agent, done) { | ||
@@ -69,3 +90,3 @@ if (agent.dead) { | ||
} | ||
this.get(agent.name, '/units/list' + encodedGroup, function(units) { | ||
this.get(agent.name, url, function(units) { | ||
result.push({agent: agent, units: units}); | ||
@@ -80,2 +101,22 @@ done(); | ||
this.getAgentGroups = function (agentName, dataCallback) { | ||
this.get(agentName, '/agent-groups', dataCallback); | ||
}; | ||
this.getAgentUnitGroups = function (agentName, dataCallback) { | ||
this.get(agentName, '/unit-groups', dataCallback); | ||
}; | ||
this.getAgentUnitTypes = function (agentName, dataCallback) { | ||
this.get(agentName, '/unit-types', dataCallback); | ||
}; | ||
this.getAgentUnitTags = function (agentName, dataCallback) { | ||
this.get(agentName, '/unit-tags', dataCallback); | ||
}; | ||
this.getAgentUnitStatuses = function (agentName, dataCallback) { | ||
this.get(agentName, '/unit-statuses', dataCallback); | ||
}; | ||
this.test = function(agentName) { | ||
@@ -82,0 +123,0 @@ return config.getAgent(agentName); |
195
app/units.js
@@ -19,13 +19,22 @@ /******************************************************************************* | ||
var _ = require('underscore'); | ||
var agentApiClient = require('./services/agent-api-client').create(config); | ||
app.get("/units/list", app.ensureLoggedIn, function(req, res) { | ||
var group = req.query.group; | ||
var agentsResp = []; | ||
agentApiClient.getUnitListForAgentGroup(group, function(results) { | ||
var filters = { | ||
agentGroups: req.query.agentGroups, | ||
unitGroups: req.query.unitGroups, | ||
unitTypes: req.query.unitTypes, | ||
tags: req.query.unitTags, | ||
units: req.query.units, | ||
unitStatus: req.query.unitStatuses | ||
}; | ||
agentApiClient.getUnits(filters, function(results) { | ||
results.forEach(function(item) { | ||
agentsResp.push({ | ||
name: item.agent.name, | ||
group: group, | ||
group: item.agent.agentGroup, | ||
loadBalancerState: item.agent.loadBalancerState, | ||
@@ -44,2 +53,182 @@ units: item.units | ||
var DELIMITER = ':'; | ||
var AGENT_GROUP_PREFIX = 'ag'; | ||
var UNIT_GROUP_PREFIX = 'ug'; | ||
var UNIT_TYPE_PREFIX = 'ut'; | ||
var TAG_PREFIX = 'tag'; | ||
var UNIT_PREFIX = 'unit'; | ||
var UNIT_STATUS_PREFIX = 'us'; | ||
var PREFIXES = [ | ||
AGENT_GROUP_PREFIX, | ||
UNIT_GROUP_PREFIX, | ||
UNIT_TYPE_PREFIX, | ||
TAG_PREFIX, | ||
UNIT_PREFIX, | ||
UNIT_STATUS_PREFIX | ||
]; | ||
app.get("/units/auto-complete", app.ensureLoggedIn, function(req, res) { | ||
/*jshint maxcomplexity:10 */ | ||
var q = req.query.q; | ||
var hasModifier = false; | ||
var hasModifierWithQuery = false; | ||
if (q) { | ||
PREFIXES.forEach(function (p) { | ||
if (q.toLowerCase().startsWith(p + DELIMITER)) { | ||
hasModifier = true; | ||
if (q.length > (p + DELIMITER).length) { | ||
hasModifierWithQuery = true; | ||
} | ||
} | ||
}); | ||
} | ||
var response = []; | ||
if (q && q.toLowerCase().startsWith(UNIT_PREFIX + DELIMITER)) { | ||
var unitResponse = { | ||
text: 'Units', | ||
children: [] | ||
}; | ||
if (q.length > 5) { | ||
var arr = q.toLowerCase().split(DELIMITER); | ||
unitResponse.children.push( | ||
{ | ||
id: UNIT_PREFIX + DELIMITER + arr[1], | ||
text: arr[1], | ||
selectionText: 'Unit: ' + arr[1], | ||
group: 'units' | ||
} | ||
); | ||
} | ||
res.json([unitResponse]); | ||
return; | ||
} | ||
var agentGroups = { | ||
text: 'Agent Groups (ag:)', | ||
children: config.getAgentGroups().map(function (agentGroup) { | ||
return { | ||
id: AGENT_GROUP_PREFIX + DELIMITER + agentGroup, | ||
text: agentGroup, | ||
prefix: AGENT_GROUP_PREFIX, | ||
selectionText: 'Agent Group: ' + agentGroup, | ||
group: 'agentGroups' | ||
}; | ||
}) | ||
}; | ||
response.push(agentGroups); | ||
var unitGroups = { | ||
text: 'Unit Groups (ug:)', | ||
children: config.getUnitGroups().map(function (unitGroup) { | ||
return { | ||
id: UNIT_GROUP_PREFIX + DELIMITER + unitGroup, | ||
text: unitGroup, | ||
prefix: UNIT_GROUP_PREFIX, | ||
selectionText: 'Unit Group: ' + unitGroup, | ||
group: 'unitGroups' | ||
}; | ||
}) | ||
}; | ||
response.push(unitGroups); | ||
var unitTypes = { | ||
text: 'Unit Types (ut:)', | ||
children: config.getUnitTypes().map(function (unitType) { | ||
return { | ||
id: UNIT_TYPE_PREFIX + DELIMITER + unitType, | ||
text: unitType, | ||
prefix: UNIT_TYPE_PREFIX, | ||
selectionText: 'Unit Type: ' + unitType, | ||
group: 'unitTypes' | ||
}; | ||
}) | ||
}; | ||
response.push(unitTypes); | ||
var unitStatuses = { | ||
text: 'Unit Statuses (us:)', | ||
children: config.getUnitStatuses().map(function (status) { | ||
return { | ||
id: UNIT_STATUS_PREFIX + DELIMITER + status, | ||
text: status, | ||
prefix: UNIT_STATUS_PREFIX, | ||
selectionText: 'Status: ' + status, | ||
group: 'unitStatuses' | ||
}; | ||
}) | ||
}; | ||
response.push(unitStatuses); | ||
var unitTags = { | ||
text: 'Tags (tag:)', | ||
children: config.getUnitTags().map(function (tag) { | ||
return { | ||
id: TAG_PREFIX + DELIMITER + tag, | ||
text: tag, | ||
prefix: TAG_PREFIX, | ||
selectionText: 'Tag: ' + tag, | ||
group: 'unitTags' | ||
}; | ||
}) | ||
}; | ||
response.push(unitTags); | ||
if (q && !hasModifier) { | ||
var unitGroup = { | ||
text: 'Units (unit:)', | ||
children: [ | ||
{ | ||
id: UNIT_PREFIX + DELIMITER + q, | ||
text: q, | ||
prefix: UNIT_PREFIX, | ||
selectionText: 'Unit: ' + q, | ||
group: 'units' | ||
} | ||
] | ||
}; | ||
response.push(unitGroup); | ||
} | ||
if (q) { | ||
response = _.map(response, function (group) { | ||
group.children = _.filter(group.children, function(s) { | ||
if (hasModifier) { | ||
var tokens = q.toLowerCase().split(":"); | ||
return s.id.toLowerCase().startsWith(tokens[0]) && | ||
s.id.toLowerCase().indexOf(tokens[1]) !== -1; | ||
} | ||
return s.text.toLowerCase().indexOf(q.toLowerCase()) !== -1; | ||
}); | ||
return group; | ||
}); | ||
response = _.filter(response, function (group) { | ||
return group.children.length > 0; | ||
}); | ||
} | ||
if (!hasModifier && (!q || q.length > 0)) { | ||
response = _.map(response, function (group) { | ||
if (group.children.length > 5) { | ||
group.children = group.children.slice(0, 3); | ||
} | ||
return group; | ||
}); | ||
} | ||
res.json(response); | ||
}); | ||
}; |
@@ -5,3 +5,3 @@ { | ||
"author": "Ebay Inc", | ||
"version": "0.8.7", | ||
"version": "0.9.0", | ||
"homepage": "https://github.com/asimov-deploy/asimov-deploy", | ||
@@ -8,0 +8,0 @@ "license": "Apache-2.0", |
@@ -44,3 +44,3 @@ /******************************************************************************* | ||
var data = _.map(agentGroups, function(group){ | ||
var sortedGroups = _.sortBy(_.pluck(group, 'group')); | ||
var sortedGroups = _.sortBy(_.pluck(group, 'agentGroup')); | ||
var groupString = _.reduce(sortedGroups, function (memo, val) { | ||
@@ -47,0 +47,0 @@ if (memo) { |
@@ -36,5 +36,4 @@ /******************************************************************************* | ||
$(function() { | ||
var windowHeight = $(window).height() - 181 - 60 - 41 - 20; | ||
var windowHeight = $(window).height() - 181 - 60 - 41; | ||
$("head").append("<style type='text/css'>.page-content { max-height: " + windowHeight + "px; overflow-y: auto; } </style>"); | ||
@@ -41,0 +40,0 @@ }); |
@@ -34,2 +34,3 @@ /******************************************************************************* | ||
"jquery.cookie": "../libs/jquery.cookie", | ||
"select2": "../libs/select2", | ||
@@ -36,0 +37,0 @@ 'socket.io': '../../node_modules/socket.io-client/dist/socket.io' |
@@ -28,7 +28,27 @@ /******************************************************************************* | ||
// events | ||
app.vent.on("group-changed", function() { | ||
unitCollection.fetch(); | ||
}); | ||
var loadUnits = function (filtersObj) { | ||
var filters = {}; | ||
_.forEach(Object.keys(filtersObj), function (group) { | ||
filters[group] = _.map(filtersObj[group], function (f) { | ||
return f.text; | ||
}); | ||
}); | ||
unitCollection.fetch(filters); | ||
}; | ||
var getCurrentFilter = function () { | ||
var filtersStr = localStorage.getItem('Dashboard:current-filter'); | ||
var filtersObj = {}; | ||
if (filtersStr) { | ||
filtersObj = JSON.parse(filtersStr); | ||
} | ||
return filtersObj; | ||
}; | ||
var setCurrentFilter = function (filters) { | ||
localStorage.setItem('Dashboard:current-filter', JSON.stringify(filters)); | ||
}; | ||
app.vent.on("agent:event:deployStarted", function(data) { | ||
@@ -78,9 +98,49 @@ var unit = unitCollection.getUnitInstance(data.unitName, data.agentName); | ||
app.vent.on("dashboard:show", function() { | ||
var view = new UnitListView({ collection: unitCollection }); | ||
var initialFilters = getCurrentFilter(); | ||
var view = new UnitListView({ | ||
collection: unitCollection, | ||
filters: initialFilters | ||
}); | ||
app.mainRegion.show(view); | ||
if (unitCollection.length === 0) { | ||
unitCollection.fetch(); | ||
loadUnits(initialFilters); | ||
} | ||
view.on('refresh', function () { | ||
loadUnits(getCurrentFilter()); | ||
}); | ||
view.on("filter-selection:added", function (payload) { | ||
var currentFilterObj = getCurrentFilter(); | ||
if (Object.keys(currentFilterObj).indexOf(payload.group) === -1) { | ||
currentFilterObj[payload.group] = []; | ||
} | ||
currentFilterObj[payload.group].push({ | ||
id: payload.id, | ||
text: payload.text, | ||
selectionText: payload.selectionText | ||
}); | ||
loadUnits(currentFilterObj); | ||
setCurrentFilter(currentFilterObj); | ||
}); | ||
view.on("filter-selection:removed", function (payload) { | ||
var currentFilterObj = getCurrentFilter(); | ||
if (Object.keys(currentFilterObj).indexOf(payload.group) === -1) { | ||
currentFilterObj[payload.group] = []; | ||
} | ||
currentFilterObj[payload.group] = _.filter(currentFilterObj[payload.group], function(item) { | ||
return item.id !== payload.id; | ||
}); | ||
loadUnits(currentFilterObj); | ||
setCurrentFilter(currentFilterObj); | ||
}); | ||
app.router.showRoute("dashboard"); | ||
@@ -87,0 +147,0 @@ }); |
@@ -64,3 +64,6 @@ /******************************************************************************* | ||
actions: instance.actions, | ||
hasDeployParameters: instance.hasDeployParameters | ||
hasDeployParameters: instance.hasDeployParameters, | ||
group: instance.group, | ||
type: instance.type, | ||
tags: instance.tags | ||
}); | ||
@@ -75,3 +78,3 @@ }, | ||
fetch: function() { | ||
fetch: function (filters) { | ||
var tempList = []; | ||
@@ -84,3 +87,3 @@ var self = this; | ||
url: "/units/list", | ||
data: $.param({group: app.currentGroup}), | ||
data: $.param(filters || {}), | ||
dataType: 'json' | ||
@@ -87,0 +90,0 @@ }).done(function(agents) { |
@@ -62,4 +62,12 @@ /******************************************************************************* | ||
}); | ||
var group = this.instances.at(0).get('group'); | ||
var type = this.instances.at(0).get('type'); | ||
this.model.set({showActions: anySelected, allSelected: allSelected, showLoadBalancerToggle: showLoadBalancerToggle}); | ||
this.model.set({ | ||
group: group, | ||
type: type, | ||
showActions: anySelected, | ||
allSelected: allSelected, | ||
showLoadBalancerToggle: showLoadBalancerToggle | ||
}); | ||
}, | ||
@@ -66,0 +74,0 @@ |
@@ -22,5 +22,6 @@ /******************************************************************************* | ||
"./unit-instance-view", | ||
"./unit-header-view" | ||
"./unit-header-view", | ||
"./../app" | ||
], | ||
function($, Backbone, Marionette, UnitInstanceView, UnitHeaderView) { | ||
function($, Backbone, Marionette, UnitInstanceView, UnitHeaderView, app) { | ||
@@ -42,2 +43,10 @@ | ||
this.$el.toggleClass("deploy-unit-collapsed", this.getToggleState()); | ||
app.vent.on('units:collapse', function () { | ||
this.collapse(); | ||
}, this); | ||
app.vent.on('units:expand', function () { | ||
this.expand(); | ||
}, this); | ||
}, | ||
@@ -71,3 +80,3 @@ | ||
var value = localStorage.getItem('deploy-unit-collapsed-state-' + this.model.get('name')); | ||
return value ? value === "true" : false; | ||
return value ? value === "true" : true; | ||
}, | ||
@@ -85,4 +94,13 @@ | ||
} | ||
}, | ||
collapse: function () { | ||
this.$el.addClass("deploy-unit-collapsed"); | ||
this.saveToggleState(); | ||
}, | ||
expand: function () { | ||
this.$el.removeClass("deploy-unit-collapsed"); | ||
this.saveToggleState(); | ||
} | ||
}); | ||
@@ -89,0 +107,0 @@ |
@@ -18,2 +18,3 @@ /******************************************************************************* | ||
define([ | ||
"underscore", | ||
"jquery", | ||
@@ -26,5 +27,6 @@ "marionette", | ||
"backbone", | ||
"jquery.cookie" | ||
"jquery.cookie", | ||
"select2" | ||
], | ||
function($, Marionette, UnitInstanceListView, DeployLifecycle, ensureActiveDeploy, app, Backbone) { | ||
function(_, $, Marionette, UnitInstanceListView, DeployLifecycle, ensureActiveDeploy, app, Backbone) { | ||
@@ -43,2 +45,6 @@ var DeployLifecycleStartCommand = Backbone.Model.extend({ | ||
var _openDropDown = function () { | ||
this.$el.find("#deploy-unit-filter").select2("open"); | ||
}; | ||
return Marionette.CompositeView.extend({ | ||
@@ -56,3 +62,5 @@ itemView: UnitInstanceListView, | ||
"click .btn-cancel-deploy": "cancelDeploy", | ||
"click .btn-configure-autopilot": "configureAutopilot" | ||
"click .btn-configure-autopilot": "configureAutopilot", | ||
"click .btn-collapse": "collapseUnits", | ||
"click .btn-expand": "expandUnits" | ||
}, | ||
@@ -63,2 +71,4 @@ | ||
this.collection = new this.collection.constructor(this.collection.models, this.collection.options); | ||
this.initialFilters = options.filters || {}; | ||
this.listenTo(this.unfiltered, "reset", this.applyFilter, this); | ||
@@ -123,2 +133,63 @@ this.loadFilterText(); | ||
onClose: function() { | ||
this.$el.find("#deploy-unit-filter").select2("destroy"); | ||
app.vent.off('focus-search-field', _openDropDown, this); | ||
}, | ||
onRender: function() { | ||
var initialData = []; | ||
_.each(Object.keys(this.initialFilters), function (group) { | ||
_.each(this.initialFilters[group], function (f) { | ||
f.group = group; | ||
f.selected = true; | ||
initialData.push(f); | ||
}); | ||
}, this); | ||
this.$el.find("#deploy-unit-filter").select2({ | ||
placeholder: "Filter deploy units...", | ||
templateSelection: function (data) { | ||
return data.selectionText; | ||
}, | ||
allowClear: true, | ||
data: initialData, | ||
ajax: { | ||
url: "/units/auto-complete", | ||
dataType: 'json', | ||
delay: 100, | ||
data: function (params) { | ||
return { | ||
q: params.term | ||
}; | ||
}, | ||
processResults: function (data) { | ||
return { | ||
results: data | ||
}; | ||
} | ||
} | ||
}) | ||
.on("select2:select", function (e) { | ||
this.trigger('filter-selection:added', { | ||
group: e.params.data.group, | ||
id: e.params.data.id, | ||
text: e.params.data.text, | ||
selectionText: e.params.data.selectionText | ||
}); | ||
}.bind(this)) | ||
.on("select2:unselect", function(e) { | ||
this.trigger('filter-selection:removed', { | ||
group: e.params.data.group, | ||
id: e.params.data.id, | ||
text: e.params.data.text, | ||
selectionText: e.params.data.selectionText | ||
}); | ||
}.bind(this)); | ||
// Hack to get the placeholder to show up on load | ||
this.$el.find('.select2-search__field').css('width', 'auto'); | ||
app.vent.on('focus-search-field', _openDropDown, this); | ||
}, | ||
initDeployMode: function() { | ||
@@ -179,9 +250,4 @@ var featureToggles = app.initData.featureToggles; | ||
refresh: function(e) { | ||
$(e.target).button("loading"); | ||
this.unfiltered.fetch() | ||
.always(function() { | ||
$(e.target).button("reset"); | ||
}); | ||
refresh: function () { | ||
this.trigger('refresh'); | ||
}, | ||
@@ -232,5 +298,12 @@ | ||
}, | ||
collapseUnits: function () { | ||
app.vent.trigger('units:collapse'); | ||
}, | ||
expandUnits: function () { | ||
app.vent.trigger('units:expand'); | ||
} | ||
}); | ||
}); |
@@ -28,3 +28,3 @@ /******************************************************************************* | ||
"current-user", | ||
"group-selection" | ||
"keyboardShortcuts" | ||
], | ||
@@ -31,0 +31,0 @@ function($, app, autopilot, Router, Backbone) { |
@@ -76,3 +76,3 @@ require('should'); | ||
apiClient.getUnitListForAgentGroup("groupName", function(results) { | ||
apiClient.getUnits({agentGroups: ['groupName']}, function(results) { | ||
unitListForAgentGroup = results; | ||
@@ -79,0 +79,0 @@ }); |
require('should'); | ||
var config = new (require('../../app/config').Config)(); | ||
@@ -10,3 +11,3 @@ describe('Autopilot', function() { | ||
autopilot: { | ||
deployableUnitSets: require('../../app/demo-mode/demo-data-generator').autopilot.deployableUnitSets | ||
deployableUnitSets: require('../../app/demo-mode/demo-data-generator')(config).autopilot.deployableUnitSets | ||
} | ||
@@ -47,3 +48,3 @@ }; | ||
before(function() { | ||
var demoDataGenerator = require('../../app/demo-mode/demo-data-generator'); | ||
var demoDataGenerator = require('../../app/demo-mode/demo-data-generator')(config); | ||
@@ -72,3 +73,3 @@ var fakeConfig = { | ||
getUnitListForAgentGroup: function (groupName, dataCallback) { | ||
getUnits: function (filters, dataCallback) { | ||
var units = []; | ||
@@ -127,3 +128,3 @@ | ||
before(function() { | ||
var demoDataGenerator = require('../../app/demo-mode/demo-data-generator'); | ||
var demoDataGenerator = require('../../app/demo-mode/demo-data-generator')(config); | ||
@@ -152,3 +153,3 @@ var fakeConfig = { | ||
getUnitListForAgentGroup: function (groupName, dataCallback) { | ||
getUnits: function (filters, dataCallback) { | ||
var units = []; | ||
@@ -207,3 +208,3 @@ | ||
before(function() { | ||
var demoDataGenerator = require('../../app/demo-mode/demo-data-generator'); | ||
var demoDataGenerator = require('../../app/demo-mode/demo-data-generator')(config); | ||
@@ -232,3 +233,3 @@ var fakeConfig = { | ||
getUnitListForAgentGroup: function (groupName, dataCallback) { | ||
getUnits: function (filters, dataCallback) { | ||
var units = []; | ||
@@ -287,3 +288,3 @@ | ||
before(function() { | ||
var demoDataGenerator = require('../../app/demo-mode/demo-data-generator'); | ||
var demoDataGenerator = require('../../app/demo-mode/demo-data-generator')(config); | ||
@@ -311,3 +312,3 @@ var fakeConfig = { | ||
getUnitListForAgentGroup: function (groupName, dataCallback) { | ||
getUnits: function (filters, dataCallback) { | ||
var units = []; | ||
@@ -314,0 +315,0 @@ |
@@ -26,2 +26,3 @@ var deps = []; | ||
"jquery.cookie": "../libs/jquery.cookie", | ||
"select2": "../libs/select2", | ||
@@ -28,0 +29,0 @@ 'socket.io': '../../node_modules/socket.io-client/dist/socket.io' |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
3577854
222
71249
5
21