Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
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