]> gitweb.fluxo.info Git - leap/leap_cli.git/commitdiff
new system for how directory paths work. now there is a file Leapfile that manages...
authorelijah <elijah@riseup.net>
Thu, 29 Nov 2012 04:14:05 +0000 (20:14 -0800)
committerelijah <elijah@riseup.net>
Thu, 29 Nov 2012 04:14:05 +0000 (20:14 -0800)
README.md
lib/leap_cli.rb
lib/leap_cli/commands/node.rb
lib/leap_cli/commands/pre.rb
lib/leap_cli/commands/project.rb
lib/leap_cli/init.rb [deleted file]
lib/leap_cli/leapfile.rb [new file with mode: 0644]
lib/leap_cli/path.rb
lib/leap_cli/util.rb

index fc1acdd5fc897b02f59a961e05460c9120a6c46a..5da7ba6be5d9e86bd7007faebadbf6ec565919a5 100644 (file)
--- a/README.md
+++ b/README.md
@@ -27,31 +27,32 @@ Run `leap help` for a usage instructions.
 
 Here is an example usage:
 
-    leap new-provider provider
+    mkdir provider
     cd provider
-    edit configuration files (see below)
+    leap init --domain example.org .
+    leap node add vpn1 --service openvpn
     leap compile
 
 Directories and Files
 =================================
 
-The general structure of leap project looks like this:
+A leap project consistents of two directories:
 
-    my_leap_project/                 # your project directory
-      leap_platform/                 # a clone of the leap_platform puppet recipes
-      provider/                      # your provider-specific configurations
+* provider directory: this is the directory where all your configurations live. By definition, a provider directory contains a file named Leapfile.
+* platform directory: this is the directory where the puppet recipes live. The path to this directory is specified in the Leapfile. Typically, the platform directory will be a clone or branch of git://leap.se/leap_platform.
 
-The "leap" command should be run from within the "provider" directory.
+The "leap" command must always be run under provider directory (or one of its children).
 
-Within the "provider" 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
+    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
+    hiera/             # compile yaml files that contain everything needed to deploy a particular node.
+    common.yaml        # all nodes inherit these options
+    provider.yaml      # global service provider definition
 
 Configuration Files
 =================================
@@ -101,8 +102,7 @@ The following methods are available to the evaluated ruby:
 * global.tags -- A list of all tags.
 
 * file(file_path) -- Inserts the full contents of the file. If the file is an erb
-  template, it is rendered. The file is searched for by first checking platform
-  and then provider/files,
+  template, it is rendered.
 
 * variable -- Any variable inherited by a particular node is available
   by just referencing it using either hash notation or object notation
index 3f35cd48a6933f15f033d856a8b8c1698f492334..f65f131eb84170e558825c4de053785082f7a586 100644 (file)
@@ -2,13 +2,13 @@ module LeapCli; end
 
 require 'leap_cli/version.rb'
 require 'leap_cli/requirements.rb'
+require 'leap_cli/leapfile.rb'
 require 'core_ext/hash'
 require 'core_ext/boolean'
 require 'core_ext/nil'
 require 'core_ext/string'
 
 require 'leap_cli/log'
-require 'leap_cli/init'
 require 'leap_cli/path'
 require 'leap_cli/util'
 require 'leap_cli/util/secret'
index 678bebd4cad585f2ee6b8282bc7d1810462c58df..aa9610f0aa3cb0922b7e7f1d673ea1c81c4c874d 100644 (file)
@@ -6,11 +6,13 @@ module LeapCli; module Commands
   ##
   ## COMMANDS
   ##
+
   desc 'Node management'
   command :node do |c|
     c.desc 'Create a new configuration file for a node'
     c.command :add do |c|
       c.action do |global_options,options,args|
+        log 'not yet implemented'
       end
     end
 
@@ -34,6 +36,7 @@ module LeapCli; module Commands
     c.desc 'Renames a node file, and all its related files'
     c.command :mv do |c|
       c.action do |global_options,options,args|
+        log 'not yet implemented'
       end
     end
 
@@ -41,7 +44,7 @@ module LeapCli; module Commands
     c.arg_name '<node-name>', :optional => false, :multiple => false
     c.command :rm do |c|
       c.action do |global_options,options,args|
-        remove_file!()
+        log 'not yet implemented'
       end
     end
   end
index dce01eb9aef6c7b255b37c0b3dea660750cdd97e..cae787e369dc3703d95bedcfb2b02b1f3c3e2c48 100644 (file)
@@ -10,11 +10,6 @@ module LeapCli
     default_value '1'
     flag [:v, :verbose]
 
-    desc 'Specify the root directory'
-    arg_name 'path'
-    default_value Path.root
-    flag [:root]
-
     desc 'Display version number and exit'
     switch :version, :negatable => false
 
@@ -30,17 +25,18 @@ module LeapCli
       end
 
       #
-      # require a root directory
+      # load Leapfile
       #
