Skip to content

Commit

Permalink
fix: allow using an existing cluster and do not require kind (#643)
Browse files Browse the repository at this point in the history
Signed-off-by: Lenin Mehedy <lenin.mehedy@swirldslabs.com>
  • Loading branch information
leninmehedy authored Jan 10, 2024
1 parent ba7426f commit 6b53618
Show file tree
Hide file tree
Showing 23 changed files with 315 additions and 121 deletions.
12 changes: 4 additions & 8 deletions .github/workflows/zxc-fsnetman-tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -127,15 +127,11 @@ jobs:
run: |
npm i
npm link
fsnetman init -d ../charts
fsnetman init -d ../charts # use the charts directory for all subsequent commands
fsnetman cluster create
fsnetman cluster setup -d ../charts \
--cert-manager \
--cert-manager-crds
fsnetman chart install -d ../charts \
--enable-tls \
--self-signed \
--enable-hedera-explorer-tls
fsnetman cluster setup --cert-manager --cert-manager-crds
fsnetman chart install --enable-tls --self-signed --enable-hedera-explorer-tls
npm run test-e2e
- name: Output logs
id: nodejs-test-e2e-logs
Expand Down
19 changes: 12 additions & 7 deletions fullstack-network-manager/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ Full Stack Network Manager (fsnetman) is a CLI tool to manage and deploy a Heder
@hashgraph:registry=https://npm.pkg.github.com
```

* Get your [Github access token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-personal-access-token-classic) and setup an environment variable GITHUB\_TOKEN.
* Get
your [Github access token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-personal-access-token-classic)
and setup an environment variable GITHUB\_TOKEN.

* Run `npm install -g @hashgraph/fullstack-network-manager`

Expand All @@ -36,9 +38,12 @@ Select a command

## Develop

* In order to support ES6 modules with `jest`, set an env variable `export NODE_OPTIONS=--experimental-vm-modules >> ~/.zshrc`
* If you are using Intellij and would like to use debugger tools, you will need to enable `--experimental-vm-modules` for `Jest`.
* `Run->Edit Configurations->Edit Configuration Templates->Jest` and then set `--experimental-vm-modules` in `Node Options`.
* In order to support ES6 modules with `jest`, set an env
variable `export NODE_OPTIONS=--experimental-vm-modules >> ~/.zshrc`
* If you are using Intellij and would like to use debugger tools, you will need to
enable `--experimental-vm-modules` for `Jest`.
* `Run->Edit Configurations->Edit Configuration Templates->Jest` and then set `--experimental-vm-modules`
in `Node Options`.
* Run `npm i` to install the required packages
* Run `npm link` to install `fsnetman` as the CLI
* Note: you need to do it once. If `fsnetman` already exists in your path, you will need to remove it first.
Expand All @@ -54,9 +59,9 @@ Select a command
* In order to run E2E test, we need to set up cluster and install the chart.

```
fsnetman init -d ../charts # use the charts directory
fsnetman init -d ../charts # use the charts directory for all subsequent commands
fsnetman cluster create
fsnetman cluster setup
fsnetman chart install
fsnetman cluster setup --cert-manager --cert-manager-crds
fsnetman chart install --enable-tls --self-signed --enable-hedera-explorer-tls
npm run test-e2e
```
2 changes: 1 addition & 1 deletion 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 @@ -39,6 +39,7 @@
"listr2": "^7.0.2",
"uuid": "^9.0.1",
"winston": "^3.11.0",
"yaml": "^2.3.4",
"yargs": "^17.7.2"
},
"devDependencies": {
Expand Down
4 changes: 2 additions & 2 deletions fullstack-network-manager/src/commands/base.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,20 @@ export class BaseCommand extends ShellRunner {

constructor (opts) {
if (!opts || !opts.logger) throw new Error('An instance of core/Logger is required')
if (!opts || !opts.kind) throw new Error('An instance of core/Kind is required')
if (!opts || !opts.helm) throw new Error('An instance of core/Helm is required')
if (!opts || !opts.kubectl) throw new Error('An instance of core/Kubectl is required')
if (!opts || !opts.chartManager) throw new Error('An instance of core/ChartManager is required')
if (!opts || !opts.configManager) throw new Error('An instance of core/ConfigManager is required')
if (!opts || !opts.depManager) throw new Error('An instance of core/DependencyManager is required')
if (!opts || !opts.clusterManager) throw new Error('An instance of core/ClusterManager is required')

super(opts.logger)

this.kind = opts.kind
this.helm = opts.helm
this.kubectl = opts.kubectl
this.chartManager = opts.chartManager
this.configManager = opts.configManager
this.depManager = opts.depManager
this.clusterManager = opts.clusterManager
}
}
31 changes: 15 additions & 16 deletions fullstack-network-manager/src/commands/chart.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,21 @@ import { constants } from '../core/index.mjs'
import * as prompts from './prompts.mjs'

export class ChartCommand extends BaseCommand {
getTlsValueArguments(enableTls, tlsClusterIssuerName, tlsClusterIssuerNamespace, enableHederaExplorerTls) {

const gatewayPrefix = 'gatewayApi.gateway'
let valuesArg = ` --set ${gatewayPrefix}.tlsEnabled=${enableTls}`
valuesArg += ` --set ${gatewayPrefix}.tlsClusterIssuerName=${tlsClusterIssuerName}`
valuesArg += ` --set ${gatewayPrefix}.tlsClusterIssuerNamespace=${tlsClusterIssuerNamespace}`

const listenerPrefix = `${gatewayPrefix}.listeners`
valuesArg += ` --set ${listenerPrefix}.grpcs.tlsEnabled=${enableTls}`
valuesArg += ` --set ${listenerPrefix}.grpcWeb.tlsEnabled=${enableTls}`

if (enableTls || enableHederaExplorerTls) {
valuesArg += ` --set ${listenerPrefix}.hederaExplorer.tlsEnabled=true`
}
getTlsValueArguments (enableTls, tlsClusterIssuerName, tlsClusterIssuerNamespace, enableHederaExplorerTls) {
const gatewayPrefix = 'gatewayApi.gateway'
let valuesArg = ` --set ${gatewayPrefix}.tlsEnabled=${enableTls}`
valuesArg += ` --set ${gatewayPrefix}.tlsClusterIssuerName=${tlsClusterIssuerName}`
valuesArg += ` --set ${gatewayPrefix}.tlsClusterIssuerNamespace=${tlsClusterIssuerNamespace}`

const listenerPrefix = `${gatewayPrefix}.listeners`
valuesArg += ` --set ${listenerPrefix}.grpcs.tlsEnabled=${enableTls}`
valuesArg += ` --set ${listenerPrefix}.grpcWeb.tlsEnabled=${enableTls}`

if (enableTls || enableHederaExplorerTls) {
valuesArg += ` --set ${listenerPrefix}.hederaExplorer.tlsEnabled=true`
}

return valuesArg
return valuesArg
}

prepareValuesFiles (valuesFile) {
Expand All @@ -39,7 +38,7 @@ export class ChartCommand extends BaseCommand {
}

prepareValuesArg (chartDir, valuesFile, deployMirrorNode, deployHederaExplorer, enableTls, tlsClusterIssuerName,
tlsClusterIssuerNamespace, enableHederaExplorerTls, acmeClusterIssuer, selfSignedClusterIssuer) {
tlsClusterIssuerNamespace, enableHederaExplorerTls, acmeClusterIssuer, selfSignedClusterIssuer) {
let valuesArg = ''
if (chartDir) {
valuesArg = `-f ${chartDir}/fullstack-deployment/values.yaml`
Expand Down
68 changes: 34 additions & 34 deletions fullstack-network-manager/src/commands/cluster.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Listr } from 'listr2'
import { FullstackTestingError } from '../core/errors.mjs'
import * as core from '../core/index.mjs'
import * as flags from './flags.mjs'
import { BaseCommand } from './base.mjs'
import chalk from 'chalk'
Expand All @@ -11,22 +10,8 @@ import * as prompts from './prompts.mjs'
* Define the core functionalities of 'cluster' command
*/
export class ClusterCommand extends BaseCommand {
/**
* List available clusters
* @returns {Promise<string[]>}
*/
async getClusters () {
try {
return await this.kind.getClusters('-q')
} catch (e) {
this.logger.showUserError(e)
}

return []
}

async showClusterList () {
this.logger.showList('Clusters', await this.getClusters())
this.logger.showList('Clusters', await this.clusterManager.getClusters())
return true
}

Expand All @@ -52,8 +37,7 @@ export class ClusterCommand extends BaseCommand {
async getClusterInfo (argv) {
try {
const clusterName = argv.clusterName
const cmd = `kubectl cluster-info --context kind-${clusterName}`
const output = await this.run(cmd)
const output = await this.clusterManager.getClusterInfo(clusterName)

this.logger.showUser(chalk.green(`\nCluster information (${clusterName})\n---------------------------------------`))
output.forEach(line => this.logger.showUser(line))
Expand Down Expand Up @@ -114,7 +98,7 @@ export class ClusterCommand extends BaseCommand {
const cachedConfig = await self.configManager.setupConfig(argv)

// get existing choices
ctx.clusters = await self.kind.getClusters('-q')
ctx.clusters = await self.clusterManager.getClusters()

// extract config values
const clusterName = self.configManager.flagValue(cachedConfig, flags.clusterName)
Expand All @@ -130,13 +114,9 @@ export class ClusterCommand extends BaseCommand {
title: 'Create cluster',
task: async (ctx, _) => {
const clusterName = ctx.config.clusterName
ctx.clusters = await self.getClusters()
ctx.clusters = await self.clusterManager.getClusters()
if (!ctx.clusters.includes(clusterName)) {
await self.kind.createCluster(
`-n ${clusterName}`,
`--config ${core.constants.RESOURCES_DIR}/dev-cluster.yaml`
)

await self.clusterManager.createCluster(clusterName)
await self.kubectl.get('--raw=\'/healthz?verbose\'')
}
}
Expand All @@ -155,7 +135,7 @@ export class ClusterCommand extends BaseCommand {
// display info
ctx.namespaces = await self.getNameSpaces()
ctx.kubeContexts = await self.kubectl.config('get-contexts --no-headers | awk \'{print $2 " [" $NF "]"}\'')
ctx.clusters = await self.getClusters()
ctx.clusters = await self.clusterManager.getClusters()
self.logger.showList('Namespaces', await ctx.namespaces)
self.logger.showList('Clusters', await ctx.clusters)
self.logger.showList('Kubernetes Contexts', ctx.kubeContexts)
Expand Down Expand Up @@ -191,7 +171,7 @@ export class ClusterCommand extends BaseCommand {
const clusterName = self.configManager.flagValue(cachedConfig, flags.clusterName)

// get existing choices
ctx.clusters = await self.kind.getClusters('-q')
ctx.clusters = await self.clusterManager.getClusters()

ctx.config = {
clusterName: await prompts.promptSelectClusterNameArg(task, clusterName, ctx.clusters)
Expand All @@ -201,8 +181,8 @@ export class ClusterCommand extends BaseCommand {
{
title: 'Delete cluster',
task: async (ctx, _) => {
await this.kind.deleteCluster(ctx.config.clusterName)
self.logger.showList('Clusters', await self.getClusters())
await this.clusterManager.deleteCluster(ctx.config.clusterName)
self.logger.showList('Clusters', await self.clusterManager.getClusters())
},
skip: (ctx, _) => !ctx.clusters.includes(ctx.config.clusterName)
}
Expand Down Expand Up @@ -232,6 +212,11 @@ export class ClusterCommand extends BaseCommand {
{
title: 'Initialize',
task: async (ctx, task) => {
const kubeConfig = await self.clusterManager.getKubeConfig()
if (!kubeConfig['current-context']) {
throw new FullstackTestingError('kubectl context is not set, set context by running: kubectl config use-context <context-name>')
}

const cachedConfig = await self.configManager.setupConfig(argv)
self.logger.debug('Setup cached config', { cachedConfig, argv })

Expand All @@ -246,7 +231,7 @@ export class ClusterCommand extends BaseCommand {
const deployCertManagerCrds = self.configManager.flagValue(cachedConfig, flags.deployCertManagerCrds)

// get existing choices
const clusters = await self.kind.getClusters('-q')
const clusters = await self.clusterManager.getClusters()
const namespaces = await self.kubectl.getNamespace('--no-headers', '-o name')

// prompt if inputs are empty and set it in the context
Expand All @@ -258,11 +243,13 @@ export class ClusterCommand extends BaseCommand {
deployMinio: await prompts.promptDeployMinio(task, deployMinio),
deployEnvoyGateway: await prompts.promptDeployEnvoyGateway(task, deployEnvoyGateway),
deployCertManager: await prompts.promptDeployCertManager(task, deployCertManager),
deployCertManagerCrds: await prompts.promptDeployCertManagerCrds(task, deployCertManagerCrds),
deployCertManagerCrds: await prompts.promptDeployCertManagerCrds(task, deployCertManagerCrds)
}

self.logger.debug('Prepare ctx.config', { config: ctx.config, argv })

// set current context based on cluster and namespace
await self.clusterManager.setContext(ctx.config.clusterName, ctx.config.namespace)
ctx.isChartInstalled = await this.chartManager.isChartInstalled(ctx.config.namespace, constants.CHART_FST_SETUP_NAME)
}
},
Expand Down Expand Up @@ -290,7 +277,20 @@ export class ClusterCommand extends BaseCommand {
const chartPath = ctx.chartPath
const valuesArg = ctx.valuesArg

await self.chartManager.install(namespace, constants.CHART_FST_SETUP_NAME, chartPath, version, valuesArg)
try {
await self.chartManager.install(namespace, constants.CHART_FST_SETUP_NAME, chartPath, version, valuesArg)
} catch (e) {
// if error, uninstall the chart and rethrow the error
self.logger.debug(`Error on installing ${constants.CHART_FST_SETUP_NAME}. attempting to rollback by uninstalling the chart`, e)
try {
await self.chartManager.uninstall(namespace, constants.CHART_FST_SETUP_NAME)
} catch (ex) {
// ignore error during uninstall since we are doing the best-effort uninstall here
}

throw e
}

await self.showInstalledChartList(namespace)
},
skip: (ctx, _) => ctx.isChartInstalled
Expand Down Expand Up @@ -326,15 +326,15 @@ export class ClusterCommand extends BaseCommand {
const namespace = self.configManager.flagValue(cachedConfig, flags.namespace)

// get existing choices
const clusters = await self.kind.getClusters('-q')
const clusters = await self.clusterManager.getClusters()
const namespaces = await self.kubectl.getNamespace('--no-headers', '-o name')

ctx.config = {
clusterName: await prompts.promptSelectClusterNameArg(task, clusterName, clusters),
namespace: await prompts.promptSelectNamespaceArg(task, namespace, namespaces)
}

ctx.isChartInstalled = await this.chartManager.isChartInstalled(namespace, constants.CHART_FST_SETUP_NAME)
ctx.isChartInstalled = await this.chartManager.isChartInstalled(ctx.config.namespace, constants.CHART_FST_SETUP_NAME)
}
},
{
Expand Down
1 change: 0 additions & 1 deletion fullstack-network-manager/src/commands/init.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ export class InitCommand extends BaseCommand {
task: async (_, task) => {
const deps = [
core.constants.HELM,
core.constants.KIND,
core.constants.KUBECTL
]

Expand Down
Loading

0 comments on commit 6b53618

Please sign in to comment.