Browse code

Merge pull request #8335 from spadgett/pod-pending-tooltip

Merged by openshift-bot

OpenShift Bot authored on 2016/04/03 12:16:24
Showing 5 changed files
... ...
@@ -1,7 +1,13 @@
1 1
 "use strict";
2 2
 
3 3
 angular.module('openshiftConsole')
4
-  .directive('podStatusChart', function($timeout, hashSizeFilter, isTroubledPodFilter, numContainersReadyFilter, Logger) {
4
+  .directive('podStatusChart', function($timeout,
5
+                                        hashSizeFilter,
6
+                                        isPullingImageFilter,
7
+                                        isTerminatingFilter,
8
+                                        isTroubledPodFilter,
9
+                                        numContainersReadyFilter,
10
+                                        Logger) {
5 11
     // Make sure our charts always have unique IDs even if the same deployment
6 12
     // or monopod is shown on the overview more than once.
7 13
     var lastId = 0;
... ...
@@ -17,7 +23,7 @@ angular.module('openshiftConsole')
17 17
         var chart, config;
18 18
 
19 19
         // The phases to show (in order).
20
-        var phases = ["Running", "Not Ready", "Warning", "Failed", "Pending", "Succeeded", "Unknown"];
20
+        var phases = ["Running", "Not Ready", "Warning", "Failed", "Pulling", "Pending", "Succeeded", "Terminating", "Unknown"];
21 21
 
22 22
         lastId++;
23 23
         $scope.chartId = 'pods-donut-chart-' + lastId;
... ...
@@ -85,6 +91,9 @@ angular.module('openshiftConsole')
85 85
               return { top: 0, left: 0 };
86 86
             }
87 87
           },
88
+          transition: {
89
+            duration: 350
90
+          },
88 91
           data: {
89 92
             type: "donut",
90 93
             groups: [ phases ],
... ...
@@ -97,8 +106,10 @@ angular.module('openshiftConsole')
97 97
               "Not Ready": "#beedf9",
98 98
               Warning: "#f9d67a",
99 99
               Failed: "#d9534f",
100
-              Pending: "#e8e8e8",
100
+              Pulling: "#d1d1d1",
101
+              Pending: "#ededed",
101 102
               Succeeded: "#3f9c35",
103
+              Terminating: "#00659c",
102 104
               Unknown: "#f9d67a"
103 105
             },
104 106
             selection: {
... ...
@@ -134,41 +145,47 @@ angular.module('openshiftConsole')
134 134
           $scope.podStatusData = data.columns;
135 135
         }
136 136
 
137
-        function countPodPhases() {
138
-          var countByPhase = {};
139
-          var incrementCount = function(phase) {
140
-            countByPhase[phase] = (countByPhase[phase] || 0) + 1;
141
-          };
137
+        function isReady(pod) {
138
+          var numReady = numContainersReadyFilter(pod);
139
+          var total = pod.spec.containers.length;
142 140
 
143
-          var isReady = function(pod) {
144
-            var numReady = numContainersReadyFilter(pod);
145
-            var total = pod.spec.containers.length;
141
+          return numReady === total;
142
+        }
146 143
 
147
-            return numReady === total;
148
-          };
144
+        function getPhase(pod) {
145
+          if (isTerminatingFilter(pod)) {
146
+            return 'Terminating';
147
+          }
149 148
 
150
-          angular.forEach($scope.pods, function(pod) {
151
-            // Count 'Warning' as its own phase, even if not strictly accurate,
152
-            // so it appears in the donut chart. Warnings are too important not
153
-            // to call out.
154
-            if (isTroubledPodFilter(pod)) {
155
-              incrementCount('Warning');
156
-              return;
157
-            }
149
+          if (isTroubledPodFilter(pod)) {
150
+            return 'Warning';
151
+          }
158 152
 
159
-            // Also count running, but not ready, as its own phase.
160
-            if (pod.status.phase === 'Running' && !isReady(pod)) {
161
-              incrementCount('Not Ready');
162
-              return;
163
-            }
153
+          if (isPullingImageFilter(pod)) {
154
+            return 'Pulling';
155
+          }
156
+
157
+          // Also count running, but not ready, as its own phase.
158
+          if (pod.status.phase === 'Running' && !isReady(pod)) {
159
+            return 'Not Ready';
160
+          }
161
+
162
+          return _.get(pod, 'status.phase', 'Unknown');
163
+        }
164 164
 
165
-            incrementCount(pod.status.phase);
165
+        function countPodPhases() {
166
+          var countByPhase = {};
167
+
168
+          angular.forEach($scope.pods, function(pod) {
169
+            var phase = getPhase(pod);
170
+            countByPhase[phase] = (countByPhase[phase] || 0) + 1;
166 171
           });
167 172
 
168 173
           return countByPhase;
169 174
         }
170 175
 
171
-        $scope.$watch(countPodPhases, updateChart, true);
176
+        var debounceUpdate = _.debounce(updateChart, 350, { maxWait: 500 });
177
+        $scope.$watch(countPodPhases, debounceUpdate, true);
172 178
         $scope.$watch('desired', updateCenterText);
173 179
 
174 180
         $scope.$on('destroy', function() {
... ...
@@ -696,6 +696,36 @@ angular.module('openshiftConsole')
696 696
       return numRestarts;
697 697
     };
698 698
   })
699
+  .filter('isTerminating', function() {
700
+    return function(resource) {
701
+      return _.has(resource, 'metadata.deletionTimestamp');
702
+    };
703
+  })
704
+  .filter('isPullingImage', function() {
705
+    return function(pod) {
706
+      if (!pod) {
707
+        return false;
708
+      }
709
+
710
+      var phase = _.get(pod, 'status.phase');
711
+      if (phase !== 'Pending') {
712
+        return false;
713
+      }
714
+
715
+      var containerStatuses = _.get(pod, 'status.containerStatuses');
716
+      if (!containerStatuses) {
717
+        return false;
718
+      }
719
+
720
+      var containerPulling = function(containerStatus) {
721
+        // TODO: Update to use the pulling reason when available. We assume
722
+        // ContainerCreating === pulling, which might not be true.
723
+        return _.get(containerStatus, 'state.waiting.reason') === 'ContainerCreating';
724
+      };
725
+
726
+      return _.some(containerStatuses, containerPulling);
727
+    };
728
+  })
699 729
   .filter('newestResource', function() {
700 730
     return function(resources) {
701 731
       var newest = null;
... ...
@@ -153,6 +153,31 @@ angular.module('openshiftConsole')
153 153
       return toString(amountAndUnitFilter(value, type, true));
154 154
     };
155 155
   })
156
+  .filter('humanizeSize', function() {
157
+    return function(bytes) {
158
+      if (bytes === null || bytes === undefined || bytes === '') {
159
+        return bytes;
160
+      }
161
+
162
+      bytes = Number(bytes);
163
+      if (bytes < 1024) {
164
+        return bytes + " bytes";
165
+      }
166
+
167
+      var KiB = bytes / 1024;
168
+      if (KiB < 1024) {
169
+        return KiB.toFixed(1) + " KiB";
170
+      }
171
+
172
+      var MiB = KiB / 1024;
173
+      if (MiB < 1024) {
174
+        return MiB.toFixed(1) + " MiB";
175
+      }
176
+
177
+      var GiB = MiB / 1024;
178
+      return GiB.toFixed(1) + " GiB";
179
+    };
180
+  })
156 181
   .filter('computeResourceLabel', function() {
157 182
     return function(computeResourceType, capitalize) {
158 183
       switch (computeResourceType) {
... ...
@@ -18,6 +18,9 @@
18 18
           <span ng-if="imagesByDockerReference[container.image]">
19 19
             <a ng-href="{{imagesByDockerReference[container.image].imageStreamName | navigateResourceURL : 'ImageStream' : imagesByDockerReference[container.image].imageStreamNamespace}}">{{container.image | imageStreamName}}</a>
20 20
             (<span title="{{imagesByDockerReference[container.image].metadata.name}}">{{imagesByDockerReference[container.image].metadata.name | stripSHAPrefix | limitTo: 7}}</span>)
21
+            <span ng-if="imagesByDockerReference[container.image].dockerImageMetadata.Size" class="small text-muted nowrap">
22
+              {{imagesByDockerReference[container.image].dockerImageMetadata.Size | humanizeSize}}
23
+            </span>
21 24
           </span>
22 25
         </div>
23 26
       </div>
... ...
@@ -6760,8 +6760,8 @@ return {
6760 6760
 restrict:"E",
6761 6761
 templateUrl:"views/directives/_ellipsis-loader.html"
6762 6762
 };
6763
-} ]), angular.module("openshiftConsole").directive("podStatusChart", [ "$timeout", "hashSizeFilter", "isTroubledPodFilter", "numContainersReadyFilter", "Logger", function(a, b, c, d, e) {
6764
-var f = 0;
6763
+} ]), angular.module("openshiftConsole").directive("podStatusChart", [ "$timeout", "hashSizeFilter", "isPullingImageFilter", "isTerminatingFilter", "isTroubledPodFilter", "numContainersReadyFilter", "Logger", function(a, b, c, d, e, f, g) {
6764
+var h = 0;
6765 6765
 return {
6766 6766
 restrict:"E",
6767 6767
 scope:{
... ...
@@ -6769,32 +6769,35 @@ pods:"=",
6769 6769
 desired:"=?"
6770 6770
 },
6771 6771
 templateUrl:"views/_pod-status-chart.html",
6772
-link:function(a, g) {
6773
-function h() {
6774
-var c, d = d3.select(g[0]).select("text.c3-chart-arcs-title"), f = b(a.pods);
6775
-return d ? (c = angular.isNumber(a.desired) && a.desired !== f ? "scaling to " + a.desired + "..." :1 === f ? "pod" :"pods", d.selectAll("*").remove(), d.insert("tspan").text(f).classed("pod-count donut-title-big-pf", !0).attr("dy", 0).attr("x", 0), void d.insert("tspan").text(c).classed("donut-title-small-pf", !0).attr("dy", 20).attr("x", 0)) :void e.warn("Can't select donut title element");
6772
+link:function(a, i) {
6773
+function j() {
6774
+var c, d = d3.select(i[0]).select("text.c3-chart-arcs-title"), e = b(a.pods);
6775
+return d ? (c = angular.isNumber(a.desired) && a.desired !== e ? "scaling to " + a.desired + "..." :1 === e ? "pod" :"pods", d.selectAll("*").remove(), d.insert("tspan").text(e).classed("pod-count donut-title-big-pf", !0).attr("dy", 0).attr("x", 0), void d.insert("tspan").text(c).classed("donut-title-small-pf", !0).attr("dy", 20).attr("x", 0)) :void g.warn("Can't select donut title element");
6776 6776
 }
6777
-function i(c) {
6777
+function k(c) {
6778 6778
 var d = {
6779 6779
 columns:[]
6780 6780
 };
6781
-angular.forEach(m, function(a) {
6781
+angular.forEach(q, function(a) {
6782 6782
 d.columns.push([ a, c[a] || 0 ]);
6783
-}), 0 === b(c) ? d.columns.push([ "Empty", 1 ]) :d.unload = "Empty", k ? k.load(d) :(l.data.columns = d.columns, k = c3.generate(l)), a.podStatusData = d.columns;
6783
+}), 0 === b(c) ? d.columns.push([ "Empty", 1 ]) :d.unload = "Empty", o ? o.load(d) :(p.data.columns = d.columns, o = c3.generate(p)), a.podStatusData = d.columns;
6784 6784
 }
6785
-function j() {
6786
-var b = {}, e = function(a) {
6787
-b[a] = (b[a] || 0) + 1;
6788
-}, f = function(a) {
6789
-var b = d(a), c = a.spec.containers.length;
6785
+function l(a) {
6786
+var b = f(a), c = a.spec.containers.length;
6790 6787
 return b === c;
6791
-};
6788
+}
6789
+function m(a) {
6790
+return d(a) ? "Terminating" :e(a) ? "Warning" :c(a) ? "Pulling" :"Running" !== a.status.phase || l(a) ? _.get(a, "status.phase", "Unknown") :"Not Ready";
6791
+}
6792
+function n() {
6793
+var b = {};
6792 6794
 return angular.forEach(a.pods, function(a) {
6793
-return c(a) ? void e("Warning") :"Running" !== a.status.phase || f(a) ? void e(a.status.phase) :void e("Not Ready");
6795
+var c = m(a);
6796
+b[c] = (b[c] || 0) + 1;
6794 6797
 }), b;
6795 6798
 }
6796
-var k, l, m = [ "Running", "Not Ready", "Warning", "Failed", "Pending", "Succeeded", "Unknown" ];
6797
-f++, a.chartId = "pods-donut-chart-" + f, l = {
6799
+var o, p, q = [ "Running", "Not Ready", "Warning", "Failed", "Pulling", "Pending", "Succeeded", "Terminating", "Unknown" ];
6800
+h++, a.chartId = "pods-donut-chart-" + h, p = {
6798 6801
 type:"donut",
6799 6802
 bindto:"#" + a.chartId,
6800 6803
 donut:{
... ...
@@ -6811,7 +6814,7 @@ width:150
6811 6811
 legend:{
6812 6812
 show:!1
6813 6813
 },
6814
-onrendered:h,
6814
+onrendered:j,
6815 6815
 tooltip:{
6816 6816
 format:{
6817 6817
 value:function(a, b, c) {
... ...
@@ -6825,9 +6828,12 @@ left:0
6825 6825
 };
6826 6826
 }
6827 6827
 },
6828
+transition:{
6829
+duration:350
6830
+},
6828 6831
 data:{
6829 6832
 type:"donut",
6830
-groups:[ m ],
6833
+groups:[ q ],
6831 6834
 order:null,
6832 6835
 colors:{
6833 6836
 Empty:"#ffffff",
... ...
@@ -6835,16 +6841,22 @@ Running:"#00b9e4",
6835 6835
 "Not Ready":"#beedf9",
6836 6836
 Warning:"#f9d67a",
6837 6837
 Failed:"#d9534f",
6838
-Pending:"#e8e8e8",
6838
+Pulling:"#d1d1d1",
6839
+Pending:"#ededed",
6839 6840
 Succeeded:"#3f9c35",
6841
+Terminating:"#00659c",
6840 6842
 Unknown:"#f9d67a"
6841 6843
 },
6842 6844
 selection:{
6843 6845
 enabled:!1
6844 6846
 }
6845 6847
 }
6846
-}, a.$watch(j, i, !0), a.$watch("desired", h), a.$on("destroy", function() {
6847
-k && (k = k.destroy());
6848
+};
6849
+var r = _.debounce(k, 350, {
6850
+maxWait:500
6851
+});
6852
+a.$watch(n, r, !0), a.$watch("desired", j), a.$on("destroy", function() {
6853
+o && (o = o.destroy());
6848 6854
 });
6849 6855
 }
6850 6856
 };
... ...
@@ -7617,6 +7629,22 @@ return angular.forEach(a.status.containerStatuses, function(a) {
7617 7617
 b += a.restartCount;
7618 7618
 }), b;
7619 7619
 };
7620
+}).filter("isTerminating", function() {
7621
+return function(a) {
7622
+return _.has(a, "metadata.deletionTimestamp");
7623
+};
7624
+}).filter("isPullingImage", function() {
7625
+return function(a) {
7626
+if (!a) return !1;
7627
+var b = _.get(a, "status.phase");
7628
+if ("Pending" !== b) return !1;
7629
+var c = _.get(a, "status.containerStatuses");
7630
+if (!c) return !1;
7631
+var d = function(a) {
7632
+return "ContainerCreating" === _.get(a, "state.waiting.reason");
7633
+};
7634
+return _.some(c, d);
7635
+};
7620 7636
 }).filter("newestResource", function() {
7621 7637
 return function(a) {
7622 7638
 var b = null;
... ...
@@ -7840,7 +7868,18 @@ return b ? a + " " + b :a;
7840 7840
 });
7841 7841
 return d(a(b, c, !0));
7842 7842
 };
7843
-} ]).filter("computeResourceLabel", function() {
7843
+} ]).filter("humanizeSize", function() {
7844
+return function(a) {
7845
+if (null === a || void 0 === a || "" === a) return a;
7846
+if (a = Number(a), 1024 > a) return a + " bytes";
7847
+var b = a / 1024;
7848
+if (1024 > b) return b.toFixed(1) + " KiB";
7849
+var c = b / 1024;
7850
+if (1024 > c) return c.toFixed(1) + " MiB";
7851
+var d = c / 1024;
7852
+return d.toFixed(1) + " GiB";
7853
+};
7854
+}).filter("computeResourceLabel", function() {
7844 7855
 return function(a, b) {
7845 7856
 switch (a) {
7846 7857
 case "cpu":
... ...
@@ -8416,6 +8455,9 @@ var _scriptsTemplatesJs = []byte(`angular.module('openshiftConsoleTemplates', []
8416 8416
     "<span ng-if=\"imagesByDockerReference[container.image]\">\n" +
8417 8417
     "<a ng-href=\"{{imagesByDockerReference[container.image].imageStreamName | navigateResourceURL : 'ImageStream' : imagesByDockerReference[container.image].imageStreamNamespace}}\">{{container.image | imageStreamName}}</a>\n" +
8418 8418
     "(<span title=\"{{imagesByDockerReference[container.image].metadata.name}}\">{{imagesByDockerReference[container.image].metadata.name | stripSHAPrefix | limitTo: 7}}</span>)\n" +
8419
+    "<span ng-if=\"imagesByDockerReference[container.image].dockerImageMetadata.Size\" class=\"small text-muted nowrap\">\n" +
8420
+    "{{imagesByDockerReference[container.image].dockerImageMetadata.Size | humanizeSize}}\n" +
8421
+    "</span>\n" +
8419 8422
     "</span>\n" +
8420 8423
     "</div>\n" +
8421 8424
     "</div>\n" +