Adds inventory tracking and templating to network UI groups and hosts.

* Adds group_id to Group table
* Adds inventory_group_id to Group table
* Adds creation of inventory hosts and groups from the network UI
* Changes network UI variables to be under awx key
* Fixes variables initial value
* Adds group membership association/disassociation
* Removes items from the inventory toolbar when loaded by a snaphot
* Adds nunjucks dependency to package.json
* Adds templating to hosts
* Adds templating for racks
* Adds site templating
* Adds group associations for sites
* Squashes migrations for network_ui
* Flake8 migrations
* Changes reserved field type to device_type, group_type, and process_type
* Allows blank values for all CharFields in network_ui models
* Changes reserved field type to device_type, group_type, and process_type
This commit is contained in:
Ben Thomasson
2018-02-22 19:35:06 -05:00
parent b7848ab4f6
commit f8d83638b0
79 changed files with 1471 additions and 1367 deletions

View File

@@ -15,7 +15,7 @@ function scale_animation (scope) {
if(scope.data.distance > 0) {
height = (x + a) * (x - d) * c + scope.data.end_height;
} else {
height = (scope.data.end_height - initial_height) * (scope.frame_number / scope.steps) + initial_height
height = (scope.data.end_height - initial_height) * (scope.frame_number / scope.steps) + initial_height;
}
//console.log({x: x,
// c: c,

View File

@@ -163,6 +163,8 @@ _Resize.prototype.onMouseMove = function (controller) {
controller.scope.send_control_message(new messages.GroupMembership(controller.scope.client_id,
groups[i].id,
membership_old_new[2]));
controller.scope.create_group_association(groups[i], membership_old_new[6]);
controller.scope.delete_group_association(groups[i], membership_old_new[7]);
}
controller.scope.pressedScaledX = controller.scope.scaledX;
controller.scope.pressedScaledY = controller.scope.scaledY;
@@ -310,6 +312,8 @@ _Move.prototype.onMouseMove = function (controller) {
controller.scope.send_control_message(new messages.GroupMembership(controller.scope.client_id,
groups[i].id,
membership_old_new[2]));
controller.scope.create_group_association(groups[i], membership_old_new[6]);
controller.scope.delete_group_association(groups[i], membership_old_new[7]);
}
controller.scope.pressedScaledX = controller.scope.scaledX;
controller.scope.pressedScaledY = controller.scope.scaledY;
@@ -551,6 +555,7 @@ _Placing.prototype.onMouseDown = function (controller) {
scope.scaledX,
scope.scaledY,
false);
scope.send_control_message(new messages.GroupCreate(scope.client_id,
group.id,
group.x1,
@@ -558,8 +563,10 @@ _Placing.prototype.onMouseDown = function (controller) {
group.x2,
group.y2,
group.name,
group.type));
group.type,
group.group_id));
scope.create_inventory_group(group);
scope.groups.push(group);
scope.selected_groups.push(group);
group.selected = true;

View File

