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

Side by Side Diff: appengine/swarming/elements/res/imp/botlist/bot-list-data.html

Issue 2227803002: Mirror filters and sort preferences to url-params (Closed) Base URL: https://chromium.googlesource.com/external/github.com/luci/luci-py@use-dimensions
Patch Set: Tweak docs Created 4 years, 4 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-list-data> 9 <bot-list-data>
10 10
11 This makes calls authenticated with Oauth 2 to the swarming apis. It parses 11 This makes calls authenticated with Oauth 2 to the swarming apis. It parses
12 that data into usable data structures. 12 that data into usable data structures.
13 13
14 Usage: 14 Usage:
15 15
16 <bot-list-data></bot-list-data> 16 <bot-list-data></bot-list-data>
17 17
18 Properties: 18 Properties:
19 // inputs 19 // inputs
20 auth_headers: Object, the OAuth2 header to include in the request. This 20 auth_headers: Object, the OAuth2 header to include in the request. This
21 should come from swarming-app. 21 should come from swarming-app.
22 query_params: Object, The query params that will filter the query
23 server-side. This can have dimensions:Array<String>, quarantined:String
24 and is_dead: String. For example:
25 {
26 "dimensions": ["pool:Skia", "device_type:Sprout"],
27 "quarantined": "FALSE", // optional
28 "is_dead": "TRUE", // optional
29 }
30 For a full list of dimensions in the fleet, see the API call:
31 https://[swarming_url]/_ah/api/swarming/v1/bots/dimensions
22 // outputs 32 // outputs
23 bots: Array<Object>, all bots returned by the botlist. This is an Object 33 bots: Array<Object>, all bots returned by the botlist. This is an Object
24 with at least the following structure: 34 with at least the following structure:
25 dimensions: Array<Object>: Has key:String and value:Array<String> 35 dimensions: Array<Object>: Has key:String and value:Array<String>
26 task_id: String 36 task_id: String
27 external_ip: String 37 external_ip: String
28 is_dead: Object: Is usually Boolean, but could be message string 38 is_dead: Object: Is usually Boolean, but could be message string
29 quarantined: Object: Is usually Boolean, but could be message string 39 quarantined: Object: Is usually Boolean, but could be message string
30 bot_id: String 40 bot_id: String
31 state: String, Stringified JSON that has many pieces of information, like 41 state: String, Stringified JSON that has many pieces of information, like
32 devices, disk space, temperature, etc. 42 devices, disk space, temperature, etc.
33 busy: Boolean, if any ajax requests are in flight. 43 busy: Boolean, if any ajax requests are in flight.
44 dimensions: Array<String>, of all valid dimensions.
34 fleet: Object, counts of all bots in the fleet. Contains "alive", "busy", 45 fleet: Object, counts of all bots in the fleet. Contains "alive", "busy",
35 "idle", "dead", and "quarantined". 46 "idle", "dead", and "quarantined".
36 primary_map: Object, a mapping of primary keys to secondary items. 47 primary_map: Object, a mapping of primary keys to secondary items.
37 The primary keys are things that can be columns or sorted by. The 48 The primary keys are things that can be columns or sorted by. The
38 primary values (aka the secondary items) are things that can be filtered 49 primary values (aka the secondary items) are things that can be filtered
39 on. Primary consists of dimensions and state. Secondary contains the 50 on. Primary consists of dimensions and state. Secondary contains the
40 values primary things can be. 51 values primary things can be.
41 primary_arr: Array<String>, the display order of the primary keys. 52 primary_arr: Array<String>, the display order of the primary keys.
42 This is dimensions, then bot properties, then elements from bot.state. 53 This is dimensions, then bot properties, then elements from bot.state.
43 54
44 Methods: 55 Methods:
45 signIn(): Force a signin of the user using OAuth. This happens 56 signIn(): Force a signin of the user using OAuth. This happens
46 automatically when auth_headers is set. 57 automatically when auth_headers is set.
47 58
48 Events: 59 Events:
49 None. 60 None.
50 --> 61 -->
51 62
52 <link rel="import" href="/res/imp/bower_components/iron-ajax/iron-ajax.html"> 63 <link rel="import" href="/res/imp/bower_components/iron-ajax/iron-ajax.html">
53 64
54 <link rel="import" href="bot-list-shared.html"> 65 <link rel="import" href="bot-list-shared.html">
55 66
56 <dom-module id="bot-list-data"> 67 <dom-module id="bot-list-data">
57 <template> 68 <template>
58 <iron-ajax id="botlist" 69 <iron-ajax id="botlist"
59 url="/_ah/api/swarming/v1/bots/list" 70 url="/_ah/api/swarming/v1/bots/list"
60 headers="[[auth_headers]]" 71 headers="[[auth_headers]]"
61 params="[[_botlistParams(dimensions.*)]]" 72 params="[[query_params]]"
62 handle-as="json" 73 handle-as="json"
63 last-response="{{_list}}" 74 last-response="{{_list}}"
64 loading="{{_busy1}}"> 75 loading="{{_busy1}}">
65 </iron-ajax> 76 </iron-ajax>
66 77
67 <iron-ajax id="dimensions" 78 <iron-ajax id="dimensions"
68 url="/_ah/api/swarming/v1/bots/dimensions" 79 url="/_ah/api/swarming/v1/bots/dimensions"
69 headers="[[auth_headers]]" 80 headers="[[auth_headers]]"
70 handle-as="json" 81 handle-as="json"
71 last-response="{{_dimensions}}" 82 last-response="{{_dimensions}}"
72 loading="{{_busy2}}"> 83 loading="{{_busy2}}">
73 </iron-ajax> 84 </iron-ajax>
74 85
75 <iron-ajax id="fleet" 86 <iron-ajax id="fleet"
76 url="/_ah/api/swarming/v1/bots/count" 87 url="/_ah/api/swarming/v1/bots/count"
77 headers="[[auth_headers]]" 88 headers="[[auth_headers]]"
78 handle-as="json" 89 handle-as="json"
79 last-response="{{_count}}" 90 last-response="{{_count}}"
80 loading="{{_busy3}}"> 91 loading="{{_busy3}}">
81 </iron-ajax> 92 </iron-ajax>
82 </template> 93 </template>
83 <script> 94 <script>
84 (function(){ 95 (function(){
96 var BLACKLIST_DIMENSIONS = ["quarantined", "error"];
85 97
86 Polymer({ 98 Polymer({
87 is: 'bot-list-data', 99 is: 'bot-list-data',
88 100
89 behaviors: [SwarmingBehaviors.BotListBehavior], 101 behaviors: [SwarmingBehaviors.BotListBehavior],
90 102
91 properties: { 103 properties: {
92 // inputs 104 // inputs
93 auth_headers: { 105 auth_headers: {
94 type: Object, 106 type: Object,
95 observer: "signIn", 107 observer: "signIn",
96 }, 108 },
97 dimensions: { 109 query_params: {
98 type: Array, 110 type: Object,
99 }, 111 },
100 112
101 //outputs 113 //outputs
102 bots: { 114 bots: {
103 type: Array, 115 type: Array,
104 computed: "_bots(_list)", 116 computed: "_bots(_list)",
105 notify: true, 117 notify: true,
106 }, 118 },
107 busy: { 119 busy: {
108 type: Boolean, 120 type: Boolean,
109 computed: "_or(_busy1,_busy2,_busy3)", 121 computed: "_or(_busy1,_busy2,_busy3)",
110 notify: true, 122 notify: true,
111 }, 123 },
124 dimensions: {
125 type: Array,
126 computed: "_makeArray(_dimensions)",
127 notify: true,
128 },
112 fleet: { 129 fleet: {
113 type: Object, 130 type: Object,
114 computed: "_fleet(_count)", 131 computed: "_fleet(_count)",
115 notify: true, 132 notify: true,
116 }, 133 },
117 primary_map: { 134 primary_map: {
118 type:Object, 135 type:Object,
119 computed: "_primaryMap(_dimensions)", 136 computed: "_primaryMap(_dimensions)",
120 notify: true, 137 notify: true,
121 }, 138 },
122 primary_arr: { 139 primary_arr: {
123 type: Array, 140 type: Array,
124 // DIMENSIONS and BOT_PROPERTIES are inherited from BotListBehavior 141 //BOT_PROPERTIES is inherited from BotListBehavior
125 computed: "_primaryArr(DIMENSIONS, BOT_PROPERTIES)", 142 computed: "_primaryArr(dimensions, BOT_PROPERTIES)",
126 notify: true, 143 notify: true,
127 }, 144 },
128 145
129 // private 146 // private
130 _count: { 147 _count: {
131 type: Object, 148 type: Object,
132 }, 149 },
133 _dimensions: { 150 _dimensions: {
134 type: Object, 151 type: Object,
135 }, 152 },
136 _list: { 153 _list: {
137 type: Object, 154 type: Object,
138 }, 155 },
139 }, 156 },
140 157
141 signIn: function(){ 158 signIn: function(){
159 // Auto on iron-ajax means to automatically re-make the request if
160 // the url or the query params change. Auto does not trigger if the
161 // [auth] headers change, so we wait until the user is signed in
162 // before making any requests.
142 this.$.botlist.auto = true; 163 this.$.botlist.auto = true;
143 this.$.dimensions.auto = true; 164 this.$.dimensions.auto = true;
144 this.$.fleet.auto = true; 165 this.$.fleet.auto = true;
145 }, 166 },
146 167
147 _botlistParams: function() {
148 if (!this.dimensions) {
149 return {};
150 }
151 return {
152 dimensions: this.dimensions,
153 };
154 },
155
156 _bots: function(){ 168 _bots: function(){
157 if (!this._list || !this._list.items) { 169 if (!this._list || !this._list.items) {
158 return []; 170 return [];
159 } 171 }
160 // Do any preprocessing here 172 // Do any preprocessing here
161 this._list.items.forEach(function(bot){ 173 this._list.items.forEach(function(bot){
162 // Parse the state, which is a JSON string. This contains a lot of 174 // Parse the state, which is a JSON string. This contains a lot of
163 // interesting information like details about the devices attached. 175 // interesting information like details about the devices attached.
164 bot.state = JSON.parse(bot.state); 176 bot.state = JSON.parse(bot.state);
165 // get the disks in an easier to deal with format, sorted by size. 177 // get the disks in an easier to deal with format, sorted by size.
(...skipping 14 matching lines...) Expand all
180 192
181 }); 193 });
182 return this._list.items; 194 return this._list.items;
183 }, 195 },
184 196
185 _fleet: function() { 197 _fleet: function() {
186 if (!this._count) { 198 if (!this._count) {
187 return {}; 199 return {};
188 } 200 }
189 return { 201 return {
190 alive: this._count.count || -1, 202 all: this._count.count || -1,
203 alive: (this._count.count - this._count.dead) || -1,
191 busy: this._count.busy || -1, 204 busy: this._count.busy || -1,
192 idle: this._count.count && this._count.busy && 205 idle: (this._count.count - this._count.busy) || -1,
193 this._count.count - this._count.busy,
194 dead: this._count.dead || -1, 206 dead: this._count.dead || -1,
195 quarantined: this._count.quarantined || -1, 207 quarantined: this._count.quarantined || -1,
196 } 208 }
197 }, 209 },
198 210
211 _makeArray: function(dimObj) {
212 if (!dimObj || !dimObj.bots_dimensions) {
213 return [];
214 }
215 var dims = [];
216 dimObj.bots_dimensions.forEach(function(d){
217 if (BLACKLIST_DIMENSIONS.indexOf(d.key) === -1) {
218 dims.push(d.key);
219 }
220 });
221 dims.sort();
222 return dims;
223 },
224
199 _primaryArr: function(dimensions, properties) { 225 _primaryArr: function(dimensions, properties) {
200 return dimensions.concat(properties); 226 return dimensions.concat(properties);
201 }, 227 },
202 228
203 _primaryMap: function(dimensions){ 229 _primaryMap: function(dimensions){
204 // map will keep track of dimensions that we have seen at least once. 230 // pMap will have a list of columns to available values (primary key
205 // This will then basically get turned into an array to be used for 231 // to secondary values). This includes bot dimensions, but also
206 // filtering. 232 // includes state like disk_space, quarantined, busy, etc.
207 dimensions = dimensions.bots_dimensions; 233 dimensions = dimensions.bots_dimensions;
208 234
209 var pMap = {}; 235 var pMap = {};
210 dimensions.forEach(function(d){ 236 dimensions.forEach(function(d){
211 if (this.DIMENSIONS_WITH_ALIASES.indexOf(d.key) === -1) { 237 if (this.DIMENSIONS_WITH_ALIASES.indexOf(d.key) === -1) {
212 // value is an array of all seen values for the dimension d.key 238 // value is an array of all seen values for the dimension d.key
213 pMap[d.key] = d.value; 239 pMap[d.key] = d.value;
214 } else if (d.key === "gpu") { 240 } else if (d.key === "gpu") {
215 var gpus = []; 241 var gpus = [];
216 d.value.forEach(function(g){ 242 d.value.forEach(function(g){
(...skipping 24 matching lines...) Expand all
241 // Add some options that might not show up. 267 // Add some options that might not show up.
242 pMap["android_devices"].push("0"); 268 pMap["android_devices"].push("0");
243 pMap["device_os"].push("none"); 269 pMap["device_os"].push("none");
244 pMap["device_type"].push("none"); 270 pMap["device_type"].push("none");
245 271
246 pMap["id"] = []; 272 pMap["id"] = [];
247 273
248 // Create custom filter options 274 // Create custom filter options
249 pMap["disk_space"] = []; 275 pMap["disk_space"] = [];
250 pMap["task"] = ["busy", "idle"]; 276 pMap["task"] = ["busy", "idle"];
251 pMap["status"] = ["available", "dead", "quarantined"]; 277 pMap["status"] = ["alive", "dead", "quarantined"];
252 278
253 // No need to sort any of this, bot-filters sorts secondary items 279 // No need to sort any of this, bot-filters sorts secondary items
254 // automatically, especially when the user types a query. 280 // automatically, especially when the user types a query.
255 return pMap; 281 return pMap;
256 }, 282 },
257 283
258 }); 284 });
259 })(); 285 })();
260 </script> 286 </script>
261 </dom-module> 287 </dom-module>
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698