From e9848034f7a799560f5bfd8d0f045bb4bc019e41 Mon Sep 17 00:00:00 2001 From: Marco Franceschi Date: Wed, 20 Apr 2022 11:43:27 -0400 Subject: [PATCH] feat: Set configurable limit for s3 list objects --- package.json | 3 +- src/commands/base.ts | 27 ++++++---- src/commands/set.ts | 120 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 140 insertions(+), 10 deletions(-) create mode 100644 src/commands/set.ts diff --git a/package.json b/package.json index 3c9ffca..a89f32d 100644 --- a/package.json +++ b/package.json @@ -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": { @@ -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", diff --git a/src/commands/base.ts b/src/commands/base.ts index 7157554..22088ef 100644 --- a/src/commands/base.ts +++ b/src/commands/base.ts @@ -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}` ) } } @@ -227,9 +230,15 @@ 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]) { @@ -237,7 +246,7 @@ homebrew: 1. ${chalk.italic.green('brew update')} \n } const { default: Client, - enums: { schemasMap }, + enums: { schemasMap, services, serviceProperties }, serviceKey, } = (await manager.getPlugin(provider)) ?? {} if (!Client || !(Client instanceof Function)) { @@ -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( diff --git a/src/commands/set.ts b/src/commands/set.ts new file mode 100644 index 0000000..b794713 --- /dev/null +++ b/src/commands/set.ts @@ -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 { + 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 { + 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 } = { ...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') + )}` + ) + } +}