Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(cli): add traceId in CLI logs for easier debugging #449

Merged
merged 19 commits into from
Oct 26, 2023
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions fullstack-network-manager/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions fullstack-network-manager/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"esm": "^3.2.25",
"figlet": "^1.6.0",
"inquirer": "^9.2.11",
"uuid": "^9.0.1",
"winston": "^3.11.0",
"yargs": "^17.7.2"
},
Expand Down
7 changes: 7 additions & 0 deletions fullstack-network-manager/resources/dev-cluster.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
name: fst # this is overridden if CLUSTER_NAME env var is set. Check .env file
nodes:
- role: control-plane
labels:
fullstack-scheduling.io/role: network
57 changes: 20 additions & 37 deletions fullstack-network-manager/src/commands/base.mjs
Original file line number Diff line number Diff line change
@@ -1,57 +1,41 @@
"use strict"
import {exec} from "child_process";
import * as core from "../core/index.mjs"
import chalk from "chalk";

export const BaseCommand = class BaseCommand {
/**
* Check if 'kind' CLI program is installed or not
* @returns {Promise<boolean>}
*/
async checkKind() {
async checkDep(dep) {
try {
this.logger.debug("Checking if 'kind' is installed")
await this.runExec("kind --version")
this.logger.debug("OK: 'kind' is installed")
await this.runExec(dep)
} catch (e) {
this.logger.error("%s", e)
return false
}

return true
}
/**
* Check if 'kind' CLI program is installed or not
* @returns {Promise<boolean>}
*/
async checkKind() {
return this.checkDep(core.constants.KIND)
}

/**
* Check if 'helm' CLI program is installed or not
* @returns {Promise<boolean>}
*/
async checkHelm() {
try {
this.logger.debug("Checking if 'helm' is installed")
await this.runExec("helm version")
this.logger.debug("OK: 'helm' is installed")
} catch (e) {
this.logger.error("%s", e)
return false
}

return true
return this.checkDep(core.constants.HELM)
}

/**
* Check if 'kubectl' CLI program is installed or not
* @returns {Promise<boolean>}
*/
async checkKubectl() {
try {
this.logger.debug("Checking if 'kubectl' is installed")
await this.runExec("kubectl version")
this.logger.debug("OK: 'kubectl' is installed")
} catch (e) {
this.logger.error("%s", e)
return false
}

return true
return this.checkDep(core.constants.KUBECTL)
}

/**
Expand All @@ -60,29 +44,28 @@ export const BaseCommand = class BaseCommand {
* @returns {Promise<boolean>}
*/
async checkDependencies(deps = []) {
this.logger.info("Checking for required dependencies: %s", deps)
this.logger.debug("Checking for required dependencies: %s", deps)

for (let i = 0; i < deps.length; i++) {
let dep = deps[i]
this.logger.debug("Checking for dependency '%s'", dep)

let status = false
let check = this.checks.get(dep)
if (!check) {
this.logger.error("FAIL: Dependency '%s' is unknown", dep)
return false
if (check) {
status = await check()
}


let status = await check()
if (!status) {
this.logger.error("FAIL: Dependency '%s' is not found", dep)
this.logger.showUser(chalk.red(`FAIL: '${dep}' is not found`))
return false
}

this.logger.debug("PASS: Dependency '%s' is found", dep)
this.logger.showUser(chalk.green(`OK: '${dep}' is found`))
}

this.logger.info("PASS: All required dependencies are found: %s", deps)
this.logger.debug("All required dependencies are found: %s", deps)

return true
}

Expand Down
116 changes: 107 additions & 9 deletions fullstack-network-manager/src/commands/cluster.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as core from '../core/index.mjs'
import {BaseCommand} from "./base.mjs";
import chalk from "chalk";

/**
* Flags for 'cluster' command
Expand All @@ -15,22 +16,94 @@ const clusterNameFlag = {
* Define the core functionalities of 'cluster' command
*/
export const ClusterCommand = class extends BaseCommand {

/**
* List available clusters
* @returns {Promise<boolean>}
*/
async getClusters() {
let cmd = `kind get clusters`

try {
let output = await this.runExec(cmd)
this.logger.showUser("\nList of available clusters \n--------------------------\n%s", output)
return true
} catch (e) {
this.logger.error("%s", e)
this.logger.showUser(e.message)
}

return false
}

/**
* Get cluster-info for the given cluster name
* @param argv arguments containing cluster name
* @returns {Promise<boolean>}
*/
async getClusterInfo(argv) {
let cmd = `kubectl cluster-info --context kind-${argv.name}`

try {
let output = await this.runExec(cmd)
this.logger.showUser(output)
return true
} catch (e) {
this.logger.error("%s", e)
this.logger.showUser(e.message)
}

return false
}

/**
* Create a cluster
* @param argv
* @returns {Promise<void>}
* @returns {Promise<boolean>}
*/
async create(argv) {
this.logger.info("creating cluster '%s'", argv.name)
let cmd = `kind create cluster -n ${argv.name} --config ${core.constants.RESOURCES_DIR}/dev-cluster.yaml`

try {
this.logger.showUser(chalk.cyan('Creating cluster:'), chalk.yellow(`${argv.name}...`))
this.logger.debug(`Invoking '${cmd}'...`)
let output = await this.runExec(cmd)
this.logger.debug(output)
this.logger.showUser(chalk.green('Created cluster:'), chalk.yellow(argv.name))

// show all clusters and cluster-info
await this.getClusters()
await this.getClusterInfo(argv)

return true
} catch (e) {
this.logger.error("%s", e)
this.logger.showUser(e.message)
}

return false
}

/**
* Delete a cluster
* @param argv
* @returns {Promise<void>}
* @returns {Promise<boolean>}
*/
async delete(argv) {
this.logger.info("deleting cluster '%s'", argv.name, {name: argv.name})
let cmd = `kind delete cluster -n ${argv.name}`
try {
this.logger.debug(`Invoking '${cmd}'...`)
this.logger.showUser(chalk.cyan('Deleting cluster:'), chalk.yellow(`${argv.name}...`))
await this.runExec(cmd)
await this.getClusters()

return true
} catch (e) {
this.logger.error("%s", e.stack)
this.logger.showUser(e.message)
}

return false
}

/**
Expand All @@ -40,27 +113,52 @@ export const ClusterCommand = class extends BaseCommand {
static getCommandDefinition(clusterCmd) {
return {
command: 'cluster',
desc: 'Manager FST cluster',
desc: 'Manage FST cluster',
builder: yargs => {
return yargs
.command({
command: 'create',
desc: 'Create FST cluster',
desc: 'Create a cluster',
builder: yargs => {
yargs.option('name', clusterNameFlag)
},
handler: argv => {
clusterCmd.create(argv).then()
clusterCmd.create(argv).then(r => {
if (!r) process.exit(1)
})
}
})
.command({
command: 'delete',
desc: 'Delete FST cluster',
desc: 'Delete a cluster',
builder: yargs => {
yargs.option('name', clusterNameFlag)
},
handler: argv => {
clusterCmd.delete(argv).then(r => {
if (!r) process.exit(1)
})
}
})
.command({
command: 'list',
desc: 'List all clusters',
handler: argv => {
clusterCmd.getClusters().then(r => {
if (!r) process.exit(1)
})
}
})
.command({
command: 'info',
desc: 'Get cluster info',
builder: yargs => {
yargs.option('name', clusterNameFlag)
},
handler: argv => {
clusterCmd.delete(argv).then()
clusterCmd.getClusterInfo(argv).then(r => {
if (!r) process.exit(1)
})
}
})
.demand(1, 'Select a cluster command')
Expand Down
18 changes: 15 additions & 3 deletions fullstack-network-manager/src/commands/init.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {BaseCommand} from "./base.mjs";
import * as core from "../core/index.mjs"
import chalk from "chalk";

/**
* Defines the core functionalities of 'init' command
Expand All @@ -10,11 +11,20 @@ export const InitCommand = class extends BaseCommand {
* @returns {Promise<boolean>}
*/
async init() {
return await this.checkDependencies([
let deps = [
core.constants.HELM,
core.constants.KIND,
core.constants.KUBECTL,
])
]

let status = await this.checkDependencies(deps)
if (!status) {
return false
}

this.logger.showUser(chalk.green("OK: All required dependencies are found: %s"), chalk.yellow(deps))

return status
}

/**
Expand All @@ -27,7 +37,9 @@ export const InitCommand = class extends BaseCommand {
desc: "Perform dependency checks and initialize local environment",
builder: {},
handler: (argv) => {
initCmd.init(argv)
initCmd.init(argv).then(r => {
if (!r) process.exit(1)
})
}
}
}
Expand Down
8 changes: 8 additions & 0 deletions fullstack-network-manager/src/core/constants.mjs
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
import {dirname, normalize} from "path"
import {fileURLToPath} from "url"

// directory of this fle
const CUR_FILE_DIR = dirname(fileURLToPath(import.meta.url))
const USER = `${process.env.USER}`
export const constants = {
USER: `${USER}`,
CLUSTER_NAME: `fst-${USER}`,
HELM: 'helm',
KIND: 'kind',
KUBECTL: 'kubectl',
CWD: process.cwd(),
FST_HOME_DIR: process.env.HOME + "/.fsnetman",
RESOURCES_DIR: normalize(CUR_FILE_DIR + "/../../resources")
}
Loading