diff --git a/cli/cli.ts b/cli/cli.ts index 037327080..31c8cff85 100644 --- a/cli/cli.ts +++ b/cli/cli.ts @@ -1,5 +1,4 @@ import * as program from 'commander' -import * as chalk from 'chalk' import * as path from 'path' import * as fs from 'fs' import { createCARootCommand } from './commands/create-ca-root' @@ -19,6 +18,7 @@ import { flashCommand } from './commands/flash' import { ioTHubDPSInfo } from './iot/ioTHubDPSInfo' import { creds } from './creds' import { functionsSettingsCommand } from './commands/functions-settings' +import { error, help } from './logging' const version = JSON.parse( fs.readFileSync(path.join(process.cwd(), 'package.json'), 'utf-8'), @@ -78,6 +78,8 @@ const main = async () => { createDeviceCertCommand({ certsDir, resourceGroup, + iotDpsClient: getIotDpsClient, + dpsName, }), reactConfigCommand({ websiteClient: getWebsiteClient, @@ -95,26 +97,21 @@ const main = async () => { ] let ran = false - commands.forEach(({ command, action, help, options }) => { + commands.forEach(({ command, action, help: h, options }) => { const cmd = program.command(command) cmd .action(async (...args) => { try { ran = true await action(...args) - } catch (error) { - console.error( - chalk.red.inverse(' ERROR '), - chalk.red(`${command} failed!`), - ) - console.error(chalk.red.inverse(' ERROR '), chalk.red(error)) + } catch (e) { + error(`${command} failed!`) + error(e) process.exit(1) } }) .on('--help', () => { - console.log('') - console.log(chalk.yellow(help)) - console.log('') + help(h) }) if (options) { options.forEach(({ flags, description, defaultValue }) => @@ -127,12 +124,12 @@ const main = async () => { program.version(version) if (!ran) { - program.outputHelp(chalk.yellow) + program.outputHelp() throw new Error('No command selected!') } } main().catch((err) => { - console.error(chalk.red(err)) + error(err) process.exit(1) }) diff --git a/cli/commands/create-ca-intermediate.ts b/cli/commands/create-ca-intermediate.ts index 56811d535..30974fc53 100644 --- a/cli/commands/create-ca-intermediate.ts +++ b/cli/commands/create-ca-intermediate.ts @@ -1,10 +1,9 @@ -import * as chalk from 'chalk' import { CommandDefinition } from './CommandDefinition' import { generateCAIntermediate } from '../iot/generateCAIntermediate' import { ProvisioningServiceClient } from 'azure-iot-provisioning-service' import { add as addToIntermediateRegistry } from '../iot/intermediateRegistry' import { v4 } from 'uuid' -import { log, debug } from '../logging' +import { log, debug, setting, next, newline } from '../logging' export const createCAIntermediateCommand = ({ certsDir: certsDirPromise, @@ -25,7 +24,7 @@ export const createCAIntermediateCommand = ({ log, debug, }) - console.log(chalk.magenta(`CA intermediate certificate generated.`)) + debug(`CA intermediate certificate generated.`) await addToIntermediateRegistry({ certsDir, id }) @@ -71,18 +70,16 @@ export const createCAIntermediateCommand = ({ lastUpdatedDateTimeUtc: undefined as any, }) - console.log( - chalk.magenta( - `Created enrollment group for CA intermediate certificiate`, - ), - chalk.yellow(enrollmentGroupId), + setting( + `Created enrollment group for CA intermediate certificiate`, + enrollmentGroupId, ) - console.log() + newline() - console.log( - chalk.green('You can now generate device certificates using'), - chalk.blueBright('node cli create-device-cert'), + next( + 'You can now generate device certificates using', + 'node cli create-device-cert', ) }, help: diff --git a/cli/commands/create-ca-root.ts b/cli/commands/create-ca-root.ts index e6a71ba85..6e1ab8f6d 100644 --- a/cli/commands/create-ca-root.ts +++ b/cli/commands/create-ca-root.ts @@ -1,10 +1,9 @@ -import * as chalk from 'chalk' import { CommandDefinition } from './CommandDefinition' import { IotDpsClient } from '@azure/arm-deviceprovisioningservices' import { generateProofOfPosession } from '../iot/generateProofOfPosession' import { v4 } from 'uuid' import { generateCARoot } from '../iot/generateCARoot' -import { log, debug } from '../logging' +import { log, debug, success, setting, newline, next } from '../logging' import { certificateName as cn } from '../iot/certificateName' export const createCARootCommand = ({ @@ -30,7 +29,7 @@ export const createCARootCommand = ({ log, debug, }) - console.log(chalk.magenta(`CA root certificate generated.`)) + success(`CA root certificate generated.`) // Register root CA certificate on DPS @@ -45,10 +44,8 @@ export const createCARootCommand = ({ }, ) - console.log( - chalk.magenta(`CA root registered with DPS`), - chalk.yellow(dpsName), - ) + success(`CA root registered with DPS`) + setting('DPS name', dpsName) // Create verification cert @@ -77,16 +74,14 @@ export const createCARootCommand = ({ verificationCode: properties.verificationCode, }) - console.log( - chalk.magenta(`Generated verification certificate for verification code`), - chalk.yellow(properties.verificationCode), - ) + success(`Generated verification certificate for verification code`) + setting('Verification Code', properties.verificationCode) - console.log() + newline() - console.log( - chalk.green('You can now verify the proof of posession using'), - chalk.blueBright('node cli proof-ca-root-possession'), + next( + 'You can now verify the proof of posession using', + 'node cli proof-ca-root-possession', ) }, help: diff --git a/cli/commands/create-device-cert.ts b/cli/commands/create-device-cert.ts index 2aeea0524..f28857c24 100644 --- a/cli/commands/create-device-cert.ts +++ b/cli/commands/create-device-cert.ts @@ -1,17 +1,22 @@ -import * as chalk from 'chalk' import { CommandDefinition } from './CommandDefinition' import { randomWords } from '@nordicsemiconductor/random-words' import { generateDeviceCertificate } from '../iot/generateDeviceCertificate' -import { log, debug } from '../logging' +import { log, debug, success, newline, next } from '../logging' import { list as listIntermediateCerts } from '../iot/intermediateRegistry' import { deviceFileLocations } from '../iot/deviceFileLocations' +import { setting, heading } from '../logging' +import { IotDpsClient } from '@azure/arm-deviceprovisioningservices' export const createDeviceCertCommand = ({ certsDir: certsDirPromise, resourceGroup, + iotDpsClient, + dpsName, }: { certsDir: () => Promise + iotDpsClient: () => Promise resourceGroup: string + dpsName: string }): CommandDefinition => ({ command: 'create-device-cert', options: [ @@ -41,10 +46,7 @@ export const createDeviceCertCommand = ({ intermediateCertId = intermediateCerts[0] } - console.log( - chalk.magenta('Intermediate certificate:'), - chalk.yellow(intermediateCertId), - ) + setting('Intermediate certificate', intermediateCertId) await generateDeviceCertificate({ deviceId: id, @@ -54,26 +56,30 @@ export const createDeviceCertCommand = ({ intermediateCertId, resourceGroup, }) - console.log( - chalk.magenta(`Certificate for device ${chalk.yellow(id)} generated.`), - ) + success(`Certificate for device generated.`) + setting('Certificate ID', id) const certJSON = deviceFileLocations({ certsDir, deviceId: id }).json - console.log() - console.log( - chalk.green('You can now connect to the broker using'), - chalk.greenBright( - 'npm exec -- @nordicsemiconductor/asset-tracker-cloud-device-simulator-azure', - ), - chalk.blueBright(certJSON), + newline() + next( + 'You can now connect to the broker using', + `npm exec -- @nordicsemiconductor/asset-tracker-cloud-device-simulator-azure ${certJSON}`, + ) + + newline() + next( + 'You can now flash the credentials to your device', + `node cli flash ${id}`, ) - console.log() - console.log( - chalk.green('You can now flash the credentials to your device'), - chalk.greenBright(`node cli flash`), - chalk.blueBright(id), + const { properties } = await (await iotDpsClient()).iotDpsResource.get( + dpsName, + resourceGroup, ) + + heading('Firmware configuration') + setting('DPS hostname', properties.serviceOperationsHostName as string), + setting('ID scope', properties.idScope as string) }, help: 'Generate a device certificate and register a device in the registry.', }) diff --git a/cli/commands/flash.ts b/cli/commands/flash.ts index d6b0135ee..67aa13f6a 100644 --- a/cli/commands/flash.ts +++ b/cli/commands/flash.ts @@ -10,9 +10,9 @@ import { } from '@nordicsemiconductor/firmware-ci-device-helpers' import { deviceFileLocations } from '../iot/deviceFileLocations' import { Octokit } from '@octokit/rest' -import * as chalk from 'chalk' import * as https from 'https' import { v4 } from 'uuid' +import { progress, success } from '../logging' const defaultPort = '/dev/ttyACM0' const defaultSecTag = 42 @@ -62,7 +62,7 @@ const getLatestFirmware = async ({ if (hexfile === undefined) throw new Error(`Failed to detect latest release.`) const downloadTarget = path.join(os.tmpdir(), `${v4()}.hex`) - console.log(chalk.magenta(`Downloading`), chalk.blue(hexfile.name)) + progress(`Downloading`, hexfile.name) await new Promise((resolve) => { const file = fs.createWriteStream(downloadTarget) @@ -115,10 +115,7 @@ export const flashCommand = ({ const hexfile = firmware ?? (await getLatestFirmware({ dk, nbiot, nodebug })) - console.log( - chalk.magenta(`Connecting to device`), - chalk.blue(port ?? defaultPort), - ) + progress(`Connecting to device`, port ?? defaultPort) const connection = await connect({ atHostHexfile: @@ -129,10 +126,7 @@ export const flashCommand = ({ progress: console.log, }) - console.log( - chalk.magenta(`Flashing credentials`), - chalk.blue(port ?? defaultPort), - ) + progress(`Flashing credentials`, port ?? defaultPort) const certs = deviceFileLocations({ certsDir: await certsDir(), @@ -150,7 +144,7 @@ export const flashCommand = ({ privateKey: fs.readFileSync(certs.privateKey, 'utf-8'), }) - console.log(chalk.magenta(`Flashing firmware`), chalk.blue(hexfile)) + progress(`Flashing firmware`, hexfile) await flash({ hexfile, @@ -158,7 +152,7 @@ export const flashCommand = ({ await connection.connection.end() - console.log(chalk.green(`Done`)) + success('Done') }, help: 'Flash credentials and latest firmware release to a device using JLink', }) diff --git a/cli/commands/proof-ca-possession.ts b/cli/commands/proof-ca-possession.ts index f183c6446..d58a23575 100644 --- a/cli/commands/proof-ca-possession.ts +++ b/cli/commands/proof-ca-possession.ts @@ -1,8 +1,8 @@ -import * as chalk from 'chalk' import { CommandDefinition } from './CommandDefinition' import { IotDpsClient } from '@azure/arm-deviceprovisioningservices' import { promises as fs } from 'fs' import { CARootFileLocations } from '../iot/caFileLocations' +import { newline, next, setting, success } from '../logging' export const proofCARootPossessionCommand = ({ certsDir, @@ -36,7 +36,7 @@ export const proofCARootPossessionCommand = ({ 'utf-8', ) - console.log(chalk.magenta('Certificate:'), chalk.yellow(certificateName)) + setting('Certificate', certificateName) await armDpsClient.dpsCertificate.verifyCertificate( certificateName, @@ -48,11 +48,11 @@ export const proofCARootPossessionCommand = ({ dpsName, ) - console.log(chalk.magenta('Verified root CA certificate.')) - console.log() - console.log( - chalk.green('You can now create a CA intermediate certificate using'), - chalk.blueBright('node cli create-ca-intermediate'), + success('Verified root CA certificate.') + newline() + next( + 'You can now create a CA intermediate certificate using', + 'node cli create-ca-intermediate', ) }, help: diff --git a/cli/creds.ts b/cli/creds.ts index 0058c465c..dcedd7048 100644 --- a/cli/creds.ts +++ b/cli/creds.ts @@ -1,6 +1,6 @@ -import * as chalk from 'chalk' import { AzureCliCredentials } from '@azure/ms-rest-nodeauth' import { resourceGroupName } from '../arm/resources' +import { setting } from './logging' export const creds = async (): Promise => { const creds = await AzureCliCredentials.create() @@ -9,11 +9,8 @@ export const creds = async (): Promise => { tokenInfo: { subscription }, } = creds - console.error(chalk.magenta('Subscription:'), chalk.yellow(subscription)) - console.error( - chalk.magenta('Resource Group:'), - chalk.yellow(resourceGroupName()), - ) + setting('Subscription', subscription) + setting('Resource Group', resourceGroupName()) return creds } diff --git a/cli/logging.ts b/cli/logging.ts index 92390eee3..b21377cfa 100644 --- a/cli/logging.ts +++ b/cli/logging.ts @@ -1,9 +1,45 @@ import * as chalk from 'chalk' -export const log = (...message: any[]) => { - console.log(...message.map((m) => chalk.magenta(m))) +export const log = (...message: any[]): void => { + console.error(...message.map((m) => chalk.magenta(m))) } -export const debug = (...message: any[]) => { - console.log(...message.map((m) => chalk.cyan(m))) +export const debug = (...message: any[]): void => { + console.error(...message.map((m) => chalk.cyan(m))) +} + +export const success = (...message: any[]): void => { + console.error(...message.map((m) => chalk.green(m))) +} + +export const setting = (property: string, value: string): void => { + console.error(chalk.magenta(`${property}:`), chalk.yellow(value)) +} + +export const next = (instructions: string, cmd: string): void => { + console.error(chalk.green(instructions), chalk.blueBright(cmd)) +} + +export const error = (message: string): void => { + console.error(chalk.red.inverse(' ERROR '), chalk.red(message)) +} + +export const help = (message: string): void => { + console.error('') + console.error(chalk.yellow(message)) + console.error('') +} + +export const progress = (label: string, info: string): void => { + console.error(chalk.magenta(label), chalk.blue(info)) +} + +export const newline = (): void => { + console.error() +} + +export const heading = (name: string): void => { + newline() + console.error(chalk.white.bold(`${name}:`)) + newline() }