Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
  • 3 commits
  • 40 files changed
  • 0 comments
  • 1 contributor

Showing 40 changed files with 215 additions and 1,345 deletions. Show diff stats Hide diff stats

  1. +4 0 CHANGELOG.md
  2. +15 0 LICENSE
  3. +16 18 README.md
  4. +36 0 TODO.md
  5. +49 0 bin/cli.coffee
  6. +0 12 bin/nodester.js
  7. 0  commands/app/alias.coffee
  8. 0  commands/app/aliases.coffee
  9. 0  commands/app/info.coffee
  10. 0  commands/app/install.coffee
  11. 0  commands/app/link.coffee
  12. 0  commands/app/logs.coffee
  13. 0  commands/app/push.coffee
  14. 0  commands/app/restart.coffee
  15. 0  commands/app/start.coffee
  16. 0  commands/app/stop.coffee
  17. 0  commands/app/unalias.coffee
  18. 0  commands/app/uninstall.coffee
  19. 0  commands/app/upgrade.coffee
  20. +9 0 commands/apps.coffee
  21. 0  commands/create.coffee
  22. +18 0 commands/login.coffee
  23. +10 0 commands/logout.coffee
  24. +5 0 commands/status.coffee
  25. +7 0 config.json
  26. +0 8 examples/davster
  27. +0 35 examples/mynodester.js
  28. +16 0 lib/api.coffee
  29. +0 299 lib/app.js
  30. +0 106 lib/appdomain.js
  31. +0 40 lib/apps.js
  32. +0 137 lib/commands.js
  33. +6 0 lib/config.coffee
  34. +0 148 lib/config.js
  35. +0 36 lib/coupon.js
  36. +0 36 lib/log.js
  37. +0 187 lib/npm.js
  38. +0 22 lib/status.js
  39. +0 235 lib/user.js
  40. +24 26 package.json
4 CHANGELOG.md
Source Rendered
... ... @@ -0,0 +1,4 @@
  1 +0.0.1 / November 30, 2011
  2 +==================
  3 + * Start of the project
  4 +
15 LICENSE
... ... @@ -0,0 +1,15 @@
  1 +Copyright (C) 2011 Chris Matthieu (contact info: chris@nodester.com)
  2 +
  3 +This program is free software: you can redistribute it and/or modify
  4 +it under the terms of the GNU Affero General Public License as
  5 +published by the Free Software Foundation, Version 3, 19 November 2007.
  6 +
  7 +This program is distributed in the hope that it will be useful,
  8 +but WITHOUT ANY WARRANTY; without even the implied warranty of
  9 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10 +GNU Affero General Public License for more details.
  11 +
  12 +You should have received a copy of the GNU Affero General Public License
  13 +along with this program. If not, see http://www.gnu.org/licenses/agpl-3.0.html.
  14 +
  15 +http://www.gnu.org/licenses/why-affero-gpl.html
34 README.md
Source Rendered
... ... @@ -1,12 +1,11 @@
1   -# Nodester API CLI access
  1 +**nodester-cli is a wrapper for the Nodester REST API**
