├── .gitattributes
├── .gitignore
├── .jscs.json
├── .jshintrc
├── Gruntfile.js
├── LICENSE
├── README.md
├── dist
├── README.md
├── components
│ ├── clusters
│ │ ├── clusterConfig.js
│ │ ├── clusterConfig.js.map
│ │ ├── clusterInfo.js
│ │ ├── clusterInfo.js.map
│ │ ├── clusterWorkloads.js
│ │ ├── clusterWorkloads.js.map
│ │ ├── clusters.js
│ │ ├── clusters.js.map
│ │ ├── nodeInfo.js
│ │ ├── nodeInfo.js.map
│ │ ├── partials
│ │ │ ├── cluster_config.html
│ │ │ ├── cluster_info.html
│ │ │ ├── cluster_workloads.html
│ │ │ ├── clusters.html
│ │ │ ├── node_info.html
│ │ │ └── pod_info.html
│ │ ├── podInfo.js
│ │ └── podInfo.js.map
│ └── config
│ │ ├── config.html
│ │ ├── config.js
│ │ └── config.js.map
├── css
│ ├── dark.css
│ └── light.css
├── dashboards
│ ├── kubernetes-cluster.json
│ ├── kubernetes-container.json
│ ├── kubernetes-deployments.json
│ └── kubernetes-node.json
├── datasource
│ ├── config.html
│ ├── datasource.js
│ ├── datasource.js.map
│ ├── img
│ │ └── logo.svg
│ ├── module.js
│ ├── module.js.map
│ └── plugin.json
├── img
│ ├── app-menu-screenshot.png
│ ├── cluster-dashboard-screenshot.png
│ ├── container-dashboard-screenshot.png
│ ├── logo.svg
│ ├── namespace-details-screenshot.png
│ ├── node-dashboard-screenshot.png
│ ├── overview-screenshot.png
│ └── pod-details-screenshot.png
├── module.js
├── module.js.map
├── panels
│ ├── nodeData
│ │ ├── module.js
│ │ ├── module.js.map
│ │ ├── nodeData.js
│ │ ├── nodeData.js.map
│ │ ├── nodeStats.js
│ │ ├── nodeStats.js.map
│ │ ├── partials
│ │ │ └── node_info.html
│ │ └── plugin.json
│ └── podNav
│ │ ├── module.js
│ │ ├── module.js.map
│ │ ├── partials
│ │ └── pod_nav.html
│ │ ├── plugin.json
│ │ ├── podNav.js
│ │ └── podNav.js.map
└── plugin.json
├── package.json
└── src
├── components
├── clusters
│ ├── clusterConfig.js
│ ├── clusterInfo.js
│ ├── clusterWorkloads.js
│ ├── clusters.js
│ ├── nodeInfo.js
│ ├── partials
│ │ ├── cluster_config.html
│ │ ├── cluster_info.html
│ │ ├── cluster_workloads.html
│ │ ├── clusters.html
│ │ ├── node_info.html
│ │ └── pod_info.html
│ └── podInfo.js
└── config
│ ├── config.html
│ └── config.js
├── css
├── dark.css
└── light.css
├── dashboards
├── kubernetes-cluster.json
├── kubernetes-container.json
├── kubernetes-deployments.json
└── kubernetes-node.json
├── datasource
├── config.html
├── datasource.js
├── img
│ └── logo.svg
├── module.js
└── plugin.json
├── img
├── app-menu-screenshot.png
├── cluster-dashboard-screenshot.png
├── container-dashboard-screenshot.png
├── logo.svg
├── namespace-details-screenshot.png
├── node-dashboard-screenshot.png
├── overview-screenshot.png
└── pod-details-screenshot.png
├── module.js
├── panels
├── nodeData
│ ├── module.js
│ ├── nodeData.js
│ ├── nodeStats.js
│ ├── partials
│ │ └── node_info.html
│ └── plugin.json
└── podNav
│ ├── module.js
│ ├── partials
│ └── pod_nav.html
│ ├── plugin.json
│ └── podNav.js
└── plugin.json
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Don't diff files in dist/
2 | *.map binary
3 | dist/** binary
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 |
6 | # Runtime data
7 | pids
8 | *.pid
9 | *.seed
10 |
11 | # Directory for instrumented libs generated by jscoverage/JSCover
12 | lib-cov
13 |
14 | # Coverage directory used by tools like istanbul
15 | coverage
16 |
17 | # nyc test coverage
18 | .nyc_output
19 |
20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
21 | .grunt
22 |
23 | # node-waf configuration
24 | .lock-wscript
25 |
26 | # Compiled binary addons (http://nodejs.org/api/addons.html)
27 | build/Release
28 |
29 | # Dependency directories
30 | node_modules
31 | jspm_packages
32 |
33 | # Optional npm cache directory
34 | .npm
35 |
36 | # Optional REPL history
37 | .node_repl_history
38 |
--------------------------------------------------------------------------------
/.jscs.json:
--------------------------------------------------------------------------------
1 | {
2 | "esnext": true,
3 | "disallowImplicitTypeConversion": ["string"],
4 | "disallowKeywords": ["with"],
5 | "disallowMultipleLineBreaks": true,
6 | "disallowMixedSpacesAndTabs": true,
7 | "disallowTrailingWhitespace": true,
8 | "requireSpacesInFunctionExpression": {
9 | "beforeOpeningCurlyBrace": true
10 | },
11 | "disallowSpacesInsideArrayBrackets": true,
12 | "disallowSpacesInsideParentheses": true,
13 | "validateIndentation": 2
14 | }
15 |
--------------------------------------------------------------------------------
/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "browser": true,
3 | "esnext": true,
4 | "bitwise":false,
5 | "curly": true,
6 | "eqnull": true,
7 | "strict": false,
8 | "devel": true,
9 | "eqeqeq": true,
10 | "forin": false,
11 | "immed": true,
12 | "supernew": true,
13 | "expr": true,
14 | "indent": 2,
15 | "latedef": false,
16 | "newcap": true,
17 | "noarg": true,
18 | "noempty": true,
19 | "undef": true,
20 | "boss": true,
21 | "trailing": true,
22 | "laxbreak": true,
23 | "laxcomma": true,
24 | "sub": true,
25 | "unused": true,
26 | "maxdepth": 6,
27 | "maxlen": 140,
28 |
29 | "globals": {
30 | "System": true,
31 | "Promise": true,
32 | "define": true,
33 | "require": true,
34 | "Chromath": false,
35 | "setImmediate": true
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/Gruntfile.js:
--------------------------------------------------------------------------------
1 | module.exports = function(grunt) {
2 |
3 | require('load-grunt-tasks')(grunt);
4 |
5 | grunt.loadNpmTasks('grunt-execute');
6 | grunt.loadNpmTasks('grunt-contrib-clean');
7 |
8 | grunt.initConfig({
9 |
10 | clean: ["dist"],
11 |
12 | copy: {
13 | src_to_dist: {
14 | cwd: 'src',
15 | expand: true,
16 | src: ['**/*', '!**/*.js', '!**/*.scss'],
17 | dest: 'dist'
18 | },
19 | includes_to_dist: {
20 | cwd: 'includes',
21 | expand: true,
22 | src: ['**/*', '!**/*.js', '!**/*.scss'],
23 | dest: 'dist'
24 | },
25 | pluginDef: {
26 | expand: true,
27 | src: ['README.md'],
28 | dest: 'dist',
29 | }
30 | },
31 |
32 | watch: {
33 | rebuild_all: {
34 | files: ['src/**/*', 'README.md'],
35 | tasks: ['default'],
36 | options: {spawn: false}
37 | },
38 | },
39 |
40 | babel: {
41 | options: {
42 | sourceMap: true,
43 | presets: ["es2015"],
44 | plugins: ['transform-es2015-modules-systemjs', "transform-es2015-for-of"],
45 | },
46 | dist: {
47 | files: [{
48 | cwd: 'src',
49 | expand: true,
50 | src: ['**/*.js', '!src/directives/*.js', '!src/filters/*.js'],
51 | dest: 'dist',
52 | ext:'.js'
53 | }]
54 | },
55 | },
56 |
57 | jshint: {
58 | source: {
59 | files: {
60 | src: ['src/**/*.js'],
61 | }
62 | },
63 | options: {
64 | jshintrc: true,
65 | reporter: require('jshint-stylish'),
66 | ignores: [
67 | 'node_modules/*',
68 | 'dist/*',
69 | ]
70 | }
71 | },
72 | jscs: {
73 | src: ['src/**/*.js'],
74 | options: {
75 | config: ".jscs.json",
76 | },
77 | },
78 |
79 | sass: {
80 | options: {
81 | sourceMap: true
82 | },
83 | dist: {
84 | files: {
85 | "dist/css/kubernetes.dark.css": "src/sass/kubernetes.dark.scss",
86 | "dist/css/kubernetes.light.css": "src/sass/kubernetes.light.scss",
87 | }
88 | }
89 | }
90 | });
91 |
92 | grunt.registerTask('default', [
93 | 'clean',
94 | 'sass',
95 | 'copy:src_to_dist',
96 | 'copy:pluginDef',
97 | 'babel',
98 | 'jshint',
99 | 'jscs',
100 | ]);
101 |
102 | // does not have sass due to grafana file dependency
103 | grunt.registerTask('test', [
104 | 'clean',
105 | 'copy:src_to_dist',
106 | 'copy:pluginDef',
107 | 'babel',
108 | 'jshint',
109 | 'jscs',
110 | ]);
111 | };
112 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # WARNING: This project is no longer maintained. Please consider using the Prometheus compatible kubernetes application: https://github.com/grafana/kubernetes-app
2 |
3 | # Grafana App for Kubernetes
4 |
5 | [Kubernetes](http://kubernetes.io/) is an open-source system for automating deployment, scaling, and management of containerized applications.
6 |
7 | The Grafana Kubernetes App allows you to monitor your Kubernetes cluster's performance. It includes 4 dashboards, Cluster, Node, Pod/Container and Deployment. It also comes with [Intel Snap](http://snap-telemetry.io/) collectors that are deployed to your cluster to collect health metrics. The metrics collected are high-level cluster and node stats as well as lower level pod and container stats. Use the high-level metrics to alert on and the low-level metrics to troubleshoot.
8 |
9 | 
10 |
11 | 
12 |
13 | 
14 |
15 | ### Requirements
16 |
17 | 1. Currently only has support for **Graphite**.
18 | 2. For automatic deployment of the collectors, then Kubernetes 1.4 or higher is required.
19 | 3. Grafana 4 is required if using TLS Client Auth (rather than Basic Auth).
20 |
21 | ### Features
22 |
23 | - The app uses Kubernetes tags to allow you to filter pod metrics. Kubernetes clusters tend to have a lot of pods and a lot of pod metrics. The Pod/Container dashboard leverages the pod tags so you can easily find the relevant pod or pods.
24 |
25 | - Easy installation of collectors, either a one click deploy from Grafana or detailed instructions to deploy them manually them with kubectl (also quite easy!)
26 |
27 | - Cluster level metrics that are not available in Heapster, like CPU Capacity vs CPU Usage.
28 |
29 | - Pod and Container status metrics. See the [Snap Kubestate Collector](https://github.com/raintank/snap-plugin-collector-kubestate) for more details.
30 |
31 | ### Cluster Metrics
32 |
33 | - Pod Capacity/Usage
34 | - Memory Capacity/Usage
35 | - CPU Capacity/Usage
36 | - Disk Capacity/Usage (measurements from each container's /var/lib/docker)
37 | - Overview of Nodes, Pods and Containers
38 |
39 | ### Node Metrics
40 |
41 | - CPU
42 | - Memory Available
43 | - Load per CPU
44 | - Read IOPS
45 | - Write IOPS
46 | - %Util
47 | - Network Traffic/second
48 | - Network Packets/second
49 | - Network Errors/second
50 |
51 | ### Pod/Container Metrics
52 |
53 | - Memory Usage
54 | - Network Traffic
55 | - TCP Connections
56 | - CPU Usage
57 | - Read IOPS
58 | - Write IOPS
59 | - All Established TCP Conn
60 |
61 | ### Documentation
62 |
63 | #### Installation
64 |
65 | 1. Use the grafana-cli tool to install kubernetes from the commandline:
66 |
67 | ```
68 | grafana-cli plugins install raintank-kubernetes-app
69 | ```
70 |
71 | 2. Restart your Grafana server.
72 |
73 | 3. Log into your Grafana instance. Navigate to the Plugins section, found in the Grafana main menu. Click the Apps tabs in the Plugins section and select the newly installed Kubernetes app. To enable the app, click the Config tab and click on the Enable button.
74 |
75 | #### Connecting to your Cluster
76 |
77 | 1. Go to the Cluster List page via the Kubernetes app menu.
78 |
79 | 
80 |
81 | 2. Click the `New Cluster` button.
82 |
83 | 3. Fill in the Auth details for your cluster.
84 |
85 | 4. Choose the Graphite datasource that will be used for reading data in the dashboards.
86 |
87 | 5. Fill in the details for the Carbon host that is used to write to Graphite. This url has to be available from inside the cluster.
88 |
89 | 6. Click `Deploy`. This will deploy a DaemonSet, to collect health metrics for every node, and a pod that collects cluster metrics.
90 |
91 | #### Manual Deployment of Collectors
92 |
93 | If you do not want to deploy the collector DaemonSet and pod automatically, then it can be deployed manually with kubectl. If using an older version of Kubernetes than 1.4, you will have to adapt the json files, particularly for the daemonset, and remove some newer features. Please create an issue if you need support for older versions of Kubernetes built in to the app.
94 |
95 | The manual deployment instructions and files needed, can be downloaded from the Cluster Config page. At the bottom of the page, there is a help section with instructions and links to all the json files needed.
96 |
97 | #### Uninstalling the Collectors (DaemonSet and Pod)
98 |
99 | There is an Undeploy button on the Cluster Config page. To manually undeploy them:
100 |
101 | ```bash
102 | kubectl delete daemonsets -n kube-system snap
103 |
104 | kubectl delete deployments -n kube-system snap-kubestate-deployment
105 |
106 | kubectl delete configmaps -n kube-system snap-tasks
107 |
108 | kubectl delete configmaps -n kube-system snap-tasks-kubestate
109 | ```
110 |
111 | #### Technical Details
112 |
113 | Metrics are collected by the [Intel Snap](http://snap-telemetry.io/) collector using the [Docker plugin](https://github.com/intelsdi-x/snap-plugin-collector-docker/blob/master/METRICS.md). A DaemonSet with Snap is deployed to your Kubernetes cluster when you add a new cluster in the app. For cluster level metrics, one Snap pod is also deployed to the cluster. The [snap_k8s](https://github.com/raintank/snap_k8s) docker image used for this is based off of Intel's Snap docker image.
114 |
115 | The following Snap plugins are used to collect metrics:
116 |
117 | - [CPU Collector](https://github.com/intelsdi-x/snap-plugin-collector-cpu/blob/master/METRICS.md)
118 | - [Docker Collector](https://github.com/intelsdi-x/snap-plugin-collector-docker/blob/master/METRICS.md)
119 | - [Network Interface Collector](https://github.com/intelsdi-x/snap-plugin-collector-interface/blob/master/METRICS.md)
120 | - [IOStat Collector](https://github.com/intelsdi-x/snap-plugin-collector-iostat)
121 | - [Load Collector](https://github.com/intelsdi-x/snap-plugin-collector-load#collected-metrics)
122 | - [MemInfo Collector](https://github.com/intelsdi-x/snap-plugin-collector-meminfo/blob/master/METRICS.md)
123 | - [Kubestate Collector](https://github.com/raintank/snap-plugin-collector-kubestate)
124 |
125 | ### Feedback and Questions
126 |
127 | Please submit any issues with the app on [Github](https://github.com/raintank/kubernetes-app/issues).
128 |
129 | #### Troubleshooting
130 |
131 | If there are any problems with metrics not being collected then you can collect some logs with the following steps:
132 |
133 | 1. Get the snap pod (or pods if you have multiple nodes) name with:
134 |
135 | `kubectl get pods -n kube-system`
136 |
137 | 2. Check if the task is running with (replace xxxx with the guid):
138 |
139 | `kubectl exec -it snap-xxxxx-n kube-system -- /opt/snap/bin/snaptel task list`
140 |
141 | Include the output in the issue.
142 |
143 | 3. Get the logs with:
144 |
145 | `kubectl logs snap-xxxxx -n kube-system`
146 |
147 | Include this output in the issue too.
148 |
--------------------------------------------------------------------------------
/dist/README.md:
--------------------------------------------------------------------------------
1 | # WARNING: This project is no longer maintained. Please consider using the Prometheus compatible kubernetes application: https://github.com/grafana/kubernetes-app
2 |
3 | # Grafana App for Kubernetes
4 |
5 | [Kubernetes](http://kubernetes.io/) is an open-source system for automating deployment, scaling, and management of containerized applications.
6 |
7 | The Grafana Kubernetes App allows you to monitor your Kubernetes cluster's performance. It includes 4 dashboards, Cluster, Node, Pod/Container and Deployment. It also comes with [Intel Snap](http://snap-telemetry.io/) collectors that are deployed to your cluster to collect health metrics. The metrics collected are high-level cluster and node stats as well as lower level pod and container stats. Use the high-level metrics to alert on and the low-level metrics to troubleshoot.
8 |
9 | 
10 |
11 | 
12 |
13 | 
14 |
15 | ### Requirements
16 |
17 | 1. Currently only has support for **Graphite**.
18 | 2. For automatic deployment of the collectors, then Kubernetes 1.4 or higher is required.
19 | 3. Grafana 4 is required if using TLS Client Auth (rather than Basic Auth).
20 |
21 | ### Features
22 |
23 | - The app uses Kubernetes tags to allow you to filter pod metrics. Kubernetes clusters tend to have a lot of pods and a lot of pod metrics. The Pod/Container dashboard leverages the pod tags so you can easily find the relevant pod or pods.
24 |
25 | - Easy installation of collectors, either a one click deploy from Grafana or detailed instructions to deploy them manually them with kubectl (also quite easy!)
26 |
27 | - Cluster level metrics that are not available in Heapster, like CPU Capacity vs CPU Usage.
28 |
29 | - Pod and Container status metrics. See the [Snap Kubestate Collector](https://github.com/raintank/snap-plugin-collector-kubestate) for more details.
30 |
31 | ### Cluster Metrics
32 |
33 | - Pod Capacity/Usage
34 | - Memory Capacity/Usage
35 | - CPU Capacity/Usage
36 | - Disk Capacity/Usage (measurements from each container's /var/lib/docker)
37 | - Overview of Nodes, Pods and Containers
38 |
39 | ### Node Metrics
40 |
41 | - CPU
42 | - Memory Available
43 | - Load per CPU
44 | - Read IOPS
45 | - Write IOPS
46 | - %Util
47 | - Network Traffic/second
48 | - Network Packets/second
49 | - Network Errors/second
50 |
51 | ### Pod/Container Metrics
52 |
53 | - Memory Usage
54 | - Network Traffic
55 | - TCP Connections
56 | - CPU Usage
57 | - Read IOPS
58 | - Write IOPS
59 | - All Established TCP Conn
60 |
61 | ### Documentation
62 |
63 | #### Installation
64 |
65 | 1. Use the grafana-cli tool to install kubernetes from the commandline:
66 |
67 | ```
68 | grafana-cli plugins install raintank-kubernetes-app
69 | ```
70 |
71 | 2. Restart your Grafana server.
72 |
73 | 3. Log into your Grafana instance. Navigate to the Plugins section, found in the Grafana main menu. Click the Apps tabs in the Plugins section and select the newly installed Kubernetes app. To enable the app, click the Config tab and click on the Enable button.
74 |
75 | #### Connecting to your Cluster
76 |
77 | 1. Go to the Cluster List page via the Kubernetes app menu.
78 |
79 | 
80 |
81 | 2. Click the `New Cluster` button.
82 |
83 | 3. Fill in the Auth details for your cluster.
84 |
85 | 4. Choose the Graphite datasource that will be used for reading data in the dashboards.
86 |
87 | 5. Fill in the details for the Carbon host that is used to write to Graphite. This url has to be available from inside the cluster.
88 |
89 | 6. Click `Deploy`. This will deploy a DaemonSet, to collect health metrics for every node, and a pod that collects cluster metrics.
90 |
91 | #### Manual Deployment of Collectors
92 |
93 | If you do not want to deploy the collector DaemonSet and pod automatically, then it can be deployed manually with kubectl. If using an older version of Kubernetes than 1.4, you will have to adapt the json files, particularly for the daemonset, and remove some newer features. Please create an issue if you need support for older versions of Kubernetes built in to the app.
94 |
95 | The manual deployment instructions and files needed, can be downloaded from the Cluster Config page. At the bottom of the page, there is a help section with instructions and links to all the json files needed.
96 |
97 | #### Uninstalling the Collectors (DaemonSet and Pod)
98 |
99 | There is an Undeploy button on the Cluster Config page. To manually undeploy them:
100 |
101 | ```bash
102 | kubectl delete daemonsets -n kube-system snap
103 |
104 | kubectl delete deployments -n kube-system snap-kubestate-deployment
105 |
106 | kubectl delete configmaps -n kube-system snap-tasks
107 |
108 | kubectl delete configmaps -n kube-system snap-tasks-kubestate
109 | ```
110 |
111 | #### Technical Details
112 |
113 | Metrics are collected by the [Intel Snap](http://snap-telemetry.io/) collector using the [Docker plugin](https://github.com/intelsdi-x/snap-plugin-collector-docker/blob/master/METRICS.md). A DaemonSet with Snap is deployed to your Kubernetes cluster when you add a new cluster in the app. For cluster level metrics, one Snap pod is also deployed to the cluster. The [snap_k8s](https://github.com/raintank/snap_k8s) docker image used for this is based off of Intel's Snap docker image.
114 |
115 | The following Snap plugins are used to collect metrics:
116 |
117 | - [CPU Collector](https://github.com/intelsdi-x/snap-plugin-collector-cpu/blob/master/METRICS.md)
118 | - [Docker Collector](https://github.com/intelsdi-x/snap-plugin-collector-docker/blob/master/METRICS.md)
119 | - [Network Interface Collector](https://github.com/intelsdi-x/snap-plugin-collector-interface/blob/master/METRICS.md)
120 | - [IOStat Collector](https://github.com/intelsdi-x/snap-plugin-collector-iostat)
121 | - [Load Collector](https://github.com/intelsdi-x/snap-plugin-collector-load#collected-metrics)
122 | - [MemInfo Collector](https://github.com/intelsdi-x/snap-plugin-collector-meminfo/blob/master/METRICS.md)
123 | - [Kubestate Collector](https://github.com/raintank/snap-plugin-collector-kubestate)
124 |
125 | ### Feedback and Questions
126 |
127 | Please submit any issues with the app on [Github](https://github.com/raintank/kubernetes-app/issues).
128 |
129 | #### Troubleshooting
130 |
131 | If there are any problems with metrics not being collected then you can collect some logs with the following steps:
132 |
133 | 1. Get the snap pod (or pods if you have multiple nodes) name with:
134 |
135 | `kubectl get pods -n kube-system`
136 |
137 | 2. Check if the task is running with (replace xxxx with the guid):
138 |
139 | `kubectl exec -it snap-xxxxx-n kube-system -- /opt/snap/bin/snaptel task list`
140 |
141 | Include the output in the issue.
142 |
143 | 3. Get the logs with:
144 |
145 | `kubectl logs snap-xxxxx -n kube-system`
146 |
147 | Include this output in the issue too.
148 |
--------------------------------------------------------------------------------
/dist/components/clusters/clusterWorkloads.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | System.register(['lodash', 'jquery'], function (_export, _context) {
4 | "use strict";
5 |
6 | var _, $, _createClass, ClusterWorkloadsCtrl;
7 |
8 | function _classCallCheck(instance, Constructor) {
9 | if (!(instance instanceof Constructor)) {
10 | throw new TypeError("Cannot call a class as a function");
11 | }
12 | }
13 |
14 | function slugify(str) {
15 | var slug = str.replace("@", "at").replace("&", "and").replace(/[.]/g, "_").replace("/\W+/", "");
16 | return slug;
17 | }
18 |
19 | return {
20 | setters: [function (_lodash) {
21 | _ = _lodash.default;
22 | }, function (_jquery) {
23 | $ = _jquery.default;
24 | }],
25 | execute: function () {
26 | _createClass = function () {
27 | function defineProperties(target, props) {
28 | for (var i = 0; i < props.length; i++) {
29 | var descriptor = props[i];
30 | descriptor.enumerable = descriptor.enumerable || false;
31 | descriptor.configurable = true;
32 | if ("value" in descriptor) descriptor.writable = true;
33 | Object.defineProperty(target, descriptor.key, descriptor);
34 | }
35 | }
36 |
37 | return function (Constructor, protoProps, staticProps) {
38 | if (protoProps) defineProperties(Constructor.prototype, protoProps);
39 | if (staticProps) defineProperties(Constructor, staticProps);
40 | return Constructor;
41 | };
42 | }();
43 |
44 | _export('ClusterWorkloadsCtrl', ClusterWorkloadsCtrl = function () {
45 | /** @ngInject */
46 | function ClusterWorkloadsCtrl($scope, $injector, backendSrv, datasourceSrv, $q, $location, alertSrv) {
47 | var _this = this;
48 |
49 | _classCallCheck(this, ClusterWorkloadsCtrl);
50 |
51 | this.$q = $q;
52 | this.backendSrv = backendSrv;
53 | this.datasourceSrv = datasourceSrv;
54 | this.$location = $location;
55 | document.title = 'Grafana Kubernetes App';
56 |
57 | this.pageReady = false;
58 | this.cluster = {};
59 | this.namespaces = [];
60 | this.namespace = "";
61 | this.daemonSets = [];
62 | this.replicationControllers = [];
63 | this.deployments = [];
64 | this.pods = [];
65 |
66 | if (!("cluster" in $location.search())) {
67 | alertSrv.set("no cluster specified.", "no cluster specified in url", 'error');
68 | return;
69 | }
70 |
71 | if ("namespace" in $location.search()) {
72 | this.namespace = $location.search().namespace;
73 | }
74 |
75 | this.getCluster($location.search().cluster).then(function (clusterDS) {
76 | _this.clusterDS = clusterDS;
77 | _this.pageReady = true;
78 | _this.getWorkloads();
79 | });
80 | }
81 |
82 | _createClass(ClusterWorkloadsCtrl, [{
83 | key: 'getCluster',
84 | value: function getCluster(id) {
85 | var _this2 = this;
86 |
87 | return this.backendSrv.get('api/datasources/' + id).then(function (ds) {
88 | _this2.cluster = ds;
89 | return _this2.datasourceSrv.get(ds.name);
90 | });
91 | }
92 | }, {
93 | key: 'getWorkloads',
94 | value: function getWorkloads() {
95 | var _this3 = this;
96 |
97 | var namespace = this.namespace;
98 | this.clusterDS.getNamespaces().then(function (namespaces) {
99 | _this3.namespaces = namespaces;
100 | });
101 | this.clusterDS.getDaemonSets(namespace).then(function (daemonSets) {
102 | _this3.daemonSets = daemonSets;
103 | });
104 | this.clusterDS.getReplicationControllers(namespace).then(function (rc) {
105 | _this3.replicationControllers = rc;
106 | });
107 | this.clusterDS.getDeployments(namespace).then(function (deployments) {
108 | _this3.deployments = deployments;
109 | });
110 | this.clusterDS.getPods(namespace).then(function (pods) {
111 | _this3.pods = pods;
112 | });
113 | }
114 | }, {
115 | key: 'componentHealth',
116 | value: function componentHealth(component) {
117 | var health = "unhealthy";
118 | _.forEach(component.conditions, function (condition) {
119 | if (condition.type === "Healthy" && condition.status === "True") {
120 | health = "healthy";
121 | }
122 | });
123 | return health;
124 | }
125 | }, {
126 | key: 'isComponentHealthy',
127 | value: function isComponentHealthy(component) {
128 | return this.componentHealth(component) === "healthy";
129 | }
130 | }, {
131 | key: 'goToPodDashboard',
132 | value: function goToPodDashboard(pod) {
133 | this.$location.path("dashboard/db/kubernetes-container").search({
134 | "var-datasource": this.cluster.jsonData.ds,
135 | "var-cluster": this.cluster.name,
136 | "var-node": slugify(pod.spec.nodeName),
137 | "var-namespace": pod.metadata.namespace,
138 | "var-pod": pod.metadata.name
139 | });
140 | }
141 | }, {
142 | key: 'goToDeploymentDashboard',
143 | value: function goToDeploymentDashboard(deploy) {
144 | this.$location.path("dashboard/db/kubernetes-deployments").search({
145 | "var-datasource": this.cluster.jsonData.ds,
146 | "var-cluster": this.cluster.name,
147 | "var-namespace": deploy.metadata.namespace,
148 | "var-deployment": deploy.metadata.name
149 | });
150 | }
151 | }, {
152 | key: 'goToPodInfo',
153 | value: function goToPodInfo(pod, evt) {
154 | var clickTargetIsLinkOrHasLinkParents = $(evt.target).closest('a').length > 0;
155 |
156 | var closestElm = _.head($(evt.target).closest('div'));
157 | var clickTargetClickAttr = _.find(closestElm.attributes, { name: "ng-click" });
158 | var clickTargetIsNodeDashboard = clickTargetClickAttr ? clickTargetClickAttr.value === "ctrl.goToPodDashboard(pod, $event)" : false;
159 | if (clickTargetIsLinkOrHasLinkParents === false && clickTargetIsNodeDashboard === false) {
160 | this.$location.path("plugins/raintank-kubernetes-app/page/pod-info").search({
161 | "cluster": this.cluster.id,
162 | "namespace": slugify(pod.metadata.namespace),
163 | "pod": pod.metadata.name
164 | });
165 | }
166 | }
167 | }]);
168 |
169 | return ClusterWorkloadsCtrl;
170 | }());
171 |
172 | _export('ClusterWorkloadsCtrl', ClusterWorkloadsCtrl);
173 |
174 | ClusterWorkloadsCtrl.templateUrl = 'components/clusters/partials/cluster_workloads.html';
175 | }
176 | };
177 | });
178 | //# sourceMappingURL=clusterWorkloads.js.map
179 |
--------------------------------------------------------------------------------
/dist/components/clusters/clusterWorkloads.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["../../../src/components/clusters/clusterWorkloads.js"],"names":["slugify","str","slug","replace","_","$","ClusterWorkloadsCtrl","$scope","$injector","backendSrv","datasourceSrv","$q","$location","alertSrv","document","title","pageReady","cluster","namespaces","namespace","daemonSets","replicationControllers","deployments","pods","search","set","getCluster","then","clusterDS","getWorkloads","id","get","ds","name","getNamespaces","getDaemonSets","getReplicationControllers","rc","getDeployments","getPods","component","health","forEach","conditions","condition","type","status","componentHealth","pod","path","jsonData","spec","nodeName","metadata","deploy","evt","clickTargetIsLinkOrHasLinkParents","target","closest","length","closestElm","head","clickTargetClickAttr","find","attributes","clickTargetIsNodeDashboard","value","templateUrl"],"mappings":"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","file":"clusterWorkloads.js","sourcesContent":["import _ from 'lodash';\nimport $ from 'jquery';\n\nfunction slugify(str) {\n var slug = str.replace(\"@\", \"at\").replace(\"&\", \"and\").replace(/[.]/g, \"_\").replace(\"/\\W+/\", \"\");\n return slug;\n}\n\nexport class ClusterWorkloadsCtrl {\n /** @ngInject */\n constructor($scope, $injector, backendSrv, datasourceSrv, $q, $location, alertSrv) {\n this.$q = $q;\n this.backendSrv = backendSrv;\n this.datasourceSrv = datasourceSrv;\n this.$location = $location;\n document.title = 'Grafana Kubernetes App';\n\n this.pageReady = false;\n this.cluster = {};\n this.namespaces = [];\n this.namespace = \"\";\n this.daemonSets = [];\n this.replicationControllers = [];\n this.deployments = [];\n this.pods = [];\n\n if (!(\"cluster\" in $location.search())) {\n alertSrv.set(\"no cluster specified.\", \"no cluster specified in url\", 'error');\n return;\n }\n\n if (\"namespace\" in $location.search()) {\n this.namespace = $location.search().namespace;\n }\n\n this.getCluster($location.search().cluster)\n .then(clusterDS => {\n this.clusterDS = clusterDS;\n this.pageReady = true;\n this.getWorkloads();\n });\n }\n\n getCluster(id) {\n return this.backendSrv.get('api/datasources/'+id).then(ds => {\n this.cluster = ds;\n return this.datasourceSrv.get(ds.name);\n });\n }\n\n getWorkloads() {\n let namespace = this.namespace;\n this.clusterDS.getNamespaces().then(namespaces => {\n this.namespaces = namespaces;\n });\n this.clusterDS.getDaemonSets(namespace).then(daemonSets => {\n this.daemonSets = daemonSets;\n });\n this.clusterDS.getReplicationControllers(namespace).then(rc => {\n this.replicationControllers = rc;\n });\n this.clusterDS.getDeployments(namespace).then(deployments => {\n this.deployments = deployments;\n });\n this.clusterDS.getPods(namespace).then(pods => {\n this.pods = pods;\n });\n }\n\n componentHealth(component) {\n var health = \"unhealthy\";\n _.forEach(component.conditions, function(condition) {\n if ((condition.type === \"Healthy\") && (condition.status === \"True\")) {\n health = \"healthy\";\n }\n });\n return health;\n }\n\n isComponentHealthy(component) {\n return this.componentHealth(component) === \"healthy\";\n }\n\n goToPodDashboard(pod) {\n this.$location.path(\"dashboard/db/kubernetes-container\")\n .search({\n \"var-datasource\": this.cluster.jsonData.ds,\n \"var-cluster\": this.cluster.name,\n \"var-node\": slugify(pod.spec.nodeName),\n \"var-namespace\": pod.metadata.namespace,\n \"var-pod\": pod.metadata.name\n });\n }\n\n goToDeploymentDashboard(deploy) {\n this.$location.path(\"dashboard/db/kubernetes-deployments\")\n .search({\n \"var-datasource\": this.cluster.jsonData.ds,\n \"var-cluster\": this.cluster.name,\n \"var-namespace\": deploy.metadata.namespace,\n \"var-deployment\": deploy.metadata.name\n });\n }\n\n goToPodInfo(pod, evt) {\n var clickTargetIsLinkOrHasLinkParents = $(evt.target).closest('a').length > 0;\n\n var closestElm = _.head($(evt.target).closest('div'));\n var clickTargetClickAttr = _.find(closestElm.attributes, {name: \"ng-click\"});\n var clickTargetIsNodeDashboard = clickTargetClickAttr ? clickTargetClickAttr.value === \"ctrl.goToPodDashboard(pod, $event)\" : false;\n if (clickTargetIsLinkOrHasLinkParents === false &&\n clickTargetIsNodeDashboard === false) {\n this.$location.path(\"plugins/raintank-kubernetes-app/page/pod-info\")\n .search({\n \"cluster\": this.cluster.id,\n \"namespace\": slugify(pod.metadata.namespace),\n \"pod\": pod.metadata.name\n });\n }\n }\n}\n\nClusterWorkloadsCtrl.templateUrl = 'components/clusters/partials/cluster_workloads.html';\n"]}
--------------------------------------------------------------------------------
/dist/components/clusters/clusters.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | System.register(['lodash', 'app/core/app_events'], function (_export, _context) {
4 | "use strict";
5 |
6 | var _, appEvents, _createClass, ClustersCtrl;
7 |
8 | function _classCallCheck(instance, Constructor) {
9 | if (!(instance instanceof Constructor)) {
10 | throw new TypeError("Cannot call a class as a function");
11 | }
12 | }
13 |
14 | return {
15 | setters: [function (_lodash) {
16 | _ = _lodash.default;
17 | }, function (_appCoreApp_events) {
18 | appEvents = _appCoreApp_events.default;
19 | }],
20 | execute: function () {
21 | _createClass = function () {
22 | function defineProperties(target, props) {
23 | for (var i = 0; i < props.length; i++) {
24 | var descriptor = props[i];
25 | descriptor.enumerable = descriptor.enumerable || false;
26 | descriptor.configurable = true;
27 | if ("value" in descriptor) descriptor.writable = true;
28 | Object.defineProperty(target, descriptor.key, descriptor);
29 | }
30 | }
31 |
32 | return function (Constructor, protoProps, staticProps) {
33 | if (protoProps) defineProperties(Constructor.prototype, protoProps);
34 | if (staticProps) defineProperties(Constructor, staticProps);
35 | return Constructor;
36 | };
37 | }();
38 |
39 | _export('ClustersCtrl', ClustersCtrl = function () {
40 | /** @ngInject */
41 | function ClustersCtrl($scope, $injector, backendSrv, contextSrv, $location) {
42 | _classCallCheck(this, ClustersCtrl);
43 |
44 | var self = this;
45 | this.isOrgEditor = contextSrv.hasRole('Editor') || contextSrv.hasRole('Admin');
46 | this.backendSrv = backendSrv;
47 | this.$location = $location;
48 | document.title = 'Grafana Kubernetes App';
49 | this.clusters = {};
50 | this.pageReady = false;
51 | this.getClusters().then(function () {
52 | self.pageReady = true;
53 | });
54 | }
55 |
56 | _createClass(ClustersCtrl, [{
57 | key: 'getClusters',
58 | value: function getClusters() {
59 | var self = this;
60 | return this.backendSrv.get('/api/datasources').then(function (result) {
61 | self.clusters = _.filter(result, { "type": "raintank-kubernetes-datasource" });
62 | });
63 | }
64 | }, {
65 | key: 'confirmDelete',
66 | value: function confirmDelete(id) {
67 | var _this = this;
68 |
69 | this.backendSrv.delete('/api/datasources/' + id).then(function () {
70 | _this.getClusters();
71 | });
72 | }
73 | }, {
74 | key: 'deleteCluster',
75 | value: function deleteCluster(cluster) {
76 | var _this2 = this;
77 |
78 | appEvents.emit('confirm-modal', {
79 | title: 'Delete',
80 | text: 'Are you sure you want to delete this data source? ' + 'If you need to undeploy the collectors, then do that before deleting the data source.',
81 | yesText: "Delete",
82 | icon: "fa-trash",
83 | onConfirm: function onConfirm() {
84 | _this2.confirmDelete(cluster.id);
85 | }
86 | });
87 | }
88 | }, {
89 | key: 'clusterInfo',
90 | value: function clusterInfo(cluster) {
91 | this.$location.path("plugins/raintank-kubernetes-app/page/cluster-info").search({ "cluster": cluster.id });
92 | }
93 | }]);
94 |
95 | return ClustersCtrl;
96 | }());
97 |
98 | _export('ClustersCtrl', ClustersCtrl);
99 |
100 | ClustersCtrl.templateUrl = 'components/clusters/partials/clusters.html';
101 | }
102 | };
103 | });
104 | //# sourceMappingURL=clusters.js.map
105 |
--------------------------------------------------------------------------------
/dist/components/clusters/clusters.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["../../../src/components/clusters/clusters.js"],"names":["_","appEvents","ClustersCtrl","$scope","$injector","backendSrv","contextSrv","$location","self","isOrgEditor","hasRole","document","title","clusters","pageReady","getClusters","then","get","result","filter","id","delete","cluster","emit","text","yesText","icon","onConfirm","confirmDelete","path","search","templateUrl"],"mappings":";;;;;;;;;;;;;;;AAAOA,O;;AACAC,e;;;;;;;;;;;;;;;;;;;;;8BAEMC,Y;AACX;AACA,8BAAYC,MAAZ,EAAoBC,SAApB,EAA+BC,UAA/B,EAA2CC,UAA3C,EAAuDC,SAAvD,EAAkE;AAAA;;AAChE,cAAIC,OAAO,IAAX;AACA,eAAKC,WAAL,GAAmBH,WAAWI,OAAX,CAAmB,QAAnB,KAAgCJ,WAAWI,OAAX,CAAmB,OAAnB,CAAnD;AACA,eAAKL,UAAL,GAAkBA,UAAlB;AACA,eAAKE,SAAL,GAAiBA,SAAjB;AACAI,mBAASC,KAAT,GAAiB,wBAAjB;AACA,eAAKC,QAAL,GAAgB,EAAhB;AACA,eAAKC,SAAL,GAAiB,KAAjB;AACA,eAAKC,WAAL,GAAmBC,IAAnB,CAAwB,YAAM;AAC5BR,iBAAKM,SAAL,GAAiB,IAAjB;AACD,WAFD;AAGD;;;;wCAEa;AACZ,gBAAIN,OAAO,IAAX;AACA,mBAAO,KAAKH,UAAL,CAAgBY,GAAhB,CAAoB,kBAApB,EACND,IADM,CACD,UAACE,MAAD,EAAY;AAChBV,mBAAKK,QAAL,GAAgBb,EAAEmB,MAAF,CAASD,MAAT,EAAiB,EAAC,QAAQ,gCAAT,EAAjB,CAAhB;AACD,aAHM,CAAP;AAID;;;wCAEaE,E,EAAI;AAAA;;AAChB,iBAAKf,UAAL,CAAgBgB,MAAhB,CAAuB,sBAAsBD,EAA7C,EAAiDJ,IAAjD,CAAsD,YAAM;AAC1D,oBAAKD,WAAL;AACD,aAFD;AAGD;;;wCAEaO,O,EAAS;AAAA;;AACrBrB,sBAAUsB,IAAV,CAAe,eAAf,EAAgC;AAC9BX,qBAAO,QADuB;AAE9BY,oBAAM,uDACJ,uFAH4B;AAI9BC,uBAAS,QAJqB;AAK9BC,oBAAM,UALwB;AAM9BC,yBAAW,qBAAM;AACf,uBAAKC,aAAL,CAAmBN,QAAQF,EAA3B;AACD;AAR6B,aAAhC;AAUD;;;sCAEWE,O,EAAS;AACnB,iBAAKf,SAAL,CAAesB,IAAf,CAAoB,mDAApB,EAAyEC,MAAzE,CAAgF,EAAC,WAAWR,QAAQF,EAApB,EAAhF;AACD;;;;;;;;AAGHlB,mBAAa6B,WAAb,GAA2B,4CAA3B","file":"clusters.js","sourcesContent":["import _ from 'lodash';\nimport appEvents from 'app/core/app_events';\n\nexport class ClustersCtrl {\n /** @ngInject */\n constructor($scope, $injector, backendSrv, contextSrv, $location) {\n var self = this;\n this.isOrgEditor = contextSrv.hasRole('Editor') || contextSrv.hasRole('Admin');\n this.backendSrv = backendSrv;\n this.$location = $location;\n document.title = 'Grafana Kubernetes App';\n this.clusters = {};\n this.pageReady = false;\n this.getClusters().then(() => {\n self.pageReady = true;\n });\n }\n\n getClusters() {\n var self = this;\n return this.backendSrv.get('/api/datasources')\n .then((result) => {\n self.clusters = _.filter(result, {\"type\": \"raintank-kubernetes-datasource\"});\n });\n }\n\n confirmDelete(id) {\n this.backendSrv.delete('/api/datasources/' + id).then(() => {\n this.getClusters();\n });\n }\n\n deleteCluster(cluster) {\n appEvents.emit('confirm-modal', {\n title: 'Delete',\n text: 'Are you sure you want to delete this data source? ' +\n 'If you need to undeploy the collectors, then do that before deleting the data source.',\n yesText: \"Delete\",\n icon: \"fa-trash\",\n onConfirm: () => {\n this.confirmDelete(cluster.id);\n }\n });\n }\n\n clusterInfo(cluster) {\n this.$location.path(\"plugins/raintank-kubernetes-app/page/cluster-info\").search({\"cluster\": cluster.id});\n }\n}\n\nClustersCtrl.templateUrl = 'components/clusters/partials/clusters.html';\n"]}
--------------------------------------------------------------------------------
/dist/components/clusters/nodeInfo.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | System.register(['moment'], function (_export, _context) {
4 | "use strict";
5 |
6 | var moment, _createClass, NodeInfoCtrl;
7 |
8 | function _classCallCheck(instance, Constructor) {
9 | if (!(instance instanceof Constructor)) {
10 | throw new TypeError("Cannot call a class as a function");
11 | }
12 | }
13 |
14 | function slugify(str) {
15 | var slug = str.replace("@", "at").replace("&", "and").replace(/[.]/g, "_").replace("/\W+/", "");
16 | return slug;
17 | }
18 |
19 | return {
20 | setters: [function (_moment) {
21 | moment = _moment.default;
22 | }],
23 | execute: function () {
24 | _createClass = function () {
25 | function defineProperties(target, props) {
26 | for (var i = 0; i < props.length; i++) {
27 | var descriptor = props[i];
28 | descriptor.enumerable = descriptor.enumerable || false;
29 | descriptor.configurable = true;
30 | if ("value" in descriptor) descriptor.writable = true;
31 | Object.defineProperty(target, descriptor.key, descriptor);
32 | }
33 | }
34 |
35 | return function (Constructor, protoProps, staticProps) {
36 | if (protoProps) defineProperties(Constructor.prototype, protoProps);
37 | if (staticProps) defineProperties(Constructor, staticProps);
38 | return Constructor;
39 | };
40 | }();
41 |
42 | _export('NodeInfoCtrl', NodeInfoCtrl = function () {
43 | /** @ngInject */
44 | function NodeInfoCtrl($scope, $injector, backendSrv, datasourceSrv, $q, $location, alertSrv) {
45 | var _this = this;
46 |
47 | _classCallCheck(this, NodeInfoCtrl);
48 |
49 | this.$q = $q;
50 | this.backendSrv = backendSrv;
51 | this.datasourceSrv = datasourceSrv;
52 | this.$location = $location;
53 | document.title = 'Grafana Kubernetes App';
54 |
55 | this.pageReady = false;
56 | this.cluster = {};
57 | this.clusterDS = {};
58 | this.node = {};
59 |
60 | if (!("cluster" in $location.search())) {
61 | alertSrv.set("no cluster specified.", "no cluster specified in url", 'error');
62 | return;
63 | } else {
64 | var cluster_id = $location.search().cluster;
65 | var node_name = $location.search().node;
66 |
67 | this.loadDatasource(cluster_id).then(function () {
68 | _this.clusterDS.getNode(node_name).then(function (node) {
69 | _this.node = node;
70 | _this.pageReady = true;
71 | });
72 | });
73 | }
74 | }
75 |
76 | _createClass(NodeInfoCtrl, [{
77 | key: 'loadDatasource',
78 | value: function loadDatasource(id) {
79 | var _this2 = this;
80 |
81 | return this.backendSrv.get('api/datasources/' + id).then(function (ds) {
82 | _this2.cluster = ds;
83 | return _this2.datasourceSrv.get(ds.name);
84 | }).then(function (clusterDS) {
85 | _this2.clusterDS = clusterDS;
86 | return clusterDS;
87 | });
88 | }
89 | }, {
90 | key: 'goToNodeDashboard',
91 | value: function goToNodeDashboard() {
92 | this.$location.path("dashboard/db/kubernetes-node").search({
93 | "var-datasource": this.cluster.jsonData.ds,
94 | "var-cluster": this.cluster.name,
95 | "var-node": slugify(this.node.metadata.name)
96 | });
97 | }
98 | }, {
99 | key: 'conditionStatus',
100 | value: function conditionStatus(condition) {
101 | var status;
102 | if (condition.type === "Ready") {
103 | status = condition.status === "True";
104 | } else {
105 | status = condition.status === "False";
106 | }
107 |
108 | return {
109 | value: status,
110 | text: status ? "Ok" : "Error"
111 | };
112 | }
113 | }, {
114 | key: 'isConditionOk',
115 | value: function isConditionOk(condition) {
116 | return this.conditionStatus(condition).value;
117 | }
118 | }, {
119 | key: 'conditionLastTransitionTime',
120 | value: function conditionLastTransitionTime(condition) {
121 | return moment(condition.lastTransitionTime).format('YYYY-MM-DD HH:mm:ss');
122 | }
123 | }]);
124 |
125 | return NodeInfoCtrl;
126 | }());
127 |
128 | _export('NodeInfoCtrl', NodeInfoCtrl);
129 |
130 | NodeInfoCtrl.templateUrl = 'components/clusters/partials/node_info.html';
131 | }
132 | };
133 | });
134 | //# sourceMappingURL=nodeInfo.js.map
135 |
--------------------------------------------------------------------------------
/dist/components/clusters/nodeInfo.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["../../../src/components/clusters/nodeInfo.js"],"names":["slugify","str","slug","replace","moment","NodeInfoCtrl","$scope","$injector","backendSrv","datasourceSrv","$q","$location","alertSrv","document","title","pageReady","cluster","clusterDS","node","search","set","cluster_id","node_name","loadDatasource","then","getNode","id","get","ds","name","path","jsonData","metadata","condition","status","type","value","text","conditionStatus","lastTransitionTime","format","templateUrl"],"mappings":"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","file":"nodeInfo.js","sourcesContent":["import moment from 'moment';\n\nexport class NodeInfoCtrl {\n /** @ngInject */\n constructor($scope, $injector, backendSrv, datasourceSrv, $q, $location, alertSrv) {\n this.$q = $q;\n this.backendSrv = backendSrv;\n this.datasourceSrv = datasourceSrv;\n this.$location = $location;\n document.title = 'Grafana Kubernetes App';\n\n this.pageReady = false;\n this.cluster = {};\n this.clusterDS = {};\n this.node = {};\n\n if (!(\"cluster\" in $location.search())) {\n alertSrv.set(\"no cluster specified.\", \"no cluster specified in url\", 'error');\n return;\n } else {\n let cluster_id = $location.search().cluster;\n let node_name = $location.search().node;\n\n this.loadDatasource(cluster_id).then(() => {\n this.clusterDS.getNode(node_name).then(node => {\n this.node = node;\n this.pageReady = true;\n });\n });\n }\n }\n\n loadDatasource(id) {\n return this.backendSrv.get('api/datasources/' + id)\n .then(ds => {\n this.cluster = ds;\n return this.datasourceSrv.get(ds.name);\n }).then(clusterDS => {\n this.clusterDS = clusterDS;\n return clusterDS;\n });\n }\n\n goToNodeDashboard() {\n this.$location.path(\"dashboard/db/kubernetes-node\")\n .search({\n \"var-datasource\": this.cluster.jsonData.ds,\n \"var-cluster\": this.cluster.name,\n \"var-node\": slugify(this.node.metadata.name)\n });\n }\n\n conditionStatus(condition) {\n var status;\n if (condition.type === \"Ready\") {\n status = condition.status === \"True\";\n } else {\n status = condition.status === \"False\";\n }\n\n return {\n value: status,\n text: status ? \"Ok\" : \"Error\"\n };\n }\n\n isConditionOk(condition) {\n return this.conditionStatus(condition).value;\n }\n\n conditionLastTransitionTime(condition) {\n return moment(condition.lastTransitionTime).format('YYYY-MM-DD HH:mm:ss');\n }\n}\n\nfunction slugify(str) {\n var slug = str.replace(\"@\", \"at\").replace(\"&\", \"and\").replace(/[.]/g, \"_\").replace(\"/\\W+/\", \"\");\n return slug;\n}\n\nNodeInfoCtrl.templateUrl = 'components/clusters/partials/node_info.html';\n"]}
--------------------------------------------------------------------------------
/dist/components/clusters/partials/cluster_config.html:
--------------------------------------------------------------------------------
1 |
2 |
Add a new cluster
3 |
4 |
5 |
72 |
The Deploy button will deploy the Snap Kubernetes Docker image with two metrics collectors that provides summary performance and availability metrics of a Kubernetes Node and its containers. (The manual deployment instructions are at the bottom of the page.)
The Deploy button will deploy the Snap Kubernetes Docker image with two metrics collectors that provides summary performance and availability metrics of a Kubernetes Node and its containers. (The manual deployment instructions are at the bottom of the page.)