Move socket helper to a service and remove old code

This commit is contained in:
Jared Tabor 2016-08-30 14:27:20 -07:00
parent 3d979bb661
commit a091069d9d
11 changed files with 205 additions and 329 deletions

View File

@ -75,7 +75,7 @@ import './shared/Modal';
import './shared/prompt-dialog';
import './shared/directives';
import './shared/filters';
import './shared/Socket';
import socket from './shared/socket/main';
import './shared/features/main';
import config from './shared/config/main';
import './login/authenticationServices/pendo/ng-pendo';
@ -183,7 +183,6 @@ var tower = angular.module('Tower', [
'HostGroupsFormDefinition',
'StreamWidget',
'JobsHelper',
'InventoryGroupsHelpDefinition',
'CredentialsHelper',
'StreamListDefinition',
'ActivityDetailDefinition',
@ -197,10 +196,9 @@ var tower = angular.module('Tower', [
'StandardOutHelper',
'LogViewerOptionsDefinition',
'JobDetailHelper',
'SocketIO',
'socket',
'lrInfiniteScroll',
'LoadConfigHelper',
'SocketHelper',
'PortalJobsListDefinition',
'features',
'longDateFilter',
@ -528,15 +526,15 @@ var tower = angular.module('Tower', [
.run(['$q', '$compile', '$cookieStore', '$rootScope', '$log',
'CheckLicense', '$location', 'Authorization', 'LoadBasePaths', 'Timer',
'ClearScope', 'Socket', 'LoadConfig', 'Store',
'ShowSocketHelp', 'pendoService', 'Prompt', 'Rest', 'Wait',
'ClearScope', 'LoadConfig', 'Store',
'pendoService', 'Prompt', 'Rest', 'Wait',
'ProcessErrors', '$state', 'GetBasePath', 'ConfigService',
'FeaturesService', '$filter',
'FeaturesService', '$filter', 'SocketService',
function($q, $compile, $cookieStore, $rootScope, $log, CheckLicense,
$location, Authorization, LoadBasePaths, Timer, ClearScope, Socket,
LoadConfig, Store, ShowSocketHelp, pendoService, Prompt, Rest, Wait,
$location, Authorization, LoadBasePaths, Timer, ClearScope,
LoadConfig, Store, pendoService, Prompt, Rest, Wait,
ProcessErrors, $state, GetBasePath, ConfigService, FeaturesService,
$filter) {
$filter, SocketService) {
var sock;
$rootScope.addPermission = function(scope) {
$compile("<add-permissions class='AddPermissions'></add-permissions>")(scope);
@ -792,35 +790,35 @@ var tower = angular.module('Tower', [
// }
$rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState) {
if(toState.name === 'dashboard'){
$rootScope.socket.emit('{"groups":{"jobs": ["status_changed"]}}');
SocketService.emit('{"groups":{"jobs": ["status_changed"]}}');
console.log(toState.name);
}
else if(toState.name === 'jobDetail'){
$rootScope.socket.emit(`{"groups":{"jobs": ["status_changed", "summary"] , "job_events":[${toParams.id}]}}`);
SocketService.emit(`{"groups":{"jobs": ["status_changed", "summary"] , "job_events":[${toParams.id}]}}`);
console.log(toState.name);
}
else if(toState.name === 'jobStdout'){
$rootScope.socket.emit('{"groups":{"jobs": ["status_changed"]}}');
SocketService.emit('{"groups":{"jobs": ["status_changed"]}}');
console.log(toState.name);
}
else if(toState.name === 'jobs'){
$rootScope.socket.emit('{"groups":{"jobs": ["status_changed"] , "schedules": ["changed"]}}');
SocketService.emit('{"groups":{"jobs": ["status_changed"] , "schedules": ["changed"]}}');
console.log(toState.name);
}
else if(toState.name === 'portalMode'){
$rootScope.socket.emit('{"groups":{"jobs": ["status_changed"]}}');
SocketService.emit('{"groups":{"jobs": ["status_changed"]}}');
console.log(toState.name);
}
else if(toState.name === 'projects'){
$rootScope.socket.emit('{"groups":{"jobs": ["status_changed"]}}');
SocketService.emit('{"groups":{"jobs": ["status_changed"]}}');
console.log(toState.name);
}
else if(toState.name === 'inventory'){
$rootScope.socket.emit('{"groups":{"jobs": ["status_changed"]}}');
SocketService.emit('{"groups":{"jobs": ["status_changed"]}}');
console.log(toState.name);
}
else if(toState.name === 'adHocJobStdout'){
$rootScope.socket.emit(`{"groups":{"ad_hoc_command_events": [${toParams.id}]}}`);
SocketService.emit(`{"groups":{"ad_hoc_command_events": [${toParams.id}]}}`);
console.log(toState.name);
}
});
@ -882,7 +880,8 @@ var tower = angular.module('Tower', [
ConfigService.getConfig().then(function() {
Timer.init().then(function(timer) {
$rootScope.sessionTimer = timer;
$rootScope.$emit('OpenSocket');
// $rootScope.$emit('OpenSocket');
SocketService.init();
pendoService.issuePendoIdentity();
CheckLicense.test();
FeaturesService.get();
@ -910,10 +909,6 @@ var tower = angular.module('Tower', [
$('#' + tabs + ' #' + tab).tab('show');
};
$rootScope.socketHelp = function() {
ShowSocketHelp();
};
$rootScope.leavePortal = function() {
$rootScope.portalMode = false;
$location.path('/home/');

View File

@ -4,7 +4,4 @@
* All Rights Reserved
*************************************************/
import "./help/ChromeSocketHelp";
import "./help/FirefoxSocketHelp";
import "./help/InventoryGroups";
import "./help/SafariSocketHelp";

View File

@ -1,47 +0,0 @@
/*************************************************
* Copyright (c) 2015 Ansible, Inc.
*
* All Rights Reserved
*************************************************/
/**
* @ngdoc overview
* @name help
* @description These are the modal windows that are shown to the user to give additional guidance on certain tasks that might not be straightforward.
*/
/**
* @ngdoc function
* @name help.function:ChromeSocketHelp
* @description This help modal gives instructions on what the user should do if not connected to the web sockets while using Chrome.
*/
angular.module('ChromeSocketHelpDefinition', [])
.value('ChromeSocketHelp', {
story: {
hdr: 'Live Events',
width: 510,
height: 560,
steps: [{
intro: 'Connection status indicator:',
img: {
src: 'socket_indicator.png',
maxWidth: 360
},
box: "<p><i class=\"fa icon-socket-ok\"></i> indicates live events are streaming and the browser is connected to the live events server.</p><p>If the indicator continually shows <i class=\"fa icon-socket-error\"></i> " +
"or <i class=\"fa icon-socket-connecting\"></i>, then live events are not streaming, and the browser is having difficulty connecting to the live events server. In this case click Next for troubleshooting help.</p>"
}, {
intro: 'Live events connection:',
icon: {
"class": "fa fa-5x fa-rss {{ socketStatus }}-color",
style: "margin-top: 75px;",
containerHeight: 200
},
box: "<p><strong>{{ browserName }}</strong> is connecting to the live events server on port <strong>{{ socketPort }}</strong>. The current connection status is " +
"<i class=\"fa icon-socket-{{ socketStatus }}\"></i> <strong>{{ socketStatus }}</strong>.</p><p>If the connection status indicator is not green, have the " +
"system administrator verify this is the correct port and that access to the port is not blocked by a firewall."
}]
}
});

View File

@ -1,78 +0,0 @@
/*************************************************
* Copyright (c) 2015 Ansible, Inc.
*
* All Rights Reserved
*************************************************/
/**
* @ngdoc function
* @name help.function:FirefoxSocketHelp
* @description This help modal gives instructions on what the user should do if not connected to the web sockets while using Firefox.
*/
angular.module('FFSocketHelpDefinition', [])
.value('FFSocketHelp', {
story: {
hdr: 'Live Events',
width: 510,
height: 560,
steps: [{
intro: 'Connection status indicator:',
img: {
src: 'socket_indicator.png',
maxWidth: 360
},
box: "<p><i class=\"fa icon-socket-ok\"></i> indicates live events are streaming and the browser is connected to the live events server.</p><p>If the indicator continually shows <i class=\"fa icon-socket-error\"></i> " +
"or <i class=\"fa icon-socket-connecting\"></i>, then live events are not streaming, and the browser is having difficulty connecting to the live events server. In this case click Next for troubleshooting help.</p>"
}, {
intro: 'Live events connection:',
icon: {
"class": "fa fa-5x fa-rss {{ socketStatus }}-color",
style: "margin-top: 75px;",
containerHeight: 200
},
box: "<p><strong>{{ browserName }}</strong> is connecting to the live events server on port <strong>{{ socketPort }}</strong>. The current connection status is " +
"<i class=\"fa icon-socket-{{ socketStatus }}\"></i> <strong>{{ socketStatus }}</strong>.</p><p>If the connection status indicator is not green, have the " +
"system administrator verify this is the correct port and that access to the port is not blocked by a firewall.</p>"
}, {
intro: 'Self signed certificate:',
icon: {
"class": "fa fa-5x fa-check ok-color",
style: "margin-top: 75px;",
containerHeight: 200
},
box: "<p>If the Tower web server is using a self signed security certificate, Firefox needs to accept the certificate and allow the " +
"connection.</p><p>Click Next for help accepting a self signed certificate.</p>"
}, {
intro: 'Accepting a self-signed certificate:',
img: {
src: 'understand_the_risk.png',
maxWidth: 440
},
box: "<p>Navigate to <a href=\"{{ socketURL }}\" target=\"_blank\">{{ socketURL }}</a> The above warning will appear.</p><p>Click <i>I Understand the Risks</i></p>"
}, {
intro: 'Accepting a self-signed certificate:',
img: {
src: 'add_exception.png',
maxWidth: 440
},
box: "<p>Click the <i>Add Exception</i> button."
}, {
intro: 'Accepting a self-signed certificate:',
img: {
src: 'confirm_exception.png',
maxWidth: 340
},
box: "<p>Click the <i>Confirm the Security Exception</i> button. This will add the self signed certificate from the Tower server to Firefox's list of trusted certificates.<p>"
}, {
intro: 'Accepting a self-signed certificate:',
img: {
src: 'refresh_firefox.png',
maxWidth: 480
},
box: "<p>Now that Firefox has accepted the security certificate the live event connection status indicator should turn green. If it does not, reload Tower by clicking the " +
"Firefox refresh button."
}]
}
});

View File

@ -1,86 +0,0 @@
/*************************************************
* Copyright (c) 2015 Ansible, Inc.
*
* All Rights Reserved
*************************************************/
/**
* @ngdoc function
* @name help.function:InventoryGroups
* @description This help modal walks the user how to add groups to an inventory or a subgroup to an existing group.
*/
angular.module('InventoryGroupsHelpDefinition', [])
.value('InventoryGroupsHelp', {
story: {
hdr: 'Inventory Setup',
width: 510,
height: 560,
steps: [{
intro: 'Start by creating a group:',
img: {
src: 'groups001.png',
maxWidth: 257,
maxHeight: 114
},
box: "Click <i class=\"fa fa-plus\"></i> on the groups list (the left side of the page) to add a new group.",
autoOffNotice: true
}, {
intro: 'Enter group properties:',
img: {
src: 'groups002.png',
maxWidth: 443,
maxHeight: 251
},
box: 'Enter the group name, a description and any inventory variables. Variables can be entered using either JSON or YAML syntax. ' +
'For more on inventory variables, see <a href=\"http://docs.ansible.com/intro_inventory.html\" target="_blank"> ' +
'docs.ansible.com/intro_inventory.html</a>'
}, {
intro: 'Cloud inventory: select cloud source',
img: {
src: 'groups003.png',
maxWidth: 412,
maxHeight: 215
},
box: "For a cloud inventory, choose the cloud provider from the list and select your credentials. If you have not already setup " +
"credentials for the provider, you will need to do that first on the <a href=\"/#/credentials\" " +
"target=\"_blank\">Credentials</a> tab."
}, {
intro: 'Cloud inventory: synchronize Tower with the cloud',
img: {
src: 'groups004.png',
maxWidth: 187,
maxHeight: 175
},
box: "To import a cloud inventory into Tower, initiate an inventory sync by clicking <i class=\"fa fa-refresh\"></i>."
}, {
intro: "Add subgroups:",
img: {
src: 'groups008.png',
maxWidth: 469,
maxHeight: 243
},
box: "<div class=\"text-left\">First, select an existing group.</div>"
}, {
intro: "Add subgroups:",
img: {
src: 'groups009.png',
maxWidth: 475,
maxHeight: 198
},
box: "<div class=\"text-left\">Then click <i class=\"fa fa-plus\"></i> to create a new group. The new group " +
"will be added to the selected group.</div>"
}, {
intro: 'Add hosts:',
img: {
src: 'groups010.png',
maxWidth: 475,
maxHeight: 122
},
box: "<div class=\"text-left\"><p>First, select a Group. " +
"Then click <i class=\"fa fa-plus\"></i> on the hosts list (the right side of the page) to create a host. " +
"The new host will be part of the selected group.</p></div>"
}]
}
});

View File

@ -1,50 +0,0 @@
/*************************************************
* Copyright (c) 2015 Ansible, Inc.
*
* All Rights Reserved
*************************************************/
/**
* @ngdoc function
* @name help.function:SafariSocketHelp
* @description This help modal gives instructions on what the user should do if not connected to the web sockets while using Safari. Safari does not support websockets.
*/
angular.module('SafariSocketHelpDefinition', [])
.value('SafariSocketHelp', {
story: {
hdr: 'Live Events',
width: 510,
height: 560,
steps: [{
intro: 'Connection status indicator:',
img: {
src: 'socket_indicator.png',
maxWidth: 360
},
box: "<p><i class=\"fa icon-socket-ok\"></i> indicates live events are streaming and the browser is connected to the live events server.</p><p>If the indicator continually shows <i class=\"fa icon-socket-error\"></i> " +
"or <i class=\"fa icon-socket-connecting\"></i>, then live events are not streaming, and the browser is having difficulty connecting to the live events server. In this case click Next for troubleshooting help.</p>"
}, {
intro: 'Live events connection:',
icon: {
"class": "fa fa-5x fa-rss {{ socketStatus }}-color",
style: "margin-top: 75px;",
containerHeight: 200
},
box: "<p><strong>{{ browserName }}</strong> is connecting to the live events server on port <strong>{{ socketPort }}</strong>. The current connection status is " +
"<i class=\"fa icon-socket-{{ socketStatus }}\"></i> <strong>{{ socketStatus }}</strong>.</p><p>If the connection status indicator is not green, have the " +
"system administrator verify this is the correct port and that access to the port is not blocked by a firewall.</p>"
}, {
intro: 'Self signed certificate:',
icon: {
"class": "fa fa-5x fa-check ok-color",
style: "margin-top: 75px;",
containerHeight: 200
},
box: "<p>Safari will not connect to the live event port when the Tower web server is configured with a self signed certificate. Check with a system administrator to " +
"determine if Tower is using a self signed certificate. Installing a signed certificate will fix the problem.</p>" +
"<p>Switching browsers to either Chrome or Firefox will work as well.</p>"
}]
}
});

View File

@ -23,7 +23,6 @@ import ProjectPath from "./helpers/ProjectPath";
import Projects from "./helpers/Projects";
import Schedules from "./helpers/Schedules";
import Selection from "./helpers/Selection";
import SocketHelper from "./helpers/SocketHelper";
import Users from "./helpers/Users";
import Variables from "./helpers/Variables";
import ApiDefaults from "./helpers/api-defaults";
@ -55,7 +54,6 @@ export
Projects,
Schedules,
Selection,
SocketHelper,
Users,
Variables,
ApiDefaults,

View File

@ -1,39 +0,0 @@
/*************************************************
* Copyright (c) 2015 Ansible, Inc.
*
* All Rights Reserved
*************************************************/
/**
* @ngdoc function
* @name helpers.function:SocketHelper
* @description
* SocketHelper.js
*
* Show web socket troubleshooting help
*
*/
export default
angular.module('SocketHelper', ['Utilities', 'FFSocketHelpDefinition', 'SafariSocketHelpDefinition' , 'ChromeSocketHelpDefinition'])
.factory('ShowSocketHelp', ['$location', '$rootScope', 'FFSocketHelp', 'SafariSocketHelp', 'ChromeSocketHelp', 'HelpDialog', 'browserData',
function($location, $rootScope, FFSocketHelp, SafariSocketHelp, ChromeSocketHelp, HelpDialog, browserData) {
return function() {
var scope = $rootScope.$new();
scope.socketPort = $AnsibleConfig.websocket_port;
scope.socketURL = 'https://' + $location.host() + ':' + scope.socketPort + '/';
scope.browserName = browserData.name;
if (browserData.name === 'Firefox') {
HelpDialog({ defn: FFSocketHelp, scope: scope });
}
else if (browserData.name === 'Safari') {
HelpDialog({ defn: SafariSocketHelp, scope: scope });
}
else {
HelpDialog({ defn: ChromeSocketHelp, scope: scope });
}
};
}]);

View File

@ -0,0 +1,13 @@
/*************************************************
* Copyright (c) 2016 Ansible, Inc.
*
* All Rights Reserved
*************************************************/
// import awFeatureDirective from './features.directive';
import socketService from './socket.service';
export default
angular.module('socket', [])
// .directive('awFeature', awFeatureDirective)
.service('SocketService', socketService);

View File

@ -0,0 +1,173 @@
/*************************************************
* Copyright (c) 2016 Ansible, Inc.
*
* All Rights Reserved
*************************************************/
import ReconnectingWebSocket from 'reconnectingwebsocket'
export default
['$rootScope', '$location', '$log', 'Authorization','$state',
function ($rootScope, $location, $log, Authorization, $state) {
return {
init: function() {
var self = this,
token = Authorization.getToken(),
host = window.location.host,
url = "ws://" + host + "/websocket/";
if (!$rootScope.sessionTimer || ($rootScope.sessionTimer && !$rootScope.sessionTimer.isExpired())) {
// We have a valid session token, so attempt socket connection
$log.debug('Socket connecting to: ' + url);
self.socket = new ReconnectingWebSocket(url, null, {
debug: true,
timeoutInterval: 3000,
maxReconnectAttempts: 10
});
self.socket.onopen = function () {
console.log('websocket connected'); //log errors
};
self.socket.onerror = function (error) {
console.log('Error Logged: ' + error); //log errors
};
self.socket.onmessage = function (e) {
console.log('Received From Server: ' + e.data);
var data = JSON.parse(e.data);
// {'groups':
// {'jobs': ['status_changed', 'summary'],
// 'schedules': ['changed'],
// 'ad_hoc_command_events': [ids,],
// 'job_events': [ids,],
// 'control': ['limit_reached'],
// }
// }
if(data.group_name==="jobs"){
if (!('status' in data)){
// we know that this must have been a
// summary complete message
$log.debug('Job summary_complete ' + data.unified_job_id);
$rootScope.$emit('JobSummaryComplete', data);
}
if ($state.is('jobs')) {
$rootScope.$emit('JobStatusChange-jobs', data);
} else if ($state.includes('jobDetail') ||
$state.is('adHocJobStdout') ||
$state.is('inventorySyncStdout') ||
$state.is('managementJobStdout') ||
$state.is('scmUpdateStdout')) {
$log.debug("sending status to standard out");
$rootScope.$emit('JobStatusChange-jobStdout', data);
}
if ($state.includes('jobDetail')) {
$rootScope.$emit('JobStatusChange-jobDetails', data);
} else if ($state.is('dashboard')) {
$rootScope.$emit('JobStatusChange-home', data);
} else if ($state.is('portalMode')) {
$rootScope.$emit('JobStatusChange-portal', data);
} else if ($state.is('projects')) {
$rootScope.$emit('JobStatusChange-projects', data);
} else if ($state.is('inventoryManage')) {
$rootScope.$emit('JobStatusChange-inventory', data);
}
}
if(data.group_name==="job_events"){
$rootScope.$emit('job_events-'+data.job, data);
}
if(data.group_name==="schedules"){
$log.debug('Schedule ' + data.unified_job_id + ' status changed to ' + data.status);
$rootScope.$emit('ScheduleStatusChange', data);
}
if(data.group_name==="ad_hoc_command_events"){
}
if(data.group_name==="control"){
$log.debug(data.reason);
$rootScope.sessionTimer.expireSession('session_limit');
$state.go('signOut');
}
return self.socket;
};
}
else {
// encountered expired token, redirect to login page
$rootScope.sessionTimer.expireSession('idle');
$location.url('/login');
}
},
checkStatus: function() {
function getSocketTip(status) {
var result = '';
switch(status) {
case 'error':
result = "Live events: error connecting to the Tower server.";
break;
case 'connecting':
result = "Live events: attempting to connect to the Tower server.";
break;
case "ok":
result = "Live events: connected. Pages containing job status information will automatically update in real-time.";
}
return result;
}
// Check connection status
var self = this;
if(self){
if(self.socket){
if (self.socket.readyState === 0 ) {
self.scope.socketStatus = 'connecting';
}
else if (self.socket.readyState === 1){
self.scope.socketStatus = 'ok';
}
else if (self.socket.readyState === 2 || self.socket.readyState === 3 ){
self.scope.socketStatus = 'error';
}
self.scope.socketTip = getSocketTip(self.scope.socketStatus);
return self.scope.socketStatus;
}
}
},
on: function (eventName, callback) {
var self = this;
if(self){
if(self.socket){
// self.socket.onmessage(function (e) {
// var args = arguments;
// self.scope.$apply(function () {
// callback.apply(self.socket, args);
// });
// });
}
}
},
emit: function (eventName, data, callback) {
var self = this;
// console.log(eventName)
self.socket.send(eventName, data, function () {
var args = arguments;
self.scope.$apply(function () {
if (callback) {
callback.apply(self.socket, args);
}
});
});
},
getUrl: function() {
return url;
},
removeAllListeners: function (eventName) {
var self = this;
if(self){
if(self.socket){
self.socket.removeEventListener(eventName);
}
}
},
};
}];

View File

@ -22,7 +22,7 @@ export default ['$log', '$rootScope', '$scope', '$state', '$stateParams', 'Proce
function openSockets() {
if ($state.current.name === 'jobDetail') {
$log.debug("socket watching on job_events-" + job_id);
$rootScope.socket.on("job_events-" + job_id, function() {
$rootScope.$on("job_events-" + job_id, function() {
$log.debug("socket fired on job_events-" + job_id);
if (api_complete) {
event_queue++;