blob: 034ff9d360504b7136359226d7c558aea84cd149 [file] [log] [blame]
Jack Lucas2832ba22018-04-20 13:22:05 +00001/*
2Copyright(c) 2018 AT&T Intellectual Property. All rights reserved.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6
7You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11Unless required by applicable law or agreed to in writing,
12software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
13CONDITIONS OF ANY KIND, either express or implied.
14See the License for the specific language governing permissions and limitations under the License.
15*/
16
17/*
18 * Query Kubernetes for status of deployments and extract readiness information
19 */
20
21const fs = require('fs');
22const request = require('request');
23
24const K8S_CREDS = '/var/run/secrets/kubernetes.io/serviceaccount';
25const K8S_API = 'https://kubernetes.default.svc.cluster.local/'; // Full name to match cert for TLS
26const K8S_PATH = 'apis/apps/v1beta2/namespaces/';
27
28//Get token and CA cert
29const ca = fs.readFileSync(K8S_CREDS + '/ca.crt');
30const token = fs.readFileSync(K8S_CREDS + '/token');
31
32const summarizeDeploymentList = function(list) {
33 // list is a DeploymentList object returned by k8s
34 // Individual deployments are in the array 'items'
35
36 let ret =
37 {
38 type: "summary",
39 count: 0,
40 ready: 0,
41 items: []
42 };
43
44 // Extract readiness information
45 for (let deployment of list.items) {
46 ret.items.push(
47 {
48 name: deployment.metadata.name,
49 ready: deployment.status.readyReplicas || 0,
50 unavailable: deployment.status.unavailableReplicas || 0
51 }
52 );
53 ret.count ++;
54 ret.ready = ret.ready + (deployment.status.readyReplicas || 0);
55 }
56
57 return ret;
58};
59
60const summarizeDeployment = function(deployment) {
61 // deployment is a Deployment object returned by k8s
62 // we make it look enough like a DeploymentList object to
63 // satisfy summarizeDeploymentList
64 return summarizeDeploymentList({items: [deployment]});
65};
66
67const queryKubernetes = function(path, callback) {
68 // Make request to Kubernetes
69
70 const options = {
71 url: K8S_API + path,
72 ca : ca,
73 headers: {
74 Authorization: 'bearer ' + token
75 },
76 json: true
77 };
78 console.log ("request url: " + options.url);
79 request(options, function(error, res, body) {
80 console.log ("status: " + (res && res.statusCode) ? res.statusCode : "NONE");
81 if (error) {
82 console.log("error: " + error);
83 }
84 callback(error, res, body);
85 });
86};
87
88const getStatus = function(path, extract, callback) {
89 // Get info from k8s and extract readiness info
90 queryKubernetes(path, function(error, res, body) {
91 let ret = body;
92 if (!error && res && res.statusCode === 200) {
93 ret = extract(body);
94 }
95 callback (error, res, ret);
96 });
97};
98
Jack Lucase6d18572018-05-09 22:44:31 +000099const getStatusSinglePromise = function (item) {
100 // Expect item to be of the form {namespace: "namespace", deployment: "deployment_name"}
101 return new Promise(function(resolve, reject){
102 const path = K8S_PATH + item.namespace + '/deployments/' + item.deployment;
103 queryKubernetes(path, function(error, res, body){
104 if (error) {
105 reject(error);
106 }
107 else if (res.statusCode === 404) {
108 // Treat absent deployment as if it's an unhealthy deployment
109 resolve ({
110 metadata: {name: item.deployment},
111 status: {unavailableReplicas: 1}
112 });
113 }
114 else if (res.statusCode != 200) {
115 reject(body);
116 }
117 else {
118 resolve(body);
119 }
120 });
121 });
122}
Jack Lucas2832ba22018-04-20 13:22:05 +0000123exports.getStatusNamespace = function (namespace, callback) {
124 // Get readiness information for all deployments in namespace
125 const path = K8S_PATH + namespace + '/deployments';
126 getStatus(path, summarizeDeploymentList, callback);
127};
128
129exports.getStatusSingle = function (namespace, deployment, callback) {
130 // Get readiness information for a single deployment
131 const path = K8S_PATH + namespace + '/deployments/' + deployment;
132 getStatus(path, summarizeDeployment, callback);
Jack Lucase6d18572018-05-09 22:44:31 +0000133};
134
135exports.getStatusListPromise = function (list) {
136 // List is of the form [{namespace: "namespace", deployment: "deployment_name"}, ... ]
137 const p = Promise.all(list.map(getStatusSinglePromise))
138 return p.then(function(results) {
139 return summarizeDeploymentList({items: results});
140 });
141}