| <!-- The <push-server-sk> custom element declaration. |
| |
| Displays the server configurations, along with the ability to modify application selections. |
| |
| Attributes: |
| servers: Map of server names to the apps and their versions. Such as: |
| |
| [ |
| { |
| Name: 'skia-monitoring', |
| Installed: [ |
| 'pull:jcgregorio@jcgregorio.cnc.corp.google.com:2014-12-08T02:09:58Z:79f6b17ea316c5d877f4f1e3fa9c7a4ea950916c.deb', |
| 'logserver/', |
| ] |
| }, |
| { |
| Name: 'skia-testing-b', |
| Installed: [] |
| } |
| ] |
| |
| Note that an entry in Installed can either be a full package path, or |
| just a shortened '{appname}/' version which indicates which app is |
| expected but also signals that no specific release package has been |
| chosen or deployed yet. |
| |
| packages: Map of app names to the list of available versions, sorted from newest to oldest. Such as: |
| |
| { |
| 'pull': [ |
| { |
| Name: 'pull:jcgregorio@jcgregorio.cnc.corp.google.com:2014-12-08T02:09:58Z:79f6b17ea316c5d877f4f1e3fa9c7a4ea950916c.deb', |
| Hash: '79f6b17ea316c5d877f4f1e3fa9c7a4ea950916c', |
| UserID: 'jcgregorio@jcgregorio.cnc.corp.google.com', |
| Built: '2014-12-08T02:09:58Z', |
| Dirty: true, |
| Note: 'some reason for a push' |
| }, |
| { |
| Name: 'pull:jcgregorio@jcgregorio.cnc.corp.google.com:2014-12-08T01:39:47Z:323894732847ace1289a9a90192123213.deb', |
| Hash: '323894732847ace1289a9a90192123213', |
| UserID: 'jcgregorio@jcgregorio.cnc.corp.google.com', |
| Built: '2014-12-08T01:39:47Z', |
| Dirty: false, |
| Note: 'no reason' |
| } |
| ], |
| 'logserver': [ |
| ] |
| } |
| |
| Events: |
| 'change-package' |
| A 'change-package' event is generated when the user selects a package to push. |
| The change event has the following attributes: |
| |
| event.detail.server - The name of the server. |
| event.detail.name - The full name of the package to push. |
| |
| Methods: |
| setConfig(servers, packages) |
| |
| Clicking on an app brings up a selection dialog with all available options, |
| the current one already selected. A selection will update and push. |
| --> |
| |
| <link rel="import" href="/res/common/imp/confirm-dialog-sk.html"> |
| |
| <dom-module id="push-server-sk"> |
| <style type="text/css" media="screen"> |
| table { |
| border-spacing: 0; |
| } |
| |
| h2 { |
| color: #33A02C; |
| margin-left: 1em; |
| display: inline; |
| padding-right: 1em; |
| } |
| |
| h3 { |
| margin-left: 1em; |
| color: #1f78b4; |
| display: inline; |
| } |
| |
| .appName { |
| padding-right: 1em; |
| width: 10em; |
| } |
| |
| td iron-icon { |
| padding-right: 1em; |
| } |
| |
| paper-button { |
| color: #1f78b4; |
| } |
| |
| paper-button:hover { |
| background: #eee; |
| } |
| |
| .service { |
| width: 14em; |
| } |
| |
| .status, |
| .uptime { |
| width: 10em; |
| } |
| |
| .uptime { |
| font-family: monospace; |
| } |
| |
| tr:nth-child(2n+1) { |
| background: #eee; |
| } |
| </style> |
| <template> |
| <confirm-dialog-sk id="reboot_confirm_dialog"></confirm-dialog-sk> |
| |
| <div on-tap="editClicked"> |
| <h3>Displaying {{displayedCount}} out of {{servers.length}} servers</h3> |
| <br/><br/><br/> |
| <template is="dom-repeat" items="{{servers}}" as=server rendered-item-count="{{displayedCount}}" |
| filter={{_filterServers(filterText)}}> |
| <section> |
| <h2>{{server.Name}}</h2> |
| <paper-button raised data-action="start" |
| data-name="reboot.target" |
| data-server$="[[server.Name]]">Reboot</paper-button> |
| [<a target=_blank href$="{{monURI(server.Name)}}">mon</a>] |
| [<a target=_blank href$="{{logsURI(server.Name)}}">logs</a>] |
| <table> |
| <template is="dom-repeat" items="{{server.Installed}}" as="installed"> |
| <tr> |
| <td> |
| <paper-button class=application |
| data-server$="{{server.Name}}" data-name$="{{installed}}" data-app$="{{prefixOf(installed)}}"><iron-icon icon="create" title="Edit which package is installed."></iron-icon></paper-button> |
| </td> |
| <td><div class=appName>{{prefixOf(installed)}}</div></td> |
| <td><span class=appName><a href$="https://github.com/google/skia-buildbot/compare/{{fullHash(installed)}}...HEAD">{{short(installed)}}</a></span></td> |
| <td><iron-icon icon$="{{alarmIfNotLatest(installed)}}" title="Out of date."></iron-icon></td> |
| <td><iron-icon icon$="{{warnIfDirty(installed)}}" title="Uncommited changes when the package was built."></iron-icon></td> |
| <td><a href$="{{logsFullURI(server.Name,installed)}}">logs</a></td> |
| <td> |
| <table> |
| <template is="dom-repeat" items="{{servicesOf(installed)}}" as="service"> |
| <tr> |
| <systemd-unit-status-sk machine="{{server.Name}}" service="{{service}}"></systemd-unit-status-sk> |
| </tr> |
| </template> |
| </table> |
| </td> |
| </tr> |
| </template> |
| </table> |
| </section> |
| </template> |
| <push-selection-sk id=extChooser></push-selection-sk> |
| </div> |
| </template> |
| </dom-module> |
| <script> |
| Polymer({ |
| is: "push-server-sk", |
| |
| properties: { |
| servers: { |
| type: Array, |
| value: function() { return []; }, |
| }, |
| packages: { |
| type: Array, |
| value: function() { return []; }, |
| }, |
| ip: { |
| type: Object, |
| value: function() { return {}; }, |
| }, |
| packageLookup: { |
| type: Object, |
| value: function() { return {}; }, |
| }, |
| server: { |
| type: String, |
| value: '', |
| }, |
| filterText: { |
| type: String, |
| value: '', |
| }, |
| displayedCount: { |
| type: Number, |
| value: 0, |
| } |
| }, |
| |
| ready: function() { |
| // When the push-selection-sk dialog notifies us of a selection |
| // we fill in some more details and pass that along as another |
| // CustomEvent. |
| this.$.extChooser.addEventListener('change-package', function(e) { |
| var detail = { |
| name: e.detail.name, |
| server: this.server |
| }; |
| this.dispatchEvent(new CustomEvent('change-package', {detail: detail})); |
| }.bind(this)); |
| }, |
| |
| editClicked: function(e) { |
| var button = sk.findParent(e.target, "PAPER-BUTTON"); |
| if (button == null || !button.dataset.server) { |
| return |
| } |
| this.server = button.dataset.server; |
| if (button.dataset.action) { |
| this.$.reboot_confirm_dialog |
| .open("Proceed with rebooting " + this.server + "?") |
| .then(function() { |
| var detail = { |
| machine: button.dataset.server, |
| name: button.dataset.name, |
| action: button.dataset.action, |
| }; |
| this.dispatchEvent(new CustomEvent('unit-action', {detail: detail, bubbles: true})); |
| }.bind(this)); |
| } else { |
| var id = button.dataset.name; |
| var app = button.dataset.app; |
| if (app != "") { |
| this.$.extChooser.choices = this.packages[app]; |
| this.$.extChooser.choice = id; |
| this.$.extChooser.toggle(); |
| } |
| } |
| }, |
| |
| setConfig: function(servers, packages, ip) { |
| this.servers = servers; |
| this.packages = packages; |
| this.ip = ip; |
| for (appName in this.packages) { |
| var that = this; |
| var latest = true; |
| this.packages[appName].forEach(function(details) { |
| that.packageLookup[details.Name] = details; |
| that.packageLookup[details.Name].Latest = latest; |
| latest = false; |
| }); |
| } |
| }, |
| |
| _filterServers: function(filterText) { |
| return function(server) { |
| var findMatchingServers = true; |
| var filterBy = filterText; |
| if (filterBy.startsWith('^')) { |
| findMatchingServers = false; |
| filterBy = filterBy.substring(1); |
| } |
| if (filterBy == "") { |
| return true; |
| } |
| // Try to match the server name prefix. |
| if (server.Name.indexOf(filterBy) == 0) { |
| return findMatchingServers; |
| } |
| // Now try to match the prefix of all server name tokens. |
| var tokens = server.Name.split('-'); |
| for (var tokenIndex in tokens) { |
| if (tokens[tokenIndex].indexOf(filterBy) == 0) { |
| return findMatchingServers; |
| } |
| } |
| // Now try to match the app name prefix. |
| for (var installedIndex in server.Installed) { |
| var installed = server.Installed[installedIndex]; |
| var appName = this.prefixOf(installed); |
| if (appName.indexOf(filterBy) == 0) { |
| return findMatchingServers; |
| } |
| } |
| return !findMatchingServers; |
| }.bind(this); |
| }, |
| |
| // prefixOf is a helper used in templates that returns all the text |
| // that appears before the first '/'. |
| prefixOf: function(s) { |
| return s.split('/')[0]; |
| }, |
| |
| // fullHash is a utility function used in templates to extract the full git hash |
| // from a package name. |
| fullHash: function(s) { |
| return s.slice(s.length-44, s.length-4) |
| }, |
| |
| // short is a utility function used in templates to truncate strings. |
| short: function(s) { |
| return this.fullHash(s).slice(0, 6); |
| }, |
| |
| alarmIfNotLatest: function(installed) { |
| if (!this.packageLookup[installed]) { |
| return ' '; // Don't return an empty string here, to force the icon to change. |
| } else { |
| return this.packageLookup[installed].Latest ? ' ' : 'alarm'; |
| } |
| }, |
| |
| warnIfDirty: function(installed) { |
| if (!this.packageLookup[installed]) { |
| return ' '; // Don't return an empty string here, to force the icon to change. |
| } else { |
| return this.packageLookup[installed].Dirty ? 'warning' : ' '; |
| } |
| }, |
| |
| servicesOf: function(installed) { |
| var p = this.packageLookup[installed]; |
| if (!p) { |
| return []; |
| } |
| return p.Services; |
| }, |
| |
| monURI: function(name) { |
| return "https://" + name + "-10000-proxy.skia.org"; |
| }, |
| |
| logsURI: function(name) { |
| return "https://console.cloud.google.com/logs/viewer?project=google.com:skia-buildbots&minLogLevel=200&expandAll=false&resource=logging_log%2Fname%2F" + name; |
| }, |
| |
| logsFullURI: function(name, installed) { |
| var app = installed.split('/')[0]; |
| return "https://console.cloud.google.com/logs/viewer?project=google.com:skia-buildbots&minLogLevel=200&expandAll=false&resource=logging_log%2Fname%2F" + name + "&logName=projects%2Fgoogle.com:skia-buildbots%2Flogs%2F" + app; |
| }, |
| |
| }); |
| </script> |