-      if global[:root]
-        Path.set_root(global[:root])
+      unless LeapCli.leapfile.load
+        bail! { log :missing, 'Leapfile in directory tree' }
       end
-      if Path.ok?
-        true
-      else
-        bail! do
-          log :error, "- Could not find the root directory. Change current working directory or try --root"
-        end
+      Path.set_platform_path(LeapCli.leapfile.platform_directory_path)
+      Path.set_provider_path(LeapCli.leapfile.provider_directory_path)
+      if !Path.provider || !File.directory?(Path.provider)
+        bail! { log :missing, "provider directory '#{Path.provider}'" }
+      end
+      if !Path.platform || !File.directory?(Path.platform)
+        bail! { log :missing, "platform directory '#{Path.platform}'" }
       end
 
       #
index c7481286f0683fcd24c7fc8f9eb8ad2ae58ad316..2f36bc5564e8a2252c3e06a59d5667fe1f687628 100644 (file)
-module LeapCli
-  module Commands
-
-    desc 'Creates a new provider directory.'
-    arg_name '<directory>'
-    skips_pre
-    command :'init-provider' do |c|
-      c.action do |global_options,options,args|
-        directory = args.first
-        unless directory && directory.any?
-          help! "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)
+require 'fileutils'
+
+module LeapCli; module Commands
+
+  desc 'Initializes a new LEAP provider in the specified directory.'
+  arg_name 'directory-path'
+  skips_pre
+  command :init do |c|
+    c.flag 'name', :desc => "The name of the provider", :default_value => 'Example'
+    c.flag 'domain', :desc => "The primary domain of the provider", :default_value => 'example.org'
+    c.flag 'platform', :desc => "File path of the leap_platform directory", :default_value => '../leap_platform'
+    c.action do |global_options, options, args|
+      directory = args.first
+      unless directory && directory.any?
+        help! "Directory name is required."
+      end
+      directory = File.expand_path(directory)
+      unless File.exists?(directory)
+        bail! { log :missing, "directory #{directory}" }
+      end
+      create_initial_provider_files(directory, options)
+    end
+  end
+
+  private
+
+  DEFAULT_REPO = 'git://leap.se/leap_platform' # TODO: use https
+
+  #
+  # creates new provider directory
+  #
+  def create_initial_provider_files(directory, options)
+    Path.set_provider_path(directory)
+    Dir.chdir(directory) do
+      assert_files_missing! 'provider.json', 'common.json', 'Leapfile', :base => directory
+
+      platform_dir = File.expand_path(options[:platform])
+
+      unless File.symlink?(platform_dir) || File.directory?(platform_dir)
+        if agree("The platform directory \"#{options[:platform]}\" does not exist.\nDo you want me to create it by cloning from the\ngit repository #{DEFAULT_REPO}? ")
+          assert_bin! 'git'
+          ensure_dir platform_dir
+          Dir.chdir(platform_dir) do
+            log :cloning, "leap_platform into #{platform_dir}"
+            pty_run "git clone --branch develop #{DEFAULT_REPO} ."
+            pty_run 'git submodule update --init'
+          end
         else
-          puts "OK, bye."
+          bail!
         end
       end
+      write_file! '.gitignore', GITIGNORE_CONTENT
+      write_file! 'provider.json', provider_content(options)
+      write_file! 'common.json', COMMON_CONTENT
+      write_file! 'Leapfile', leapfile_content(options)
+      ["nodes", "services", "tags"].each do |dir|
+        ensure_dir dir
+      end
+      log :completed, 'initialization'
     end
   end
-end
\ No newline at end of file
+
+  def leapfile_content(options)
+    %[@platform_directory_path = "#{options[:platform]}"
+]
+    # leap_version = "#{LeapCli::VERSION}"
+    # platform_version = ""
+  end
+
+  GITIGNORE_CONTENT = <<EOS
+test/Vagrantfile
+test/.vagrant
+test/openvpn
+test/cert
+EOS
+
+  def provider_content(options)
+  %[#
+# General service provider configuration.
+#
+{
+  "domain": "#{options[:domain]}",
+  "name": {
+    "en": "#{options[:name]}"
+  },
+  "description": {
+    "en": "You really should change this text"
+  },
+  "languages": ["en"],
+  "default_language": "en",
+  "enrollment_policy": "open"
+}
+]
+  end
+
+  COMMON_CONTENT = <<EOS
+#
+# Options put here are inherited by all nodes.
+#
+{
+}
+EOS
+
+end; end
+
+
diff --git a/lib/leap_cli/init.rb b/lib/leap_cli/init.rb
deleted file mode 100644 (file)
index bebede7..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-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/lib/leap_cli/leapfile.rb b/lib/leap_cli/leapfile.rb
new file mode 100644 (file)
index 0000000..2559864
--- /dev/null
@@ -0,0 +1,43 @@
+#
+# The Leapfile is the bootstrap configuration file for a LEAP provider.
+#
+# It is akin to a Gemfile, Rakefile, or Capfile (e.g. it is a ruby file that gets eval'ed)
+#
+
+module LeapCli
+  def self.leapfile
+    @leapfile ||= Leapfile.new
+  end
+
+  class Leapfile
+    attr_accessor :platform_directory_path
+    attr_accessor :provider_directory_path
+
+    def load
+      directory = File.expand_path(find_in_directory_tree('Leapfile'))
+      if directory == '/'
+        return nil
+      else
+        self.provider_directory_path = directory
+        leapfile = directory + '/Leapfile'
+        instance_eval(File.read(leapfile), leapfile)
+        self.platform_directory_path = File.expand_path(self.platform_directory_path || '../leap_platform', self.provider_directory_path)
+        return true
+      end
+    end
+
+    private
+
+    def 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
+
index 27ffcce944bb91f291b007b315030f3f6b05a40c..20994f4caa37b0a2502303051c2b5a42358b1934 100644 (file)
@@ -53,35 +53,8 @@ module LeapCli; module Path
     :test_client_openvpn_template => 'test/openvpn/client.ovpn.erb'
   }
 
