blob: f3c4f97688271221c10b4ba39995fade8034d909 [file] [log] [blame]
Jack Lucas2832ba22018-04-20 13:22:05 +00001/*
2Copyright(c) 2018 AT&T Intellectual Property. All rights reserved.
Grzegorz-Lis5d467662020-08-17 12:51:33 +02003Copyright(c) 2020 Nokia Intellectual Property. All rights reserved.
Jack Lucas2832ba22018-04-20 13:22:05 +00004
5Licensed under the Apache License, Version 2.0 (the "License");
6you may not use this file except in compliance with the License.
7
8You may obtain a copy of the License at
9
10 http://www.apache.org/licenses/LICENSE-2.0
11
12Unless required by applicable law or agreed to in writing,
13software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
14CONDITIONS OF ANY KIND, either express or implied.
15See the License for the specific language governing permissions and limitations under the License.
16*/
17
18/*
19 * Query Kubernetes for status of deployments and extract readiness information
20 */
21
22const fs = require('fs');
Jack Lucase60d88b2018-12-12 16:48:41 -050023const https = require('https');
Jack Lucas2832ba22018-04-20 13:22:05 +000024
25const K8S_CREDS = '/var/run/secrets/kubernetes.io/serviceaccount';
Jack Lucase60d88b2018-12-12 16:48:41 -050026const K8S_HOST = 'kubernetes.default.svc.cluster.local'; // Full name to match cert for TLS
Grzegorz-Lis5d467662020-08-17 12:51:33 +020027const K8S_PATH = 'apis/apps/v1/namespaces/';
Jack Lucas2832ba22018-04-20 13:22:05 +000028
Jack Lucase60d88b2018-12-12 16:48:41 -050029const MAX_DEPS = 1000; // Maximum number of k8s deployments to return from a query to k8s
30
Jack Lucas2832ba22018-04-20 13:22:05 +000031//Get token and CA cert
32const ca = fs.readFileSync(K8S_CREDS + '/ca.crt');
33const token = fs.readFileSync(K8S_CREDS + '/token');
34
35const summarizeDeploymentList = function(list) {
Jack Lucas1d746682018-12-13 17:24:29 -050036 // list is a DeploymentList object returned by k8s
37 // Individual deployments are in the array 'items'
38
39 let ret =
40 {
41 type: "summary",
42 count: 0,
43 ready: 0,
44 items: []
45 };
46
47 // Extract readiness information
48 for (let deployment of list.items) {
49 ret.items.push(
50 {
51 name: deployment.metadata.name,
52 ready: deployment.status.readyReplicas || 0,
53 unavailable: deployment.status.unavailableReplicas || 0
54 }
55 );
56 ret.count ++;
57 ret.ready = ret.ready + (deployment.status.readyReplicas || 0);
58 }
59
60 return ret;
Jack Lucas2832ba22018-04-20 13:22:05 +000061};
62
Jack Lucas2832ba22018-04-20 13:22:05 +000063const queryKubernetes = function(path, callback) {
Jack Lucas1d746682018-12-13 17:24:29 -050064 // Make GET request to Kubernetes API
65 const options = {
66 host: K8S_HOST,
67 path: "/" + path,
68 ca : ca,
69 headers: {
70 Authorization: 'bearer ' + token
71 }
72 };
73 console.log ("request url: " + options.host + options.path);
74 const req = https.get(options, function(resp) {
75 let rawBody = "";
76 resp.on("data", function(data) {
77 rawBody += data;
78 });
79 resp.on("error", function (error) {
80 console.error("error: " + error);
81 callback(error, null, null)
82 });
83 resp.on("end", function() {
84 console.log ("status: " + resp.statusCode ? resp.statusCode: "NONE")
85 callback(null, resp, JSON.parse(rawBody));
86 });
87 });
88 req.end();
Jack Lucas2832ba22018-04-20 13:22:05 +000089};
90
Jack Lucase6d18572018-05-09 22:44:31 +000091const getStatusSinglePromise = function (item) {
Jack Lucas1d746682018-12-13 17:24:29 -050092 // Expect item to be of the form {namespace: "namespace", deployment: "deployment_name"}
93 return new Promise(function(resolve, reject){
94 const path = K8S_PATH + item.namespace + '/deployments/' + item.deployment;
95 queryKubernetes(path, function(error, res, body){
96 if (error) {
97 reject(error);
98 }
99 else if (res.statusCode === 404) {
100 // Treat absent deployment as if it's an unhealthy deployment
101 resolve ({
102 metadata: {name: item.deployment},
103 status: {unavailableReplicas: 1}
104 });
105 }
106 else if (res.statusCode != 200) {
107 reject(body);
108 }
109 else {
110 resolve(body);
111 }
112 });
113 });
Jack Lucase6d18572018-05-09 22:44:31 +0000114}
Jack Lucase6d18572018-05-09 22:44:31 +0000115
116exports.getStatusListPromise = function (list) {
Jack Lucas1d746682018-12-13 17:24:29 -0500117 // List is of the form [{namespace: "namespace", deployment: "deployment_name"}, ... ]
118 const p = Promise.all(list.map(getStatusSinglePromise))
119 return p.then(function(results) {
120 return summarizeDeploymentList({items: results});
121 });
Jack Lucase60d88b2018-12-12 16:48:41 -0500122}
123
Jack Lucasef3183f2020-06-12 11:44:49 -0400124exports.getLabeledDeploymentsPromise = function (namespace, label) {
125 // Return list of the form [{namespace: "namespace", deployment: "deployment_name"}].
Jack Lucas1d746682018-12-13 17:24:29 -0500126 // List contains all k8s deployments in the specified namespace that were deployed
Jack Lucasef3183f2020-06-12 11:44:49 -0400127 // with the specified 'label'. (The check is for the presence of the label--its
128 // values is not important.) In DCAE, this is used to find deployments created
Jack Lucas1d746682018-12-13 17:24:29 -0500129 // by Cloudify, based on Cloudify's use of a "marker" label on each k8s deployment that
130 // the k8s plugin created.
Jack Lucasef3183f2020-06-12 11:44:49 -0400131 // If 'label' is unspecified or has zero length, returns an empty list.
Jack Lucase60d88b2018-12-12 16:48:41 -0500132
Jack Lucas1d746682018-12-13 17:24:29 -0500133 return new Promise(function(resolve, reject) {
Jack Lucasef3183f2020-06-12 11:44:49 -0400134 if (!label || label.length < 1) {
135 resolve([]);
136 }
137 else {
138 const path = K8S_PATH + namespace + '/deployments?labelSelector=' + label + '&limit=' + MAX_DEPS
139 queryKubernetes(path, function(error, res, body){
140 if (error) {
141 reject(error);
142 }
143 else if (res.statusCode !== 200) {
144 reject(body);
145 }
146 else {
147 resolve(body.items.map(function(i) {return {namespace : namespace, deployment: i.metadata.name};}));
148 }
149 });
150 }
Jack Lucas1d746682018-12-13 17:24:29 -0500151 });
Jack Lucase60d88b2018-12-12 16:48:41 -0500152};