From a27c9e53f46700acb79b33173060e45c97c183c2 Mon Sep 17 00:00:00 2001 From: elijah Date: Thu, 18 Dec 2014 10:15:08 -0800 Subject: added info note to leap db destroy --- lib/leap_cli/commands/db.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/leap_cli/commands/db.rb b/lib/leap_cli/commands/db.rb index ea83b0c..fd50424 100644 --- a/lib/leap_cli/commands/db.rb +++ b/lib/leap_cli/commands/db.rb @@ -17,6 +17,7 @@ module LeapCli; module Commands ssh.run('/etc/init.d/bigcouch stop && test ! -z "$(ls /opt/bigcouch/var/lib/ 2> /dev/null)" && rm -r /opt/bigcouch/var/lib/* && echo "db destroyed" || echo "db already destroyed"') ssh.run('grep ^seq_file /etc/leap/tapicero.yaml | cut -f2 -d\" | xargs rm -v') end + say 'You must run `leap deploy` in order to create the databases again.' else say 'No nodes' end -- cgit v1.2.3 From 5dbbc5ba6d4e83f11bf4787dc020865001ad8ef4 Mon Sep 17 00:00:00 2001 From: elijah Date: Mon, 5 Jan 2015 13:52:25 -0800 Subject: omit underscore from random alpha secrets in secrets.json --- lib/leap_cli/util/secret.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/leap_cli/util/secret.rb b/lib/leap_cli/util/secret.rb index 837a0af..749b959 100644 --- a/lib/leap_cli/util/secret.rb +++ b/lib/leap_cli/util/secret.rb @@ -8,7 +8,7 @@ autoload :OpenSSL, 'openssl' module LeapCli; module Util class Secret - CHARS = ('A'..'Z').to_a + ('a'..'z').to_a + ('0'..'9').to_a + "_".split(//u) - "io01lO".split(//u) + CHARS = (('A'..'Z').to_a + ('a'..'z').to_a + ('0'..'9').to_a) - "i1loO06G".split(//u) HEX = (0..9).to_a + ('a'..'f').to_a # -- cgit v1.2.3 From 0bb30766e6f6fe1832343132b3433533e7b314a0 Mon Sep 17 00:00:00 2001 From: elijah Date: Thu, 22 Jan 2015 14:12:14 -0800 Subject: added support for custom tests in files/tests --- lib/leap_cli/commands/deploy.rb | 29 +++++++++++++++++++-------- lib/leap_cli/util.rb | 44 ++++++++++++++++++++++++++--------------- 2 files changed, 49 insertions(+), 24 deletions(-) diff --git a/lib/leap_cli/commands/deploy.rb b/lib/leap_cli/commands/deploy.rb index e413807..dbbaaba 100644 --- a/lib/leap_cli/commands/deploy.rb +++ b/lib/leap_cli/commands/deploy.rb @@ -177,17 +177,11 @@ module LeapCli # def sync_support_files(ssh) dest_dir = Leap::Platform.files_dir - source_files = [] - if Path.defined?(:custom_puppet_dir) && file_exists?(:custom_puppet_dir) - source_files += [:custom_puppet_dir, :custom_puppet_modules_dir, :custom_puppet_manifests_dir].collect{|path| - Path.relative_path(path, Path.provider) + '/' # rsync needs trailing slash - } - ensure_dir :custom_puppet_modules_dir - end + custom_files = build_custom_file_list ssh.rsync.update do |server| node = manager.node(server.host) files_to_sync = node.file_paths.collect {|path| Path.relative_path(path, Path.provider) } - files_to_sync += source_files + files_to_sync += custom_files if files_to_sync.any? ssh.leap.log(files_to_sync.join(', ') + ' -> ' + node.name + ':' + dest_dir) { @@ -282,5 +276,24 @@ module LeapCli tags.join(',') end + # + # a provider might have various customization files that should be sync'ed to the server. + # this method builds that list of files to sync. + # + def build_custom_file_list + custom_files = [] + Leap::Platform.paths.keys.grep(/^custom_/).each do |path| + if file_exists?(path) + relative_path = Path.relative_path(path, Path.provider) + if dir_exists?(path) + custom_files << relative_path + '/' # rsync needs trailing slash + else + custom_files << relative_path + end + end + end + return custom_files + end + end end diff --git a/lib/leap_cli/util.rb b/lib/leap_cli/util.rb index ce5471c..9edb150 100644 --- a/lib/leap_cli/util.rb +++ b/lib/leap_cli/util.rb @@ -97,6 +97,23 @@ module LeapCli return output end + def assert_config!(conf_path) + value = nil + begin + value = manager.instance_eval(conf_path) + #rescue NoMethodError + #rescue NameError + ensure + assert! !value.nil? && value != "REQUIRED" do + log :missing, "required configuration value for #{conf_path}" + end + end + end + + ## + ## FILES AND DIRECTORIES + ## + def assert_files_missing!(*files) options = files.last.is_a?(Hash) ? files.pop : {} base = options[:base] || Path.provider @@ -117,19 +134,6 @@ module LeapCli end end - def assert_config!(conf_path) - value = nil - begin - value = manager.instance_eval(conf_path) - #rescue NoMethodError - #rescue NameError - ensure - assert! !value.nil? && value != "REQUIRED" do - log :missing, "required configuration value for #{conf_path}" - end - end - end - def assert_files_exist!(*files) options = files.last.is_a?(Hash) ? files.pop : {} file_list = files.collect { |file_path| @@ -149,6 +153,7 @@ module LeapCli end end + # takes a list of symbolic paths. returns true if all files exist or are directories. def file_exists?(*files) files.each do |file_path| file_path = Path.named_path(file_path) @@ -159,9 +164,16 @@ module LeapCli return true end - ## - ## FILES AND DIRECTORIES - ## + # takes a list of symbolic paths. returns true if all are directories. + def dir_exists?(*dirs) + dirs.each do |dir_path| + dir_path = Path.named_path(dir_path) + if !Dir.exists?(dir_path) + return false + end + end + return true + end # # creates a directory if it doesn't already exist -- cgit v1.2.3 From 84ae4c6eba59efc683e102245e0da03b782ea067 Mon Sep 17 00:00:00 2001 From: elijah Date: Wed, 28 Jan 2015 11:59:39 -0800 Subject: remove deprecated OpenSSL::Digest::Digest with OpenSSL::Digest --- vendor/certificate_authority/lib/certificate_authority/certificate.rb | 4 ++-- .../lib/certificate_authority/certificate_revocation_list.rb | 4 ++-- .../lib/certificate_authority/signing_request.rb | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/vendor/certificate_authority/lib/certificate_authority/certificate.rb b/vendor/certificate_authority/lib/certificate_authority/certificate.rb index 3fcae90..496d91e 100644 --- a/vendor/certificate_authority/lib/certificate_authority/certificate.rb +++ b/vendor/certificate_authority/lib/certificate_authority/certificate.rb @@ -108,9 +108,9 @@ module CertificateAuthority end if signing_profile["digest"].nil? - digest = OpenSSL::Digest::Digest.new("SHA512") + digest = OpenSSL::Digest.new("SHA512") else - digest = OpenSSL::Digest::Digest.new(signing_profile["digest"]) + digest = OpenSSL::Digest.new(signing_profile["digest"]) end self.openssl_body = openssl_cert.sign(parent.key_material.private_key, digest) diff --git a/vendor/certificate_authority/lib/certificate_authority/certificate_revocation_list.rb b/vendor/certificate_authority/lib/certificate_authority/certificate_revocation_list.rb index e222e26..c84d588 100644 --- a/vendor/certificate_authority/lib/certificate_authority/certificate_revocation_list.rb +++ b/vendor/certificate_authority/lib/certificate_authority/certificate_revocation_list.rb @@ -59,9 +59,9 @@ module CertificateAuthority signing_cert = OpenSSL::X509::Certificate.new(self.parent.to_pem) if signing_profile["digest"].nil? - digest = OpenSSL::Digest::Digest.new("SHA512") + digest = OpenSSL::Digest.new("SHA512") else - digest = OpenSSL::Digest::Digest.new(signing_profile["digest"]) + digest = OpenSSL::Digest.new(signing_profile["digest"]) end crl.issuer = signing_cert.subject self.crl_body = crl.sign(self.parent.key_material.private_key, digest) diff --git a/vendor/certificate_authority/lib/certificate_authority/signing_request.rb b/vendor/certificate_authority/lib/certificate_authority/signing_request.rb index 72d9e2b..3584dac 100644 --- a/vendor/certificate_authority/lib/certificate_authority/signing_request.rb +++ b/vendor/certificate_authority/lib/certificate_authority/signing_request.rb @@ -62,7 +62,7 @@ module CertificateAuthority opensslcsr.subject = @distinguished_name.to_x509_name opensslcsr.public_key = @key_material.public_key opensslcsr.attributes = @attributes unless @attributes.nil? - opensslcsr.sign @key_material.private_key, OpenSSL::Digest::Digest.new(@digest || "SHA512") + opensslcsr.sign @key_material.private_key, OpenSSL::Digest.new(@digest || "SHA512") opensslcsr end -- cgit v1.2.3 From b3f186752b5279c8c7311c099bdf2bf19afb7434 Mon Sep 17 00:00:00 2001 From: elijah Date: Wed, 28 Jan 2015 13:34:53 -0800 Subject: don't use md5sum command line tool. closes #6675 --- lib/leap_cli/util.rb | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/lib/leap_cli/util.rb b/lib/leap_cli/util.rb index 9edb150..5014238 100644 --- a/lib/leap_cli/util.rb +++ b/lib/leap_cli/util.rb @@ -355,16 +355,12 @@ module LeapCli end # - # compares md5 fingerprints to see if the contents of a file match the string we have in memory + # compares md5 fingerprints to see if the contents of a file match the + # string we have in memory # def file_content_equals?(filepath, contents) filepath = Path.named_path(filepath) - output = `md5sum '#{filepath}'`.strip - if $?.to_i == 0 - return output.split(" ").first == Digest::MD5.hexdigest(contents).to_s - else - return false - end + Digest::MD5.file(filepath).hexdigest == Digest::MD5.hexdigest(contents) end ## -- cgit v1.2.3 From 5676272e90dc69234181eaa5b2e96447f904966e Mon Sep 17 00:00:00 2001 From: elijah Date: Wed, 28 Jan 2015 13:41:12 -0800 Subject: honor --yes for 'db destroy'. closes 6649. --- lib/leap_cli/commands/db.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/leap_cli/commands/db.rb b/lib/leap_cli/commands/db.rb index fd50424..3502d7e 100644 --- a/lib/leap_cli/commands/db.rb +++ b/lib/leap_cli/commands/db.rb @@ -6,8 +6,10 @@ module LeapCli; module Commands db.arg_name 'FILTER', :optional => true db.command :destroy do |destroy| destroy.action do |global_options,options,args| - say 'You are about to permanently destroy all database data.' - return unless agree("Continue? ") + unless global_options[:yes] + say 'You are about to permanently destroy all database data.' + bail! unless agree("Continue? ") + end nodes = manager.filter(args) if nodes.any? nodes = nodes[:services => 'couchdb'] -- cgit v1.2.3 From e01bf415d80883c369dfd4247aae401fde421b80 Mon Sep 17 00:00:00 2001 From: elijah Date: Wed, 28 Jan 2015 22:19:25 -0800 Subject: cert generation: (1) auto generate certs (2) actually support configuring expiration times. REQUIRES platform >= 0.6.1. closes #6387 --- lib/leap_cli.rb | 1 + lib/leap_cli/commands/ca.rb | 71 +++++++++++++++++++--------------- lib/leap_cli/commands/deploy.rb | 2 + lib/leap_cli/core_ext/time.rb | 86 +++++++++++++++++++++++++++++++++++++++++ lib/leap_cli/version.rb | 4 +- 5 files changed, 130 insertions(+), 34 deletions(-) create mode 100644 lib/leap_cli/core_ext/time.rb diff --git a/lib/leap_cli.rb b/lib/leap_cli.rb index f07fd25..cbd8ac5 100644 --- a/lib/leap_cli.rb +++ b/lib/leap_cli.rb @@ -26,6 +26,7 @@ require 'leap_cli/core_ext/nil' require 'leap_cli/core_ext/string' require 'leap_cli/core_ext/json' require 'leap_cli/core_ext/yaml' +require 'leap_cli/core_ext/time' require 'leap_cli/log' require 'leap_cli/path' diff --git a/lib/leap_cli/commands/ca.rb b/lib/leap_cli/commands/ca.rb index 357792f..785e043 100644 --- a/lib/leap_cli/commands/ca.rb +++ b/lib/leap_cli/commands/ca.rb @@ -28,22 +28,7 @@ module LeapCli; module Commands cert.command :update do |update| update.switch 'force', :desc => 'Always generate new certificates', :negatable => false update.action do |global_options,options,args| - assert_files_exist! :ca_cert, :ca_key, :msg => 'Run `leap cert ca` to create them' - assert_config! 'provider.ca.server_certificates.bit_size' - assert_config! 'provider.ca.server_certificates.digest' - assert_config! 'provider.ca.server_certificates.life_span' - assert_config! 'common.x509.use' - - nodes = manager.filter!(args) - nodes.each_node do |node| - warn_if_commercial_cert_will_soon_expire(node) - if !node.x509.use - remove_file!([:node_x509_key, node.name]) - remove_file!([:node_x509_cert, node.name]) - elsif options[:force] || cert_needs_updating?(node) - generate_cert_for_node(node) - end - end + update_certificates(manager.filter!(args), options) end end @@ -139,7 +124,7 @@ module LeapCli; module Commands cert = csr.to_cert cert.serial_number.number = cert_serial_number(domain) cert.not_before = yesterday - cert.not_after = years_from_yesterday(1) + cert.not_after = yesterday.advance(:years => 1) cert.parent = ca_root cert.sign! domain_test_signing_profile write_file! [:commercial_cert, domain], cert.to_pem @@ -158,6 +143,29 @@ module LeapCli; module Commands end end + protected + + # + # will generate new certificates for the specified nodes, if needed. + # + def update_certificates(nodes, options={}) + assert_files_exist! :ca_cert, :ca_key, :msg => 'Run `leap cert ca` to create them' + assert_config! 'provider.ca.server_certificates.bit_size' + assert_config! 'provider.ca.server_certificates.digest' + assert_config! 'provider.ca.server_certificates.life_span' + assert_config! 'common.x509.use' + + nodes.each_node do |node| + warn_if_commercial_cert_will_soon_expire(node) + if !node.x509.use + remove_file!([:node_x509_key, node.name]) + remove_file!([:node_x509_cert, node.name]) + elsif options[:force] || cert_needs_updating?(node) + generate_cert_for_node(node) + end + end + end + private def generate_new_certificate_authority(key_file, cert_file, common_name) @@ -179,7 +187,7 @@ module LeapCli; module Commands # set expiration root.not_before = yesterday - root.not_after = years_from_yesterday(provider.ca.life_span.to_i) + root.not_after = yesterday_advance(provider.ca.life_span) # generate private key root.serial_number.number = 1 @@ -203,7 +211,7 @@ module LeapCli; module Commands return true else cert = load_certificate_file([:node_x509_cert, node.name]) - if cert.not_after < months_from_yesterday(2) + if cert.not_after < Time.now.advance(:months => 2) log :updating, "cert for node '#{node.name}' because it will expire soon" return true end @@ -242,7 +250,7 @@ module LeapCli; module Commands if cert.not_after < Time.now.utc log :error, "the commercial certificate '#{path}' has EXPIRED! " + "You should renew it with `leap cert csr --domain #{domain}`." - elsif cert.not_after < months_from_yesterday(2) + elsif cert.not_after < Time.now.advance(:months => 2) log :warning, "the commercial certificate '#{path}' will expire soon. "+ "You should renew it with `leap cert csr --domain #{domain}`." end @@ -261,7 +269,7 @@ module LeapCli; module Commands # set expiration cert.not_before = yesterday - cert.not_after = years_from_yesterday(provider.ca.server_certificates.life_span.to_i) + cert.not_after = yesterday_advance(provider.ca.server_certificates.life_span) # generate key cert.key_material.generate_key(provider.ca.server_certificates.bit_size) @@ -283,7 +291,7 @@ module LeapCli; module Commands cert.serial_number.number = cert_serial_number(provider.domain) cert.subject.common_name = [prefix, random_common_name(provider.domain)].join cert.not_before = yesterday - cert.not_after = years_from_yesterday(1) + cert.not_after = yesterday.advance(:years => 1) cert.key_material.generate_key(1024) # just for testing, remember! cert.parent = client_ca_root cert.sign! client_test_signing_profile @@ -492,16 +500,15 @@ module LeapCli; module Commands Time.utc t.year, t.month, t.day end - def years_from_yesterday(num) - t = yesterday - Time.utc t.year + num, t.month, t.day - end - - def months_from_yesterday(num) - t = yesterday - date = Date.new t.year, t.month, t.day - date = date >> num # >> is months in the future operator - Time.utc date.year, date.month, date.day + def yesterday_advance(string) + number, unit = string.split(' ') + unless ['years', 'months', 'days', 'hours', 'minutes'].include? unit + bail("The time property '#{string}' is missing a unit (one of: years, months, days, hours, minutes).") + end + unless number.to_i.to_s == number + bail("The time property '#{string}' is missing a number.") + end + yesterday.advance(unit.to_sym => number.to_i) end end; end diff --git a/lib/leap_cli/commands/deploy.rb b/lib/leap_cli/commands/deploy.rb index dbbaaba..204be5f 100644 --- a/lib/leap_cli/commands/deploy.rb +++ b/lib/leap_cli/commands/deploy.rb @@ -54,6 +54,8 @@ module LeapCli # compile hiera files for all the nodes in every environment that is # being deployed and only those environments. compile_hiera_files(manager.filter(environments)) + # update server certificates if needed + update_certificates(nodes) ssh_connect(nodes, connect_options(options)) do |ssh| ssh.leap.log :checking, 'node' do diff --git a/lib/leap_cli/core_ext/time.rb b/lib/leap_cli/core_ext/time.rb new file mode 100644 index 0000000..fef6c5d --- /dev/null +++ b/lib/leap_cli/core_ext/time.rb @@ -0,0 +1,86 @@ +# +# The following methods are copied from ActiveSupport's Time extension: +# activesupport/lib/active_support/core_ext/time/calculations.rb +# + +class Time + + # + # Uses Date to provide precise Time calculations for years, months, and days + # according to the proleptic Gregorian calendar. The options parameter takes + # a hash with any of these keys: :years, :months, :weeks, :days, :hours, + # :minutes, :seconds. + # + def advance(options) + unless options[:weeks].nil? + options[:weeks], partial_weeks = options[:weeks].divmod(1) + options[:days] = options.fetch(:days, 0) + 7 * partial_weeks + end + + unless options[:days].nil? + options[:days], partial_days = options[:days].divmod(1) + options[:hours] = options.fetch(:hours, 0) + 24 * partial_days + end + + d = to_date.advance(options) + d = d.gregorian if d.julian? + time_advanced_by_date = change(:year => d.year, :month => d.month, :day => d.day) + seconds_to_advance = options.fetch(:seconds, 0) + + options.fetch(:minutes, 0) * 60 + + options.fetch(:hours, 0) * 3600 + + if seconds_to_advance.zero? + time_advanced_by_date + else + time_advanced_by_date.since(seconds_to_advance) + end + end + + def since(seconds) + self + seconds + rescue + to_datetime.since(seconds) + end + + # + # Returns a new Time where one or more of the elements have been changed + # according to the options parameter. The time options (:hour, :min, :sec, + # :usec) reset cascadingly, so if only the hour is passed, then minute, sec, + # and usec is set to 0. If the hour and minute is passed, then sec and usec + # is set to 0. The options parameter takes a hash with any of these keys: + # :year, :month, :day, :hour, :min, :sec, :usec. + # + def change(options) + new_year = options.fetch(:year, year) + new_month = options.fetch(:month, month) + new_day = options.fetch(:day, day) + new_hour = options.fetch(:hour, hour) + new_min = options.fetch(:min, options[:hour] ? 0 : min) + new_sec = options.fetch(:sec, (options[:hour] || options[:min]) ? 0 : sec) + new_usec = options.fetch(:usec, (options[:hour] || options[:min] || options[:sec]) ? 0 : Rational(nsec, 1000)) + + if utc? + ::Time.utc(new_year, new_month, new_day, new_hour, new_min, new_sec, new_usec) + elsif zone + ::Time.local(new_year, new_month, new_day, new_hour, new_min, new_sec, new_usec) + else + ::Time.new(new_year, new_month, new_day, new_hour, new_min, new_sec + (new_usec.to_r / 1000000), utc_offset) + end + end + +end + +class Date + + # activesupport/lib/active_support/core_ext/date/calculations.rb + def advance(options) + options = options.dup + d = self + d = d >> options.delete(:years) * 12 if options[:years] + d = d >> options.delete(:months) if options[:months] + d = d + options.delete(:weeks) * 7 if options[:weeks] + d = d + options.delete(:days) if options[:days] + d + end + +end diff --git a/lib/leap_cli/version.rb b/lib/leap_cli/version.rb index 909131b..c945ea0 100644 --- a/lib/leap_cli/version.rb +++ b/lib/leap_cli/version.rb @@ -1,7 +1,7 @@ module LeapCli unless defined?(LeapCli::VERSION) - VERSION = '1.6.2' - COMPATIBLE_PLATFORM_VERSION = '0.6.0'..'1.99' + VERSION = '1.6.3' + COMPATIBLE_PLATFORM_VERSION = '0.6.1'..'1.99' SUMMARY = 'Command line interface to the LEAP platform' DESCRIPTION = 'The command "leap" can be used to manage a bevy of servers running the LEAP platform from the comfort of your own home.' LOAD_PATHS = ['lib', 'vendor/certificate_authority/lib', 'vendor/rsync_command/lib'] -- cgit v1.2.3 From 406a5bc18a5e5733d081c785984f06ad730a8dba Mon Sep 17 00:00:00 2001 From: elijah Date: Mon, 2 Feb 2015 14:54:35 -0800 Subject: fix bail! typo --- lib/leap_cli/commands/ca.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/leap_cli/commands/ca.rb b/lib/leap_cli/commands/ca.rb index 785e043..9b3409a 100644 --- a/lib/leap_cli/commands/ca.rb +++ b/lib/leap_cli/commands/ca.rb @@ -503,10 +503,10 @@ module LeapCli; module Commands def yesterday_advance(string) number, unit = string.split(' ') unless ['years', 'months', 'days', 'hours', 'minutes'].include? unit - bail("The time property '#{string}' is missing a unit (one of: years, months, days, hours, minutes).") + bail!("The time property '#{string}' is missing a unit (one of: years, months, days, hours, minutes).") end unless number.to_i.to_s == number - bail("The time property '#{string}' is missing a number.") + bail!("The time property '#{string}' is missing a number.") end yesterday.advance(unit.to_sym => number.to_i) end -- cgit v1.2.3 From c7d5c2798f47ed0a06f0ef57908c556580f72f9c Mon Sep 17 00:00:00 2001 From: elijah Date: Mon, 2 Feb 2015 16:41:12 -0800 Subject: more verbose --version (closes #4428) --- bin/leap | 18 +++++++++--- lib/leap_cli/commands/pre.rb | 69 +++++++++++++++++++++++++------------------- lib/leap_cli/leapfile.rb | 7 ++++- 3 files changed, 59 insertions(+), 35 deletions(-) diff --git a/bin/leap b/bin/leap index 47dfdf9..59e4ee8 100755 --- a/bin/leap +++ b/bin/leap @@ -10,6 +10,8 @@ else DEBUG=false end +LEAP_CLI_BASE_DIR = File.expand_path('..', File.dirname(File.symlink?(__FILE__) ? File.readlink(__FILE__) : __FILE__)) + begin require 'leap_cli' rescue LoadError @@ -24,8 +26,7 @@ rescue LoadError # 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). # - base_dir = File.expand_path('..', File.dirname(File.symlink?(__FILE__) ? File.readlink(__FILE__) : __FILE__)) - require File.join(base_dir, 'lib','leap_cli','load_paths') + require File.join(LEAP_CLI_BASE_DIR, 'lib','leap_cli','load_paths') require 'leap_cli' end @@ -77,9 +78,16 @@ module LeapCli::Commands program_desc LeapCli::SUMMARY program_long_desc LeapCli::DESCRIPTION - # handle --version ourselves + # handle --version ourselves (and not GLI) if ARGV.grep(/--version/).any? puts "leap #{LeapCli::VERSION}, ruby #{RUBY_VERSION}" + begin + commands_from('leap_cli/commands') + initialize_leap_cli(false, {:verbose => 2}) + rescue StandardError => exc + puts exc.to_s + raise exc if DEBUG + end exit(0) end @@ -88,8 +96,10 @@ module LeapCli::Commands def error_message(msg) end - # load commands and run + # load commands commands_from('leap_cli/commands') + + # run command ORIGINAL_ARGV = ARGV.dup begin exit_status = run(ARGV) diff --git a/lib/leap_cli/commands/pre.rb b/lib/leap_cli/commands/pre.rb index 055f3a1..74d7e62 100644 --- a/lib/leap_cli/commands/pre.rb +++ b/lib/leap_cli/commands/pre.rb @@ -28,57 +28,66 @@ module LeapCli; module Commands switch 'color', :negatable => true pre do |global,command,options,args| - # + initialize_leap_cli(true, global) + true + end + + protected + + # + # available options: + # :verbose -- integer log verbosity level + # :log -- log file path + # :color -- true or false, to log in color or not. + # + def initialize_leap_cli(require_provider, options={}) # set verbosity - # - LeapCli.set_log_level(global[:verbose].to_i) + options[:verbose] ||= 1 + LeapCli.set_log_level(options[:verbose].to_i) - # # load Leapfile - # - unless LeapCli.leapfile.load + LeapCli.leapfile.load + if LeapCli.leapfile.valid? + 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 + elsif require_provider bail! { log :missing, 'Leapfile in directory tree' } 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 - # # set log file - # - LeapCli.log_file = global[:log] || LeapCli.leapfile.log + LeapCli.log_file = options[:log] || LeapCli.leapfile.log LeapCli::Util.log_raw(:log) { $0 + ' ' + ORIGINAL_ARGV.join(' ')} log_version - LeapCli.log_in_color = global[:color] - - true + LeapCli.log_in_color = options[:color] end - private - # # add a log entry for the leap command and leap platform versions # def log_version if LeapCli.log_level >= 2 str = "leap command v#{LeapCli::VERSION}" - cli_dir = File.dirname(__FILE__) - if Util.is_git_directory?(cli_dir) - str << " (%s %s)" % [Util.current_git_branch(cli_dir), Util.current_git_commit(cli_dir)] + if Util.is_git_directory?(LEAP_CLI_BASE_DIR) + str << " (%s %s)" % [Util.current_git_branch(LEAP_CLI_BASE_DIR), + Util.current_git_commit(LEAP_CLI_BASE_DIR)] + else + str << " (%s)" % LEAP_CLI_BASE_DIR end log 2, str - str = "leap platform v#{Leap::Platform.version}" - if Util.is_git_directory?(Path.platform) - str << " (%s %s)" % [Util.current_git_branch(Path.platform), Util.current_git_commit(Path.platform)] + if LeapCli.leapfile.valid? + str = "leap platform v#{Leap::Platform.version}" + if Util.is_git_directory?(Path.platform) + str << " (%s %s)" % [Util.current_git_branch(Path.platform), Util.current_git_commit(Path.platform)] + end + log 2, str end - log 2, str end end - end; end diff --git a/lib/leap_cli/leapfile.rb b/lib/leap_cli/leapfile.rb index 8895f4d..7aaf10f 100644 --- a/lib/leap_cli/leapfile.rb +++ b/lib/leap_cli/leapfile.rb @@ -72,7 +72,8 @@ module LeapCli unless @platform_branch.nil? Util::log 0, :warning, "in Leapfile: @platform_branch is no longer supported." end - return true + @valid = true + return @valid end end @@ -84,6 +85,10 @@ module LeapCli edit_leaprc(property) end + def valid? + !!@valid + end + private # -- cgit v1.2.3 From 885e44ec43c17a595fff8d10f24d0724fb2c37ce Mon Sep 17 00:00:00 2001 From: elijah Date: Tue, 3 Feb 2015 10:14:14 -0800 Subject: fixed missing ORIGINAL_ARGV when running with --version --- bin/leap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/leap b/bin/leap index 59e4ee8..dbdd312 100755 --- a/bin/leap +++ b/bin/leap @@ -11,6 +11,7 @@ else end LEAP_CLI_BASE_DIR = File.expand_path('..', File.dirname(File.symlink?(__FILE__) ? File.readlink(__FILE__) : __FILE__)) +ORIGINAL_ARGV = ARGV.dup begin require 'leap_cli' @@ -100,7 +101,6 @@ module LeapCli::Commands commands_from('leap_cli/commands') # run command - ORIGINAL_ARGV = ARGV.dup begin exit_status = run(ARGV) exit(LeapCli::Util.exit_status || exit_status) -- cgit v1.2.3 From effe065ad6d810431c61f02330011c7443967bc4 Mon Sep 17 00:00:00 2001 From: elijah Date: Thu, 5 Feb 2015 23:23:33 -0800 Subject: minor - fix indentation --- lib/leap_cli/config/secrets.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/leap_cli/config/secrets.rb b/lib/leap_cli/config/secrets.rb index 366ffd3..e0f3080 100644 --- a/lib/leap_cli/config/secrets.rb +++ b/lib/leap_cli/config/secrets.rb @@ -13,10 +13,10 @@ module LeapCli; module Config @discovered_keys = {} end - # we can't use fetch() or get(), since those already have special meanings - def retrieve(key, environment=nil) - self.fetch(environment||'default', {})[key.to_s] - end + # we can't use fetch() or get(), since those already have special meanings + def retrieve(key, environment=nil) + self.fetch(environment||'default', {})[key.to_s] + end def set(key, value, environment=nil) environment ||= 'default' -- cgit v1.2.3 From a32c332963e3bca8ab4bd40b636d36a77468e219 Mon Sep 17 00:00:00 2001 From: elijah Date: Thu, 5 Feb 2015 23:25:18 -0800 Subject: vagrant - fix version calculation when vagrant version has three parts (e.g. 1.1.1) --- lib/leap_cli/commands/vagrant.rb | 91 ++++++++++++++++++---------------------- 1 file changed, 40 insertions(+), 51 deletions(-) diff --git a/lib/leap_cli/commands/vagrant.rb b/lib/leap_cli/commands/vagrant.rb index 31c7878..5ad43d1 100644 --- a/lib/leap_cli/commands/vagrant.rb +++ b/lib/leap_cli/commands/vagrant.rb @@ -111,32 +111,23 @@ module LeapCli; module Commands def vagrant_setup assert_bin! 'vagrant', 'Vagrant is required for running local virtual machines. Run "sudo apt-get install vagrant".' - version = vagrant_version - case version - when 0..1 - gem_path = assert_run!('vagrant gem which sahara') - if gem_path.nil? || gem_path.empty? || gem_path =~ /^ERROR/ - log :installing, "vagrant plugin 'sahara'" - assert_run! 'vagrant gem install sahara -v 0.0.13' - # (sahara versions above 0.0.13 require vagrant > 1.0) - end - when 2 - unless assert_run!('vagrant plugin list | grep sahara | cat').chars.any? - log :installing, "vagrant plugin 'sahara'" - assert_run! 'vagrant plugin install sahara' - end + if vagrant_version <= Gem::Version.new('1.0.0') + gem_path = assert_run!('vagrant gem which sahara') + if gem_path.nil? || gem_path.empty? || gem_path =~ /^ERROR/ + log :installing, "vagrant plugin 'sahara'" + assert_run! 'vagrant gem install sahara -v 0.0.13' + end + else + unless assert_run!('vagrant plugin list | grep sahara | cat').chars.any? + log :installing, "vagrant plugin 'sahara'" + assert_run! 'vagrant plugin install sahara' + end end create_vagrant_file end def vagrant_version - minor_version = `vagrant --version | rev | cut -d'.' -f 2`.to_i - version = case minor_version - when 1..9 then 2 - when 0 then 1 - else 0 - end - return version + @vagrant_version ||= Gem::Version.new(assert_run!('vagrant --version').split(' ')[1]) end def execute(cmd) @@ -148,38 +139,36 @@ module LeapCli; module Commands lines = [] netmask = IPAddr.new('255.255.255.255').mask(LeapCli.leapfile.vagrant_network.split('/').last).to_s - version = vagrant_version - case version - when 0..1 - lines << %[Vagrant::Config.run do |config|] - manager.each_node do |node| - if node.vagrant? - lines << %[ config.vm.define :#{node.name} do |config|] - lines << %[ config.vm.box = "leap-wheezy"] - lines << %[ config.vm.box_url = "https://downloads.leap.se/platform/vagrant/virtualbox/leap-wheezy.box"] - lines << %[ config.vm.network :hostonly, "#{node.ip_address}", :netmask => "#{netmask}"] - lines << %[ config.vm.customize ["modifyvm", :id, "--natdnshostresolver1", "on"]] - lines << %[ config.vm.customize ["modifyvm", :id, "--name", "#{node.name}"]] - lines << %[ #{leapfile.custom_vagrant_vm_line}] if leapfile.custom_vagrant_vm_line - lines << %[ end] - end + if vagrant_version <= Gem::Version.new('1.1.0') + lines << %[Vagrant::Config.run do |config|] + manager.each_node do |node| + if node.vagrant? + lines << %[ config.vm.define :#{node.name} do |config|] + lines << %[ config.vm.box = "leap-wheezy"] + lines << %[ config.vm.box_url = "https://downloads.leap.se/platform/vagrant/virtualbox/leap-wheezy.box"] + lines << %[ config.vm.network :hostonly, "#{node.ip_address}", :netmask => "#{netmask}"] + lines << %[ config.vm.customize ["modifyvm", :id, "--natdnshostresolver1", "on"]] + lines << %[ config.vm.customize ["modifyvm", :id, "--name", "#{node.name}"]] + lines << %[ #{leapfile.custom_vagrant_vm_line}] if leapfile.custom_vagrant_vm_line + lines << %[ end] end - when 2 - lines << %[Vagrant.configure("2") do |config|] - manager.each_node do |node| - if node.vagrant? - lines << %[ config.vm.define :#{node.name} do |config|] - lines << %[ config.vm.box = "leap-wheezy"] - lines << %[ config.vm.box_url = "https://downloads.leap.se/platform/vagrant/virtualbox/leap-wheezy.box"] - lines << %[ config.vm.network :private_network, ip: "#{node.ip_address}"] - lines << %[ config.vm.provider "virtualbox" do |v|] - lines << %[ v.customize ["modifyvm", :id, "--natdnshostresolver1", "on"]] - lines << %[ v.name = "#{node.name}"] - lines << %[ end] - lines << %[ #{leapfile.custom_vagrant_vm_line}] if leapfile.custom_vagrant_vm_line - lines << %[ end] - end + end + else + lines << %[Vagrant.configure("2") do |config|] + manager.each_node do |node| + if node.vagrant? + lines << %[ config.vm.define :#{node.name} do |config|] + lines << %[ config.vm.box = "leap-wheezy"] + lines << %[ config.vm.box_url = "https://downloads.leap.se/platform/vagrant/virtualbox/leap-wheezy.box"] + lines << %[ config.vm.network :private_network, ip: "#{node.ip_address}"] + lines << %[ config.vm.provider "virtualbox" do |v|] + lines << %[ v.customize ["modifyvm", :id, "--natdnshostresolver1", "on"]] + lines << %[ v.name = "#{node.name}"] + lines << %[ end] + lines << %[ #{leapfile.custom_vagrant_vm_line}] if leapfile.custom_vagrant_vm_line + lines << %[ end] end + end end lines << %[end] -- cgit v1.2.3 From 5130afca6ff1f5ec49b8abeaccfbe17dec129e32 Mon Sep 17 00:00:00 2001 From: elijah Date: Sun, 8 Feb 2015 13:01:19 -0800 Subject: pass --info to puppet_command (needed to support logging deploy details) --- lib/leap_cli/commands/deploy.rb | 40 +++++++++++++++++++++++++++++------- lib/leap_cli/logger.rb | 10 ++++----- lib/leap_cli/remote/puppet_plugin.rb | 2 +- 3 files changed, 39 insertions(+), 13 deletions(-) diff --git a/lib/leap_cli/commands/deploy.rb b/lib/leap_cli/commands/deploy.rb index 204be5f..a0b7c20 100644 --- a/lib/leap_cli/commands/deploy.rb +++ b/lib/leap_cli/commands/deploy.rb @@ -1,3 +1,4 @@ +require 'etc' module LeapCli module Commands @@ -7,20 +8,17 @@ module LeapCli arg_name 'FILTER' command [:deploy, :d] do |c| - # --fast c.switch :fast, :desc => 'Makes the deploy command faster by skipping some slow steps. A "fast" deploy can be used safely if you recently completed a normal deploy.', :negatable => false - # --sync - c.switch :sync, :desc => "Sync files, but don't actually apply recipes." + c.switch :sync, :desc => "Sync files, but don't actually apply recipes.", :negatable => false - # --force c.switch :force, :desc => 'Deploy even if there is a lockfile.', :negatable => false - # --dev + c.switch :downgrade, :desc => 'Allows deploy to run with an older platform version.', :negatable => false + c.switch :dev, :desc => "Development mode: don't run 'git submodule update' before deploy.", :negatable => false - # --tags c.flag :tags, :desc => 'Specify tags to pass through to puppet (overriding the default).', :arg_name => 'TAG[,TAG]' @@ -71,7 +69,12 @@ module LeapCli end unless options[:sync] ssh.leap.log :applying, "puppet" do - ssh.puppet.apply(:verbosity => [LeapCli.log_level,5].min, :tags => tags(options), :force => options[:force]) + ssh.puppet.apply(:verbosity => [LeapCli.log_level,5].min, + :tags => tags(options), + :force => options[:force], + :info => deploy_info, + :downgrade => options[:downgrade] + ) end end end @@ -297,5 +300,28 @@ module LeapCli return custom_files end + def deploy_info + info = [] + info << "user: %s" % Etc.getpwuid(Process.euid).name + if is_git_directory?(Path.platform) && current_git_branch(Path.platform) != 'master' + info << "platform: %s (%s %s)" % [ + Leap::Platform.version, + current_git_branch(Path.platform), + current_git_commit(Path.platform)[0..4] + ] + else + info << "platform: %s" % Leap::Platform.version + end + if is_git_directory?(LEAP_CLI_BASE_DIR) + info << "leap_cli: %s (%s %s)" % [ + LeapCli::VERSION, + current_git_branch(LEAP_CLI_BASE_DIR), + current_git_commit(LEAP_CLI_BASE_DIR)[0..4] + ] + else + info << "leap_cli: %s" % LeapCli::VERSION + end + info.join(', ') + end end end diff --git a/lib/leap_cli/logger.rb b/lib/leap_cli/logger.rb index 3560d21..328dc27 100644 --- a/lib/leap_cli/logger.rb +++ b/lib/leap_cli/logger.rb @@ -113,8 +113,8 @@ module LeapCli { :match => /sh: .+: command not found/, :color => :magenta, :match_level => 1, :priority => -30 }, # IMPORTANT - { :match => /^err ::/, :color => :red, :match_level => 0, :priority => -10 }, - { :match => /^ERROR:/, :color => :red, :match_level => 0, :priority => -10 }, + { :match => /^err ::/, :color => :red, :match_level => 0, :priority => -10, :exit => 1}, + { :match => /^ERROR:/, :color => :red, :priority => -10, :exit => 1}, { :match => /.*/, :color => :blue, :match_level => 0, :priority => -20 }, # CLEANUP @@ -136,8 +136,8 @@ module LeapCli { :match => /^warning:/, :level => 0, :color => :yellow, :priority => -20}, { :match => /^Duplicate declaration:/, :level => 0, :color => :red, :priority => -20}, { :match => /Finished catalog run/, :level => 0, :color => :green, :priority => -10}, - { :match => /^Puppet apply complete \(changes made\)/, :level => 0, :color => :green, :priority => -10}, - { :match => /^Puppet apply complete \(no changes\)/, :level => 0, :color => :green, :priority => -10}, + { :match => /^APPLY COMPLETE \(changes made\)/, :level => 0, :color => :green, :priority => -10}, + { :match => /^APPLY COMPLETE \(no changes\)/, :level => 0, :color => :green, :priority => -10}, # PUPPET FATAL ERRORS { :match => /^err:/, :level => 0, :color => :red, :priority => -1, :exit => 1}, @@ -146,7 +146,7 @@ module LeapCli { :match => /^Syntax error/, :level => 0, :color => :red, :priority => -1, :exit => 1}, { :match => /^Cannot reassign variable/, :level => 0, :color => :red, :priority => -1, :exit => 1}, { :match => /^Could not find template/, :level => 0, :color => :red, :priority => -1, :exit => 1}, - { :match => /^Puppet apply complete.*fail/, :level => 0, :color => :red, :priority => -1, :exit => 1}, + { :match => /^APPLY COMPLETE.*fail/, :level => 0, :color => :red, :priority => -1, :exit => 1}, # TESTS { :match => /^PASS: /, :color => :green, :priority => -20}, diff --git a/lib/leap_cli/remote/puppet_plugin.rb b/lib/leap_cli/remote/puppet_plugin.rb index e3f6be2..77bb4a3 100644 --- a/lib/leap_cli/remote/puppet_plugin.rb +++ b/lib/leap_cli/remote/puppet_plugin.rb @@ -18,7 +18,7 @@ module LeapCli; module Remote; module PuppetPlugin elsif item[1] === true str << "--" + item[0].to_s else - str << "--" + item[0].to_s + " " + item[1].to_s + str << "--" + item[0].to_s + " " + item[1].inspect end }.join(' ') end -- cgit v1.2.3 From 39c8a357ec10b9cb4ecf75324561ed82241e27d6 Mon Sep 17 00:00:00 2001 From: elijah Date: Mon, 9 Feb 2015 22:44:49 -0800 Subject: more verbose `leap cert update` --- lib/leap_cli/commands/ca.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/leap_cli/commands/ca.rb b/lib/leap_cli/commands/ca.rb index 9b3409a..356e616 100644 --- a/lib/leap_cli/commands/ca.rb +++ b/lib/leap_cli/commands/ca.rb @@ -216,7 +216,7 @@ module LeapCli; module Commands return true end if cert.subject.common_name != node.domain.full - log :updating, "cert for node '#{node.name}' because domain.full has changed" + log :updating, "cert for node '#{node.name}' because domain.full has changed (was #{cert.subject.common_name}, now #{node.domain.full})" return true end cert.openssl_body.extensions.each do |ext| -- cgit v1.2.3 From c0770e0c5a914a7c7f25349e51b41a16a1154373 Mon Sep 17 00:00:00 2001 From: elijah Date: Wed, 25 Feb 2015 09:39:35 -0800 Subject: allow use of byebug --- bin/leap | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/bin/leap b/bin/leap index dbdd312..e42b8c2 100755 --- a/bin/leap +++ b/bin/leap @@ -3,7 +3,11 @@ if ARGV.include?('--debug') || ARGV.include?('-d') DEBUG=true begin - require 'debugger' + if RUBY_VERSION =~ /^2/ + require 'byebug' + else + require 'debugger' + end rescue LoadError end else -- cgit v1.2.3 From 4d1872b1b6fee85e30f7ec71af38f2f28d816b04 Mon Sep 17 00:00:00 2001 From: elijah Date: Wed, 25 Feb 2015 09:40:21 -0800 Subject: set Aquire::Languages=none for apt-get update. --- lib/leap_cli/remote/tasks.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/leap_cli/remote/tasks.rb b/lib/leap_cli/remote/tasks.rb index 7fd8d64..38a440c 100644 --- a/lib/leap_cli/remote/tasks.rb +++ b/lib/leap_cli/remote/tasks.rb @@ -34,10 +34,11 @@ BAD_APT_GET_UPDATE = /(BADSIG|NO_PUBKEY|KEYEXPIRED|REVKEYSIG|NODATA)/ task :install_prerequisites, :max_hosts => MAX_HOSTS do apt_get = "DEBIAN_FRONTEND=noninteractive apt-get -q -y -o DPkg::Options::=--force-confold" + apt_get_update = "apt-get update -o Acquire::Languages=none" leap.mkdirs Leap::Platform.leap_dir run "echo 'en_US.UTF-8 UTF-8' > /etc/locale.gen" leap.log :updating, "package list" do - run "apt-get update" do |channel, stream, data| + run apt_get_update do |channel, stream, data| # sadly exitcode is unreliable measure if apt-get update hit a failure. if data =~ BAD_APT_GET_UPDATE LeapCli::Util.bail! do -- cgit v1.2.3 From b1d277f5d58bc5aeef3c024ca7e2b45a0e2edb83 Mon Sep 17 00:00:00 2001 From: elijah Date: Fri, 27 Feb 2015 22:19:07 -0800 Subject: added ability to select which dbs to delete with `leap db destroy` --- lib/leap_cli/commands/db.rb | 49 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 8 deletions(-) diff --git a/lib/leap_cli/commands/db.rb b/lib/leap_cli/commands/db.rb index 3502d7e..55134f5 100644 --- a/lib/leap_cli/commands/db.rb +++ b/lib/leap_cli/commands/db.rb @@ -2,22 +2,30 @@ module LeapCli; module Commands desc 'Database commands.' command :db do |db| - db.desc 'Destroy all the databases. If present, limit to FILTER nodes.' + db.desc 'Destroy one or more databases. If present, limit to FILTER nodes. For example `leap db destroy --db sessions,tokens testing`.' db.arg_name 'FILTER', :optional => true db.command :destroy do |destroy| + destroy.flag :db, :arg_name => "DATABASES", :desc => 'Comma separated list of databases to destroy (no space). Use "--db all" to destroy all databases.', :optional => false destroy.action do |global_options,options,args| - unless global_options[:yes] - say 'You are about to permanently destroy all database data.' - bail! unless agree("Continue? ") - end + dbs = (options[:db]||"").split(',') + bail!('No databases specified') if dbs.empty? nodes = manager.filter(args) if nodes.any? nodes = nodes[:services => 'couchdb'] end if nodes.any? - ssh_connect(nodes, connect_options(options)) do |ssh| - ssh.run('/etc/init.d/bigcouch stop && test ! -z "$(ls /opt/bigcouch/var/lib/ 2> /dev/null)" && rm -r /opt/bigcouch/var/lib/* && echo "db destroyed" || echo "db already destroyed"') - ssh.run('grep ^seq_file /etc/leap/tapicero.yaml | cut -f2 -d\" | xargs rm -v') + unless global_options[:yes] + if dbs.include?('all') + say 'You are about to permanently destroy all database data for nodes [%s].' % nodes.keys.join(', ') + else + say 'You are about to permanently destroy databases [%s] for nodes [%s].' % [dbs.join(', '), nodes.keys.join(', ')] + end + bail! unless agree("Continue? ") + end + if dbs.include?('all') + destroy_all_dbs(nodes) + else + destroy_dbs(nodes, dbs) end say 'You must run `leap deploy` in order to create the databases again.' else @@ -29,4 +37,29 @@ module LeapCli; module Commands private + def destroy_all_dbs(nodes) + ssh_connect(nodes) do |ssh| + ssh.run('/etc/init.d/bigcouch stop && test ! -z "$(ls /opt/bigcouch/var/lib/ 2> /dev/null)" && rm -r /opt/bigcouch/var/lib/* && echo "db destroyed" || echo "db already destroyed"') + ssh.run('grep ^seq_file /etc/leap/tapicero.yaml | cut -f2 -d\" | xargs rm -v') + end + end + + def destroy_dbs(nodes, dbs) + nodes.each_node do |node| + ssh_connect(node) do |ssh| + dbs.each do |db| + ssh.run(DESTROY_DB_COMMAND % {:db => db}) + end + end + end + end + + DESTROY_DB_COMMAND = %{ +if [ 200 = `curl -ns -w "%%{http_code}" -X GET "127.0.0.1:5984/%{db}" -o /dev/null` ]; then + echo "Result from DELETE /%{db}:" `curl -ns -X DELETE "127.0.0.1:5984/%{db}"`; +else + echo "Skipping db '%{db}': it does not exist or has already been deleted."; +fi +} + end; end -- cgit v1.2.3 From 585c00840d17347f54941db36921a4bf4a9f397a Mon Sep 17 00:00:00 2001 From: elijah Date: Tue, 31 Mar 2015 14:08:33 -0700 Subject: update tapicero config --- lib/leap_cli/commands/db.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/leap_cli/commands/db.rb b/lib/leap_cli/commands/db.rb index 55134f5..e4fd385 100644 --- a/lib/leap_cli/commands/db.rb +++ b/lib/leap_cli/commands/db.rb @@ -40,7 +40,7 @@ module LeapCli; module Commands def destroy_all_dbs(nodes) ssh_connect(nodes) do |ssh| ssh.run('/etc/init.d/bigcouch stop && test ! -z "$(ls /opt/bigcouch/var/lib/ 2> /dev/null)" && rm -r /opt/bigcouch/var/lib/* && echo "db destroyed" || echo "db already destroyed"') - ssh.run('grep ^seq_file /etc/leap/tapicero.yaml | cut -f2 -d\" | xargs rm -v') + ssh.run('grep ^seq_dir /etc/leap/tapicero.yaml | cut -f2 -d\" | xargs rm -rv') end end -- cgit v1.2.3 From b13d362ac1909bfb14846294577b2d52f63b7abd Mon Sep 17 00:00:00 2001 From: elijah Date: Wed, 1 Apr 2015 13:47:54 -0700 Subject: added `leap scp` --- lib/leap_cli/commands/ssh.rb | 100 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 84 insertions(+), 16 deletions(-) diff --git a/lib/leap_cli/commands/ssh.rb b/lib/leap_cli/commands/ssh.rb index 40d205e..1a81902 100644 --- a/lib/leap_cli/commands/ssh.rb +++ b/lib/leap_cli/commands/ssh.rb @@ -35,6 +35,33 @@ module LeapCli; module Commands end end + desc 'Secure copy from FILE1 to FILE2. Files are specified as NODE_NAME:FILE_PATH. For local paths, omit "NODE_NAME:".' + arg_name 'FILE1 FILE2' + command :scp do |c| + c.switch :r, :desc => 'Copy recursively' + c.action do |global_options, options, args| + if args.size != 2 + bail!('You must specificy both FILE1 and FILE2') + end + from, to = args + if (from !~ /:/ && to !~ /:/) || (from =~ /:/ && to =~ /:/) + bail!('One FILE must be remote and the other local.') + end + src_node_name = src_file_path = src_node = nil + dst_node_name = dst_file_path = dst_node = nil + if from =~ /:/ + src_node_name, src_file_path = from.split(':') + src_node = get_node_from_args([src_node_name], :include_disabled => true) + dst_file_path = to + else + dst_node_name, dst_file_path = to.split(':') + dst_node = get_node_from_args([dst_node_name], :include_disabled => true) + src_file_path = from + end + exec_scp(options, src_node, src_file_path, dst_node, dst_file_path) + end + end + protected # @@ -78,22 +105,7 @@ module LeapCli; module Commands def exec_ssh(cmd, cli_options, args) node = get_node_from_args(args, :include_disabled => true) port = node.ssh.port - options = [ - "-o 'HostName=#{node.ip_address}'", - # "-o 'HostKeyAlias=#{node.name}'", << oddly incompatible with ports in known_hosts file, so we must not use this or non-standard ports break. - "-o 'GlobalKnownHostsFile=#{path(:known_hosts)}'", - "-o 'UserKnownHostsFile=/dev/null'" - ] - if node.vagrant? - options << "-i #{vagrant_ssh_key_file}" # use the universal vagrant insecure key - options << "-o IdentitiesOnly=yes" # force the use of the insecure vagrant key - options << "-o 'StrictHostKeyChecking=no'" # blindly accept host key and don't save it (since userknownhostsfile is /dev/null) - else - options << "-o 'StrictHostKeyChecking=yes'" - end - if !node.supported_ssh_host_key_algorithms.empty? - options << "-o 'HostKeyAlgorithms=#{node.supported_ssh_host_key_algorithms}'" - end + options = ssh_config(node) username = 'root' if LeapCli.log_level >= 3 options << "-vv" @@ -133,6 +145,62 @@ module LeapCli; module Commands end end + def exec_scp(cli_options, src_node, src_file_path, dst_node, dst_file_path) + node = src_node || dst_node + options = ssh_config(node) + port = node.ssh.port + username = 'root' + options << "-r" if cli_options[:r] + scp = "scp -P #{port} #{options.join(' ')}" + if src_node + command = "#{scp} #{username}@#{src_node.domain.full}:#{src_file_path} #{dst_file_path}" + elsif dst_node + command = "#{scp} #{src_file_path} #{username}@#{dst_node.domain.full}:#{dst_file_path}" + end + log 2, command + + # exec the shell command in a subprocess + pid = fork { exec "#{command}" } + + Signal.trap("SIGINT") do + Process.kill("KILL", pid) + Process.wait(pid) + exit(0) + end + + # wait for shell to exit so we can grab the exit status + _, status = Process.waitpid2(pid) + exit(status.exitstatus) + end + + # + # SSH command line -o options. See `man ssh_config` + # + # NOTES: + # + # The option 'HostKeyAlias=#{node.name}' is oddly incompatible with ports in + # known_hosts file, so we must not use this or non-standard ports break. + # + def ssh_config(node) + options = [ + "-o 'HostName=#{node.ip_address}'", + "-o 'GlobalKnownHostsFile=#{path(:known_hosts)}'", + "-o 'UserKnownHostsFile=/dev/null'" + ] + if node.vagrant? + options << "-i #{vagrant_ssh_key_file}" # use the universal vagrant insecure key + options << "-o IdentitiesOnly=yes" # force the use of the insecure vagrant key + options << "-o 'StrictHostKeyChecking=no'" # blindly accept host key and don't save it + # (since userknownhostsfile is /dev/null) + else + options << "-o 'StrictHostKeyChecking=yes'" + end + if !node.supported_ssh_host_key_algorithms.empty? + options << "-o 'HostKeyAlgorithms=#{node.supported_ssh_host_key_algorithms}'" + end + return options + end + def parse_tunnel_arg(arg) if arg.count(':') == 1 node_name, remote = arg.split(':') -- cgit v1.2.3 From 2dc48bf4bcf0f98fe715233c3746b7affc0a9175 Mon Sep 17 00:00:00 2001 From: elijah Date: Wed, 1 Apr 2015 14:05:59 -0700 Subject: version 1.7 --- README.md | 28 ++++++++++++++++++++++++++++ lib/leap_cli/version.rb | 4 ++-- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 90bce52..73613b0 100644 --- a/README.md +++ b/README.md @@ -100,3 +100,31 @@ other places, it is easier to create the symlink. If you run ``leap`` directly, the command launcher that rubygems installs, leap will run in a mode that simulates ``bundle exec leap`` (i.e. only gems included in Gemfile are allowed to be loaded). +Changes +==================================================== + +1.7 + +* requires platform 0.7 +* deployment logging (see /var/log/leap) +* compatible with new tapicero +* selectively destroy some dbs with `leap db destroy` +* faster apt-get update +* added `leap scp` command +* bug fixes + +1.6.2 + +* auto generate certs on compile +* use internal ruby md5sum for compatibility on mac +* may override or customize tests by putting tests in `files/tests` +* bug fixes + +1.6.1 + +* requires platform 0.6 +* better `leap test run` +* added `leap tunnel` command +* only print stack trace if `--debug` flag was specified +* prompt user to upgrade host ssh key if a better one exists +* bug fixes diff --git a/lib/leap_cli/version.rb b/lib/leap_cli/version.rb index c945ea0..d45884e 100644 --- a/lib/leap_cli/version.rb +++ b/lib/leap_cli/version.rb @@ -1,7 +1,7 @@ module LeapCli unless defined?(LeapCli::VERSION) - VERSION = '1.6.3' - COMPATIBLE_PLATFORM_VERSION = '0.6.1'..'1.99' + VERSION = '1.7' + COMPATIBLE_PLATFORM_VERSION = '0.7'..'0.99' SUMMARY = 'Command line interface to the LEAP platform' DESCRIPTION = 'The command "leap" can be used to manage a bevy of servers running the LEAP platform from the comfort of your own home.' LOAD_PATHS = ['lib', 'vendor/certificate_authority/lib', 'vendor/rsync_command/lib'] -- cgit v1.2.3 From 26842662815d1409400d85275b32789156d50db5 Mon Sep 17 00:00:00 2001 From: varac Date: Tue, 7 Apr 2015 11:14:46 +0200 Subject: make clear that dh file is only needed for VPN --- doc/leap.md | 2 +- lib/leap_cli/commands/ca.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/leap.md b/doc/leap.md index d735fef..f531d32 100644 --- a/doc/leap.md +++ b/doc/leap.md @@ -77,7 +77,7 @@ Default Value: None ## leap cert dh -Creates a Diffie-Hellman parameter file. +Creates a Diffie-Hellman parameter file, needed for forward secret OpenVPN ciphers. You don't need this file if you don't provide the VPN service. diff --git a/lib/leap_cli/commands/ca.rb b/lib/leap_cli/commands/ca.rb index 356e616..cfa18f5 100644 --- a/lib/leap_cli/commands/ca.rb +++ b/lib/leap_cli/commands/ca.rb @@ -32,7 +32,7 @@ module LeapCli; module Commands end end - cert.desc 'Creates a Diffie-Hellman parameter file.' # (needed for server-side of some TLS connections) + cert.desc 'Creates a Diffie-Hellman parameter file, needed for forward secret OpenVPN ciphers.' # (needed for server-side of some TLS connections) cert.command :dh do |dh| dh.action do |global_options,options,args| long_running do -- cgit v1.2.3 From ddd160afb1fd2c729cf806de879add5a15cafe31 Mon Sep 17 00:00:00 2001 From: elijah Date: Wed, 8 Apr 2015 18:14:09 -0700 Subject: added `leap history` command to dump the recent deploy history to console --- lib/leap_cli/commands/deploy.rb | 16 ++++++++++++++++ lib/leap_cli/remote/leap_plugin.rb | 7 +++++++ 2 files changed, 23 insertions(+) diff --git a/lib/leap_cli/commands/deploy.rb b/lib/leap_cli/commands/deploy.rb index a0b7c20..394ea61 100644 --- a/lib/leap_cli/commands/deploy.rb +++ b/lib/leap_cli/commands/deploy.rb @@ -84,6 +84,22 @@ module LeapCli end end + desc 'Display recent deployment history for a set of nodes.' + long_desc 'The FILTER can be the name of a node, service, or tag.' + arg_name 'FILTER' + command [:history, :h] do |c| + c.flag :port, :desc => 'Override the default SSH port.', + :arg_name => 'PORT' + c.flag :ip, :desc => 'Override the default SSH IP address.', + :arg_name => 'IPADDRESS' + c.action do |global,options,args| + nodes = manager.filter!(args) + ssh_connect(nodes, connect_options(options)) do |ssh| + ssh.leap.history + end + end + end + private # diff --git a/lib/leap_cli/remote/leap_plugin.rb b/lib/leap_cli/remote/leap_plugin.rb index af88c2a..c155097 100644 --- a/lib/leap_cli/remote/leap_plugin.rb +++ b/lib/leap_cli/remote/leap_plugin.rb @@ -60,6 +60,13 @@ module LeapCli; module Remote; module LeapPlugin run "touch #{Leap::Platform.init_path}" end + # + # dumps the recent deploy history to the console + # + def history + run "(test -s /var/log/leap/deploy-summary.log && tail /var/log/leap/deploy-summary.log) || (test -s /var/log/leap/deploy-summary.log.1 && tail /var/log/leap/deploy-summary.log.1) || (echo 'no history')" + end + # # This is a hairy ugly hack, exactly the kind of stuff that makes ruby # dangerous and too much fun for its own good. -- cgit v1.2.3 From ea5be4ea7b6f0b269ac54655f01c7cd6dc28ece7 Mon Sep 17 00:00:00 2001 From: elijah Date: Wed, 8 Apr 2015 18:15:43 -0700 Subject: version 1.7.1 --- lib/leap_cli/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/leap_cli/version.rb b/lib/leap_cli/version.rb index d45884e..1c6801b 100644 --- a/lib/leap_cli/version.rb +++ b/lib/leap_cli/version.rb @@ -1,6 +1,6 @@ module LeapCli unless defined?(LeapCli::VERSION) - VERSION = '1.7' + VERSION = '1.7.1' COMPATIBLE_PLATFORM_VERSION = '0.7'..'0.99' SUMMARY = 'Command line interface to the LEAP platform' DESCRIPTION = 'The command "leap" can be used to manage a bevy of servers running the LEAP platform from the comfort of your own home.' -- cgit v1.2.3 From 1c58dd5905bdad68df4f57aa3323d95d8bd2db0a Mon Sep 17 00:00:00 2001 From: elijah Date: Mon, 27 Apr 2015 09:57:35 -0700 Subject: added --force --- lib/leap_cli/commands/deploy.rb | 65 ++++++++++++++++++++++++++++------------- lib/leap_cli/commands/pre.rb | 14 ++++++--- 2 files changed, 55 insertions(+), 24 deletions(-) diff --git a/lib/leap_cli/commands/deploy.rb b/lib/leap_cli/commands/deploy.rb index 394ea61..03240ce 100644 --- a/lib/leap_cli/commands/deploy.rb +++ b/lib/leap_cli/commands/deploy.rb @@ -47,7 +47,7 @@ module LeapCli environments = [nil] end environments.each do |env| - check_platform_pinning(env) + check_platform_pinning(env, global) end # compile hiera files for all the nodes in every environment that is # being deployed and only those environments. @@ -102,6 +102,16 @@ module LeapCli private + def forcible_prompt(forced, msg, prompt) + say(msg) + if forced + log :warning, "continuing anyway because of --force" + else + say "hint: use --force to skip this prompt." + quit!("OK. Bye.") unless agree(prompt) + end + end + # # The currently activated provider.json could have loaded some pinning # information for the platform. If this is the case, refuse to deploy @@ -115,7 +125,7 @@ module LeapCli # "commit": "e1d6280e0a8c565b7fb1a4ed3969ea6fea31a5e2..HEAD" # } # - def check_platform_pinning(environment) + def check_platform_pinning(environment, global_options) provider = manager.env(environment).provider return unless provider['platform'] @@ -133,34 +143,46 @@ module LeapCli # check version if provider.platform['version'] if !Leap::Platform.version_in_range?(provider.platform.version) - say("The platform is pinned to a version range of '#{provider.platform.version}' "+ - "by the `platform.version` property in #{provider_json}, but the platform "+ - "(#{Path.platform}) has version #{Leap::Platform.version}.") - quit!("OK. Bye.") unless agree("Do you really want to deploy from the wrong version? ") + forcible_prompt( + global_options[:force], + "The platform is pinned to a version range of '#{provider.platform.version}' "+ + "by the `platform.version` property in #{provider_json}, but the platform "+ + "(#{Path.platform}) has version #{Leap::Platform.version}.", + "Do you really want to deploy from the wrong version? " + ) end end # check branch if provider.platform['branch'] if !is_git_directory?(Path.platform) - say("The platform is pinned to a particular branch by the `platform.branch` property "+ - "in #{provider_json}, but the platform directory (#{Path.platform}) is not a git repository.") - quit!("OK. Bye.") unless agree("Do you really want to deploy anyway? ") + forcible_prompt( + global_options[:force], + "The platform is pinned to a particular branch by the `platform.branch` property "+ + "in #{provider_json}, but the platform directory (#{Path.platform}) is not a git repository.", + "Do you really want to deploy anyway? " + ) end unless provider.platform.branch == current_git_branch(Path.platform) - say("The platform is pinned to branch '#{provider.platform.branch}' by the `platform.branch` property "+ - "in #{provider_json}, but the current branch is '#{current_git_branch(Path.platform)}' " + - "(for directory '#{Path.platform}')") - quit!("OK. Bye.") unless agree("Do you really want to deploy from the wrong branch? ") + forcible_prompt( + global_options[:force], + "The platform is pinned to branch '#{provider.platform.branch}' by the `platform.branch` property "+ + "in #{provider_json}, but the current branch is '#{current_git_branch(Path.platform)}' " + + "(for directory '#{Path.platform}')", + "Do you really want to deploy from the wrong branch? " + ) end end # check commit if provider.platform['commit'] if !is_git_directory?(Path.platform) - say("The platform is pinned to a particular commit range by the `platform.commit` property "+ - "in #{provider_json}, but the platform directory (#{Path.platform}) is not a git repository.") - quit!("OK. Bye.") unless agree("Do you really want to deploy anyway? ") + forcible_prompt( + global_options[:force], + "The platform is pinned to a particular commit range by the `platform.commit` property "+ + "in #{provider_json}, but the platform directory (#{Path.platform}) is not a git repository.", + "Do you really want to deploy anyway? " + ) end current_commit = current_git_commit(Path.platform) Dir.chdir(Path.platform) do @@ -171,10 +193,13 @@ module LeapCli commit_range = commit_range.split("\n") if !commit_range.include?(current_commit) && provider.platform.commit.split('..').first != current_commit - say("The platform is pinned via the `platform.commit` property in #{provider_json} " + - "to a commit in the range #{provider.platform.commit}, but the current HEAD " + - "(#{current_commit}) is not in that range.") - quit!("OK. Bye.") unless agree("Do you really want to deploy from the wrong commit? ") + forcible_prompt( + global_options[:force], + "The platform is pinned via the `platform.commit` property in #{provider_json} " + + "to a commit in the range #{provider.platform.commit}, but the current HEAD " + + "(#{current_commit}) is not in that range.", + "Do you really want to deploy from the wrong commit? " + ) end end end diff --git a/lib/leap_cli/commands/pre.rb b/lib/leap_cli/commands/pre.rb index 74d7e62..3b316a4 100644 --- a/lib/leap_cli/commands/pre.rb +++ b/lib/leap_cli/commands/pre.rb @@ -9,25 +9,31 @@ module LeapCli; module Commands default_value '1' flag [:v, :verbose] - desc 'Override default log file' + desc 'Override default log file.' arg_name 'FILE' default_value nil flag :log - desc 'Display version number and exit' + desc 'Display version number and exit.' switch :version, :negatable => false - desc 'Skip prompts and assume "yes"' + desc 'Skip prompts and assume "yes".' switch :yes, :negatable => false + desc 'Like --yes, but also skip prompts that are potentially dangerous to skip.' + switch :force, :negatable => false + desc 'Print full stack trace for exceptions and load `debugger` gem if installed.' switch [:d, :debug], :negatable => false - desc 'Disable colors in output' + desc 'Disable colors in output.' default_value true switch 'color', :negatable => true pre do |global,command,options,args| + if global[:force] + global[:yes] = true + end initialize_leap_cli(true, global) true end -- cgit v1.2.3 From 44de719a21c80646125063e7a5f6dafc5cfc44ae Mon Sep 17 00:00:00 2001 From: elijah Date: Mon, 27 Apr 2015 09:58:24 -0700 Subject: make self.environment available to Leapfile. --- lib/leap_cli/leapfile.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lib/leap_cli/leapfile.rb b/lib/leap_cli/leapfile.rb index 7aaf10f..1bb2fa0 100644 --- a/lib/leap_cli/leapfile.rb +++ b/lib/leap_cli/leapfile.rb @@ -47,6 +47,12 @@ module LeapCli # set up paths # @provider_directory_path = directory + begin + # load leaprc first, so that we can potentially access which environment is pinned in Leapfile + # but also load leaprc last, so that it can override what is set in Leapfile. + read_settings(leaprc_path) + rescue StandardError + end read_settings(directory + '/Leapfile') read_settings(leaprc_path) @platform_directory_path = File.expand_path(@platform_directory_path || '../leap_platform', @provider_directory_path) @@ -54,6 +60,10 @@ module LeapCli # # load the platform # + platform_file = "#{@platform_directory_path}/platform.rb" + unless File.exists?(platform_file) + Util.bail! "ERROR: The file `#{platform_file}` does not exist. Please check the value of `@platform_directory_path` in `Leapfile` or `~/.leaprc`." + end require "#{@platform_directory_path}/platform.rb" if !Leap::Platform.compatible_with_cli?(LeapCli::VERSION) Util.bail! "This leap command (v#{LeapCli::VERSION}) " + -- cgit v1.2.3 From 9a6b198873823d8deb6d405222a0eca28312ae0a Mon Sep 17 00:00:00 2001 From: elijah Date: Tue, 28 Apr 2015 10:04:43 -0700 Subject: fail to compile if you pass it an invalid environment name --- lib/leap_cli/commands/compile.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/leap_cli/commands/compile.rb b/lib/leap_cli/commands/compile.rb index 78d7520..cfafc74 100644 --- a/lib/leap_cli/commands/compile.rb +++ b/lib/leap_cli/commands/compile.rb @@ -12,8 +12,12 @@ module LeapCli if !LeapCli.leapfile.environment.nil? && !environment.nil? && environment != LeapCli.leapfile.environment bail! "You cannot specify an ENVIRONMENT argument while the environment is pinned." end - if environment && manager.environment_names.include?(environment) - compile_hiera_files(manager.filter([environment])) + if environment + if manager.environment_names.include?(environment) + compile_hiera_files(manager.filter([environment])) + else + bail! "There is no environment named `#{environment}`." + end else compile_hiera_files(manager.filter) end -- cgit v1.2.3 From 59c931ae3c2c0b6783cecbba965179b5985d0b2b Mon Sep 17 00:00:00 2001 From: elijah Date: Tue, 28 Apr 2015 11:03:47 -0700 Subject: better platform version incompatibility message (closes #6855) --- lib/leap_cli/leapfile.rb | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/lib/leap_cli/leapfile.rb b/lib/leap_cli/leapfile.rb index 1bb2fa0..c2bc10b 100644 --- a/lib/leap_cli/leapfile.rb +++ b/lib/leap_cli/leapfile.rb @@ -65,17 +65,13 @@ module LeapCli Util.bail! "ERROR: The file `#{platform_file}` does not exist. Please check the value of `@platform_directory_path` in `Leapfile` or `~/.leaprc`." end require "#{@platform_directory_path}/platform.rb" - if !Leap::Platform.compatible_with_cli?(LeapCli::VERSION) + if !Leap::Platform.compatible_with_cli?(LeapCli::VERSION) || + !Leap::Platform.version_in_range?(LeapCli::COMPATIBLE_PLATFORM_VERSION) Util.bail! "This leap command (v#{LeapCli::VERSION}) " + - "is not compatible with the platform #{@platform_directory_path} (v#{Leap::Platform.version}). " + - "You need leap command #{Leap::Platform.compatible_cli.first} to #{Leap::Platform.compatible_cli.last}." + "is not compatible with the platform #{@platform_directory_path} (v#{Leap::Platform.version}).\n " + + "You need either leap command #{Leap::Platform.compatible_cli.first} to #{Leap::Platform.compatible_cli.last} or " + + "platform version #{LeapCli::COMPATIBLE_PLATFORM_VERSION.first} to #{LeapCli::COMPATIBLE_PLATFORM_VERSION.last}" end - if !Leap::Platform.version_in_range?(LeapCli::COMPATIBLE_PLATFORM_VERSION) - Util.bail! "This leap command (v#{LeapCli::VERSION}) " + - "is not compatible with the platform #{@platform_directory_path} (v#{Leap::Platform.version}). " + - "You need platform version #{LeapCli::COMPATIBLE_PLATFORM_VERSION.first} to #{LeapCli::COMPATIBLE_PLATFORM_VERSION.last}." - end - unless @allow_production_deploy.nil? Util::log 0, :warning, "in Leapfile: @allow_production_deploy is no longer supported." end -- cgit v1.2.3 From b4d0e0e3b4bfa2436e3f76a591d5639819a4853b Mon Sep 17 00:00:00 2001 From: elijah Date: Mon, 4 May 2015 15:11:46 -0700 Subject: remove ruby-hiera-puppet from list of required packages (except for wheezy) closes #6918 --- lib/leap_cli/remote/leap_plugin.rb | 4 ++++ lib/leap_cli/remote/tasks.rb | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/leap_cli/remote/leap_plugin.rb b/lib/leap_cli/remote/leap_plugin.rb index c155097..e425842 100644 --- a/lib/leap_cli/remote/leap_plugin.rb +++ b/lib/leap_cli/remote/leap_plugin.rb @@ -6,6 +6,10 @@ module LeapCli; module Remote; module LeapPlugin def required_packages + "puppet rsync lsb-release locales" + end + + def required_wheezy_packages "puppet ruby-hiera-puppet rsync lsb-release locales" end diff --git a/lib/leap_cli/remote/tasks.rb b/lib/leap_cli/remote/tasks.rb index 38a440c..ab60a51 100644 --- a/lib/leap_cli/remote/tasks.rb +++ b/lib/leap_cli/remote/tasks.rb @@ -58,7 +58,7 @@ task :install_prerequisites, :max_hosts => MAX_HOSTS do run "( test -f /etc/init.d/ntp && /etc/init.d/ntp start ) || true" end leap.log :installing, "required packages" do - run "#{apt_get} install #{leap.required_packages}" + run %[#{apt_get} install $( (grep -q wheezy /etc/debian_version && echo #{leap.required_wheezy_packages}) || echo #{leap.required_packages} )] end #run "locale-gen" leap.mkdirs("/etc/leap", "/srv/leap") -- cgit v1.2.3 From 6b35bbbe1a9909c737c1cd53edcfc47af0ad063c Mon Sep 17 00:00:00 2001 From: elijah Date: Mon, 4 May 2015 16:17:01 -0700 Subject: make gpgme optional --- Gemfile | 30 ------------------------------ leap_cli.gemspec | 3 ++- lib/leap_cli/commands/user.rb | 2 +- 3 files changed, 3 insertions(+), 32 deletions(-) diff --git a/Gemfile b/Gemfile index fe076b0..06618ce 100644 --- a/Gemfile +++ b/Gemfile @@ -1,33 +1,3 @@ source 'https://rubygems.org' gemspec -# # -# # Specify support gems used that we might also develop locally. -# # -# # Available options: -# # -# # :dev_path - the development path of the gem. this path is used if running in 'development mode'. -# # -# # :vendor_path - where this gem is vendored. this path is used if it exists and we are running in 'production mode' -# # -# development_gems = { -# 'supply_drop' => {:dev_path => '../gems/supply_drop', :vendor_path => 'vendor/supply_drop'}, -# 'certificate_authority' => {:dev_path => '../gems/certificate_authority', :vendor_path => 'vendor/certificate_authority'} -# } - -# # -# # A little bit of code to magically pick the correct gem -# # - -# mode = :production - -# gem_root = File.dirname(__FILE__) -# path_key = mode == :development ? :dev_path : :vendor_path -# development_gems.each do |gem_name, options| -# path = File.expand_path(options[path_key], gem_root) -# if File.directory?(path) -# gem gem_name, :path => path -# else -# gem gem_name -# end -# end diff --git a/leap_cli.gemspec b/leap_cli.gemspec index e9215fb..b9bad48 100644 --- a/leap_cli.gemspec +++ b/leap_cli.gemspec @@ -64,7 +64,8 @@ spec = Gem::Specification.new do |s| # crypto gems #s.add_runtime_dependency('certificate_authority', '>= 0.2.0') # ^^ currently vendored - s.add_runtime_dependency('gpgme') # not essential, but used for some minor stuff in adding sysadmins + # s.add_runtime_dependency('gpgme') # << does not build on debian jessie, so now optional. + # also, there is a ruby-gpgme package anyway. # misc gems s.add_runtime_dependency('ya2yaml') # pure ruby yaml, so we can better control output. see https://github.com/afunai/ya2yaml diff --git a/lib/leap_cli/commands/user.rb b/lib/leap_cli/commands/user.rb index 6c33878..480e9a9 100644 --- a/lib/leap_cli/commands/user.rb +++ b/lib/leap_cli/commands/user.rb @@ -100,9 +100,9 @@ module LeapCli # def pick_pgp_key begin - return unless `which gpg`.strip.any? require 'gpgme' rescue LoadError + log "Skipping OpenPGP setup because gpgme is not installed." return end -- cgit v1.2.3 From 142468636189f36ee542245856ef4ca84bda0509 Mon Sep 17 00:00:00 2001 From: elijah Date: Mon, 4 May 2015 16:34:44 -0700 Subject: gemspec clean up: remove gems 'tee' and 'versionomy', and tighten dependency version requirements. --- leap_cli.gemspec | 18 ++++++++---------- lib/leap/platform.rb | 16 +++++++--------- 2 files changed, 15 insertions(+), 19 deletions(-) diff --git a/leap_cli.gemspec b/leap_cli.gemspec index b9bad48..6f8f8de 100644 --- a/leap_cli.gemspec +++ b/leap_cli.gemspec @@ -43,17 +43,16 @@ spec = Gem::Specification.new do |s| ## # test - s.add_development_dependency('minitest') + s.add_development_dependency('minitest', '~> 5.0') #s.add_development_dependency('rdoc') #s.add_development_dependency('aruba') # console gems - s.add_runtime_dependency('gli','~> 2.12.0') - s.add_runtime_dependency('command_line_reporter') - s.add_runtime_dependency('highline') - s.add_runtime_dependency('paint') - s.add_runtime_dependency('tee') + s.add_runtime_dependency('gli','~> 2.12') + s.add_runtime_dependency('command_line_reporter', '~> 3.3') + s.add_runtime_dependency('highline', '~> 1.6') + s.add_runtime_dependency('paint', '~> 0.9') # network gems s.add_runtime_dependency('net-ssh', '~> 2.7.0') @@ -68,10 +67,9 @@ spec = Gem::Specification.new do |s| # also, there is a ruby-gpgme package anyway. # misc gems - s.add_runtime_dependency('ya2yaml') # pure ruby yaml, so we can better control output. see https://github.com/afunai/ya2yaml - s.add_runtime_dependency('json_pure') # pure ruby json, so we can better control output. - s.add_runtime_dependency('versionomy') # compare version strings - s.add_runtime_dependency('base32') # base32 encoding + s.add_runtime_dependency('ya2yaml', '~> 0.31') # pure ruby yaml, so we can better control output. see https://github.com/afunai/ya2yaml + s.add_runtime_dependency('json_pure', '~> 1.8') # pure ruby json, so we can better control output. + s.add_runtime_dependency('base32', '~> 0.3') # base32 encoding ## ## DEPENDENCIES for VENDORED GEMS diff --git a/lib/leap/platform.rb b/lib/leap/platform.rb index 3e1d138..0fdb312 100644 --- a/lib/leap/platform.rb +++ b/lib/leap/platform.rb @@ -1,5 +1,3 @@ -require 'versionomy' - module Leap class Platform @@ -34,24 +32,24 @@ module Leap self.instance_eval(&block) - @version ||= Versionomy.parse("0.0") + @version ||= Gem::Version.new("0.0") end def version=(version) - @version = Versionomy.parse(version) + @version = Gem::Version.new(version) end def compatible_cli=(range) @compatible_cli = range - @minimum_cli_version = Versionomy.parse(range.first) - @maximum_cli_version = Versionomy.parse(range.last) + @minimum_cli_version = Gem::Version.new(range.first) + @maximum_cli_version = Gem::Version.new(range.last) end # # return true if the cli_version is compatible with this platform. # def compatible_with_cli?(cli_version) - cli_version = Versionomy.parse(cli_version) + cli_version = Gem::Version.new(cli_version) cli_version >= @minimum_cli_version && cli_version <= @maximum_cli_version end @@ -62,8 +60,8 @@ module Leap if range.is_a? String range = range.split('..') end - minimum_platform_version = Versionomy.parse(range.first) - maximum_platform_version = Versionomy.parse(range.last) + minimum_platform_version = Gem::Version.new(range.first) + maximum_platform_version = Gem::Version.new(range.last) @version >= minimum_platform_version && @version <= maximum_platform_version end -- cgit v1.2.3 From 4b8d17980d2948c5c406ec6c2106123266c4a10b Mon Sep 17 00:00:00 2001 From: elijah Date: Tue, 5 May 2015 14:44:03 -0700 Subject: fix bug with using Gem::Version instead of Versionomy --- lib/leap/platform.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/leap/platform.rb b/lib/leap/platform.rb index 0fdb312..36a13f8 100644 --- a/lib/leap/platform.rb +++ b/lib/leap/platform.rb @@ -66,10 +66,10 @@ module Leap end def major_version - if @version.major == 0 - "#{@version.major}.#{@version.minor}" + if @version.segments.first == 0 + @version.segments[0..1].join('.') else - @version.major + @version.segments.first end end -- cgit v1.2.3 From 80f28c3862da72172a55d3e0218faad5cdd46b4b Mon Sep 17 00:00:00 2001 From: elijah Date: Tue, 5 May 2015 14:57:27 -0700 Subject: properly bind 'global.services' and 'global.tags' in the right environment in the macros. --- lib/leap_cli.rb | 7 ++--- lib/leap_cli/config/manager.rb | 9 ++++--- lib/leap_cli/config/object.rb | 43 +++++++++++++++++++++++++++++-- lib/leap_cli/config/object_list.rb | 2 +- lib/leap_cli/core_ext/deep_dup.rb | 53 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 105 insertions(+), 9 deletions(-) create mode 100644 lib/leap_cli/core_ext/deep_dup.rb diff --git a/lib/leap_cli.rb b/lib/leap_cli.rb index cbd8ac5..7b22913 100644 --- a/lib/leap_cli.rb +++ b/lib/leap_cli.rb @@ -20,13 +20,14 @@ require 'leap_cli/version' require 'leap_cli/exceptions' require 'leap_cli/leapfile' -require 'leap_cli/core_ext/hash' require 'leap_cli/core_ext/boolean' +require 'leap_cli/core_ext/deep_dup' +require 'leap_cli/core_ext/hash' +require 'leap_cli/core_ext/json' require 'leap_cli/core_ext/nil' require 'leap_cli/core_ext/string' -require 'leap_cli/core_ext/json' -require 'leap_cli/core_ext/yaml' require 'leap_cli/core_ext/time' +require 'leap_cli/core_ext/yaml' require 'leap_cli/log' require 'leap_cli/path' diff --git a/lib/leap_cli/config/manager.rb b/lib/leap_cli/config/manager.rb index be95831..33b7f05 100644 --- a/lib/leap_cli/config/manager.rb +++ b/lib/leap_cli/config/manager.rb @@ -133,9 +133,9 @@ module LeapCli next unless ename log 3, :loading, '%s environment...' % ename env(ename) do |e| - e.services = load_all_json(Path.named_path([:service_env_config, '*', ename], @provider_dir), Config::Tag) - e.tags = load_all_json(Path.named_path([:tag_env_config, '*', ename], @provider_dir), Config::Tag) - e.provider = load_json( Path.named_path([:provider_env_config, ename], @provider_dir), Config::Provider) + e.services = load_all_json(Path.named_path([:service_env_config, '*', ename], @provider_dir), Config::Tag, :env => ename) + e.tags = load_all_json(Path.named_path([:tag_env_config, '*', ename], @provider_dir), Config::Tag, :env => ename) + e.provider = load_json( Path.named_path([:provider_env_config, ename], @provider_dir), Config::Provider, :env => ename) e.services.inherit_from! env('default').services e.tags.inherit_from! env('default').tags e.provider.inherit_from! env('default').provider @@ -315,6 +315,9 @@ module LeapCli if obj name = File.basename(filename).force_encoding('utf-8').sub(/^([^\.]+).*\.json$/,'\1') obj['name'] ||= name + if options[:env] + obj.environment = options[:env] + end results[name] = obj end end diff --git a/lib/leap_cli/config/object.rb b/lib/leap_cli/config/object.rb index a0d402b..6f71a08 100644 --- a/lib/leap_cli/config/object.rb +++ b/lib/leap_cli/config/object.rb @@ -10,6 +10,34 @@ require 'ya2yaml' # pure ruby yaml module LeapCli module Config + + # + # A proxy for Manager that binds to a particular object + # (so that we can bind to a particular environment) + # + class ManagerBinding + def initialize(manager, object) + @manager = manager + @object = object + end + + def services + @manager.env(@object.environment).services + end + + def tags + @manager.env(@object.environment).tags + end + + def provider + @manager.env(@object.environment).provider + end + + def method_missing(*args) + @manager.send(*args) + end + end + # # This class represents the configuration for a single node, service, or tag. # Also, all the nested hashes are also of this type. @@ -19,8 +47,6 @@ module LeapCli class Object < Hash attr_reader :node - attr_reader :manager - alias :global :manager def initialize(manager=nil, node=nil) # keep a global pointer around to the config manager. used a lot in the eval strings and templates @@ -31,6 +57,19 @@ module LeapCli @node = node || self end + def manager + ManagerBinding.new(@manager, self) + end + alias :global :manager + + def environment=(e) + self.store('environment', e) + end + + def environment + self['environment'] + end + # # export YAML # diff --git a/lib/leap_cli/config/object_list.rb b/lib/leap_cli/config/object_list.rb index 33ca4dd..afcc6a6 100644 --- a/lib/leap_cli/config/object_list.rb +++ b/lib/leap_cli/config/object_list.rb @@ -174,7 +174,7 @@ module LeapCli if self[name] self[name].inherit_from!(object) else - self[name] = object.dup + self[name] = object.deep_dup end end end diff --git a/lib/leap_cli/core_ext/deep_dup.rb b/lib/leap_cli/core_ext/deep_dup.rb new file mode 100644 index 0000000..b9cf0d3 --- /dev/null +++ b/lib/leap_cli/core_ext/deep_dup.rb @@ -0,0 +1,53 @@ +unless Hash.method_defined?(:deep_dup) + + class Array + def deep_dup + map { |it| it.deep_dup } + end + end + + class Hash + def deep_dup + each_with_object(dup) do |(key, value), hash| + hash[key.deep_dup] = value.deep_dup + end + end + end + + class String + def deep_dup + self.dup + end + end + + class Integer + def deep_dup + self + end + end + + class Float + def deep_dup + self + end + end + + class TrueClass + def deep_dup + self + end + end + + class FalseClass + def deep_dup + self + end + end + + class NilClass + def deep_dup + self + end + end + +end \ No newline at end of file -- cgit v1.2.3 From ab3184ff6dea960e347da299deaabeb23e2cf86e Mon Sep 17 00:00:00 2001 From: elijah Date: Tue, 5 May 2015 14:58:03 -0700 Subject: add --force to 'leap cert csr' --- lib/leap_cli/commands/ca.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/leap_cli/commands/ca.rb b/lib/leap_cli/commands/ca.rb index cfa18f5..d5c6240 100644 --- a/lib/leap_cli/commands/ca.rb +++ b/lib/leap_cli/commands/ca.rb @@ -87,7 +87,11 @@ module LeapCli; module Commands assert_config! 'provider.ca.server_certificates.bit_size' assert_config! 'provider.ca.server_certificates.digest' domain = options[:domain] || provider.domain - assert_files_missing! [:commercial_key, domain], [:commercial_csr, domain], :msg => 'If you really want to create a new key and CSR, remove these files first.' + + unless global_options[:force] + assert_files_missing! [:commercial_key, domain], [:commercial_csr, domain], + :msg => 'If you really want to create a new key and CSR, remove these files first or run with --force.' + end server_certificates = provider.ca.server_certificates -- cgit v1.2.3 From bd090aa1d1cc8cbfe6381310b6b4e200e7e717df Mon Sep 17 00:00:00 2001 From: elijah Date: Tue, 5 May 2015 14:58:13 -0700 Subject: fix tests --- test/leap_platform/platform.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/leap_platform/platform.rb b/test/leap_platform/platform.rb index d93f59c..57ea980 100644 --- a/test/leap_platform/platform.rb +++ b/test/leap_platform/platform.rb @@ -4,8 +4,8 @@ # Leap::Platform.define do - self.version = "0.6.0" - self.compatible_cli = "1.5.8".."1.99" + self.version = "0.7.0" + self.compatible_cli = "1.7.0".."1.7.99" # # the facter facts that should be gathered -- cgit v1.2.3 From 3c1cc376787a7866d929205959e42be403a2c2ce Mon Sep 17 00:00:00 2001 From: elijah Date: Tue, 5 May 2015 15:21:14 -0700 Subject: added support for secrets.set() with value passed as a block, so that secrets don't get needlessly generated --- lib/leap_cli/config/secrets.rb | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/lib/leap_cli/config/secrets.rb b/lib/leap_cli/config/secrets.rb index e0f3080..184d11d 100644 --- a/lib/leap_cli/config/secrets.rb +++ b/lib/leap_cli/config/secrets.rb @@ -14,17 +14,28 @@ module LeapCli; module Config end # we can't use fetch() or get(), since those already have special meanings - def retrieve(key, environment=nil) - self.fetch(environment||'default', {})[key.to_s] + def retrieve(key, environment) + self.fetch(environment, {})[key.to_s] end - def set(key, value, environment=nil) - environment ||= 'default' + def set(*args, &block) + if block_given? + set_with_block(*args, &block) + else + set_without_block(*args) + end + end + + def set_without_block(key, value, environment) + set_with_block(key, environment) {value} + end + + def set_with_block(key, environment, &block) key = key.to_s @discovered_keys[environment] ||= {} @discovered_keys[environment][key] = true self[environment] ||= {} - self[environment][key] ||= value + self[environment][key] ||= yield end # -- cgit v1.2.3 From 304cc961908542ec94a15cde8991d9486eeb6b22 Mon Sep 17 00:00:00 2001 From: elijah Date: Tue, 5 May 2015 15:26:00 -0700 Subject: added 1.7.1 changes description --- RELEASES.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/RELEASES.md b/RELEASES.md index f8407c0..53ba0f6 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,11 @@ +Version 1.7.1 + - added 'leap scp' and 'leap tunnel' + - support for deploy logging and 'leap history' + - added --force + - server certs are now autogenerated as needed + - better mac, debian, and ruby 2.0 compatibility. + - many bug fixes + Version 1.6.1 - add environment pinning, see `leap help env` - support both rsa and ecdsa host keys -- cgit v1.2.3 From 61fdf41087b480db12720df5d5beadd32992475a Mon Sep 17 00:00:00 2001 From: kwadronaut Date: Tue, 5 May 2015 20:47:30 +0200 Subject: Changed location of local nodes basebox to hashicorp. If you already have local nodes, basebox will not be updated, however when adding new local nodes, they will be checking for updates of the basebox. --- lib/leap_cli/commands/vagrant.rb | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/leap_cli/commands/vagrant.rb b/lib/leap_cli/commands/vagrant.rb index 5ad43d1..e652e8b 100644 --- a/lib/leap_cli/commands/vagrant.rb +++ b/lib/leap_cli/commands/vagrant.rb @@ -144,8 +144,7 @@ module LeapCli; module Commands manager.each_node do |node| if node.vagrant? lines << %[ config.vm.define :#{node.name} do |config|] - lines << %[ config.vm.box = "leap-wheezy"] - lines << %[ config.vm.box_url = "https://downloads.leap.se/platform/vagrant/virtualbox/leap-wheezy.box"] + lines << %[ config.vm.box = "LEAP/wheezy"] lines << %[ config.vm.network :hostonly, "#{node.ip_address}", :netmask => "#{netmask}"] lines << %[ config.vm.customize ["modifyvm", :id, "--natdnshostresolver1", "on"]] lines << %[ config.vm.customize ["modifyvm", :id, "--name", "#{node.name}"]] @@ -158,8 +157,7 @@ module LeapCli; module Commands manager.each_node do |node| if node.vagrant? lines << %[ config.vm.define :#{node.name} do |config|] - lines << %[ config.vm.box = "leap-wheezy"] - lines << %[ config.vm.box_url = "https://downloads.leap.se/platform/vagrant/virtualbox/leap-wheezy.box"] + lines << %[ config.vm.box = "LEAP/wheezy"] lines << %[ config.vm.network :private_network, ip: "#{node.ip_address}"] lines << %[ config.vm.provider "virtualbox" do |v|] lines << %[ v.customize ["modifyvm", :id, "--natdnshostresolver1", "on"]] -- cgit v1.2.3