From f54ff2aec56f9fc7dbdb77768ae8b2b88e7bd8bd Mon Sep 17 00:00:00 2001 From: Louis DeJardin Date: Mon, 19 Mar 2012 22:32:31 -0700 Subject: [PATCH] Updating commands Disabling "site deploy" and "space" Moving "site config" utility to "config" Taking out the scaffolding from "site create" --- lib/cli/channel.js | 9 +- .../commands/{account-config.js => config.js} | 2 +- lib/cli/commands/site-deploy.js | 2 + lib/cli/commands/site.js | 1097 ++++++++--------- lib/cli/commands/site_.js | 570 +++++++++ 5 files changed, 1112 insertions(+), 568 deletions(-) rename lib/cli/commands/{account-config.js => config.js} (92%) create mode 100644 lib/cli/commands/site_.js diff --git a/lib/cli/channel.js b/lib/cli/channel.js index 79d04b235..49ee6aaf1 100644 --- a/lib/cli/channel.js +++ b/lib/cli/channel.js @@ -1,5 +1,6 @@ var https = require('https'); +var tunnel = require('tunnel'); var xml2js = require('xml2js'); var log = require('winston'); @@ -48,7 +49,11 @@ 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); @@ -66,7 +71,7 @@ Channel.prototype.send = function (method, data, cb) { } }); res.on('end', function () { - if (++done==1) cb(null, {}); + if (++done == 1) cb(null, {}); }); parser.on('end', function (result) { if (result.Message && result.Code) { diff --git a/lib/cli/commands/account-config.js b/lib/cli/commands/config.js similarity index 92% rename from lib/cli/commands/account-config.js rename to lib/cli/commands/config.js index 019cc44a1..d7544099b 100644 --- a/lib/cli/commands/account-config.js +++ b/lib/cli/commands/config.js @@ -11,7 +11,7 @@ exports.init = function (cli) { var account = cli.category('account'); - var config = account.category('config') + var config = cli.category('config') .description('Manage settings in your config file.'); config.command('list') diff --git a/lib/cli/commands/site-deploy.js b/lib/cli/commands/site-deploy.js index 095d6ec47..57d28e984 100644 --- a/lib/cli/commands/site-deploy.js +++ b/lib/cli/commands/site-deploy.js @@ -3,6 +3,8 @@ var fs = require('fs'); var pfx2pem = require('../../util/certificates/pkcs').pfx2pem; var Channel = require('../channel'); +return; + exports.init = function (cli) { var deploy = cli.category('site').category('deploy') diff --git a/lib/cli/commands/site.js b/lib/cli/commands/site.js index 007ccdc9c..fa086959f 100644 --- a/lib/cli/commands/site.js +++ b/lib/cli/commands/site.js @@ -1,565 +1,532 @@ - -if (!require('streamline/module')(module)) return; - -var fs = require('fs'); -var path = require('path'); -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'); - - 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 ', '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(null,x);}); - } - - site.command('create ') - .description('Create a new web site and local directory.') - .option('-s, --subscription ', 'use the subscription id') - .option('--location ', 'the geographic region to create the website') - .option('--hostname ', 'custom host name to use') - .execute(function (name, options, _) { - var context = { - subscription: cli.category('account').lookupSubscriptionId(options.subscription), - site: { - name: name, - webspace: options.location, - hostname: options.hostname - } - }; - - if (context.site.webspace === undefined) { - log.help('Choose a region'); - context.site.webspace = regions[choose(regionPrompts, _)].webspace; - } - - site.doSitesPost(context, _); - site.doRepositoryPost(context, _); - var repo = site.doRepositoryGet(context, _); - - log.info('Creating local folder', name); - fs.mkdir(name, _); - process.chdir(name); - site.initConfig({name:name}); - - log.help('To start adding content to the website, type in the following:'); - log.help(' cd ' + name); - 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('show ') - .description('Show details for a web sites.') - .option('-s, --subscription ', 'use the subscription id') - .execute(function (name, options, _) { - var context = { - subscription: cli.category('account').lookupSubscriptionId(options.subscription), - site: { - name: name - } - }; - - 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 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.command('delete ') - .description('Delete a web site.') - .option('-s, --subscription ', 'use the subscription id') - .execute(function (name, options, _) { - var context = { - subscription: cli.category('account').lookupSubscriptionId(options.subscription), - site: { - name: name - } - }; - - 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 ') - .description('Start a web site.') - .option('-s, --subscription ', 'use the subscription id') - .execute(function (name, options, _) { - var context = { - subscription: cli.category('account').lookupSubscriptionId(options.subscription), - site: { - name: name - } - }; - - 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(''); - req.write(''); - req.write('Running'); - req.write(''); - req.write(''); - - req.end(); - }, _); - - }); - - site.command('stop ') - .description('Stop a web site.') - .option('-s, --subscription ', 'use the subscription id') - .execute(function (name, options, _) { - var context = { - subscription: cli.category('account').lookupSubscriptionId(options.subscription), - site: { - name: name - } - }; - - 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(''); - req.write(''); - req.write('Stopped'); - req.write(''); - req.write(''); - - 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) && - path.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) { - return path.join(azureFolder, files[0]); - } - } - - // recurse upwards, or return null when that's no longer possible - try { - var parentFolder = path.dirname(scanFolder); - if (parentFolder === scanFolder || !path.exists(scanFolder)) { - return null; - } - } - catch(err) { - return null; - } - } - }; - - 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 null; - } - - 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 null; - } - 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(''); - req.write(''); - req.write(''); - req.write(site.name + '.antdir0.antares-test.windows-int.net'); - req.write(''); - - if (site.hostname) { - req.write(''); - req.write(site.hostname); - req.write(''); - } - req.write(''); - req.write(''); - req.write(site.name); - req.write(''); - req.write(''); - - 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; - } -}; +/*** 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 fs = require("fs"); +/* 5 */ var path = require("path"); +/* 6 */ var url = require("url"); +/* 7 */ var crypto = require("crypto"); +/* 8 */ var pfx2pem = require("../../util/certificates/pkcs").pfx2pem; +/* 9 */ var Channel = require("../channel"); +/* 10 */ var async = require("async"); +/* 12 */ exports.init = function(cli) { +/* 14 */ var log = cli.output; +/* 16 */ var regions = [{ +/* 18 */ prompt: "South Central US", +/* 19 */ webspace: "southcentraluswebspace", +/* 20 */ location: "SouthCentralUS1", +/* 21 */ plan: "VirtualDedicatedPlan" +/* 23 */ },{ +/* 24 */ prompt: "North Europe", +/* 25 */ webspace: "northeuropewebspace", +/* 26 */ location: "NorthEurope1", +/* 27 */ plan: "VirtualDedicatedPlan" + },]; +/* 30 */ var regionPrompts = regions.map(function(region) { +/* 30 */ return region.prompt; + }); +/* 32 */ function getChannel() { +/* 33 */ var pem = cli.category("account").managementCertificate(); +/* 35 */ var channel = new Channel({ +/* 36 */ host: "umapi-tc2.rdfetest.dnsdemo4.com", +/* 37 */ port: 8443, +/* 38 */ key: pem, +/* 39 */ cert: pem +/* 40 */ }).header("x-ms-version", "2011-02-25"); +/* 42 */ var proxyString = (((process.env.HTTPS_PROXY || process.env.https_proxy) || process.env.ALL_PROXY) || process.env.all_proxy); +/* 48 */ if ((proxyString != undefined)) { +/* 49 */ channel = channel.add({ +/* 49 */ proxy: url.parse(proxyString) + }); + } + ; +/* 52 */ return channel; + }; +/* 56 */ var site = cli.category("site").description("Commands to manage your web sites."); +/* 60 */ site.command("list").description("List your web sites.").option("-s, --subscription ", "use the subscription id").execute(function __1(options, _) { + var parameters, spaces, sites; + var __frame = { + name: "__1", + line: 63 + }; + return __func(_, this, arguments, __1, 1, __frame, function __$__1() { +/* 64 */ parameters = { +/* 65 */ subscription: cli.category("account").lookupSubscriptionId(options.subscription) + }; +/* 68 */ return site.doSpacesGet(parameters, __cb(_, __frame, 5, 25, function ___(__0, __1) { + spaces = __1; +/* 69 */ return site.doSitesGet(parameters, __cb(_, __frame, 6, 24, function ___(__0, __2) { + sites = __2; +/* 71 */ log.table(sites, function(row, site) { +/* 72 */ row.cell("Name", site.Name); +/* 73 */ row.cell("State", site.State); +/* 74 */ row.cell("Host names", clean(site).HostNames); + }); + _(); + })); + })); + }); + }); +/* 78 */ function choose(data, callback) { +/* 79 */ cli.choose(data, function(x) { +/* 79 */ callback(null, x); + }); + }; +/* 82 */ site.command("create ").description("Create a new web site and local directory.").option("-s, --subscription ", "use the subscription id").option("--location ", "the geographic region to create the website").option("--hostname ", "custom host name to use").execute(function __2(name, options, _) { + var context, repo; + var __frame = { + name: "__2", + line: 87 + }; + return __func(_, this, arguments, __2, 2, __frame, function __$__2() { +/* 88 */ context = { +/* 89 */ subscription: cli.category("account").lookupSubscriptionId(options.subscription), +/* 90 */ site: { +/* 91 */ name: name, +/* 92 */ webspace: options.location, +/* 93 */ hostname: options.hostname + } + }; + return (function __$__2(__then) { +/* 97 */ if ((context.site.webspace === undefined)) { +/* 98 */ log.help("Choose a region"); +/* 99 */ return choose(regionPrompts, __cb(_, __frame, 12, 48, function ___(__0, __1) { +/* 99 */ context.site.webspace = regions[__1].webspace; + __then(); + })); + } + else { + __then(); + } + ; + })(function __$__2() { +/* 102 */ return site.doSitesPost(context, __cb(_, __frame, 15, 12, function __$__2() { +/* 103 */ return site.doRepositoryPost(context, __cb(_, __frame, 16, 12, function __$__2() { +/* 104 */ return site.doRepositoryGet(context, __cb(_, __frame, 17, 23, function ___(__0, __2) { + repo = __2; +/* 106 */ log.help("To start adding content to the website, type in the following:"); +/* 107 */ log.help(" git init"); +/* 108 */ log.help(" git add ."); +/* 109 */ log.help(" git commit -m \"initial commit\""); +/* 110 */ log.help((((" git remote add azure " + repo) + context.site.name) + ".git")); +/* 111 */ log.help(" git push azure master"); + _(); + })); + })); + })); + }); + }); + }); +/* 114 */ site.command("show ").description("Show details for a web sites.").option("-s, --subscription ", "use the subscription id").execute(function __3(name, options, _) { + var context, siteData, configData, repositoryData; + var __frame = { + name: "__3", + line: 117 + }; + return __func(_, this, arguments, __3, 2, __frame, function __$__3() { +/* 118 */ context = { +/* 119 */ subscription: cli.category("account").lookupSubscriptionId(options.subscription), +/* 120 */ site: { +/* 121 */ name: name + } + }; +/* 125 */ return lookupSiteWebSpace(context, __cb(_, __frame, 8, 12, function __$__3() { +/* 127 */ log.info("Showing details for site"); +/* 128 */ log.verbose("Parameters", context); +/* 130 */ return site.doSiteGet(context, __cb(_, __frame, 13, 27, function ___(__0, __1) { + siteData = __1; +/* 131 */ return site.doSiteConfigGet(context, __cb(_, __frame, 14, 29, function ___(__0, __2) { + configData = __2; +/* 132 */ return site.doRepositoryGet(context, __cb(_, __frame, 15, 33, function ___(__0, __3) { + repositoryData = __3; +/* 134 */ logEachData("Site", siteData); +/* 135 */ logEachData("Config", configData); +/* 136 */ log.data("Repository", clean(repositoryData)); + _(); + })); + })); + })); + })); + }); + }); +/* 139 */ function lookupSiteWebSpace(context, _) { + var sites, index; + var __frame = { + name: "lookupSiteWebSpace", + line: 139 + }; + return __func(_, this, arguments, lookupSiteWebSpace, 1, __frame, function __$lookupSiteWebSpace() { +/* 140 */ log.verbose("Attempting to locate site ", context.site.name); +/* 141 */ return site.doSitesGet(context, __cb(_, __frame, 2, 20, function ___(__0, __1) { + sites = __1; +/* 142 */ for (index in sites) { +/* 143 */ if ((sites[index].Name === context.site.name)) { +/* 144 */ log.verbose("Site located at ", sites[index].WebSpace); +/* 145 */ context.site.webspace = sites[index].WebSpace; + } + ; + }; +/* 148 */ if ((context.site.webspace === undefined)) { +/* 149 */ return _(new Error(("Unable to locate site named " + context.site.name))); + } + ; + _(); + })); + }); + }; +/* 153 */ site.command("delete ").description("Delete a web site.").option("-s, --subscription ", "use the subscription id").execute(function __4(name, options, _) { + var context, result; + var __frame = { + name: "__4", + line: 156 + }; + return __func(_, this, arguments, __4, 2, __frame, function __$__4() { +/* 157 */ context = { +/* 158 */ subscription: cli.category("account").lookupSubscriptionId(options.subscription), +/* 159 */ site: { +/* 160 */ name: name + } + }; +/* 164 */ return lookupSiteWebSpace(context, __cb(_, __frame, 8, 12, function __$__4() { +/* 172 */ return getChannel().path(context.subscription).path("services/webspaces").path(context.site.webspace).path("sites").path(context.site.name).DELETE(__cb(_, __frame, 16, 25, function ___(__0, __1) { + result = __1; + _(); + })); + })); + }); + }); +/* 176 */ site.command("start ").description("Start a web site.").option("-s, --subscription ", "use the subscription id").execute(function __5(name, options, _) { + var context, result; + var __frame = { + name: "__5", + line: 179 + }; + return __func(_, this, arguments, __5, 2, __frame, function __$__5() { +/* 180 */ context = { +/* 181 */ subscription: cli.category("account").lookupSubscriptionId(options.subscription), +/* 182 */ site: { +/* 183 */ name: name + } + }; +/* 187 */ return lookupSiteWebSpace(context, __cb(_, __frame, 8, 12, function __$__5() { +/* 196 */ 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) { +/* 197 */ req.write(""); +/* 198 */ req.write(""); +/* 199 */ req.write("Running"); +/* 200 */ req.write(""); +/* 201 */ req.write(""); +/* 203 */ req.end(); + }, __cb(_, __frame, 17, 25, function ___(__0, __1) { + result = __1; + _(); + })); + })); + }); + }); +/* 208 */ site.command("stop ").description("Stop a web site.").option("-s, --subscription ", "use the subscription id").execute(function __6(name, options, _) { + var context, result; + var __frame = { + name: "__6", + line: 211 + }; + return __func(_, this, arguments, __6, 2, __frame, function __$__6() { +/* 212 */ context = { +/* 213 */ subscription: cli.category("account").lookupSubscriptionId(options.subscription), +/* 214 */ site: { +/* 215 */ name: name + } + }; +/* 219 */ return lookupSiteWebSpace(context, __cb(_, __frame, 8, 12, function __$__6() { +/* 228 */ 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) { +/* 229 */ req.write(""); +/* 230 */ req.write(""); +/* 231 */ req.write("Stopped"); +/* 232 */ req.write(""); +/* 233 */ req.write(""); +/* 235 */ req.end(); + }, __cb(_, __frame, 17, 25, function ___(__0, __1) { + result = __1; + _(); + })); + })); + }); + }); +/* 243 */ site.findConfig = function() { +/* 244 */ var scanFolder = process.cwd(); +/* 245 */ while (true) { +/* 246 */ var azureFolder = path.join(scanFolder, ".azure"); +/* 249 */ if ((path.existsSync(azureFolder) && path.statSync(azureFolder).isDirectory())) { +/* 253 */ var files = fs.readDirSync(azureFolder); +/* 254 */ files = files.filter(function(filename) { +/* 255 */ return endsWith(filename, ".config"); + }); +/* 259 */ if ((files.length == 1)) { +/* 260 */ return path.join(azureFolder, files[0]); + } + ; + } + ; +/* 265 */ try { +/* 266 */ var parentFolder = path.dirname(scanFolder); +/* 267 */ if (((parentFolder === scanFolder) || !path.exists(scanFolder))) { +/* 268 */ return null; + } + ; +/* 271 */ } catch (err) { +/* 272 */ return null; + }; + }; + }; +/* 277 */ site.initConfig = function(config) { +/* 278 */ var baseFolder = process.cwd(); +/* 279 */ var azureFolder = path.join(baseFolder, ".azure"); +/* 280 */ var baseName = crypto.randomBytes(16).toString("hex"); +/* 281 */ var configPath = path.join(azureFolder, (baseName + ".config")); +/* 282 */ if (!path.exists(azureFolder)) { +/* 283 */ log.silly("Creating folder", azureFolder); +/* 284 */ fs.mkdirSync(azureFolder); + } + ; +/* 286 */ log.silly("Writing file", configPath); +/* 287 */ var configText = JSON.stringify(config); +/* 288 */ fs.writeFileSync(configPath, configText); + }; +/* 291 */ site.readConfig = function() { +/* 292 */ var configPath = site.findConfig(); +/* 293 */ if ((configPath === undefined)) { +/* 294 */ log.verbose("No site .azure/*.config file locate at current directory"); +/* 295 */ return null; + } + ; +/* 298 */ log.silly("Reading file", configPath); +/* 299 */ var configText = fs.readFileSync(configPath); +/* 300 */ var config = JSON.parse(configText); +/* 301 */ log.json("silly", "Site config", config); +/* 302 */ return config; + }; +/* 305 */ site.writeConfig = function(config) { +/* 306 */ var configPath = site.findConfig(); +/* 307 */ if ((configPath === undefined)) { +/* 308 */ log.verbose("No site .azure/*.config file locate at current directory"); +/* 309 */ return null; + } + ; +/* 311 */ log.silly("Writing file", configPath); +/* 312 */ var configText = JSON.stringify(config); +/* 313 */ fs.writeFileSync(configPath, configText); + }; +/* 321 */ site.doSitesPost = function(options, callback) { +/* 322 */ log.info("Creating a new web site"); +/* 323 */ log.verbose("Subscription", options.subscription); +/* 324 */ log.verbose("Webspace", options.site.webspace); +/* 325 */ log.verbose("Site", options.site.name); +/* 327 */ 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) { +/* 336 */ if (err) { +/* 337 */ logError("Failed to create site", err); + } +/* 338 */ else { +/* 339 */ log.info("Created website at ", clean(result).HostNames); +/* 340 */ log.verbose("Site", clean(result)); + } + ; +/* 342 */ callback(err, result); + }); + }; +/* 346 */ site.doRepositoryPost = function(options, callback) { +/* 347 */ log.info("Initializing repository"); +/* 348 */ log.verbose("Subscription", options.subscription); +/* 349 */ log.verbose("Webspace", options.site.webspace); +/* 350 */ log.verbose("Site", options.site.name); +/* 352 */ getChannel().path(options.subscription).path("services/webspaces").path(options.site.webspace).path("sites").path(options.site.name).path("repository").POST("", function(err, result) { +/* 362 */ if (err) { +/* 363 */ logError("Failed to initialize repository", err); + } +/* 364 */ else { +/* 365 */ log.info("Repository initialized"); + } + ; +/* 367 */ callback(err, result); + }); + }; +/* 371 */ site.doSpacesGet = function site_doSpacesGet__7(options, _) { + var result; + var __frame = { + name: "site_doSpacesGet__7", + line: 371 + }; + return __func(_, this, arguments, site_doSpacesGet__7, 1, __frame, function __$site_doSpacesGet__7() { +/* 372 */ log.verbose("Subscription", options.subscription); +/* 377 */ return getChannel().path(options.subscription).path("services/webspaces/").GET(__cb(_, __frame, 6, 21, function ___(__0, __1) { + result = __1; +/* 379 */ log.json("silly", result); +/* 380 */ return _(null, toArray(result.WebSpace)); + })); + }); + }; +/* 383 */ site.doSitesGet = function site_doSitesGet__8(options, _) { + var spaces, channel, result, sites; + var __frame = { + name: "site_doSitesGet__8", + line: 383 + }; + return __func(_, this, arguments, site_doSitesGet__8, 1, __frame, function __$site_doSitesGet__8() { +/* 384 */ log.verbose("Subscription", options.subscription); +/* 386 */ return site.doSpacesGet(options, __cb(_, __frame, 3, 21, function ___(__0, __2) { + spaces = __2; +/* 390 */ channel = getChannel().path(options.subscription).path("services/webspaces"); +/* 392 */ return async.map(spaces, function __1(webspace, _) { + var __frame = { + name: "__1", + line: 394 + }; + return __func(_, this, arguments, __1, 1, __frame, function __$__1() { +/* 398 */ return channel.path(webspace.Name).path("sites/").GET(__cb(_, __frame, 4, 23, _)); + }); + }, __cb(_, __frame, 9, 21, function ___(__0, __3) { + result = __3; +/* 402 */ sites = []; +/* 403 */ result.forEach(function(item) { +/* 404 */ sites = sites.concat(toArray(item.Site)); + }); +/* 406 */ result = sites; +/* 408 */ log.json("verbose", sites); +/* 409 */ return _(null, sites); + })); + })); + }); + }; +/* 412 */ site.doSiteGet = function(options, callback) { +/* 413 */ getChannel().path(options.subscription).path("services/webspaces").path(options.site.webspace).path("sites").path(options.site.name).GET(function(err, result) { +/* 421 */ if (err) { +/* 422 */ logError("Failed to get site info", err); + } +/* 423 */ else { +/* 424 */ log.verbose("Site", clean(result)); + } + ; +/* 426 */ callback(err, result); + }); + }; +/* 430 */ site.doSiteConfigGet = function(options, callback) { +/* 431 */ getChannel().path(options.subscription).path("services/webspaces").path(options.site.webspace).path("sites").path(options.site.name).path("config").GET(function(err, result) { +/* 440 */ if (err) { +/* 441 */ logError("Failed to get site config info", err); + } +/* 442 */ else { +/* 443 */ log.verbose("SiteConfig", clean(result)); + } + ; +/* 445 */ callback(err, result); + }); + }; +/* 449 */ site.doRepositoryGet = function(options, callback) { +/* 450 */ getChannel().path(options.subscription).path("services/webspaces").path(options.site.webspace).path("sites").path(options.site.name).path("repository").GET(function(err, result) { +/* 459 */ if (err) { +/* 460 */ logError("Failed to get repository info", err); + } +/* 461 */ else { +/* 462 */ log.verbose("Repository", clean(result)); + } + ; +/* 464 */ callback(err, clean(result)); + }); + }; +/* 472 */ var writers = { +/* 473 */ Site: { +/* 474 */ xml: function(site) { +/* 475 */ return function(req) { +/* 476 */ req.write(""); +/* 477 */ req.write(""); +/* 478 */ req.write(""); +/* 479 */ req.write((site.name + ".antdir0.antares-test.windows-int.net")); +/* 480 */ req.write(""); +/* 482 */ if (site.hostname) { +/* 483 */ req.write(""); +/* 484 */ req.write(site.hostname); +/* 485 */ req.write(""); + } + ; +/* 487 */ req.write(""); +/* 488 */ req.write(""); +/* 489 */ req.write(site.name); +/* 490 */ req.write(""); +/* 491 */ req.write(""); +/* 493 */ req.end(); + }; + } + } + }; +/* 499 */ function clean(source) { +/* 500 */ if ((typeof (source) === "string")) { +/* 501 */ return source; + } + ; +/* 504 */ var target = { + }; +/* 505 */ var hasString = false; +/* 506 */ var hasNonString = false; +/* 507 */ var stringValue = ""; +/* 509 */ for (var prop in source) { +/* 510 */ if ((prop == "@")) { +/* 511 */ continue; + } +/* 512 */ else { +/* 513 */ if ((((prop === "#") || (prop === "string")) || (prop.substring((prop.length - 7)) === ":string"))) { +/* 514 */ hasString = true; +/* 515 */ stringValue = source[prop]; + } +/* 516 */ else { +/* 517 */ hasNonString = true; + } + ; +/* 519 */ target[prop] = clean(source[prop]); + } + ; + }; +/* 522 */ if ((hasString && !hasNonString)) { +/* 523 */ return stringValue; + } + ; +/* 525 */ return target; + }; +/* 528 */ function logEachData(title, data) { +/* 529 */ var cleaned = clean(data); +/* 530 */ for (var property in cleaned) { +/* 531 */ log.data(((title + " ") + property), cleaned[property]); + }; + }; +/* 535 */ function logError(message, err) { +/* 536 */ if ((arguments.length == 1)) { +/* 537 */ err = message; +/* 538 */ message = undefined; + } +/* 539 */ else { +/* 540 */ log.error(message); + } + ; +/* 543 */ if (err) { +/* 544 */ if (err.message) { +/* 545 */ log.error(err.message); +/* 546 */ log.verbose("stack", err.stack); +/* 547 */ log.json("silly", err); + } +/* 549 */ else if (err.Message) { +/* 550 */ log.error(err.Message); +/* 551 */ log.json("verbose", clean(err)); + } +/* 553 */ else { +/* 554 */ log.error(err); + } + + ; + } + ; + }; +/* 559 */ function isArray(testObject) { +/* 560 */ return (((testObject && !(testObject.propertyIsEnumerable("length"))) && (typeof testObject === "object")) && (typeof testObject.length === "number")); + }; +/* 563 */ function toArray(testObject) { +/* 564 */ return (isArray(testObject) ? testObject : ((typeof testObject === "undefined") ? [] : [testObject,])); + }; +/* 567 */ function endsWith(str, suffix) { +/* 568 */ return (str.indexOf(suffix, (str.length - suffix.length)) !== -1); + }; + }; diff --git a/lib/cli/commands/site_.js b/lib/cli/commands/site_.js new file mode 100644 index 000000000..c4fb84f08 --- /dev/null +++ b/lib/cli/commands/site_.js @@ -0,0 +1,570 @@ + +//if (!require('streamline/module')(module)) return; + +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) { + channel = channel.add({ proxy: url.parse(proxyString) }); + } + + 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 ', '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(null, x); }); + } + + site.command('create ') + .description('Create a new web site and local directory.') + .option('-s, --subscription ', 'use the subscription id') + .option('--location ', 'the geographic region to create the website') + .option('--hostname ', 'custom host name to use') + .execute(function (name, options, _) { + var context = { + subscription: cli.category('account').lookupSubscriptionId(options.subscription), + site: { + name: name, + webspace: options.location, + hostname: options.hostname + } + }; + + if (context.site.webspace === undefined) { + log.help('Choose a region'); + context.site.webspace = regions[choose(regionPrompts, _)].webspace; + } + + 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('show ') + .description('Show details for a web sites.') + .option('-s, --subscription ', 'use the subscription id') + .execute(function (name, options, _) { + var context = { + subscription: cli.category('account').lookupSubscriptionId(options.subscription), + site: { + name: name + } + }; + + 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 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.command('delete ') + .description('Delete a web site.') + .option('-s, --subscription ', 'use the subscription id') + .execute(function (name, options, _) { + var context = { + subscription: cli.category('account').lookupSubscriptionId(options.subscription), + site: { + name: name + } + }; + + 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 ') + .description('Start a web site.') + .option('-s, --subscription ', 'use the subscription id') + .execute(function (name, options, _) { + var context = { + subscription: cli.category('account').lookupSubscriptionId(options.subscription), + site: { + name: name + } + }; + + 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(''); + req.write(''); + req.write('Running'); + req.write(''); + req.write(''); + + req.end(); + }, _); + + }); + + site.command('stop ') + .description('Stop a web site.') + .option('-s, --subscription ', 'use the subscription id') + .execute(function (name, options, _) { + var context = { + subscription: cli.category('account').lookupSubscriptionId(options.subscription), + site: { + name: name + } + }; + + 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(''); + req.write(''); + req.write('Stopped'); + req.write(''); + req.write(''); + + 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) && + path.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) { + return path.join(azureFolder, files[0]); + } + } + + // recurse upwards, or return null when that's no longer possible + try { + var parentFolder = path.dirname(scanFolder); + if (parentFolder === scanFolder || !path.exists(scanFolder)) { + return null; + } + } + catch (err) { + return null; + } + } + }; + + 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 null; + } + + 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 null; + } + 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(''); + req.write(''); + req.write(''); + req.write(site.name + '.antdir0.antares-test.windows-int.net'); + req.write(''); + + if (site.hostname) { + req.write(''); + req.write(site.hostname); + req.write(''); + } + req.write(''); + req.write(''); + req.write(site.name); + req.write(''); + req.write(''); + + 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; + } +};