-  #
-  # required file structure
-  #
-  # Option 1 -- A project directory with platform and provider directories
-  #
-  #  -: $root
-  #   :-- leap_platform
-  #   '-: provider
-  #     '-- provider.json
-  #
-  #  $root can be any name
-  #
-  # Option 2 -- A stand alone provider directory
-  #
-  #  -: $provider
-  #   '-- provider.json
-  #
-  #  $provider can be any name. Some commands are not available.
-  #
-  # In either case, the 'leap' command must be run from inside the provider directory or
-  # you must specify root directory with --root=dir.
-  #
-
-  def self.root
-    @root ||= File.expand_path("#{provider}/..")
-  end
-
   def self.platform
-    @platform ||= File.expand_path("#{root}/leap_platform")
+    @platform
   end
 
   def self.provider_base
@@ -93,41 +66,16 @@ module LeapCli; module Path
   end
 
   def self.provider
-    @provider ||= if @root
-      File.expand_path("#{root}/provider")
-    else
-      find_in_directory_tree('provider.json')
-    end
+    @provider
   end
 
-  def self.ok?
-    provider != '/'
+  def self.set_provider_path(provider)
+    @provider = provider
   end
-
-  def self.set_root(root_path)
-    @root = File.expand_path(root_path)
-    raise "No such directory '#{@root}'" unless File.directory?(@root)
+  def self.set_platform_path(platform)
+    @platform = platform
   end
 
-  #
-  # all the places we search for a file when using find_file.
-  # this is perhaps too many places.
-  #
-  # def self.search_path
-  #   @search_path ||= begin
-  #     search_path = []
-  #     [Path.provider_base, Path.provider].each do |provider|
-  #       #files_dir = named_path(:files_dir, provider)
-  #       search_path << provider
-  #       #search_path << named_path(:files_dir, provider)
-  #       #search_path << named_path(:nodes_dir, files_dir)
-  #       #search_path << named_path(:services_dir, files_dir)
-  #       #search_path << named_path(:tags_dir, files_dir)
-  #     end
-  #     search_path
-  #   end
-  # end
-
   #
   # tries to find a file somewhere
   #
@@ -174,22 +122,9 @@ module LeapCli; module Path
     File.exists?(named_path(name, provider_dir))
   end
 
-  def self.relative_path(path)
-    path = named_path(path)
-    path.sub(/^#{Regexp.escape(provider)}\//,'')
-  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
+  def self.relative_path(path, provider_dir=Path.provider)
+    path = named_path(path, provider_dir)
+    path.sub(/^#{Regexp.escape(provider_dir)}\//,'')
   end
 
 end; end
index 967acca810af9db5768f175bb042aea8a2688800..98c3002f90ab777eec189556bd87a40b8e4d95de 100644 (file)
@@ -2,6 +2,7 @@ require 'digest/md5'
 require 'paint'
 require 'fileutils'
 require 'erb'
+require 'pty'
 
 module LeapCli
   module Util
@@ -84,9 +85,10 @@ module LeapCli
 
     def assert_files_missing!(*files)
       options = files.last.is_a?(Hash) ? files.pop : {}
+      base = options[:base] || Path.provider
       file_list = files.collect { |file_path|
-        file_path = Path.named_path(file_path)
-        File.exists?(file_path) ? Path.relative_path(file_path) : nil
+        file_path = Path.named_path(file_path, base)
+        File.exists?(file_path) ? Path.relative_path(file_path, base) : nil
       }.compact
       if file_list.length > 1
         bail! do
@@ -280,6 +282,21 @@ module LeapCli
       STDOUT.puts
     end
 
+    #
+    # runs a command in a pseudo terminal
+    #
+    def pty_run(cmd)
+      PTY.spawn(cmd) do |output, input, pid|
+        begin
+          while line = output.gets do
+            puts line
+          end
+        rescue Errno::EIO
+        end
+      end
+    rescue PTY::ChildExited
+    end
+
     ##
     ## ERB
     ##