You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficcontrol.apache.org by oc...@apache.org on 2021/06/17 17:15:57 UTC

[trafficcontrol] branch master updated: TP: Adds ability to view/create/delete a cdn lock (#5934)

This is an automated email from the ASF dual-hosted git repository.

ocket8888 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficcontrol.git


The following commit(s) were added to refs/heads/master by this push:
     new 8eb412c  TP: Adds ability to view/create/delete a cdn lock (#5934)
8eb412c is described below

commit 8eb412ccf2da7b0a859b7a87cfdc79e3ae5205af
Author: Jeremy Mitchell <mi...@users.noreply.github.com>
AuthorDate: Thu Jun 17 11:15:49 2021 -0600

    TP: Adds ability to view/create/delete a cdn lock (#5934)
    
    * adds the ability to display locks
    
    * adds the ability to create a hard or soft lock for a cdn
    
    * removes uneccessary css
    
    * ensures that lock interval is destroyed on logout
    
    * adds trailing line
    
    * updates per code review
    
    * removes data- prefixes
    
    * new html for radio buttons
    
    * maxlength is fine for a static value
    
    * removes uneccessary error messages from cdn lock creation form
    
    * changes to lock form to prevent cutoff of hard/soft tooltip
    
    * style changes
    
    * adds missing type legend
    
    * dialog improvements
    
    * removes invalid character
---
 traffic_portal/app/src/app.js                      |  2 +
 traffic_portal/app/src/common/api/CDNService.js    | 35 +++++++++
 .../app/src/common/modules/dialog/_dialog.scss     | 12 +++
 .../select/lock/DialogSelectLockController.js      | 46 +++++++++++
 .../dialog/select/lock/dialog.select.lock.tpl.html | 68 ++++++++++++++++
 .../src/common/modules/dialog/select/lock/index.js | 21 +++++
 .../src/common/modules/header/HeaderController.js  | 23 ++++++
 .../app/src/common/modules/header/header.tpl.html  |  5 ++
 .../src/common/modules/locks/LocksController.js    | 91 ++++++++++++++++++++++
 .../_notifications.scss => locks/_locks.scss}      |  7 +-
 .../app/src/common/modules/locks/index.js          | 21 +++++
 .../locks/locks.tpl.html}                          | 28 +------
 .../app/src/common/templates/master.tpl.html       |  3 +
 traffic_portal/app/src/modules/private/index.js    |  4 +
 traffic_portal/app/src/styles/main.scss            |  8 +-
 15 files changed, 343 insertions(+), 31 deletions(-)

diff --git a/traffic_portal/app/src/app.js b/traffic_portal/app/src/app.js
index fd624d0..e44aa34 100644
--- a/traffic_portal/app/src/app.js
+++ b/traffic_portal/app/src/app.js
@@ -256,10 +256,12 @@ var trafficPortal = angular.module('trafficPortal', [
         require('./common/modules/dialog/input').name,
         require('./common/modules/dialog/reset').name,
         require('./common/modules/dialog/select').name,
+        require('./common/modules/dialog/select/lock').name,
         require('./common/modules/dialog/select/status').name,
         require('./common/modules/dialog/text').name,
         require('./common/modules/dialog/textarea').name,
         require('./common/modules/header').name,
+        require('./common/modules/locks').name,
         require('./common/modules/message').name,
         require('./common/modules/navigation').name,
         require('./common/modules/notifications').name,
diff --git a/traffic_portal/app/src/common/api/CDNService.js b/traffic_portal/app/src/common/api/CDNService.js
index 04494c7..0b81350 100644
--- a/traffic_portal/app/src/common/api/CDNService.js
+++ b/traffic_portal/app/src/common/api/CDNService.js
@@ -259,6 +259,41 @@ var CDNService = function($http, locationUtils, messageModel, ENV) {
         );
     };
 
+    this.getLocks = function(queryParams) {
+        return $http.get(ENV.api['root'] + 'cdn_locks', { params: queryParams }).then(
+            function(result) {
+                return result.data.response;
+            },
+            function(err) {
+                throw err;
+            }
+        );
+    };
+
+    this.createLock = function(lock) {
+        return $http.post(ENV.api['root'] + 'cdn_locks', lock).then(
+            function(result) {
+                return result;
+            },
+            function(err) {
+                messageModel.setMessages(err.data.alerts, false);
+                throw err;
+            }
+        );
+    };
+
+    this.deleteLock = function(queryParams) {
+        return $http.delete(ENV.api['root'] + 'cdn_locks', { params: queryParams }).then(
+            function(result) {
+                return result;
+            },
+            function(err) {
+                messageModel.setMessages(err.data.alerts, false);
+                throw err;
+            }
+        );
+    };
+
 };
 
 CDNService.$inject = ['$http', 'locationUtils', 'messageModel', 'ENV'];
diff --git a/traffic_portal/app/src/common/modules/dialog/_dialog.scss b/traffic_portal/app/src/common/modules/dialog/_dialog.scss
index 60d889f..4b42719 100644
--- a/traffic_portal/app/src/common/modules/dialog/_dialog.scss
+++ b/traffic_portal/app/src/common/modules/dialog/_dialog.scss
@@ -45,3 +45,15 @@
 .dialog-20 .modal-dialog {
   width: 20%;
 }
+
+.fieldset-body {
+  display: grid;
+  grid-template-columns: auto 1fr;
+  grid-column-gap: 1.5em;
+  grid-row-gap: 5px;
+  justify-items: start;
+  align-items: center;
+  & > :nth-child(n) {
+    margin: 0;
+  }
+}
diff --git a/traffic_portal/app/src/common/modules/dialog/select/lock/DialogSelectLockController.js b/traffic_portal/app/src/common/modules/dialog/select/lock/DialogSelectLockController.js
new file mode 100644
index 0000000..9da061d
--- /dev/null
+++ b/traffic_portal/app/src/common/modules/dialog/select/lock/DialogSelectLockController.js
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+var DialogSelectLockController = function(cdns, $scope, $uibModalInstance) {
+
+	$scope.cdns = cdns.filter(
+		function (cdn) {
+			// you cannot apply a lock to the 'ALL' cdn
+			return cdn.name !== 'ALL';
+		}
+	);
+
+	$scope.lock = {
+		cdn: null,
+		soft: true,
+		message: null
+	};
+
+	$scope.select = function() {
+		$uibModalInstance.close($scope.lock);
+	};
+
+	$scope.cancel = function () {
+		$uibModalInstance.dismiss('cancel');
+	};
+
+};
+
+DialogSelectLockController.$inject = ['cdns', '$scope', '$uibModalInstance'];
+module.exports = DialogSelectLockController;
diff --git a/traffic_portal/app/src/common/modules/dialog/select/lock/dialog.select.lock.tpl.html b/traffic_portal/app/src/common/modules/dialog/select/lock/dialog.select.lock.tpl.html
new file mode 100644
index 0000000..d6230fd
--- /dev/null
+++ b/traffic_portal/app/src/common/modules/dialog/select/lock/dialog.select.lock.tpl.html
@@ -0,0 +1,68 @@
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+  http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+​
+<div class="modal-header">
+    <button type="button" class="close" ng-click="cancel()"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
+    <h4 class="modal-title">Create CDN Lock</h4>
+</div>
+<form ng-submit="select()">
+    <div class="modal-body">
+        <div class="row">
+            <div class="col-sm-12 col-md-12">
+                <div class="form-group">
+                    <label class="control-label" for="cdn">CDN *</label>
+                    <select id="cdn" name="cdn" class="form-control" ng-model="lock.cdn" ng-options="cdn.name as cdn.name for cdn in cdns" required>
+                        <option disabled hidden selected value="">Select...</option>
+                    </select>
+                </div>
+            </div>
+        </div>
+        <div class="row">
+            <div class="col-sm-12 col-md-12">
+                <div class="form-group">
+                    <label class="control-label" for="message">Message *</label>
+                    <input id="message" name="message" type="text" class="form-control" ng-model="lock.message" maxlength="256" required autofocus>
+                </div>
+            </div>
+        </div>
+        <div class="row">
+            <div class="col-sm-12 col-md-12">
+                <fieldset class="form-group">
+                    <legend>Type</legend>
+                    <div class="fieldset-body">
+                        <label class="has-tooltip" for="soft">Soft<div class="helptooltip">
+                            <div class="helptext">A <dfn>soft</dfn> lock will prevent others from queueing server updates or snapshotting the locked CDN
+                            </div>
+                        </div>
+                        </label>
+                        <input id="soft" name="lockType" type="radio" ng-model="lock.soft" ng-value="true" required>
+                        <label class="has-tooltip" for="hard">Hard<div class="helptooltip">
+                            <div class="helptext">A <dfn>hard</dfn> lock will prevent others from queueing server updates or snapshotting the locked CDN. It will also block others from making changes that would change the state of the locked CDN.
+                            </div>
+                        </div>
+                        </label>
+                        <input id="hard" name="lockType" type="radio" ng-model="lock.soft" ng-value="false" required>
+                    </div>
+                </fieldset>
+            </div>
+        </div>
+    </div>
+    <div class="modal-footer">
+        <button type="button" class="btn action-btn" ng-click="cancel()">Cancel</button>
+        <button class="btn btn-link">Submit</button>
+    </div>
+</form>
diff --git a/traffic_portal/app/src/common/modules/dialog/select/lock/index.js b/traffic_portal/app/src/common/modules/dialog/select/lock/index.js
new file mode 100644
index 0000000..6a02869
--- /dev/null
+++ b/traffic_portal/app/src/common/modules/dialog/select/lock/index.js
@@ -0,0 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+module.exports = angular.module('trafficPortal.dialog.select.lock', [])
+	.controller('DialogSelectLockController', require('./DialogSelectLockController'));
diff --git a/traffic_portal/app/src/common/modules/header/HeaderController.js b/traffic_portal/app/src/common/modules/header/HeaderController.js
index 9dec203..37082a0 100644
--- a/traffic_portal/app/src/common/modules/header/HeaderController.js
+++ b/traffic_portal/app/src/common/modules/header/HeaderController.js
@@ -109,6 +109,29 @@ var HeaderController = function($rootScope, $scope, $state, $uibModal, $location
         });
     };
 
