Merge pull request #139 from loudej/winston

Winston output and command implementation
This commit is contained in:
Louis DeJardin 2012-03-22 15:35:04 -07:00
Родитель 59a47d8c12 4849da8358
Коммит 50db13800a
29 изменённых файлов: 2554 добавлений и 352 удалений

7
bin/azure Executable file
Просмотреть файл

@ -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']);
}

7
bin/azure.js Normal file
Просмотреть файл

@ -0,0 +1,7 @@
var cli = require('../lib/cli/cli');
cli.parse(process.argv);
if (cli.args.length == 0) {
cli.parse(['', '', '-h']);
}

Просмотреть файл

@ -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') {

373
lib/cli/cli.js Normal file
Просмотреть файл

@ -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;

241
lib/cli/commands/account.js Normal file
Просмотреть файл

@ -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');
}
};

118
lib/cli/commands/config.js Normal file
Просмотреть файл

@ -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');
}
};

33
lib/cli/commands/help.js Normal file
Просмотреть файл

@ -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 () { });
};

671
lib/cli/commands/site.js Normal file
Просмотреть файл

@ -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);
};
};

685
lib/cli/commands/site_.js Normal file
Просмотреть файл

@ -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);
});
});
};
};

28
lib/cli/common.js Normal file
Просмотреть файл

@ -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]);
}
};

92
lib/cli/patch-winston.js Normal file
Просмотреть файл

@ -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;

Просмотреть файл

@ -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:');

1
test/cli/cli.js Normal file
Просмотреть файл

@ -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');