Skip to content

Commit d13ed93

Browse files
committed
Fixed unauthorized bug
Signed-off-by: Maia Iyer <[email protected]>
1 parent e34cd4d commit d13ed93

File tree

2 files changed

+47
-33
lines changed

2 files changed

+47
-33
lines changed

exporter/src/server.ts

+45-33
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
import express from 'express';
22
import { Gauge, register } from 'prom-client';
33
import http from 'http'
4-
import { AllAppwrappers } from './appwrapper-utils';
54
import * as k8s from '@kubernetes/client-node';
6-
import * as fs from 'fs';
75

86
const app = express();
97
const PORT = 9101;
@@ -12,19 +10,13 @@ const PORT = 9101;
1210
const isRunningInKubernetes = process.env.KUBERNETES_SERVICE_HOST;
1311
const kc = new k8s.KubeConfig();
1412
if (isRunningInKubernetes) {
15-
const token = fs.readFileSync('/var/run/secrets/kubernetes.io/serviceaccount/token', 'utf8');
1613
kc.loadFromCluster();
14+
console.log(`Connected to k8s api via cluster credentials`);
1715
} else {
1816
kc.loadFromDefault();
17+
console.log(`Connected to k8s api via local kubeconfig`);
1918
}
2019
const k8sApi = kc.makeApiClient(k8s.CustomObjectsApi);
21-
console.log(`connected to kubernetes... testing appwrapper call`);
22-
// test k8s
23-
const list = k8sApi.listClusterCustomObject('workload.codeflare.dev', 'v1beta1', 'appwrappers');
24-
list.then((res) => {
25-
console.log(`test resuld: ${res}`)
26-
})
27-
console.log(`finished kubernetes connection test`);
2820