2 2
3   -This app is a little wrapper around the REST API for the [Nodester](http://nodester.com/) OS Node hosting platform.
4 3
5 4 ## Installation
  5 +
  6 +To install nodester-cli, use [npm](http://github.com/isaacs/npm):
6 7
7   -**If you are using `npm 1.0` you need to provide the `-g` flag to install this app globally.**
8   -
9   - npm install nodester-cli -g
  8 + $ npm install -g nodester-cli
10 9
11 10 ## Usage
12 11
@@ -14,23 +13,22 @@ This app is a little wrapper around the REST API for the [Nodester](http://nodes
14 13 nodester help app
15 14 nodester help user
16 15
17   - //All options
18 16 nodester help all
19 17
  18 +## LICENSE
20 19
21   -## Local installation
22   -
23   -If you have your own instance of [Nodester](http://nodester.com/) installed on your own server, the
24   -command line app is designed to work with that too. Currently it supports 3 environment variables
25   -to change a couple of default settings.
  20 +Copyright (C) 2011 Chris Matthieu (contact info: chris@nodester.com)
26 21
27   -Here is a simple example:
  22 +This program is free software: you can redistribute it and/or modify
  23 +it under the terms of the GNU Affero General Public License as
  24 +published by the Free Software Foundation, Version 3, 19 November 2007.
28 25
29   - #!/bin/bash
  26 +This program is distributed in the hope that it will be useful,
  27 +but WITHOUT ANY WARRANTY; without even the implied warranty of
  28 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  29 +GNU Affero General Public License for more details.
30 30
31   - export NODESTER_BRAND=davster;
32   - export NODESTER_APIHOST=auth.davglass.com;
33   - nodester "$@"
34   - export NODESTER_BRAND=;
35   - export NODESTER_APIHOST=;
  31 +You should have received a copy of the GNU Affero General Public License
  32 +along with this program. If not, see http://www.gnu.org/licenses/agpl-3.0.html.
36 33
  34 +http://www.gnu.org/licenses/why-affero-gpl.html
36 TODO.md
Source Rendered
... ... @@ -0,0 +1,36 @@
  1 +# TODO
  2 +
  3 +### Minor
  4 +
  5 + * Nothing here yet
  6 +
  7 +### Major
  8 +
  9 + * Remove all SSH key logic and replace with GitHub integration (maybe)
  10 + * WebForm for requesting coupons
  11 + * WebForm for requesting password resets
  12 + * WebForm for resetting password
  13 + * WebForm for resetting SSH key for git
  14 +
  15 + * The following commands:
  16 + nodester status - Displays service status
  17 + nodester login <username> <password> - Creates local user file if credentials are valid
  18 + nodester logout - Deletes local user file
  19 + nodester apps - Lists all user apps
  20 +
  21 + nodester create <appname> <(optional initial js file)> - Creates app on server and sets the initial js file. Creates app folder locally
  22 + nodester <appname> info - Displays app info.
  23 + nodester <appname> logs - Displays app logs
  24 + nodester <appname> start - Starts the app
  25 + nodester <appname> restart - Restarts the app
  26 + nodester <appname> stop - Stops the app
  27 + nodester <appname> delete - Deletes the app
  28 + nodester <appname> push - Pushes files to the app
  29 + nodester <appname> link <giturl> - Future pushes will pull data from <giturl>
  30 + nodester <appname> install <package names> - Installs packages for npm
  31 + nodester <appname> upgrade - Upgrades packages for npm
  32 + nodester <appname> uninstall <package names> - Uninstalls packages for npm. Package name "all" will clean npm registry
  33 + nodester <appname> alias <domain-name> - Set up external domain route for app
  34 + nodester <appname> unalias <domain-name> - Remove external domain route for app
  35 + nodester <appname> aliases - List all routes
  36 +
49 bin/cli.coffee
... ... @@ -0,0 +1,49 @@
  1 +#!/usr/bin/env coffee
  2 +require('coffee-script');
  3 +config = require '../lib/config'
  4 +path = require 'path'
  5 +fs = require 'fs'
  6 +log = require 'node-log'
  7 +log.setName config.service
  8 +
  9 +commando = {}
  10 +commandPath = path.join __dirname, '../commands/'
  11 +
  12 +# Parse process args to command name and command arguments
  13 +parse = ->
  14 + args = process.argv[2...]
  15 + command = args[0]
  16 + args.shift()
  17 + if commandExists command
  18 + require(commandPath + command).exe commando, args
  19 + else if appExists command
  20 + command = args[0]
  21 + args.shift()
  22 + commandPath = path.join __dirname, '../commands/app/'
  23 + if commandExists command
  24 + require(commandPath + command).exe commando, args
  25 + else
  26 + defaultHelp commandPath, args
  27 + else
  28 + defaultHelp commandPath, args
  29 +
  30 +defaultHelp = (commandPath, args) ->
  31 + if commandExists 'help'
  32 + require(commandPath + 'help').exe(commando, args)
  33 + else
  34 + files = fs.readdirSync commandPath
  35 + return log.error 'No commands found.' unless files
  36 + commands = (path.basename(x, path.extname(x)) for x in files)
  37 + log.info 'Available Commands:'
  38 + log.info " - #{command}" for command in commands
  39 +
  40 +commandExists = (command) ->
  41 + try
  42 + require.resolve path.join commandPath, command
  43 + return true
  44 + catch err
  45 + return false
  46 +
  47 +appExists = (appName) -> appName in config.applications
  48 +
  49 +parse()
12 bin/nodester.js
... ... @@ -1,12 +0,0 @@
1   -#!/usr/bin/env node
2   -
3   -process.nodester = {
4   - brand: 'nodester',
5   - apihost: 'api.nodester.com'
6   -}
7   -
8   -var cli = require('nodester-cli'),
9   - command = process.argv[0],
10   - cmds = cli.commands;
11   -
12   -cli.run(cmds, command);
0  commands/app/alias.coffee
No changes.
0  commands/app/aliases.coffee
No changes.
0  commands/app/info.coffee
No changes.
0  commands/app/install.coffee
No changes.
0  commands/app/link.coffee
No changes.
0  commands/app/logs.coffee
No changes.
0  commands/app/push.coffee
No changes.
0  commands/app/restart.coffee
No changes.
0  commands/app/start.coffee
No changes.
0  commands/app/stop.coffee
No changes.
0  commands/app/unalias.coffee
No changes.
0  commands/app/uninstall.coffee
No changes.
0  commands/app/upgrade.coffee
No changes.
9 commands/apps.coffee
... ... @@ -0,0 +1,9 @@
  1 +log = require 'node-log'
  2 +config = require '../lib/config'
  3 +
  4 +exports.exe = (cmd, args) ->
  5 + return log.error 'Not logged in' unless config.username? and config.password?
  6 + if config.applications.length > -1
  7 + log.info x for x in config.applications
  8 + else
  9 + log.error 'No applications.'
0  commands/create.coffee
No changes.
18 commands/login.coffee
... ... @@ -0,0 +1,18 @@
  1 +log = require 'node-log'
  2 +api = require '../lib/api'
  3 +config = require '../lib/config'
  4 +
  5 +exports.exe = (cmd, args) ->
  6 + return log.error 'Please logout before trying to login' if config.username? and config.password?
  7 + return log.error 'Missing arguments' if args.length < 2
  8 + api.post 'login', {username: args[0], password: args[1]}, (error, response, body) ->
  9 + return log.error(error) if error
  10 + parsed = JSON.parse body
  11 + if parsed.valid
  12 + config.username = args[0]
  13 + config.password = args[1]
  14 + config.applications = parsed.applications
  15 + config.write()
  16 + log.info 'Login successful'
  17 + else
  18 + log.error parsed.error
10 commands/logout.coffee
... ... @@ -0,0 +1,10 @@
  1 +log = require 'node-log'
  2 +config = require '../lib/config'
  3 +
  4 +exports.exe = (cmd, args) ->
  5 + return log.error 'Not logged in' unless config.username? and config.password?
  6 + config.username = null
  7 + config.password = null
  8 + config.applications = []
  9 + config.write()
  10 + log.info 'Logged out'
5 commands/status.coffee
... ... @@ -0,0 +1,5 @@
  1 +log = require 'node-log'
  2 +api = require '../lib/api'
  3 +
  4 +exports.exe = (cmd, args) ->
  5 + api.get 'status', (res) -> log.info "#{x}: #{res[x]}" for x of res
7 config.json
... ... @@ -0,0 +1,7 @@
  1 +{
  2 + "service":"nodester",
  3 + "host":"nodester.com",
  4 + "user":null,
  5 + "password":null,
  6 + "applications":["testapp"]
  7 +}
8 examples/davster
... ... @@ -1,8 +0,0 @@
1   -#!/bin/bash
2   -
3   -export NODESTER_BRAND=davster;
4   -export NODESTER_APIHOST=auth.davglass.com;
5   -nodester "$@"
6   -export NODESTER_BRAND=;
7   -export NODESTER_APIHOST=;
8   -
35 examples/mynodester.js
... ... @@ -1,35 +0,0 @@
1   -#!/usr/bin/env node
2   -
3   -/**
4   -* Setup the brand info here..
5   -*/
6   -process.nodester = {
7   - brand: 'myapp',
8   - apihost: 'nodester.myapp.com'
9   -}
10   -
11   -//Include the CLI
12   -var cli = require('nodester-cli'),
13   - //Find the command (process.argv has already been processed here to remove node and scriptname)
14   - command = process.argv[0],
15   - //Include the commands so you can add your own
16   - cmds = cli.commands;
17   -
18   -/*
19   -* Add a new command:
20   -* mynodester davglass
21   -* mynodester davglass test
22   -* mynodester help davglass
23   -*/
24   -cmds.davglass = {
25   - test: function() {
26   - cli.log.info('DAVGLASS TEST');
27   - },
28   - usage: function() {
29   - cli.log.usage('davglass USAGE GOES HERE');
30   - }
31   -}
32   -
33   -//Execute the command..
34   -cli.run(cmds, command);
35   -
16 lib/api.coffee
... ... @@ -0,0 +1,16 @@
  1 +config = require './config'
  2 +request = require 'request'
  3 +log = require 'node-log'
  4 +
  5 +send = (path, method, cb, msg) ->
  6 + request {url: "http://#{config.host}/#{path}", method: method, json: JSON.stringify msg}, (error, res, body) ->
  7 + return log.error error if error?
  8 + return log.error "#{res.statusCode} - Invalid API '#{path}'" if res?.statusCode is 404
  9 + return log.error "Failed to read response from server." unless body?
  10 + cb JSON.parse body
  11 +
  12 +module.exports =
  13 + get: (path, cb) -> send path, 'GET', cb
  14 + del: (path, cb) -> send path, 'DELETE', cb
  15 + post: (path, body, cb) -> send path, 'POST', cb, body
  16 + put: (path, body, cb) -> send path, 'PUT', cb, body
299 lib/app.js
... ... @@ -1,299 +0,0 @@
1   -var node = require('nodester-api').nodester,
2   - config = require('./config'),
3   - path = require('path'),
4   - exists = path.existsSync;
5   -log = require('./log'), util = require('util'), exec = require('child_process').exec, fs = require('fs');
6   -
7   -
8   -module.exports = {
9   - usage: function () {
10   - log.usage('app or <appname> is not required if inside an app directory after you call setup');
11   - log.usage('app setup <appname> - Configure this app for future app commands');
12   - log.usage('app info <appname> - Returns app specific information');
13   - log.usage('app logs <appname> - Returns app logs');
14   - log.usage('app stop|start|restart <appname> - Controls app status.');
15   - log.usage('app create <appname> <startfile> - Creates a new app named <appname>, <startfile> is optional.');
16   - log.usage('app delete <appname> - Deletes the app.');
17   - log.usage('app gitreset <appname> - Resets the app to git HEAD (in case you want a clean restart).');
18   - log.usage('app init <appname> - Fetches the remote repo and sets it up.');
19   - log.usage('app clone <appname> - Fetches the remote repo.');
20   - },
21   - setup: function (args) {
22   - if (!args.length) {
23   - log.error('appname required');
24   - return;
25   - }
26   - config.writeApp(args[0]);
27   - },
28   - info: function (args) {
29   - config.check();
30   - var appname = config.appname;
31   - if (args.length) {
32   - appname = args[0].toLowerCase();
33   - }
34   - log.info('Gathering information about:', appname);
35   - var nodeapi = new node(config.username, config.password, config.apihost, config.apisecure);
36   - nodeapi.app_info(appname, function (err, data, original) {
37   - if (err) {
38   - log.error(err.message);
39   - }
40   - var l = 'info',
41   - r = data.running;
42   - if (data.running == false || data.running.indexOf('error') > -1 || data.running.indexOf('failed-to-stop') > -1) {
43   - l = 'warn';
44   - if (r === false) {
45   - r = 'false'
46   - }
47   - r = r.red;
48   - }
49   - var pid = '';
50   - if (data.pid) {
51   - pid = '(pid: ' + data.pid + ')';
52   - }
53   - log[l](appname, 'on port', data.port, 'running:', r.bold, pid);
54   - log.info('gitrepo:', data.gitrepo);
55   - log.info('appfile:', data.start);
56   - });
57   - },
58   - logs: function (args) {
59   - config.check();
60   - var appname = config.appname;
61   - if (args.length) {
62   - appname = args[0].toLowerCase();
63   - }
64   -
65   - var nodeapi = new node(config.username, config.password, config.apihost, config.apisecure);
66   - nodeapi.app_logs(appname, function (err, data, original) {
67   - if (err) {
68   - log.info(original);
69   - log.error(err.message);
70   - }
71   - if (data.lines && data.lines.length && data.lines[0] !== '') {
72   - log.info('Showing logs for:', appname);
73   - data.lines.forEach(function (l) {
74   - log.plain(l);
75   - });
76   - } else {
77   - log.warn('no log data returned.');
78   - }
79   - });
80   -
81   - },
82   - stop: function (args) {
83   - config.check();
84   - var appname = config.appname;
85   - if (args.length) {
86   - appname = args[0].toLowerCase();
87   - }
88   - log.info('Attemping to stop app:', appname);
89   - var nodeapi = new node(config.username, config.password, config.apihost, config.apisecure);
90   - nodeapi.app_stop(appname, function (err, data, original) {
91   - if (err) {
92   - log.info(original);
93   - log.error(err.message);
94   - }
95   - if (data.status == "success") {
96   - log.info('app stopped.');
97   - } else {
98   - log.warn(data.status);
99   - }
100   - });
101   - },
102   - start: function (args) {
103   - config.check();
104   - var appname = config.appname;
105   - if (args.length) {
106   - appname = args[0].toLowerCase();
107   - }
108   - log.info('Attemping to start app:', appname);
109   - var nodeapi = new node(config.username, config.password, config.apihost, config.apisecure);
110   - nodeapi.app_start(appname, function (err, data, original) {
111   - if (err) {
112   - log.info(original);
113   - log.error(err.message);
114   - }
115   - if (data.status == "success") {
116   - log.info('app started.'.bold.green);
117   - } else {
118   - log.warn(data.status);
119   - }
120   - });
121   - },
122   - restart: function (args) {
123   - config.check();
124   - var appname = config.appname;
125   - if (args.length) {
126   - appname = args[0].toLowerCase();
127   - }
128   - log.info('Attemping to restart app:', appname);
129   - var nodeapi = new node(config.username, config.password, config.apihost, config.apisecure);
130   - nodeapi.app_restart(appname, function (err, data, original) {
131   - if (err) {
132   - log.info(original);
133   - log.error(err.message);
134   - }
135   - if (data.status == "success") {
136   - log.info('app restarted.'.bold.green);
137   - } else {
138   - log.warn(data.status);
139   - }
140   - });
141   - },
142   - gitreset: function (args) {
143   - config.check();
144   - var appname = config.appname;
145   - if (args.length) {
146   - var appname = args[0].toLowerCase();
147   - }
148   - log.warn('resetting app:', appname);
149   - var nodeapi = new node(config.username, config.password, config.apihost, config.apisecure);
150   - nodeapi.app_gitreset(appname, function (err, data, original) {
151   - if (err) {
152   - log.info(original);
153   - log.error(err.message);
154   - }
155   - if (data.status == "success") {
156   - log.warn('successfully reset app', appname.bold);
157   - } else {
158   - log.info(original);
159   - log.error(data.status);
160   - }
161   - });
162   - },
163   - delete: function (args) {
164   - config.check();
165   - var appname = config.appname;
166   - if (args.length) {
167   - var appname = args[0].toLowerCase();
168   - }
169   - log.warn('deleting app:', appname);
170   - log.warn('Are you sure you want to do this?');
171   - log.plain(' Waiting 10 seconds before continuing, Ctrl+C to abort)');
172   - util.print('.');
173   - var timer = setInterval(function () {
174   - util.print('.');
175   - }, 1000);
176   - setTimeout(function () {
177   - clearInterval(timer);
178   - util.print('\n');
179   - log.warn('Really deleting app now, you were warned..');
180   - var nodeapi = new node(config.username, config.password, config.apihost, config.apisecure);
181   - nodeapi.app_delete(appname, function (err, data, original) {
182   - if (err) {
183   - log.info(original);
184   - log.error(err.message);
185   - }
186   - if (data.status == "success") {
187   - log.warn('successfully deleted app', appname.bold);
188   - } else {
189   - log.info(original);
190   - log.error(data.status);
191   - }
192   - });
193   - }, 10000);
194   - },
195   - create: function (args) {
196   - config.check();
197   - if (!args.length) {
198   - log.error('appname required');
199   - return;
200   - }
201   - var name = args[0].toLowerCase();
202   - var start = args[1] || 'server.js';
203   - log.info('creating app:', name, start);
204   -
205   - var nodeapi = new node(config.username, config.password, config.apihost, config.apisecure);
206   - nodeapi.app_create(name, start, function (err, data, original) {
207   - if (err) {
208   - log.info(original);
209   - log.error(err.message);
210   - }
211   - if (data.status == "success") {
212   - log.info('successfully created app', name.bold, 'to will run on port', ((data.port) + '').bold, 'from', start.bold);
213   - log.info('run', (config.brand + ' app init ' + name).yellow.bold, 'to setup this app.');
214   - } else {
215   - log.info(original);
216   - log.error(data.status, ':', data.message);
217   - }
218   - });
219   - },
220   - init: function (args) {
221   - config.check();
222   - if (!args.length) {
223   - log.error('appname required');
224   - return;
225   - } else {
226   - var appname = args[0].toLowerCase();
227   - var folder = appname;
228   - if (args[1]) {
229   - folder = args[1].toLowerCase();
230   - }
231   - }
232   - log.info('initializing git repo for', appname, 'into folder', folder);
233   - if (!exists(folder)) {
234   - try {
235   - fs.mkdirSync(folder, 0750);
236   - } catch (e) {
237   - log.error(e.toString());
238   - }
239   - }
240   - var nodeapi = new node(config.username, config.password, config.apihost, config.apisecure);
241   - nodeapi.app_info(appname, function (err, data, original) {
242   - if (err) {
243   - log.info(original);
244   - log.error(err.message);
245   - }
246   - log.info('cloning the repo', 'git clone ' + data.gitrepo + ' ' + folder);
247   - var child = exec('git clone ' + data.gitrepo + ' ' + folder, function (error, stdout, stderr) {
248   - log.info('clone complete');
249   - var rcfile = config.writeApp(appname, folder);
250   - log.info('writing app files');
251   - fs.writeFileSync(folder + '/.gitignore', rcfile + "\n");
252   -
253   - var defaultCode = "var http = require('http');\n" + "http.createServer(function (req, res) {\n" + " res.writeHead(200, {'Content-Type': 'text/plain'});\n" + " res.end('Hello World\\nApp (" + appname + ") is running..');\n" + "}).listen(" + data.port + ");\n";
254   -
255   - fs.writeFileSync(folder + '/' + data.start, defaultCode);
256   - var cmd = 'cd ' + folder + '; git add ' + data.start + ' .gitignore; git commit -am "Initial commit via ' + config.brand + '-cli"; git push origin master;';
257   - log.info('processing the initial commit');
258   -
259   - var child2 = exec(cmd, function (error, stdout, stderr) {
260   - log.info(appname, "started.");
261   - log.info('Some helpful app commands:\n');
262   - log.plain(' cd ./' + folder);
263   - log.plain(' curl http://' + folder + '.nodester.com/');
264   - log.plain(' ', (config.brand + ' app info').yellow);
265   - log.plain(' ', (config.brand + ' app logs').yellow);
266   - log.plain(' ', (config.brand + ' app stop|start|restart').yellow);
267   - });
268   - });
269   - });
270   - },
271   - clone: function (args) {
272   - config.check();
273   - if (args.length) {
274   - var appname = folder = args[0].toLowerCase();
275   - if (args[1]) {
276   - folder = args[1].toLowerCase();
277   - }
278   - }
279   - log.info('initializing git repo for', appname, 'into folder', folder);
280   - try {
281   - fs.mkdirSync(folder, 0750);
282   - } catch (e) {
283   - log.error(e.toString());
284   - }
285   - var nodeapi = new node(config.username, config.password, config.apihost, config.apisecure);
286   - nodeapi.app_info(appname, function (err, data, original) {
287   - if (err) {
288   - log.info(original);
289   - log.error(err.message);
290   - }
291   - log.info('cloning the repo', 'git clone ' + data.gitrepo + ' ' + folder);
292   - var child = exec('git clone ' + data.gitrepo + ' ' + folder, function (error, stdout, stderr) {
293   - var rcfile = config.writeApp(appname, folder);
294   - fs.writeFileSync(folder + '/.gitignore', rcfile + "\n");
295   - });
296   - });
297   -
298   - }
299   -}
106 lib/appdomain.js
... ... @@ -1,106 +0,0 @@
1   -var node = require('nodester-api').nodester,
2   - config = require('./config'),
3   - log = require('./log');
4   -
5   -
6   -module.exports = {
7   - usage: function () {
8   - log.usage('In a configured app dir, <appname> is optional. (domain aliases appdomain)');
9   - log.usage('domain add|create <appname> <domainname> - Add a domain router for this app');
10   - log.usage('domain remove|delete <appname> <domainname> - Remove a domain router from this app');
11   - log.usage('domain - List domains');
12   - },
13   - add: function (args) {
14   - config.check();
15   - var appname = config.appname,
16   - domain;
17   - if (args.length) {
18   - if (args.length === 2) {
19   - domain = args[1];
20   - appname = args[0];
21   - } else {
22   - domain = args[0];
23   - }
24   - }
25   - if (!domain) {
26   - log.error('<domainname> required');
27   - } else if (!appname) {
28   - log.error('<appname> name required');
29   - }
30   - log.info('adding domain', domain, 'to', appname);
31   - var nodeapi = new node(config.username, config.password, config.apihost, config.apisecure);
32   - nodeapi.appdomain_add(appname, domain, function (err, data, original) {
33   - if (err) {
34   - log.info(original);
35   - log.error(err.message);
36   - }
37   - if (data.status == 'success') {
38   - log.info(original);
39   - log.info(data.message);
40   - log.info('Please restart before any changes will be seen');
41   - } else {
42   - log.info(original);
43   - log.warn(data);
44   - }
45   - });
46   - },
47   - create: function (args) {
48   - module.exports.add.call(this, args);
49   - },
50   - remove: function (args) {
51   - module.exports.delete.call(this, args);
52   - },
53   - delete: function (args) {
54   - config.check();
55   - var appname = config.appname,
56   - domain;
57   - if (args.length) {
58   - if (args.length === 2) {
59   - domain = args[1];
60   - appname = args[0];
61   - } else {
62   - domain = args[0];
63   - }
64   - }
65   - if (!domain) {
66   - log.error('<domainname> required');
67   - } else if (!appname) {
68   - log.error('<appname> name required');
69   - }
70   - log.info('removing domain', domain, 'from', appname);
71   - var nodeapi = new node(config.username, config.password, config.apihost, config.apisecure);
72   - nodeapi.appdomain_delete(appname, domain, function (err, data, original) {
73   - if (err) {
74   - log.info(original);
75   - log.error(err.message);
76   - }
77   - if (data.status == 'success') {
78   - log.info(original);
79   - log.info(data.message);
80   - log.info('Please restart before any changes will be seen');
81   - } else {
82   - log.info(original);
83   - log.warn(data);
84   - }
85   - });
86   - },
87   - run: function () {
88   - config.check();
89   - log.info('fetching your list of domain aliases');
90   - var nodeapi = new node(config.username, config.password, config.apihost, config.apisecure);
91   - nodeapi.appdomains(function (err, data, original) {
92   - if (err) {
93   - log.info(original);
94   - log.error(err);
95   - }
96   - if (data.length > 0) {
97   - data.forEach(function (i) {
98   - log.info(i.domain.white, 'aliased to app', i.appname.white, 'running on port', i.port);
99   - });
100   - } else {
101   - log.warn('no app domains to report');
102   - }
103   - });
104   - }
105   -
106   -}
40 lib/apps.js
... ... @@ -1,40 +0,0 @@
1   -var node = require('nodester-api').nodester,
2   - config = require('./config'),
3   - log = require('./log');
4   -
5   -
6   -module.exports = {
7   - usage: function () {
8   - log.usage('apps list - list all your registered apps');
9   - },
10   - run: function () {
11   - //Placeholder for later adding more `cmd apps` commands
12   - this.list();
13   - },
14   - list: function (args) {
15   - config.check();
16   - var nodeapi = new node(config.username, config.password, config.apihost, config.apisecure);
17   - nodeapi.apps_list(function (err, data, original) {
18   - if (err) {
19   - log.info(original);
20   - log.error(err);
21   - }
22   - if (data.length > 0) {
23   - for (var i in data) {
24   - var l = 'info',
25   - r = data[i].running;
26   - if (data[i].running == false || data[i].running == 'false' || data[i].running.indexOf('error') > -1 || data[i].running.indexOf('failed-to') > -1) {
27   - l = 'warn';
28   - if (r === false || r == 'false') {
29   - r = 'false'
30   - }
31   - r = r.red;
32   - }
33   - log[l](data[i].name, 'on port', data[i].port, 'running:', r.bold);
34   - }
35   - } else {
36   - log.warn('no apps to report');
37   - }
38   - });
39   - }
40   -}
137 lib/commands.js
... ... @@ -1,137 +0,0 @@
1   -var log = require('./log');
2   - brand = "nodester",
3   - apihost = "api.nodester.com",
4   - apisecure = false,
5   - env = process.env,
6   - fs = require('fs');
7   -
8   -
9   -
10   -process.argv = process.argv.slice(2);
11   -
12   -if (env.NODESTER_APIHOST) {
13   - apihost = env.NODESTER_APIHOST;
14   -}
15   -if (env.NODESTER_APISECURE) {
16   - apisecure = true;
17   -}
18   -if (env.NODESTER_BRAND) {
19   - brand = env.NODESTER_BRAND;
20   -}
21   -
22   -
23   -var nodester_config = {
24   - apisecure: apisecure,
25   - apihost: apihost,
26   - brand: brand,
27   - appname: '',
28   - config: {
29   - username: '',
30   - password: ''
31   - }
32   -};
33   -if (!process.nodester) {
34   - process.nodester = {};
35   -}
36   -for (var i in nodester_config) {
37   - if (!process.nodester[i]) {
38   - process.nodester[i] = nodester_config[i];
39   - }
40   -}
41   -
42   -var path = require('path');
43   -try {
44   -var pack = JSON.parse(fs.readFileSync(path.join(__dirname, '../', 'package.json'), encoding='utf8'));
45   -} catch (e) {
46   - var pack = {
47   - version: 'unknown'
48   - };
49   -}
50   -
51   -require('./config').parse();
52   -
53   -exports.log = log;
54   -
55   -exports.commands = {
56   - status: require('./status'),
57   - coupon: require('./coupon'),
58   - apps: require('./apps'),
59   - app: require('./app'),
60   - user: require('./user'),
61   - appdomain: require('./appdomain'),
62   - domain: require('./appdomain'),
63   - npm: require('./npm'),
64   - appnpm: require('./npm'),
65   - version: {
66   - run: function() {
67   - log.plain(pack.version);
68   - }
69   - },
70   - help: {
71   - run: function(args) {
72   - if (args[0] && args[0].toLowerCase() === 'all') {
73   - showUsage();
74   - } else {
75   - showHelp(args);
76   - }
77   - }
78   - }
79   -};
80   -
81   -exports.commands.v = exports.commands.version;
82   -exports.commands['-v'] = exports.commands.version;
83   -exports.commands['-version'] = exports.commands.version;
84   -exports.commands['--version'] = exports.commands.version;
85   -
86   -exports.run = function(cmds, command) {
87   - if (!command) {
88   - showHelp(exports.commands);
89   - process.exit(1);
90   - }
91   -
92   - if (!cmds[command] && process.nodester.appname) {
93   - command = 'app';
94   - process.argv.unshift('app');
95   - }
96   -
97   - if (cmds[command]) {
98   - if (cmds[command][process.argv.slice(1)[0]]) {
99   - cmds[command][process.argv.slice(1)[0]](process.argv.slice(2));
100   - } else if (cmds[command].run) {
101   - cmds[command].run(process.argv.slice(1));
102   - } else {
103   - if (cmds[command].usage) {
104   - cmds[command].usage();
105   - }
106   - }
107   - } else {
108   - log.error('command not found: ' + command);
109   - }
110   -}
111   -
112   -
113   -var showHelp = exports.showHelp = function(args) {
114   - var cmds = exports.commands;
115   - if (args && cmds[args[0]] && cmds[args[0]].usage) {
116   - cmds[args[0]].usage();
117   - } else {
118   - log.info('showing all available sub commands');
119   - for (var i in cmds) {
120   - if (cmds[i].usage) {
121   - log.usage(i);
122   - }
123   - }
124   - log.info('For more help, type', brand, 'help <command>');
125   - }
126   -}
127   -
128   -var showUsage = function () {
129   - log.info('show usage');
130   - var cmds = exports.commands;
131   - for (var i in cmds) {
132   - if (cmds[i].usage) {
133   - cmds[i].usage();
134   - }
135   - }
136   -};
137   -
6 lib/config.coffee
... ... @@ -0,0 +1,6 @@
  1 +path = require 'path'
  2 +fs = require 'fs'
  3 +
  4 +loc = path.join __dirname, '../config.json'
  5 +module.exports = config = JSON.parse fs.readFileSync loc
  6 +module.exports.write = -> fs.writeFileSync loc, JSON.stringify config
148 lib/config.js
... ... @@ -1,148 +0,0 @@
1   -
2   -var path = require('path'),
3   - fs = require('fs'),
4   - path = require('path'),
5   - exists = path.existsSync,
6   - crypto = require("crypto"),
7   - iniparser = require('iniparser'),
8   - log = require('./log');
9   -
10   -
11   -exports.check = function() {
12   - //log.info('Checking config..');
13   - if (process.nodester.config.username == "" || process.nodester.config.password == "") {
14   - log.error("Username and password not set in config.\nPlease run " + process.nodester.brand + " user setup <username> <password>\n");
15   - }
16   - //log.info('Config valid..');
17   -}
18   -
19   -exports.__defineGetter__('username', function() {
20   - return process.nodester.config.username;
21   -});
22   -exports.__defineGetter__('password', function() {
23   - return process.nodester.config.password;
24   -});
25   -exports.__defineGetter__('apihost', function() {
26   - return process.nodester.apihost;
27   -});
28   -exports.__defineGetter__('apisecure', function() {
29   - return process.nodester.apisecure;
30   -});
31   -exports.__defineGetter__('brand', function() {
32   - return process.nodester.brand;
33   -});
34   -exports.__defineGetter__('appname', function() {
35   - return process.nodester.appname.toLowerCase();
36   -});
37   -
38   -exports.writeUser = function(user, pass) {
39   - log.info('writing user data to config');
40   - var config_file = path.join(process.env.HOME, "." + process.nodester.brand + '.rc');
41   - var str = user + ':' + pass;
42   - var x = cryptAuth(str);
43   - var out = 'auth=' + x + '\n';
44   - fs.writeFileSync(config_file, out, encoding='utf8');
45   - return config_file;
46   -}
47   -
48   -exports.writeApp = function(appname, folder) {
49   - if (!folder) {
50   - folder = '';
51   - }
52   - if(!exists(folder)){
53   - fs.mkdirSync(folder, '0777');
54   - }
55   - var config_file = path.join("./" + folder, "." + process.nodester.brand + ".appconfig");
56   - log.info('Writing app data to config in ' + config_file);
57   - fs.writeFileSync(config_file, "appname=" + appname.toLowerCase() + "\n");
58   - return "." + process.nodester.brand + ".appconfig";
59   -}
60   -
61   -var getKey = function(warn) {
62   - var ssh = path.join(process.env.HOME, ".ssh"),
63   - data = '',
64   - keys = [
65   - path.join(ssh, "id_dsa"),
66   - path.join(ssh, "id_rsa"),
67   - path.join(ssh, "identity")
68   - ];
69   - keys.some(function(v) {
70   - if (exists(v)) {
71   - data = fs.readFileSync(v, encoding='utf8') + '';
72   - return true;
73   - }
74   - });
75   - if (data === '' && warn) {
76   - log.warn('No key file found, encrypt is not going to be strong.');
77   - }
78   -
79   - return data;
80   -}
81   -
82   -
83   -var convertConfig = function(config_file) {
84   - var config = iniparser.parseSync(config_file);
85   - var str = config.username + ':' + config.password;
86   - var x = cryptAuth(str);
87   - var new_config_file = path.join(process.env.HOME, "." + process.nodester.brand + '.rc');
88   - var out = 'auth=' + x + '\n';
89   - fs.writeFileSync(new_config_file, out, encoding='utf8');
90   - log.warn('saved new config file: ' + new_config_file);
91   - log.warn('removing old config file');
92   - fs.unlinkSync(config_file);
93   -};
94   -
95   -/**
96   -* Based heavily on NPM's _authCrypt
97   -* https://github.com/isaacs/npm/blob/master/lib/utils/ini.js
98   -*/
99   -
100   -var decryptAuth = function(str) {
101   - if (crypto.Decipher) {
102   - var key = getKey();
103   - var c = (new crypto.Decipher).init("aes192", key)
104   - var auth = c.update(str, "hex", "utf8")
105   - auth += c.final("utf8");
106   - } else {
107   - auth = str;
108   - }
109   -
110   - var b = new Buffer(auth, 'base64');
111   - return b.toString('utf8');
112   -}
113   -
114   -var cryptAuth = function(str) {
115   - str = new Buffer(str).toString('base64');
116   - if (crypto.Cipher) {
117   - var key = getKey(true);
118   - var c = (new crypto.Cipher).init("aes192", key)
119   - var Crypt = c.update(str, "utf8", "hex");
120   - Crypt += c.final("hex");
121   - } else {
122   - Crypt = str;
123   - }
124   - return Crypt;
125   -}
126   -
127   -exports.parse = function() {
128   - //log.info('parsing config');
129   - var old_config_file = path.join(process.env.HOME, "." + process.nodester.brand + "rc");
130   - if (exists(old_config_file)) {
131   - log.warn('old config file found, converting..');
132   - convertConfig(old_config_file);
133   - }
134   -
135   - var config_file = path.join(process.env.HOME, "." + process.nodester.brand + '.rc');
136   - if (exists(config_file)) {
137   - var config = iniparser.parseSync(config_file);
138   - var a = decryptAuth(config.auth).split(':');
139   - process.nodester.config.username = a[0];
140   - process.nodester.config.password = a[1];
141   - }
142   -
143   - var apprcfile = "." + process.nodester.brand + ".appconfig";
144   - if (exists(apprcfile)) {
145   - var config = iniparser.parseSync(apprcfile);
146   - process.nodester.appname = config.appname.toLowerCase();
147   - }
148   -}
36 lib/coupon.js
... ... @@ -1,36 +0,0 @@
1   -var node = require('nodester-api').nodester,
2   - config = require('./config'),
3   - log = require('./log');
4   -
5   -
6   -module.exports = {
7   - usage: function () {
8   - log.usage('coupon <email address> - Request a coupon code for access');
9   - },
10   - run: function (args) {
11   - if (!args.length) {
12   - //log.error('Email address is required..');
13   - this.usage();
14   - return;
15   - }
16   - var email = args[0];
17   - log.info('Requesting coupon code for: ' + email);
18   - var nodeapi = new node("", "", process.nodester.apihost, config.apisecure);
19   -
20   - nodeapi.coupon_request(email, function (err, data, original) {
21   - if (err) {
22   - log.info(original);
23   - log.error(err);
24   - }
25   - var s = data.status;
26   - if (s.indexOf('success') === 0) {
27   - s = s.replace('success', '');
28   - log.info('SUCCESS'.green.bold + s);
29   - } else {
30   - log.info(original);
31   - log.info(data.status);
32   - }
33   - });
34   -
35   - }
36   -}
36 lib/log.js
... ... @@ -1,36 +0,0 @@
1   -require('colors');
2   -
3   -var level = process.env.NODESTER_LOGLEVEL || 0;
4   -
5   -var strArgs = function (args) {
6   - if (args.length > 1) {
7   - var str = [];
8   - for (var i in args) {
9   - str.push(args[i]);
10   - }
11   - return str.join(' ');
12   - } else {
13   - return args[0];
14   - }
15   - }
16   -
17   -exports.plain = function () {
18   - console.log(strArgs(arguments));
19   -}
20   -
21   -exports.usage = function () {
22   - console.log(process.nodester.brand.magenta, strArgs(arguments));
23   -}
24   -
25   -exports.info = function () {
26   - console.log(process.nodester.brand.magenta, 'info'.white, strArgs(arguments));
27   -}
28   -
29   -exports.warn = function (str) {
30   - console.log(process.nodester.brand.magenta, 'warn'.yellow, strArgs(arguments));
31   -}
32   -
33   -exports.error = function (str) {
34   - console.log(process.nodester.brand.magenta, 'ERROR'.red.inverse, strArgs(arguments));
35   - process.exit(1);
36   -}
187 lib/npm.js
... ... @@ -1,187 +0,0 @@
1   -var node = require('nodester-api').nodester,
2   - path = require('path'),
3   - fs = require('fs'),
4   - exists = path.existsSync,
5   - config = require('./config'),
6   - log = require('./log');
7   -
8   -
9   -module.exports = {
10   - usage: function () {
11   - log.usage('In a configured app dir, <appname> is optional.');
12   - log.usage('All arguments after install|update|uninstall or appname will be sent to npm as packages.');
13   - log.usage('npm list - Lists the installed npm packages for this app.');
14   - log.usage('npm install <appname> <packages> - Installs the list of specified packages to this app.');
15   - log.usage('npm update <appname> <packages> - Update the list of specified packages to this app.');
16   - log.usage('npm uninstall <appname> <packages> - Removes the list of specified packages to this app.');
17   - },
18   - install: function (args) {
19   - config.check();
20   - var appname = config.appname,
21   - p = args;
22   -
23   - if (args.length && !appname) {
24   - appname = args[0];
25   - p = args.splice(1);
26   - }
27   - if (!p.length) {
28   - if (exists('package.json')) {
29   - log.info('grabbing dependencies from package.json...');
30   - var depen = JSON.parse(fs.readFileSync('package.json')).dependencies;
31   - if (!depen) {
32   - log.error('no depedencies found!');
33   - } else {
34   - p = [];
35   - for (dependency in depen) {
36   - p.push(dependency);
37   - }
38   - }
39   - } else {
40   - log.error('no packages to install!');
41   - }
42   - }
43   - log.info('installing to app:', appname);
44   - log.info('installing these npm packages:', p);
45   - var nodeapi = new node(config.username, config.password, config.apihost, config.apisecure);
46   - nodeapi.appnpm_install(appname, p.join(' '), function (err, data, original) {
47   - if (err) {
48   - log.info(original);
49   - log.error(err.message);
50   - }
51   - if (data.output) {
52   - var out = data.output.split('\n');
53   - out.forEach(function (l) {
54   - if (l.indexOf('stdout: ') === -1) {
55   - if (l.length > 1) {
56   - l = l.replace('stderr: ', '');
57   - l = l.split(' ');
58   - l[0] = l[0].magenta;
59   - if (l[1]) {
60   - if (l[1].toLowerCase() === 'warn') {
61   - l[1] = l[1].red;
62   - } else if (l[1].toLowerCase() === 'erro') {
63   - l[1] = l[1].red.inverse.bold;
64   - } else {
65   - l[1] = l[1].white;
66   - }
67   - }
68   - log.usage(l.join(' '));
69   - }
70   - }
71   - });
72   - }
73   - log.plain('');
74   - log.warn('you should restart your app after you are finished installing packages.'.yellow.bold);
75   - });
76   - },
77   - list: function (args) {
78   - config.check();
79   - var appname = config.appname;
80   - if (args.length && !appname) {
81   - appname = args[0];
82   - }
83   - log.info('list npm packages for app:', appname);
84   - var nodeapi = new node(config.username, config.password, config.apihost, config.apisecure);
85   - nodeapi.appnpm_list(appname, function (err, data, original) {
86   - if (err) {
87   - log.info(original);
88   - log.error(err.message);
89   - }
90   - if (data.output) {
91   - var out = data.output.split('\n');
92   - out.forEach(function (l) {
93   - if (l.indexOf('stdout: ') === -1) {
94   - if (l.length > 1) {
95   - l = l.replace('stderr: ', '');
96   - l = l.split(' ');
97   - l[0] = l[0].magenta;
98   - if (l[1]) {
99   - l[1] = l[1].white;
100   - }
101   - log.usage(l.join(' '));
102   - }
103   - }
104   - });
105   - }
106   - log.plain('');
107   - });
108   - },
109   - update: function (args) {
110   - config.check();
111   - var appname = config.appname,
112   - p = args;
113   -
114   - if (args.length && !appname) {
115   - appname = args[0];
116   - p = args.splice(1);
117   - }
118   - if (!p.length) {
119   - log.error('no packages to install');
120   - }
121   - log.info('updating to app:', appname);
122   - log.info('updating these npm packages:', p);
123   - var nodeapi = new node(config.username, config.password, config.apihost, config.apisecure);
124   - nodeapi.appnpm_update(appname, p.join(' '), function (err, data, original) {
125   - if (err) {
126   - log.info(original);
127   - log.error(err.message);
128   - }
129   - if (data.output) {
130   - var out = data.output.split('\n');
131   - out.forEach(function (l) {
132   - if (l.indexOf('stdout: ') === -1) {
133   - if (l.length > 1) {
134   - l = l.replace('stderr: ', '');
135   - l = l.split(' ');
136   - l[0] = l[0].magenta;
137   - if (l[1]) {
138   - l[1] = l[1].white;
139   - }
140   - log.usage(l.join(' '));
141   - }
142   - }
143   - });
144   - }
145   - log.plain('');
146   - log.warn('you should restart your app after you are finished installing packages.'.yellow.bold);
147   - });
148   - },
149   - uninstall: function (args) {
150   - config.check();
151   - var appname = config.appname,
152   - p = args;
153   -
154   - if (args.length && !appname) {
155   - appname = args[0];
156   - p = args.splice(1);
157   - }
158   - if (!p.length) {
159   - log.error('no packages to install');
160   - }
161   - log.info('removing to app:', appname);
162   - log.info('removing these npm packages:', p);
163   - var nodeapi = new node(config.username, config.password, config.apihost, config.apisecure);
164   - nodeapi.appnpm_uninstall(appname, p.join(' '), function (err, data, original) {
165   - if (err) {
166   - log.info(original);
167   - log.error(err.message);
168   - }
169   - if (data.output) {
170   - var out = data.output.split('\n');
171   - out.forEach(function (l) {
172   - if (l.indexOf('stdout: ') === -1) {
173   - if (l.length > 1) {
174   - l = l.replace('stderr: ', '');
175   - l = l.split(' ');
176   - l[0] = l[0].magenta;
177   - if (l[1]) {
178   - l[1] = l[1].white;
179   - }
180   - log.usage(l.join(' '));
181   - }
182   - }
183   - });
184   - }
185   - });
186   - }
187   -}
22 lib/status.js
... ... @@ -1,22 +0,0 @@
1   -var node = require('nodester-api').nodester,
2   - config = require('./config'),
3   - log = require('./log');
4   -
5   -
6   -module.exports = {
7   - usage: function () {
8   - log.usage('status - Show', config.brand, 'API status');
9   - },
10   - run: function () {
11   - log.info('checking api status for:', config.apihost);
12   - var nodeapi = new node('', '', config.apihost, config.apisecure);
13   - nodeapi.status(function (err, data, original) {
14   - if (err) {
15   - log.info(original);
16   - }
17   - for (var i in data) {
18   - log.info(i, data[i].toString().bold);
19   - }
20   - });
21   - }
22   -}
235 lib/user.js
... ... @@ -1,235 +0,0 @@
1   -var node = require('nodester-api').nodester,
2   - config = require('./config'),
3   - sys = require('sys'),
4   - path = require('path'),
5   - log = require('./log'),
6   - fs = require('fs'),
7   - tty, iniparser = require('iniparser');
8   -
9   -try {
10   - tty = require('tty');
11   -} catch (e) {}
12   -
13   -
14   -var info = {
15   - email: '',
16   - coupon: '',
17   - username: '',
18   - sshkey: ''
19   -};
20   -
21   -module.exports = {
22   - usage: function () {
23   - log.usage('user register <coupon-code> - Register a user');
24   - log.usage('user setup <username> <password> - Setup this user');
25   - log.usage('user setpass sendtoken - Sends password reset token to user email');
26   - log.usage('user setpass <token> <new_password> - Set a new password for this user');
27   - log.usage('user setkey </path/to/sshkey> - Set an sshkey (if no argument, ~/.ssh/id_rsa.pub is used)');
28   - log.usage('user create <username> <password> <email address> <file containing ssh public key> <coupon code> - Create a user');
29   - },
30   - create: function (args) {
31   - if (args.length < 5) {
32   - log.usage('user create <username> <password> <email address> <file containing ssh public key> <coupon code> - Create a user');
33   - log.error('All arguments are required');
34   - }
35   -
36   - var user = args[0];
37   - var pass = args[1];
38   - var email = args[2];
39   - var rsakey = args[3];
40   - var coupon = args[4];
41   -
42   - log.info('creating user:', user, ' <' + email + '>');
43   - var nodeapi = new node("", "", config.apihost, config.apisecure);
44   - args.push(function (err, data, original) {
45   - if (err) {
46   - log.info(original);
47   - log.error(err.message);
48   - }
49   - log.info('user successfully created');
50   - config.writeUser(user, pass);
51   - });
52   - nodeapi.user_create.apply(nodeapi, args);
53   - },
54   - setkey: function (args) {
55   - config.check();
56   - var key = args[0];
57   - if (!key) {
58   - key = path.join(process.env.HOME, '.ssh', 'id_rsa.pub');
59   - }
60   - if (!path.existsSync(key)) {
61   - log.error('sshkey was not found:', key);
62   - }
63   - var rsadata = fs.readFileSync(key).toString();
64   - if (rsadata.length < 40) {
65   - log.error("Invalid SSH key file.");
66   - }
67   - log.info('sending sshkey:', key);
68   - var nodeapi = new node(config.username, config.password, config.apihost, config.apisecure);
69   - nodeapi.user_setkey(rsadata, function (err, data, original) {
70   - if (err) {
71   - log.info(original);
72   - log.error(err.message);
73   - }
74   - log.info('ssh key successfully sent');
75   - });
76   - },
77   - setpass: function (args) {
78   - config.check();
79   - var nodeapi = new node(config.username, config.password, config.apihost, config.apisecure);
80   - if (args.length == 1 && args[0] == 'sendtoken') {
81   - nodeapi.user_sendtoken(config.username, function (err, data, original) {
82   - if (err && !data) {
83   - log.info(original);
84   - log.error(err.message);
85   - } else {
86   - log.info(data.status);
87   - log.info('token for setpass has been sent to your email!');
88   - }
89   - });
90   - } else if (args.length == 2) {
91   - nodeapi.user_setpass(args[0], args[1], function (err, data, original) {
92   - if (err) {
93   - log.info(original);
94   - log.error(err.message);
95   - }
96   - log.info('password successfully changed.');
97   - config.writeUser(config.username, args[0]);
98   - });
99   - } else {
100   - log.error('Argument missing: ', 'setpass sendtoken or setpass <token> <new_password>');
101   - }
102   - },
103   - setup: function (args) {
104   - if (args.length < 2) {
105   - log.error('Argument missing: ', '<username> <password>');
106   - }
107   - var nodeapi = new node(args[0], args[1], config.apihost, config.apisecure);
108   - log.info('verifying credentials');
109   - nodeapi.apps_list(function (err, data, original) {
110   - if (err) {
111   - log.info(original);
112   - log.error(err.message);
113   - }
114   - log.info('user verified..');
115   - config.writeUser(args[0], args[1]);
116   - });
117   - },
118   - register: function (args) {
119   - if (!args.length) {
120   - log.error('Coupon Code Required');
121   - }
122   - if (args[1] && args[1].indexOf('@') > -1) {
123   - info.email = args[1];
124   - }
125   - if (!info.email && path.existsSync(path.join(process.env.HOME, '.gitconfig'))) {
126   - var git = iniparser.parseSync(path.join(process.env.HOME, '.gitconfig'));
127   - info.email = git.user.email;
128   - } else if (!info.email) {
129   - log.error('Could not find an email address as an argument or from your ~/.gitconfig, please pass one as an additional argument');
130   - }
131   - info.coupon = args[0];
132   - info.username = process.env.USER;
133   - var sshkey = path.join(process.env.HOME, '.ssh', 'id_rsa.pub')
134   - if (path.existsSync(sshkey)) {
135   - info.sshkey = sshkey;
136   - } else {
137   - log.error('Could not auto find your ssh key: ', sshkey, 'use <' + config.brand + ' user create> instead');
138   - }
139   - log.info('Registering with the following information:');
140   - for (var i in info) {
141   - log.info(i + ':', info[i]);
142   - }
143   - log.warn('Does this information look correct? [y/N]');
144   - log.info('(If it does not, hit Ctrl+C and use <' + config.brand + ' user create> instead)');
145   - var stdin = process.openStdin();
146   - stdin.setEncoding('utf8');
147   - stdin.addListener('data', function (data) {
148   - stdin.removeAllListeners('data');
149   - data = data.replace('\n', '').toLowerCase().substring(0, 1);
150   - if (data === 'y') {
151   - askPass(function (password) {
152   - info.password = password;
153   - log.info('creating user:', info.username, ' <' + info.email + '>');
154   - var nodeapi = new node("", "", config.apihost, config.apisecure);
155   - nodeapi.user_create(info.username, info.password, info.email, info.sshkey, info.coupon, function (err, data, original) {
156   - if (err) {
157   - log.info(original);
158   - log.error(err.message);
159   - }
160   - log.info('user created..');
161   - config.writeUser(info.username, info.password);
162   - });
163   - });
164   - } else {
165   - log.error('aborting registration');
166   - stdin.pause();
167   - }
168   - });
169   -
170   - }
171   -}
172   -
173   -var askPass = exports.askPass = function (fn) {
174   - var stdin = process.openStdin();
175   - stdin.setEncoding('utf8');
176   - var p = [],
177   - c = '';
178   - console.log('Please enter your password:');
179   - if (!tty) {
180   - log.warn('Node version (' + process.version + ') has no tty module, passwords will be echoed to stdout');
181   - stdin.addListener('data', function (data) {
182   - data += '';
183   - data = data.replace('\n', '');
184   - p.push(data);
185   - if (p.length === 2) {
186   - if (p[0] !== p[1]) {
187   - p = [];
188   - log.warn('Passwords did not match, please try again.');
189   - console.log('Please re-enter your password:');
190   - } else {
191   - stdin.removeAllListeners('data');
192   - stdin.pause();
193   - fn(p[0]);
194   - }
195   - } else {
196   - console.log('Confirm password:');
197   - }
198   - });
199   - } else {
200   - tty.setRawMode();
201   - stdin.addListener('data', function (data) {
202   - data += '';
203   - switch (data) {
204   - case '\u0003':
205   - log.error('exiting from Ctrl+C');
206   - process.exit()
207   - break
208   - case '\n':
209   - case '\r':
210   - p.push(c);
211   - c = '';
212   - if (p.length === 1) {
213   - console.log('\nConfirm password:');
214   - } else {
215   - if (p[0] === p[1]) {
216   - stdin.removeAllListeners('data');
217   - console.log('\n');
218   - tty.setRawMode(false);
219   - stdin.pause();
220   - fn(p[0]);
221   - } else {
222   - p = [];
223   - console.log('\n');
224   - log.warn('Passwords did not match, please try again.');
225   - console.log('Please re-enter your password:');
226   - }
227   - }
228   - break;
229   - default:
230   - process.stdout.write("*");
231   - c += data;
232   - }
233   - });
234   - }
235   - }
50 package.json
... ... @@ -1,28 +1,26 @@
1 1 {
2   - "name": "nodester-cli",
3   - "description": "A CLI tool to allow interaction with the http://nodester.com/ platform.",
4   - "version": "0.2.34",
5   - "homepage": "http://nodester.com/",
6   - "repository": "git://github.com/nodester/nodester-cli.git",
7   - "author": "Daniel Bartlett <dan@f-box.org> (http://danb-uk.net/)",
8   - "contributors": [
9   - "Dav Glass <davglass@gmail.com> @davglass",
10   - "Chris Matthieu <chris@matthieu.us>",
11   - "Abraham Williams <4braham@gmail.com>",
12   - "Contra <contra@australia.edu>",
13   - "Marcos Oliveira <marcosvm@gmail.com"
14   - ],
15   - "preferGlobal" : "true",
16   - "bin": {