github.com/enmand/kubernetes@v1.2.0-alpha.0/docs/getting-started-guides/coreos/azure/lib/azure_wrapper.js (about)

     1  var _ = require('underscore');
     2  
     3  var fs = require('fs');
     4  var cp = require('child_process');
     5  
     6  var yaml = require('js-yaml');
     7  
     8  var openssl = require('openssl-wrapper');
     9  
    10  var clr = require('colors');
    11  var inspect = require('util').inspect;
    12  
    13  var util = require('./util.js');
    14  
    15  var coreos_image_ids = {
    16    'stable': '2b171e93f07c4903bcad35bda10acf22__CoreOS-Stable-717.3.0',
    17    'beta': '2b171e93f07c4903bcad35bda10acf22__CoreOS-Beta-723.3.0', // untested
    18    'alpha': '2b171e93f07c4903bcad35bda10acf22__CoreOS-Alpha-745.1.0' // untested
    19  };
    20  
    21  var conf = {};
    22  
    23  var hosts = {
    24    collection: [],
    25    ssh_port_counter: 2200,
    26  };
    27  
    28  var task_queue = [];
    29  
    30  exports.run_task_queue = function (dummy) {
    31    var tasks = {
    32      todo: task_queue,
    33      done: [],
    34    };
    35  
    36    var pop_task = function() {
    37      console.log(clr.yellow('azure_wrapper/task:'), clr.grey(inspect(tasks)));
    38      var ret = {};
    39      ret.current = tasks.todo.shift();
    40      ret.remaining = tasks.todo.length;
    41      return ret;
    42    };
    43  
    44    (function iter (task) {
    45      if (task.current === undefined) {
    46        if (conf.destroying === undefined) {
    47          create_ssh_conf();
    48          save_state();
    49        }
    50        return;
    51      } else {
    52        if (task.current.length !== 0) {
    53          console.log(clr.yellow('azure_wrapper/exec:'), clr.blue(inspect(task.current)));
    54          cp.fork('node_modules/azure-cli/bin/azure', task.current)
    55            .on('exit', function (code, signal) {
    56              tasks.done.push({
    57                code: code,
    58                signal: signal,
    59                what: task.current.join(' '),
    60                remaining: task.remaining,
    61              });
    62              if (code !== 0 && conf.destroying === undefined) {
    63                console.log(clr.red('azure_wrapper/fail: Exiting due to an error.'));
    64                save_state();
    65                console.log(clr.cyan('azure_wrapper/info: You probably want to destroy and re-run.'));
    66                process.abort();
    67              } else {
    68                iter(pop_task());
    69              }
    70          });
    71        } else {
    72          iter(pop_task());
    73        }
    74      }
    75    })(pop_task());
    76  };
    77  
    78  var save_state = function () {
    79    var file_name = util.join_output_file_path(conf.name, 'deployment.yml');
    80    try {
    81      conf.hosts = hosts.collection;
    82      fs.writeFileSync(file_name, yaml.safeDump(conf));
    83      console.log(clr.yellow('azure_wrapper/info: Saved state into `%s`'), file_name);
    84    } catch (e) {
    85      console.log(clr.red(e));
    86    }
    87  };
    88  
    89  var load_state = function (file_name) {
    90    try {
    91      conf = yaml.safeLoad(fs.readFileSync(file_name, 'utf8'));
    92      console.log(clr.yellow('azure_wrapper/info: Loaded state from `%s`'), file_name);
    93      return conf;
    94    } catch (e) {
    95      console.log(clr.red(e));
    96    }
    97  };
    98  
    99  var create_ssh_key = function (prefix) {
   100    var opts = {
   101      x509: true,
   102      nodes: true,
   103      newkey: 'rsa:2048',
   104      subj: '/O=Weaveworks, Inc./L=London/C=GB/CN=weave.works',
   105      keyout: util.join_output_file_path(prefix, 'ssh.key'),
   106      out: util.join_output_file_path(prefix, 'ssh.pem'),
   107    };
   108    openssl.exec('req', opts, function (err, buffer) {
   109      if (err) console.log(clr.red(err));
   110      fs.chmod(opts.keyout, '0600', function (err) {
   111        if (err) console.log(clr.red(err));
   112      });
   113    });
   114    return {
   115      key: opts.keyout,
   116      pem: opts.out,
   117    }
   118  }
   119  
   120  var create_ssh_conf = function () {
   121    var file_name = util.join_output_file_path(conf.name, 'ssh_conf');
   122    var ssh_conf_head = [
   123      "Host *",
   124      "\tHostname " + conf.resources['service'] + ".cloudapp.net",
   125      "\tUser core",
   126      "\tCompression yes",
   127      "\tLogLevel FATAL",
   128      "\tStrictHostKeyChecking no",
   129      "\tUserKnownHostsFile /dev/null",
   130      "\tIdentitiesOnly yes",
   131      "\tIdentityFile " + conf.resources['ssh_key']['key'],
   132      "\n",
   133    ];
   134  
   135    fs.writeFileSync(file_name, ssh_conf_head.concat(_.map(hosts.collection, function (host) {
   136      return _.template("Host <%= name %>\n\tPort <%= port %>\n")(host);
   137    })).join('\n'));
   138    console.log(clr.yellow('azure_wrapper/info:'), clr.green('Saved SSH config, you can use it like so: `ssh -F ', file_name, '<hostname>`'));
   139    console.log(clr.yellow('azure_wrapper/info:'), clr.green('The hosts in this deployment are:\n'), _.map(hosts.collection, function (host) { return host.name; }));
   140  };
   141  
   142  var get_location = function () {
   143    if (process.env['AZ_AFFINITY']) {
   144      return '--affinity-group=' + process.env['AZ_AFFINITY'];
   145    } else if (process.env['AZ_LOCATION']) {
   146      return '--location=' + process.env['AZ_LOCATION'];
   147    } else {
   148      return '--location=West Europe';
   149    }
   150  }
   151  var get_vm_size = function () {
   152    if (process.env['AZ_VM_SIZE']) {
   153      return '--vm-size=' + process.env['AZ_VM_SIZE'];
   154    } else {
   155      return '--vm-size=Small';
   156    }
   157  }
   158  
   159  exports.queue_default_network = function () {
   160    task_queue.push([
   161      'network', 'vnet', 'create',
   162      get_location(),
   163      '--address-space=172.16.0.0',
   164      conf.resources['vnet'],
   165    ]);
   166  }
   167  
   168  exports.queue_storage_if_needed = function() {
   169    if (!process.env['AZURE_STORAGE_ACCOUNT']) {
   170      conf.resources['storage_account'] = util.rand_suffix;
   171      task_queue.push([
   172        'storage', 'account', 'create',
   173        '--type=LRS',
   174        get_location(),
   175        conf.resources['storage_account'],
   176      ]);
   177      process.env['AZURE_STORAGE_ACCOUNT'] = conf.resources['storage_account'];
   178    } else {
   179      // Preserve it for resizing, so we don't create a new one by accedent,
   180      // when the environment variable is unset
   181      conf.resources['storage_account'] = process.env['AZURE_STORAGE_ACCOUNT'];
   182    }
   183  };
   184  
   185  exports.queue_machines = function (name_prefix, coreos_update_channel, cloud_config_creator) {
   186    var x = conf.nodes[name_prefix];
   187    var vm_create_base_args = [
   188      'vm', 'create',
   189      get_location(),
   190      get_vm_size(),
   191      '--connect=' + conf.resources['service'],
   192      '--virtual-network-name=' + conf.resources['vnet'],
   193      '--no-ssh-password',
   194      '--ssh-cert=' + conf.resources['ssh_key']['pem'],
   195    ];
   196  
   197    var cloud_config = cloud_config_creator(x, conf);
   198  
   199    var next_host = function (n) {
   200      hosts.ssh_port_counter += 1;
   201      var host = { name: util.hostname(n, name_prefix), port: hosts.ssh_port_counter };
   202      if (cloud_config instanceof Array) {
   203        host.cloud_config_file = cloud_config[n];
   204      } else {
   205        host.cloud_config_file = cloud_config;
   206      }
   207      hosts.collection.push(host);
   208      return _.map([
   209          "--vm-name=<%= name %>",
   210          "--ssh=<%= port %>",
   211          "--custom-data=<%= cloud_config_file %>",
   212      ], function (arg) { return _.template(arg)(host); });
   213    };
   214  
   215    task_queue = task_queue.concat(_(x).times(function (n) {
   216      if (conf.resizing && n < conf.old_size) {
   217        return [];
   218      } else {
   219        return vm_create_base_args.concat(next_host(n), [
   220          coreos_image_ids[coreos_update_channel], 'core',
   221        ]);
   222      }
   223    }));
   224  };
   225  
   226  exports.create_config = function (name, nodes) {
   227    conf = {
   228      name: name,
   229      nodes: nodes,
   230      weave_salt: util.rand_string(),
   231      resources: {
   232        vnet: [name, 'internal-vnet', util.rand_suffix].join('-'),
   233        service: [name, util.rand_suffix].join('-'),
   234        ssh_key: create_ssh_key(name),
   235      }
   236    };
   237  
   238  };
   239  
   240  exports.destroy_cluster = function (state_file) {
   241    load_state(state_file);
   242    if (conf.hosts === undefined) {
   243      console.log(clr.red('azure_wrapper/fail: Nothing to delete.'));
   244      process.abort();
   245    }
   246  
   247    conf.destroying = true;
   248    task_queue = _.map(conf.hosts, function (host) {
   249      return ['vm', 'delete', '--quiet', '--blob-delete', host.name];
   250    });
   251  
   252    task_queue.push(['network', 'vnet', 'delete', '--quiet', conf.resources['vnet']]);
   253    task_queue.push(['storage', 'account', 'delete', '--quiet', conf.resources['storage_account']]);
   254  
   255    exports.run_task_queue();
   256  };
   257  
   258  exports.load_state_for_resizing = function (state_file, node_type, new_nodes) {
   259    load_state(state_file);
   260    if (conf.hosts === undefined) {
   261      console.log(clr.red('azure_wrapper/fail: Nothing to look at.'));
   262      process.abort();
   263    }
   264    conf.resizing = true;
   265    conf.old_size = conf.nodes[node_type];
   266    conf.old_state_file = state_file;
   267    conf.nodes[node_type] += new_nodes;
   268    hosts.collection = conf.hosts;
   269    hosts.ssh_port_counter += conf.hosts.length;
   270    process.env['AZURE_STORAGE_ACCOUNT'] = conf.resources['storage_account'];
   271  }