| OLD | NEW |
| 1 <!-- | 1 <!-- |
| 2 Copyright 2016 The LUCI Authors. All rights reserved. | 2 Copyright 2016 The LUCI Authors. All rights reserved. |
| 3 Use of this source code is governed under the Apache License, Version 2.0 | 3 Use of this source code is governed under the Apache License, Version 2.0 |
| 4 that can be found in the LICENSE file. | 4 that can be found in the LICENSE file. |
| 5 | 5 |
| 6 This in an HTML Import-able file that contains the definition | 6 This in an HTML Import-able file that contains the definition |
| 7 of the following elements: | 7 of the following elements: |
| 8 | 8 |
| 9 <bot-page> | 9 <bot-page> |
| 10 | 10 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 28 <link rel="import" href="/res/imp/bower_components/iron-icon/iron-icon.html"> | 28 <link rel="import" href="/res/imp/bower_components/iron-icon/iron-icon.html"> |
| 29 <link rel="import" href="/res/imp/bower_components/iron-icons/iron-icons.html"> | 29 <link rel="import" href="/res/imp/bower_components/iron-icons/iron-icons.html"> |
| 30 <link rel="import" href="/res/imp/bower_components/paper-button/paper-button.htm
l"> | 30 <link rel="import" href="/res/imp/bower_components/paper-button/paper-button.htm
l"> |
| 31 <link rel="import" href="/res/imp/bower_components/paper-checkbox/paper-checkbox
.html"> | 31 <link rel="import" href="/res/imp/bower_components/paper-checkbox/paper-checkbox
.html"> |
| 32 <link rel="import" href="/res/imp/bower_components/paper-dialog/paper-dialog.htm
l"> | 32 <link rel="import" href="/res/imp/bower_components/paper-dialog/paper-dialog.htm
l"> |
| 33 <link rel="import" href="/res/imp/bower_components/paper-input/paper-input.html"
> | 33 <link rel="import" href="/res/imp/bower_components/paper-input/paper-input.html"
> |
| 34 <link rel="import" href="/res/imp/bower_components/paper-tabs/paper-tabs.html"> | 34 <link rel="import" href="/res/imp/bower_components/paper-tabs/paper-tabs.html"> |
| 35 <link rel="import" href="/res/imp/bower_components/polymer/polymer.html"> | 35 <link rel="import" href="/res/imp/bower_components/polymer/polymer.html"> |
| 36 | 36 |
| 37 <link rel="import" href="/res/imp/common/error-toast.html"> | 37 <link rel="import" href="/res/imp/common/error-toast.html"> |
| 38 <link rel="import" href="/res/imp/common/pageable-data.html"> |
| 38 <link rel="import" href="/res/imp/common/single-page-style.html"> | 39 <link rel="import" href="/res/imp/common/single-page-style.html"> |
| 39 <link rel="import" href="/res/imp/common/swarming-app.html"> | 40 <link rel="import" href="/res/imp/common/swarming-app.html"> |
| 40 <link rel="import" href="/res/imp/common/task-behavior.html"> | 41 <link rel="import" href="/res/imp/common/task-behavior.html"> |
| 41 <link rel="import" href="/res/imp/common/url-param.html"> | 42 <link rel="import" href="/res/imp/common/url-param.html"> |
| 42 | 43 |
| 43 <link rel="import" href="bot-page-data.html"> | 44 <link rel="import" href="bot-page-data.html"> |
| 44 <link rel="import" href="bot-page-shared-behavior.html"> | 45 <link rel="import" href="bot-page-shared-behavior.html"> |
| 45 | 46 |
| 46 | 47 |
| 47 <dom-module id="bot-page"> | 48 <dom-module id="bot-page"> |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 93 value="{{_show_state}}"> | 94 value="{{_show_state}}"> |
| 94 </url-param> | 95 </url-param> |
| 95 | 96 |
| 96 <swarming-app | 97 <swarming-app |
| 97 client_id="[[client_id]]" | 98 client_id="[[client_id]]" |
| 98 auth_headers="{{_auth_headers}}" | 99 auth_headers="{{_auth_headers}}" |
| 99 permissions="{{_permissions}}" | 100 permissions="{{_permissions}}" |
| 100 server_version="{{_server_version}}" | 101 server_version="{{_server_version}}" |
| 101 signed_in="{{_signed_in}}" | 102 signed_in="{{_signed_in}}" |
| 102 | 103 |
| 103 busy="[[_busy]]" | 104 busy="[[_or(_busy1,_busy2,_busy3)]]" |
| 104 name="Swarming Bot Page"> | 105 name="Swarming Bot Page"> |
| 105 | 106 |
| 106 <h2 hidden$="[[_signed_in]]">You must sign in to see anything useful.</h2> | 107 <h2 hidden$="[[_signed_in]]">You must sign in to see anything useful.</h2> |
| 107 | 108 |
| 108 <div hidden$="[[_not(_signed_in)]]"> | 109 <div hidden$="[[_not(_signed_in)]]"> |
| 109 | 110 |
| 110 <bot-page-data | 111 <bot-page-data |
| 111 id="data" | 112 id="data" |
| 112 auth_headers="[[_auth_headers]]" | 113 auth_headers="[[_auth_headers]]" |
| 113 bot_id="[[bot_id]]" | 114 bot_id="[[bot_id]]" |
| 114 | 115 |
| 115 bot="{{_bot}}" | 116 bot="{{_bot}}" |
| 116 busy="{{_busy}}" | 117 busy="{{_busy1}}" |
| 117 events="{{_events}}" | 118 events="{{_events}}" |
| 118 tasks="{{_tasks}}"> | 119 tasks="{{_tasks}}" |
| 120 on-reload="_clearAndReload"> |
| 119 </bot-page-data> | 121 </bot-page-data> |
| 120 | 122 |
| 121 <div class="header horizontal layout"> | 123 <div class="header horizontal layout"> |
| 122 <paper-input class="id_input" label="Bot id" value="{{bot_id}}"></pape
r-input> | 124 <paper-input class="id_input" label="Bot id" value="{{bot_id}}"></pape
r-input> |
| 123 <button on-click="_refresh"> | 125 <button on-click="_refresh"> |
| 124 <iron-icon class="refresh" icon="icons:refresh"></iron-icon> | 126 <iron-icon class="refresh" icon="icons:refresh"></iron-icon> |
| 125 </button> | 127 </button> |
| 126 </div> | 128 </div> |
| 127 | 129 |
| 128 <div> | 130 <div> |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 228 <div class="bot_state">[[_prettyPrint(_bot.state)]]</div> | 230 <div class="bot_state">[[_prettyPrint(_bot.state)]]</div> |
| 229 </iron-collapse> | 231 </iron-collapse> |
| 230 </div> | 232 </div> |
| 231 | 233 |
| 232 <div class="tabs"> | 234 <div class="tabs"> |
| 233 <paper-tabs selected="{{_selected}}" no-bar> | 235 <paper-tabs selected="{{_selected}}" no-bar> |
| 234 <paper-tab>Tasks</paper-tab> | 236 <paper-tab>Tasks</paper-tab> |
| 235 <paper-tab>Events</paper-tab> | 237 <paper-tab>Events</paper-tab> |
| 236 </paper-tabs> | 238 </paper-tabs> |
| 237 | 239 |
| 238 <template is="dom-if" if="[[_selected]]"> | 240 <template is="dom-if" if="[[_showEvents]]"> |
| 239 <paper-checkbox checked="{{_show_all}}"> | 241 <paper-checkbox checked="{{_show_all}}"> |
| 240 Show all events | 242 Show all events |
| 241 </paper-checkbox> | 243 </paper-checkbox> |
| 242 </template> | 244 </template> |
| 243 </div> | 245 </div> |
| 244 | 246 |
| 245 <template is="dom-if" if="[[_not(_selected)]]"> | 247 <template is="dom-if" if="[[_not(_showEvents)]]"> |
| 246 <table class="tasks_table"> | 248 <table class="tasks_table"> |
| 247 <thead> | 249 <thead> |
| 248 <tr> | 250 <tr> |
| 249 <th>Task</th> | 251 <th>Task</th> |
| 250 <th>Started</th> | 252 <th>Started</th> |
| 251 <th>Duration</th> | 253 <th>Duration</th> |
| 252 <th>Result</th> | 254 <th>Result</th> |
| 253 </tr> | 255 </tr> |
| 254 </thead> | 256 </thead> |
| 255 <tbody> | 257 <tbody> |
| 256 <template is="dom-repeat" items="{{_tasks}}" as="task"> | 258 <template is="dom-repeat" items="{{_tasks}}" as="task"> |
| 257 <tr class$="[[_taskClass(task)]]"> | 259 <tr class$="[[_taskClass(task)]]"> |
| 258 <td><a target="_blank" href$="[[_taskLink(task.task_id)]]">[[t
ask.name]]</a></td> | 260 <td><a target="_blank" href$="[[_taskLink(task.task_id)]]">[[t
ask.name]]</a></td> |
| 259 <td>[[task.human_started_ts]]</td> | 261 <td>[[task.human_started_ts]]</td> |
| 260 <td title="[[task.human_completed_ts]]">[[task.human_duration]
]</td> | 262 <td title="[[task.human_completed_ts]]">[[task.human_duration]
]</td> |
| 261 <td>[[task.state]]</td> | 263 <td>[[task.state]]</td> |
| 262 </tr> | 264 </tr> |
| 263 </template> | 265 </template> |
| 264 </tbody> | 266 </tbody> |
| 265 </table> | 267 </table> |
| 266 </template> | 268 </template> |
| 267 | 269 |
| 268 <template is="dom-if" if="[[_selected]]"> | 270 <template is="dom-if" if="[[_showEvents]]"> |
| 269 <table class="events_table"> | 271 <table class="events_table"> |
| 270 <thead> | 272 <thead> |
| 271 <tr> | 273 <tr> |
| 272 <th>Message</th> | 274 <th>Message</th> |
| 273 <th>Type</th> | 275 <th>Type</th> |
| 274 <th>Timestamp</th> | 276 <th>Timestamp</th> |
| 275 <th>Task ID</th> | 277 <th>Task ID</th> |
| 276 <th>Version</th> | 278 <th>Version</th> |
| 277 </tr> | 279 </tr> |
| 278 </thead> | 280 </thead> |
| 279 <tbody> | 281 <tbody> |
| 280 <template is="dom-repeat" items="{{_eventList(_events,_show_all)}}
" as="event"> | 282 <template is="dom-repeat" items="{{_eventList(_show_all,_events.*)
}}" as="event"> |
| 281 <tr> | 283 <tr> |
| 282 <td class="message">[[event.message]]</a></td> | 284 <td class="message">[[event.message]]</a></td> |
| 283 <td>[[event.event_type]]</td> | 285 <td>[[event.event_type]]</td> |
| 284 <td>[[event.human_ts]]</td> | 286 <td>[[event.human_ts]]</td> |
| 285 <td><a target="_blank" href$="[[_taskLink(event.task_id)]]">[[
event.task_id]]</a></td> | 287 <td><a target="_blank" href$="[[_taskLink(event.task_id)]]">[[
event.task_id]]</a></td> |
| 286 <td class$="[[_classVersion(_server_version.bot_version,event.
version)]]"> | 288 <td class$="[[_classVersion(_server_version.bot_version,event.
version)]]"> |
| 287 <a target="_blank" href$="[[_luciLink(event.version)]]">[[_s
horten(event.version,'8')]]</a> | 289 <a target="_blank" href$="[[_luciLink(event.version)]]">[[_s
horten(event.version,'8')]]</a> |
| 288 </td> | 290 </td> |
| 289 </tr> | 291 </tr> |
| 290 </template> | 292 </template> |
| 291 </tbody> | 293 </tbody> |
| 292 </table> | 294 </table> |
| 293 </template> | 295 </template> |
| 296 <!-- https://github.com/Polymer/polymer/issues/3669 hidden$ doesn't |
| 297 respect truthiness, only booleanness, so we have _showEvents |
| 298 instead of using _selected directly.--> |
| 299 <pageable-data |
| 300 id="page_tasks" |
| 301 hidden$="[[_showEvents]]" |
| 302 busy="{{_busy2}}" |
| 303 label="Show more tasks" |
| 304 output="{{_tasks}}" |
| 305 parse="[[_parseTasks]]"> |
| 306 </pageable-data> |
| 307 <pageable-data |
| 308 id="page_events" |
| 309 hidden$="[[_not(_showEvents)]]" |
| 310 busy="{{_busy3}}" |
| 311 label="Show more events" |
| 312 output="{{_events}}" |
| 313 parse="[[_parseEvents]]"> |
| 314 </pageable-data> |
| 294 </div> | 315 </div> |
| 295 </swarming-app> | 316 </swarming-app> |
| 296 | 317 |
| 297 <paper-dialog id="prompt" modal on-iron-overlay-closed="_promptClosed"> | 318 <paper-dialog id="prompt" modal on-iron-overlay-closed="_promptClosed"> |
| 298 <h2>Are you sure?</h2> | 319 <h2>Are you sure?</h2> |
| 299 <div>Are you sure you want to [[_dialogPrompt]]?</div> | 320 <div>Are you sure you want to [[_dialogPrompt]]?</div> |
| 300 <div class="buttons"> | 321 <div class="buttons"> |
| 301 <paper-button dialog-dismiss autofocus>No</paper-button> | 322 <paper-button dialog-dismiss autofocus>No</paper-button> |
| 302 <paper-button dialog-confirm>Yes</paper-button> | 323 <paper-button dialog-confirm>Yes</paper-button> |
| 303 </div> | 324 </div> |
| (...skipping 15 matching lines...) Expand all Loading... |
| 319 properties: { | 340 properties: { |
| 320 bot_id: { | 341 bot_id: { |
| 321 type: String, | 342 type: String, |
| 322 }, | 343 }, |
| 323 client_id: { | 344 client_id: { |
| 324 type: String, | 345 type: String, |
| 325 }, | 346 }, |
| 326 | 347 |
| 327 _auth_headers: { | 348 _auth_headers: { |
| 328 type: Object, | 349 type: Object, |
| 350 observer: "_reload", |
| 329 }, | 351 }, |
| 330 _bot: { | 352 _bot: { |
| 331 type: Object, | 353 type: Object, |
| 332 }, | 354 }, |
| 333 _dialogPrompt: { | 355 _dialogPrompt: { |
| 334 type: String, | 356 type: String, |
| 335 value: "", | 357 value: "", |
| 336 }, | 358 }, |
| 337 _selected: { | 359 _selected: { |
| 338 type: Number, | 360 type: Number, |
| 339 }, | 361 }, |
| 340 _show_all: { | 362 _show_all: { |
| 341 type: Boolean, | 363 type: Boolean, |
| 342 }, | 364 }, |
| 365 _showEvents: { |
| 366 type: Boolean, |
| 367 computed: "_truthy(_selected)" |
| 368 }, |
| 343 _show_state: { | 369 _show_state: { |
| 344 type: Boolean, | 370 type: Boolean, |
| 371 }, |
| 372 |
| 373 _parseEvents: { |
| 374 type: Function, |
| 375 value: function() { |
| 376 return this.$.data.parseEvents.bind(this); |
| 377 } |
| 378 }, |
| 379 _parseTasks: { |
| 380 type: Function, |
| 381 value: function() { |
| 382 return this.$.data.parseTasks.bind(this); |
| 383 } |
| 345 } | 384 } |
| 346 }, | 385 }, |
| 347 | 386 |
| 348 _canCancel: function(bot, permissions) { | 387 _canCancel: function(bot, permissions) { |
| 349 return bot && bot.task_id && permissions.cancel_task; | 388 return bot && bot.task_id && permissions.cancel_task; |
| 350 }, | 389 }, |
| 351 | 390 |
| 352 _canDelete: function(bot, permissions) { | 391 _canDelete: function(bot, permissions) { |
| 353 return bot && bot.is_dead && permissions.delete_bot; | 392 return bot && bot.is_dead && permissions.delete_bot; |
| 354 }, | 393 }, |
| 355 | 394 |
| 356 _canShutdown: function(bot, permissions){ | 395 _canShutdown: function(bot, permissions){ |
| 357 return bot && !bot.is_dead && permissions.terminate_bot; | 396 return bot && !bot.is_dead && permissions.terminate_bot; |
| 358 }, | 397 }, |
| 359 | 398 |
| 360 _classVersion: function(serverVersion, otherVersion) { | 399 _classVersion: function(serverVersion, otherVersion) { |
| 361 if (serverVersion !== otherVersion) { | 400 if (serverVersion !== otherVersion) { |
| 362 return "old_version"; | 401 return "old_version"; |
| 363 } | 402 } |
| 364 return ""; | 403 return ""; |
| 365 }, | 404 }, |
| 366 | 405 |
| 406 _clearAndReload: function(botID) { |
| 407 this.$.page_tasks.clear(); |
| 408 this.$.page_events.clear(); |
| 409 this._reload(); |
| 410 }, |
| 411 |
| 367 _concat: function(arr) { | 412 _concat: function(arr) { |
| 368 if (!arr) { | 413 if (!arr) { |
| 369 return ""; | 414 return ""; |
| 370 } | 415 } |
| 371 return arr.join(" | "); | 416 return arr.join(" | "); |
| 372 }, | 417 }, |
| 373 | 418 |
| 374 _deleteBot: function() { | 419 _deleteBot: function() { |
| 375 swarming.postWithToast("/_ah/api/swarming/v1/bot/"+this.bot_id+"/delete"
, | 420 swarming.postWithToast("/_ah/api/swarming/v1/bot/"+this.bot_id+"/delete"
, |
| 376 "Deleting "+this.bot_id, this._auth_headers); | 421 "Deleting "+this.bot_id, this._auth_headers); |
| 377 }, | 422 }, |
| 378 | 423 |
| 379 _eventList(events, showAll) { | 424 _eventList(showAll) { |
| 380 if (!events) { | 425 if (!this._events) { |
| 381 return []; | 426 return []; |
| 382 } | 427 } |
| 383 return events.filter(function(e){ | 428 return this._events.filter(function(e){ |
| 384 return showAll || e.message; | 429 return showAll || e.message; |
| 385 }); | 430 }); |
| 386 }, | 431 }, |
| 387 | 432 |
| 388 _isDead(bot){ | 433 _isDead(bot){ |
| 389 if (bot && bot.is_dead) { | 434 if (bot && bot.is_dead) { |
| 390 return "dead"; | 435 return "dead"; |
| 391 } | 436 } |
| 392 return ""; | 437 return ""; |
| 393 }, | 438 }, |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 442 } | 487 } |
| 443 return msg || "True"; | 488 return msg || "True"; |
| 444 } | 489 } |
| 445 return ""; | 490 return ""; |
| 446 }, | 491 }, |
| 447 | 492 |
| 448 _refresh: function() { | 493 _refresh: function() { |
| 449 this.$.data.request(); | 494 this.$.data.request(); |
| 450 }, | 495 }, |
| 451 | 496 |
| 497 _reload: function() { |
| 498 if (!this._auth_headers) { |
| 499 return; |
| 500 } |
| 501 var baseUrl = "/_ah/api/swarming/v1/bot/"+this.bot_id; |
| 502 // We limit the fields on these two queries to make them faster. |
| 503 this.$.page_tasks.load(baseUrl + "/tasks?fields=cursor%2Citems(abandoned
_ts%2Cbot_version%2Ccompleted_ts%2Cduration%2Cexit_code%2Cfailure%2Cinternal_fai
lure%2Cmodified_ts%2Cname%2Cstarted_ts%2Cstate%2Ctask_id%2Ctry_number)", |
| 504 this._auth_headers, 30); |
| 505 this.$.page_events.load(baseUrl + "/events?fields=cursor%2Citems(event_t
ype%2Cmessage%2Cquarantined%2Ctask_id%2Cts%2Cversion)", |
| 506 this._auth_headers, 50); |
| 507 }, |
| 508 |
| 452 _shorten: function(str, length) { | 509 _shorten: function(str, length) { |
| 453 if (!str || ! length) { | 510 if (!str || ! length) { |
| 454 return ""; | 511 return ""; |
| 455 } | 512 } |
| 456 return str.substring(0, length); | 513 return str.substring(0, length); |
| 457 }, | 514 }, |
| 458 | 515 |
| 459 _shutdownBot: function() { | 516 _shutdownBot: function() { |
| 460 swarming.postWithToast("/_ah/api/swarming/v1/bot/"+this.bot_id+"/termina
te", | 517 swarming.postWithToast("/_ah/api/swarming/v1/bot/"+this.bot_id+"/termina
te", |
| 461 "Shutting down "+this.bot_id, this._auth_headers); | 518 "Shutting down "+this.bot_id, this._auth_headers); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 476 }, | 533 }, |
| 477 | 534 |
| 478 _toggleState: function() { | 535 _toggleState: function() { |
| 479 this.set("_show_state", !this._show_state); | 536 this.set("_show_state", !this._show_state); |
| 480 } | 537 } |
| 481 | 538 |
| 482 }); | 539 }); |
| 483 })(); | 540 })(); |
| 484 </script> | 541 </script> |
| 485 </dom-module> | 542 </dom-module> |
| OLD | NEW |