+    $scope.lockCDN = function() {
+        const modalInstance = $uibModal.open({
+            templateUrl: 'common/modules/dialog/select/lock/dialog.select.lock.tpl.html',
+            controller: 'DialogSelectLockController',
+            size: 'md',
+            resolve: {
+                cdns: function() {
+                    return $scope.cdns;
+                }
+            }
+        });
+        modalInstance.result.then(function(lock) {
+            cdnService.createLock(lock).
+            then(
+                function() {
+                    $state.reload();
+                }
+            );
+        }, function () {
+            // do nothing
+        });
+    };
+
     $scope.snapshot = function() {
         var params = {
             title: 'Diff CDN Config Snapshot',
diff --git a/traffic_portal/app/src/common/modules/header/header.tpl.html b/traffic_portal/app/src/common/modules/header/header.tpl.html
index 0c63706..31adc90 100644
--- a/traffic_portal/app/src/common/modules/header/header.tpl.html
+++ b/traffic_portal/app/src/common/modules/header/header.tpl.html
@@ -71,6 +71,11 @@ under the License.
                 </div>
             </li>
             <li>
+                <div class="btn-group" title="Lock CDN">
+                    <button type="button" class="btn btn-link" ng-if="hasCapability('cdns-lock')" ng-click="lockCDN()"><i class="fa fa-lock"></i></button>
+                </div>
+            </li>
+            <li>
                 <div class="btn-group" title="Queue CDN Server Updates">
                     <button type="button" class="btn btn-link" ng-if="hasCapability('servers-write')" ng-click="confirmQueueServerUpdates()"><i class="fa fa-flag"></i></button>
                 </div>
diff --git a/traffic_portal/app/src/common/modules/locks/LocksController.js b/traffic_portal/app/src/common/modules/locks/LocksController.js
new file mode 100644
index 0000000..00de6a9
--- /dev/null
+++ b/traffic_portal/app/src/common/modules/locks/LocksController.js
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+var LocksController = function($scope, $rootScope, $interval, $state, $uibModal, cdnService, userModel) {
+
+	let interval;
+
+	let getLocks = function() {
+		cdnService.getLocks()
+			.then(function(result) {
+				$scope.locks = result;
+			});
+	};
+
+	let createInterval = function() {
+		interval = $interval(function() { getLocks() }, 30000 );
+	};
+
+	let killInterval = function() {
+		if (angular.isDefined(interval)) {
+			$interval.cancel(interval);
+			interval = undefined;
+		}
+	};
+
+	$scope.loggedInUser = userModel.user.username;
+
+	$scope.confirmUnlock = function(lock) {
+		const params = {
+			title: 'Remove lock from: ' + lock.cdn,
+			message: 'Are you sure you want to remove the lock from the ' + lock.cdn + ' CDN?'
+		};
+		const modalInstance = $uibModal.open({
+			templateUrl: 'common/modules/dialog/confirm/dialog.confirm.tpl.html',
+			controller: 'DialogConfirmController',
+			size: 'md',
+			resolve: {
+				params: function () {
+					return params;
+				}
+			}
+		});
+		modalInstance.result.then(function() {
+			cdnService.deleteLock({ cdn: lock.cdn }).
+				then(
+					function() {
+						$state.reload();
+					}
+				);
+		}, function () {
+			// do nothing
+		});
+	};
+
+	$rootScope.$on('authService::login', function() {
+		getLocks();
+		createInterval();
+	});
+
+	$rootScope.$on('trafficPortal::exit', function() {
+		killInterval();
+	});
+
+	let init = function () {
+		if (userModel.loaded) {
+			getLocks();
+			createInterval();
+		}
+	};
+	init();
+
+};
+
+LocksController.$inject = ['$scope', '$rootScope', '$interval', '$state', '$uibModal', 'cdnService', 'userModel'];
+module.exports = LocksController;
diff --git a/traffic_portal/app/src/common/modules/notifications/_notifications.scss b/traffic_portal/app/src/common/modules/locks/_locks.scss
similarity index 94%
rename from traffic_portal/app/src/common/modules/notifications/_notifications.scss
rename to traffic_portal/app/src/common/modules/locks/_locks.scss
index 6a9c857..15de266 100644
--- a/traffic_portal/app/src/common/modules/notifications/_notifications.scss
+++ b/traffic_portal/app/src/common/modules/locks/_locks.scss
@@ -1,19 +1,14 @@
 /*
-
-
  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at
-
  http://www.apache.org/licenses/LICENSE-2.0
-
  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
-
 */
-#notificationsContainer {
+#locksContainer {
   margin-top: 70px;
 }
diff --git a/traffic_portal/app/src/common/modules/locks/index.js b/traffic_portal/app/src/common/modules/locks/index.js
new file mode 100644
index 0000000..cbb19e9
--- /dev/null
+++ b/traffic_portal/app/src/common/modules/locks/index.js
@@ -0,0 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+module.exports = angular.module('trafficPortal.locks', [])
+	.controller('LocksController', require('./LocksController'));
diff --git a/traffic_portal/app/src/common/templates/master.tpl.html b/traffic_portal/app/src/common/modules/locks/locks.tpl.html
similarity index 62%
copy from traffic_portal/app/src/common/templates/master.tpl.html
copy to traffic_portal/app/src/common/modules/locks/locks.tpl.html
index 14f5acf..339adae 100644
--- a/traffic_portal/app/src/common/templates/master.tpl.html
+++ b/traffic_portal/app/src/common/modules/locks/locks.tpl.html
@@ -6,9 +6,7 @@ regarding copyright ownership.  The ASF licenses this file
 to you under the Apache License, Version 2.0 (the
 "License"); you may not use this file except in compliance
 with the License.  You may obtain a copy of the License at
-
   http://www.apache.org/licenses/LICENSE-2.0
-
 Unless required by applicable law or agreed to in writing,
 software distributed under the License is distributed on an
 "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -17,27 +15,9 @@ specific language governing permissions and limitations
 under the License.
 -->
 
-<div class="main_container">
-
-    <!-- navigation -->
-    <div class="main-nav col-md-3" ui-view="navigation"></div>
-
-    <!-- header -->
-    <div class="top_nav" ui-view="header"></div>
-
-    <!-- page content -->
-    <div class="main-content" role="main">
-
-        <!-- notifications -->
-        <div ui-view="notifications"></div>
-
-        <!-- messages -->
-        <div ui-view="message"></div>
-
-        <!-- the content -->
-        <div ui-view="content"></div>
-
+<div id="locksContainer">
+    <div class="alert alert-dark" ng-repeat="l in locks">
+        <button type="button" class="close" title="Unlock {{l.cdn}}" ng-click="confirmUnlock(l)"><i class="fa fa-unlock"></i></button>
+        <div ng-bind-html="l.cdn + ' is ' + ((l.soft) ? 'soft' : 'hard') + ' locked by ' + l.userName + ' (' + l.message + ')' | linky:'_blank'"></div>
     </div>
-
 </div>
-
diff --git a/traffic_portal/app/src/common/templates/master.tpl.html b/traffic_portal/app/src/common/templates/master.tpl.html
index 14f5acf..dac99af 100644
--- a/traffic_portal/app/src/common/templates/master.tpl.html
+++ b/traffic_portal/app/src/common/templates/master.tpl.html
@@ -28,6 +28,9 @@ under the License.
     <!-- page content -->
     <div class="main-content" role="main">
 
+        <!-- locks -->
+        <div ui-view="locks"></div>
+
         <!-- notifications -->
         <div ui-view="notifications"></div>
 
diff --git a/traffic_portal/app/src/modules/private/index.js b/traffic_portal/app/src/modules/private/index.js
index 55de9d9..92c91bd 100644
--- a/traffic_portal/app/src/modules/private/index.js
+++ b/traffic_portal/app/src/modules/private/index.js
@@ -33,6 +33,10 @@ module.exports = angular.module('trafficPortal.private', [])
                         templateUrl: 'common/modules/header/header.tpl.html',
                         controller: 'HeaderController'
                     },
