azure-cli
Version:
Microsoft Azure Cross Platform Command Line tool
671 lines (586 loc) • 19.3 kB
JavaScript
/*** Generated by streamline 0.10.17 (callbacks) - DO NOT EDIT ***//**
* Creates a new VNetUtil object.
*
* @constructor
*/
var azureCommon = require('azure-common');
var xml = azureCommon.xml2js;
var builder = require('xmlbuilder');
var Constants = azureCommon.Constants;
var jsonTransformer = require('./../commands/asm/network/jsontransform/jsontransformer');
var networkManagementMeta = require('./../commands/asm/network/jsontransform/networkmanagementmeta.json');
function VNetUtil() {
this.defaultCidrRange = {
start: 0,
end: 32
};
this.ipv4Pattern = new RegExp(/^([01]?\d\d?|2[0-4]\d|25[0-5])\.([01]?\d\d?|2[0-4]\d|25[0-5])\.([01]?\d\d?|2[0-4]\d|25[0-5])\.([01]?\d\d?|2[0-4]\d|25[0-5])$/);
this.dnsPattern = new RegExp(/^([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,6}$/);
this.privateAddressSpacesInfo = {
'10.0.0.0/8': {},
'172.16.0.0/12': {},
'192.168.0.0/16': {}
};
for (var key in this.privateAddressSpacesInfo) {
var addressSpaceInfo = this.privateAddressSpacesInfo[key];
var parsedIpv4Cidr = this.parseIPv4Cidr(key);
addressSpaceInfo.ipv4Cidr = parsedIpv4Cidr.ipv4Cidr;
addressSpaceInfo.ipv4Octects = parsedIpv4Cidr.octects;
addressSpaceInfo.startCidr = parsedIpv4Cidr.cidr;
addressSpaceInfo.endCidr = this.defaultCidrRange.end;
var networkMaskOctects = this.getNetworkMaskFromCIDR(addressSpaceInfo.startCidr).octects;
var addressSpaceRange = this.getIPRange(addressSpaceInfo.ipv4Octects, networkMaskOctects);
addressSpaceInfo.ipv4StartOctects = addressSpaceRange.start;
addressSpaceInfo.ipv4EndOctects = addressSpaceRange.end;
addressSpaceInfo.ipv4Start = this.octectsToString(addressSpaceInfo.ipv4StartOctects);
addressSpaceInfo.ipv4End = this.octectsToString(addressSpaceInfo.ipv4EndOctects);
}
}
VNetUtil.prototype.setError = function(error) {
return {
error: error
};
};
VNetUtil.prototype.formatName = function(name) {
var fname = '';
if (name) {
fname = '(' + name + ') ';
}
return fname;
};
/**
* Given ip in octects format get the corresponding string format
*
* @return string
*/
VNetUtil.prototype.octectsToString = function(octects) {
return octects.octect0 + '.' + octects.octect1 + '.' +
octects.octect2 + '.' + octects.octect3;
};
/**
* Gets the default address space.
*
* @return object
*/
VNetUtil.prototype.defaultAddressSpaceInfo = function() {
return this.privateAddressSpacesInfo['10.0.0.0/8'];
};
/**
* Given an address space returns the corresponding private address space.
*
* @param object addressSpaceOctects The addressspace as octects
*
* @return object
*/
VNetUtil.prototype.getPrivateAddressSpaceInfo = function(addressSpaceOctects) {
var privateAddressSpaceInfo = null;
for (var key in this.privateAddressSpacesInfo) {
var addressSpaceInfo = this.privateAddressSpacesInfo[key];
if (this.isIPInRange(
addressSpaceInfo.ipv4StartOctects,
addressSpaceInfo.ipv4EndOctects,
addressSpaceOctects)) {
privateAddressSpaceInfo = addressSpaceInfo;
break;
}
}
return privateAddressSpaceInfo;
};
/**
* Parse the given ipv4 address and return it in octet format
*
* @param string address The IPv4 address
* @param string name A name to be included in the error message
*
* @return object
*/
VNetUtil.prototype.parseIPv4 = function(address, name) {
var octects = {
octect0: null,
octect1: null,
octect2: null,
octect3: null
};
var patternMatch = address.match(this.ipv4Pattern);
if (!patternMatch) {
var fname = this.formatName(name);
return this.setError('The IP address ' + fname + address + ' is invalid. ');
}
for (var i = 0; i < 4; i++) {
octects['octect' + i] = parseInt(patternMatch[i + 1], 10);
}
return {
error: null,
octects: octects
};
};
/**
* Parse the given ipv4 address in cidr form and return
* cidr and ipv4 in octet format
*
* @param string address The IPv4 address in cidr format (---.---.---.---/cidr)
* @param string name A name to be included in the error message
*
* @return object
*/
VNetUtil.prototype.parseIPv4Cidr = function(addressSpace, name) {
var cidr = null;
var fname = this.formatName(name);
var invalidIpErr = 'The address space ' + fname + addressSpace + ' is invalid. ';
var parts = addressSpace.split('/');
if (parts.length > 2) {
return this.setError(invalidIpErr);
}
if (parts.length == 2) {
cidr = parseInt(parts[1], 10);
var cidrResult = this.verfiyCIDR(cidr);
if (cidrResult.error) {
return this.setError(invalidIpErr + cidrResult.error);
}
}
var parsedIpResult = this.parseIPv4(parts[0], name);
if (parsedIpResult.error) {
return this.setError(parsedIpResult.error);
}
return {
error: null,
cidr: cidr,
octects: parsedIpResult.octects,
ipv4Cidr: addressSpace
};
};
/**
* Checks the given cidr is correct
*
* @param int value Possible cidr to validate
* @param string name Optional, a name to be included in the error message
* @param object range Optional, range for cidr
*
* @return object
*/
VNetUtil.prototype.verfiyCIDR = function(value, range, name) {
var fname = this.formatName(name);
if (!range) {
range = {
start: this.defaultCidrRange.start,
end: this.defaultCidrRange.end
};
}
if (isNaN(value) || value < range.start || value > range.end) {
return this.setError('cidr ' + fname + 'should be a number in the range [' + range.start + ', ' + range.end + '] ');
}
return {
error: null
};
};
/**
* Given cidr calculate number of hosts
*
* @param int cidr The cidr value
*
* @return object
*/
VNetUtil.prototype.getHostsCountForCIDR = function(cidr) {
var cidrResult = this.verfiyCIDR(cidr);
if (cidrResult.error) {
return this.setError(cidrResult.error);
}
return {
error: null,
hostsCount: Math.pow(2, (32 - cidr))
};
};
/**
* Given number of hosts calculate the appropriate cidr.
*
* @param int hostsCount Number of hosts
*
* @return object
*/
VNetUtil.prototype.getCIDRFromHostsCount = function(hostsCount) {
var _log2 = function(number) {
return Math.log(number) / Math.log(2);
};
var cidr = 32 - Math.ceil(_log2(hostsCount));
if (cidr > this.defaultCidrRange.end) {
cidr = this.defaultCidrRange.end;
}
return cidr;
};
/**
* Calculate the default subnet cidr for the given address space cidr
*
* @param int addressSpaceCidr The address space cidr
*
* @return object
*/
VNetUtil.prototype.getDefaultSubnetCIDRFromAddressSpaceCIDR = function(addressSpaceCidr) {
if (addressSpaceCidr >= 27) {
return this.defaultCidrRange.end;
}
return addressSpaceCidr + 3;
};
/**
* Checks the given ip address is in range
*
* @param object lower The lower bound IP
* @param object upper The upper bound IP
* @param object target The ip to check
*
* @return boolean
*/
VNetUtil.prototype.isIPInRange = function(lower, upper, target) {
return (target.octect0 >= lower.octect0 && target.octect0 <= upper.octect0 &&
target.octect1 >= lower.octect1 && target.octect1 <= upper.octect1 &&
target.octect2 >= lower.octect2 && target.octect2 <= upper.octect2 &&
target.octect3 >= lower.octect3 && target.octect3 <= upper.octect3);
};
/**
* Given CIDR calculate the network mask
*
* @param int cidr The cidr
*
* @return object
*/
VNetUtil.prototype.getNetworkMaskFromCIDR = function(cidr) {
var cidrResult = this.verfiyCIDR(cidr);
if (cidrResult.error) {
return this.setError(cidrResult.error);
}
var octects = {
'octect0': 0xff,
'octect1': 0xff,
'octect2': 0xff,
'octect3': 0xff
};
var i = Math.floor(cidr / 8);
octects['octect' + i] = (0xff << (8 - cidr % 8)) & 0xff;
for (var j = i + 1; j < 4; j++) {
octects['octect' + j] = 0;
}
return {
error: cidrResult.error,
octects: octects
};
};
/**
* Given address space and cidr calculate the range
*
* @param object addressSpace The start ip of address space
* @param object mask The network mask
*
* @return object
*/
VNetUtil.prototype.getIPRange = function(addressSpace, mask) {
return {
'start': {
'octect0': addressSpace.octect0 & mask.octect0,
'octect1': addressSpace.octect1 & mask.octect1,
'octect2': addressSpace.octect2 & mask.octect2,
'octect3': addressSpace.octect3 & mask.octect3
},
'end': {
'octect0': addressSpace.octect0 | (~(mask.octect0) & 0xff),
'octect1': addressSpace.octect1 | (~(mask.octect1) & 0xff),
'octect2': addressSpace.octect2 | (~(mask.octect2) & 0xff),
'octect3': addressSpace.octect3 | (~(mask.octect3) & 0xff)
}
};
};
/**
* Gets a new network configuration.
*
* @return object
*/
VNetUtil.prototype.getNewNetworkConfigObj = function() {
return {
VirtualNetworkConfiguration: {
VirtualNetworkSites: [],
Dns: {
DnsServers: []
}
}
};
};
/**
* Parse given xml configuration to json object
*
* @param string configuration The configuration xml string
*
* @return object
*/
VNetUtil.prototype.getNetworkConfigObj = function(configuration) {
function stripBOM(content) {
if (content.charCodeAt(0) === 0xFEFF || content.charCodeAt(0) === 0xFFFE) {
content = content.slice(1);
}
return content;
}
function attributeToKeyValue(object) {
for (var key in object) {
if (key === Constants.XML_METADATA_MARKER) {
for (var atrKey in object[key]) {
if (object[key].hasOwnProperty(atrKey)) {
var newKey = atrKey[0].toUpperCase() + atrKey.substr(1);
object[newKey] = object[key][atrKey];
}
}
delete object[key];
} else if (typeof(object[key]) == 'object') {
attributeToKeyValue(object[key]);
}
}
}
var networkConfig = {};
// xml2js parser options
var options = {
'explicitCharkey': false,
'trim': false,
'normalize': false,
'normalizeTags': false,
'attrkey': '$',
'charkey': '_',
'explicitArray': false,
'ignoreAttrs': false,
'mergeAttrs': false,
'explicitRoot': false,
'validator': null,
'xmlns': false,
'explicitChildren': false,
'childkey': '$$',
'charsAsChildren': false,
'async': false,
'strict': true
};
var transformer = new jsonTransformer();
xml.parseString(stripBOM(configuration), options, function(err, result) {
transformer.transform(result, networkManagementMeta.getNetworkConfig);
attributeToKeyValue(result.VirtualNetworkConfiguration);
networkConfig = result;
});
return networkConfig;
};
/**
* Checks if cidrs ovelaps
*
* @param string cidr1 cidr in format _._._._/__
*
* @param string cidr2 cidr in format _._._._/__
*
* @return boolean
*/
VNetUtil.prototype.isCidrsOverlapping = function(cidr1, cidr2) {
var parsedCidr1 = this.parseIPv4Cidr(cidr1);
if (parsedCidr1.error) {
throw new Error(parsedCidr1.error);
}
var parsedCidr2 = this.parseIPv4Cidr(cidr2);
if (parsedCidr2.error) {
throw new Error(parsedCidr2.error);
}
var maskObj1 = this.getNetworkMaskFromCIDR(parsedCidr1.cidr);
if (maskObj1.error) {
throw new Error(maskObj1.error);
}
var maskObj2 = this.getNetworkMaskFromCIDR(parsedCidr2.cidr);
if (maskObj2.error) {
throw new Error(maskObj2.error);
}
var ipRangeObj1 = this.getIPRange(parsedCidr1.octects, maskObj1.octects);
var ipRangeObj2 = this.getIPRange(parsedCidr2.octects, maskObj2.octects);
var startIp1 = ipRangeObj1.start;
var startIp2 = ipRangeObj2.start;
var endIp1 = ipRangeObj1.end;
var endIp2 = ipRangeObj2.end;
var overlap1 = false;
var overlap2 = false;
for (var i = 0; i < 4; i++) {
if (startIp1['octect'+i] < endIp2['octect'+i]) {
overlap1 = true;
break;
} else if (startIp1['octect'+i] > endIp2['octect'+i]) {
overlap1 = false;
break;
}
}
for (var j = 0; j < 4; j++) {
if (endIp1['octect'+j] > startIp2['octect'+j]) {
overlap2 = true;
break;
} else if (endIp1['octect'+j] < startIp2['octect'+j]) {
overlap2 = false;
break;
}
}
if (overlap1 && overlap2) {
return true;
} else {
return false;
}
};
/**
* Check if given string is valid domain name
*
* @param string domain The full DNS address
*
* @return object
*/
VNetUtil.prototype.isValidDns = function(domain) {
return this.dnsPattern.test(domain);
};
/**
* Parse given json object to xml configuration string
*
* @param string configuration The configuration json object
*
* @return xml string
*/
VNetUtil.prototype.getNetworkConfigXml = function(configurationObj) {
var root = builder.create('NetworkConfiguration');
root.att('xmlns:xsd', 'http://www.w3.org/2001/XMLSchema');
root.att('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
root.att('xmlns', 'http://schemas.microsoft.com/ServiceHosting/2011/07/NetworkConfiguration');
var eleVNet = root.ele('VirtualNetworkConfiguration');
var eleDns = eleVNet.ele('Dns');
var eleDnsServers = eleDns.ele('DnsServers');
if (configurationObj.VirtualNetworkConfiguration.Dns.DnsServers instanceof Array) {
for (var i = 0; i < configurationObj.VirtualNetworkConfiguration.Dns.DnsServers.length; i++) {
var dnsServer = configurationObj.VirtualNetworkConfiguration.Dns.DnsServers[i];
var eleServer = eleDnsServers.ele('DnsServer');
eleServer.att('name', dnsServer.Name);
eleServer.att('IPAddress', dnsServer.IPAddress);
}
}
var eleLocalSites = eleDns.insertAfter('LocalNetworkSites');
if (configurationObj.VirtualNetworkConfiguration.LocalNetworkSites instanceof Array) {
for (var l = 0; l < configurationObj.VirtualNetworkConfiguration.LocalNetworkSites.length; l++) {
var localSite = configurationObj.VirtualNetworkConfiguration.LocalNetworkSites[l];
var eleLocalSite = eleLocalSites.ele('LocalNetworkSite');
eleLocalSite.att('name', localSite.Name);
if (localSite.VPNGatewayAddress) {
eleLocalSite.ele('VPNGatewayAddress').text(localSite.VPNGatewayAddress);
}
// AddressSpace
var eleAddressSpace = eleLocalSite.ele('AddressSpace');
for (var m = 0; m < localSite.AddressSpace.length; m++) {
var elePrefix = eleAddressSpace.ele('AddressPrefix');
elePrefix.text(localSite.AddressSpace[m]);
}
}
}
var eleSites = eleLocalSites.insertAfter('VirtualNetworkSites');
for (var k = 0; k < configurationObj.VirtualNetworkConfiguration.VirtualNetworkSites.length; k++) {
var site = configurationObj.VirtualNetworkConfiguration.VirtualNetworkSites[k];
var eleSite = eleSites.ele('VirtualNetworkSite');
eleSite.att('name', site.Name);
if (site.AffinityGroup) {
eleSite.att('AffinityGroup', site.AffinityGroup);
}
if (site.Location) {
eleSite.att('Location', site.Location);
}
// AddressSpace
var eleSiteAddressSpace = eleSite.ele('AddressSpace');
for (var j = 0; j < site.AddressSpace.length; j++) {
var eleAdrPrefix = eleSiteAddressSpace.ele('AddressPrefix');
eleAdrPrefix.text(site.AddressSpace[j]);
}
// Subnets
if (site.Subnets && site.Subnets.length > 0) {
var eleSubnets = eleSite.ele('Subnets');
for (var p = 0; p < site.Subnets.length; p++) {
var subnet = site.Subnets[p];
var eleSubnet = eleSubnets.ele('Subnet');
eleSubnet.att('name', subnet.Name);
var eleSubnetAddrPrefix = eleSubnet.ele('AddressPrefix');
eleSubnetAddrPrefix.text(subnet.AddressPrefix);
}
}
// DnsServersRef
if (site.DnsServersRef && site.DnsServersRef.length > 0) {
var eleDnsServersRef = eleSite.ele('DnsServersRef');
for (var n = 0; n < site.DnsServersRef.length; n++) {
var serverRef = site.DnsServersRef[n];
var eleServerRef = eleDnsServersRef.ele('DnsServerRef');
eleServerRef.att('name', serverRef.Name);
}
}
// Gateway
if (site.Gateway) {
var eleGateway = eleSite.ele('Gateway');
if (site.Gateway.ConnectionsToLocalNetwork && site.Gateway.ConnectionsToLocalNetwork.length > 0) {
var eleConnectionsToLocalNetwork = eleGateway.ele('ConnectionsToLocalNetwork');
for (var a = 0; a < site.Gateway.ConnectionsToLocalNetwork.length; a++) {
var localNetworkSiteRef = site.Gateway.ConnectionsToLocalNetwork[a];
var eleLocalNetworkSiteRef = eleConnectionsToLocalNetwork.ele('LocalNetworkSiteRef');
eleLocalNetworkSiteRef.att('name', localNetworkSiteRef.Name);
eleLocalNetworkSiteRef.ele('Connection').att('type', localNetworkSiteRef.Connection.Type);
}
}
}
}
var xmlString = root.end({
pretty: true,
indent: ' ',
newline: '\n'
});
return xmlString;
};
VNetUtil.prototype.ensureRequiredParams = function (param, paramName, dependentParams) {
var result = {
error: null,
emptyParams: null,
requiredParams: null,
allEmpty: false
};
var arrayToString = function(array, combine) {
var arrayAsString = null;
if (array.length == 1) {
arrayAsString = array[0];
} else if (array.length > 1) {
var last = ' ' + combine + ' ' + array.pop();
arrayAsString = array.join(',');
arrayAsString += last;
}
return arrayAsString;
};
var emptyParams = [];
var requiresParams = [];
if (typeof param != 'undefined') {
for (var key in dependentParams) {
if (typeof dependentParams[key] == 'undefined') {
emptyParams.push(key);
requiresParams.push(key);
} else if (typeof dependentParams[key] == 'object') {
var emptyParams2 = [];
var requiresParams2 = [];
for (var key2 in dependentParams[key]) {
requiresParams2.push(key2);
if (typeof dependentParams[key][key2] == 'undefined') {
emptyParams2.push(key2);
}
}
if (emptyParams2.length == requiresParams2.length) {
emptyParams.push('"' + arrayToString(emptyParams2, 'or') + '"');
}
requiresParams.push('"' + arrayToString(requiresParams2, 'or') + '"');
} else {
requiresParams.push(key);
}
}
}
if (emptyParams.length > 0) {
var singleEmpty = emptyParams.length == 1;
var singleRequired = requiresParams.length == 1;
result.allEmpty = (emptyParams.length == requiresParams.length);
result.emptyParams = arrayToString(emptyParams, 'and');
result.requiredParams = arrayToString(requiresParams, 'and');
result.error = 'The parameter(s) ' + result.requiredParams +
(singleRequired ? ' is' : ' are') +
' required when ' + paramName + ' is specified but ' +
(result.allEmpty ? 'none of them present' :
('the parameter(s) ' + result.emptyParams + (singleEmpty ? ' is' : ' are') + ' not present'));
}
return result;
};
module.exports = VNetUtil;