UNPKG

azure-cli

Version:

Microsoft Azure Cross Platform Command Line tool

263 lines (228 loc) 8.67 kB
/** * Copyright (c) Microsoft. All rights reserved. * * 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. */ 'use strict'; var _ = require('underscore'); var EventEmitter = require('events').EventEmitter; var util = require('util'); var adalAuth = require('../authentication/adalAuth'); var AccessTokenCloudCredentials = require('../authentication/accessTokenCloudCredentials'); var azureCommon = require('azure-common'); var log = require('../logging'); var utils = require('../utils'); var $ = utils.getLocaleString; function Subscription(subscriptionData, environment) { this.id = subscriptionData.id; if (subscriptionData.managementCertificate) { this.managementCertificate = subscriptionData.managementCertificate; } this.values = {}; _.extend(this, _.omit(subscriptionData, 'environmentName', 'username')); this.isDefault = this.isDefault || false; this.environment = environment; if (_.isUndefined(subscriptionData.user)) { if (subscriptionData.username) { this.user = { name: subscriptionData.username, tenant: null, type: 'user' }; } } this.registeredProviders = subscriptionData.registeredProviders || []; } util.inherits(Subscription, EventEmitter); function getField(fieldName) { /*jshint validthis: true */ return this.values[fieldName] || this.environment[fieldName]; } function setField(fieldName, value) { /*jshint validthis: true */ this.values[fieldName] = value; } function descriptorForField(fieldName) { return { enumerable: true, configurable: false, get: function () { return getField.call(this, fieldName); }, set: function (value) { return setField.call(this, fieldName, value); } }; } function descriptorsFor() { return _.object(arguments, _.map(arguments, descriptorForField)); } Object.defineProperties(Subscription.prototype, descriptorsFor( 'managementEndpointUrl', 'resourceManagerEndpointUrl', 'sqlManagementEndpointUrl', 'hostNameSuffix', 'sqlServerHostnameSuffix', 'activeDirectoryEndpointUrl', 'storageEndpoint', 'galleryEndpointUrl', 'activeDirectoryGraphResourceId' ) ); _.extend(Subscription.prototype, { /** * Update this subscription object with values from the * given subscription. * * @param {object} subscription Other subscription object to pull values from. * * @returns {object} this */ updateFrom: function (subscription) { _.extend(this.values, subscription.values); if (subscription.user) { this.user = subscription.user; } if (subscription.managementCertificate) { this.managementCertificate = subscription.managementCertificate; } return this; }, exportManagementCertificate: function (outputFile) { if (!this.managementCertificate) { throw new Error($('This subscription does not use a management certificate')); } var pemData = this.managementCertificate.key + this.managementCertificate.cert; utils.writeFileSyncMode(outputFile, pemData, 'utf8'); }, _createCredentials: function (resourceId) { var token; var authConfig = this.environment.getAuthConfig(this.tenantId, resourceId); if (this.user) { switch (this.user.type) { case 'user': token = new adalAuth.AdalAccessToken(authConfig, this.user.name); break; case 'servicePrincipal': authConfig.tenantId = this.user.tenant; token = new adalAuth.ServicePrincipalAccessToken(authConfig, this.user.name); break; default: throw new Error($('Unknown user type, cannot create credentials')); } return new AccessTokenCloudCredentials(token, this.id); } else if (this.managementCertificate) { return new azureCommon.CertificateCloudCredentials({ subscriptionId: this.id, cert: this.managementCertificate.cert, key: this.managementCertificate.key }); } throw new Error($('No token or management certificate, cannot create credentials')); }, toJSON: function () { return _.extend( _.pick(this, 'id', 'name', 'user', 'managementCertificate', 'accessToken', 'tenantId', 'isDefault', 'registeredProviders'), { environmentName: this.environment.name }, this.values); }, isAsmProviderRegistered: function (providerName) { var result = false; if (this.registeredProviders.some(function (item) { return utils.ignoreCaseEquals(item, providerName); })) { result = true; } return result; }, registerAsmProvider: function (providerName, callback) { var self = this; if (!self.isAsmProviderRegistered(providerName)) { var client = utils.createManagementClient(self); log.verbose(util.format($('Registering resource %s with subscription %s'), providerName, self.id)); client.subscriptions.registerResource(providerName, function (err) { if (err) { // 409 - conflict means the resource is already registered. Not an error if (err.statusCode === 409) { log.silly(util.format($('Resource %s is already registered'), providerName)); } else { return callback(err); } } self.registeredProviders.push(providerName); self.emit('updated'); callback(); }); } else { callback(); } }, registerArmProvider: function (namespace, waitForComplete, callback) { var self = this; var client = utils.createResourceClient(self); var numRetries = 5; log.verbose(util.format($('Registering resource namespace %s with subscription %s'), namespace, self.id)); client.providers.register(namespace, function (err) { if (err || !waitForComplete) { return callback(err); } self._waitForRegistrationComplete(client, true, numRetries, namespace, callback); }); }, unRegisterArmProvider: function (namespace, callback) { var self = this; var client = utils.createResourceClient(self); //"Unregister" is less common and we care less for the result, //so we retry less times comparing with "register" command. var numRetries = 3; log.verbose(util.format($('Un-registering resource namespace %s with subscription %s'), namespace, self.id)); client.providers.unregister(namespace, function (err) { if (err) { log.error(util.format($('Un-registering resource namespace %s failed'), namespace)); return callback(err); } self._waitForRegistrationComplete(client, false, numRetries, namespace, function (err) { if (err) { log.warn(util.format($('Unregistration is still ongoing. You can execute \'azure provider show\' to monitor the status'))); } callback(); }); }); }, /** * Waits for Registration or Uregistration to complete * * @param {object} client - The ARM Resource Management Client * @param {boolean} regOrUnreg - A boolean value, true - register, false - unregister * @param {number} retriesLeft - An integer specifying the number of times to retry * @param {string} namespace - the namespace/provider for which the registration status needs to be polled * @param {function} callback */ _waitForRegistrationComplete: function (client, regOrUnreg, retriesLeft, namespace, cb) { var pollIntervalInMS = 10 * 1000; var self = this; var action = regOrUnreg ? 'Registration' : 'Unregistration'; var state = regOrUnreg ? 'Registered' : 'Unregistered'; if (retriesLeft === 0) { return cb(util.format($('Namespace %s %s took too long to complete'), namespace, action)); } client.providers.get(namespace, function (err, result) { if (!err) { if (utils.ignoreCaseEquals(result.provider.registrationState, state)) { log.verbose(util.format($('%s of resource provider %s completed'), action, namespace)); return cb(); } } setTimeout(function () { self._waitForRegistrationComplete(client, regOrUnreg, retriesLeft - 1, namespace, cb); }, pollIntervalInMS); }); } }); module.exports = Subscription;