diff options
48 files changed, 1770 insertions, 0 deletions
| diff --git a/cli/DEVNOTES b/cli/DEVNOTES new file mode 100644 index 0000000..eceac87 --- /dev/null +++ b/cli/DEVNOTES @@ -0,0 +1,97 @@ +Features to add +========================== + +templates +-------------------- + +templates for nodes and services stored in leap_platform + +commands: + +    leap add-service   # menu of services, adding copies the template +    leap add-node      # you pick a service, then it copies template + +deploy +--------------------- + +not yet working + +    leap bootstrap +    leap dryrun +    leap deploy + +key management +------------------------- + +not yet working + +    leap add-ssh-keypair +    leap add-x509-keypair + +hiera logic +------------------------ + +leap_platform should be able insert ruby logic in the generation of hiera .yml files. for example, so say that a webapp node should get a list of all the couchdb nodes its config. + +this code might look like this + +    node['couchdb_ips'] = @nodes[:services => :couchdb].map(&:ip_address) + +or + +    node['couchdb_ips'] = @services[:couchdb].nodes.map(&:ip_address) + +maybe see http://blog.bigbinary.com/2008/10/17/under-the-hood-how-named-scope-works.html + + +json validation +------------------------ + +json validation +http://www.kuwata-lab.com/kwalify/ruby/users-guide.html + + +useful liberaries +================================ + +user interaction + +  readline +  highline +  terminal-tables +  rainbow +  http://stackoverflow.com/questions/9577718/what-ruby-libraries-should-i-use-for-building-a-console-based-application + +testing + +  aruba -- test for cli + +help + +  gem-man -- install man pages with gems +  ronn -- write man pages in markdown + +push examples + +  https://github.com/net-ssh/net-ssh + +  https://github.com/seattlerb/rake-remote_task +    http://docs.seattlerb.org/rake-remote_task/ +    https://github.com/seattlerb/rake-remote_task/blob/master/lib/rake/remote_task.rb + +  https://github.com/davidwinter/sooty +    push puppet with rake/remote_task +    https://github.com/davidwinter/sooty/blob/master/lib/sooty.rb + +  calling rsync from ruby +    https://github.com/RichGuk/rrsync/blob/master/rrsync.rb +    http://rubyforge.org/projects/six-rsync/ + +  https://github.com/automateit/automateit + +  http://www.jedi.be/blog/2009/11/17/shell-scripting-dsl-in-ruby/ + +  parallel shell +    https://github.com/delano/rye +    https://github.com/adamwiggins/rush + diff --git a/cli/Gemfile b/cli/Gemfile new file mode 100644 index 0000000..e45e65f --- /dev/null +++ b/cli/Gemfile @@ -0,0 +1,2 @@ +source :rubygems +gemspec diff --git a/cli/Gemfile.lock b/cli/Gemfile.lock new file mode 100644 index 0000000..60ce6f8 --- /dev/null +++ b/cli/Gemfile.lock @@ -0,0 +1,22 @@ +PATH +  remote: . +  specs: +    leap_cli (0.0.1) +      gli (~> 2.3) +      oj +      terminal-table + +GEM +  remote: http://rubygems.org/ +  specs: +    gli (2.3.0) +    oj (1.3.7) +    rake (0.9.2.2) +    terminal-table (1.4.5) + +PLATFORMS +  ruby + +DEPENDENCIES +  leap_cli! +  rake diff --git a/cli/README.md b/cli/README.md new file mode 100644 index 0000000..fccd6d1 --- /dev/null +++ b/cli/README.md @@ -0,0 +1,132 @@ +About LEAP command line interface +================================= + +This gem installs an executable 'leap' that allows you to manage servers using the leap platform. + +Installation +================================= + +To install the gem: + +    gem install leap_cli + +To run from a clone of the git repo, see "Development", below. + +Usage +================================= + +This tool is incomplete, so most commands don't yet work. + +Run `leap help` for a usage instructions. + +Here is an example usage: + +    leap init provider +    cd provider +    edit configuration files (see below) +    leap compile + +Directories and Files +================================= + +The general structure of leap project looks like this: + +    my_leap_project/                 # the 'root' directory +      leap_platform/                 # a clone of the leap_platform puppet recipes +      provider/                      # your provider-specific configurations + +The "leap" command should be run from within the "provider" directory. + +You can name these directories whatever you like. The leap command will walk up the directory tree until it finds a directory that looks like a 'root' directory. + +Within the "provider" directory: + +    nodes/               # one configuration file per node (i.e. server) +    services/            # nodes inherit from these files if specified in node config. +    tags/                # nodes inherit from these files if specified in node config. +    files/               # text and binary files needed for services and nodes, including keypairs +    users/               # crypto key material for sysadmins +    common.yaml          # all nodes inherit these options +    provider.yaml        # global service provider definition + +Configuration Files +================================= + +All configuration files are in JSON format. For example + +    { +      "key1": "value1", +      "key2": "value2" +    } + +Keys should match /[a-z0-9_]/ + +Unlike traditional JSON, comments are allowed. If the first non-whitespace character is '#' the line is treated as a comment. + +    # this is a comment +    { +      # this is a comment +      "key": "value"  # this is an error +    } + +Options in the configuration files might be nested. For example: + +    { +      "openvpn": { +        "ip_address": "1.1.1.1" +      } +    } + +When compiled into hiera and made available in puppet, this becomes a Hash object with flattened keys: + +    {"openvpn.ip_address" => "1.1.1.1"} + +Node Configuration +================================= + +The name of the file will be the hostname of the node. + +An example configuration "nodes/dns-europe.json" + +    { +       "services": "dns", +       "tags": ["production", "europe"], +       "ip_address": "1.1.1.1" +    } + +This node will have hostname "dns-europe" and it will inherit from the following files (in this order): + +    common.json +    services/dns.json +    tags/europe.json +    tags/production.json + +Development +================================= + +prerequisites: + +* rubygems (``apt-get install rubygems``) +* bundler  (``gem install bundler``) + +Install command line ``leap``: + +    git clone git://leap.se/leap_cli   # clone leap cli code +    cd leap_cli +    bundle                             # install required gems +    ln -s `pwd`/bin/leap ~/bin         # link executable somewhere in your bin path + +You can experiment using the example provider in the test directory + +    cd test/provider +    leap + +Alternately, you can create your own provider for testing: + +    mkdir ~/dev/example.org +    cd ~/dev/example.org +    git clone git://leap.se/leap_platform +    leap init provider +    cd provider +    leap + diff --git a/cli/Rakefile b/cli/Rakefile new file mode 100644 index 0000000..c97688b --- /dev/null +++ b/cli/Rakefile @@ -0,0 +1,44 @@ +require 'rake/clean' +require 'rubygems' +require 'rubygems/package_task' +require 'rdoc/task' +require 'cucumber' +require 'cucumber/rake/task' +Rake::RDocTask.new do |rd| +  rd.main = "README.rdoc" +  rd.rdoc_files.include("README.rdoc","lib/**/*.rb","bin/**/*") +  rd.title = 'Your application title' +end + +spec = eval(File.read('leap_cli.gemspec')) + +Gem::PackageTask.new(spec) do |pkg| +end +CUKE_RESULTS = 'results.html' +CLEAN << CUKE_RESULTS +desc 'Run features' +Cucumber::Rake::Task.new(:features) do |t| +  opts = "features --format html -o #{CUKE_RESULTS} --format progress -x" +  opts += " --tags #{ENV['TAGS']}" if ENV['TAGS'] +  t.cucumber_opts =  opts +  t.fork = false +end + +desc 'Run features tagged as work-in-progress (@wip)' +Cucumber::Rake::Task.new('features:wip') do |t| +  tag_opts = ' --tags ~@pending' +  tag_opts = ' --tags @wip' +  t.cucumber_opts = "features --format html -o #{CUKE_RESULTS} --format pretty -x -s#{tag_opts}" +  t.fork = false +end + +task :cucumber => :features +task 'cucumber:wip' => 'features:wip' +task :wip => 'features:wip' +require 'rake/testtask' +Rake::TestTask.new do |t| +  t.libs << "test" +  t.test_files = FileList['test/*_test.rb'] +end + +task :default => [:test,:features] diff --git a/cli/bin/leap b/cli/bin/leap new file mode 100755 index 0000000..4155b58 --- /dev/null +++ b/cli/bin/leap @@ -0,0 +1,64 @@ +#!/usr/bin/env ruby +begin +  require 'leap_cli' +rescue LoadError +  # +  # When developing a gem with a command, you normally use `bundle exec bin/command-name` +  # to run your app. At install-time, RubyGems will make sure lib, etc. are in the load path, +  # so that you can run the command directly. +  # +  # However, I don't like using 'bundle exec'. It is slow, and limits which directory you can +  # run in. So, instead, we fall back to some path manipulation hackery. +  # +  # This allows you to run the command directly while developing the gem, and also lets you +  # run from anywhere (I like to link 'bin/leap' to /usr/local/bin/leap). +  # +  file = File.symlink?(__FILE__) ? File.readlink(__FILE__) : __FILE__ +  lib_dir = File.expand_path(File.dirname(file) + '/../lib') +  $LOAD_PATH.unshift lib_dir unless $LOAD_PATH.include?(lib_dir) +  require 'rubygems' +  require 'leap_cli' +end + +require 'gli' +require 'highline' +require 'forwardable' +require 'terminal-table' + +# +# Typically, GLI and Highline methods are loaded into the global namespace. +# Instead, here we load these into the module LeapCli::Commands in order to +# ensure that the cli logic and code is kept isolated to leap_cli/commands/*.rb +# +# no cheating! +# +module LeapCli::Commands +  extend GLI::App +  extend Forwardable +  extend Terminal::Table::TableHelper + +  ENV['GLI_DEBUG'] = "true" + +  # +  # delegate highline methods to make them available to sub-commands +  # +  @terminal = HighLine.new +  def_delegator :@terminal, :ask, 'self.ask' +  def_delegator :@terminal, :agree, 'self.agree' +  def_delegator :@terminal, :ask, 'self.ask' +  def_delegator :@terminal, :choose, 'self.choose' +  def_delegator :@terminal, :say, 'self.say' + +  # +  # info about leap command line suite +  # +  program_desc       'LEAP platform command line interface' +  program_long_desc  'This is the long description. It is very interesting.' +  version            LeapCli::VERSION + +  # +  # load commands and run +  # +  commands_from('leap_cli/commands') +  exit run(ARGV) +end diff --git a/cli/leap_cli.gemspec b/cli/leap_cli.gemspec new file mode 100644 index 0000000..208355d --- /dev/null +++ b/cli/leap_cli.gemspec @@ -0,0 +1,45 @@ +# +# Ensure we require the local version and not one we might have installed already +# +require File.join([File.dirname(__FILE__),'lib','leap_cli','version.rb']) + +spec = Gem::Specification.new do |s| + +  ## +  ## ABOUT THIS GEM +  ## +  s.name = 'leap_cli' +  s.version = LeapCli::VERSION +  s.author = 'LEAP' +  s.email = 'root@leap.se' +  s.homepage = 'https://leap.se' +  s.platform = Gem::Platform::RUBY +  s.summary = 'Command line interface to the leap platform.' + +  ## +  ## GEM FILES +  ## +  s.files = `find lib -name '*.rb'`.split("\n") << "bin/leap" +  s.require_paths << 'lib' + +  s.bindir = 'bin' +  s.executables << 'leap' + +  ## +  ## DOCUMENTATION +  ## +  #s.has_rdoc = true +  #s.extra_rdoc_files = ['README.rdoc','leap_cli.rdoc'] +  #s.rdoc_options << '--title' << 'leap_cli' << '--main' << 'README.rdoc' << '-ri' + +  ## +  ## DEPENDENCIES +  ## +  s.add_development_dependency('rake') +  #s.add_development_dependency('rdoc') +  #s.add_development_dependency('aruba') + +  s.add_runtime_dependency('gli','~> 2.3') +  s.add_runtime_dependency('oj') +  s.add_runtime_dependency('terminal-table') +end diff --git a/cli/leap_cli.rdoc b/cli/leap_cli.rdoc new file mode 100644 index 0000000..31d5deb --- /dev/null +++ b/cli/leap_cli.rdoc @@ -0,0 +1,5 @@ += leap_cli + +Generate this with +    leap_cli rdoc +After you have described your command line interface
\ No newline at end of file diff --git a/cli/lib/leap_cli.rb b/cli/lib/leap_cli.rb new file mode 100644 index 0000000..b935e35 --- /dev/null +++ b/cli/lib/leap_cli.rb @@ -0,0 +1,19 @@ +module LeapCli; end + +unless defined?(LeapCli::VERSION) +  # ^^ I am not sure why this is needed. +  require 'leap_cli/version.rb' +end + +require 'leap_cli/init' +require 'leap_cli/path' +require 'leap_cli/log' +require 'leap_cli/config' +require 'leap_cli/config_list' +require 'leap_cli/config_manager' + +unless String.method_defined?(:to_a) +  class String +    def to_a; [self]; end +  end +end
\ No newline at end of file diff --git a/cli/lib/leap_cli/commands/README b/cli/lib/leap_cli/commands/README new file mode 100644 index 0000000..00fcd84 --- /dev/null +++ b/cli/lib/leap_cli/commands/README @@ -0,0 +1,101 @@ +This directory contains ruby source files that define the available sub-commands of the `leap` executable. + +For example, the command: + +  leap init <directory> + +Lives in lib/leap_cli/commands/init.rb + +These files use a DSL (called GLI) for defining command suites. +See https://github.com/davetron5000/gli for more information. + + +      c.command +      c.commands +      c.default_command +      c.default_value +      c.get_default_command +      c.commands +      c.commands_declaration_order + +      c.flag +      c.flags +      c.switch +      c.switches + +      c.long_desc + +      c.default_desc +      c.default_description +      c.desc +      c.description +      c.long_description +      c.context_description +      c.usage + +      c.arg_name +      c.arguments_description +      c.arguments_options + +      c.skips_post +      c.skips_pre +      c.skips_around + +      c.action + +      c.copy_options_to_aliases +      c.nodoc +      c.aliases +      c.execute +      c.names + + +#desc 'Describe some switch here' +#switch [:s,:switch] + +#desc 'Describe some flag here' +#default_value 'the default' +#arg_name 'The name of the argument' +#flag [:f,:flagname] + +# desc 'Describe deploy here' +# arg_name 'Describe arguments to deploy here' +# command :deploy do |c| +#   c.action do |global_options,options,args| +#     puts "deploy command ran" +#   end +# end + +# desc 'Describe dryrun here' +# arg_name 'Describe arguments to dryrun here' +# command :dryrun do |c| +#   c.action do |global_options,options,args| +#     puts "dryrun command ran" +#   end +# end + +# desc 'Describe add-node here' +# arg_name 'Describe arguments to add-node here' +# command :"add-node" do |c| +#   c.desc 'Describe a switch to init' +#   c.switch :s +# +#   c.desc 'Describe a flag to init' +#   c.default_value 'default' +#   c.flag :f +#   c.action do |global_options,options,args| +#     puts "add-node command ran" +#   end +# end + +# post do |global,command,options,args| +#   # Post logic here +#   # Use skips_post before a command to skip this +#   # block on that command only +# end + +# on_error do |exception| +#   # Error logic here +#   # return false to skip default error handling +#   true +# end diff --git a/cli/lib/leap_cli/commands/compile.rb b/cli/lib/leap_cli/commands/compile.rb new file mode 100644 index 0000000..6b38de5 --- /dev/null +++ b/cli/lib/leap_cli/commands/compile.rb @@ -0,0 +1,15 @@ +module LeapCli +  module Commands + +    desc 'Compile json files to hiera configs' +    command :compile do |c| +      c.action do |global_options,options,args| +        manager = ConfigManager.new +        manager.load(Path.provider) +        Path.ensure_dir(Path.hiera) +        manager.export(Path.hiera) +      end +    end + +  end +end
\ No newline at end of file diff --git a/cli/lib/leap_cli/commands/deploy.rb b/cli/lib/leap_cli/commands/deploy.rb new file mode 100644 index 0000000..3694a38 --- /dev/null +++ b/cli/lib/leap_cli/commands/deploy.rb @@ -0,0 +1,20 @@ +module LeapCli +  module Commands + +    desc 'Apply recipes to a node or set of nodes' +    long_desc 'The node filter can be the name of a node, service, or tag.' +    arg_name '<node filter>' +    command :deploy do |c| +      c.action do |global_options,options,args| +        nodes = ConfigManager.filter(args) +        say "Deploying to these nodes: #{nodes.keys.join(', ')}" +        if agree "Continue? " +          say "deploy not yet implemented" +        else +          say "OK. Bye." +        end +      end +    end + +  end +end
\ No newline at end of file diff --git a/cli/lib/leap_cli/commands/init.rb b/cli/lib/leap_cli/commands/init.rb new file mode 100644 index 0000000..75cc876 --- /dev/null +++ b/cli/lib/leap_cli/commands/init.rb @@ -0,0 +1,24 @@ +module LeapCli +  module Commands +    desc 'Creates a new provider configuration directory.' +    arg_name '<directory>' +    skips_pre +    command :init do |c| +      c.action do |global_options,options,args| +        directory = args.first +        unless directory && directory.any? +          help_now! "Directory name is required." +        end +        directory = File.expand_path(directory) +        if File.exists?(directory) +          raise "#{directory} already exists." +        end +        if agree("Create directory '#{directory}'? ") +          LeapCli.init(directory) +        else +          puts "OK, bye." +        end +      end +    end +  end +end
\ No newline at end of file diff --git a/cli/lib/leap_cli/commands/list.rb b/cli/lib/leap_cli/commands/list.rb new file mode 100644 index 0000000..a186049 --- /dev/null +++ b/cli/lib/leap_cli/commands/list.rb @@ -0,0 +1,61 @@ +module LeapCli +  module Commands + +    def self.print_config_table(type, config_list) +      style = {:border_x => '-', :border_y => ':', :border_i => '-', :width => 60} + +      if type == :services +        t = table do +          self.style = style +          self.headings = ['SERVICE', 'NODES'] +          list = config_list.keys.sort +          list.each do |name| +            add_row [name, config_list[name].nodes.keys.join(', ')] +            add_separator unless name == list.last +          end +        end +        puts t +        puts "\n\n" +      elsif type == :tags +        t = table do +          self.style = style +          self.headings = ['TAG', 'NODES'] +          list = config_list.keys.sort +          list.each do |name| +            add_row [name, config_list[name].nodes.keys.join(', ')] +            add_separator unless name == list.last +          end +        end +        puts t +        puts "\n\n" +      elsif type == :nodes +        t = table do +          self.style = style +          self.headings = ['NODE', 'SERVICES', 'TAGS'] +          list = config_list.keys.sort +          list.each do |name| +            add_row [name, config_list[name].services.to_a.join(', '), config_list[name].tags.to_a.join(', ')] +            add_separator unless name == list.last +          end +        end +        puts t +      end +    end + +    desc 'List nodes and their classifications' +    long_desc 'Prints out a listing of nodes, services, or tags.' +    arg_name 'filter' +    command :list do |c| +      c.action do |global_options,options,args| +        if args.any? +          print_config_table(:nodes, ConfigManager.filter(args)) +        else +          print_config_table(:services, ConfigManager.services) +          print_config_table(:tags,     ConfigManager.tags) +          print_config_table(:nodes,  ConfigManager.nodes) +        end +      end +    end + +  end +end diff --git a/cli/lib/leap_cli/commands/pre.rb b/cli/lib/leap_cli/commands/pre.rb new file mode 100644 index 0000000..ae58fc8 --- /dev/null +++ b/cli/lib/leap_cli/commands/pre.rb @@ -0,0 +1,38 @@ + +# +# check to make sure we can find the root directory of the platform +# +module LeapCli +  module Commands + +    desc 'Verbosity level 0..2' +    arg_name 'level' +    default_value '0' +    flag [:v, :verbose] + +    desc 'Specify the root directory' +    arg_name 'path' +    default_value Path.root +    flag [:root] + +    pre do |global,command,options,args| +      # +      # set verbosity +      # +      LeapCli.log_level = global[:verbose].to_i + +      # +      # require a root directory +      # +      if global[:root] +        Path.set_root(global[:root]) +      end +      if Path.ok? +        true +      else +        exit_now!("Could not find the root directory. Change current working directory or try --root") +      end +    end + +  end +end diff --git a/cli/lib/leap_cli/config.rb b/cli/lib/leap_cli/config.rb new file mode 100644 index 0000000..44e66be --- /dev/null +++ b/cli/lib/leap_cli/config.rb @@ -0,0 +1,119 @@ +module LeapCli +  # +  # This class represents the configuration for a single node, service, or tag. +  # +  class Config < Hash + +    def initialize(config_type, manager) +      @manager = manager +      @type = config_type +    end + +    # +    # lazily eval dynamic values when we encounter them. +    # +    def [](key) +      value = fetch(key, nil) +      if value.is_a? Array +        value +      elsif value.nil? +        nil +      else +        if value =~ /^= (.*)$/ +          value = eval($1) +          self[key] = value +        end +        value +      end +    end + +    # +    # make the type appear to be a normal Hash in yaml. +    # +    def to_yaml_type +     "!map" +    end + +    # +    # just like Hash#to_yaml, but sorted +    # +    def to_yaml(opts = {}) +      YAML::quick_emit(self, opts) do |out| +        out.map(taguri, to_yaml_style) do |map| +          keys.sort.each do |k| +            v = self.fetch(k) +            map.add(k, v) +          end +        end +      end +    end + +    # +    # make obj['name'] available as obj.name +    # +    def method_missing(method, *args, &block) +      if has_key?(method.to_s) +        self[method.to_s] +      else +        super +      end +    end + +    # +    # convert self into a plain hash, but only include the specified keys +    # +    def to_h(*keys) +      keys.map(&:to_s).inject({}) do |hsh, key| +        if has_key?(key) +          hsh[key] = self[key] +        end +        hsh +      end +    end + +    def nodes +      if @type == :node +        @manager.nodes +      else +        @nodes ||= ConfigList.new +      end +    end + +    def services +      if @type == :node +        self['services'] || [] +      else +        @manager.services +      end +    end + +    def tags +      if @type == :node +        self['tags'] || [] +      else +        @manager.tags +      end +    end + +    private + +    ## +    ## MACROS +    ## these are methods used when eval'ing a value in the .json configuration +    ## + +    # +    # inserts the contents of a file +    # +    def file(filename) +      filepath = Path.find_file(name, filename) +      if filepath +        File.read(filepath) +      else +        log0('no such file, "%s"' % filename) +        "" +      end +    end + +  end # class +end # module
\ No newline at end of file diff --git a/cli/lib/leap_cli/config_list.rb b/cli/lib/leap_cli/config_list.rb new file mode 100644 index 0000000..c8ff23b --- /dev/null +++ b/cli/lib/leap_cli/config_list.rb @@ -0,0 +1,77 @@ +module LeapCli +  class ConfigList < Hash + +    def initialize(config=nil) +      if config +        self << config +      end +    end + +    # +    # if the key is a hash, we treat it as a condition and filter all the configs using the condition +    # +    # for example: +    # +    #   nodes[:public_dns => true] +    # +    # will return a ConfigList with node configs that have public_dns set to true +    # +    def [](key) +      if key.is_a? Hash +        results = ConfigList.new +        field, match_value = key.to_a.first +        field = field.is_a?(Symbol) ? field.to_s : field +        match_value = match_value.is_a?(Symbol) ? match_value.to_s : match_value +        each do |name, config| +          value = config[field] +          if !value.nil? +            if value.is_a? Array +              if value.includes?(match_value) +                results[name] = config +              end +            else +              if value == match_value +                results[name] = config +              end +            end +          end +        end +        results +      else +        super +      end +    end + +    def <<(config) +      if config.is_a? ConfigList +        self.merge!(config) +      else +        self[config['name']] = config +      end +    end + +    # +    # converts the hash of configs into an array of hashes, with ONLY the specified fields +    # +    def fields(*fields) +      result = [] +      keys.sort.each do |name| +        result << self[name].to_h(*fields) +      end +      result +    end + +    # +    # like fields(), but returns an array of values instead of an array of hashes. +    # +    def field(field) +      field = field.to_s +      result = [] +      keys.sort.each do |name| +        result << self[name][field] +      end +      result +    end + +  end +end diff --git a/cli/lib/leap_cli/config_manager.rb b/cli/lib/leap_cli/config_manager.rb new file mode 100644 index 0000000..d383cc1 --- /dev/null +++ b/cli/lib/leap_cli/config_manager.rb @@ -0,0 +1,200 @@ +require 'oj' +require 'yaml' + +module LeapCli + +  class ConfigManager + +    attr_reader :services, :tags, :nodes + +    ## +    ## IMPORT EXPORT +    ## + +    # +    # load .json configuration files +    # +    def load(dir) +      @services = load_all_json("#{dir}/services/*.json") +      @tags     = load_all_json("#{dir}/tags/*.json") +      @common   = load_all_json("#{dir}/common.json")['common'] +      @nodes    = load_all_json("#{dir}/nodes/*.json", :node) +      @nodes.each do |name, node| +        apply_inheritance(node) +      end +      @nodes.each do |name, node| +        node.each {|key,value| node[key] } # force evaluation of dynamic values +      end +    end + +    # +    # save compiled hiera .yaml files +    # +    def export(dir) +      Dir.glob(dir + '/*.yaml').each do |f| +        File.unlink(f) +      end +      @nodes.each do |name, node| +        File.open("#{dir}/#{name}.#{node.domain_internal}.yaml", 'w') do |f| +          f.write node.to_yaml +        end +      end +    end + +    ## +    ## FILTERING +    ## + +    # +    # returns a node list consisting only of nodes that satisfy the filter criteria. +    # +    # filter: condition [condition] [condition] [+condition] +    # condition: [node_name | service_name | tag_name] +    # +    # if conditions is prefixed with +, then it works like an AND. Otherwise, it works like an OR. +    # +    def filter(filters) +      if filters.empty? +        return nodes +      end +      if filters[0] =~ /^\+/ +        # don't let the first filter have a + prefix +        filters[0] = filters[0][1..-1] +      end + +      node_list = ConfigList.new +      filters.each do |filter| +        if filter =~ /^\+/ +          keep_list = nodes_for_filter(filter[1..-1]) +          node_list.delete_if do |name, node| +            if keep_list[name] +              false +            else +              true +            end +          end +        else +          node_list << nodes_for_filter(filter) +        end +      end +      return node_list +    end + +    ## +    ## CLASS METHODS +    ## + +    def self.manager +      @manager ||= begin +        manager = ConfigManager.new +        manager.load(Path.provider) +        manager +      end +    end + +    def self.filter(filters); manager.filter(filters); end +    def self.nodes; manager.nodes; end +    def self.services; manager.services; end +    def self.tags; manager.tags; end + +    private + +    def load_all_json(pattern, config_type = :class) +      results = ConfigList.new +      Dir.glob(pattern).each do |filename| +        obj = load_json(filename, config_type) +        if obj +          name = File.basename(filename).sub(/\.json$/,'') +          obj['name'] = name +          results[name] = obj +        end +      end +      results +    end + +    def load_json(filename, config_type) +      log2 { filename.sub(/^#{Regexp.escape(Path.root)}/,'') } + +      # +      # read file, strip out comments +      # (File.read(filename) would be faster, but we like ability to have comments) +      # +      buffer = StringIO.new +      File.open(filename) do |f| +        while (line = f.gets) +          next if line =~ /^\s*#/ +          buffer << line +        end +      end + +      # parse json, and flatten hash +      begin +        hash = Oj.load(buffer.string) || {} +      rescue SyntaxError => exc +        log0 'Error in file "%s":' % filename +        log0 exc.to_s +        return nil +      end +      return flatten_hash(hash, Config.new(config_type, self)) +    end + +    # +    # remove all the nesting from a hash. +    # +    def flatten_hash(input = {}, output = {}, options = {}) +      input.each do |key, value| +        key = options[:prefix].nil? ? "#{key}" : "#{options[:prefix]}#{options[:delimiter]||"_"}#{key}" +        if value.is_a? Hash +          flatten_hash(value, output, :prefix => key, :delimiter => options[:delimiter]) +        else +          output[key]  = value +        end +      end +      output +    end + +    # +    # makes this node inherit options from the common, service, and tag json files. +    # +    def apply_inheritance(node) +      new_node = Config.new(:node, self) +      new_node.merge!(@common) +      if node['services'] +        node['services'].sort.each do |node_service| +          service = @services[node_service] +          if service.nil? +            log0('Error in node "%s": the service "%s" does not exist.' % [node['name'], node_service]) +          else +            new_node.merge!(service) +            service.nodes << node # this is odd, but we want the node pointer, not new_node pointer. +          end +        end +      end +      if node['tags'] +        node['tags'].sort.each do |node_tag| +          tag = @tags[node_tag] +          if tag.nil? +            log0('Error in node "%s": the tag "%s" does not exist.' % [node['name'], node_tag]) +          else +            new_node.merge!(tag) +            tag.nodes << node +          end +        end +      end +      new_node.merge!(node) +      node.replace(new_node) +    end + +    def nodes_for_filter(filter) +      if node = self.nodes[filter] +        ConfigList.new(node) +      elsif service = self.services[filter] +        service.nodes +      elsif tag = self.tags[filter] +        tag.nodes +      end +    end + +  end + +end diff --git a/cli/lib/leap_cli/init.rb b/cli/lib/leap_cli/init.rb new file mode 100644 index 0000000..bebede7 --- /dev/null +++ b/cli/lib/leap_cli/init.rb @@ -0,0 +1,74 @@ +require 'fileutils' + +module LeapCli +  # +  # creates new provider directory +  # +  def self.init(directory) +    dirs = [directory] +    mkdirs(dirs, false, false) + +    Dir.chdir(directory) do +      dirs = ["nodes", "services", "keys", "tags"] +      mkdirs(dirs, false, false) + +      #puts "Creating .provider" +      #FileUtils.touch('.provider') + +      mkfile("provider.json", PROVIDER_CONTENT) +      mkfile("common.json", COMMON_CONTENT) +    end +  end + +  def self.mkfile(filename, content) +    puts "Creating #{filename}" +    File.open(filename, 'w') do |f| +      f.write content +    end +  end + +  def self.mkdirs(dirs,force,dry_run) +    exists = false +    if !force +      dirs.each do |dir| +        if File.exist? dir +          raise "#{dir} exists; use --force to override" +          exists = true +        end +      end +    end +    if !exists +      dirs.each do |dir| +        puts "Creating #{dir}/" +        if dry_run +          puts "dry-run; #{dir} not created" +        else +          FileUtils.mkdir_p dir +        end +      end +    else +      puts "Exiting..." +      return false +    end +    true +  end + +  PROVIDER_CONTENT = <<EOS +# +# Global provider definition file. +# +{ +  "domain": "example.org" +} +EOS + +  COMMON_CONTENT = <<EOS +# +# Options put here are inherited by all nodes. +# +{ +  "domain": "example.org" +} +EOS + +end diff --git a/cli/lib/leap_cli/log.rb b/cli/lib/leap_cli/log.rb new file mode 100644 index 0000000..f51ca1e --- /dev/null +++ b/cli/lib/leap_cli/log.rb @@ -0,0 +1,44 @@ +module LeapCli + +  def self.log_level +    @log_level +  end + +  def self.log_level=(value) +    @log_level = value +  end + +end + +def log0(message=nil, &block) +  if message +    puts message +  elsif block +    puts yield(block) +  end +end + +def log1(message=nil, &block) +  if LeapCli.log_level > 0 +    if message +      puts message +    elsif block +      puts yield(block) +    end +  end +end + +def log2(message=nil, &block) +  if LeapCli.log_level > 1 +    if message +      puts message +    elsif block +      puts yield(block) +    end +  end +end + +def help!(message=nil) +  ENV['GLI_DEBUG'] = "false" +  help_now!(message) +end diff --git a/cli/lib/leap_cli/path.rb b/cli/lib/leap_cli/path.rb new file mode 100644 index 0000000..5dc8fe8 --- /dev/null +++ b/cli/lib/leap_cli/path.rb @@ -0,0 +1,79 @@ +require 'fileutils' + +module LeapCli +  module Path + +    def self.root +      @root ||= File.expand_path("#{provider}/..") +    end + +    def self.platform +      @platform ||= File.expand_path("#{root}/leap_platform") +    end + +    def self.provider +      @provider ||= if @root +        File.expand_path("#{root}/provider") +      else +        find_in_directory_tree('provider.json') +      end +    end + +    def self.hiera +      @hiera ||= "#{provider}/hiera" +    end + +    def self.files +      @files ||= "#{provider}/files" +    end + +    def self.ok? +      provider != '/' +    end + +    def self.set_root(root_path) +      @root = File.expand_path(root_path) +      raise "No such directory '#{@root}'" unless File.directory?(@root) +    end + +    def self.ensure_dir(dir) +      unless File.directory?(dir) +        if File.exists?(dir) +          raise 'Unable to create directory "%s", file already exists.' % dir +        else +          FileUtils.mkdir_p(dir) +        end +      end +    end + +    def self.find_file(name, filename) +      path = [Path.files, filename].join('/') +      return path if File.exists?(path) +      path = [Path.files, name, filename].join('/') +      return path if File.exists?(path) +      path = [Path.files, 'nodes', name, filename].join('/') +      return path if File.exists?(path) +      path = [Path.files, 'services', name, filename].join('/') +      return path if File.exists?(path) +      path = [Path.files, 'tags', name, filename].join('/') +      return path if File.exists?(path) + +      # give up +      return nil +    end + +    private + +    def self.find_in_directory_tree(filename) +      search_dir = Dir.pwd +      while search_dir != "/" +        Dir.foreach(search_dir) do |f| +          return search_dir if f == filename +        end +        search_dir = File.dirname(search_dir) +      end +      return search_dir +    end + +  end +end diff --git a/cli/lib/leap_cli/version.rb b/cli/lib/leap_cli/version.rb new file mode 100644 index 0000000..c272647 --- /dev/null +++ b/cli/lib/leap_cli/version.rb @@ -0,0 +1,3 @@ +module LeapCli +  VERSION = '0.0.1' +end diff --git a/cli/test/default_test.rb b/cli/test/default_test.rb new file mode 100644 index 0000000..c363bbb --- /dev/null +++ b/cli/test/default_test.rb @@ -0,0 +1,14 @@ +require 'test_helper' + +class DefaultTest < Test::Unit::TestCase + +  def setup +  end + +  def teardown +  end + +  def test_the_truth +    assert true +  end +end diff --git a/cli/test/provider/common.json b/cli/test/provider/common.json new file mode 100644 index 0000000..ead9d68 --- /dev/null +++ b/cli/test/provider/common.json @@ -0,0 +1,11 @@ +# +# Options put here are inherited by all nodes. +# +{ +  "domain": { +     "public": "rewire.co", +     "internal": "rewire" +  }, +  "public_dns": true, +  "fqdn": "= name + '.' + (public_dns ? domain_public : domain_internal)" +} diff --git a/cli/test/provider/files/ca/ca.crt b/cli/test/provider/files/ca/ca.crt new file mode 100644 index 0000000..ed12e15 --- /dev/null +++ b/cli/test/provider/files/ca/ca.crt @@ -0,0 +1,24 @@ +-----BEGIN CERTIFICATE----- +MIIECzCCAl2gAwIBAgIEUFDp9TANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDEwRU +RVNUMB4XDTEyMDkxMjIwMDA1M1oXDTEzMDkxMjIwMDA1M1owDzENMAsGA1UEAxME +VEVTVDCCAbgwDQYJKoZIhvcNAQEBBQADggGlADCCAaACggGXANsoS1m9wj9iv+UV +BXfeq14SR94gSot96eJu7PZVRrcGlGe/PRfbmfxF3j/gXM9B8sIkyM2L46OMtOKw +1iOTKtYYdMhtnUSd3FRshWGtYeuy+OCe9umU0jfZDBZ2pXlUmSqCNqfD0OPkksYL +GDjQUKjaEd1oURwpCG8uEU+3tjBNCMuEwhcMEoUYmI8t4vss2hdFb+LKefVMPTzz +oiNM/o8Z/ANzWCC0qSW5FsB4wGhUS5HKLDOr4tACgdxaJSWtAqFFAnyMeG9g8aqe +PTM+URlqVnzzGckrJwBbd4y0zEpv/R7SAiSAP725cnB1GKptwdrcNIIHnQjOdAOl +uNg6JlRXrv6fV1gApka4INfJAf1yMf+fA0WdZ22UJQ9Up7tdzi8lL+3HsEpEx4Pz +NyzuqzEw9LJ6SUmMcE/VP00t4RjTOVoncwcLjvURY8jt2DQ9E36JEPwUoyALq/De +bGBjeK2KGzBZcOu1HZAwWLLWR2++WKuCEXbRbahwSIlbMfmAe8xGx4bbHol0D1A+ +wmu0uxjAze6FvUkCAwEAAaNDMEEwDwYDVR0TAQH/BAUwAwEB/zAPBgNVHQ8BAf8E +BQMDBwQAMB0GA1UdDgQWBBT/PX8XZ0Y2jDkppz6PHs23IgzQEDANBgkqhkiG9w0B +AQsFAAOCAZcAMfi+HLbcFaB0/Mv8/GkIdjpThUBVEeFrIiDy9GmGWUDOXgP1Skld +5H4eY5inE5lFfB69yacHIGS4OiZIBuBKfKNl5d6XO+ztJEJpG3yrbF4MtGV/aHEp +OlbJCncnk3fspBk6tFGrv4Inak4gza6SQPfBEZj29ciwfwrqrtuWZ7km+og0Clcd +pIB0g+DK0K//NtaDZDK0havQw2AFJKyXlNfI8XZ2jsNmQYR1wtiMci+UfGQr7bjn +Kw9yyVCf0ohXvnSK4ortz/bDQbcMWkK0m/VCCEK8PSldk+XFzPWFWn5ndKCczcvd +1BQc392n12ZstEuzm6+d9A0D3kCxralJUXUC+4kThq4Rtjey/gBjyZQnZ+5tIxMF +5ZFAStEglNxqm6HB17q7owJqTvIg9Cf9GATsvoFFQDJrBXewRX7cWVeSr0zNSQB4 +ydIlSUOkyE3AyfLN+lx8NVS/I7gp4fWDuHrh27NKKDtMxalxPL5pTGO7l4uTybLY +4aVzQYGvzA5HVS++VAtcTQ6TP9p4HURL2cllEU9u9A== +-----END CERTIFICATE----- diff --git a/cli/test/provider/files/ca/ca.key b/cli/test/provider/files/ca/ca.key new file mode 100644 index 0000000..9721c35 --- /dev/null +++ b/cli/test/provider/files/ca/ca.key @@ -0,0 +1,41 @@ +-----BEGIN RSA PRIVATE KEY----- +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 +-----END RSA PRIVATE KEY----- diff --git a/cli/test/provider/files/public-definitions/provider.json.erb b/cli/test/provider/files/public-definitions/provider.json.erb new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/cli/test/provider/files/public-definitions/provider.json.erb diff --git a/cli/test/provider/files/vpn1/vpn1.rewire.co.crt b/cli/test/provider/files/vpn1/vpn1.rewire.co.crt new file mode 100644 index 0000000..d2c9734 --- /dev/null +++ b/cli/test/provider/files/vpn1/vpn1.rewire.co.crt @@ -0,0 +1,26 @@ +-----BEGIN CERTIFICATE----- +MIIEWjCCAqygAwIBAgIEUFDqXzANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDEwRU +RVNUMB4XDTEyMDkxMjIwMDIzOVoXDTEzMDkxMjIwMDIzOVowKzEPMA0GA1UEChMG +eHgub3JnMRgwFgYDVQQDEw9ob3N0bmFtZS54eC5vcmcwggG4MA0GCSqGSIb3DQEB +AQUAA4IBpQAwggGgAoIBlwCvGqkXry509EWGAqbFUB5nqvsvA3kSIh0prgzaPYCg +MMst58ZB89eTgiuM+U3jSF7LZr+CuE1DAb4m2U2f8D8IfViwK1yCa5AohG+LCmwe +4w4bgXtxwEBDac4u23JZ4AKE/EcKMeBbXe2d3o1S3P3XdN1ZVP0DVw04+H8cdh+0 +ggvhAA+9W/NvAQCAffL8sospj9nbl2OhRnrlFAzMWECyEyySPK5TEchU0hnFBRys +DuYso5klLC6QXfSOkCSCOg9WQgjoyYBndTYxS3GwBnwyM+5V4TNtdc+P4vkkj+ZB +D9R9oMpamUuuRQvk5/hJa7i8AaBy7ZmOO9QtL3866ONa6cLUN/QfBUkgM5iS6oQt +X/qKxZFFYZPZUGBJqavuT+n4FB8XlIwcnqunK7rLD9OZwumYuZlHDtdAsgQ9Fd2z +06e7sDp28jcrk6gmpOapLqNPtPHVOGNA6mCZza4LonDMOSQKTfb6ZEXty+a8f2ig +zErhHvmyCvREytDc9pIf2bL+Sz4ULTq62GDKf1Y3tRi2uHFjhKLTAgMBAAGjdjB0 +MAwGA1UdEwEB/wQCMAAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYDVR0PAQH/BAUD +AwegADAdBgNVHQ4EFgQUmQ5YZjESlkYq2FBaYqGp2HAnSfAwHwYDVR0jBBgwFoAU +/z1/F2dGNow5Kac+jx7NtyIM0BAwDQYJKoZIhvcNAQELBQADggGXAHiaPMSeIzac +rRZQ/dJA7VDgvuFcY67zj9531zsDVi848kBkpSZ+9UyZOdhy5b9Din/IAVvd/XUP ++VWwVsvKPbrWK79T/w8wj5nQR0uYfLdpMu7ZGjPhNes+/DnMX8Are2eb012g1km/ +HhOUxNg8/YpOJI4ZRnZls7j+u5kmHhc47sOQH9sY1FkHcWJ+K/lVhTk8Fmcm1vbN +p7rjO4BItPVDxle0XF6bItwF1ahsK9MTzJIEO9ulHQnKYdhT9BcJbcwA3vhcn8nN +uPN/RbDcWZTjONy58LVr7GxDQ267nZs5/wj4Cv3vDVq83kQJ7lCsYGTvxOejHWeQ +QjcXREdBih9CPO3f86TOI8GRipIGvDcEll4DzgGRi+uTSWG69uC9yud/7+rnLd9Z +WlobzAzRwljnR3aNACq0adYv1Wl05Fi2ab+QqL/C5ySrF5jL4OFUMpBu7nDPjty0 +KjQSmI9t6By6ORx14XT6piSlvSFn5phdMexXx1AYZEtdPSQduh2OquIPjN/qSdHO +J+ZXOqDL1Jv+a89ghE8= +-----END CERTIFICATE----- diff --git a/cli/test/provider/files/vpn1/vpn1.rewire.co.key b/cli/test/provider/files/vpn1/vpn1.rewire.co.key new file mode 100644 index 0000000..3fdf38a --- /dev/null +++ b/cli/test/provider/files/vpn1/vpn1.rewire.co.key @@ -0,0 +1,41 @@ +-----BEGIN RSA PRIVATE KEY----- +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 +-----END RSA PRIVATE KEY----- diff --git a/cli/test/provider/hiera/couch1.rewire.yaml b/cli/test/provider/hiera/couch1.rewire.yaml new file mode 100644 index 0000000..2c731ce --- /dev/null +++ b/cli/test/provider/hiera/couch1.rewire.yaml @@ -0,0 +1,8 @@ +---  +domain_internal: rewire +domain_public: rewire.co +fqdn: couch1.rewire +ip_address: 245.2.45.42 +name: couch1 +public_dns: false +services: couchdb diff --git a/cli/test/provider/hiera/couch2.rewire.yaml b/cli/test/provider/hiera/couch2.rewire.yaml new file mode 100644 index 0000000..a835c79 --- /dev/null +++ b/cli/test/provider/hiera/couch2.rewire.yaml @@ -0,0 +1,8 @@ +---  +domain_internal: rewire +domain_public: rewire.co +fqdn: couch2.rewire +ip_address: 73.45.87.11 +name: couch2 +public_dns: false +services: couchdb diff --git a/cli/test/provider/hiera/ns1.rewire.yaml b/cli/test/provider/hiera/ns1.rewire.yaml new file mode 100644 index 0000000..264dd52 --- /dev/null +++ b/cli/test/provider/hiera/ns1.rewire.yaml @@ -0,0 +1,25 @@ +---  +domain_internal: rewire +domain_public: rewire.co +fqdn: ns1.rewire.co +hosts_private:  +- ip_address: 245.2.45.42 +  fqdn: couch1.rewire +- ip_address: 73.45.87.11 +  fqdn: couch2.rewire +hosts_public:  +- ip_address: 1.1.1.1 +  fqdn: ns1.rewire.co +- ip_address: 1.1.1.2 +  fqdn: ns2.rewire.co +- ip_address: 2.2.2.2 +  fqdn: vpn1.rewire.co +- ip_address: 6.6.7.7 +  fqdn: web1.rewire.co +  dns_alias: user.rewire.co +ip_address: 1.1.1.1 +name: ns1 +production: true +public_dns: true +services: dns +tags: production diff --git a/cli/test/provider/hiera/ns2.rewire.yaml b/cli/test/provider/hiera/ns2.rewire.yaml new file mode 100644 index 0000000..2885424 --- /dev/null +++ b/cli/test/provider/hiera/ns2.rewire.yaml @@ -0,0 +1,25 @@ +---  +domain_internal: rewire +domain_public: rewire.co +fqdn: ns2.rewire.co +hosts_private:  +- ip_address: 245.2.45.42 +  fqdn: couch1.rewire +- ip_address: 73.45.87.11 +  fqdn: couch2.rewire +hosts_public:  +- ip_address: 1.1.1.1 +  fqdn: ns1.rewire.co +- ip_address: 1.1.1.2 +  fqdn: ns2.rewire.co +- ip_address: 2.2.2.2 +  fqdn: vpn1.rewire.co +- ip_address: 6.6.7.7 +  fqdn: web1.rewire.co +  dns_alias: user.rewire.co +ip_address: 1.1.1.2 +name: ns2 +production: true +public_dns: true +services: dns +tags: production diff --git a/cli/test/provider/hiera/vpn1.rewire.yaml b/cli/test/provider/hiera/vpn1.rewire.yaml new file mode 100644 index 0000000..158bb1b --- /dev/null +++ b/cli/test/provider/hiera/vpn1.rewire.yaml @@ -0,0 +1,158 @@ +---  +domain_internal: rewire +domain_public: rewire.co +fqdn: vpn1.rewire.co +ip_address: 2.2.2.2 +name: vpn1 +openvpn_ca_crt: | +  -----BEGIN CERTIFICATE----- +  MIIECzCCAl2gAwIBAgIEUFDp9TANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDEwRU +  RVNUMB4XDTEyMDkxMjIwMDA1M1oXDTEzMDkxMjIwMDA1M1owDzENMAsGA1UEAxME +  VEVTVDCCAbgwDQYJKoZIhvcNAQEBBQADggGlADCCAaACggGXANsoS1m9wj9iv+UV +  BXfeq14SR94gSot96eJu7PZVRrcGlGe/PRfbmfxF3j/gXM9B8sIkyM2L46OMtOKw +  1iOTKtYYdMhtnUSd3FRshWGtYeuy+OCe9umU0jfZDBZ2pXlUmSqCNqfD0OPkksYL +  GDjQUKjaEd1oURwpCG8uEU+3tjBNCMuEwhcMEoUYmI8t4vss2hdFb+LKefVMPTzz +  oiNM/o8Z/ANzWCC0qSW5FsB4wGhUS5HKLDOr4tACgdxaJSWtAqFFAnyMeG9g8aqe +  PTM+URlqVnzzGckrJwBbd4y0zEpv/R7SAiSAP725cnB1GKptwdrcNIIHnQjOdAOl +  uNg6JlRXrv6fV1gApka4INfJAf1yMf+fA0WdZ22UJQ9Up7tdzi8lL+3HsEpEx4Pz +  NyzuqzEw9LJ6SUmMcE/VP00t4RjTOVoncwcLjvURY8jt2DQ9E36JEPwUoyALq/De +  bGBjeK2KGzBZcOu1HZAwWLLWR2++WKuCEXbRbahwSIlbMfmAe8xGx4bbHol0D1A+ +  wmu0uxjAze6FvUkCAwEAAaNDMEEwDwYDVR0TAQH/BAUwAwEB/zAPBgNVHQ8BAf8E +  BQMDBwQAMB0GA1UdDgQWBBT/PX8XZ0Y2jDkppz6PHs23IgzQEDANBgkqhkiG9w0B +  AQsFAAOCAZcAMfi+HLbcFaB0/Mv8/GkIdjpThUBVEeFrIiDy9GmGWUDOXgP1Skld +  5H4eY5inE5lFfB69yacHIGS4OiZIBuBKfKNl5d6XO+ztJEJpG3yrbF4MtGV/aHEp +  OlbJCncnk3fspBk6tFGrv4Inak4gza6SQPfBEZj29ciwfwrqrtuWZ7km+og0Clcd +  pIB0g+DK0K//NtaDZDK0havQw2AFJKyXlNfI8XZ2jsNmQYR1wtiMci+UfGQr7bjn +  Kw9yyVCf0ohXvnSK4ortz/bDQbcMWkK0m/VCCEK8PSldk+XFzPWFWn5ndKCczcvd +  1BQc392n12ZstEuzm6+d9A0D3kCxralJUXUC+4kThq4Rtjey/gBjyZQnZ+5tIxMF +  5ZFAStEglNxqm6HB17q7owJqTvIg9Cf9GATsvoFFQDJrBXewRX7cWVeSr0zNSQB4 +  ydIlSUOkyE3AyfLN+lx8NVS/I7gp4fWDuHrh27NKKDtMxalxPL5pTGO7l4uTybLY +  4aVzQYGvzA5HVS++VAtcTQ6TP9p4HURL2cllEU9u9A== +  -----END CERTIFICATE----- + +openvpn_ca_key: | +  -----BEGIN RSA PRIVATE KEY----- +  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 +  -----END RSA PRIVATE KEY----- + +openvpn_filter_dns: false +openvpn_gateway_address: 3.3.3.3 +openvpn_nat: true +openvpn_ports:  +- "80" +- "443" +- "53" +- "1194" +openvpn_server_crt: | +  -----BEGIN CERTIFICATE----- +  MIIEWjCCAqygAwIBAgIEUFDqXzANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDEwRU +  RVNUMB4XDTEyMDkxMjIwMDIzOVoXDTEzMDkxMjIwMDIzOVowKzEPMA0GA1UEChMG +  eHgub3JnMRgwFgYDVQQDEw9ob3N0bmFtZS54eC5vcmcwggG4MA0GCSqGSIb3DQEB +  AQUAA4IBpQAwggGgAoIBlwCvGqkXry509EWGAqbFUB5nqvsvA3kSIh0prgzaPYCg +  MMst58ZB89eTgiuM+U3jSF7LZr+CuE1DAb4m2U2f8D8IfViwK1yCa5AohG+LCmwe +  4w4bgXtxwEBDac4u23JZ4AKE/EcKMeBbXe2d3o1S3P3XdN1ZVP0DVw04+H8cdh+0 +  ggvhAA+9W/NvAQCAffL8sospj9nbl2OhRnrlFAzMWECyEyySPK5TEchU0hnFBRys +  DuYso5klLC6QXfSOkCSCOg9WQgjoyYBndTYxS3GwBnwyM+5V4TNtdc+P4vkkj+ZB +  D9R9oMpamUuuRQvk5/hJa7i8AaBy7ZmOO9QtL3866ONa6cLUN/QfBUkgM5iS6oQt +  X/qKxZFFYZPZUGBJqavuT+n4FB8XlIwcnqunK7rLD9OZwumYuZlHDtdAsgQ9Fd2z +  06e7sDp28jcrk6gmpOapLqNPtPHVOGNA6mCZza4LonDMOSQKTfb6ZEXty+a8f2ig +  zErhHvmyCvREytDc9pIf2bL+Sz4ULTq62GDKf1Y3tRi2uHFjhKLTAgMBAAGjdjB0 +  MAwGA1UdEwEB/wQCMAAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYDVR0PAQH/BAUD +  AwegADAdBgNVHQ4EFgQUmQ5YZjESlkYq2FBaYqGp2HAnSfAwHwYDVR0jBBgwFoAU +  /z1/F2dGNow5Kac+jx7NtyIM0BAwDQYJKoZIhvcNAQELBQADggGXAHiaPMSeIzac +  rRZQ/dJA7VDgvuFcY67zj9531zsDVi848kBkpSZ+9UyZOdhy5b9Din/IAVvd/XUP +  +VWwVsvKPbrWK79T/w8wj5nQR0uYfLdpMu7ZGjPhNes+/DnMX8Are2eb012g1km/ +  HhOUxNg8/YpOJI4ZRnZls7j+u5kmHhc47sOQH9sY1FkHcWJ+K/lVhTk8Fmcm1vbN +  p7rjO4BItPVDxle0XF6bItwF1ahsK9MTzJIEO9ulHQnKYdhT9BcJbcwA3vhcn8nN +  uPN/RbDcWZTjONy58LVr7GxDQ267nZs5/wj4Cv3vDVq83kQJ7lCsYGTvxOejHWeQ +  QjcXREdBih9CPO3f86TOI8GRipIGvDcEll4DzgGRi+uTSWG69uC9yud/7+rnLd9Z +  WlobzAzRwljnR3aNACq0adYv1Wl05Fi2ab+QqL/C5ySrF5jL4OFUMpBu7nDPjty0 +  KjQSmI9t6By6ORx14XT6piSlvSFn5phdMexXx1AYZEtdPSQduh2OquIPjN/qSdHO +  J+ZXOqDL1Jv+a89ghE8= +  -----END CERTIFICATE----- + +openvpn_server_key: | +  -----BEGIN RSA PRIVATE KEY----- +  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 +  -----END RSA PRIVATE KEY----- + +production: true +public_dns: true +services: openvpn +tags: production diff --git a/cli/test/provider/hiera/web1.rewire.yaml b/cli/test/provider/hiera/web1.rewire.yaml new file mode 100644 index 0000000..6fc76d9 --- /dev/null +++ b/cli/test/provider/hiera/web1.rewire.yaml @@ -0,0 +1,16 @@ +---  +dns_alias: user.rewire.co +domain_internal: rewire +domain_public: rewire.co +fqdn: web1.rewire.co +ip_address: 6.6.7.7 +name: web1 +public_dns: true +services: webapp +webapp_couchdb_hosts:  +- couch1.rewire +- couch2.rewire +webapp_modules:  +- user +- billing +- help diff --git a/cli/test/provider/nodes/couch1.json b/cli/test/provider/nodes/couch1.json new file mode 100644 index 0000000..fe5d7e5 --- /dev/null +++ b/cli/test/provider/nodes/couch1.json @@ -0,0 +1,4 @@ +{ +  "services": "couchdb", +  "ip_address": "245.2.45.42" +}
\ No newline at end of file diff --git a/cli/test/provider/nodes/couch2.json b/cli/test/provider/nodes/couch2.json new file mode 100644 index 0000000..1fe2977 --- /dev/null +++ b/cli/test/provider/nodes/couch2.json @@ -0,0 +1,4 @@ +{ +  "services": "couchdb", +  "ip_address": "73.45.87.11" +}
\ No newline at end of file diff --git a/cli/test/provider/nodes/ns1.json b/cli/test/provider/nodes/ns1.json new file mode 100644 index 0000000..6323d10 --- /dev/null +++ b/cli/test/provider/nodes/ns1.json @@ -0,0 +1,8 @@ +# +# this is a comment +# +{ +  "services": "dns", +  "tags": "production", +  "ip_address": "1.1.1.1" +}
\ No newline at end of file diff --git a/cli/test/provider/nodes/ns2.json b/cli/test/provider/nodes/ns2.json new file mode 100644 index 0000000..eeba9df --- /dev/null +++ b/cli/test/provider/nodes/ns2.json @@ -0,0 +1,8 @@ +# +# A nameserver +# +{ +  "services": "dns", +  "tags": "production", +  "ip_address": "1.1.1.2" +}
\ No newline at end of file diff --git a/cli/test/provider/nodes/vpn1.json b/cli/test/provider/nodes/vpn1.json new file mode 100644 index 0000000..10859ac --- /dev/null +++ b/cli/test/provider/nodes/vpn1.json @@ -0,0 +1,8 @@ +{ +  "services": "openvpn", +  "ip_address": "2.2.2.2", +  "tags": "production", +  "openvpn": { +    "gateway_address": "3.3.3.3" +  } +}
\ No newline at end of file diff --git a/cli/test/provider/nodes/web1.json b/cli/test/provider/nodes/web1.json new file mode 100644 index 0000000..894fb6e --- /dev/null +++ b/cli/test/provider/nodes/web1.json @@ -0,0 +1,4 @@ +{ +  "services": "webapp", +  "ip_address": "6.6.7.7" +}
\ No newline at end of file diff --git a/cli/test/provider/provider.json b/cli/test/provider/provider.json new file mode 100644 index 0000000..58b6728 --- /dev/null +++ b/cli/test/provider/provider.json @@ -0,0 +1,13 @@ +# +# General service provider configuration. +# +{ +  "name": "The Rewire Company", +  "description": "A demonstration service provider using the LEAP platform", +  "languages": ["en"], +  "ca": { +    "name": "Rewire Root CA", +    "organization": "#{name}", +    "bit_size": 4096 +  } +}
\ No newline at end of file diff --git a/cli/test/provider/services/couchdb.json b/cli/test/provider/services/couchdb.json new file mode 100644 index 0000000..7c13c8d --- /dev/null +++ b/cli/test/provider/services/couchdb.json @@ -0,0 +1,3 @@ +{ +  "public_dns": false +}
\ No newline at end of file diff --git a/cli/test/provider/services/dns.json b/cli/test/provider/services/dns.json new file mode 100644 index 0000000..3fea381 --- /dev/null +++ b/cli/test/provider/services/dns.json @@ -0,0 +1,6 @@ +{ +  "hosts": { +    "public":  "= nodes[:public_dns => true].fields(:fqdn, :dns_alias, :ip_address)", +    "private": "= nodes[:public_dns => false].fields(:fqdn, :dns_alias, :ip_address)" +  } +}
\ No newline at end of file diff --git a/cli/test/provider/services/openvpn.json b/cli/test/provider/services/openvpn.json new file mode 100644 index 0000000..ffaa313 --- /dev/null +++ b/cli/test/provider/services/openvpn.json @@ -0,0 +1,11 @@ +{ +  "openvpn": { +    "ports": ["80", "443", "53", "1194"], +    "filter_dns": false, +    "nat": true, +    "ca_crt": "= file 'ca/ca.crt'", +    "ca_key": "= file 'ca/ca.key'", +    "server_crt": "= file fqdn + '.crt'", +    "server_key": "= file fqdn + '.key'" +  } +} diff --git a/cli/test/provider/services/webapp.json b/cli/test/provider/services/webapp.json new file mode 100644 index 0000000..1513d6f --- /dev/null +++ b/cli/test/provider/services/webapp.json @@ -0,0 +1,7 @@ +{ +  "dns_alias": "= 'user.' + domain_public", +  "webapp": { +    "modules": ["user", "billing", "help"], +    "couchdb_hosts": "= nodes[:services => :couchdb].field(:fqdn)" +  } +}
\ No newline at end of file diff --git a/cli/test/provider/tags/production.json b/cli/test/provider/tags/production.json new file mode 100644 index 0000000..b35c065 --- /dev/null +++ b/cli/test/provider/tags/production.json @@ -0,0 +1,3 @@ +{ +  "production": true +}
\ No newline at end of file diff --git a/cli/test/test_helper.rb b/cli/test/test_helper.rb new file mode 100644 index 0000000..2e33705 --- /dev/null +++ b/cli/test/test_helper.rb @@ -0,0 +1,9 @@ +require 'test/unit' + +# Add test libraries you want to use here, e.g. mocha + +class Test::Unit::TestCase + +  # Add global extensions to the test case class here +   +end | 