@@ -17,6 +17,22 @@ function DeviceMove(sender, id, x, y, previous_x, previous_y) {
}
exports.DeviceMove = DeviceMove;
function DeviceInventoryUpdate(sender, id, host_id) {
this.msg_type = "DeviceInventoryUpdate";
this.sender = sender;
this.id = id;
this.host_id = host_id;
}
exports.DeviceInventoryUpdate = DeviceInventoryUpdate;
function GroupInventoryUpdate(sender, id, group_id) {
this.msg_type = "GroupInventoryUpdate";
this.sender = sender;
this.id = id;
this.group_id = group_id;
}
exports.GroupInventoryUpdate = GroupInventoryUpdate;
function DeviceCreate(sender, id, x, y, name, type, host_id) {
this.msg_type = "DeviceCreate";
this.sender = sender;
@@ -290,7 +306,7 @@ function GroupMove(sender, id, x1, y1, x2, y2, previous_x1, previous_y1, previou
}
exports.GroupMove = GroupMove;
function GroupCreate(sender, id, x1, y1, x2, y2, name, type) {
function GroupCreate(sender, id, x1, y1, x2, y2, name, type, group_id) {
this.msg_type = "GroupCreate";
this.sender = sender;
this.id = id;
@@ -300,10 +316,11 @@ function GroupCreate(sender, id, x1, y1, x2, y2, name, type) {
this.y2 = y2;
this.name = name;
this.type = type;
this.group_id = group_id;
}
exports.GroupCreate = GroupCreate;
function GroupDestroy(sender, id, previous_x1, previous_y1, previous_x2, previous_y2, previous_name, previous_type) {
function GroupDestroy(sender, id, previous_x1, previous_y1, previous_x2, previous_y2, previous_name, previous_type, previous_group_id) {
this.msg_type = "GroupDestroy";
this.sender = sender;
this.id = id;
@@ -313,6 +330,7 @@ function GroupDestroy(sender, id, previous_x1, previous_y1, previous_x2, previou
this.previous_y2 = previous_y2;
this.previous_name = previous_name;
this.previous_type = previous_type;
this.previous_group_id = previous_group_id;
}
exports.GroupDestroy = GroupDestroy;

View File

@@ -29,6 +29,8 @@ function Device(id, name, x, y, type, host_id) {
this.process_id_seq = util.natural_numbers(0);
this.processes = [];
this.in_group = false;
this.template = false;
this.variables = {};
}
exports.Device = Device;
@@ -58,6 +60,29 @@ Device.prototype.is_selected = function (x, y) {
Device.prototype.describeArc = util.describeArc;
Device.prototype.compile_variables = function () {
var variables = JSON.parse(JSON.stringify(this.variables));
var awx_variables = {};
variables.awx = awx_variables;
awx_variables.name = this.name;
awx_variables.type = this.type;
awx_variables.interfaces = [];
var i = 0;
var intf = null;
for (i = 0; i < this.interfaces.length; i++) {
intf = {name: this.interfaces[i].name,
id: this.interfaces[i].id};
if (this.interfaces[i].link !== null) {
intf.link_id = this.interfaces[i].link.id;
intf.link_name = this.interfaces[i].link.name;
intf.remote_interface_name = this.interfaces[i].remote_interface().name;
intf.remote_device_name = this.interfaces[i].remote_interface().device.name;
}
awx_variables.interfaces.push(intf);
}
return variables;
};
function Interface(id, name) {
this.id = id;
this.name = name;
@@ -439,10 +464,20 @@ function Group(id, name, type, x1, y1, x2, y2, selected) {
this.links = [];
this.groups = [];
this.streams = [];
this.group_id = 0;
this.icon_size = type === 'site' ? 500 : 100;
this.template = false;
this.variables = {};
this.sequences = {};
}
exports.Group = Group;
Group.prototype.compile_variables = function () {
var variables = JSON.parse(JSON.stringify(this.variables));
return variables;
};
Group.prototype.toJSON = function () {
return {id: this.id,
@@ -634,7 +669,10 @@ Group.prototype.update_membership = function (devices, groups) {
var y2 = this.bottom_extent();
var x2 = this.right_extent();
var old_devices = this.devices;
var new_devices = [];
var removed_devices = old_devices.slice();
var device_ids = [];
var index = -1;
this.devices = [];
for (i = 0; i < devices.length; i++) {
if (devices[i].x > x1 &&
@@ -644,6 +682,12 @@ Group.prototype.update_membership = function (devices, groups) {
devices[i].in_group = true;
this.devices.push(devices[i]);
device_ids.push(devices[i].id);
index = removed_devices.indexOf(devices[i]);
if (index !== -1) {
removed_devices.splice(index, 1);
} else {
new_devices.push(devices[i]);
}
}
}
var old_groups = this.groups;
@@ -658,7 +702,7 @@ Group.prototype.update_membership = function (devices, groups) {
group_ids.push(groups[i].id);
}
}
return [old_devices, this.devices, device_ids, old_groups, this.groups, group_ids];
return [old_devices, this.devices, device_ids, old_groups, this.groups, group_ids, new_devices, removed_devices];
};
Group.prototype.is_in_breadcrumb = function(viewport){

View File

@@ -4,6 +4,7 @@ var fsm = require('./fsm.js');
var models = require('./models.js');
var messages = require('./messages.js');
var util = require('./util.js');
var nunjucks = require('nunjucks');
function _State () {
}
@@ -137,6 +138,10 @@ _Ready.prototype.onNewDevice = function (controller, msg_type, message) {
device.name,
device.type,
device.host_id));
if (scope.template_building) {
device.template = true;
}
scope.create_inventory_host(device);
scope.selected_devices.push(device);
device.selected = true;
scope.$emit('addSearchOption', device);
@@ -153,6 +158,7 @@ _Ready.prototype.onPasteDevice = function (controller, msg_type, message) {
var process = null;
var i = 0;
var c_messages = [];
var template_context = null;
scope.pressedX = scope.mouseX;
scope.pressedY = scope.mouseY;
@@ -165,6 +171,20 @@ _Ready.prototype.onPasteDevice = function (controller, msg_type, message) {
scope.scaledY,
message.device.type,
message.device.host_id);
if (!controller.scope.template_building && message.device.template) {
try {
template_context = {};
template_context.id = device.id;
controller.scope.create_template_sequences(controller.scope.sequences, device.name, template_context);
device.name = nunjucks.renderString(device.name, template_context);
scope.create_inventory_host(device);
} catch (err) {
console.log(err);
}
} else {
device.template = true;
}
device.variables = JSON.parse(message.device.variables);
scope.devices.push(device);
c_messages.push(new messages.DeviceCreate(scope.client_id,
device.id,
@@ -242,7 +262,7 @@ _Selected2.prototype.onCopySelected = function (controller) {
var i = 0;
var j = 0;
for(i=0; i < devices.length; i++) {
device_copy = new models.Device(0, devices[i].name, 0, 0, devices[i].type);
device_copy = new models.Device(0, devices[i].name, 0, 0, devices[i].type, 0);
device_copy.icon = true;
for(j=0; j < devices[i].processes.length; j++) {
process_copy = new models.Process(0, devices[i].processes[j].name, devices[i].processes[j].name, 0, 0);
@@ -252,6 +272,8 @@ _Selected2.prototype.onCopySelected = function (controller) {
interface_copy = new models.Interface(devices[i].interfaces[j].id, devices[i].interfaces[j].name);
device_copy.interfaces.push(interface_copy);
}
device_copy.variables = JSON.stringify(devices[i]);
device_copy.template = true;
controller.scope.inventory_toolbox.items.push(device_copy);
}
};
@@ -387,6 +409,8 @@ _Move.prototype.onMouseMove = function (controller) {
controller.scope.send_control_message(new messages.GroupMembership(controller.scope.client_id,
groups[i].id,
membership_old_new[2]));
controller.scope.create_group_association(groups[i], membership_old_new[6]);
controller.scope.delete_group_association(groups[i], membership_old_new[7]);
}
};

View File

@@ -5,8 +5,8 @@
*************************************************/
export default
['$scope', '$state', '$stateParams', 'GenerateForm', 'ParseTypeChange', 'HostsService', '$rootScope',
function($scope, $state, $stateParams, GenerateForm, ParseTypeChange, HostsService, $rootScope){
['$scope', '$state', '$stateParams', 'GenerateForm', 'ParseTypeChange', 'HostsService',
function($scope, $state, $stateParams, GenerateForm, ParseTypeChange, HostsService){
$scope.parseType = 'yaml';
$scope.formCancel = function(){
@@ -42,10 +42,6 @@
}
});
$scope.$watch('item', function(){
init();
});
var init = function(){
if($scope.item && $scope.item.host_id){
$scope.variables = getVars($scope.item.variables);
@@ -58,6 +54,10 @@
};
$scope.$watch('item', function(){
init();
});
// Adding this function b/c sometimes extra vars are returned to the
// UI as a string (ex: "foo: bar"), and other times as a
// json-object-string (ex: "{"foo": "bar"}"). CodeMirror wouldn't know

View File

@@ -1,5 +1,5 @@
/* eslint-disable */
function NetworkingController (models, $state, $scope, strings, CreateSelect2) {
function NetworkingController (models, $state, $scope, strings) {
const vm = this || {};
const {
@@ -93,7 +93,7 @@ function NetworkingController (models, $state, $scope, strings, CreateSelect2) {
}
});
$('#networking-search').on('select2:select', (e) => {
$('#networking-search').on('select2:select', () => {
$scope.$broadcast('search', $scope.device);
});

View File

@@ -20,6 +20,7 @@
<button class="Networking-toolbarButton" ng-click="vm.redirectButtonHandler('DownloadRecording')">DOWNLOAD RECORDING</button>
<button class="Networking-toolbarButton" ng-click="vm.redirectButtonHandler('UploadTest')">UPLOAD TEST</button>
<button class="Networking-toolbarButton" ng-click="vm.redirectButtonHandler('RunTests')">RUN TESTS</button>
<button class="Networking-toolbarButton" ng-click="vm.redirectButtonHandler('CompileVariables')">COMPILE VARIABLES</button>
</div>
<div class="Networking-toolbarRightSide">
<div class="Networking-searchBarContainer">

View File

@@ -24,13 +24,26 @@ var keybindings = require('./keybindings.fsm.js');
var details_panel_fsm = require('./details.panel.fsm.js');
var svg_crowbar = require('./svg-crowbar.js');
var ReconnectingWebSocket = require('reconnectingwebsocket');
var nunjucks = require('nunjucks');
var NetworkUIController = function($scope, $document, $location, $window, $http,
$q, $state, ProcessErrors, ConfigService, rbacUiControlService) {
var NetworkUIController = function($scope,
$document,
$location,
$window,
$http,
$q,
$state,
ProcessErrors,
ConfigService,
rbacUiControlService,
HostsService,
GroupsService) {
window.scope = $scope;
var i = 0;
$scope.nunjucks = nunjucks;
$scope.http = $http;
$scope.api_token = '';
@@ -123,12 +136,14 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
$scope.current_tests = [];
$scope.current_test = null;
$scope.testing = false;
$scope.template_building = false;
$scope.version = null;
$scope.test_events = [];
$scope.test_results = [];
$scope.test_errors = [];
$scope.streams = [];
$scope.animations = [];
$scope.sequences = {};
$scope.view_port = {'x': 0,
'y': 0,
'width': 0,
@@ -260,25 +275,44 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
//Inventory Toolbox Setup
$scope.inventory_toolbox = new models.ToolBox(0, 'Inventory', 'device', 0, toolboxTopMargin, 200, toolboxHeight);
if (!$scope.disconnected) {
console.log($location.protocol() + "://" + $location.host() + ':' + $location.port());
console.log($scope.my_location);
$http.get('/api/v2/inventories/' + $scope.inventory_id + '/hosts/')
.then(function(response) {
var devices_by_name = {};
var i = 0;
for (i = 0; i < $scope.devices.length; i++) {
devices_by_name[$scope.devices[i].name] = $scope.devices[i];
}
let hosts = response.data.results;
for(var i = 0; i<hosts.length; i++){
for(i = 0; i<hosts.length; i++) {
try {
var device_type = null;
var device_name = null;
var device = null;
let host = hosts[i];
console.log(host);
if (host.variables !== "") {
host.data = jsyaml.safeLoad(host.variables);
if (host.data.type === undefined) {
host.data.type = 'unknown';
} else {
host.data = {};
}
if (host.data.awx === undefined) {
device_type = 'unknown';
device_name = host.name;
} else {
if (host.data.awx.type === undefined) {
device_type = 'unknown';
} else {
device_type = host.data.awx.type;
}
if (host.data.name === undefined) {
host.data.name = host.name;
if (host.data.awx.name === undefined) {
device_name = host.name;
} else {
device_name = host.data.awx.name;
}
var device = new models.Device(0, host.data.name, 0, 0, host.data.type, host.id, host.variables);
}
if (devices_by_name[device_name] === undefined) {
device = new models.Device(0, device_name, 0, 0, device_type, host.id);
device.icon = true;
device.variables = JSON.stringify(host.data);
$scope.inventory_toolbox.items.push(device);
}
} catch (error) {
@@ -287,7 +321,6 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
}
})
.catch(({data, status}) => {
console.log([data, status]);
ProcessErrors($scope, data, status, null, { hdr: 'Error!', msg: 'Failed to get host data: ' + status });
});
}
@@ -744,7 +777,7 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
};
$scope.onRenameContextButton = function (button) {
$scope.onRenameContextButton = function () {
$scope.removeContextMenu();
$scope.first_channel.send("LabelEdit", {});
};
@@ -819,7 +852,8 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
group.y1,
group.x2,
group.y2,
group.name));
group.name,
group.group_id));
}
if($scope.current_scale <= 0.5){
@@ -849,7 +883,7 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
}
};
$scope.onDeleteContextMenu = function($event){
$scope.onDeleteContextMenu = function(){
$scope.removeContextMenu();
if($scope.selected_devices.length === 1){
$scope.deleteDevice();
@@ -860,7 +894,7 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
};
// Button Event Handlers
$scope.onToggleToolboxButtonLeft = function (button) {
$scope.onToggleToolboxButtonLeft = function () {
$scope.first_channel.send("ToggleToolbox", {});
$scope.action_icons[0].fsm.handle_message("Disable", {});
$scope.action_icons[1].fsm.handle_message("Enable", {});
@@ -868,7 +902,7 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
$scope.$emit('overall_toolbox_collapsed');
};
$scope.onToggleToolboxButtonRight = function (button) {
$scope.onToggleToolboxButtonRight = function () {
$scope.first_channel.send("ToggleToolbox", {});
$scope.action_icons[0].fsm.handle_message("Enable", {});
$scope.action_icons[1].fsm.handle_message("Disable", {});
@@ -890,7 +924,6 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
$scope.$on('search', function(e, device){
var num_frames = 30;
var searched;
for(var i = 0; i < $scope.devices.length; i++){
if(Number(device.id) === $scope.devices[i].id){
@@ -899,22 +932,18 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
}
searched.selected = true;
$scope.selected_devices.push(searched);
//console.log(searched);
$scope.jump_to_animation(searched.x, searched.y, 1.0);
});
$scope.jump_to_animation = function(jump_to_x, jump_to_y, jump_to_scale, updateZoom) {
$scope.cancel_animations();
var v_center = $scope.to_virtual_coordinates($scope.graph.width/2, $scope.graph.height/2);
//console.log({v_center: v_center});
$scope.jump.from_x = v_center.x;
$scope.jump.from_y = v_center.y;
$scope.jump.to_x = jump_to_x;
$scope.jump.to_y = jump_to_y;
var distance = util.distance(v_center.x, v_center.y, jump_to_x, jump_to_y);
//console.log({distance: distance});
var num_frames = 30 * Math.floor((1 + 4 * distance / (distance + 3000)));
//console.log({num_frames: num_frames});
var scale_animation = new models.Animation($scope.animation_id_seq(),
num_frames,
{
@@ -964,19 +993,19 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
$scope.$on('zoom', (e, zoomPercent) => {
let v_center = $scope.to_virtual_coordinates($scope.graph.width/2, $scope.graph.height/2);
let scale = Math.pow(10, (zoomPercent - 120) / 40)
let scale = Math.pow(10, (zoomPercent - 120) / 40);
$scope.jump_to_animation(v_center.x, v_center.y, scale, false);
});
$scope.onDeployButton = function (button) {
$scope.onDeployButton = function () {
$scope.send_control_message(new messages.Deploy($scope.client_id));
};
$scope.onDestroyButton = function (button) {
$scope.onDestroyButton = function () {
$scope.send_control_message(new messages.Destroy($scope.client_id));
};
$scope.onRecordButton = function (button) {
$scope.onRecordButton = function () {
$scope.recording = ! $scope.recording;
if ($scope.recording) {
$scope.trace_id = $scope.trace_id_seq();
@@ -1007,7 +1036,7 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
}
};
$scope.onExportButton = function (button) {
$scope.onExportButton = function () {
$scope.cursor.hidden = true;
$scope.debug.hidden = true;
$scope.hide_buttons = true;
@@ -1019,34 +1048,10 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
}, 1000);
};
$scope.onLayoutButton = function (button) {
$scope.onLayoutButton = function () {
$scope.send_control_message(new messages.Layout($scope.client_id));
};
$scope.onDiscoverButton = function (button) {
var xhr = new XMLHttpRequest();
xhr.open("POST", "http://" + window.location.host + "/api/v1/job_templates/7/launch/", true);
xhr.onload = function () {
console.log(xhr.readyState);
};
xhr.onerror = function () {
console.error(xhr.statusText);
};
xhr.send();
};
$scope.onConfigureButton = function (button) {
var xhr = new XMLHttpRequest();
xhr.open("POST", "http://" + window.location.host + "/api/v1/job_templates/9/launch/", true);
xhr.onload = function () {
console.log(xhr.readyState);
};
xhr.onerror = function () {
console.error(xhr.statusText);
};
xhr.send();
};
$scope.onTogglePhysical = function () {
$scope.hide_links = false;
};
@@ -1065,7 +1070,7 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
};
$scope.onExportYamlButton = function (button) {
$scope.onExportYamlButton = function () {
$window.open('/network_ui/topology.yaml?topology_id=' + $scope.topology_id , '_blank');
};
@@ -1088,27 +1093,55 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
new models.ActionIcon("chevron-right", 15, actionIconVerticalOffset, 16, $scope.onToggleToolboxButtonRight, false, $scope)
];
$scope.onDownloadTraceButton = function (button) {
$scope.onDownloadTraceButton = function () {
window.open("/network_ui/download_trace?topology_id=" + $scope.topology_id + "&trace_id=" + $scope.trace_id + "&client_id=" + $scope.client_id);
};
$scope.onDownloadRecordingButton = function (button) {
$scope.onDownloadRecordingButton = function () {
window.open("/network_ui/download_recording?topology_id=" + $scope.topology_id + "&trace_id=" + $scope.trace_id + "&client_id=" + $scope.client_id);
};
$scope.onUploadTestButton = function (button) {
$scope.onUploadTestButton = function () {
window.open("/network_ui/upload_test", "_top");
};
$scope.onRunTestsButton = function (button) {
$scope.onRunTestsButton = function () {
$scope.test_results = [];
$scope.current_tests = $scope.tests.slice();
$scope.first_channel.send("EnableTest", new messages.EnableTest());
};
// Buttons
var button_offset = 200;
$scope.onCompileVariablesButton = function () {
function noop (response) {
console.log(response);
}
function error_handler (response) {
console.log(response);
}
var i = 0;
var variables = null;
for(i = 0; i < $scope.devices.length; i++) {
variables = $scope.devices[i].compile_variables();
if ($scope.devices[i].host_id !== 0) {
$http.put('/api/v2/hosts/' + $scope.devices[i].host_id + '/variable_data/', JSON.stringify(variables)).then(noop).catch(error_handler);
}
}
for(i = 0; i < $scope.groups.length; i++) {
variables = $scope.groups[i].compile_variables();
if ($scope.groups[i].group_id !== 0) {
$http.put('/api/v2/groups/' + $scope.groups[i].group_id + '/variable_data/', JSON.stringify(variables)).then(noop).catch(error_handler);
}
}
};
$scope.buttons = [
// new models.Button("DEPLOY", button_offset + 10, 48, 70, 30, $scope.onDeployButton, $scope),
@@ -1193,6 +1226,7 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
return null;
};
$scope.getDeviceInterface = function(device_name, interface_name) {
var i = 0;
@@ -1209,11 +1243,157 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
return null;
};
$scope.create_template_sequences = function (sequences, template, template_context) {
var i = 0;
var template_variables = util.nunjucks_find_variables(template);
for (i = 0; i < template_variables.length; i++) {
if (template_context[template_variables[i]] === undefined) {
if (sequences[template_variables[i]] === undefined) {
sequences[template_variables[i]] = util.natural_numbers(0);
}
template_context[template_variables[i]] = sequences[template_variables[i]]();
}
}
};
$scope.create_inventory_host = function (device) {
if ($scope.template_building || device.template) {
return;
}
console.log(device);
function update_inventory () {
HostsService.post({inventory: $scope.inventory_id,
name: device.name,
variables: JSON.stringify({awx: {name: device.name,
type: device.type}})})
.then(function (res) {
console.log(res);
device.host_id = res.data.id;
device.variables = util.parse_variables(res.data.variables);
$scope.send_control_message(new messages.DeviceInventoryUpdate($scope.client_id,
device.id,
device.host_id));
})
.catch(function (res) {
console.log(res);
});
}
return HostsService.get({inventory: $scope.inventory_id,
name: device.name})
.then(function (res) {
console.log(res);
if (res.data.count === 0) {
update_inventory();
} else if (res.data.count === 1) {
device.host_id = res.data.results[0].id;
device.variables = util.parse_variables(res.data.results[0].variables);
$scope.send_control_message(new messages.DeviceInventoryUpdate($scope.client_id,
device.id,
device.host_id));
}
})
.catch(function (res) {
console.log(res);
});
};
$scope.create_inventory_group = function (group) {
if ($scope.template_building || group.template) {
return;
}
console.log(group);
function update_inventory () {
GroupsService.post({inventory: $scope.inventory_id,
name: group.name,
variables: JSON.stringify({awx: {name: group.name,
type: group.type}})})
.then(function (res) {
console.log(res);
group.group_id = res.data.id;
group.variables = util.parse_variables(res.data.variables);
$scope.send_control_message(new messages.GroupInventoryUpdate($scope.client_id,
group.id,
group.group_id));
})
.catch(function (res) {
console.log(res);
});
}
return GroupsService.get({inventory: $scope.inventory_id,
name: group.name})
.then(function (res) {
console.log(res);
if (res.data.count === 0) {
update_inventory();
} else if (res.data.count === 1) {
group.group_id = res.data.results[0].id;
group.variables = util.parse_variables(res.data.results[0].variables);
$scope.send_control_message(new messages.GroupInventoryUpdate($scope.client_id,
group.id,
group.group_id));
}
})
.catch(function (res) {
console.log(res);
});
};
$scope.create_group_association = function (group, devices) {
if ($scope.template_building || group.template) {
return;
}
console.log(['create_group_association', group, devices]);
function noop (response) {
console.log(response);
}
function error_handler (response) {
console.log(response);
}
var i = 0;
for (i = 0; i < devices.length; i ++) {
if (!devices[i].template) {
$http.post('/api/v2/groups/' + group.group_id + '/hosts/', JSON.stringify({name: devices[i].name})).then(noop).catch(error_handler);
}
}
};
$scope.delete_group_association = function (group, devices) {
if ($scope.template_building || group.template) {
return;
}
console.log(['delete_group_association', group, devices]);
function noop (response) {
console.log(response);
}
function error_handler (response) {
console.log(response);
}
var i = 0;
for (i = 0; i < devices.length; i ++) {
if (!devices[i].template) {
GroupsService.disassociateHost(devices[i].host_id, group.group_id).then(noop).catch(error_handler);
}
}
};
$scope.onDeviceCreate = function(data) {
$scope.create_device(data);
};
$scope.create_device = function(data) {
console.log(data);
var device = new models.Device(data.id,
data.name,
data.x,
@@ -1591,7 +1771,7 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
$scope.onToolboxItem = function (data) {
if (data.toolbox_name === "Site") {
var site = JSON.parse(data.data);
var site = util.parse_variables(data.data);
var i = 0;
var j = 0;
var site_copy = new models.Group(site.id,
@@ -1727,8 +1907,15 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
device.name,
device.x,
device.y,
device.type,
device.device_type,
device.host_id);
for (j=0; j < $scope.inventory_toolbox.items.length; j++) {
if($scope.inventory_toolbox.items[j].name === device.name) {
$scope.inventory_toolbox.items.splice(j, 1);
break;
}
}
new_device.interface_seq = util.natural_numbers(device.interface_id_seq);
new_device.process_id_seq = util.natural_numbers(device.process_id_seq);
$scope.devices.push(new_device);
@@ -1738,7 +1925,7 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
process = device.processes[j];
new_process = (new models.Process(process.id,
process.name,
process.type,
process.process_type,
0,
0));
new_process.device = new_device;
@@ -1795,12 +1982,13 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
}
new_group = new models.Group(group.id,
group.name,
group.type,
group.group_type,
group.x1,
group.y1,
group.x2,
group.y2,
false);
new_group.group_id = group.inventory_group_id;
if (group.members !== undefined) {
for (j=0; j < group.members.length; j++) {
new_group.devices.push(device_map[group.members[j]]);
@@ -1859,6 +2047,36 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
$scope.updateInterfaceDots();
$scope.$emit('instatiateSelect', $scope.devices);
$scope.$emit('awxNet-breadcrumbGroups', $scope.breadcrumbGroups());
$scope.update_device_variables();
};
$scope.update_device_variables = function () {
var hosts_by_id = {};
var i = 0;
for (i = 0; i < $scope.devices.length; i++) {
hosts_by_id[$scope.devices[i].host_id] = $scope.devices[i];
}
$http.get('/api/v2/inventories/' + $scope.inventory_id + '/hosts/')
.then(function(response) {
let hosts = response.data.results;
for(var i = 0; i<hosts.length; i++){
try {
let host = hosts[i];
if (hosts_by_id[host.id] !== undefined) {
hosts_by_id[host.id].variables = util.parse_variables(host.variables);
}
} catch (error) {
console.log(error);
}
}
})
.catch(({data, status}) => {
console.log([data, status]);
ProcessErrors($scope, data, status, null, { hdr: 'Error!', msg: 'Failed to get host data: ' + status });
});
};
$scope.updateInterfaceDots = function() {

View File

@@ -106,5 +106,6 @@
<g awx-net-debug></g>
<g awx-net-test-results></g>
<g awx-net-cursor></g>
<g ng-if="template_building"><text stroke="none" fill="red" font-size="48" ng-attr-x="{{graph.width/2}}" ng-attr-y="200">TEMPLATE BUILDING</text></g>
</svg>
</div>

View File

@@ -3,6 +3,7 @@ var inherits = require('inherits');
var fsm = require('./fsm.js');
var models = require('./models.js');
var messages = require('./messages.js');
var nunjucks = require('nunjucks');
function _State () {
}
@@ -95,6 +96,9 @@ _Ready.prototype.onPasteRack = function (controller, msg_type, message) {
var top_left_x, top_left_y;
var device_map = {};
var c_messages = [];
var rack_template_context = null;
var device_template_context = null;
var promises = [];
scope.hide_groups = false;
scope.pressedX = scope.mouseX;
@@ -113,6 +117,18 @@ _Ready.prototype.onPasteRack = function (controller, msg_type, message) {
top_left_y + message.group.y2,
false);
if (!controller.scope.template_building && message.group.template) {
try {
rack_template_context = {};
rack_template_context.id = group.id;
controller.scope.create_template_sequences(controller.scope.sequences, group.name, rack_template_context);
group.name = nunjucks.renderString(group.name, rack_template_context);
promises.push(scope.create_inventory_group(group));
} catch (err) {
console.log(err);
}
}
c_messages.push(new messages.GroupCreate(scope.client_id,
group.id,
group.x1,
@@ -120,10 +136,19 @@ _Ready.prototype.onPasteRack = function (controller, msg_type, message) {
group.x2,
group.y2,
group.name,
group.type));
group.type,
0));
scope.groups.push(group);
if (!controller.scope.template_building && message.group.template) {
device_template_context = Object.assign({}, rack_template_context);
device_template_context.rack_id = group.id;
for(i=0; i<message.group.devices.length;i++) {
controller.scope.create_template_sequences(group.sequences, message.group.devices[i].name, device_template_context);
}
}
for(i=0; i<message.group.devices.length;i++) {
device = new models.Device(controller.scope.device_id_seq(),
@@ -133,8 +158,19 @@ _Ready.prototype.onPasteRack = function (controller, msg_type, message) {
message.group.devices[i].type);
device_map[message.group.devices[i].id] = device;
device.interface_map = {};
device.in_group = true;
scope.devices.push(device);
group.devices.push(device);
if (!controller.scope.template_building && message.group.template) {
try {
device_template_context.id = device.id;
device.name = nunjucks.renderString(device.name, device_template_context);
promises.push(scope.create_inventory_host(device));
} catch (err) {
console.log(err);
}
}
c_messages.push(new messages.DeviceCreate(scope.client_id,
device.id,
device.x,
@@ -189,6 +225,14 @@ _Ready.prototype.onPasteRack = function (controller, msg_type, message) {
}
scope.send_control_message(new messages.MultipleMessage(controller.scope.client_id, c_messages));
Promise.all(promises)
.then(function () {
controller.scope.create_group_association(group, group.devices);
})
.catch(function(res) {
console.log(res);
});
};
@@ -262,6 +306,8 @@ _Selected2.prototype.onCopySelected = function (controller) {
device_copy.interfaces.push(interface_copy);
device_copy.interface_map[interface_copy.id] = interface_copy;
}
device_copy.variables = JSON.stringify(devices[j].variables);
device_copy.template = true;
group_copy.devices.push(device_copy);
}
@@ -286,6 +332,8 @@ _Selected2.prototype.onCopySelected = function (controller) {
}
}
group_copy.variables = JSON.stringify(group.variables);
group_copy.template = true;
controller.scope.rack_toolbox.items.push(group_copy);
}
};

View File

@@ -3,6 +3,7 @@ var inherits = require('inherits');
var fsm = require('./fsm.js');
var models = require('./models.js');
var messages = require('./messages.js');
var nunjucks = require('nunjucks');
function _State () {
}
@@ -100,6 +101,10 @@ _Ready.prototype.onPasteSite = function (controller, msg_type, message) {
var inner_group = null;
var c_messages = [];
var membership_old_new = null;
var site_template_context = null;
var rack_template_context = null;
var device_template_context = null;
var promises = [];
scope.hide_groups = false;
scope.pressedX = scope.mouseX;
@@ -125,7 +130,8 @@ _Ready.prototype.onPasteSite = function (controller, msg_type, message) {
group.x2,
group.y2,
group.name,
group.type));
group.type,
0));
scope.groups.push(group);
@@ -225,7 +231,8 @@ _Ready.prototype.onPasteSite = function (controller, msg_type, message) {
inner_group.x2,
inner_group.y2,
inner_group.name,
inner_group.type));
inner_group.type,
0));
}
for(i=0; i< group.groups.length; i++) {
membership_old_new = group.groups[i].update_membership(scope.devices, scope.groups);
@@ -239,7 +246,73 @@ _Ready.prototype.onPasteSite = function (controller, msg_type, message) {
group.id,
membership_old_new[2]));
if (!controller.scope.template_building && message.group.template) {
try {
site_template_context = {};
site_template_context.id = group.id;
controller.scope.create_template_sequences(controller.scope.sequences, group.name, site_template_context);
group.name = nunjucks.renderString(group.name, site_template_context);
promises.push(scope.create_inventory_group(group));
c_messages.push(new messages.GroupLabelEdit(controller.scope.client_id,
group.id,
group.name,
group.name));
rack_template_context = Object.assign({}, site_template_context);
rack_template_context.site_id = group.id;
for (i = 0; i < group.groups.length; i++) {
controller.scope.create_template_sequences(group.sequences,
group.groups[i].name,
rack_template_context);
}
for (i = 0; i < group.groups.length; i++) {
rack_template_context.id = group.groups[i].id;
group.groups[i].name = nunjucks.renderString(group.groups[i].name, rack_template_context);
promises.push(scope.create_inventory_group(group.groups[i]));
c_messages.push(new messages.GroupLabelEdit(controller.scope.client_id,
group.groups[i].id,
group.groups[i].name,
group.groups[i].name));
if (group.groups[i].type !== "rack") {
continue;
}
device_template_context = Object.assign({}, rack_template_context);
device_template_context.rack_id = group.groups[i].id;
for(j=0; j<group.groups[i].devices.length;j++) {
controller.scope.create_template_sequences(group.groups[i].sequences,
group.groups[i].devices[j].name,
device_template_context);
}
for (j=0; j < group.groups[i].devices.length; j++) {
device_template_context.id = group.groups[i].devices[j].id;
group.groups[i].devices[j].name = nunjucks.renderString(group.groups[i].devices[j].name, device_template_context);
console.log(group.groups[i].devices[j].name);
promises.push(scope.create_inventory_host(group.groups[i].devices[j]));
c_messages.push(new messages.DeviceLabelEdit(controller.scope.client_id,
group.groups[i].devices[j].id,
group.groups[i].devices[j].name,
group.groups[i].devices[j].name));
}
}
} catch (err) {
console.log(err);
}
}
scope.send_control_message(new messages.MultipleMessage(controller.scope.client_id, c_messages));
Promise.all(promises)
.then(function () {
controller.scope.create_group_association(group, group.devices);
for (i = 0; i < group.groups.length; i++) {
controller.scope.create_group_association(group.groups[i], group.groups[i].devices);
}
})
.catch(function(res) {
console.log(res);
});
};
@@ -297,6 +370,7 @@ _Selected2.prototype.onCopySelected = function (controller) {
group.bottom_extent() - group.top_extent(),
false);
group_copy.icon = true;
group_copy.template = true;
devices = group.devices;

View File

@@ -83,14 +83,13 @@ _Dropping.prototype.start = function (controller) {
var i = 0;
var toolbox = controller.toolbox;
console.log(["Dropping", toolbox.selected_item]);
for(i = 0; i < toolbox.items.length; i++) {
toolbox.items[i].selected = false;
}
controller.dropped_action(toolbox.selected_item);
if (controller.remove_on_drop) {
if (controller.remove_on_drop && !toolbox.selected_item.template) {
var dindex = toolbox.items.indexOf(toolbox.selected_item);
if (dindex !== -1) {
toolbox.items.splice(dindex, 1);
@@ -213,7 +212,8 @@ _Scrolling.prototype.onMouseWheel = function (controller, msg_type, $event) {
var delta = $event[1];
controller.toolbox.scroll_offset += -1 * delta;
controller.toolbox.scroll_offset = Math.min(controller.toolbox.scroll_offset, 0);
controller.toolbox.scroll_offset = Math.max(controller.toolbox.scroll_offset, -1 * controller.toolbox.spacing * controller.toolbox.items.length + controller.toolbox.height);
controller.toolbox.scroll_offset = Math.max(controller.toolbox.scroll_offset,
-1 * controller.toolbox.spacing * (controller.toolbox.items.length + 1) + controller.toolbox.height);
controller.changeState(Ready);

View File

@@ -7,8 +7,53 @@ Array.prototype.extend = function (other_array) {
}
};
var math = require('mathjs');
var yaml = require('js-yaml');
var nunjucks = require('nunjucks');
function nunjucks_find_variables (text) {
var variables = [];
var tokenizer = nunjucks.lexer.lex(text, {});
var token = tokenizer.nextToken();
while (token !== null) {
if (token.type === 'variable-start') {
token = tokenizer.nextToken();
while (token !== null) {
if (token.type === 'symbol') {
variables.push(token.value);
}
if (token.type === 'variable-end') {
break;
}
token = tokenizer.nextToken();
}
}
token = tokenizer.nextToken();
}
return variables;
}
exports.nunjucks_find_variables = nunjucks_find_variables;
function parse_variables (variables) {
var parsed_variables = {};
try {
parsed_variables = JSON.parse(variables);
} catch (err) {
try {
parsed_variables = yaml.safeLoad(variables);
} catch (err) {
parsed_variables = {};
}
}
if (parsed_variables === undefined) {
return {};
}
return parsed_variables;
}
exports.parse_variables = parse_variables;
function noop () {
}