aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorelijah <elijah@riseup.net>2012-11-28 20:14:05 -0800
committerelijah <elijah@riseup.net>2012-11-28 20:14:05 -0800
commite5ed1ba2df6f735e32de35d9171d572dce322b7f (patch)
tree1a9120599adc7215edee5cf36ef27511823dd819
parente2c31618b6f70d86c55c348436dd600b2e4ace21 (diff)
downloadleap_cli-e5ed1ba2df6f735e32de35d9171d572dce322b7f.tar.gz
leap_cli-e5ed1ba2df6f735e32de35d9171d572dce322b7f.tar.bz2
new system for how directory paths work. now there is a file Leapfile that manages this, instead of it always being ../leap_platform
-rw-r--r--README.md34
-rw-r--r--lib/leap_cli.rb2
-rw-r--r--lib/leap_cli/commands/node.rb5
-rw-r--r--lib/leap_cli/commands/pre.rb24
-rw-r--r--lib/leap_cli/commands/project.rb121
-rw-r--r--lib/leap_cli/init.rb74
-rw-r--r--lib/leap_cli/leapfile.rb43
-rw-r--r--lib/leap_cli/path.rb83
-rw-r--r--lib/leap_cli/util.rb21
9 files changed, 204 insertions, 203 deletions
diff --git a/README.md b/README.md
index fc1acdd..5da7ba6 100644
--- 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
diff --git a/lib/leap_cli.rb b/lib/leap_cli.rb
index 3f35cd4..f65f131 100644
--- a/lib/leap_cli.rb
+++ b/lib/leap_cli.rb
@@ -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'
diff --git a/lib/leap_cli/commands/node.rb b/lib/leap_cli/commands/node.rb
index 678bebd..aa9610f 100644
--- a/lib/leap_cli/commands/node.rb
+++ b/lib/leap_cli/commands/node.rb
@@ -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
diff --git a/lib/leap_cli/commands/pre.rb b/lib/leap_cli/commands/pre.rb
index dce01eb..cae787e 100644
--- a/lib/leap_cli/commands/pre.rb
+++ b/lib/leap_cli/commands/pre.rb
@@ -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
#
diff --git a/lib/leap_cli/commands/project.rb b/lib/leap_cli/commands/project.rb
index c748128..2f36bc5 100644
--- a/lib/leap_cli/commands/project.rb
+++ b/lib/leap_cli/commands/project.rb
@@ -1,25 +1,106 @@
-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
index bebede7..0000000
--- a/lib/leap_cli/init.rb
+++ /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
index 0000000..2559864
--- /dev/null
+++ b/lib/leap_cli/leapfile.rb
@@ -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
+
diff --git a/lib/leap_cli/path.rb b/lib/leap_cli/path.rb
index 27ffcce..20994f4 100644
--- a/lib/leap_cli/path.rb
+++ b/lib/leap_cli/path.rb
@@ -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,42 +66,17 @@ 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
#
def self.find_file(arg)
@@ -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
diff --git a/lib/leap_cli/util.rb b/lib/leap_cli/util.rb
index 967acca..98c3002 100644
--- a/lib/leap_cli/util.rb
+++ b/lib/leap_cli/util.rb
@@ -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
##