azure-cli
Version:
Microsoft Azure Cross Platform Command Line tool
218 lines (184 loc) • 7.37 kB
JavaScript
//
// Copyright (c) Microsoft and contributors. 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.
//
var _ = require('underscore');
var fs = require('fs');
var path = require('path');
var read = require('read');
var wrap = require('wordwrap').hard(0, 75);
var util = require('util');
var Constants = require('./constants');
var userHome = require('user-home');
exports.camelcase = function (flag) {
return flag.split('-').reduce(function (str, word) {
return str + word[0].toUpperCase() + word.slice(1);
});
};
exports.ignoreCaseEquals = function (a, b) {
return a === b ||
(a !== null && a !== undefined &&
b !== null && b !== undefined &&
(a.toLowerCase() === b.toLowerCase())) === true;
};
exports.azureDir = function () {
if (!process.env.AZURE_CONFIG_DIR && !userHome) {
throw new Error('No Azure_CONFIG_DIR or HOME path is available');
}
var dir = process.env.AZURE_CONFIG_DIR ||
path.join(userHome, '.azure');
if (!exports.pathExistsSync(dir)) {
fs.mkdirSync(dir, 502); // 0766
}
return dir;
};
exports.stringStartsWith = function (text, prefix, ignoreCase) {
if (_.isNull(prefix)) {
return true;
}
if (ignoreCase) {
return text.toLowerCase().substr(0, prefix.toLowerCase().length) === prefix.toLowerCase();
} else {
return text.substr(0, prefix.length) === prefix;
}
};
exports.pathExistsSync = fs.existsSync ? fs.existsSync : path.existsSync;
/**
* Read azure cli config
*/
exports.readConfig = function () {
var azureConfigPath = path.join(exports.azureDir(), 'config.json');
var cfg = {};
if (exports.pathExistsSync(azureConfigPath)) {
try {
cfg = JSON.parse(fs.readFileSync(azureConfigPath));
} catch (err) {
cfg = {};
}
}
return cfg;
};
exports.writeConfig = function (cfg) {
var azurePath = exports.azureDir();
var azureConfigPath = path.join(exports.azureDir(), 'config.json');
if (!exports.pathExistsSync(azurePath)) {
fs.mkdirSync(azurePath, 502); //0766
}
fs.writeFileSync(azureConfigPath, JSON.stringify(cfg, null, 2));
};
exports.getMode = function () {
var config = exports.readConfig();
return config.mode ? config.mode : Constants.API_VERSIONS.ARM;
};
exports.getFiles = function (scanPath, recursively) {
var results = [];
var list = fs.readdirSync(scanPath);
var pending = list.length;
if (!pending) {
return results;
}
for (var i = 0; i < list.length; i++) {
var file = list[i];
file = scanPath + '/' + file;
var stat = fs.statSync(file);
if (stat && stat.isDirectory()) {
if (recursively) {
var res = exports.getFiles(file);
results = results.concat(res);
}
} else {
results.push(file);
}
}
return results;
};
exports.readTelemetry = function () {
var azureTelemetryPath = path.join(exports.azureDir(), Constants.TELEMETRY);
var telemetry = {};
if (exports.pathExistsSync(azureTelemetryPath)) {
try {
telemetry = JSON.parse(fs.readFileSync(azureTelemetryPath));
} catch (err) {
telemetry = {};
}
}
return telemetry;
};
exports.writeTelemetry = function (telemetry) {
var azurePath = exports.azureDir();
var azureTelemetryPath = path.join(exports.azureDir(), Constants.TELEMETRY);
if (!exports.pathExistsSync(azurePath)) {
fs.mkdirSync(azurePath, 502); //0766
}
fs.writeFileSync(azureTelemetryPath, JSON.stringify(telemetry, null, 2));
};
/**
* Determines whether telemtry is enabled or not. If this is the first time, that this decision
* needs to be made, then it prompts the user for data collection. It will timeout in 60 seconds
* with default response being 'n' i.e. telemetry is disabled.
*
* @returns {function} callback(err, result)
*
* {null} err - Always null.
*
* {boolean} result - true if telemetry is enabled, false otherwise.
*/
exports.isTelemetryEnabled = function (callback) {
var telemetryInfo = exports.readTelemetry();
var outcome = false;
if (telemetryInfo.telemetry !== null && telemetryInfo.telemetry !== undefined && typeof telemetryInfo.telemetry === 'boolean') {
return callback(null, telemetryInfo.telemetry);
} else if (process.argv[2] && process.argv[2].toLowerCase() === 'telemetry') {
return callback(null, outcome);
} else {
// we've determined that this is not a telemetry command and we do not have user's telemetry preference.
// we proceed to read out the telemetry prompt and get user preference. But, before that check if we're
// in non interactive mode. If so, do not prompt, assume default response of 'no'.
// This behavior is intended to make scripting scenarios better. E.g: running azure cli on a CI server.
if (process.env['AZURE_NON_INTERACTIVE_MODE']) {
return callback(null, outcome);
}
var telemetryPromptText = wrap('\nMicrosoft Azure CLI would like to collect data about how users use CLI commands and some problems they encounter. ' +
'Microsoft uses this information to improve our CLI commands. Participation is voluntary and when you choose to participate your device ' +
'automatically sends information to Microsoft about how you use Azure CLI. ' +
'\n\nIf you choose to participate, you can stop at any time later by using Azure CLI as follows: ' +
'\n1. Use the azure telemetry command to turn the feature Off. ' +
'\nTo disable data collection, execute: azure telemetry --disable' +
'\n\nIf you choose to not participate, you can enable at any time later by using Azure CLI as follows: ' +
'\n1. Use the azure telemetry command to turn the feature On. ' +
'\nTo enable data collection, execute: azure telemetry --enable' +
'\n\nSelect y to enable data collection :(y/n) ');
var telemetryOptions = {
prompt : telemetryPromptText,
timeout : 30000,
edit : false,
silent : false
};
read(telemetryOptions, function(err, result) {
if ((err && err.message === 'timed out') || (result && result.match(/^no?$/i))) {
exports.writeTelemetry({telemetry: false});
console.log('\nYou choose not to participate in Microsoft Azure CLI data collection.\n\n');
} else if (result && result.match(/^y?(es)?$/i)) {
exports.writeTelemetry({telemetry: true});
outcome = true;
console.log('\nYou choose to participate in Microsoft Azure CLI data collection.\n\n');
} else {
exports.writeTelemetry({telemetry: false});
console.log(wrap(util.format('\nYou provided \'%s\' which is an invalid input. This translates ' +
'to you choosing not to participate in Microsoft Azure CLI data collection.\n\n', result)));
}
return callback(null, outcome);
});
}
};