Merge pull request #139 from loudej/winston
Winston output and command implementation
This commit is contained in:
Коммит
50db13800a
|
@ -0,0 +1,7 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
var cli = require('../lib/cli/cli');
|
||||
cli.parse(process.argv);
|
||||
if (cli.args.length == 0) {
|
||||
cli.parse(['', '', '-h']);
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
|
||||
|
||||
var cli = require('../lib/cli/cli');
|
||||
cli.parse(process.argv);
|
||||
if (cli.args.length == 0) {
|
||||
cli.parse(['', '', '-h']);
|
||||
}
|
4
bin/waz
4
bin/waz
|
@ -1,4 +0,0 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
var waz = require('../lib/waz/waz');
|
||||
waz.parse(process.argv);
|
|
@ -1,4 +0,0 @@
|
|||
|
||||
|
||||
var waz = require('../lib/waz/waz');
|
||||
waz.parse(process.argv);
|
|
@ -1,6 +1,23 @@
|
|||
/**
|
||||
* Copyright 2011 Microsoft Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
var https = require('https');
|
||||
var tunnel = require('tunnel');
|
||||
var xml2js = require('xml2js');
|
||||
var log = require('winston');
|
||||
|
||||
module.exports = Channel;
|
||||
|
||||
|
@ -47,21 +64,36 @@ Channel.prototype.header = function (name, value) {
|
|||
|
||||
Channel.prototype.send = function (method, data, cb) {
|
||||
var options = merge({}, this.options, { method: method });
|
||||
options.agent = new https.Agent(options);
|
||||
if (options.proxy) {
|
||||
options.agent = tunnel.httpsOverHttp(options);
|
||||
} else {
|
||||
options.agent = new https.Agent(options);
|
||||
}
|
||||
|
||||
log.silly('Request.Method', options.method);
|
||||
log.silly('Request.Path', options.path);
|
||||
var req = https.request(options, function (res) {
|
||||
console.log('statusCode: ', res.statusCode);
|
||||
console.log('headers: ', res.headers);
|
||||
|
||||
var done = 0;
|
||||
var parser = new xml2js.Parser();
|
||||
log.silly('Response.Headers', res.headers);
|
||||
res.on('data', function (data) {
|
||||
parser.parseString(data);
|
||||
log.silly('Response.Data', data.toString());
|
||||
try {
|
||||
parser.parseString(data);
|
||||
}
|
||||
catch (err) {
|
||||
cb(err);
|
||||
}
|
||||
});
|
||||
res.on('end', function () {
|
||||
//cb(null, null);
|
||||
if (++done == 1) cb(null, {});
|
||||
});
|
||||
parser.on('end', function (result) {
|
||||
cb(null, result);
|
||||
if (result.Message && result.Code) {
|
||||
if (++done == 1) cb(result, null);
|
||||
} else {
|
||||
if (++done == 1) cb(null, result);
|
||||
}
|
||||
});
|
||||
});
|
||||
if (typeof (data) === 'function') {
|
|
@ -0,0 +1,373 @@
|
|||
/**
|
||||
* Copyright 2011 Microsoft Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
var commander = require('commander');
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
|
||||
var log = require('winston');
|
||||
var colors = require('colors');
|
||||
var eyes = require('eyes');
|
||||
var Table = require('easy-table');
|
||||
|
||||
require('./patch-winston');
|
||||
|
||||
///////////////////////////
|
||||
// prepare output logger
|
||||
|
||||
// use cli output settings by default
|
||||
log.cli();
|
||||
|
||||
log.format = function(options) {
|
||||
var transport = log.default.transports.console;
|
||||
|
||||
if (arguments.length == 0) {
|
||||
return {
|
||||
json: transport.json,
|
||||
terse: transport.terse,
|
||||
level: transport.level,
|
||||
logo: log.format.logo,
|
||||
};
|
||||
}
|
||||
|
||||
if (options.json) {
|
||||
log.padLevels = false;
|
||||
log.stripColors = true;
|
||||
transport.json = true;
|
||||
}
|
||||
if (options.terse) {
|
||||
log.padLevels = false;
|
||||
transport.terse = true;
|
||||
}
|
||||
if (options.level) {
|
||||
transport.level = options.level;
|
||||
}
|
||||
if (options.logo) {
|
||||
log.format.logo = options.logo;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
log.json = function (level, data) {
|
||||
if (arguments.length == 1) {
|
||||
data = level;
|
||||
level = 'data';
|
||||
}
|
||||
if (log.format().json) {
|
||||
log.log(level, typeof data, data);
|
||||
} else {
|
||||
var lines = eyes.inspect(data, level, { stream: false });
|
||||
lines.split('\n').forEach(function (line) {
|
||||
// eyes all is "cyan" by default, so this property accessor will
|
||||
// fix the entry/exit color codes of the line. it's needed because we're
|
||||
// splitting the eyes formatting and inserting winston formatting where it
|
||||
// wasn't before.
|
||||
log.log(level, line[eyes.defaults.styles.all]);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
log.table = function (level, data, transform) {
|
||||
if (arguments.length == 2) {
|
||||
transform = data;
|
||||
data = level;
|
||||
level = 'data';
|
||||
}
|
||||
if (log.format().json) {
|
||||
log.log(level, "table", data);
|
||||
} else {
|
||||
var table = new Table();
|
||||
table.LeftPadder = Table.LeftPadder;
|
||||
table.padLeft = Table.padLeft;
|
||||
table.RightPadder = Table.RightPadder;
|
||||
table.padRight = Table.padRight;
|
||||
|
||||
if (data && data.forEach) {
|
||||
data.forEach(function (item) { transform(table, item); table.newLine(); });
|
||||
} else if (data) {
|
||||
for (var item in data) {
|
||||
transform(table, item);
|
||||
table.newLine();
|
||||
}
|
||||
}
|
||||
|
||||
var lines = table.toString();
|
||||
lines.substring(0, lines.length - 1).split('\n').forEach(function (line) {
|
||||
log.log(level, line);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
// prepare root cli command
|
||||
|
||||
var cli = new commander.Command();
|
||||
cli.output = log;
|
||||
enableNestedCommands(cli);
|
||||
|
||||
|
||||
cli.exit = function (level, message, exitCode) {
|
||||
log.log(level, message);
|
||||
process.exit(exitCode);
|
||||
};
|
||||
|
||||
|
||||
function enableNestedCommands(command) {
|
||||
command.option('-v, --verbose', 'use verbose output');
|
||||
command.option('--json', 'use json output');
|
||||
|
||||
command.categories = {};
|
||||
|
||||
command.category = function (name) {
|
||||
var category = command.categories[name];
|
||||
if (!command.categories[name]) {
|
||||
category = command.categories[name] = new commander.Command();
|
||||
category.parent = this;
|
||||
category.name = name;
|
||||
category.helpInformation = categoryHelpInformation;
|
||||
enableNestedCommands(category);
|
||||
}
|
||||
return category;
|
||||
};
|
||||
|
||||
command.on('*', function () {
|
||||
var args = command.rawArgs.slice(0, 2);
|
||||
var raw = command.normalize(command.rawArgs.slice(2));
|
||||
|
||||
var verbose = 0;
|
||||
var json = 0;
|
||||
var category = '*';
|
||||
for (var i = 0, len = raw.length; i < len; ++i) {
|
||||
if (raw[i] === '--json') {
|
||||
++json;
|
||||
} else if (raw[i] === '-v' || raw[i] === '--verbose') {
|
||||
++verbose;
|
||||
} else if (category === '*') {
|
||||
category = raw[i];
|
||||
} else {
|
||||
args.push(raw[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (verbose || json) {
|
||||
var opts = {};
|
||||
if (json) {
|
||||
opts.json = true;
|
||||
}
|
||||
if (verbose == 1) {
|
||||
opts.level = 'verbose';
|
||||
}
|
||||
if (verbose >= 2) {
|
||||
opts.level = 'silly';
|
||||
}
|
||||
log.format(opts);
|
||||
}
|
||||
|
||||
if (!command.categories[category]) {
|
||||
log.error('\'' + category + '\' is not an azure command. See \'azure help\'.');
|
||||
} else {
|
||||
command.categories[category].parse(args);
|
||||
if (command.categories[category].args.length == 0) {
|
||||
args.push('-h');
|
||||
command.categories[category].parse(args);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
commander.Command.prototype.execute = function (fn) {
|
||||
var self = this;
|
||||
return self.action(function () {
|
||||
log.info('Executing command ' + self.fullName().bold);
|
||||
|
||||
try {
|
||||
var args = [];
|
||||
for (var i = 0; i != arguments.length; ++i) {
|
||||
args.push(arguments[i]);
|
||||
}
|
||||
args.push(callback);
|
||||
fn.apply(this, args);
|
||||
}
|
||||
catch (err) {
|
||||
callback(err);
|
||||
}
|
||||
|
||||
function callback(err) {
|
||||
if (err) {
|
||||
if (err.message) {
|
||||
log.error(err.message);
|
||||
//log.verbose('stack', err.stack);
|
||||
log.json('silly', err);
|
||||
} else if (err.Message) {
|
||||
log.error(err.Message);
|
||||
log.json('verbose', err);
|
||||
} else {
|
||||
log.error(err);
|
||||
}
|
||||
|
||||
cli.exit('error', self.fullName().bold + ' command ' + 'failed'.red.bold, 1);
|
||||
} else {
|
||||
cli.exit('info', self.fullName().bold + ' command ' + 'OK'.green.bold, 0);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//////////////////////////////
|
||||
// override help subsystem
|
||||
|
||||
cli.helpInformation = rootHelpInformation;
|
||||
|
||||
commander.Command.prototype.helpInformation = commandHelpInformation;
|
||||
|
||||
commander.Command.prototype.fullName = function () {
|
||||
var name = this.name;
|
||||
var scan = this.parent;
|
||||
while (scan.parent !== undefined) {
|
||||
name = scan.name + ' ' + name;
|
||||
scan = scan.parent;
|
||||
}
|
||||
return name;
|
||||
};
|
||||
|
||||
function rootHelpInformation() {
|
||||
if (log.format().logo === 'fire') {
|
||||
log.info(' ) ( '.red);
|
||||
log.info(' ( ( /( )\\ ) '.red);
|
||||
log.info(' )\\ )\\()) ( (()/(( '.red);
|
||||
log.info('((((_)( ((_)\\ )\\ /(_))\\ '.red);
|
||||
log.info(' )\\ '.red + '_'.cyan + ' )\\ '.red + '_'.cyan + '(('.red + '_'.cyan + ') (('.red + '_'.cyan + ')'.red + '_'.cyan + '))(('.red + '_'.cyan + ') '.red);
|
||||
log.info(' (_)'.red + '_\\'.cyan + '(_)'.red + '_ / | | | _ \\ __| '.cyan);
|
||||
log.info(' / _ \\ / /| |_| | / _| '.cyan);
|
||||
log.info(' /_/ \\_\\/___|\\___/|_|_\\___| '.cyan);
|
||||
log.info('');
|
||||
} else if (log.format().logo === 'on') {
|
||||
log.info(' _ _____ _ ___ ___ '.cyan);
|
||||
log.info(' /_\\ |_ / | | | _ \\ __|'.cyan);
|
||||
log.info(' / _ \\ / /| |_| | / _| '.cyan);
|
||||
log.info('/_/ \\_\\/___|\\___/|_|_\\___|'.cyan);
|
||||
log.info('');
|
||||
}
|
||||
log.info('Windows Azure: Microsoft\'s Cloud Platform');
|
||||
|
||||
|
||||
helpCommands(this);
|
||||
helpCategories(this);
|
||||
helpOptions(this);
|
||||
return "";
|
||||
};
|
||||
|
||||
function categoryHelpInformation() {
|
||||
log.help(this.description());
|
||||
helpCommands(this);
|
||||
helpCategories(this);
|
||||
helpOptions(this);
|
||||
return "";
|
||||
};
|
||||
|
||||
function commandHelpInformation() {
|
||||
log.help(this.description());
|
||||
log.help('');
|
||||
log.help('Usage:', this.fullName() + ' ' + this.usage());
|
||||
helpOptions(this);
|
||||
return "";
|
||||
}
|
||||
|
||||
function helpCategories(parent) {
|
||||
for (var name in parent.categories) {
|
||||
var cat = parent.categories[name];
|
||||
log.help('');
|
||||
log.help(cat.description().cyan);
|
||||
cat.commands.forEach(function (cmd) {
|
||||
log.help(' ', cmd.fullName() + ' ' + cmd.usage());
|
||||
});
|
||||
helpCategories(cat);
|
||||
for (var subCat in cat.categories) {
|
||||
helpCategories(cat.categories[subCat]);
|
||||
//log.help(' ', cat.categories[subCat].fullName() + ' ...');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function helpCommands(parent) {
|
||||
parent.commands.forEach(function (cmd) {
|
||||
log.help('');
|
||||
log.help(cmd.description().cyan);
|
||||
log.help(' ', cmd.fullName() + ' ' + cmd.usage());
|
||||
});
|
||||
}
|
||||
|
||||
function helpOptions(cmd) {
|
||||
log.help('');
|
||||
log.help('Options:');
|
||||
cmd.optionHelp().split('\n').forEach(function (line) { log.help(' ', line); });
|
||||
}
|
||||
|
||||
|
||||
|
||||
//////////////////////////////
|
||||
// load command plugins
|
||||
|
||||
function harvestPlugins() {
|
||||
function scan(scanPath) {
|
||||
var results = fs.readdirSync(scanPath);
|
||||
|
||||
results = results.filter(function (filePath) {
|
||||
if (filePath.substring(0, 5) === 'tmp--') {
|
||||
return false;
|
||||
}
|
||||
if (filePath.substring(filePath.length - 4) === '_.js') {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
// combine file path
|
||||
results = results.map(function (fileName) {
|
||||
return path.join(scanPath, fileName);
|
||||
});
|
||||
|
||||
// skip directories
|
||||
results = results.filter(function (filePath) {
|
||||
return fs.statSync(filePath).isFile();
|
||||
});
|
||||
|
||||
// load modules
|
||||
results = results.map(function (filePath) {
|
||||
return require(filePath);
|
||||
});
|
||||
|
||||
// look for exports.init
|
||||
results = results.filter(function (entry) {
|
||||
return entry.init !== undefined;
|
||||
});
|
||||
return results;
|
||||
}
|
||||
|
||||
var basePath = path.dirname(__filename);
|
||||
var plugins = scan(path.join(basePath, 'commands'));
|
||||
plugins.forEach(function (plugin) { plugin.init(cli); });
|
||||
}
|
||||
|
||||
harvestPlugins();
|
||||
|
||||
exports = module.exports = cli;
|
|
@ -0,0 +1,241 @@
|
|||
/**
|
||||
* Copyright 2011 Microsoft Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
var common = require('../common');
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var xml2js = require('xml2js');
|
||||
var assert = require('assert');
|
||||
var pfx2pem = require('../../util/certificates/pkcs').pfx2pem;
|
||||
|
||||
exports.init = function (cli) {
|
||||
|
||||
var log = cli.output;
|
||||
|
||||
var account = cli.category('account')
|
||||
.description('Manage your account information and publish settings');
|
||||
|
||||
|
||||
account.command('download')
|
||||
.description('Launch a browser to download your publishsettings file')
|
||||
.execute(function (options, callback) {
|
||||
try {
|
||||
var url = 'https://windows.azure.com/download/publishprofile.aspx';
|
||||
common.launchBrowser(url);
|
||||
log.help('Save the downloaded file, then execute the command');
|
||||
log.help(' account import <file>');
|
||||
callback();
|
||||
}
|
||||
catch (err) {
|
||||
callback(err);
|
||||
}
|
||||
});
|
||||
|
||||
account.command('import <file>')
|
||||
.description('Import a publishsettings file for your account')
|
||||
.action(function (publishSettingsFile) {
|
||||
log.info('Importing publish settings file', publishSettingsFile);
|
||||
|
||||
var wazPath = path.join(homeFolder(), '.azure');
|
||||
var wazPublishSettingsFilePath = path.join(wazPath, 'publishSettings.xml');
|
||||
var wazManagementCertificatePfxFilePath = path.join(wazPath, 'managementCertificate.pfx');
|
||||
var wazManagementCertificatePemFilePath = path.join(wazPath, 'managementCertificate.pem');
|
||||
|
||||
var parser = new xml2js.Parser();
|
||||
parser.on('end', processSettings);
|
||||
try {
|
||||
var readBuffer = fs.readFileSync(publishSettingsFile);
|
||||
parser.parseString(readBuffer);
|
||||
} catch (err) {
|
||||
log.error('Unable to read publish settings file');
|
||||
log.error(err);
|
||||
}
|
||||
function processSettings(settings) {
|
||||
var attribs = settings.PublishProfile['@'];
|
||||
var subs = settings.PublishProfile.Subscription;
|
||||
if (subs === 'undefined') {
|
||||
subs = [];
|
||||
} else if (typeof (subs[0]) === 'undefined') {
|
||||
subs = [subs];
|
||||
}
|
||||
|
||||
if (subs.length == 0) {
|
||||
log.warning('Importing profile with no subscriptions');
|
||||
}
|
||||
else {
|
||||
for (var index in subs) {
|
||||
log.info('Found subscription:', subs[index]['@'].Name);
|
||||
log.verbose(' Id:', subs[index]['@'].Id);
|
||||
}
|
||||
}
|
||||
|
||||
log.verbose('Parsing management certificate');
|
||||
var pfx = new Buffer(attribs.ManagementCertificate, 'base64');
|
||||
var pem = pfx2pem(pfx);
|
||||
|
||||
log.verbose('Storing account information at', wazPath);
|
||||
fs.stat(wazPath, function (err, stat) {
|
||||
if (err) {
|
||||
fs.mkdirSync(wazPath, 0766);
|
||||
} else {
|
||||
//assert.equal(stat.isDirectory());
|
||||
}
|
||||
var reader = fs.createReadStream(publishSettingsFile, { flags: 'r' });
|
||||
log.silly('Writing to file', wazPublishSettingsFilePath);
|
||||
var writer = fs.createWriteStream(wazPublishSettingsFilePath, { flags: 'w', mode: 0600 });
|
||||
reader.pipe(writer);
|
||||
reader.on('end', function () {
|
||||
log.silly('Writing to file', wazManagementCertificatePemFilePath);
|
||||
var writer = fs.createWriteStream(wazManagementCertificatePemFilePath, { flags: 'w', mode: 0600 });
|
||||
writer.write(pem, pem.toString());
|
||||
writer.end();
|
||||
|
||||
log.silly('Writing to file', wazManagementCertificatePfxFilePath);
|
||||
var writer = fs.createWriteStream(wazManagementCertificatePfxFilePath, { flags: 'w', mode: 0600 });
|
||||
writer.write(pfx, pfx.toString());
|
||||
writer.end();
|
||||
|
||||
if (subs.length != 0) {
|
||||
log.info('Setting default subscription to:', subs[0]['@'].Name);
|
||||
var config = account.readConfig();
|
||||
config.subscription = subs[0]['@'].Id;
|
||||
account.writeConfig(config);
|
||||
}
|
||||
log.warn('The \'' + publishSettingsFile + '\' file contains sensitive information.');
|
||||
log.warn('Remember to delete it now that it has been imported.');
|
||||
log.info('Account publish settings imported successfully');
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
account.command('settings')
|
||||
.description('Display and alter the stored account defaults')
|
||||
.option('-s, --subscription <id>', 'use the subscription id as the default')
|
||||
.option('--labels <on|off>', 'show information labels in console output')
|
||||
.action(function (options) {
|
||||
var config = account.readConfig();
|
||||
var writeConfig = false;
|
||||
|
||||
if (options.subscription) {
|
||||
log.info('Setting default subscription to', options.subscription);
|
||||
config.subscription = options.subscription;
|
||||
writeConfig = true;
|
||||
}
|
||||
|
||||
if (options.labels) {
|
||||
if (options.labels === 'on') {
|
||||
log.info('Enabling information labels in console output');
|
||||
config.labels = 'on';
|
||||
writeConfig = true;
|
||||
}
|
||||
else if (options.labels === 'off') {
|
||||
log.info('Disabling information labels in console output');
|
||||
config.labels = 'off';
|
||||
writeConfig = true;
|
||||
}
|
||||
else {
|
||||
log.error('Unknown --labels value', options.labels);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (writeConfig) {
|
||||
account.writeConfig(config);
|
||||
log.info('Changes saved');
|
||||
} else {
|
||||
log.info('Showing account settings');
|
||||
log.table(config, function (row, name) {
|
||||
row.cell('Setting', name);
|
||||
row.cell('Value', config[name]);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
account.command('clear')
|
||||
.description('Remove any of the stored account info stored by import')
|
||||
.action(function () {
|
||||
console.log('Clearing account info.');
|
||||
});
|
||||
|
||||
|
||||
account.readPublishSettings = function () {
|
||||
var wazPath = path.join(homeFolder(), '.azure');
|
||||
var wazPublishSettingsFilePath = path.join(wazPath, 'publishSettings.xml');
|
||||
|
||||
var publishSettings = {};
|
||||
|
||||
var parser = new xml2js.Parser();
|
||||
parser.on('end', function (result) { publishSettings = result; });
|
||||
try {
|
||||
log.silly('Reading publish settings', wazPublishSettingsFilePath);
|
||||
var readBuffer = fs.readFileSync(wazPublishSettingsFilePath);
|
||||
parser.parseString(readBuffer);
|
||||
} catch (err) {
|
||||
log.error('Unable to read publish settings file');
|
||||
log.error(err);
|
||||
}
|
||||
|
||||
return publishSettings;
|
||||
}
|
||||
|
||||
account.defaultSubscriptionId = function () {
|
||||
return account.readConfig().subscription;
|
||||
};
|
||||
|
||||
account.lookupSubscriptionId = function (subscription) {
|
||||
// use default subscription if not passed as an argument
|
||||
if (subscription === undefined) {
|
||||
subscription = account.readConfig().subscription;
|
||||
}
|
||||
|
||||
// load and normalize publish settings
|
||||
var publishSettings = account.readPublishSettings();
|
||||
|
||||
var subs = publishSettings.PublishProfile.Subscription;
|
||||
if (subs === 'undefined') {
|
||||
subs = [];
|
||||
} else if (typeof (subs[0]) === 'undefined') {
|
||||
subs = [subs];
|
||||
}
|
||||
|
||||
// use subscription id when the subscription name matches
|
||||
for (var index in subs) {
|
||||
if (subs[index]['@'].Name === subscription) {
|
||||
return subs[index]['@'].Id;
|
||||
}
|
||||
}
|
||||
|
||||
return subscription;
|
||||
};
|
||||
|
||||
account.managementCertificate = function () {
|
||||
var wazPath = path.join(homeFolder(), '.azure');
|
||||
var wazManagementCertificateFilePath = path.join(wazPath, 'managementCertificate.pem');
|
||||
log.silly('Reading cert', wazManagementCertificateFilePath);
|
||||
return fs.readFileSync(wazManagementCertificateFilePath);
|
||||
};
|
||||
|
||||
function homeFolder() {
|
||||
if (process.env.HOME !== undefined) {
|
||||
return process.env.HOME;
|
||||
}
|
||||
if (process.env.HOMEDRIVE && process.env.HOMEPATH) {
|
||||
return process.env.HOMEDRIVE + process.env.HOMEPATH;
|
||||
}
|
||||
throw new Error('No HOME path available');
|
||||
}
|
||||
};
|
|
@ -0,0 +1,118 @@
|
|||
/**
|
||||
* Copyright 2011 Microsoft Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var xml2js = require('xml2js');
|
||||
var assert = require('assert');
|
||||
var pfx2pem = require('../../util/certificates/pkcs').pfx2pem;
|
||||
|
||||
exports.init = function (cli) {
|
||||
|
||||
var log = cli.output;
|
||||
|
||||
var account = cli.category('account');
|
||||
|
||||
var config = cli.category('config')
|
||||
.description('Manage tool local settings');
|
||||
|
||||
config.command('list')
|
||||
.description('Display config settings')
|
||||
.action(function (options) {
|
||||
log.info('Displaying config settings');
|
||||
|
||||
var cfg = account.readConfig();
|
||||
|
||||
log.table(cfg, function (row, name) {
|
||||
row.cell('Setting', name);
|
||||
row.cell('Value', cfg[name]);
|
||||
});
|
||||
});
|
||||
|
||||
config.command('set <name> <value>')
|
||||
.description('Change a config setting')
|
||||
.action(function (name, value, options) {
|
||||
log.info('Setting \'' + name + '\' to value \'' + value + '\'');
|
||||
var cfg = account.readConfig();
|
||||
cfg[name] = value;
|
||||
account.writeConfig(cfg);
|
||||
log.info('Changes saved.');
|
||||
});
|
||||
|
||||
|
||||
config.readConfig = function () {
|
||||
var wazPath = path.join(homeFolder(), '.azure');
|
||||
var wazConfigPath = path.join(wazPath, 'config.json');
|
||||
var cfg = {};
|
||||
log.silly('Reading config', wazConfigPath);
|
||||
|
||||
if (path.existsSync(wazConfigPath)) {
|
||||
try {
|
||||
cfg = JSON.parse(fs.readFileSync(wazConfigPath));
|
||||
}
|
||||
catch (err) {
|
||||
log.warn('Unable to read settings');
|
||||
cfg = {};
|
||||
}
|
||||
log.json('silly', cfg);
|
||||
}
|
||||
return cfg;
|
||||
};
|
||||
|
||||
config.writeConfig = function (cfg) {
|
||||
var wazPath = path.join(homeFolder(), '.azure');
|
||||
var wazConfigPath = path.join(wazPath, 'config.json');
|
||||
|
||||
if (!path.existsSync(wazPath)) {
|
||||
log.silly('Creating folder', wazPath);
|
||||
fs.mkdirSync(wazPath, 0766);
|
||||
}
|
||||
log.silly('Writing config', wazConfigPath);
|
||||
fs.writeFileSync(wazConfigPath, JSON.stringify(cfg));
|
||||
};
|
||||
|
||||
// added temporarily for back-compat
|
||||
cli.category('account').readConfig = config.readConfig;
|
||||
cli.category('account').writeConfig = config.writeConfig;
|
||||
|
||||
// apply any persistant switches at load-time
|
||||
function applyGlobalSettings() {
|
||||
var cfg = config.readConfig();
|
||||
if (!cfg) {
|
||||
return;
|
||||
}
|
||||
if (cfg.labels === 'off') {
|
||||
log.format({ terse: true });
|
||||
}
|
||||
if (cfg.logo === 'on') {
|
||||
log.format({ logo: 'on' });
|
||||
} else if (cfg.logo === 'fire') {
|
||||
log.format({ logo: 'fire' });
|
||||
}
|
||||
}
|
||||
|
||||
applyGlobalSettings();
|
||||
|
||||
function homeFolder() {
|
||||
if (process.env.HOME !== undefined) {
|
||||
return process.env.HOME;
|
||||
}
|
||||
if (process.env.HOMEDRIVE && process.env.HOMEPATH) {
|
||||
return process.env.HOMEDRIVE + process.env.HOMEPATH;
|
||||
}
|
||||
throw new Error('No HOME path available');
|
||||
}
|
||||
};
|
|
@ -0,0 +1,33 @@
|
|||
/**
|
||||
* Copyright 2011 Microsoft Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
exports.init = function (cli) {
|
||||
|
||||
cli.command('help [command]')
|
||||
.description('Display help for a given command')
|
||||
.action(function (name, a, b, c) {
|
||||
if (!name) {
|
||||
var args = ['', '', '-h'];
|
||||
cli.parse(args);
|
||||
} else if (!cli.categories[name]) {
|
||||
throw new Error("Unknown command name " + name)
|
||||
} else {
|
||||
var args = ['', ''].concat(cli.rawArgs.slice(4), ['-h']);
|
||||
cli.categories[name].parse(args);
|
||||
}
|
||||
});
|
||||
|
||||
};
|
|
@ -0,0 +1,55 @@
|
|||
/*** Generated by streamline 0.2.2 - DO NOT EDIT ***/
|
||||
var __rt=require('streamline/lib/callbacks/runtime').runtime(__filename),__func=__rt.__func,__cb=__rt.__cb,__propagate=__rt.__propagate,__trap=__rt.__trap,__future=__rt.__future,__setEF=__rt.__setEF,__g=__rt.__g;
|
||||
/* 1 */ var url = require("url");
|
||||
/* 18 */ var querystring = require("querystring");
|
||||
/* 19 */ var Channel = require("../channel");
|
||||
/* 23 */ var child_process = require("child_process");
|
||||
/* 25 */ exports.init = function(cli) {
|
||||
/* 26 */ var log = cli.output;
|
||||
/* 27 */ var site = cli.category("site");
|
||||
/* 29 */ var deploy = site.command("push [name]").description("Publish the current directory as web site via git").option("-s, --subscription <id>", "use the subscription id").execute(function __1(name, options, _) {
|
||||
var context, siteConfig, repositoryData, repositoryUrl, result;
|
||||
var __frame = {
|
||||
name: "__1",
|
||||
line: 32
|
||||
};
|
||||
return __func(_, this, arguments, __1, 2, __frame, function __$__1() {
|
||||
/* 36 */ context = {
|
||||
/* 37 */ subscription: cli.category("account").lookupSubscriptionId(options.subscription),
|
||||
/* 38 */ site: {
|
||||
/* 39 */ name: name
|
||||
}
|
||||
};
|
||||
/* 42 */ return site.lookupSiteName(context, __cb(_, __frame, 10, 12, function __$__1() {
|
||||
/* 43 */ return site.lookupSiteWebSpace(context, __cb(_, __frame, 11, 12, function __$__1() {
|
||||
/* 44 */ return site.doSiteConfigGet(context, __cb(_, __frame, 12, 29, function ___(__0, __1) {
|
||||
siteConfig = __1;
|
||||
/* 45 */ return site.doRepositoryGet(context, __cb(_, __frame, 13, 33, function ___(__0, __2) {
|
||||
repositoryData = __2;
|
||||
/* 46 */ repositoryUrl = url.parse(repositoryData);
|
||||
/* 48 */ repositoryUrl.pathname = (context.site.name + ".git");
|
||||
/* 49 */ repositoryUrl.auth = ((querystring.escape(("$" + context.site.name)) + ":") + querystring.escape(siteConfig.PublishingPassword));
|
||||
/* 50 */ repositoryUrl.protocol = "http:";
|
||||
/* 51 */ delete repositoryUrl.host;
|
||||
/* 53 */ return exec((("git push " + url.format(repositoryUrl)) + " HEAD:master -f"), __cb(_, __frame, 21, 25, function ___(__0, __3) {
|
||||
result = __3;
|
||||
/* 54 */ ((result.stdout + result.stderr)).split("\n").forEach(function(line) {
|
||||
/* 55 */ log.data(line.replace(/:\/\/[^@]*@/, "://...@"));
|
||||
});
|
||||
_();
|
||||
}));
|
||||
}));
|
||||
}));
|
||||
}));
|
||||
}));
|
||||
});
|
||||
});
|
||||
/* 59 */ function exec(cmd, cb) {
|
||||
/* 60 */ child_process.exec(cmd, function(err, stdout, stderr) {
|
||||
/* 61 */ cb(err, {
|
||||
/* 62 */ stdout: stdout,
|
||||
/* 63 */ stderr: stderr
|
||||
});
|
||||
});
|
||||
};
|
||||
};
|
|
@ -0,0 +1,75 @@
|
|||
/**
|
||||
* Copyright 2011 Microsoft Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
var url = require('url');
|
||||
var querystring = require('querystring');
|
||||
var Channel = require('../channel');
|
||||
|
||||
|
||||
|
||||
var child_process = require('child_process');
|
||||
|
||||
exports.init = function (cli) {
|
||||
var log = cli.output;
|
||||
var site = cli.category('site');
|
||||
|
||||
var deploy = site.command('push [name]')
|
||||
.description('Publish the current directory as web site via git')
|
||||
.option('-s, --subscription <id>', 'use the subscription id')
|
||||
.execute(function (name, options, _) {
|
||||
|
||||
// log.json(url.parse('http://a:b@c.com/d?e#f'));
|
||||
|
||||
var context = {
|
||||
subscription: cli.category('account').lookupSubscriptionId(options.subscription),
|
||||
site: {
|
||||
name: name
|
||||
}
|
||||
};
|
||||
site.lookupSiteName(context, _);
|
||||
site.lookupSiteWebSpace(context, _);
|
||||
var siteConfig = site.doSiteConfigGet(context, _);
|
||||
var repositoryData = site.doRepositoryGet(context, _);
|
||||
var repositoryUrl = url.parse(repositoryData);
|
||||
|
||||
repositoryUrl.pathname = context.site.name + '.git';
|
||||
repositoryUrl.auth = querystring.escape('$' + context.site.name) + ':' + querystring.escape(siteConfig.PublishingPassword);
|
||||
repositoryUrl.protocol = 'http:';
|
||||
delete repositoryUrl.host;
|
||||
|
||||
var result = exec('git push ' + url.format(repositoryUrl) + ' HEAD:master -f', _);
|
||||
(result.stdout + result.stderr).split('\n').forEach(function (line) {
|
||||
log.data(line.replace(/:\/\/[^@]*@/, '://...@'));
|
||||
});
|
||||
});
|
||||
|
||||
function exec(cmd, cb) {
|
||||
child_process.exec(cmd, function (err, stdout, stderr) {
|
||||
cb(err, {
|
||||
stdout:stdout,
|
||||
stderr:stderr
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// deploy.command('list')
|
||||
// .description('Show deployment history')
|
||||
// .action(function () { });
|
||||
|
||||
// deploy.command('activate')
|
||||
// .description('Reactivate a specific deployment')
|
||||
// .action(function () { });
|
||||
};
|
|
@ -0,0 +1,671 @@
|
|||
/*** Generated by streamline 0.2.2 - DO NOT EDIT ***/
|
||||
var __rt=require('streamline/lib/callbacks/runtime').runtime(__filename),__func=__rt.__func,__cb=__rt.__cb,__propagate=__rt.__propagate,__trap=__rt.__trap,__future=__rt.__future,__setEF=__rt.__setEF,__g=__rt.__g;
|
||||
/* 1 */ var common = require("../common");
|
||||
/* 20 */ var fs = require("fs");
|
||||
/* 21 */ var path = require("path");
|
||||
/* 22 */ var url = require("url");
|
||||
/* 23 */ var crypto = require("crypto");
|
||||
/* 24 */ var pfx2pem = require("../../util/certificates/pkcs").pfx2pem;
|
||||
/* 25 */ var Channel = require("../channel");
|
||||
/* 26 */ var async = require("async");
|
||||
/* 29 */ exports.init = function(cli) {
|
||||
/* 31 */ var log = cli.output;
|
||||
/* 33 */ var regions = [{
|
||||
/* 35 */ prompt: "South Central US",
|
||||
/* 36 */ webspace: "southcentraluswebspace",
|
||||
/* 37 */ location: "SouthCentralUS1",
|
||||
/* 38 */ plan: "VirtualDedicatedPlan"
|
||||
/* 40 */ },{
|
||||
/* 41 */ prompt: "North Europe",
|
||||
/* 42 */ webspace: "northeuropewebspace",
|
||||
/* 43 */ location: "NorthEurope1",
|
||||
/* 44 */ plan: "VirtualDedicatedPlan"
|
||||
},];
|
||||
/* 47 */ var regionPrompts = regions.map(function(region) {
|
||||
/* 47 */ return region.prompt;
|
||||
});
|
||||
/* 49 */ function getChannel() {
|
||||
/* 50 */ var pem = cli.category("account").managementCertificate();
|
||||
/* 52 */ var channel = new Channel({
|
||||
/* 53 */ host: "umapi-tc2.rdfetest.dnsdemo4.com",
|
||||
/* 54 */ port: 8443,
|
||||
/* 55 */ key: pem,
|
||||
/* 56 */ cert: pem
|
||||
/* 57 */ }).header("x-ms-version", "2011-02-25");
|
||||
/* 59 */ var proxyString = (((process.env.HTTPS_PROXY || process.env.https_proxy) || process.env.ALL_PROXY) || process.env.all_proxy);
|
||||
/* 65 */ if ((proxyString != undefined)) {
|
||||
/* 66 */ var proxyUrl = url.parse(proxyString);
|
||||
/* 67 */ if (((proxyUrl.protocol !== "http:") && (proxyUrl.protocol !== "https:"))) {
|
||||
/* 70 */ proxyUrl = url.parse(("http://" + proxyString));
|
||||
}
|
||||
;
|
||||
/* 73 */ channel = channel.add({
|
||||
/* 73 */ proxy: proxyUrl
|
||||
});
|
||||
}
|
||||
;
|
||||
/* 76 */ return channel;
|
||||
};
|
||||
/* 80 */ var site = cli.category("site").description("Commands to manage your web sites");
|
||||
/* 84 */ site.command("list").description("List your web sites").option("-s, --subscription <id>", "use the subscription id").execute(function __1(options, _) {
|
||||
var parameters, spaces, sites;
|
||||
var __frame = {
|
||||
name: "__1",
|
||||
line: 87
|
||||
};
|
||||
return __func(_, this, arguments, __1, 1, __frame, function __$__1() {
|
||||
/* 88 */ parameters = {
|
||||
/* 89 */ subscription: cli.category("account").lookupSubscriptionId(options.subscription)
|
||||
};
|
||||
/* 92 */ return site.doSpacesGet(parameters, __cb(_, __frame, 5, 25, function ___(__0, __1) {
|
||||
spaces = __1;
|
||||
/* 93 */ return site.doSitesGet(parameters, __cb(_, __frame, 6, 24, function ___(__0, __2) {
|
||||
sites = __2;
|
||||
/* 95 */ log.table(sites, function(row, site) {
|
||||
/* 96 */ row.cell("Name", site.Name);
|
||||
/* 97 */ row.cell("State", site.State);
|
||||
/* 98 */ row.cell("Host names", clean(site).HostNames);
|
||||
});
|
||||
_();
|
||||
}));
|
||||
}));
|
||||
});
|
||||
});
|
||||
/* 102 */ function choose(data, callback) {
|
||||
/* 103 */ cli.choose(data, function(x) {
|
||||
/* 103 */ callback(undefined, x);
|
||||
});
|
||||
};
|
||||
/* 106 */ site.command("create [name]").description("Create a new web site and local directory").option("-s, --subscription <id>", "use the subscription id").option("--location <location>", "the geographic region to create the website").option("--hostname <hostname>", "custom host name to use").execute(function __2(nameArg, options, _) {
|
||||
var context, cfg, spaces, href, repo;
|
||||
var __frame = {
|
||||
name: "__2",
|
||||
line: 111
|
||||
};
|
||||
return __func(_, this, arguments, __2, 2, __frame, function __$__2() {
|
||||
/* 112 */ context = {
|
||||
/* 113 */ subscription: cli.category("account").lookupSubscriptionId(options.subscription),
|
||||
/* 114 */ site: {
|
||||
/* 115 */ name: nameArg,
|
||||
/* 116 */ webspace: options.location,
|
||||
/* 117 */ hostname: options.hostname
|
||||
}
|
||||
};
|
||||
/* 121 */ cfg = site.readConfig();
|
||||
return (function __$__2(__then) {
|
||||
/* 122 */ if ((cfg === undefined)) {
|
||||
return (function __$__2(__then) {
|
||||
/* 123 */ if ((context.site.name === undefined)) {
|
||||
/* 124 */ log.help("Need a site name");
|
||||
/* 125 */ return cli.prompt("Name: ", __cb(_, __frame, 14, 40, function ___(__0, __1) {
|
||||
/* 125 */ context.site.name = __1;
|
||||
__then();
|
||||
}));
|
||||
}
|
||||
else {
|
||||
/* 127 */ log.verbose("Initializing config with site name:", context.site.name);
|
||||
__then();
|
||||
}
|
||||
;
|
||||
})(function __$__2() {
|
||||
/* 129 */ cfg = {
|
||||
/* 129 */ name: context.site.name
|
||||
};
|
||||
/* 130 */ site.initConfig(cfg);
|
||||
__then();
|
||||
});
|
||||
}
|
||||
else {
|
||||
/* 132 */ if ((context.site.name === undefined)) {
|
||||
/* 133 */ log.verbose("Using existing site name from config:", cfg.name);
|
||||
/* 134 */ context.site.name = cfg.name;
|
||||
}
|
||||
/* 135 */ else {
|
||||
/* 136 */ log.verbose("Updating config with site name:", context.site.name);
|
||||
/* 137 */ cfg.name = context.site.name;
|
||||
/* 138 */ site.writeConfig(cfg);
|
||||
}
|
||||
;
|
||||
__then();
|
||||
}
|
||||
;
|
||||
})(function __$__2() {
|
||||
/* 142 */ return site.doSpacesGet(context, __cb(_, __frame, 31, 25, function ___(__0, __2) {
|
||||
spaces = __2;
|
||||
return (function __$__2(__then) {
|
||||
/* 144 */ if ((spaces.length == 0)) {
|
||||
/* 145 */ log.help("You must create your first web site online.");
|
||||
/* 146 */ log.help("Launching portal.");
|
||||
/* 147 */ href = "https://commonuxfx-bvt01.cloudapp.net/";
|
||||
/* 148 */ common.launchBrowser(href);
|
||||
return _(null);
|
||||
}
|
||||
else {
|
||||
return (function __$__2(__then) {
|
||||
/* 150 */ if ((spaces.length == 1)) {
|
||||
/* 151 */ context.site.webspace = spaces[0].Name;
|
||||
__then();
|
||||
}
|
||||
else {
|
||||
/* 153 */ log.help("Choose a region");
|
||||
/* 154 */ return choose(spaces.map(function(space) {
|
||||
/* 155 */ return space.GeoRegion;
|
||||
}), __cb(_, __frame, 43, 47, function ___(__0, __3) {
|
||||
/* 154 */ context.site.webspace = spaces[__3].Name;
|
||||
__then();
|
||||
}));
|
||||
}
|
||||
;
|
||||
})(__then);
|
||||
}
|
||||
;
|
||||
})(function __$__2() {
|
||||
/* 159 */ log.json("silly", context);
|
||||
/* 161 */ return site.doSitesPost(context, __cb(_, __frame, 50, 12, function __$__2() {
|
||||
/* 162 */ return site.doRepositoryPost(context, __cb(_, __frame, 51, 12, function __$__2() {
|
||||
/* 163 */ return site.doRepositoryGet(context, __cb(_, __frame, 52, 23, function ___(__0, __4) {
|
||||
repo = __4;
|
||||
/* 165 */ log.help("To start adding content to the website, type in the following:");
|
||||
/* 166 */ log.help(" git init");
|
||||
/* 167 */ log.help(" git add .");
|
||||
/* 168 */ log.help(" git commit -m \"initial commit\"");
|
||||
/* 169 */ log.help((((" git remote add azure " + repo) + context.site.name) + ".git"));
|
||||
/* 170 */ log.help(" git push azure master");
|
||||
_();
|
||||
}));
|
||||
}));
|
||||
}));
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
/* 173 */ site.command("portal [name]").description("Opens the portal in a browser to manage your web sites").execute(function __3(name, options, _) {
|
||||
var href;
|
||||
var __frame = {
|
||||
name: "__3",
|
||||
line: 175
|
||||
};
|
||||
return __func(_, this, arguments, __3, 2, __frame, function __$__3() {
|
||||
/* 177 */ href = "https://commonuxfx-bvt01.cloudapp.net/";
|
||||
/* 178 */ if (name) {
|
||||
/* 179 */ href = (((href + "#Workspaces/WebsiteExtension/Website/") + name) + "/dashboard");
|
||||
}
|
||||
;
|
||||
/* 182 */ common.launchBrowser(href);
|
||||
_();
|
||||
});
|
||||
});
|
||||
/* 185 */ site.command("browse [name]").description("Open your web site in a browser.").option("-s, --subscription <id>", "use the subscription id").execute(function __4(name, options, _) {
|
||||
var context, siteData, href;
|
||||
var __frame = {
|
||||
name: "__4",
|
||||
line: 188
|
||||
};
|
||||
return __func(_, this, arguments, __4, 2, __frame, function __$__4() {
|
||||
/* 190 */ context = {
|
||||
/* 191 */ subscription: cli.category("account").lookupSubscriptionId(options.subscription),
|
||||
/* 192 */ site: {
|
||||
/* 193 */ name: name
|
||||
}
|
||||
};
|
||||
/* 196 */ return lookupSiteName(context, __cb(_, __frame, 8, 12, function __$__4() {
|
||||
/* 197 */ return lookupSiteWebSpace(context, __cb(_, __frame, 9, 12, function __$__4() {
|
||||
/* 198 */ return site.doSiteGet(context, __cb(_, __frame, 10, 33, function ___(__0, __1) {
|
||||
/* 198 */ siteData = clean(__1);
|
||||
/* 200 */ href = ("http://" + toArray(siteData.HostNames)[0]);
|
||||
/* 202 */ common.launchBrowser(href);
|
||||
_();
|
||||
}));
|
||||
}));
|
||||
}));
|
||||
});
|
||||
});
|
||||
/* 205 */ site.command("show [name]").description("Show details for a web sites").option("-s, --subscription <id>", "use the subscription id").execute(function __5(name, options, _) {
|
||||
var context, siteData, configData, repositoryData;
|
||||
var __frame = {
|
||||
name: "__5",
|
||||
line: 208
|
||||
};
|
||||
return __func(_, this, arguments, __5, 2, __frame, function __$__5() {
|
||||
/* 209 */ context = {
|
||||
/* 210 */ subscription: cli.category("account").lookupSubscriptionId(options.subscription),
|
||||
/* 211 */ site: {
|
||||
/* 212 */ name: name
|
||||
}
|
||||
};
|
||||
/* 216 */ return lookupSiteName(context, __cb(_, __frame, 8, 12, function __$__5() {
|
||||
/* 217 */ return lookupSiteWebSpace(context, __cb(_, __frame, 9, 12, function __$__5() {
|
||||
/* 219 */ log.info("Showing details for site");
|
||||
/* 220 */ log.verbose("Parameters", context);
|
||||
/* 222 */ return site.doSiteGet(context, __cb(_, __frame, 14, 27, function ___(__0, __1) {
|
||||
siteData = __1;
|
||||
/* 223 */ return site.doSiteConfigGet(context, __cb(_, __frame, 15, 29, function ___(__0, __2) {
|
||||
configData = __2;
|
||||
/* 224 */ return site.doRepositoryGet(context, __cb(_, __frame, 16, 33, function ___(__0, __3) {
|
||||
repositoryData = __3;
|
||||
/* 226 */ logEachData("Site", siteData);
|
||||
/* 227 */ logEachData("Config", configData);
|
||||
/* 228 */ log.data("Repository", clean(repositoryData));
|
||||
_();
|
||||
}));
|
||||
}));
|
||||
}));
|
||||
}));
|
||||
}));
|
||||
});
|
||||
});
|
||||
/* 231 */ function lookupSiteName(context, _) {
|
||||
var cfg;
|
||||
var __frame = {
|
||||
name: "lookupSiteName",
|
||||
line: 231
|
||||
};
|
||||
return __func(_, this, arguments, lookupSiteName, 1, __frame, function __$lookupSiteName() {
|
||||
/* 232 */ if ((context.site.name !== undefined)) {
|
||||
return _(null);
|
||||
}
|
||||
;
|
||||
/* 237 */ cfg = site.readConfig();
|
||||
/* 238 */ if ((cfg !== undefined)) {
|
||||
/* 240 */ context.site.name = cfg.name;
|
||||
return _(null);
|
||||
}
|
||||
;
|
||||
/* 244 */ return cli.prompt("Web site name:", __cb(_, __frame, 13, 28, function ___(__0, __1) {
|
||||
/* 244 */ context.site.name = __1;
|
||||
_();
|
||||
}));
|
||||
});
|
||||
};
|
||||
/* 246 */ site.lookupSiteName = lookupSiteName;
|
||||
/* 248 */ function lookupSiteWebSpace(context, _) {
|
||||
var sites, index;
|
||||
var __frame = {
|
||||
name: "lookupSiteWebSpace",
|
||||
line: 248
|
||||
};
|
||||
return __func(_, this, arguments, lookupSiteWebSpace, 1, __frame, function __$lookupSiteWebSpace() {
|
||||
/* 249 */ log.verbose("Attempting to locate site ", context.site.name);
|
||||
/* 250 */ return site.doSitesGet(context, __cb(_, __frame, 2, 20, function ___(__0, __1) {
|
||||
sites = __1;
|
||||
/* 251 */ for (index in sites) {
|
||||
/* 252 */ if ((sites[index].Name === context.site.name)) {
|
||||
/* 253 */ log.verbose("Site located at ", sites[index].WebSpace);
|
||||
/* 254 */ context.site.webspace = sites[index].WebSpace;
|
||||
}
|
||||
;
|
||||
};
|
||||
/* 257 */ if ((context.site.webspace === undefined)) {
|
||||
/* 258 */ return _(new Error(("Unable to locate site named " + context.site.name)));
|
||||
}
|
||||
;
|
||||
_();
|
||||
}));
|
||||
});
|
||||
};
|
||||
/* 261 */ site.lookupSiteWebSpace = lookupSiteWebSpace;
|
||||
/* 263 */ site.command("delete [name]").description("Delete a web site").option("-s, --subscription <id>", "use the subscription id").execute(function __6(name, options, _) {
|
||||
var context, result;
|
||||
var __frame = {
|
||||
name: "__6",
|
||||
line: 266
|
||||
};
|
||||
return __func(_, this, arguments, __6, 2, __frame, function __$__6() {
|
||||
/* 267 */ context = {
|
||||
/* 268 */ subscription: cli.category("account").lookupSubscriptionId(options.subscription),
|
||||
/* 269 */ site: {
|
||||
/* 270 */ name: name
|
||||
}
|
||||
};
|
||||
/* 274 */ return lookupSiteName(context, __cb(_, __frame, 8, 12, function __$__6() {
|
||||
/* 275 */ return lookupSiteWebSpace(context, __cb(_, __frame, 9, 12, function __$__6() {
|
||||
/* 283 */ return getChannel().path(context.subscription).path("services/webspaces").path(context.site.webspace).path("sites").path(context.site.name).DELETE(__cb(_, __frame, 17, 25, function ___(__0, __1) {
|
||||
result = __1;
|
||||
_();
|
||||
}));
|
||||
}));
|
||||
}));
|
||||
});
|
||||
});
|
||||
/* 287 */ site.command("start [name]").description("Start a web site").option("-s, --subscription <id>", "use the subscription id").execute(function __7(name, options, _) {
|
||||
var context, result;
|
||||
var __frame = {
|
||||
name: "__7",
|
||||
line: 290
|
||||
};
|
||||
return __func(_, this, arguments, __7, 2, __frame, function __$__7() {
|
||||
/* 291 */ context = {
|
||||
/* 292 */ subscription: cli.category("account").lookupSubscriptionId(options.subscription),
|
||||
/* 293 */ site: {
|
||||
/* 294 */ name: name
|
||||
}
|
||||
};
|
||||
/* 298 */ return lookupSiteName(context, __cb(_, __frame, 8, 12, function __$__7() {
|
||||
/* 299 */ return lookupSiteWebSpace(context, __cb(_, __frame, 9, 12, function __$__7() {
|
||||
/* 308 */ return getChannel().path(context.subscription).path("services/webspaces").path(context.site.webspace).path("sites").path(context.site.name).header("Content-Type", "application/xml").POST(function(req) {
|
||||
/* 309 */ req.write("<Site xmlns=\"http://schemas.microsoft.com/windowsazure\">");
|
||||
/* 310 */ req.write("<State>");
|
||||
/* 311 */ req.write("Running");
|
||||
/* 312 */ req.write("</State>");
|
||||
/* 313 */ req.write("</Site>");
|
||||
/* 315 */ req.end();
|
||||
}, __cb(_, __frame, 18, 25, function ___(__0, __1) {
|
||||
result = __1;
|
||||
_();
|
||||
}));
|
||||
}));
|
||||
}));
|
||||
});
|
||||
});
|
||||
/* 320 */ site.command("stop <name>").description("Stop a web site").option("-s, --subscription <id>", "use the subscription id").execute(function __8(name, options, _) {
|
||||
var context, result;
|
||||
var __frame = {
|
||||
name: "__8",
|
||||
line: 323
|
||||
};
|
||||
return __func(_, this, arguments, __8, 2, __frame, function __$__8() {
|
||||
/* 324 */ context = {
|
||||
/* 325 */ subscription: cli.category("account").lookupSubscriptionId(options.subscription),
|
||||
/* 326 */ site: {
|
||||
/* 327 */ name: name
|
||||
}
|
||||
};
|
||||
/* 331 */ return lookupSiteName(context, __cb(_, __frame, 8, 12, function __$__8() {
|
||||
/* 332 */ return lookupSiteWebSpace(context, __cb(_, __frame, 9, 12, function __$__8() {
|
||||
/* 341 */ return getChannel().path(context.subscription).path("services/webspaces").path(context.site.webspace).path("sites").path(context.site.name).header("Content-Type", "application/xml").POST(function(req) {
|
||||
/* 342 */ req.write("<Site xmlns=\"http://schemas.microsoft.com/windowsazure\">");
|
||||
/* 343 */ req.write("<State>");
|
||||
/* 344 */ req.write("Stopped");
|
||||
/* 345 */ req.write("</State>");
|
||||
/* 346 */ req.write("</Site>");
|
||||
/* 348 */ req.end();
|
||||
}, __cb(_, __frame, 18, 25, function ___(__0, __1) {
|
||||
result = __1;
|
||||
_();
|
||||
}));
|
||||
}));
|
||||
}));
|
||||
});
|
||||
});
|
||||
/* 356 */ site.findConfig = function() {
|
||||
/* 357 */ var scanFolder = process.cwd();
|
||||
/* 358 */ while (true) {
|
||||
/* 359 */ var azureFolder = path.join(scanFolder, ".azure");
|
||||
/* 362 */ if ((path.existsSync(azureFolder) && fs.statSync(azureFolder).isDirectory())) {
|
||||
/* 366 */ var files = fs.readdirSync(azureFolder);
|
||||
/* 367 */ files = files.filter(function(filename) {
|
||||
/* 368 */ return endsWith(filename, ".config");
|
||||
});
|
||||
/* 372 */ if ((files.length == 1)) {
|
||||
/* 373 */ var hit = path.join(azureFolder, files[0]);
|
||||
/* 374 */ log.silly("Found local config", hit);
|
||||
/* 375 */ return hit;
|
||||
}
|
||||
;
|
||||
}
|
||||
;
|
||||
/* 380 */ try {
|
||||
/* 381 */ var parentFolder = path.dirname(scanFolder);
|
||||
/* 382 */ if (((parentFolder === scanFolder) || !path.exists(scanFolder))) {
|
||||
/* 383 */ return undefined;
|
||||
}
|
||||
;
|
||||
/* 386 */ } catch (err) {
|
||||
/* 387 */ return undefined;
|
||||
};
|
||||
};
|
||||
};
|
||||
/* 392 */ site.initConfig = function(config) {
|
||||
/* 393 */ var baseFolder = process.cwd();
|
||||
/* 394 */ var azureFolder = path.join(baseFolder, ".azure");
|
||||
/* 395 */ var baseName = crypto.randomBytes(16).toString("hex");
|
||||
/* 396 */ var configPath = path.join(azureFolder, (baseName + ".config"));
|
||||
/* 397 */ if (!path.exists(azureFolder)) {
|
||||
/* 398 */ log.silly("Creating folder", azureFolder);
|
||||
/* 399 */ fs.mkdirSync(azureFolder);
|
||||
}
|
||||
;
|
||||
/* 401 */ log.silly("Writing file", configPath);
|
||||
/* 402 */ var configText = JSON.stringify(config);
|
||||
/* 403 */ fs.writeFileSync(configPath, configText);
|
||||
};
|
||||
/* 406 */ site.readConfig = function() {
|
||||
/* 407 */ var configPath = site.findConfig();
|
||||
/* 408 */ if ((configPath === undefined)) {
|
||||
/* 409 */ log.verbose("No site .azure/*.config file locate at current directory");
|
||||
/* 410 */ return undefined;
|
||||
}
|
||||
;
|
||||
/* 413 */ log.silly("Reading file", configPath);
|
||||
/* 414 */ var configText = fs.readFileSync(configPath);
|
||||
/* 415 */ var config = JSON.parse(configText);
|
||||
/* 416 */ log.json("silly", "Site config", config);
|
||||
/* 417 */ return config;
|
||||
};
|
||||
/* 420 */ site.writeConfig = function(config) {
|
||||
/* 421 */ var configPath = site.findConfig();
|
||||
/* 422 */ if ((configPath === undefined)) {
|
||||
/* 423 */ log.verbose("No site .azure/*.config file locate at current directory");
|
||||
/* 424 */ return undefined;
|
||||
}
|
||||
;
|
||||
/* 426 */ log.silly("Writing file", configPath);
|
||||
/* 427 */ var configText = JSON.stringify(config);
|
||||
/* 428 */ fs.writeFileSync(configPath, configText);
|
||||
};
|
||||
/* 436 */ site.doSitesPost = function(options, callback) {
|
||||
/* 437 */ log.info("Creating a new web site");
|
||||
/* 438 */ log.verbose("Subscription", options.subscription);
|
||||
/* 439 */ log.verbose("Webspace", options.site.webspace);
|
||||
/* 440 */ log.verbose("Site", options.site.name);
|
||||
/* 442 */ getChannel().path(options.subscription).path("services/webspaces").path(options.site.webspace).path("sites/").header("Content-Type", "application/xml").POST(writers.Site.xml(options.site), function(err, result) {
|
||||
/* 451 */ if (err) {
|
||||
/* 452 */ logError("Failed to create site", err);
|
||||
}
|
||||
/* 453 */ else {
|
||||
/* 454 */ log.info("Created website at ", clean(result).HostNames);
|
||||
/* 455 */ log.verbose("Site", clean(result));
|
||||
}
|
||||
;
|
||||
/* 457 */ callback(err, result);
|
||||
});
|
||||
};
|
||||
/* 461 */ site.doRepositoryPost = function(options, callback) {
|
||||
/* 462 */ log.info("Initializing repository");
|
||||
/* 463 */ log.verbose("Subscription", options.subscription);
|
||||
/* 464 */ log.verbose("Webspace", options.site.webspace);
|
||||
/* 465 */ log.verbose("Site", options.site.name);
|
||||
/* 467 */ getChannel().path(options.subscription).path("services/webspaces").path(options.site.webspace).path("sites").path(options.site.name).path("repository").POST("", function(err, result) {
|
||||
/* 477 */ if (err) {
|
||||
/* 478 */ logError("Failed to initialize repository", err);
|
||||
}
|
||||
/* 479 */ else {
|
||||
/* 480 */ log.info("Repository initialized");
|
||||
}
|
||||
;
|
||||
/* 482 */ callback(err, result);
|
||||
});
|
||||
};
|
||||
/* 486 */ site.doSpacesGet = function site_doSpacesGet__9(options, _) {
|
||||
var result;
|
||||
var __frame = {
|
||||
name: "site_doSpacesGet__9",
|
||||
line: 486
|
||||
};
|
||||
return __func(_, this, arguments, site_doSpacesGet__9, 1, __frame, function __$site_doSpacesGet__9() {
|
||||
/* 487 */ log.verbose("Subscription", options.subscription);
|
||||
/* 492 */ return getChannel().path(options.subscription).path("services/webspaces/").GET(__cb(_, __frame, 6, 21, function ___(__0, __1) {
|
||||
result = __1;
|
||||
/* 494 */ log.json("silly", result);
|
||||
/* 495 */ return _(null, toArray(result.WebSpace));
|
||||
}));
|
||||
});
|
||||
};
|
||||
/* 498 */ site.doSitesGet = function site_doSitesGet__10(options, _) {
|
||||
var spaces, channel, result, sites;
|
||||
var __frame = {
|
||||
name: "site_doSitesGet__10",
|
||||
line: 498
|
||||
};
|
||||
return __func(_, this, arguments, site_doSitesGet__10, 1, __frame, function __$site_doSitesGet__10() {
|
||||
/* 499 */ log.verbose("Subscription", options.subscription);
|
||||
/* 501 */ return site.doSpacesGet(options, __cb(_, __frame, 3, 21, function ___(__0, __2) {
|
||||
spaces = __2;
|
||||
/* 505 */ channel = getChannel().path(options.subscription).path("services/webspaces");
|
||||
/* 507 */ return async.map(spaces, function __1(webspace, _) {
|
||||
var __frame = {
|
||||
name: "__1",
|
||||
line: 509
|
||||
};
|
||||
return __func(_, this, arguments, __1, 1, __frame, function __$__1() {
|
||||
/* 513 */ return channel.path(webspace.Name).path("sites/").GET(__cb(_, __frame, 4, 23, _));
|
||||
});
|
||||
}, __cb(_, __frame, 9, 21, function ___(__0, __3) {
|
||||
result = __3;
|
||||
/* 517 */ sites = [];
|
||||
/* 518 */ result.forEach(function(item) {
|
||||
/* 519 */ sites = sites.concat(toArray(item.Site));
|
||||
});
|
||||
/* 521 */ result = sites;
|
||||
/* 523 */ log.json("verbose", sites);
|
||||
/* 524 */ return _(null, sites);
|
||||
}));
|
||||
}));
|
||||
});
|
||||
};
|
||||
/* 527 */ site.doSiteGet = function(options, callback) {
|
||||
/* 528 */ getChannel().path(options.subscription).path("services/webspaces").path(options.site.webspace).path("sites").path(options.site.name).GET(function(err, result) {
|
||||
/* 536 */ if (err) {
|
||||
/* 537 */ logError("Failed to get site info", err);
|
||||
}
|
||||
/* 538 */ else {
|
||||
/* 539 */ log.verbose("Site", clean(result));
|
||||
}
|
||||
;
|
||||
/* 541 */ callback(err, result);
|
||||
});
|
||||
};
|
||||
/* 545 */ site.doSiteConfigGet = function(options, callback) {
|
||||
/* 546 */ getChannel().path(options.subscription).path("services/webspaces").path(options.site.webspace).path("sites").path(options.site.name).path("config").GET(function(err, result) {
|
||||
/* 555 */ if (err) {
|
||||
/* 556 */ logError("Failed to get site config info", err);
|
||||
}
|
||||
/* 557 */ else {
|
||||
/* 558 */ log.verbose("SiteConfig", clean(result));
|
||||
}
|
||||
;
|
||||
/* 560 */ callback(err, result);
|
||||
});
|
||||
};
|
||||
/* 564 */ site.doRepositoryGet = function(options, callback) {
|
||||
/* 565 */ getChannel().path(options.subscription).path("services/webspaces").path(options.site.webspace).path("sites").path(options.site.name).path("repository").GET(function(err, result) {
|
||||
/* 574 */ if (err) {
|
||||
/* 575 */ logError("Failed to get repository info", err);
|
||||
}
|
||||
/* 576 */ else {
|
||||
/* 577 */ log.verbose("Repository", clean(result));
|
||||
}
|
||||
;
|
||||
/* 579 */ callback(err, clean(result));
|
||||
});
|
||||
};
|
||||
/* 587 */ var writers = {
|
||||
/* 588 */ Site: {
|
||||
/* 589 */ xml: function(site) {
|
||||
/* 590 */ return function(req) {
|
||||
/* 591 */ req.write("<Site xmlns=\"http://schemas.microsoft.com/windowsazure\">");
|
||||
/* 592 */ req.write("<HostNames>");
|
||||
/* 593 */ req.write("<string xmlns=\"http://schemas.microsoft.com/2003/10/Serialization/Arrays\">");
|
||||
/* 594 */ req.write((site.name + ".antdir0.antares-test.windows-int.net"));
|
||||
/* 595 */ req.write("</string>");
|
||||
/* 597 */ if (site.hostname) {
|
||||
/* 598 */ req.write("<string xmlns=\"http://schemas.microsoft.com/2003/10/Serialization/Arrays\">");
|
||||
/* 599 */ req.write(site.hostname);
|
||||
/* 600 */ req.write("</string>");
|
||||
}
|
||||
;
|
||||
/* 602 */ req.write("</HostNames>");
|
||||
/* 603 */ req.write("<Name>");
|
||||
/* 604 */ req.write(site.name);
|
||||
/* 605 */ req.write("</Name>");
|
||||
/* 606 */ req.write("</Site>");
|
||||
/* 608 */ req.end();
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
/* 614 */ function clean(source) {
|
||||
/* 615 */ if ((typeof (source) === "string")) {
|
||||
/* 616 */ return source;
|
||||
}
|
||||
;
|
||||
/* 619 */ var target = {
|
||||
};
|
||||
/* 620 */ var hasString = false;
|
||||
/* 621 */ var hasNonString = false;
|
||||
/* 622 */ var stringValue = "";
|
||||
/* 624 */ for (var prop in source) {
|
||||
/* 625 */ if ((prop == "@")) {
|
||||
/* 626 */ continue;
|
||||
}
|
||||
/* 627 */ else {
|
||||
/* 628 */ if ((((prop === "#") || (prop === "string")) || (prop.substring((prop.length - 7)) === ":string"))) {
|
||||
/* 629 */ hasString = true;
|
||||
/* 630 */ stringValue = source[prop];
|
||||
}
|
||||
/* 631 */ else {
|
||||
/* 632 */ hasNonString = true;
|
||||
}
|
||||
;
|
||||
/* 634 */ target[prop] = clean(source[prop]);
|
||||
}
|
||||
;
|
||||
};
|
||||
/* 637 */ if ((hasString && !hasNonString)) {
|
||||
/* 638 */ return stringValue;
|
||||
}
|
||||
;
|
||||
/* 640 */ return target;
|
||||
};
|
||||
/* 643 */ function logEachData(title, data) {
|
||||
/* 644 */ var cleaned = clean(data);
|
||||
/* 645 */ for (var property in cleaned) {
|
||||
/* 646 */ log.data(((title + " ") + property), cleaned[property]);
|
||||
};
|
||||
};
|
||||
/* 650 */ function logError(message, err) {
|
||||
/* 651 */ if ((arguments.length == 1)) {
|
||||
/* 652 */ err = message;
|
||||
/* 653 */ message = undefined;
|
||||
}
|
||||
/* 654 */ else {
|
||||
/* 655 */ log.error(message);
|
||||
}
|
||||
;
|
||||
/* 658 */ if (err) {
|
||||
/* 659 */ if (err.message) {
|
||||
/* 661 */ log.verbose("stack", err.stack);
|
||||
/* 662 */ log.json("silly", err);
|
||||
}
|
||||
/* 664 */ else if (err.Message) {
|
||||
/* 666 */ log.json("verbose", clean(err));
|
||||
}
|
||||
/* 668 */ else {
|
||||
|
||||
}
|
||||
|
||||
;
|
||||
}
|
||||
;
|
||||
};
|
||||
/* 674 */ function isArray(testObject) {
|
||||
/* 675 */ return (((testObject && !(testObject.propertyIsEnumerable("length"))) && (typeof testObject === "object")) && (typeof testObject.length === "number"));
|
||||
};
|
||||
/* 678 */ function toArray(testObject) {
|
||||
/* 679 */ return (isArray(testObject) ? testObject : ((typeof testObject === "undefined") ? [] : [testObject,]));
|
||||
};
|
||||
/* 682 */ function endsWith(str, suffix) {
|
||||
/* 683 */ return (str.indexOf(suffix, (str.length - suffix.length)) !== -1);
|
||||
};
|
||||
};
|
|
@ -0,0 +1,685 @@
|
|||
/**
|
||||
* Copyright 2011 Microsoft Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
//if (!require('streamline/module')(module)) return;
|
||||
|
||||
var common = require('../common');
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var url = require('url');
|
||||
var crypto = require('crypto');
|
||||
var pfx2pem = require('../../util/certificates/pkcs').pfx2pem;
|
||||
var Channel = require('../channel');
|
||||
var async = require('async');
|
||||
|
||||
|
||||
exports.init = function (cli) {
|
||||
|
||||
var log = cli.output;
|
||||
|
||||
var regions = [
|
||||
{
|
||||
prompt: 'South Central US',
|
||||
webspace: 'southcentraluswebspace',
|
||||
location: 'SouthCentralUS1',
|
||||
plan: 'VirtualDedicatedPlan'
|
||||
},
|
||||
{
|
||||
prompt: 'North Europe',
|
||||
webspace: 'northeuropewebspace',
|
||||
location: 'NorthEurope1',
|
||||
plan: 'VirtualDedicatedPlan'
|
||||
},
|
||||
];
|
||||
var regionPrompts = regions.map(function (region) { return region.prompt; });
|
||||
|
||||
function getChannel() {
|
||||
var pem = cli.category('account').managementCertificate();
|
||||
|
||||
var channel = new Channel({
|
||||
host: 'umapi-tc2.rdfetest.dnsdemo4.com',
|
||||
port: 8443,
|
||||
key: pem,
|
||||
cert: pem
|
||||
}).header('x-ms-version', '2011-02-25');
|
||||
|
||||
var proxyString =
|
||||
process.env.HTTPS_PROXY ||
|
||||
process.env.https_proxy ||
|
||||
process.env.ALL_PROXY ||
|
||||
process.env.all_proxy;
|
||||
|
||||
if (proxyString != undefined) {
|
||||
var proxyUrl = url.parse(proxyString);
|
||||
if (proxyUrl.protocol !== 'http:' &&
|
||||
proxyUrl.protocol !== 'https:') {
|
||||
// fall-back parsing support XXX_PROXY=host:port environment variable values
|
||||
proxyUrl = url.parse('http://' + proxyString);
|
||||
}
|
||||
|
||||
channel = channel.add({ proxy: proxyUrl });
|
||||
}
|
||||
|
||||
return channel;
|
||||
}
|
||||
|
||||
|
||||
var site = cli.category('site')
|
||||
.description('Commands to manage your web sites');
|
||||
|
||||
|
||||
site.command('list')
|
||||
.description('List your web sites')
|
||||
.option('-s, --subscription <id>', 'use the subscription id')
|
||||
.execute(function (options, _) {
|
||||
var parameters = {
|
||||
subscription: cli.category('account').lookupSubscriptionId(options.subscription)
|
||||
};
|
||||
|
||||
var spaces = site.doSpacesGet(parameters, _);
|
||||
var sites = site.doSitesGet(parameters, _);
|
||||
|
||||
log.table(sites, function (row, site) {
|
||||
row.cell('Name', site.Name);
|
||||
row.cell('State', site.State);
|
||||
row.cell('Host names', clean(site).HostNames);
|
||||
});
|
||||
});
|
||||
|
||||
function choose(data, callback) {
|
||||
cli.choose(data, function (x) { callback(undefined, x); });
|
||||
}
|
||||
|
||||
site.command('create [name]')
|
||||
.description('Create a new web site and local directory')
|
||||
.option('-s, --subscription <id>', 'use the subscription id')
|
||||
.option('--location <location>', 'the geographic region to create the website')
|
||||
.option('--hostname <hostname>', 'custom host name to use')
|
||||
.execute(function (nameArg, options, _) {
|
||||
var context = {
|
||||
subscription: cli.category('account').lookupSubscriptionId(options.subscription),
|
||||
site: {
|
||||
name: nameArg,
|
||||
webspace: options.location,
|
||||
hostname: options.hostname
|
||||
}
|
||||
};
|
||||
|
||||
var cfg = site.readConfig();
|
||||
if (cfg === undefined) {
|
||||
if (context.site.name === undefined) {
|
||||
log.help('Need a site name');
|
||||
context.site.name = cli.prompt('Name: ', _);
|
||||
} else {
|
||||
log.verbose('Initializing config with site name:', context.site.name);
|
||||
}
|
||||
cfg = { name: context.site.name };
|
||||
site.initConfig(cfg);
|
||||
} else {
|
||||
if (context.site.name === undefined) {
|
||||
log.verbose('Using existing site name from config:', cfg.name);
|
||||
context.site.name = cfg.name;
|
||||
} else {
|
||||
log.verbose('Updating config with site name:', context.site.name);
|
||||
cfg.name = context.site.name;
|
||||
site.writeConfig(cfg);
|
||||
}
|
||||
}
|
||||
|
||||
var spaces = site.doSpacesGet(context, _);
|
||||
|
||||
if (spaces.length == 0) {
|
||||
log.help('You must create your first web site online.');
|
||||
log.help('Launching portal.');
|
||||
var href = 'https://commonuxfx-bvt01.cloudapp.net/';
|
||||
common.launchBrowser(href);
|
||||
return;
|
||||
} else if (spaces.length == 1) {
|
||||
context.site.webspace = spaces[0].Name;
|
||||
} else {
|
||||
log.help('Choose a region');
|
||||
context.site.webspace = spaces[choose(spaces.map(function (space) {
|
||||
return space.GeoRegion;
|
||||
}), _)].Name;
|
||||
}
|
||||
|
||||
log.json('silly', context);
|
||||
|
||||
site.doSitesPost(context, _);
|
||||
site.doRepositoryPost(context, _);
|
||||
var repo = site.doRepositoryGet(context, _);
|
||||
|
||||
log.help('To start adding content to the website, type in the following:');
|
||||
log.help(' git init');
|
||||
log.help(' git add .');
|
||||
log.help(' git commit -m "initial commit"');
|
||||
log.help(' git remote add azure ' + repo + context.site.name + '.git');
|
||||
log.help(' git push azure master');
|
||||
});
|
||||
|
||||
site.command('portal [name]')
|
||||
.description('Opens the portal in a browser to manage your web sites')
|
||||
.execute(function (name, options, _) {
|
||||
|
||||
var href = 'https://commonuxfx-bvt01.cloudapp.net/';
|
||||
if (name) {
|
||||
href = href + '#Workspaces/WebsiteExtension/Website/' + name + '/dashboard';
|
||||
}
|
||||
|
||||
common.launchBrowser(href);
|
||||
});
|
||||
|
||||
site.command('browse [name]')
|
||||
.description('Open your web site in a browser.')
|
||||
.option('-s, --subscription <id>', 'use the subscription id')
|
||||
.execute(function (name, options, _) {
|
||||
|
||||
var context = {
|
||||
subscription: cli.category('account').lookupSubscriptionId(options.subscription),
|
||||
site: {
|
||||
name: name
|
||||
}
|
||||
};
|
||||
lookupSiteName(context, _);
|
||||
lookupSiteWebSpace(context, _);
|
||||
var siteData = clean(site.doSiteGet(context, _));
|
||||
|
||||
var href = 'http://' + toArray(siteData.HostNames)[0];
|
||||
|
||||
common.launchBrowser(href);
|
||||
});
|
||||
|
||||
site.command('show [name]')
|
||||
.description('Show details for a web sites')
|
||||
.option('-s, --subscription <id>', 'use the subscription id')
|
||||
.execute(function (name, options, _) {
|
||||
var context = {
|
||||
subscription: cli.category('account').lookupSubscriptionId(options.subscription),
|
||||
site: {
|
||||
name: name
|
||||
}
|
||||
};
|
||||
|
||||
lookupSiteName(context, _);
|
||||
lookupSiteWebSpace(context, _);
|
||||
|
||||
log.info('Showing details for site');
|
||||
log.verbose('Parameters', context);
|
||||
|
||||
var siteData = site.doSiteGet(context, _);
|
||||
var configData = site.doSiteConfigGet(context, _);
|
||||
var repositoryData = site.doRepositoryGet(context, _);
|
||||
|
||||
logEachData('Site', siteData);
|
||||
logEachData('Config', configData);
|
||||
log.data('Repository', clean(repositoryData));
|
||||
});
|
||||
|
||||
function lookupSiteName(context, _) {
|
||||
if (context.site.name !== undefined) {
|
||||
// no need to read further
|
||||
return;
|
||||
}
|
||||
|
||||
var cfg = site.readConfig();
|
||||
if (cfg !== undefined) {
|
||||
// using the name from current location
|
||||
context.site.name = cfg.name;
|
||||
return;
|
||||
}
|
||||
|
||||
context.site.name = cli.prompt('Web site name:', _);
|
||||
}
|
||||
site.lookupSiteName = lookupSiteName;
|
||||
|
||||
function lookupSiteWebSpace(context, _) {
|
||||
log.verbose('Attempting to locate site ', context.site.name);
|
||||
var sites = site.doSitesGet(context, _);
|
||||
for (var index in sites) {
|
||||
if (sites[index].Name === context.site.name) {
|
||||
log.verbose('Site located at ', sites[index].WebSpace);
|
||||
context.site.webspace = sites[index].WebSpace;
|
||||
}
|
||||
}
|
||||
if (context.site.webspace === undefined) {
|
||||
throw new Error('Unable to locate site named ' + context.site.name);
|
||||
}
|
||||
}
|
||||
site.lookupSiteWebSpace = lookupSiteWebSpace;
|
||||
|
||||
site.command('delete [name]')
|
||||
.description('Delete a web site')
|
||||
.option('-s, --subscription <id>', 'use the subscription id')
|
||||
.execute(function (name, options, _) {
|
||||
var context = {
|
||||
subscription: cli.category('account').lookupSubscriptionId(options.subscription),
|
||||
site: {
|
||||
name: name
|
||||
}
|
||||
};
|
||||
|
||||
lookupSiteName(context, _);
|
||||
lookupSiteWebSpace(context, _);
|
||||
|
||||
var result = getChannel()
|
||||
.path(context.subscription)
|
||||
.path('services/webspaces')
|
||||
.path(context.site.webspace)
|
||||
.path('sites')
|
||||
.path(context.site.name)
|
||||
.DELETE(_);
|
||||
});
|
||||
|
||||
|
||||
site.command('start [name]')
|
||||
.description('Start a web site')
|
||||
.option('-s, --subscription <id>', 'use the subscription id')
|
||||
.execute(function (name, options, _) {
|
||||
var context = {
|
||||
subscription: cli.category('account').lookupSubscriptionId(options.subscription),
|
||||
site: {
|
||||
name: name
|
||||
}
|
||||
};
|
||||
|
||||
lookupSiteName(context, _);
|
||||
lookupSiteWebSpace(context, _);
|
||||
|
||||
var result = getChannel()
|
||||
.path(context.subscription)
|
||||
.path('services/webspaces')
|
||||
.path(context.site.webspace)
|
||||
.path('sites')
|
||||
.path(context.site.name)
|
||||
.header('Content-Type', 'application/xml')
|
||||
.POST(function (req) {
|
||||
req.write('<Site xmlns="http://schemas.microsoft.com/windowsazure">');
|
||||
req.write('<State>');
|
||||
req.write('Running');
|
||||
req.write('</State>');
|
||||
req.write('</Site>');
|
||||
|
||||
req.end();
|
||||
}, _);
|
||||
|
||||
});
|
||||
|
||||
site.command('stop <name>')
|
||||
.description('Stop a web site')
|
||||
.option('-s, --subscription <id>', 'use the subscription id')
|
||||
.execute(function (name, options, _) {
|
||||
var context = {
|
||||
subscription: cli.category('account').lookupSubscriptionId(options.subscription),
|
||||
site: {
|
||||
name: name
|
||||
}
|
||||
};
|
||||
|
||||
lookupSiteName(context, _);
|
||||
lookupSiteWebSpace(context, _);
|
||||
|
||||
var result = getChannel()
|
||||
.path(context.subscription)
|
||||
.path('services/webspaces')
|
||||
.path(context.site.webspace)
|
||||
.path('sites')
|
||||
.path(context.site.name)
|
||||
.header('Content-Type', 'application/xml')
|
||||
.POST(function (req) {
|
||||
req.write('<Site xmlns="http://schemas.microsoft.com/windowsazure">');
|
||||
req.write('<State>');
|
||||
req.write('Stopped');
|
||||
req.write('</State>');
|
||||
req.write('</Site>');
|
||||
|
||||
req.end();
|
||||
}, _);
|
||||
});
|
||||
|
||||
|
||||
/////////////////
|
||||
// config and settings
|
||||
|
||||
site.findConfig = function () {
|
||||
var scanFolder = process.cwd();
|
||||
while (true) {
|
||||
var azureFolder = path.join(scanFolder, '.azure');
|
||||
|
||||
// probe for config if azure folder exists
|
||||
if (path.existsSync(azureFolder) &&
|
||||
fs.statSync(azureFolder).isDirectory()) {
|
||||
|
||||
// find a single .config file
|
||||
var files = fs.readdirSync(azureFolder);
|
||||
files = files.filter(function (filename) {
|
||||
return endsWith(filename, '.config');
|
||||
});
|
||||
|
||||
// return full path if it exists
|
||||
if (files.length == 1) {
|
||||
var hit = path.join(azureFolder, files[0]);
|
||||
log.silly('Found local config', hit);
|
||||
return hit;
|
||||
}
|
||||
}
|
||||
|
||||
// recurse upwards, or return null when that's no longer possible
|
||||
try {
|
||||
var parentFolder = path.dirname(scanFolder);
|
||||
if (parentFolder === scanFolder || !path.exists(scanFolder)) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
site.initConfig = function (config) {
|
||||
var baseFolder = process.cwd();
|
||||
var azureFolder = path.join(baseFolder, '.azure');
|
||||
var baseName = crypto.randomBytes(16).toString('hex');
|
||||
var configPath = path.join(azureFolder, baseName + '.config');
|
||||
if (!path.exists(azureFolder)) {
|
||||
log.silly('Creating folder', azureFolder);
|
||||
fs.mkdirSync(azureFolder);
|
||||
}
|
||||
log.silly('Writing file', configPath);
|
||||
var configText = JSON.stringify(config);
|
||||
fs.writeFileSync(configPath, configText);
|
||||
};
|
||||
|
||||
site.readConfig = function () {
|
||||
var configPath = site.findConfig();
|
||||
if (configPath === undefined) {
|
||||
log.verbose('No site .azure/*.config file locate at current directory');
|
||||
return undefined;
|
||||
}
|
||||
|
||||
log.silly('Reading file', configPath);
|
||||
var configText = fs.readFileSync(configPath);
|
||||
var config = JSON.parse(configText);
|
||||
log.json('silly', 'Site config', config);
|
||||
return config;
|
||||
};
|
||||
|
||||
site.writeConfig = function (config) {
|
||||
var configPath = site.findConfig();
|
||||
if (configPath === undefined) {
|
||||
log.verbose('No site .azure/*.config file locate at current directory');
|
||||
return undefined;
|
||||
}
|
||||
log.silly('Writing file', configPath);
|
||||
var configText = JSON.stringify(config);
|
||||
fs.writeFileSync(configPath, configText);
|
||||
};
|
||||
|
||||
|
||||
|
||||
/////////////////
|
||||
// remote api operations
|
||||
|
||||
site.doSitesPost = function (options, callback) {
|
||||
log.info('Creating a new web site');
|
||||
log.verbose('Subscription', options.subscription);
|
||||
log.verbose('Webspace', options.site.webspace);
|
||||
log.verbose('Site', options.site.name);
|
||||
|
||||
getChannel()
|
||||
.path(options.subscription)
|
||||
.path('services/webspaces')
|
||||
.path(options.site.webspace)
|
||||
.path('sites/')
|
||||
.header('Content-Type', 'application/xml')
|
||||
.POST(
|
||||
writers.Site.xml(options.site),
|
||||
function (err, result) {
|
||||
if (err) {
|
||||
logError('Failed to create site', err);
|
||||
} else {
|
||||
log.info('Created website at ', clean(result).HostNames);
|
||||
log.verbose('Site', clean(result));
|
||||
}
|
||||
callback(err, result);
|
||||
});
|
||||
};
|
||||
|
||||
site.doRepositoryPost = function (options, callback) {
|
||||
log.info('Initializing repository');
|
||||
log.verbose('Subscription', options.subscription);
|
||||
log.verbose('Webspace', options.site.webspace);
|
||||
log.verbose('Site', options.site.name);
|
||||
|
||||
getChannel()
|
||||
.path(options.subscription)
|
||||
.path('services/webspaces')
|
||||
.path(options.site.webspace)
|
||||
.path('sites')
|
||||
.path(options.site.name)
|
||||
.path('repository')
|
||||
.POST(
|
||||
"",
|
||||
function (err, result) {
|
||||
if (err) {
|
||||
logError('Failed to initialize repository', err);
|
||||
} else {
|
||||
log.info('Repository initialized');
|
||||
}
|
||||
callback(err, result);
|
||||
});
|
||||
};
|
||||
|
||||
site.doSpacesGet = function (options, _) {
|
||||
log.verbose('Subscription', options.subscription);
|
||||
|
||||
var result = getChannel()
|
||||
.path(options.subscription)
|
||||
.path('services/webspaces/')
|
||||
.GET(_);
|
||||
|
||||
log.json('silly', result);
|
||||
return toArray(result.WebSpace);
|
||||
};
|
||||
|
||||
site.doSitesGet = function (options, _) {
|
||||
log.verbose('Subscription', options.subscription);
|
||||
|
||||
var spaces = site.doSpacesGet(options, _);
|
||||
|
||||
var channel = getChannel()
|
||||
.path(options.subscription)
|
||||
.path('services/webspaces');
|
||||
|
||||
var result = async.map(
|
||||
spaces,
|
||||
function (webspace, _) {
|
||||
return channel
|
||||
.path(webspace.Name)
|
||||
.path('sites/')
|
||||
.GET(_);
|
||||
},
|
||||
_);
|
||||
|
||||
var sites = [];
|
||||
result.forEach(function (item) {
|
||||
sites = sites.concat(toArray(item.Site));
|
||||
});
|
||||
result = sites;
|
||||
|
||||
log.json('verbose', sites);
|
||||
return sites;
|
||||
};
|
||||
|
||||
site.doSiteGet = function (options, callback) {
|
||||
getChannel()
|
||||
.path(options.subscription)
|
||||
.path('services/webspaces')
|
||||
.path(options.site.webspace)
|
||||
.path('sites')
|
||||
.path(options.site.name)
|
||||
.GET(
|
||||
function (err, result) {
|
||||
if (err) {
|
||||
logError('Failed to get site info', err);
|
||||
} else {
|
||||
log.verbose('Site', clean(result));
|
||||
}
|
||||
callback(err, result);
|
||||
});
|
||||
};
|
||||
|
||||
site.doSiteConfigGet = function (options, callback) {
|
||||
getChannel()
|
||||
.path(options.subscription)
|
||||
.path('services/webspaces')
|
||||
.path(options.site.webspace)
|
||||
.path('sites')
|
||||
.path(options.site.name)
|
||||
.path('config')
|
||||
.GET(
|
||||
function (err, result) {
|
||||
if (err) {
|
||||
logError('Failed to get site config info', err);
|
||||
} else {
|
||||
log.verbose('SiteConfig', clean(result));
|
||||
}
|
||||
callback(err, result);
|
||||
});
|
||||
};
|
||||
|
||||
site.doRepositoryGet = function (options, callback) {
|
||||
getChannel()
|
||||
.path(options.subscription)
|
||||
.path('services/webspaces')
|
||||
.path(options.site.webspace)
|
||||
.path('sites')
|
||||
.path(options.site.name)
|
||||
.path('repository')
|
||||
.GET(
|
||||
function (err, result) {
|
||||
if (err) {
|
||||
logError('Failed to get repository info', err);
|
||||
} else {
|
||||
log.verbose('Repository', clean(result));
|
||||
}
|
||||
callback(err, clean(result));
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/////////////////
|
||||
// helper methods
|
||||
|
||||
var writers = {
|
||||
Site: {
|
||||
xml: function (site) {
|
||||
return function (req) {
|
||||
req.write('<Site xmlns="http://schemas.microsoft.com/windowsazure">');
|
||||
req.write('<HostNames>');
|
||||
req.write('<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/Arrays">');
|
||||
req.write(site.name + '.antdir0.antares-test.windows-int.net');
|
||||
req.write('</string>');
|
||||
|
||||
if (site.hostname) {
|
||||
req.write('<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/Arrays">');
|
||||
req.write(site.hostname);
|
||||
req.write('</string>');
|
||||
}
|
||||
req.write('</HostNames>');
|
||||
req.write('<Name>');
|
||||
req.write(site.name);
|
||||
req.write('</Name>');
|
||||
req.write('</Site>');
|
||||
|
||||
req.end();
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function clean(source) {
|
||||
if (typeof (source) === 'string') {
|
||||
return source;
|
||||
}
|
||||
|
||||
var target = {};
|
||||
var hasString = false;
|
||||
var hasNonString = false;
|
||||
var stringValue = '';
|
||||
|
||||
for (var prop in source) {
|
||||
if (prop == '@') {
|
||||
continue;
|
||||
} else {
|
||||
if (prop === '#' || prop === 'string' || prop.substring(prop.length - 7) === ':string') {
|
||||
hasString = true;
|
||||
stringValue = source[prop];
|
||||
} else {
|
||||
hasNonString = true;
|
||||
}
|
||||
target[prop] = clean(source[prop]);
|
||||
}
|
||||
}
|
||||
if (hasString && !hasNonString) {
|
||||
return stringValue;
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
function logEachData(title, data) {
|
||||
var cleaned = clean(data);
|
||||
for (var property in cleaned) {
|
||||
log.data(title + ' ' + property, cleaned[property]);
|
||||
}
|
||||
}
|
||||
|
||||
function logError(message, err) {
|
||||
if (arguments.length == 1) {
|
||||
err = message;
|
||||
message = undefined;
|
||||
} else {
|
||||
log.error(message);
|
||||
}
|
||||
|
||||
if (err) {
|
||||
if (err.message) {
|
||||
// log.error(err.message);
|
||||
log.verbose('stack', err.stack);
|
||||
log.json('silly', err);
|
||||
}
|
||||
else if (err.Message) {
|
||||
// log.error(err.Message);
|
||||
log.json('verbose', clean(err));
|
||||
}
|
||||
else {
|
||||
// log.error(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function isArray(testObject) {
|
||||
return testObject && !(testObject.propertyIsEnumerable('length')) && typeof testObject === 'object' && typeof testObject.length === 'number';
|
||||
}
|
||||
|
||||
function toArray(testObject) {
|
||||
return isArray(testObject) ? testObject : typeof testObject === 'undefined' ? [] : [testObject];
|
||||
}
|
||||
|
||||
function endsWith(str, suffix) {
|
||||
return str.indexOf(suffix, str.length - suffix.length) !== -1;
|
||||
}
|
||||
};
|
|
@ -1,32 +1,51 @@
|
|||
/**
|
||||
* Copyright 2011 Microsoft Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
var fs = require('fs');
|
||||
var pfx2pem = require('../../util/certificates/pkcs').pfx2pem;
|
||||
var Channel = require('../channel');
|
||||
|
||||
return;
|
||||
|
||||
exports.init = function (waz) {
|
||||
var cli = waz;
|
||||
function getChannel() {
|
||||
var pem = cli.category('account').managementCertificate();
|
||||
|
||||
var pem = pfx2pem(fs.readFileSync('client-x509-rsa.pfx'));
|
||||
var channel = new Channel({
|
||||
host: 'umapi-tc2.rdfetest.dnsdemo4.com',
|
||||
port: 8443,
|
||||
key: pem,
|
||||
cert: pem
|
||||
}).header('x-ms-version', '2011-02-25');
|
||||
|
||||
var channel = new Channel({
|
||||
host: 'umapi-new.rdfetest.dnsdemo4.com',
|
||||
port: 8443,
|
||||
key: pem,
|
||||
cert: pem
|
||||
});
|
||||
return channel;
|
||||
}
|
||||
|
||||
var space = waz.category('space')
|
||||
.description('Commands to manage your Azure web spaces.');
|
||||
.description('Commands to manage your Azure web spaces');
|
||||
|
||||
space.command('show [name]')
|
||||
.description('Show info about a web space.')
|
||||
.option('-i, --subscription <id>', 'use the subscription id')
|
||||
.description('Show info about a web space')
|
||||
.option('-s, --subscription <id>', 'use the subscription id')
|
||||
.action(function (name, options) {
|
||||
|
||||
var subscription = options.subscription || waz.category('account').defaultSubscriptionId();
|
||||
var subscription = cli.category('account').lookupSubscriptionId(options.subscription);
|
||||
|
||||
channel
|
||||
.header('x-ms-version', '2011-02-25')
|
||||
getChannel()
|
||||
.path(subscription)
|
||||
.path('services/webspaces')
|
||||
.path(name || '')
|
||||
|
@ -36,8 +55,8 @@ exports.init = function (waz) {
|
|||
});
|
||||
|
||||
space.command('delete <name>')
|
||||
.description('Kill a web space.')
|
||||
.option('-i, --subscription <id>', 'use the subscription id')
|
||||
.description('Delete a web space')
|
||||
.option('-s, --subscription <id>', 'use the subscription id')
|
||||
.action(function (name, options) {
|
||||
|
||||
var subscription = options.subscription || waz.category('account').defaultSubscriptionId();
|
||||
|
@ -57,15 +76,14 @@ exports.init = function (waz) {
|
|||
|
||||
|
||||
space.command('create <name>')
|
||||
.description('Create a web space.')
|
||||
.option('-i, --subscription <id>', 'use the subscription id')
|
||||
.description('Create a web space')
|
||||
.option('-s, --subscription <id>', 'use the subscription id')
|
||||
.option('-p, --plan <plan>', 'use the plan')
|
||||
.action(function (name, options) {
|
||||
|
||||
var subscription = options.subscription || waz.category('account').defaultSubscriptionId();
|
||||
|
||||
channel
|
||||
.header('x-ms-version', '2011-02-25')
|
||||
getChannel()
|
||||
.path(subscription)
|
||||
.path('services/webspaces/')
|
||||
.header('Content-Type', 'application/xml')
|
||||
|
@ -75,7 +93,7 @@ exports.init = function (waz) {
|
|||
req.write(name);
|
||||
req.write('</Name>');
|
||||
req.write('<Plan>');
|
||||
req.write(options.plan || 'Plan 1');
|
||||
req.write(options.plan || 'VirtualDedicatedPlan');
|
||||
req.write('</Plan>');
|
||||
req.write('<Subscription>');
|
||||
req.write(subscription);
|
||||
|
@ -88,4 +106,4 @@ exports.init = function (waz) {
|
|||
console.log(thing);
|
||||
});
|
||||
});
|
||||
};
|
||||
};
|
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
* Copyright 2011 Microsoft Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
var log = require('winston');
|
||||
var child_process = require('child_process');
|
||||
|
||||
exports.launchBrowser = function(url) {
|
||||
log.info('Launching browser to', url);
|
||||
if (process.env.OS !== undefined) {
|
||||
child_process.exec('start ' + url);
|
||||
} else {
|
||||
child_process.spawn('open', [url]);
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
/**
|
||||
* Copyright 2011 Microsoft Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
var util = require('util');
|
||||
var winston = require('winston');
|
||||
var config = require('winston/lib/winston/config');
|
||||
var common = require('winston/lib/winston/common');
|
||||
|
||||
winston.transports.Console.prototype.log = function (level, msg, meta, callback) {
|
||||
if (this.silent) {
|
||||
return callback(null, true);
|
||||
}
|
||||
|
||||
var self = this, output = common.log({
|
||||
colorize: this.colorize,
|
||||
json: this.json,
|
||||
terse: this.terse,
|
||||
level: level,
|
||||
message: msg,
|
||||
meta: meta,
|
||||
stringify: this.stringify,
|
||||
timestamp: this.timestamp
|
||||
});
|
||||
|
||||
if (level === 'error' || level === 'debug') {
|
||||
util.error(output);
|
||||
}
|
||||
else {
|
||||
util.puts(output);
|
||||
}
|
||||
|
||||
//
|
||||
// Emit the `logged` event immediately because the event loop
|
||||
// will not exit until `process.stdout` has drained anyway.
|
||||
//
|
||||
self.emit('logged');
|
||||
callback(null, true);
|
||||
};
|
||||
|
||||
common.log = function (options) {
|
||||
var timestampFn = typeof options.timestamp === 'function' ? options.timestamp : common.timestamp,
|
||||
timestamp = options.timestamp ? timestampFn() : null,
|
||||
meta = options.meta ? common.clone(options.meta) : null,
|
||||
output;
|
||||
|
||||
if (options.json) {
|
||||
output = meta || {};
|
||||
output.level = options.level;
|
||||
output.message = options.message;
|
||||
|
||||
if (timestamp) {
|
||||
output.timestamp = timestamp;
|
||||
}
|
||||
|
||||
return typeof options.stringify === 'function'
|
||||
? options.stringify(output)
|
||||
: JSON.stringify(output);
|
||||
}
|
||||
|
||||
output = timestamp ? timestamp + ' - ' : '';
|
||||
if (options.terse) {
|
||||
output += options.message;
|
||||
}
|
||||
else {
|
||||
output += options.colorize ? config.colorize(options.level) : options.level;
|
||||
output += (': ' + options.message);
|
||||
}
|
||||
|
||||
if (meta) {
|
||||
if (typeof meta !== 'object') {
|
||||
output += ' ' + meta;
|
||||
}
|
||||
else if (Object.keys(meta).length > 0) {
|
||||
output += ' ' + common.serialize(meta);
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
};
|
|
@ -1,3 +1,18 @@
|
|||
/**
|
||||
* Copyright 2011 Microsoft Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
var util = require('util');
|
||||
var EventEmitter = require( 'events' ).EventEmitter;
|
||||
|
@ -137,7 +152,7 @@ Der.defaultFormatter.on(Der.OBJECT_IDENTIFIER, function(element) {
|
|||
while (scan--) {
|
||||
var octet = element.buffer[offset++];
|
||||
if (octet & 0x80) {
|
||||
cumulative = (cumulative << 7) + (octet & 0x7f);
|
||||
cumulative = (cumulative << 7) + (octet & 0x7f);
|
||||
} else {
|
||||
values.push((cumulative << 7) + octet);
|
||||
cumulative = 0;
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/**
|
||||
* Copyright 2011 Microsoft Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
var der = require('./der');
|
||||
var util = require('util');
|
||||
|
@ -31,39 +46,39 @@ var Pkcs = {
|
|||
},
|
||||
|
||||
pfx2pem: pfx2pem
|
||||
};
|
||||
|
||||
|
||||
function pfx2pem(buffer) {
|
||||
var pem = '';
|
||||
|
||||
var decoder = new PfxDecoder();
|
||||
decoder.on('key', function (key) {
|
||||
pem = pem +
|
||||
'-----BEGIN RSA PRIVATE KEY-----\r\n' +
|
||||
split(key.buffer.toString('base64')) + '\r\n' +
|
||||
'-----END RSA PRIVATE KEY-----\r\n';
|
||||
});
|
||||
decoder.on('cert', function (cert) {
|
||||
pem = pem +
|
||||
'-----BEGIN CERTIFICATE-----\r\n' +
|
||||
split(cert.buffer.toString('base64')) + '\r\n' +
|
||||
'-----END CERTIFICATE-----\r\n';
|
||||
});
|
||||
decoder.parse(buffer);
|
||||
|
||||
function split(text) {
|
||||
var index = 0;
|
||||
var result = '';
|
||||
while (index + 64 < text.length) {
|
||||
result = result + text.substring(index, index + 64) + '\r\n';
|
||||
index += 64;
|
||||
}
|
||||
return result + text.substring(index);
|
||||
}
|
||||
|
||||
return new Buffer(pem);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
function pfx2pem(buffer) {
|
||||
var pem = '';
|
||||
|
||||
var decoder = new PfxDecoder();
|
||||
decoder.on('key', function (key) {
|
||||
pem = pem +
|
||||
'-----BEGIN RSA PRIVATE KEY-----\r\n' +
|
||||
split(key.buffer.toString('base64')) + '\r\n' +
|
||||
'-----END RSA PRIVATE KEY-----\r\n';
|
||||
});
|
||||
decoder.on('cert', function (cert) {
|
||||
pem = pem +
|
||||
'-----BEGIN CERTIFICATE-----\r\n' +
|
||||
split(cert.buffer.toString('base64')) + '\r\n' +
|
||||
'-----END CERTIFICATE-----\r\n';
|
||||
});
|
||||
decoder.parse(buffer);
|
||||
|
||||
function split(text) {
|
||||
var index = 0;
|
||||
var result = '';
|
||||
while (index + 64 < text.length) {
|
||||
result = result + text.substring(index, index + 64) + '\r\n';
|
||||
index += 64;
|
||||
}
|
||||
return result + text.substring(index);
|
||||
}
|
||||
|
||||
return new Buffer(pem);
|
||||
}
|
||||
|
||||
|
||||
function PfxDecoder() {
|
||||
|
@ -169,7 +184,7 @@ function PfxContentInfoDecoder() {
|
|||
assert.equal(elements[0].value, 0);
|
||||
assert.equal(elements[1].tag, der.SEQUENCE);
|
||||
|
||||
encryptedData.parse(elements[1].buffer);
|
||||
encryptedData.parse(elements[1].buffer);
|
||||
} else {
|
||||
throw new Error('Unknown AuthenticatedSafe oid ' + oid);
|
||||
}
|
||||
|
@ -240,7 +255,7 @@ function PfxAlgorithmDecoder() {
|
|||
var key = createPkcs12Info(password, salt, 24, iterations, 1);
|
||||
var iv = createPkcs12Info(password, salt, 8, iterations, 2);
|
||||
return crypto.createDecipheriv('des-ede3-cbc', key.toString('binary'), iv.toString('binary'));
|
||||
};
|
||||
};
|
||||
} else {
|
||||
throw new Error('Unknown algorithmId ' + bagId);
|
||||
}
|
||||
|
@ -275,7 +290,7 @@ function PfxSafeBagDecoder() {
|
|||
elements = generic.parse(elements[1].buffer);
|
||||
|
||||
assert.equal(elements[0].tag, der.SEQUENCE);
|
||||
certBag.parse(elements[0].buffer);
|
||||
certBag.parse(elements[0].buffer);
|
||||
} else {
|
||||
throw new Error('Unknown SafeBag bagId ' + bagId);
|
||||
}
|
||||
|
@ -341,7 +356,7 @@ function PfxCertBagDecoder() {
|
|||
self.emit('cert', {
|
||||
type: certId,
|
||||
buffer: elements[0].buffer
|
||||
});
|
||||
});
|
||||
} else {
|
||||
throw new Error('Unknown CertBag certId ' + certId);
|
||||
}
|
||||
|
@ -363,7 +378,7 @@ function createPkcs12Info(password, salt, keyLength, iterations, id) {
|
|||
|
||||
var passwordString = null;
|
||||
if (password === null || password.length === 0) {
|
||||
passwordString = new Buffer(0);
|
||||
passwordString = new Buffer(0);
|
||||
} else {
|
||||
passwordString = new Buffer(strangeLength(password.length, inputBytes));
|
||||
fillBuffer(password, passwordString);
|
||||
|
|
|
@ -1,61 +0,0 @@
|
|||
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var assert = require('assert');
|
||||
|
||||
exports.init = function (waz) {
|
||||
|
||||
var account = waz.category('account')
|
||||
.description('Manage your account information and publish settings on the current machine.');
|
||||
|
||||
|
||||
account.defaultSubscriptionId = function () {
|
||||
return '51ca709f-562d-4d4f-8efc-46de5833042e';
|
||||
};
|
||||
|
||||
|
||||
account.command('info')
|
||||
.description('Display the current account info.')
|
||||
.action(function () {
|
||||
console.log('Displaying account info');
|
||||
});
|
||||
|
||||
account.command('download')
|
||||
.description('Download or import a publishsettings file for your Azure account.')
|
||||
.action(function (publishSettingsFile) {
|
||||
console.log('importing: ', publishSettingsFile);
|
||||
});
|
||||
|
||||
account.command('import <file>')
|
||||
.description('Download or import a publishsettings file for your Azure account.')
|
||||
.action(function (publishSettingsFile) {
|
||||
console.log('importing: ', publishSettingsFile);
|
||||
|
||||
var wazPath = path.join(process.env.HOME, '.waz');
|
||||
|
||||
var targetFilePath = path.join(wazPath, 'publishSettings.xml');
|
||||
|
||||
fs.stat(wazPath, function (err, stat) {
|
||||
console.log(stat);
|
||||
if (err) {
|
||||
fs.mkdirSync(wazPath, 0766);
|
||||
} else {
|
||||
//assert.equal(stat.isDirectory());
|
||||
}
|
||||
|
||||
// host owin->aspnet
|
||||
// builder.RunAspNet()
|
||||
|
||||
var reader = fs.createReadStream(publishSettingsFile, { flags: 'r' });
|
||||
var writer = fs.createWriteStream(targetFilePath, { flags: 'w', mode: 0600 });
|
||||
reader.pipe(writer);
|
||||
});
|
||||
});
|
||||
|
||||
account.command('clear')
|
||||
.description('Remove any of the stored account info stored by import.')
|
||||
.action(function () {
|
||||
console.log('Clearing account info.');
|
||||
});
|
||||
|
||||
};
|
|
@ -1,15 +0,0 @@
|
|||
|
||||
exports.init = function(waz) {
|
||||
|
||||
waz
|
||||
.command('help [command]')
|
||||
.action(function(name, a, b, c) {
|
||||
if (!waz.categories[name]) {
|
||||
throw new Error("Unknown command name " + name)
|
||||
} else {
|
||||
var args = ['',''].concat(waz.rawArgs.slice(4), ['-h']);
|
||||
waz.categories[name].parse(args);
|
||||
}
|
||||
});
|
||||
|
||||
};
|
|
@ -1,139 +0,0 @@
|
|||
|
||||
var fs = require('fs');
|
||||
var pfx2pem = require('../../util/certificates/pkcs').pfx2pem;
|
||||
var Channel = require('../channel');
|
||||
|
||||
exports.init = function (waz) {
|
||||
|
||||
var pem = pfx2pem(fs.readFileSync('client-x509-rsa.pfx'));
|
||||
|
||||
var channel = new Channel({
|
||||
host: 'umapi-new.rdfetest.dnsdemo4.com',
|
||||
port: 8443,
|
||||
key: pem,
|
||||
cert: pem
|
||||
});
|
||||
|
||||
var site = waz.category('site')
|
||||
.description('Commands to manage your Azure web sites.');
|
||||
|
||||
site.command('show [name]')
|
||||
.description('List your Azure web sites.')
|
||||
.option('-i, --subscription <id>', 'use the subscription id')
|
||||
.action(function (name, options) {
|
||||
|
||||
var subscription = options.subscription || waz.category('account').defaultSubscriptionId();
|
||||
|
||||
channel
|
||||
.header('x-ms-version', '2011-02-25')
|
||||
.path(subscription)
|
||||
.path('services/webspaces/ctpwebspace/sites')
|
||||
.path(name || '')
|
||||
.header('Content-Type', 'application/xml')
|
||||
.GET(function (err, thing) {
|
||||
console.log(thing);
|
||||
});
|
||||
});
|
||||
|
||||
site.command('create <name>')
|
||||
.description('Initialize your Azure web site.')
|
||||
.option('-i, --subscription <id>', 'use the subscription id')
|
||||
.action(function (name, options) {
|
||||
|
||||
var subscription = options.subscription || waz.category('account').defaultSubscriptionId();
|
||||
|
||||
channel
|
||||
.header('x-ms-version', '2011-02-25')
|
||||
.path(subscription)
|
||||
.path('services/webspaces/ctpwebspace/sites/')
|
||||
.header('Content-Type', 'application/xml')
|
||||
.POST(function (req) {
|
||||
req.write('<Site xmlns="http://schemas.microsoft.com/windowsazure">');
|
||||
req.write('<HostNames>');
|
||||
req.write('<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/Arrays">');
|
||||
req.write(name + '.antint0.antares-test.windows-int.net');
|
||||
req.write('</string>');
|
||||
req.write('</HostNames>');
|
||||
req.write('<Name>');
|
||||
req.write(name);
|
||||
req.write('</Name>');
|
||||
req.write('</Site>');
|
||||
|
||||
req.end();
|
||||
},
|
||||
function (err, thing) {
|
||||
console.log(thing);
|
||||
});
|
||||
});
|
||||
|
||||
site.command('delete <name>')
|
||||
.description('Delete a web site.')
|
||||
.option('-i, --subscription <id>', 'use the subscription id')
|
||||
.action(function (name, options) {
|
||||
|
||||
var subscription = options.subscription || waz.category('account').defaultSubscriptionId();
|
||||
|
||||
channel
|
||||
.header('x-ms-version', '2011-02-25')
|
||||
.path(subscription)
|
||||
.path('services/webspaces/ctpwebspace/sites/')
|
||||
.path(name)
|
||||
.header('Content-Type', 'application/xml')
|
||||
.DELETE(function (err, thing) {
|
||||
console.log(thing);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
site.command('start <name>')
|
||||
.description('Delete a web site.')
|
||||
.option('-i, --subscription <id>', 'use the subscription id')
|
||||
.action(function (name, options) {
|
||||
|
||||
var subscription = options.subscription || waz.category('account').defaultSubscriptionId();
|
||||
|
||||
channel
|
||||
.header('x-ms-version', '2011-02-25')
|
||||
.path(subscription)
|
||||
.path('services/webspaces/ctpwebspace/sites/')
|
||||
.path(name)
|
||||
.header('Content-Type', 'application/xml')
|
||||
.POST(function (req) {
|
||||
req.write('<Site xmlns="http://schemas.microsoft.com/windowsazure">');
|
||||
// req.write('<State>');
|
||||
// req.write('Running');
|
||||
// req.write('</State>');
|
||||
req.write('</Site>');
|
||||
|
||||
req.end();
|
||||
}, function (err, thing) {
|
||||
console.log(thing);
|
||||
});
|
||||
});
|
||||
|
||||
site.command('stop <name>')
|
||||
.description('Delete a web site.')
|
||||
.option('-i, --subscription <id>', 'use the subscription id')
|
||||
.action(function (name, options) {
|
||||
|
||||
var subscription = options.subscription || waz.category('account').defaultSubscriptionId();
|
||||
|
||||
channel
|
||||
.header('x-ms-version', '2011-02-25')
|
||||
.path(subscription)
|
||||
.path('services/webspaces/ctpwebspace/sites/')
|
||||
.path(name)
|
||||
.header('Content-Type', 'application/xml')
|
||||
.PUT(function (req) {
|
||||
req.write('<Site xmlns="http://schemas.microsoft.com/windowsazure">');
|
||||
req.write('<State>');
|
||||
req.write('Stopped');
|
||||
req.write('</State>');
|
||||
req.write('</Site>');
|
||||
|
||||
req.end();
|
||||
}, function (err, thing) {
|
||||
console.log(thing);
|
||||
});
|
||||
});
|
||||
};
|
|
@ -1,46 +0,0 @@
|
|||
var commander = require('commander');
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
|
||||
var waz = new commander.Command();
|
||||
|
||||
waz.categories = {};
|
||||
|
||||
waz.category = function(name) {
|
||||
if (!waz.categories[name]) {
|
||||
waz.categories[name] = new commander.Command();
|
||||
}
|
||||
return waz.categories[name];
|
||||
}
|
||||
|
||||
waz
|
||||
.command('*')
|
||||
.action(function(name) {
|
||||
if (!waz.categories[name]) {
|
||||
throw new Error("Unknown command category " + name)
|
||||
} else {
|
||||
if (waz.rawArgs[2] != name) {
|
||||
throw new Error('Commands may not be preceded by options or switches');
|
||||
}
|
||||
var args = [];
|
||||
for(var index = 0; index != waz.rawArgs.length; ++index) {
|
||||
if (index != 2) {
|
||||
args.push(waz.rawArgs[index]);
|
||||
}
|
||||
}
|
||||
waz.categories[name].parse(args);
|
||||
}
|
||||
});
|
||||
|
||||
var commandsPath = path.join(path.dirname(__filename), 'commands');
|
||||
var commandFiles = fs.readdirSync(commandsPath);
|
||||
|
||||
for (var i = 0; i < commandFiles.length; i++) {
|
||||
var commandFile = path.join(commandsPath, commandFiles[i]);
|
||||
if (!fs.statSync(commandFile).isFile()) {
|
||||
continue;
|
||||
}
|
||||
require(commandFile).init(waz);
|
||||
}
|
||||
|
||||
exports = module.exports = waz;
|
10
package.json
10
package.json
|
@ -19,7 +19,13 @@
|
|||
"underscore": ">= 1.3.1",
|
||||
"underscore.string": ">= 2.0.0",
|
||||
"tunnel": ">= 0.0.1",
|
||||
"commander": ">= 0.5.2"
|
||||
"async": ">= 0.1.18",
|
||||
"streamline": "0.2.4",
|
||||
"commander": ">= 0.5.2",
|
||||
"winston": ">= 0.5.10",
|
||||
"colors": "0.x.x",
|
||||
"eyes": "0.x.x",
|
||||
"easy-table": "0.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"mocha": "*",
|
||||
|
@ -39,6 +45,6 @@
|
|||
"extendedtests": "node test/runextendedtests.js"
|
||||
},
|
||||
"bin": {
|
||||
"waz": "./bin/waz"
|
||||
"azure": "./bin/azure"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
|
||||
require('should');
|
||||
var waz = require('./waz');
|
||||
var cli = require('./cli');
|
||||
var capture = require('./util').capture;
|
||||
|
||||
suite('waz', function(){
|
||||
suite('cli', function(){
|
||||
suite('account', function() {
|
||||
|
||||
suite('import', function() {
|
||||
|
||||
test('should launch browser when there is no file name', function(done) {
|
||||
|
||||
var result = capture(function() {
|
||||
waz.parse('node waz.js account import'.split(' '));
|
||||
var result = capture(function() {
|
||||
cli.parse('node cli.js account import'.split(' '));
|
||||
});
|
||||
|
||||
done();
|
|
@ -1,15 +1,15 @@
|
|||
|
||||
require('should');
|
||||
var waz = require('./waz');
|
||||
var capture = require('./util').capture;
|
||||
|
||||
suite('waz', function(){
|
||||
var cli = require('./cli');
|
||||
var capture = require('./util').capture;
|
||||
|
||||
suite('cli', function () {
|
||||
suite('help', function() {
|
||||
|
||||
test('should display help with -h option', function(done) {
|
||||
|
||||
var result = capture(function() {
|
||||
waz.parse('node waz.js -h'.split(' '));
|
||||
var result = capture(function() {
|
||||
cli.parse('node cli.js -h'.split(' '));
|
||||
});
|
||||
|
||||
result.text.should.include('Usage:');
|
|
@ -0,0 +1 @@
|
|||
module.exports = require('../../lib/cli/cli.js');
|
|
@ -1,9 +1,9 @@
|
|||
util/certificates/der.decoder-tests.js
|
||||
util/certificates/der.decoder.pfx.root-tests.js
|
||||
util/certificates/pkcs.filedecoder-tests.js
|
||||
waz/waz.help-tests.js
|
||||
waz/waz.account-tests.js
|
||||
waz/waz.site-tests.js
|
||||
cli/cli.help-tests.js
|
||||
cli/cli.account-tests.js
|
||||
cli/cli.site-tests.js
|
||||
services/blob/blobservice-tests.js
|
||||
services/blob/sharedaccesssignature-tests.js
|
||||
services/blob/sharedkey-tests.js
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
module.exports = require('../../lib/waz/waz.js');
|
Загрузка…
Ссылка в новой задаче