Continued implementation of site command

Taking into account recent changes - multiple regions
Integrating cli review feedback
This commit is contained in:
Louis DeJardin 2012-03-18 15:54:58 -07:00
Родитель 9720f4a2f1
Коммит b907b8471d
6 изменённых файлов: 276 добавлений и 133 удалений

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

@ -11,6 +11,11 @@ var Table = require('easy-table');
var cli = new commander.Command();
cli.output = log;
cli.exit = function (level, message, exitCode) {
log.log(level, message);
process.exit(exitCode);
};
log.reset = function (options) {
log.format = options;
log.level = options.level;
@ -135,7 +140,7 @@ function enableNestedCommands(command) {
}
if (!command.categories[category]) {
log.error("Unknown command", 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) {

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

@ -0,0 +1,41 @@
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 = account.category('config')
.description('Manage settings in your config file.');
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.');
});
};

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

@ -14,13 +14,13 @@ exports.init = function (cli) {
account.command('download')
.description('Download or import a publishsettings file for your Azure account.')
.description('Launch a browser to download your publishsettings file.')
.action(function (publishSettingsFile) {
console.log('downloading: ', publishSettingsFile);
});
account.command('import <file>')
.description('Download or import a publishsettings file for your Azure account.')
.description('Import a publishsettings file for your account.')
.action(function (publishSettingsFile) {
log.info('Importing publish settings file', publishSettingsFile);
@ -41,7 +41,9 @@ exports.init = function (cli) {
function processSettings(settings) {
var attribs = settings.PublishProfile['@'];
var subs = settings.PublishProfile.Subscription;
if (typeof (subs[0]) === 'undefined') {
if (subs === 'undefined') {
subs = [];
} else if (typeof (subs[0]) === 'undefined') {
subs = [subs];
}
@ -51,8 +53,6 @@ exports.init = function (cli) {
else {
for (var index in subs) {
log.info('Found subscription:', subs[index]['@'].Name);
//log.info('Profile applies to subscription');
//log.verbose(' Name:', subs[index]['@'].Name);
log.verbose(' Id:', subs[index]['@'].Id);
}
}
@ -89,7 +89,8 @@ exports.init = function (cli) {
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');
});
});
@ -101,17 +102,25 @@ exports.init = function (cli) {
.option('-s, --subscription <id>', 'use the subscription id as the default')
.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;
account.writeConfig(config);
writeConfig = true;
}
log.table(config, function (row, name) {
row.cell('Setting', name);
row.cell('Value', config[name]);
});
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')
@ -126,6 +135,7 @@ exports.init = function (cli) {
var wazConfigPath = path.join(wazPath, 'config.json');
var config = {};
log.silly('Reading config', wazConfigPath);
if (path.existsSync(wazConfigPath)) {
try {
config = JSON.parse(fs.readFileSync(wazConfigPath));
@ -134,6 +144,7 @@ exports.init = function (cli) {
log.warn('Unable to read settings');
config = {};
}
log.json('silly', config);
}
return config;
};
@ -145,10 +156,56 @@ exports.init = function (cli) {
fs.writeFileSync(wazConfigPath, JSON.stringify(config));
};
account.readPublishSettings = function () {
var wazPath = path.join(process.env.HOME, '.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(process.env.HOME, '.azure');
var wazManagementCertificateFilePath = path.join(wazPath, 'managementCertificate.pem');

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

@ -2,11 +2,27 @@
var fs = require('fs');
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'
},
];
function getChannel() {
var pem = cli.category('account').managementCertificate();
@ -20,79 +36,34 @@ exports.init = function (cli) {
return channel;
}
var site = cli.category('site')
.description('Commands to manage your web sites.');
site.command('sample')
.description('Sample output from json and table')
.action(function () {
var data = [
{ id: 123123, desc: 'Something awesome', price: 1000.00 },
{ id: 245452, desc: 'Very interesting book', price: 11.45 },
{ id: 232323, desc: 'Yet another product', price: 555.55 }
];
log.json(data);
log.table(data, function (row, item) {
row.cell('Product Id', item.id);
row.cell('Description', item.desc);
row.cell('Price, USD', item.price.toFixed(2), row.padLeft);
});
log.json('verbose', data);
log.table('verbose', data, function (row, item) {
row.cell('Product Id', item.id);
row.cell('Description', item.desc);
row.cell('Price, USD', item.price.toFixed(2), row.padLeft);
});
});
site.command('list')
.description('List your web sites.')
.option('-s, --subscription <id>', 'use the subscription id')
.action(function (options) {
var subscription = options.subscription || cli.category('account').defaultSubscriptionId();
log.info('Listing your web sites');
log.verbose('Subscription ', subscription);
getChannel()
.path(subscription)
.path('services/webspaces/northeuropewebspace/sites/')
.GET(function (err, data) {
if (err) {
log.error(err.Message);
log.verbose('Error', clean(err));
}
else {
var parameters = {
subscription: cli.category('account').lookupSubscriptionId(options.subscription)
};
data.Site = isArray(data.Site) ? data.Site : [data.Site];
log.json('verbose', data);
log.table(data.Site, function (row, site) {
row.cell('Name', site.Name);
row.cell('State', site.State);
row.cell('Host names', clean(site).HostNames);
});
// for (var index in data.Site) {
// log.data('Site', {
// Name: data.Site[index].Name,
// State: data.Site[index].State,
// UsageState: data.Site[index].UsageState
// });
// log.verbose('Site', clean(data.Site[index]));
// }
}
site.doSitesGet(
parameters,
function (sites) {
log.table(sites, function (row, site) {
row.cell('Name', site.Name);
row.cell('State', site.State);
row.cell('Host names', clean(site).HostNames);
});
});
});
function isArray(testObject) {
return testObject && !(testObject.propertyIsEnumerable('length')) && typeof testObject === 'object' && typeof testObject.length === 'number';
}
site.command('show <name>')
.description('Show details for a web sites.')
@ -100,7 +71,7 @@ exports.init = function (cli) {
.action(function (name, options) {
var parameters = {
subscription: options.subscription || cli.category('account').defaultSubscriptionId(),
subscription: cli.category('account').lookupSubscriptionId(options.subscription),
site: {
name: name
}
@ -127,29 +98,43 @@ exports.init = function (cli) {
.option('--hostname <hostname>', 'custom host name to use')
.action(function (name, options) {
var parameters = {
subscription: options.subscription || cli.category('account').defaultSubscriptionId(),
site: {
name: name,
location: options.location,
hostname: options.hostname
}
};
log.help('Choose a location');
cli.choose(regions.map(function (x) { return x.prompt; }), function (regionIndex) {
site.doSitesPost(parameters, function () {
site.doRepositoryPost(parameters, function () {
site.doRepositoryGet(parameters, function (repo) {
site.doRepositoryGet(parameters, function (account) {
log.help('To start adding content to the website, type in the following:\n git init\n git add .');
var parameters = {
subscription: cli.category('account').lookupSubscriptionId(options.subscription),
site: {
name: name,
webspace: regions[regionIndex].webspace,
hostname: options.hostname
}
};
site.doSitesPost(parameters, function (err) {
if (err) {
return cli.exit('error', 'Command failed', -1);
}
site.doRepositoryPost(parameters, function (err) {
if (err) {
return cli.exit('error', 'Command failed', -1);
}
site.doRepositoryGet(parameters, function (err, repo) {
if (err) {
return cli.exit('error', 'Command failed', -1);
}
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 http://{UserName}@repository-{Name}.antintdublin.dnsremap.com/git');
log.help(' git remote add azure ' + repo + parameters.site.name + '.git');
log.help(' git push azure master');
cli.exit('info', 'Success', 0);
});
});
});
});
});
site.command('delete <name>')
@ -157,7 +142,8 @@ exports.init = function (cli) {
.option('-s, --subscription <id>', 'use the subscription id')
.action(function (name, options) {
var subscription = options.subscription || cli.category('account').defaultSubscriptionId();
var subscription = cli.category('account').lookupSubscriptionId(options.subscription);
getChannel()
.path(subscription)
@ -174,7 +160,7 @@ exports.init = function (cli) {
.option('-s, --subscription <id>', 'use the subscription id')
.action(function (name, options) {
var subscription = options.subscription || cli.category('account').defaultSubscriptionId();
var subscription = cli.category('account').lookupSubscriptionId(options.subscription);
getChannel()
.path(subscription)
@ -183,9 +169,9 @@ exports.init = function (cli) {
.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('<State>');
req.write('Running');
req.write('</State>');
req.write('</Site>');
req.end();
@ -199,7 +185,8 @@ exports.init = function (cli) {
.option('-s, --subscription <id>', 'use the subscription id')
.action(function (name, options) {
var subscription = options.subscription || cli.category('account').defaultSubscriptionId();
var subscription = cli.category('account').lookupSubscriptionId(options.subscription);
getChannel()
.path(subscription)
@ -223,112 +210,140 @@ exports.init = function (cli) {
/////////////////
// fundamental operations
site.doSitesPost = function (options, done, failed) {
site.doSitesPost = function (options, callback) {
log.info('Creating a new web site');
log.verbose('Subscription', options.subscription);
log.verbose('Parameters', options.site);
log.verbose('Webspace', options.site.webspace);
log.verbose('Site', options.site.name);
getChannel()
.path(options.subscription)
.path('services/webspaces/northeuropewebspace/sites/')
.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) {
log.error('Failed to create site');
log.error(err.Message);
log.verbose('Error', clean(err));
if (failed) failed(err, result);
logError('Failed to create site', err);
} else {
log.info('Created website at ', clean(result).HostNames);
log.verbose('Site', clean(result));
if (done) done(result);
}
callback(err, result);
});
};
site.doRepositoryPost = function (options, done, failed) {
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/northeuropewebspace/sites/')
.path('services/webspaces')
.path(options.site.webspace)
.path('sites')
.path(options.site.name)
.path('repository')
.POST(
"",
function (err, result) {
if (err) {
log.error('Failed to initialize repository');
log.error(err.Message);
log.verbose('Error', clean(err));
if (failed) failed(err, result);
logError('Failed to initialize repository', err);
} else {
log.info('Repository initialized');
if (done) done(result);
}
callback(err, result);
});
};
site.doSiteGet = function (options, done, failed) {
site.doSitesGet = function (options, callback) {
log.verbose('Subscription', options.subscription);
var channel = getChannel()
.path(options.subscription)
.path('services/webspaces');
async.map(
regions,
function (region, result) {
channel
.path(region.webspace)
.path('sites/')
.GET(result);
},
function (err, result) {
if (err) {
logError('Failed to get site info', err);
} else {
var sites = [];
result.forEach(function (item) {
sites = sites.concat(toArray(item.Site));
});
result = sites;
log.json('verbose', result);
}
callback(err, result);
});
};
site.doSiteGet = function (options, callback) {
getChannel()
.path(options.subscription)
.path('services/webspaces/northeuropewebspace/sites')
.path('services/webspaces')
.path(options.site.webspace)
.path('sites')
.path(options.site.name)
.GET(
function (err, result) {
if (err) {
log.error('Failed to get site info');
log.error(err.Message);
log.verbose('Error', clean(err));
if (failed) failed(err, result);
logError('Failed to get site info', err);
} else {
log.verbose('Site', clean(result));
if (done) done(result);
}
callback(err, result);
});
};
site.doSiteConfigGet = function (options, done, failed) {
site.doSiteConfigGet = function (options, callback) {
getChannel()
.path(options.subscription)
.path('services/webspaces/northeuropewebspace/sites')
.path('services/webspaces')
.path(options.site.webspace)
.path('sites')
.path(options.site.name)
.path('config')
.GET(
function (err, result) {
if (err) {
log.error('Failed to get site config info');
log.error(err.Message);
log.verbose('Error', clean(err));
if (failed) failed(err, result);
logError('Failed to get site config info', err);
} else {
log.verbose('SiteConfig', clean(result));
if (done) done(result);
}
callback(err, result);
});
};
site.doRepositoryGet = function (options, done, failed) {
site.doRepositoryGet = function (options, callback) {
getChannel()
.path(options.subscription)
.path('services/webspaces/northeuropewebspace/sites')
.path('services/webspaces')
.path(options.site.webspace)
.path('sites')
.path(options.site.name)
.path('repository')
.GET(
function (err, result) {
if (err) {
log.error('Failed to get repository info');
log.error(err.Message);
log.verbose('Error', clean(err));
if (failed) failed(err, result);
logError('Failed to get repository info', err);
} else {
log.verbose('Repository', clean(result));
if (done) done(result);
}
callback(err, result);
});
};
@ -344,11 +359,8 @@ exports.init = function (cli) {
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>');
// req.write('<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/Arrays">');
// req.write('www.' + site.name + '.antint0.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);
@ -401,4 +413,31 @@ exports.init = function (cli) {
log.data(title + ' ' + property, cleaned[property]);
}
}
function logError(message, err) {
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];
}
};

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

@ -27,7 +27,7 @@ exports.init = function (waz) {
.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);
getChannel()
.header('x-ms-version', '2011-02-25')
@ -79,7 +79,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);

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

@ -19,6 +19,7 @@
"underscore": ">= 1.3.1",
"underscore.string": ">= 2.0.0",
"tunnel": ">= 0.0.1",
"async": ">= 0.1.18",
"commander": ">= 0.5.2",
"winston": ">= 0.5.10",
"colors": "0.x.x",