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

feature(command): Added set command to CG #79

Open
wants to merge 1 commit into
base: alpha
Choose a base branch
from
Open
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
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@cloudgraph/cli",
"description": "Scan your cloud infrastructure data and query it with GraphQL",
"version": "0.21.4-alpha.1",
"version": "0.21.3",
"author": "AutoCloud",
"license": "MPL-2.0",
"publishConfig": {
Expand Down Expand Up @@ -126,6 +126,7 @@
"postpack": "rm -f oclif.manifest.json",
"posttest": "eslint . --ext .ts --config .eslintrc.json",
"prepack": "rm -rf lib && npx tsc -b --force && oclif manifest && oclif readme && yarn cpx 'src/scripts/*' lib/scripts",
"run:set": "cross-env NODE_ENV=development ./bin/dev set",
"run:init": "cross-env NODE_ENV=development ./bin/dev init",
"run:init:aws": "cross-env NODE_ENV=development ./bin/dev init aws",
"run:load": "cross-env NODE_ENV=development ./bin/dev load",
Expand Down
27 changes: 18 additions & 9 deletions src/commands/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,15 +156,18 @@ homebrew: 1. ${chalk.italic.green('brew update')} \n
await queryEngine.startServer(
this.getHost(await this.getConnectionSettings())
)
const queryEngineUrl = `http://localhost:${availablePort}/${await this.getQueryEngine()}`
this.logger.success(
`Serving query engine at ${chalk.underline.green(queryEngineUrl)}`
`Serving query engine at ${chalk.underline.green(
`http://localhost:${availablePort}`
)}`
)
try {
await openBrowser(queryEngineUrl)
await openBrowser(
`http://localhost:${availablePort}/${await this.getQueryEngine()}`
)
} catch (error) {
this.logger.warn(
`Could not open a browser tab with query engine, open manually at ${queryEngineUrl}`
`Could not open a browser tab with query engine, open manually at http://localhost:${availablePort}`
)
}
}
Expand Down Expand Up @@ -227,17 +230,23 @@ homebrew: 1. ${chalk.italic.green('brew update')} \n
return this.manager
}

async getProviderClient(
provider: string
): Promise<{ client: any; schemasMap?: SchemaMap; serviceKey?: string }> {
async getProviderClient(provider: string): Promise<{
client: any
schemasMap?: SchemaMap
serviceKey?: string
services?: SchemaMap
serviceProperties?: {
[key: string]: { field: string; defaultValue: any }[]
}
}> {
try {
const manager = await this.getPluginManager(PluginType.Provider)
if (this.providers[provider]) {
return this.providers[provider]
}
const {
default: Client,
enums: { schemasMap },
enums: { schemasMap, services, serviceProperties },
serviceKey,
} = (await manager.getPlugin(provider)) ?? {}
if (!Client || !(Client instanceof Function)) {
Expand All @@ -251,7 +260,7 @@ homebrew: 1. ${chalk.italic.green('brew update')} \n
provider: await this.buildProviderConfig(provider),
})
this.providers[provider] = { client, schemasMap, serviceKey }
return { client, schemasMap, serviceKey }
return { client, schemasMap, serviceKey, services, serviceProperties }
} catch (error: any) {
this.logger.error(error)
this.logger.warn(
Expand Down
120 changes: 120 additions & 0 deletions src/commands/set.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import fs from 'fs'
import path from 'path'
import chalk from 'chalk'
import { fileUtils } from '../utils'

import Command from './base'
import { CloudGraphConfig } from '../types'
import { getProviderQuestion } from '../utils/questions'
import { DEFAULT_CG_CONFIG } from '../utils/constants'

export default class SetField extends Command {
static description = 'Configure cloud provider service properties'

static examples = ['$ cg set', '$ cg set aws [Initialize AWS provider]']

static flags = {
...Command.flags,
}

static hidden = false

static strict = false

static args = Command.args

async getProvider(): Promise<string> {
const { provider } = await this.interface.prompt(getProviderQuestion)
this.logger.debug(provider)
return provider
}

/**
* Ensures that the configuration path exists and saves the CloudGraph json config file in it
*/
saveCloudGraphConfigFile(configResult: CloudGraphConfig): void {
const { configDir } = this.config
const previousConfig = this.getCGConfig()
const newConfig = configResult
if (previousConfig) {
for (const key of Object.keys(previousConfig)) {
if (!configResult[key]) {
newConfig[key] = previousConfig[key]
}
}
} else {
fileUtils.makeDirIfNotExists(configDir)
}
fs.writeFileSync(
path.join(configDir, '.cloud-graphrc.json'),
JSON.stringify(newConfig, null, 2)
)
}

async run(): Promise<void> {
const { configDir } = this.config
const { argv } = await this.parse(SetField)
const config = this.getCGConfig() ?? DEFAULT_CG_CONFIG

// First determine the provider if one has not been passed in args
// if no provider is passed, they can select from a list of offically supported providers
let allProviders: string[] = argv
if (allProviders.length === 0) {
allProviders = [await this.getProvider()]
}
const configResult: { [key: string]: Record<string, any> } = { ...config }
for (const provider of allProviders) {
/**
* First install and require the provider plugin
*/
const { services, serviceProperties } = await this.getProviderClient(
provider
)

if (!serviceProperties) {
this.logger.warn(
"Provider's Properties should be defined to configure services"
)
continue // eslint-disable-line no-continue
}

const { resources: resourcesAnswer } = await this.interface.prompt([
{
type: 'checkbox',
message: 'Select services to configure',
loop: false,
name: 'resources',
choices: Object.values(services as { [key: string]: string }).map(
(service: string) => ({
name: service,
})
),
},
])
const properties: { [field: string]: any } = {}
for (const resource of resourcesAnswer) {
const resourceProperties = serviceProperties[resource].map(
({ field, defaultValue }) => ({
type: 'input',
message: `set ${resource} ${field}`,
name: field,
default: defaultValue ?? undefined,
})
)
properties[resource] = await this.interface.prompt(resourceProperties)
}

configResult[provider] = {
...configResult[provider],
properties,
}
}

this.saveCloudGraphConfigFile(configResult)
this.logger.success(
`Your config has been successfully stored at ${chalk.italic.green(
path.join(configDir, '.cloud-graphrc.json')
)}`
)
}
}