├── src
├── assets
│ └── kubernetes.png
├── kObjects
│ ├── kObject.ts
│ ├── egressPolicy.ts
│ ├── volumeClaimTemplates.ts
│ ├── kReplicaSet.ts
│ ├── kDaemonSet.ts
│ ├── container.ts
│ ├── ingressPolicy.ts
│ ├── statefulContainer.ts
│ ├── kPod.ts
│ ├── kService.ts
│ ├── __index.ts
│ ├── kDeployment.ts
│ ├── kNetworkPolicy.ts
│ └── kStatefulSet.ts
├── components
│ ├── views
│ │ ├── NotLiveMessage.tsx
│ │ ├── NavBar.tsx
│ │ ├── NetworkPolicyLegend.tsx
│ │ ├── FetchLiveData.tsx
│ │ ├── SidebarClusterView.tsx
│ │ ├── PodInfoInNodeView.tsx
│ │ ├── Legend.tsx
│ │ ├── SidebarNodeView.tsx
│ │ ├── UploadView.tsx
│ │ ├── NetworkPolicyView.tsx
│ │ ├── NodeView.tsx
│ │ └── ClusterView.tsx
│ └── App.tsx
├── index.tsx
├── index.html
├── component_data
│ ├── findSelectorMatch.ts
│ └── kDataParser.ts
├── preload.js
├── main.js
└── scss
│ ├── styles.scss
│ └── GraphStyles.ts
├── teardown.js
├── decs.d.ts
├── jest.config.js
├── navigate_logs
└── readme.txt
├── .babelrc
├── __tests__
├── server.test.ts
├── FetchLiveData.test.tsx
├── SidebarClusterView.test.tsx
└── runCommand.test.ts
├── .github
└── workflows
│ └── regressionTest.yml
├── tsconfig.json
├── LICENSE
├── server
├── parseDeployment.ts
├── runCommand.js
├── kDeploymentLive.ts
├── parser.ts
├── GetLiveData
│ ├── parser.js
│ └── getKubernetesData.js
├── parsePods.ts
├── logAggregator.ts
├── server.ts
├── kPodLive.ts
└── databaseController.ts
├── webpack.config.js
├── .gitignore
├── README.md
└── package.json
/src/assets/kubernetes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oslabs-beta/navigate/HEAD/src/assets/kubernetes.png
--------------------------------------------------------------------------------
/src/kObjects/kObject.ts:
--------------------------------------------------------------------------------
1 | export interface kObject {
2 | label: string;
3 | getLabel: () => string;
4 | }
--------------------------------------------------------------------------------
/teardown.js:
--------------------------------------------------------------------------------
1 | module.exports = async function () {
2 | console.log('tests finished!');
3 | process.exit(0);
4 | }
--------------------------------------------------------------------------------
/decs.d.ts:
--------------------------------------------------------------------------------
1 | declare module 'cytoscape-dagre';
2 | declare module 'cytoscape-cola';
3 | declare module 'react-cytoscapejs';
4 | declare module '*.scss';
5 | declare module 'react-router-dom';
--------------------------------------------------------------------------------
/jest.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */
2 | module.exports = {
3 | preset: 'ts-jest',
4 | testEnvironment: 'jsdom',
5 | globalTeardown: './teardown.js',
6 | };
--------------------------------------------------------------------------------
/navigate_logs/readme.txt:
--------------------------------------------------------------------------------
1 | This file is necessary as we currently have dependencies on a nonempty "navigate_logs" folder in the root directory of the project.
2 | We're working to have this not be the case soon :)
--------------------------------------------------------------------------------
/src/components/views/NotLiveMessage.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 |
3 | export default function NotLiveMessage() {
4 | return (
5 |
6 |
Kubernetes engine not running, no nodes detected.
7 |
8 | )
9 | }
10 |
--------------------------------------------------------------------------------
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "@babel/preset-env",
4 | "@babel/preset-react",
5 | "@babel/preset-typescript"
6 | ],
7 | "plugins": [
8 | [
9 | "@babel/plugin-transform-runtime",
10 | {
11 | "regenerator": true
12 | }
13 | ]
14 | ]
15 | }
--------------------------------------------------------------------------------
/src/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {render} from 'react-dom';
3 | import App from './components/App';
4 | const styles = require('./scss/styles.scss');
5 | import UploadView from './components/views/UploadView';
6 | render (
7 | ,
8 | document.getElementById('root')
9 | );
--------------------------------------------------------------------------------
/src/kObjects/egressPolicy.ts:
--------------------------------------------------------------------------------
1 | export default class EgressPolicy{
2 | ipBlock: string;
3 | protocol: string;
4 | port: number;
5 |
6 | constructor(ipBlock: string, protocol: string, port: number){
7 | this.ipBlock = ipBlock;
8 | this.protocol = protocol;
9 | this.port = port;
10 | }
11 |
12 | }
--------------------------------------------------------------------------------
/src/kObjects/volumeClaimTemplates.ts:
--------------------------------------------------------------------------------
1 | export default class volumeClaimTemplates {
2 | name: string;
3 | accessMode: string[];
4 | storage: any;
5 | constructor(name: string, accessMode: string[], storage: any){
6 | this.name = name;
7 | this.accessMode = accessMode;
8 | this.storage = storage;
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Navigate
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/kObjects/kReplicaSet.ts:
--------------------------------------------------------------------------------
1 | import type {kObject} from './kObject';
2 |
3 | export class kReplicaSet implements kObject {
4 | label: string;
5 | replicas: number;
6 |
7 | constructor(label: string, replicas: number)
8 | {
9 | this.label = label;
10 | this.replicas = replicas;
11 | }
12 | getLabel(): string
13 | {
14 | return this.label;
15 | }
16 | }
--------------------------------------------------------------------------------
/src/kObjects/kDaemonSet.ts:
--------------------------------------------------------------------------------
1 | import type {kObject} from './kObject';
2 |
3 | export class kDaemonSet implements kObject {
4 | label: string;
5 | namespace: string;
6 | kind: string;
7 |
8 | constructor(label: string, namespace: string, kind: string)
9 | {
10 | this.label = label;
11 | this.namespace= namespace;
12 | this.kind = kind;
13 | }
14 | getLabel(): string
15 | {
16 | return this.label;
17 | }
18 | }
--------------------------------------------------------------------------------
/src/component_data/findSelectorMatch.ts:
--------------------------------------------------------------------------------
1 | import { anyObject } from "../kObjects/__index";
2 | export const findSelectorMatch = (obj1: anyObject, obj2: anyObject) => {
3 | let namespaceCount: number = 0;
4 | for(let key in obj2.selectors){
5 | if(obj2.selectors[key] === obj1.selectors[key]){
6 | if(obj1.selectors[key] !== obj2.namespace)
7 | return true;
8 | else namespaceCount++;
9 | if(namespaceCount > 1) return true;
10 | }
11 | else continue;
12 | }
13 | return false;
14 | }
--------------------------------------------------------------------------------
/src/components/views/NavBar.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Link } from 'react-router-dom';
3 |
4 | export default function NavBar() {
5 | return (
6 |
7 |
15 |
16 | )
17 | }
18 |
--------------------------------------------------------------------------------
/src/kObjects/container.ts:
--------------------------------------------------------------------------------
1 | export default class Container {
2 | name: string;
3 | image: string;
4 | env: env;
5 | containerPort: number;
6 |
7 |
8 | constructor(name: string, image: string, env: env, port: number){
9 | this.name = name;
10 | this.image = image;
11 | this.env = env;
12 | this.containerPort = port;
13 | }
14 | }
15 |
16 | export class env {
17 | name: string;
18 | value: string;
19 |
20 | constructor(name: string, value: string){
21 | this.name = name;
22 | this.value = value;
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/__tests__/server.test.ts:
--------------------------------------------------------------------------------
1 | import {PORT} from '../server/server';
2 | import request from 'supertest';
3 |
4 | const server = `http://localhost:${PORT}`;
5 |
6 | describe("router unit tests", () => {
7 |
8 | describe("GET", () => {
9 | it("should return with a status code of 200", (done) => {
10 | request(server).get('/')
11 | .send()
12 | .expect(200)
13 | done();
14 | });
15 |
16 | it("returns an html file", (done) => {
17 | request(server).get('/')
18 | .expect('text/html; charset=UTF-8')
19 | done();
20 | })
21 | })
22 | });
--------------------------------------------------------------------------------
/src/components/views/NetworkPolicyLegend.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 |
3 | export default function NetworkPolicyLegend() {
4 | return (
5 |
6 |
7 |
8 | | Legend |
9 | | △ | External IP addresses |
10 | | ▭ | Pod |
11 | | ⇢ | Allowed Traffic |
12 | | ⇢ | Blocked Traffic |
13 |
14 |
15 |
16 | )
17 | }
--------------------------------------------------------------------------------
/.github/workflows/regressionTest.yml:
--------------------------------------------------------------------------------
1 | name: RegressionTest CI
2 | on:
3 | pull_request:
4 | types: [opened, reopened]
5 | branches:
6 | - 'develop'
7 | - 'main'
8 |
9 | jobs:
10 | run-tests:
11 | runs-on: ubuntu-latest
12 | strategy:
13 | matrix:
14 | node-version: [12.x, 14.x]
15 |
16 | steps:
17 | - uses: actions/checkout@v2
18 | - name: Use Node.js ${{ matrix.node-version }}
19 | uses: actions/setup-node@v1
20 | with:
21 | node-version: ${{ matrix.node-version }}
22 | - run: npm install
23 | - run: npm run test
24 |
--------------------------------------------------------------------------------
/src/kObjects/ingressPolicy.ts:
--------------------------------------------------------------------------------
1 | export default class IngressPolicy {
2 | ipBlock: string;
3 | except: string;
4 | namespaceSelectors: Array;
5 | podSelectors: Array;
6 | protocol: string;
7 | port: number;
8 |
9 | constructor(ipBlock: string, except: string, namespaceSelectors: Array, podSelectors: Array, protocol: string, port: number){
10 | this.ipBlock = ipBlock;
11 | this.except = except;
12 | this.namespaceSelectors = namespaceSelectors;
13 | this.podSelectors = podSelectors;
14 | this.protocol = protocol;
15 | this.port = port;
16 | }
17 | }
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "module": "commonjs",
5 | "lib": ["dom", "dom.iterable", "esnext"],
6 | "allowJs": true,
7 | "allowSyntheticDefaultImports": true,
8 | "skipLibCheck": true,
9 | "esModuleInterop": true,
10 | "strict": true,
11 | "forceConsistentCasingInFileNames": true,
12 | "moduleResolution": "node",
13 | "resolveJsonModule": true,
14 | "isolatedModules": true,
15 | "noEmit": true,
16 | "jsx": "react",
17 | "outDir": "build",
18 | "sourceMap": true,
19 | },
20 | "include": ["src", "decs.d.ts", "server/**/*"]
21 | }
--------------------------------------------------------------------------------
/src/kObjects/statefulContainer.ts:
--------------------------------------------------------------------------------
1 | export default class statefulContainer {
2 | name: string;
3 | image: string;
4 | containerPort: number;
5 | volumeMount: volumeMount;
6 |
7 | constructor(name: string, image: string, port: number, volumeMount:volumeMount){
8 | this.name = name;
9 | this.image = image;
10 | this.containerPort = port;
11 | this.volumeMount = volumeMount;
12 | }
13 | }
14 |
15 | export class volumeMount {
16 | mountPath: string;
17 | name: string;
18 |
19 | constructor(mountPath: string, name: string){
20 | this.mountPath = mountPath;
21 | this.name = name;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/__tests__/FetchLiveData.test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {render, fireEvent, waitFor, screen} from '@testing-library/react';
3 | import '@testing-library/jest-dom';
4 | import FetchLiveData from '../src/components/views/FetchLiveData';
5 | import {rest} from 'msw';
6 | import { setupServer } from 'msw/node';
7 |
8 | const server = setupServer(
9 | rest.get('http://localhost:3000/update', (req, res, ctx) => {
10 | return res(ctx.status(200));
11 | })
12 | );
13 |
14 | beforeAll(() => server.listen())
15 | afterEach(() => server.resetHandlers())
16 | afterAll(() => server.close())
17 |
18 | test('', async () => {
19 | render()
20 | expect(screen.getByRole('button')).toBeTruthy();
21 | });
--------------------------------------------------------------------------------
/src/components/views/FetchLiveData.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 |
3 | function FetchLiveData(props: any) {
4 |
5 | const reRunGetKubernetesData = () => {
6 | function requestUpdate() {
7 | fetch('http://localhost:3000/update')
8 | .then(response => console.log("Successful"))
9 | .catch(error => console.log('POST ERROR: ' + error));
10 | }
11 | requestUpdate();
12 | }
13 |
14 | return (
15 |
16 |
17 |
18 | )
19 | }
20 |
21 | export default FetchLiveData;
22 |
--------------------------------------------------------------------------------
/src/kObjects/kPod.ts:
--------------------------------------------------------------------------------
1 | import type {kObject} from './kObject';
2 |
3 | export default class kPod implements kObject {
4 | label: string;
5 | identifier: string;
6 | currentHealthState: HealthState;
7 | ownerLabel: ownerRef;
8 |
9 | constructor(label: string, identifier: string){
10 | this.label = label;
11 | this.identifier = identifier;
12 | this.currentHealthState = HealthState.Healthy;
13 | }
14 |
15 | getLabel = (): string => {
16 | return this.label;
17 | }
18 |
19 | setOwner = (reference: ownerRef): void => {
20 | this.ownerLabel = reference;
21 | }
22 | }
23 |
24 | export class ownerRef {
25 | name: string;
26 | UID: string;
27 | }
28 |
29 | export enum HealthState {
30 | Healthy,
31 | Unhealty
32 | }
--------------------------------------------------------------------------------
/src/kObjects/kService.ts:
--------------------------------------------------------------------------------
1 | import type {kObject} from './kObject'
2 | export default class kService implements kObject {
3 | namespace: string;
4 | label: string;
5 | kind: string;
6 | port: number;
7 | targetPort: number;
8 | selectors: object;
9 | type: serviceType;
10 |
11 | constructor(namespace: string,label: string, kind:string, port: number, targetPort: number, selectors: object, type = serviceType.ClusterIP){
12 | this.namespace = namespace;
13 | this.label = label;
14 | this.kind = kind;
15 | this.port = port;
16 | this.targetPort = targetPort;
17 | this.selectors = selectors;
18 | this.type = type;
19 | }
20 | getLabel(): string
21 | {
22 | return this.label;
23 | }
24 | }
25 |
26 | export enum serviceType {
27 | ClusterIP, LoadBalancer, NodePort
28 | }
--------------------------------------------------------------------------------
/src/kObjects/__index.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * utility script for kObjects
3 | */
4 |
5 | //allow for one line importing
6 | export {default as container} from './container';
7 | export {env} from './container';
8 | export {default as kPod} from './kPod';
9 | export {kDaemonSet} from './kDaemonSet';
10 | export {default as kDeployment} from './kDeployment';
11 | export {kReplicaSet} from './kReplicaSet';
12 | export {kStatefulSet} from './kStatefulSet';
13 | export {default as statefulContainer, volumeMount} from './statefulContainer';
14 | export {default as volumeClaimTemplates} from './volumeClaimTemplates';
15 | export {default as kService} from './kService';
16 | export {default as NetworkPolicy} from './kNetworkPolicy'
17 |
18 | //allow for object param declarations
19 | export interface anyObject {
20 | [key: string]: any
21 | }
22 |
--------------------------------------------------------------------------------
/src/kObjects/kDeployment.ts:
--------------------------------------------------------------------------------
1 | import container from './container';
2 | import type {kObject} from './kObject';
3 |
4 | export default class kDeployment implements kObject {
5 | namespace: string;
6 | kind: string
7 | label: string;
8 | podLabel: string;
9 | replicas: number;
10 | container: container;
11 | selectors: object;
12 |
13 |
14 | constructor(namespace = "", kind: string, label: string, podLabel: string, replicas: number, container: container, selectors: object)
15 | {
16 | this.namespace = namespace;
17 | this.kind = kind;
18 | this.label = label;
19 | this.podLabel = podLabel;
20 | this.replicas = replicas;
21 | this.container = container;
22 | this.selectors = selectors;
23 | }
24 |
25 | getLabel(): string
26 | {
27 | return this.label;
28 | }
29 | }
--------------------------------------------------------------------------------
/src/preload.js:
--------------------------------------------------------------------------------
1 | var exec = require('child_process').exec, child;
2 | const fs = require('fs');
3 | const path = require('path');
4 |
5 | // All of the Node.js APIs are available in the preload process.
6 | // It has the same sandbox as a Chrome extension.
7 | window.addEventListener('DOMContentLoaded', () => {
8 | const serverFile = path.join(__dirname, '../server/server.ts')
9 |
10 | runCommand = async (cmd) => {
11 | console.log(process.env.SHELL);
12 | await exec(cmd, function (error, stdout, stderr) {
13 | if(process.env.NODE_ENV !== 'test')
14 | {
15 | console.log(stdout);
16 | if(stderr)
17 | console.log('stderr: ' + stderr);
18 | if (error !== null) {
19 | console.log('exec error: ' + error);
20 | }
21 | }
22 | });
23 |
24 | }
25 |
26 | runCommand(`npx ts-node ${serverFile}`)
27 |
28 | })
29 |
--------------------------------------------------------------------------------
/src/kObjects/kNetworkPolicy.ts:
--------------------------------------------------------------------------------
1 | import EgressPolicy from './egressPolicy';
2 | import IngressPolicy from './ingressPolicy';
3 | import type {kObject} from './kObject';
4 |
5 | export default class kNetworkPolicy implements kObject {
6 | namespace: string;
7 | kind: string
8 | label: string;
9 | podSelectors: object;
10 | policyTypes: Array;
11 | ingressPolicy: IngressPolicy;
12 | egressPolicy: EgressPolicy;
13 |
14 | constructor(namespace: string, kind: string, label: string, podSelectors: object, policyTypes: Array, ingressPolicy: IngressPolicy, egressPolicy: EgressPolicy)
15 | {
16 | this.namespace = namespace;
17 | this.kind = kind;
18 | this.label = label;
19 | this.podSelectors = podSelectors;
20 | this.policyTypes = policyTypes;
21 | this.ingressPolicy = ingressPolicy;
22 | this.egressPolicy= egressPolicy;
23 | }
24 |
25 | getLabel(): string
26 | {
27 | return this.label;
28 | }
29 | }
--------------------------------------------------------------------------------
/src/kObjects/kStatefulSet.ts:
--------------------------------------------------------------------------------
1 | import type {kObject} from './kObject';
2 | import statefulContainer from './statefulContainer'
3 | import volumeClaimTemplates from './volumeClaimTemplates';
4 | export class kStatefulSet implements kObject {
5 | namespace: string;
6 | kind :string;
7 | label: string;
8 | replicas: number;
9 | serviceName: string;
10 | container: statefulContainer;
11 | volumeClaimTemplates: volumeClaimTemplates;
12 | constructor(namespace= "",kind: string, label: string, replicas: number, serviceName: string, container: statefulContainer, volumeClaimTemplates: volumeClaimTemplates)
13 | {
14 | this.namespace = namespace;
15 | this.kind = kind;
16 | this.label = label;
17 | this.replicas = replicas;
18 | this.serviceName = serviceName;
19 | this.container = container;
20 | this.volumeClaimTemplates = volumeClaimTemplates;
21 | }
22 | getLabel(): string
23 | {
24 | return this.label;
25 | }
26 | }
--------------------------------------------------------------------------------
/__tests__/SidebarClusterView.test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {render, fireEvent, waitFor, screen} from '@testing-library/react';
3 | import '@testing-library/jest-dom';
4 | import SidebarClusterView from '../src/components/views/SidebarClusterView';
5 |
6 | test('', async () => {
7 | //rerender original component with props to be called when needed
8 | const { rerender } = render();
9 |
10 | render()
11 | //should have a button called "refresh" due to FetchLiveData component
12 | expect(screen.getAllByText('refresh')).toBeTruthy();
13 | //it should not display any events if props are empty
14 | expect(screen.getByText('Kubernetes engine not running, no nodes detected.'));
15 | //should display events if props have something
16 | rerender;
17 | expect(screen.getByText('Kind:'));
18 | });
19 |
20 | const mockProps = [
21 | {
22 | deploymentStatus: [
23 | {
24 | Kind: "NetworkPolicy",
25 | Name: "app-v1",
26 | Event: "Mocked",
27 | Time: "now"
28 | }
29 | ]
30 | }
31 | ];
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Brian Kang
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/server/parseDeployment.ts:
--------------------------------------------------------------------------------
1 | import kDeploymentLive from './kDeploymentLive';
2 |
3 | export default function parseDeploymentInformation(jsonObjs: any): Array{
4 | const podsInfoObjs: Array = [];
5 | for(let i = 0; i < jsonObjs.length; i++){
6 | const ele = jsonObjs[i][0];
7 | if(ele.kind === 'Deployment'){
8 | const infoObject = new kDeploymentLive(
9 | ele.metadata.namespace,
10 | ele.kind,
11 | ele.metadata.name,
12 | ele.metadata.creationTimestamp,
13 | ele.metadata.resourceVersion,
14 | ele.metadata.uid,
15 | ele.spec.strategy.type,
16 | ele.spec.strategy.rollingUpdate.maxSurge,
17 | ele.spec.strategy.rollingUpdate.maxUnavailable,
18 | ele.spec.template.spec.containers[0].env,
19 | ele.spec.template.spec.dnsPolicy,
20 | ele.spec.template.spec.restartPolicy,
21 | ele.spec.template.spec.schedulerName,
22 | )
23 | podsInfoObjs.push(infoObject)
24 | }
25 | }
26 | return podsInfoObjs;
27 | }
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const HtmlWebpackPlugin = require('html-webpack-plugin');
3 |
4 | module.exports = {
5 | mode: process.env.NODE_ENV,
6 | entry: './src/index.tsx',
7 | module: {
8 | rules: [
9 | {
10 | test: /\.(ts|js)x?$/,
11 | loader: 'babel-loader',
12 | exclude: /node_modules/,
13 | options:{
14 | presets: ['@babel/preset-env', '@babel/preset-react', "@babel/preset-typescript"]
15 | }
16 | },
17 | {
18 | test: /\.s[ac]ss$/,
19 | use: ['style-loader', 'css-loader', 'sass-loader']
20 | }
21 | ],
22 | },
23 | //this is what enables users to leave off the extension when importing
24 | resolve: {
25 | extensions: ['.tsx', '.ts', '.js', '.jsx']
26 | },
27 | performance: {
28 | hints: false,
29 | maxEntrypointSize: 512000,
30 | maxAssetSize: 512000
31 | },
32 | // publicPath is causing 404 errors if incorrect
33 | output: {
34 | filename: 'bundle.js',
35 | path: path.resolve(__dirname, 'build'),
36 | publicPath: 'auto'
37 | },
38 | devServer: {
39 | proxy: {'/api': 'http://localhost:3000'},
40 | },
41 | plugins: [
42 | new HtmlWebpackPlugin({
43 | template: path.join(__dirname, "src", "index.html"),
44 | }),
45 | ],
46 | }
--------------------------------------------------------------------------------
/__tests__/runCommand.test.ts:
--------------------------------------------------------------------------------
1 | import exportObj from '../server/runCommand';
2 | import * as kubernetesData from '../server/GetLiveData/getKubernetesData';
3 | import fs from 'fs';
4 | import * as path from 'path';
5 |
6 | describe("run sh scripts from node", () => {
7 |
8 | afterEach(() => {
9 | jest.restoreAllMocks();
10 | });
11 |
12 | exportObj.runCommand(`${exportObj.command} -n mafia &> ./navigate_logs/${exportObj.fileName}`);
13 | xit("should create a txt file", (done) => {
14 | expect(fs.promises.access(path.join(__dirname, '../navigate_logs/')+exportObj.fileName, fs.constants.R_OK | fs.constants.W_OK)).toBeTruthy();
15 | done();
16 | });
17 |
18 | xit("should get an array of pod names", (done) => {
19 | const parseSpy = jest.mock(path.join(__dirname, '../server/GetLiveData/getKubernetesData'));
20 | let readFileCallback: Function;
21 | jest.spyOn(fs, 'readFile').mockImplementation((path: fs.PathOrFileDescriptor, callback) => {
22 | readFileCallback = callback;
23 | });
24 | kubernetesData.parsePodNames();
25 | const someError = new Error('read file failed');
26 | expect(() => readFileCallback(someError, null)).toThrowError();
27 | expect(fs.readFile).toBeCalledWith(path.join(__dirname, `../navigate_logs/${exportObj.fileName}`), 'utf-8', expect.any(Function));
28 | done();
29 | });
30 | });
--------------------------------------------------------------------------------
/server/runCommand.js:
--------------------------------------------------------------------------------
1 | var exec = require('child_process').exec, child;
2 | const fs = require('fs');
3 | const path = require('path');
4 |
5 | const exportObj = {};
6 |
7 | //default command
8 | exportObj.command = `kubectl get pods -o=jsonpath='{.items[*].metadata.name}'`;
9 | exportObj.fileName = 'podNames.txt'
10 |
11 | exportObj.runCommand = (cmd) => {
12 | exec(cmd, function (error, stdout, stderr) {
13 | if(process.env.NODE_ENV !== 'test')
14 | {
15 | console.log(stdout);
16 | if(stderr)
17 | console.log('stderr: ' + stderr);
18 | if (error !== null) {
19 | console.log('exec error: ' + error);
20 | }
21 | }
22 | });
23 | }
24 |
25 | exportObj.runAndSave = (cmd, callback) => {
26 | var child_process = exec(cmd, function (err, stdout, stderr) {
27 | if (err && err.length > 1) {
28 | console.log("failed to execute");
29 | callback(error("InternalError", "No input or output devices found", 500));
30 | return;
31 | }else{
32 | if(stdout){
33 | callback(null,stdout);
34 | }
35 | if(stderr){
36 | callback(stderr);
37 | }
38 |
39 | }
40 | });
41 | return child_process;
42 | }
43 |
44 | module.exports = exportObj;
--------------------------------------------------------------------------------
/server/kDeploymentLive.ts:
--------------------------------------------------------------------------------
1 | import * as kObjects from '../src/kObjects/__index';
2 |
3 | export default class kDeploymentLive {
4 | namespace: string;
5 | kind: string
6 | name: string;
7 |
8 | created: string;
9 | resourceVersion: string;
10 | uid: string;
11 | strategyType: string;
12 | rollingUpdateMaxSurge: string | number;
13 | rollingUpdateMaxUnavailable: string | number;
14 | env: Array;
15 | dnsPolicy: string;
16 | restartPolicy: string;
17 | schedulerName: string;
18 |
19 | constructor(namespace = "", kind: string, name: string, created: string, resourceVersion: string,uid: string,
20 | strategyType: string, rollingUpdateMaxSurge: string | number, rollingUpdateMaxUnavailable: string | number, env: Array, dnsPolicy: string,
21 | restartPolicy: string, schedulerName: string){
22 | this.namespace = namespace;
23 | this.kind = kind;
24 | this.name = name;
25 |
26 | this.created = created;
27 | this.resourceVersion = resourceVersion;
28 | this.uid = uid;
29 | this.strategyType = strategyType;
30 | this.rollingUpdateMaxSurge = rollingUpdateMaxSurge;
31 | this.rollingUpdateMaxUnavailable = rollingUpdateMaxUnavailable;
32 | this.env = env;
33 | this.dnsPolicy = dnsPolicy;
34 | this.restartPolicy = restartPolicy;
35 | this.schedulerName = schedulerName;
36 | }
37 | }
--------------------------------------------------------------------------------
/server/parser.ts:
--------------------------------------------------------------------------------
1 | import * as fs from 'fs';
2 | import * as YAML from 'js-yaml';
3 | import * as path from 'path';
4 |
5 | let data: object[];
6 |
7 | function getFiles(fileType: RegExp, root: string): Array