2921
interface AppwrapperObject extends k8s.KubernetesObject {
3022
metadata: {
@@ -71,7 +63,7 @@ function getAppwrapperStatus(status: string) {
7163
}
7264

7365
// initialize count metrics
74-
console.log(`initializing prometheus metrics`);
66+
console.log(`Initializing Prometheus metrics`);
7567
appwrapperCountMetric.labels("Running").set(0);
7668
appwrapperCountMetric.labels("Pending").set(0);
7769
appwrapperCountMetric.labels("Failed").set(0);
@@ -80,56 +72,76 @@ appwrapperCountMetric.labels("Other").set(0);
8072
/** END initialize prometheus metrics **/
8173

8274
/** initialize informer **/
83-
console.log(`initializing informer`)
75+
// need to store previous state for each appwrapper so that upon change we can update labels
76+
// the key is `<appwrapper_namespace>,<appwrapper_name>` as a string
77+
// this assumes commas are not included in namespaces names or appwrapper names
78+
const previousAppwrapperStates: Map<string, string> = new Map();
79+
80+
console.log(`Initializing informer`)
8481
async function listFn(): Promise<{ response: http.IncomingMessage; body: k8s.KubernetesListObject<AppwrapperObject>; }>{
8582
const list = await k8sApi.listClusterCustomObject('workload.codeflare.dev', 'v1beta1', 'appwrappers');
8683
let k8sBody = list.body as k8s.KubernetesListObject<AppwrapperObject>;
8784
let value = {response: list.response, body: k8sBody};
8885
let returnedPromise: Promise<{ response: http.IncomingMessage; body: k8s.KubernetesListObject<AppwrapperObject>; }> = new Promise((resolve, reject) => {
8986
resolve(value);
9087
})
91-
console.log(`listFN called: `)
92-
console.log(list.response)
93-
console.log(k8sBody)
94-
console.log(value)
95-
console.log(returnedPromise);
96-
console.log(`listFN called: ${returnedPromise}, ${value}, ${list.response}, ${k8sBody}`);
9788
return returnedPromise
9889
}
9990

10091
const informer = k8s.makeInformer(kc, '/apis/workload.codeflare.dev/v1beta1/appwrappers', listFn);
101-
informer.on('change', (obj) => {
102-
//console.log(`hello ch!`);
103-
//console.log(`changed: ${obj.metadata.name}`);
92+
informer.on('add', (obj) => {
93+
let appwrapperName: string = obj.metadata.name;
94+
let appwrapperNamespace = obj.metadata.namespace;
95+
let appwrapperStatus = obj.status.state;
96+
console.log(`add received: ${appwrapperName}, ${appwrapperNamespace}, ${appwrapperStatus}`)
97+
appwrapperStatusMetric.labels(appwrapperName, appwrapperNamespace).set(getAppwrapperStatus(appwrapperStatus))
98+
appwrapperCountMetric.labels(appwrapperStatus).inc(1);
99+
// set previous state
100+
previousAppwrapperStates.set(`${appwrapperNamespace},${appwrapperName}`, appwrapperStatus);
101+
});
102+
informer.on('update', (obj) => {
104103
let appwrapperName: string = obj.metadata.name;
105104
let appwrapperNamespace = obj.metadata.namespace;
106105
let appwrapperStatus = obj.status.state;
106+
console.log(`update received: ${appwrapperName}, ${appwrapperNamespace}, ${appwrapperStatus}`);
107+
console.log(informer.get(appwrapperName, appwrapperNamespace))
107108
appwrapperStatusMetric.labels(appwrapperName, appwrapperNamespace).set(getAppwrapperStatus(appwrapperStatus))
109+
// decrement count of previous state
110+
let previousState = previousAppwrapperStates.get(`${appwrapperNamespace},${appwrapperName}`);
111+
if (!previousState) {
112+
console.log(`error: update received but no previous state recorded`)
113+
return;
114+
}
115+
appwrapperCountMetric.labels(previousState).dec(1);
116+
appwrapperCountMetric.labels(appwrapperStatus).inc(1);
117+
// set previous state
118+
previousAppwrapperStates.set(`${appwrapperNamespace},${appwrapperName}`, appwrapperStatus);
108119
});
109120
informer.on('delete', (obj) => {
110-
//console.log(`hello de!`);
111-
//console.log(`deled: ${obj.metadata.name}`);
112121
let appwrapperName: string = obj.metadata.name;
113122
let appwrapperNamespace = obj.metadata.namespace;
114-
//let metricName = `appwrapper_status{appwrapper_name="${appwrapperName}",appwrapper_namespace="${appwrapperNamespace}"}`;
115-
//metricName = `appwrapper_status{appwrapper_name="0001-aw-generic-deployment-3-5",appwrapper_namespace="test1"}`;
116-
//console.log(metricName)
117-
//register.removeSingleMetric(metricName);
123+
let appwrapperStatus = obj.status.state;
124+
// Prometheus does not support removing a single tagged series
125+
// Instead, we set to NaN to effectively end the series, as shown in Prometheus charts
126+
// NOTE: Consequently, when querying Prometheus, if one appwrapper is added and deleted with same
127+
// name and namespace multiple times, a query may get information for both
118128
appwrapperStatusMetric.labels(appwrapperName, appwrapperNamespace).set(NaN)
119-
129+
appwrapperCountMetric.labels(appwrapperStatus).dec(1);
130+
// set previous state
131+
previousAppwrapperStates.delete(`${appwrapperNamespace},${appwrapperName}`);
120132
});
121133
informer.on('error', (err) => {
122-
console.log(`hello e!`);
123-
console.log(`errord: ${err}`);
134+
console.log(`Informer errored: ${err}`);
135+
console.log(`NOTE: if the above error says "forbidden" check you or the relevant deployment has permission to "watch" appwrappers`);
136+
124137
});
125138
informer.on('connect', (err) => {
126-
console.log(`hello c!`);
127-
console.log(`connected: ${err}`);
139+
console.log(`Informer connected!`);
128140
});
129141

130142
// start informer
131143
informer.start();
132-
console.log(`informer started...`);
144+
console.log(`Informer started watching...`);
133145

134146
/** end initialize informer **/
135147

manifests/base/exporter.yaml

+2
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ rules:
9191
- verbs:
9292
- get
9393
- list
94+
- watch
9495
apiGroups:
9596
- workload.codeflare.dev
9697
resources:
@@ -105,6 +106,7 @@ rules:
105106
- verbs:
106107
- get
107108
- list
109+
- watch
108110
apiGroups:
109111
- workload.codeflare.dev
110112
resources:

0 commit comments

Comments
 (0)