diff --git a/.circleci/config.yml b/.circleci/config.yml index ccb247d6..9b7cc39c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -262,6 +262,18 @@ jobs: key: v1-repo-{{ .Environment.CIRCLE_SHA1 }} - run: yarn run test:e2e:anonymous + test_e2e_instance: + name: E2E Tests + docker: + - image: circleci/node:latest + + working_directory: ~/repo/packages/cli + + steps: + - restore_cache: + key: v1-repo-{{ .Environment.CIRCLE_SHA1 }} + - run: yarn run test:e2e:instance + test_e2e_deploy: name: E2E Tests docker: @@ -373,6 +385,9 @@ workflows: - test_e2e_client: requires: - build + - test_e2e_instance: + requires: + - build - test_e2e_deploy: requires: - build @@ -398,6 +413,7 @@ workflows: - deploy_docs: requires: - build + - test_e2e_instance - test_e2e_validate - test_e2e_client - test_e2e_registry @@ -414,6 +430,7 @@ workflows: only: master - publish: requires: + - test_e2e_instance - test_e2e_validate - test_e2e_client - test_e2e_registry diff --git a/packages/cli/package.json b/packages/cli/package.json index a495d9b4..81c2b737 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -122,6 +122,7 @@ "test:e2e:registry": "yarn run test:e2e-single tests/e2e/registry.test-e2e.js", "test:e2e:hosting": "yarn run test:e2e-single tests/e2e/hosting.test-e2e.js", "test:e2e:socket": "yarn run test:e2e-single tests/e2e/socket.test-e2e.js", + "test:e2e:instance": "yarn run test:e2e-single tests/e2e/instance.test-e2e.js", "test:e2e-single": "mocha --require babel-register --timeout 100000 --slow 8000", "test:unit": "yarn run unit", "lint": "standard --fix --env mocha", diff --git a/packages/cli/src/cli-instance.js b/packages/cli/src/cli-instance.js new file mode 100644 index 00000000..3fe0a40f --- /dev/null +++ b/packages/cli/src/cli-instance.js @@ -0,0 +1,52 @@ +#!/usr/bin/env node +import program from './program' +import commands from './commands' +import session from './utils/session' +import context from './utils/context' +import validateCommands from './utils/validate-commands' +import { echo } from './utils/print-tools' + +const setup = async () => { + await context.session.load() + + program + .command('list') + .group('Instance') + .description('List all your instances') + .action(async (...options) => { + session.isAuthenticated() + echo() + new commands.InstanceList(context).run(options) + }) + + program + .command('create ') + .group('Instance') + .description('Create an Instance') + .action(async (...options) => { + session.isAuthenticated() + echo() + new commands.InstanceCreate(context).run(options) + }) + + program + .command('delete ') + .group('Instance') + .description('Create an Instance') + .action(async (...options) => { + session.isAuthenticated() + echo() + new commands.InstanceDelete(context).run(options) + }) + + program + .on('*', (commandsArr) => validateCommands(commandsArr)) + + if (!process.argv.slice(2).length) { + program.outputHelp() + } + + program.parse(process.argv) +} + +setup() diff --git a/packages/cli/src/cli.js b/packages/cli/src/cli.js index ef6c8103..aa4823d5 100755 --- a/packages/cli/src/cli.js +++ b/packages/cli/src/cli.js @@ -278,6 +278,10 @@ const setup = async () => { .command('component', 'Manage your Socket components') .on('*', (commandsArr) => validateCommands(commandsArr)) + program + .command('instance', 'Manage your instances') + .on('*', (commandsArr) => validateCommands(commandsArr)) + context.session.loadPlugins(program, context) program.parse(process.argv) diff --git a/packages/cli/src/commands/index.js b/packages/cli/src/commands/index.js index 77234efc..5e5d8630 100644 --- a/packages/cli/src/commands/index.js +++ b/packages/cli/src/commands/index.js @@ -24,6 +24,9 @@ import SocketCreate from './socket-create' import SocketUninstall from './socket-uninstall' import ComponentList from './component-list' import ComponentLink from './component-link' +import InstanceList from './instance-list' +import InstanceCreate from './instance-create' +import InstanceDelete from './instance-delete' export default { Attach, @@ -51,5 +54,8 @@ export default { SocketCreate, SocketUninstall, ComponentList, - ComponentLink + ComponentLink, + InstanceList, + InstanceCreate, + InstanceDelete } diff --git a/packages/cli/src/commands/instance-create.js b/packages/cli/src/commands/instance-create.js new file mode 100644 index 00000000..f9fad62f --- /dev/null +++ b/packages/cli/src/commands/instance-create.js @@ -0,0 +1,17 @@ +import logger from '../utils/debug' +import { createInstance } from './helpers/create-instance' + +const { debug } = logger('cmd-instance-create') + +export default class InstanceCreateCmd { + constructor (context) { + debug('InstanceCreateCmd.constructor') + this.context = context + this.session = context.session + this.Init = context.Init + } + + async run ([instanceName]) { + return createInstance(instanceName, this.session) + } +} diff --git a/packages/cli/src/commands/instance-delete.js b/packages/cli/src/commands/instance-delete.js new file mode 100644 index 00000000..b1fa0b8c --- /dev/null +++ b/packages/cli/src/commands/instance-delete.js @@ -0,0 +1,24 @@ +import logger from '../utils/debug' +import { echo, error } from '../utils/print-tools' + +const { debug } = logger('cmd-instance-create') + +export default class InstanceCreateCmd { + constructor (context) { + debug('InstanceCreateCmd.constructor') + this.context = context + this.session = context.session + this.Init = context.Init + } + + async run ([instanceName]) { + try { + await this.session.deleteInstance(instanceName) + echo() + echo(4)('Instance was deleted successfully!') + echo() + } catch (err) { + error('Deleting instance failed!') + } + } +} diff --git a/packages/cli/src/commands/instance-list.js b/packages/cli/src/commands/instance-list.js new file mode 100644 index 00000000..d4e69d5c --- /dev/null +++ b/packages/cli/src/commands/instance-list.js @@ -0,0 +1,29 @@ +import logger from '../utils/debug' +import { echo } from '../utils/print-tools' + +const { debug } = logger('cmd-instance-list') + +export default class InstanceCreateCmd { + constructor (context) { + debug('InstanceCreateCmd.constructor') + this.context = context + this.session = context.session + this.Init = context.Init + } + + async run ([cmd]) { + const instances = await this.session.getInstances() + if (instances.length < 1) { + echo() + echo(4)('You don\'t have any instances!') + echo() + } else { + echo() + echo(4)('Instances:') + instances.forEach(instance => { + echo(6)(`- ${instance.name}`) + }) + echo() + } + } +} diff --git a/packages/cli/src/utils/session.js b/packages/cli/src/utils/session.js index f40aaa3d..fe25c08c 100644 --- a/packages/cli/src/utils/session.js +++ b/packages/cli/src/utils/session.js @@ -105,6 +105,10 @@ export class Session { } catch (err) {} } + async deleteInstance (name) { + return this.connection.instance.delete(name) + } + async createInstance (name = genUniqueName()) { return this.connection.instance.create({ name }) } @@ -115,7 +119,7 @@ export class Session { } async getInstances () { - return this.connection.Instance.please().list() + return this.connection.instance.list() } async checkAuth () { diff --git a/packages/cli/tests/e2e/instance.test-e2e.js b/packages/cli/tests/e2e/instance.test-e2e.js new file mode 100644 index 00000000..b7f13cea --- /dev/null +++ b/packages/cli/tests/e2e/instance.test-e2e.js @@ -0,0 +1,75 @@ +/* global describe it */ +import path from 'path' +import { + nixt, + deleteInstance, + createInstance, + uniqueInstance +} from '@syncano/test-tools' + +const cliLocation = path.join(process.cwd(), 'lib/cli.js') + +describe('[E2E] CLI Instance', function () { + const testNixt = () => nixt() + .env('SYNCANO_AUTH_KEY', process.env.E2E_CLI_ACCOUNT_KEY) + + it.only('can create an instance', function (done) { + const testInstance = uniqueInstance() + + testNixt() + .before(() => createInstance(testInstance)) + .after(() => deleteInstance(testInstance)) + .run(`${cliLocation} instance create ${testInstance}`) + .stdout(/Instance already exist!/) + .end(done) + }) + + it('can\'t create an instance if already exist', function (done) { + const testInstance = uniqueInstance() + + testNixt() + .after(() => deleteInstance(testInstance)) + .run(`${cliLocation} instance create ${testInstance}`) + .stdout(/has been created/) + .end(done) + }) + + it('can list if there is no instances', function (done) { + testNixt() + .run(`${cliLocation} instance list`) + .stdout(/You don't have any instances!/) + .end(done) + }) + + it('can list instances', function (done) { + const testInstance1 = uniqueInstance() + const testInstance2 = uniqueInstance() + + testNixt() + .before(async () => { + await createInstance(testInstance1) + await createInstance(testInstance2) + }) + .after(async () => { + await deleteInstance(testInstance1) + await deleteInstance(testInstance2) + }) + .run(`${cliLocation} instance list`) + .stdout(/Instances:/) + .stdout(new RegExp(testInstance1)) + .stdout(new RegExp(testInstance2)) + .end(done) + }) + + it('can delete instance', function (done) { + const testInstance = uniqueInstance() + + testNixt() + .before(async () => { + await createInstance(testInstance) + }) + .run(`${cliLocation} instance delete ${testInstance}`) + .stdout(/Instance was deleted successfully!/) + .end(done) + }) +})