Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(221)

Side by Side Diff: appengine/swarming/elements/res/imp/botpage/bot-page.html

Issue 2302973002: Refactor post requests, implement bot cancel/terminate (Closed) Base URL: https://chromium.googlesource.com/external/github.com/luci/luci-py@basic-layout
Patch Set: rebase Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
11 bot-page shows the tasks, events, and dimensions of a bot. 11 bot-page shows the tasks, events, and dimensions of a bot.
12 12
13 This is a top-level element. 13 This is a top-level element.
14 14
15 Properties: 15 Properties:
16 bot_id: String, Used in testing to specify a bot_id 16 bot_id: String, Used in testing to specify a bot_id
17 client_id: String, Oauth 2.0 client id. It will be set by server-side 17 client_id: String, Oauth 2.0 client id. It will be set by server-side
18 template evaluation. 18 template evaluation.
19 19
20 Methods: 20 Methods:
21 None. 21 None.
22 22
23 Events: 23 Events:
24 None. 24 None.
25 --> 25 -->
26 26
27 <link rel="import" href="/res/imp/bower_components/iron-collapse/iron-collapse.h tml"> 27 <link rel="import" href="/res/imp/bower_components/iron-collapse/iron-collapse.h tml">
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-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">
31 <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" >
32 <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">
33 <link rel="import" href="/res/imp/bower_components/paper-icon-button/paper-icon- button.html"> 35 <link rel="import" href="/res/imp/bower_components/paper-toast/paper-toast.html" >
34 <link rel="import" href="/res/imp/bower_components/polymer/polymer.html"> 36 <link rel="import" href="/res/imp/bower_components/polymer/polymer.html">
35 37
36 <link rel="import" href="/res/imp/common/swarming-app.html"> 38 <link rel="import" href="/res/imp/common/swarming-app.html">
37 <link rel="import" href="/res/imp/common/url-param.html"> 39 <link rel="import" href="/res/imp/common/url-param.html">
38 40
39 <link rel="import" href="bot-page-data.html"> 41 <link rel="import" href="bot-page-data.html">
40 <link rel="import" href="bot-page-shared-behavior.html"> 42 <link rel="import" href="bot-page-shared-behavior.html">
41 43
42 44
43 <dom-module id="bot-page"> 45 <dom-module id="bot-page">
(...skipping 27 matching lines...) Expand all
71 margin-bottom: 5px; 73 margin-bottom: 5px;
72 } 74 }
73 td, th { 75 td, th {
74 border: 1px solid #BBB; 76 border: 1px solid #BBB;
75 padding: 5px; 77 padding: 5px;
76 } 78 }
77 79
78 .quarantined, .failed_task { 80 .quarantined, .failed_task {
79 background-color: #ffdddd; 81 background-color: #ffdddd;
80 } 82 }
81 .dead { 83 .dead, .bot_died {
82 background-color: #cccccc; 84 background-color: #cccccc;
83 } 85 }
84 86
85 .message { 87 .message {
86 white-space: pre-line; 88 white-space: pre-line;
87 font-family: monospace; 89 font-family: monospace;
88 } 90 }
89 91
90 .bot_state { 92 .bot_state {
91 white-space: pre; 93 white-space: pre;
(...skipping 22 matching lines...) Expand all
114 } 116 }
115 117
116 paper-tab.iron-selected { 118 paper-tab.iron-selected {
117 background-color: #A6CEE3; 119 background-color: #A6CEE3;
118 border: 3px solid #1F78B4; 120 border: 3px solid #1F78B4;
119 color: #000; 121 color: #000;
120 font-weight: bold; 122 font-weight: bold;
121 text-decoration: underline; 123 text-decoration: underline;
122 } 124 }
123 125
126 paper-dialog {
127 border-radius: 6px;
128 }
129
124 </style> 130 </style>
125 131
126 <url-param name="id" 132 <url-param name="id"
127 value="{{bot_id}}"> 133 value="{{bot_id}}">
128 </url-param> 134 </url-param>
129 <url-param name="show_all_events" 135 <url-param name="show_all_events"
130 value="{{_show_all}}"> 136 value="{{_show_all}}">
131 </url-param> 137 </url-param>
132 <url-param name="selected" 138 <url-param name="selected"
133 value="{{_selected}}"> 139 value="{{_selected}}">
134 </url-param> 140 </url-param>
135 <url-param name="show_state" 141 <url-param name="show_state"
136 value="{{_show_state}}"> 142 value="{{_show_state}}">
137 </url-param> 143 </url-param>
138 144
139 <swarming-app 145 <swarming-app
140 client_id="[[client_id]]" 146 client_id="[[client_id]]"
141 auth_headers="{{_auth_headers}}" 147 auth_headers="{{_auth_headers}}"
142 permissions="{{_permissions}}" 148 permissions="{{_permissions}}"
143 signed_in="{{_signed_in}}" 149 signed_in="{{_signed_in}}"
144 150
145 busy="[[_busy]]" 151 busy="[[_busy]]"
146 name="Swarming Bot Page"> 152 name="Swarming Bot Page">
147 153
148 <h2 hidden$="[[_signed_in]]">You must sign in to see anything useful.</h2> 154 <h2 hidden$="[[_signed_in]]">You must sign in to see anything useful.</h2>
149 155
150 <div hidden$="[[_not(_signed_in)]]"> 156 <div hidden$="[[_not(_signed_in)]]">
151 157
152 <bot-page-data 158 <bot-page-data
159 id="data"
153 auth_headers="[[_auth_headers]]" 160 auth_headers="[[_auth_headers]]"
154 bot_id="[[bot_id]]" 161 bot_id="[[bot_id]]"
155 162
156 bot="{{_bot}}" 163 bot="{{_bot}}"
157 busy="{{_busy}}" 164 busy="{{_busy}}"
158 events="{{_events}}" 165 events="{{_events}}"
159 tasks="{{_tasks}}"> 166 tasks="{{_tasks}}">
160 </bot-page-data> 167 </bot-page-data>
161 168
162 <div class="header horizontal layout"> 169 <div class="header horizontal layout">
163 <paper-input class="id_input" label="Bot id" value="{{bot_id}}"></pape r-input> 170 <paper-input class="id_input" label="Bot id" value="{{bot_id}}"></pape r-input>
164 <button> 171 <button on-click="_refresh">
165 <iron-icon class="refresh" icon="icons:refresh"></iron-icon> 172 <iron-icon class="refresh" icon="icons:refresh"></iron-icon>
166 </button> 173 </button>
167 </div> 174 </div>
168 175
169 <div> 176 <div>
170 <table> 177 <table>
171 <tr class$="[[_isDead(_bot)]]"> 178 <tr class$="[[_isDead(_bot)]]">
172 <td>Last Seen</td> 179 <td>Last Seen</td>
173 <td title="[[_bot.human_last_seen_ts]]"> 180 <td title="[[_bot.human_last_seen_ts]]">
174 [[_timeDiffExact(_bot.last_seen_ts)]] ago</td> 181 [[_timeDiffExact(_bot.last_seen_ts)]] ago</td>
175 <td> 182 <td>
176 <!-- dom-ifs are slightly less performant than hidden$=, but 183 <!-- dom-ifs are slightly less performant than hidden$=, but
177 prevent things from first drawing and then hiding. We prefer to 184 prevent things from first drawing and then hiding. We prefer to
178 not flash buttons or quarantined messages --> 185 not flash buttons or quarantined messages -->
179 <template is="dom-if" if="[[_canShutdown(_bot,_permissions)]]"> 186 <template is="dom-if" if="[[_canShutdown(_bot,_permissions)]]">
180 <button class="raised"> 187 <button class="raised" on-click="_promptShutdown">
181 Shut Down Gracefully 188 Shut Down Gracefully
182 </button> 189 </button>
183 </template> 190 </template>
184 <template is="dom-if" if="[[_canDelete(_bot,_permissions)]]"> 191 <template is="dom-if" if="[[_canDelete(_bot,_permissions)]]">
185 <button class="raised"> 192 <button class="raised" on-click="_promptDelete">
186 Delete 193 Delete
187 </button> 194 </button>
188 </template> 195 </template>
189 </td> 196 </td>
190 </tr> 197 </tr>
191 <template is="dom-if" if="[[_bot.quarantined]]"> 198 <template is="dom-if" if="[[_bot.quarantined]]">
192 <tr class="quarantined"> 199 <tr class="quarantined">
193 <td>Quarantined</td> 200 <td>Quarantined</td>
194 <td colspan="2">[[_quarantineMessage(_bot)]]</td> 201 <td colspan="2">[[_quarantineMessage(_bot)]]</td>
195 </tr> 202 </tr>
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
282 <thead> 289 <thead>
283 <tr> 290 <tr>
284 <th>Task</th> 291 <th>Task</th>
285 <th>Started</th> 292 <th>Started</th>
286 <th>Duration</th> 293 <th>Duration</th>
287 <th>Result</th> 294 <th>Result</th>
288 </tr> 295 </tr>
289 </thead> 296 </thead>
290 <tbody> 297 <tbody>
291 <template is="dom-repeat" items="{{_tasks}}" as="task"> 298 <template is="dom-repeat" items="{{_tasks}}" as="task">
292 <tr> 299 <tr class$="[[_taskClass(task)]]">
293 <td><a target="_blank" href$="[[_taskLink(task.task_id)]]">[[t ask.name]]</a></td> 300 <td><a target="_blank" href$="[[_taskLink(task.task_id)]]">[[t ask.name]]</a></td>
294 <td>[[task.human_started_ts]]</td> 301 <td>[[task.human_started_ts]]</td>
295 <td title="[[task.human_completed_ts]]">[[task.human_duration] ]</td> 302 <td title="[[task.human_completed_ts]]">[[task.human_duration] ]</td>
296 <td>[[task.state]]</td> 303 <td>[[task.state]]</td>
297 </tr> 304 </tr>
298 </template> 305 </template>
299 </tbody> 306 </tbody>
300 </table> 307 </table>
301 </template> 308 </template>
302 309
(...skipping 18 matching lines...) Expand all
321 <td> 328 <td>
322 <a target="_blank" href$="[[_luciLink(_bot.version)]]">[[_sh orten(_bot.version,'8')]]</a> 329 <a target="_blank" href$="[[_luciLink(_bot.version)]]">[[_sh orten(_bot.version,'8')]]</a>
323 </td> 330 </td>
324 </tr> 331 </tr>
325 </template> 332 </template>
326 </tbody> 333 </tbody>
327 </table> 334 </table>
328 </template> 335 </template>
329 </div> 336 </div>
330 </div> 337 </div>
338 </swarming-app>
331 339
332 </swarming-app> 340 <paper-dialog id="prompt" modal on-iron-overlay-closed="_promptClosed">
341 <h2>Are you sure?</h2>
342 <div>Are you sure you want to [[_dialogPrompt]]?</div>
343 <div class="buttons">
344 <paper-button dialog-dismiss autofocus>No</paper-button>
345 <paper-button dialog-confirm>Yes</paper-button>
346 </div>
347 </paper-dialog>
348
349 <paper-toast id="toast"></paper-toast>
333 350
334 </template> 351 </template>
335 <script> 352 <script>
336 (function(){ 353 (function(){
337 354
338 355
339 Polymer({ 356 Polymer({
340 is: 'bot-page', 357 is: 'bot-page',
341 358
342 behaviors: [ 359 behaviors: [
343 SwarmingBehaviors.BotPageBehavior, 360 SwarmingBehaviors.BotPageBehavior,
344 ], 361 ],
345 362
346 properties: { 363 properties: {
347 bot_id: { 364 bot_id: {
348 type: String, 365 type: String,
349 }, 366 },
350 client_id: { 367 client_id: {
351 type: String, 368 type: String,
352 }, 369 },
353 370
371 _auth_headers: {
372 type: Object,
373 },
354 _bot: { 374 _bot: {
355 type: Object, 375 type: Object,
356 }, 376 },
377 _dialogPrompt: {
378 type: String,
379 value: "",
380 },
357 _selected: { 381 _selected: {
358 type: Number, 382 type: Number,
359 }, 383 },
360 _show_all: { 384 _show_all: {
361 type: Boolean, 385 type: Boolean,
362 }, 386 },
363 _show_state: { 387 _show_state: {
364 type: Boolean, 388 type: Boolean,
365 } 389 }
366 }, 390 },
(...skipping 10 matching lines...) Expand all
377 return bot && !bot.is_dead && permissions.terminate_bot; 401 return bot && !bot.is_dead && permissions.terminate_bot;
378 }, 402 },
379 403
380 _concat: function(arr) { 404 _concat: function(arr) {
381 if (!arr) { 405 if (!arr) {
382 return ""; 406 return "";
383 } 407 }
384 return arr.join(" | "); 408 return arr.join(" | ");
385 }, 409 },
386 410
411 _deleteBot: function() {
412 this.$.toast.text="Deleting "+this.bot_id;
413 this._postWithToast("/_ah/api/swarming/v1/bot/"+this.bot_id+"/delete",
414 this.$.toast, this._auth_headers);
415 },
416
387 _eventList(events, showAll) { 417 _eventList(events, showAll) {
388 if (!events) { 418 if (!events) {
389 return []; 419 return [];
390 } 420 }
391 return events.filter(function(e){ 421 return events.filter(function(e){
392 return showAll || e.message; 422 return showAll || e.message;
393 }); 423 });
394 }, 424 },
395 425
396 _isDead(bot){ 426 _isDead(bot){
(...skipping 16 matching lines...) Expand all
413 return 1; 443 return 1;
414 } 444 }
415 return 1 + arr.length; 445 return 1 + arr.length;
416 }, 446 },
417 447
418 _prettyPrint: function(obj) { 448 _prettyPrint: function(obj) {
419 obj = obj || {}; 449 obj = obj || {};
420 return JSON.stringify(obj, null, 2); 450 return JSON.stringify(obj, null, 2);
421 }, 451 },
422 452
453 _promptClosed: function(e) {
454 if (e.detail.confirmed) {
455 if (this._dialogPrompt.startsWith("shut down")) {
456 this._shutdownBot();
457 } else {
458 this._deleteBot();
459 }
460 }
461 },
462
463 _promptDelete: function() {
464 this.set("_dialogPrompt", "delete "+this.bot_id);
465 this.$.prompt.open();
466 },
467
468 _promptShutdown: function() {
469 this.set("_dialogPrompt", "shut down "+this.bot_id);
470 this.$.prompt.open();
471 },
472
423 _quarantineMessage: function(bot) { 473 _quarantineMessage: function(bot) {
424 if (bot && bot.quarantined) { 474 if (bot && bot.quarantined) {
425 var msg = bot.state.quarantined; 475 var msg = bot.state.quarantined;
426 // Sometimes, the quarantined message is actually in "error". This 476 // Sometimes, the quarantined message is actually in "error". This
427 // happens when the bot code has thrown an exception. 477 // happens when the bot code has thrown an exception.
428 if (msg === undefined || msg === "true" || msg === true) { 478 if (msg === undefined || msg === "true" || msg === true) {
429 msg = this._attribute(bot, "error"); 479 msg = this._attribute(bot, "error");
430 } 480 }
431 return msg || "True"; 481 return msg || "True";
432 } 482 }
433 return ""; 483 return "";
434 }, 484 },
435 485
486 _refresh: function() {
487 this.$.data.request();
488 },
489
436 _shorten: function(str, length) { 490 _shorten: function(str, length) {
437 if (!str || ! length) { 491 if (!str || ! length) {
438 return ""; 492 return "";
439 } 493 }
440 return str.substring(0, length); 494 return str.substring(0, length);
441 }, 495 },
442 496
497 _shutdownBot: function() {
498 this.$.toast.text="Shutting down "+this.bot_id;
499 this._postWithToast("/_ah/api/swarming/v1/bot/"+this.bot_id+"/terminate" ,
500 this.$.toast, this._auth_headers);
501 },
502
443 _task: function(bot) { 503 _task: function(bot) {
444 return (bot && bot.task_id) || "idle"; 504 return (bot && bot.task_id) || "idle";
445 }, 505 },
446 506
507 _taskClass: function(task) {
508 if (task && task.internal_failure) {
509 return "bot_died";
510 }
511 if (task && task.failure) {
512 return "failed_task";
513 }
514 return "";
515 },
516
447 _taskLink: function(task_id) { 517 _taskLink: function(task_id) {
448 // TODO(kjlubick): Migrate this to /newui/ when ready 518 // TODO(kjlubick): Migrate this to /newui/ when ready
449 if (task_id) { 519 if (task_id) {
450 return "/user/task/" + task_id; 520 return "/user/task/" + task_id;
451 } 521 }
452 return undefined; 522 return undefined;
453 }, 523 },
454 524
455 _toggleState: function() { 525 _toggleState: function() {
456 this.set("_show_state", !this._show_state); 526 this.set("_show_state", !this._show_state);
457 } 527 }
458 528
459 }); 529 });
460 })(); 530 })();
461 </script> 531 </script>
462 </dom-module> 532 </dom-module>
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698