+                    locks: {
+                        templateUrl: 'common/modules/locks/locks.tpl.html',
+                        controller: 'LocksController'
+                    },
                     notifications: {
                         templateUrl: 'common/modules/notifications/notifications.tpl.html',
                         controller: 'NotificationsController'
diff --git a/traffic_portal/app/src/styles/main.scss b/traffic_portal/app/src/styles/main.scss
index 074ec7d..bc7ad5e 100644
--- a/traffic_portal/app/src/styles/main.scss
+++ b/traffic_portal/app/src/styles/main.scss
@@ -32,8 +32,8 @@ $fa-font-path: "../assets/fonts";
 @import "../common/modules/header/header";
 @import "../common/modules/form/cacheGroup/form.cacheGroup";
 @import "../common/modules/form/form";
+@import "../common/modules/locks/locks";
 @import "../common/modules/navigation/navigation";
-@import "../common/modules/notifications/notifications";
 @import "../common/modules/table/table";
 @import "../common/modules/table/parameters/table.parameters";
 @import "../common/modules/release/release";
@@ -262,3 +262,9 @@ input[type="checkbox"].dirty {
     cursor: default !important;
   }
 }
+
+.alert-dark {
+  color: #141619;
+  background-color: #d3d3d4;
+  border-color: #bcbebf;
+}