leap_cli 1.6.2 → 1.7.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -174,7 +174,7 @@ module LeapCli
174
174
  if self[name]
175
175
  self[name].inherit_from!(object)
176
176
  else
177
- self[name] = object.dup
177
+ self[name] = object.deep_dup
178
178
  end
179
179
  end
180
180
  end
@@ -13,18 +13,29 @@ module LeapCli; module Config
13
13
  @discovered_keys = {}
14
14
  end
15
15
 
16
- # we can't use fetch() or get(), since those already have special meanings
17
- def retrieve(key, environment=nil)
18
- self.fetch(environment||'default', {})[key.to_s]
19
- end
16
+ # we can't use fetch() or get(), since those already have special meanings
17
+ def retrieve(key, environment)
18
+ self.fetch(environment, {})[key.to_s]
19
+ end
20
+
21
+ def set(*args, &block)
22
+ if block_given?
23
+ set_with_block(*args, &block)
24
+ else
25
+ set_without_block(*args)
26
+ end
27
+ end
28
+
29
+ def set_without_block(key, value, environment)
30
+ set_with_block(key, environment) {value}
31
+ end
20
32
 
21
- def set(key, value, environment=nil)
22
- environment ||= 'default'
33
+ def set_with_block(key, environment, &block)
23
34
  key = key.to_s
24
35
  @discovered_keys[environment] ||= {}
25
36
  @discovered_keys[environment][key] = true
26
37
  self[environment] ||= {}
27
- self[environment][key] ||= value
38
+ self[environment][key] ||= yield
28
39
  end
29
40
 
30
41
  #
@@ -0,0 +1,11 @@
1
+ # encoding: utf-8
2
+ #
3
+ # A class for the sources.json file
4
+ #
5
+
6
+ module LeapCli
7
+ module Config
8
+ class Sources < Object
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,53 @@
1
+ unless Hash.method_defined?(:deep_dup)
2
+
3
+ class Array
4
+ def deep_dup
5
+ map { |it| it.deep_dup }
6
+ end
7
+ end
8
+
9
+ class Hash
10
+ def deep_dup
11
+ each_with_object(dup) do |(key, value), hash|
12
+ hash[key.deep_dup] = value.deep_dup
13
+ end
14
+ end
15
+ end
16
+
17
+ class String
18
+ def deep_dup
19
+ self.dup
20
+ end
21
+ end
22
+
23
+ class Integer
24
+ def deep_dup
25
+ self
26
+ end
27
+ end
28
+
29
+ class Float
30
+ def deep_dup
31
+ self
32
+ end
33
+ end
34
+
35
+ class TrueClass
36
+ def deep_dup
37
+ self
38
+ end
39
+ end
40
+
41
+ class FalseClass
42
+ def deep_dup
43
+ self
44
+ end
45
+ end
46
+
47
+ class NilClass
48
+ def deep_dup
49
+ self
50
+ end
51
+ end
52
+
53
+ end
@@ -0,0 +1,86 @@
1
+ #
2
+ # The following methods are copied from ActiveSupport's Time extension:
3
+ # activesupport/lib/active_support/core_ext/time/calculations.rb
4
+ #
5
+
6
+ class Time
7
+
8
+ #
9
+ # Uses Date to provide precise Time calculations for years, months, and days
10
+ # according to the proleptic Gregorian calendar. The options parameter takes
11
+ # a hash with any of these keys: :years, :months, :weeks, :days, :hours,
12
+ # :minutes, :seconds.
13
+ #
14
+ def advance(options)
15
+ unless options[:weeks].nil?
16
+ options[:weeks], partial_weeks = options[:weeks].divmod(1)
17
+ options[:days] = options.fetch(:days, 0) + 7 * partial_weeks
18
+ end
19
+
20
+ unless options[:days].nil?
21
+ options[:days], partial_days = options[:days].divmod(1)
22
+ options[:hours] = options.fetch(:hours, 0) + 24 * partial_days
23
+ end
24
+
25
+ d = to_date.advance(options)
26
+ d = d.gregorian if d.julian?
27
+ time_advanced_by_date = change(:year => d.year, :month => d.month, :day => d.day)
28
+ seconds_to_advance = options.fetch(:seconds, 0) +
29
+ options.fetch(:minutes, 0) * 60 +
30
+ options.fetch(:hours, 0) * 3600
31
+
32
+ if seconds_to_advance.zero?
33
+ time_advanced_by_date
34
+ else
35
+ time_advanced_by_date.since(seconds_to_advance)
36
+ end
37
+ end
38
+
39
+ def since(seconds)
40
+ self + seconds
41
+ rescue
42
+ to_datetime.since(seconds)
43
+ end
44
+
45
+ #
46
+ # Returns a new Time where one or more of the elements have been changed
47
+ # according to the options parameter. The time options (:hour, :min, :sec,
48
+ # :usec) reset cascadingly, so if only the hour is passed, then minute, sec,
49
+ # and usec is set to 0. If the hour and minute is passed, then sec and usec
50
+ # is set to 0. The options parameter takes a hash with any of these keys:
51
+ # :year, :month, :day, :hour, :min, :sec, :usec.
52
+ #
53
+ def change(options)
54
+ new_year = options.fetch(:year, year)
55
+ new_month = options.fetch(:month, month)
56
+ new_day = options.fetch(:day, day)
57
+ new_hour = options.fetch(:hour, hour)
58
+ new_min = options.fetch(:min, options[:hour] ? 0 : min)
59
+ new_sec = options.fetch(:sec, (options[:hour] || options[:min]) ? 0 : sec)
60
+ new_usec = options.fetch(:usec, (options[:hour] || options[:min] || options[:sec]) ? 0 : Rational(nsec, 1000))
61
+
62
+ if utc?
63
+ ::Time.utc(new_year, new_month, new_day, new_hour, new_min, new_sec, new_usec)
64
+ elsif zone
65
+ ::Time.local(new_year, new_month, new_day, new_hour, new_min, new_sec, new_usec)
66
+ else
67
+ ::Time.new(new_year, new_month, new_day, new_hour, new_min, new_sec + (new_usec.to_r / 1000000), utc_offset)
68
+ end
69
+ end
70
+
71
+ end
72
+
73
+ class Date
74
+
75
+ # activesupport/lib/active_support/core_ext/date/calculations.rb
76
+ def advance(options)
77
+ options = options.dup
78
+ d = self
79
+ d = d >> options.delete(:years) * 12 if options[:years]
80
+ d = d >> options.delete(:months) if options[:months]
81
+ d = d + options.delete(:weeks) * 7 if options[:weeks]
82
+ d = d + options.delete(:days) if options[:days]
83
+ d
84
+ end
85
+
86
+ end
@@ -47,6 +47,12 @@ module LeapCli
47
47
  # set up paths
48
48
  #
49
49
  @provider_directory_path = directory
50
+ begin
51
+ # load leaprc first, so that we can potentially access which environment is pinned in Leapfile
52
+ # but also load leaprc last, so that it can override what is set in Leapfile.
53
+ read_settings(leaprc_path)
54
+ rescue StandardError
55
+ end
50
56
  read_settings(directory + '/Leapfile')
51
57
  read_settings(leaprc_path)
52
58
  @platform_directory_path = File.expand_path(@platform_directory_path || '../leap_platform', @provider_directory_path)
@@ -54,25 +60,26 @@ module LeapCli
54
60
  #
55
61
  # load the platform
56
62
  #
57
- require "#{@platform_directory_path}/platform.rb"
58
- if !Leap::Platform.compatible_with_cli?(LeapCli::VERSION)
59
- Util.bail! "This leap command (v#{LeapCli::VERSION}) " +
60
- "is not compatible with the platform #{@platform_directory_path} (v#{Leap::Platform.version}). " +
61
- "You need leap command #{Leap::Platform.compatible_cli.first} to #{Leap::Platform.compatible_cli.last}."
63
+ platform_file = "#{@platform_directory_path}/platform.rb"
64
+ unless File.exists?(platform_file)
65
+ Util.bail! "ERROR: The file `#{platform_file}` does not exist. Please check the value of `@platform_directory_path` in `Leapfile` or `~/.leaprc`."
62
66
  end
63
- if !Leap::Platform.version_in_range?(LeapCli::COMPATIBLE_PLATFORM_VERSION)
67
+ require "#{@platform_directory_path}/platform.rb"
68
+ if !Leap::Platform.compatible_with_cli?(LeapCli::VERSION) ||
69
+ !Leap::Platform.version_in_range?(LeapCli::COMPATIBLE_PLATFORM_VERSION)
64
70
  Util.bail! "This leap command (v#{LeapCli::VERSION}) " +
65
- "is not compatible with the platform #{@platform_directory_path} (v#{Leap::Platform.version}). " +
66
- "You need platform version #{LeapCli::COMPATIBLE_PLATFORM_VERSION.first} to #{LeapCli::COMPATIBLE_PLATFORM_VERSION.last}."
71
+ "is not compatible with the platform #{@platform_directory_path} (v#{Leap::Platform.version}).\n " +
72
+ "You need either leap command #{Leap::Platform.compatible_cli.first} to #{Leap::Platform.compatible_cli.last} or " +
73
+ "platform version #{LeapCli::COMPATIBLE_PLATFORM_VERSION.first} to #{LeapCli::COMPATIBLE_PLATFORM_VERSION.last}"
67
74
  end
68
-
69
75
  unless @allow_production_deploy.nil?
70
76
  Util::log 0, :warning, "in Leapfile: @allow_production_deploy is no longer supported."
71
77
  end
72
78
  unless @platform_branch.nil?
73
79
  Util::log 0, :warning, "in Leapfile: @platform_branch is no longer supported."
74
80
  end
75
- return true
81
+ @valid = true
82
+ return @valid
76
83
  end
77
84
  end
78
85
 
@@ -84,6 +91,10 @@ module LeapCli
84
91
  edit_leaprc(property)
85
92
  end
86
93
 
94
+ def valid?
95
+ !!@valid
96
+ end
97
+
87
98
  private
88
99
 
89
100
  #
@@ -113,8 +113,8 @@ module LeapCli
113
113
  { :match => /sh: .+: command not found/, :color => :magenta, :match_level => 1, :priority => -30 },
114
114
 
115
115
  # IMPORTANT
116
- { :match => /^err ::/, :color => :red, :match_level => 0, :priority => -10 },
117
- { :match => /^ERROR:/, :color => :red, :match_level => 0, :priority => -10 },
116
+ { :match => /^err ::/, :color => :red, :match_level => 0, :priority => -10, :exit => 1},
117
+ { :match => /^ERROR:/, :color => :red, :priority => -10, :exit => 1},
118
118
  { :match => /.*/, :color => :blue, :match_level => 0, :priority => -20 },
119
119
 
120
120
  # CLEANUP
@@ -136,8 +136,8 @@ module LeapCli
136
136
  { :match => /^warning:/, :level => 0, :color => :yellow, :priority => -20},
137
137
  { :match => /^Duplicate declaration:/, :level => 0, :color => :red, :priority => -20},
138
138
  { :match => /Finished catalog run/, :level => 0, :color => :green, :priority => -10},
139
- { :match => /^Puppet apply complete \(changes made\)/, :level => 0, :color => :green, :priority => -10},
140
- { :match => /^Puppet apply complete \(no changes\)/, :level => 0, :color => :green, :priority => -10},
139
+ { :match => /^APPLY COMPLETE \(changes made\)/, :level => 0, :color => :green, :priority => -10},
140
+ { :match => /^APPLY COMPLETE \(no changes\)/, :level => 0, :color => :green, :priority => -10},
141
141
 
142
142
  # PUPPET FATAL ERRORS
143
143
  { :match => /^err:/, :level => 0, :color => :red, :priority => -1, :exit => 1},
@@ -146,7 +146,7 @@ module LeapCli
146
146
  { :match => /^Syntax error/, :level => 0, :color => :red, :priority => -1, :exit => 1},
147
147
  { :match => /^Cannot reassign variable/, :level => 0, :color => :red, :priority => -1, :exit => 1},
148
148
  { :match => /^Could not find template/, :level => 0, :color => :red, :priority => -1, :exit => 1},
149
- { :match => /^Puppet apply complete.*fail/, :level => 0, :color => :red, :priority => -1, :exit => 1},
149
+ { :match => /^APPLY COMPLETE.*fail/, :level => 0, :color => :red, :priority => -1, :exit => 1},
150
150
 
151
151
  # TESTS
152
152
  { :match => /^PASS: /, :color => :green, :priority => -20},
@@ -6,6 +6,10 @@
6
6
  module LeapCli; module Remote; module LeapPlugin
7
7
 
8
8
  def required_packages
9
+ "puppet rsync lsb-release locales"
10
+ end
11
+
12
+ def required_wheezy_packages
9
13
  "puppet ruby-hiera-puppet rsync lsb-release locales"
10
14
  end
11
15
 
@@ -60,6 +64,13 @@ module LeapCli; module Remote; module LeapPlugin
60
64
  run "touch #{Leap::Platform.init_path}"
61
65
  end
62
66
 
67
+ #
68
+ # dumps the recent deploy history to the console
69
+ #
70
+ def history
71
+ 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')"
72
+ end
73
+
63
74
  #
64
75
  # This is a hairy ugly hack, exactly the kind of stuff that makes ruby
65
76
  # dangerous and too much fun for its own good.
@@ -18,7 +18,7 @@ module LeapCli; module Remote; module PuppetPlugin
18
18
  elsif item[1] === true
19
19
  str << "--" + item[0].to_s
20
20
  else
21
- str << "--" + item[0].to_s + " " + item[1].to_s
21
+ str << "--" + item[0].to_s + " " + item[1].inspect
22
22
  end
23
23
  }.join(' ')
24
24
  end
@@ -34,10 +34,11 @@ BAD_APT_GET_UPDATE = /(BADSIG|NO_PUBKEY|KEYEXPIRED|REVKEYSIG|NODATA)/
34
34
 
35
35
  task :install_prerequisites, :max_hosts => MAX_HOSTS do
36
36
  apt_get = "DEBIAN_FRONTEND=noninteractive apt-get -q -y -o DPkg::Options::=--force-confold"
37
+ apt_get_update = "apt-get update -o Acquire::Languages=none"
37
38
  leap.mkdirs Leap::Platform.leap_dir
38
39
  run "echo 'en_US.UTF-8 UTF-8' > /etc/locale.gen"
39
40
  leap.log :updating, "package list" do
40
- run "apt-get update" do |channel, stream, data|
41
+ run apt_get_update do |channel, stream, data|
41
42
  # sadly exitcode is unreliable measure if apt-get update hit a failure.
42
43
  if data =~ BAD_APT_GET_UPDATE
43
44
  LeapCli::Util.bail! do
@@ -57,7 +58,7 @@ task :install_prerequisites, :max_hosts => MAX_HOSTS do
57
58
  run "( test -f /etc/init.d/ntp && /etc/init.d/ntp start ) || true"
58
59
  end
59
60
  leap.log :installing, "required packages" do
60
- run "#{apt_get} install #{leap.required_packages}"
61
+ run %[#{apt_get} install #{leap.required_wheezy_packages}]
61
62
  end
62
63
  #run "locale-gen"
63
64
  leap.mkdirs("/etc/leap", "/srv/leap")
data/lib/leap_cli/util.rb CHANGED
@@ -97,6 +97,23 @@ module LeapCli
97
97
  return output
98
98
  end
99
99
 
100
+ def assert_config!(conf_path)
101
+ value = nil
102
+ begin
103
+ value = manager.instance_eval(conf_path)
104
+ #rescue NoMethodError
105
+ #rescue NameError
106
+ ensure
107
+ assert! !value.nil? && value != "REQUIRED" do
108
+ log :missing, "required configuration value for #{conf_path}"
109
+ end
110
+ end
111
+ end
112
+
113
+ ##
114
+ ## FILES AND DIRECTORIES
115
+ ##
116
+
100
117
  def assert_files_missing!(*files)
101
118
  options = files.last.is_a?(Hash) ? files.pop : {}
102
119
  base = options[:base] || Path.provider
@@ -117,19 +134,6 @@ module LeapCli
117
134
  end
118
135
  end
119
136
 
120
- def assert_config!(conf_path)
121
- value = nil
122
- begin
123
- value = manager.instance_eval(conf_path)
124
- #rescue NoMethodError
125
- #rescue NameError
126
- ensure
127
- assert! !value.nil? && value != "REQUIRED" do
128
- log :missing, "required configuration value for #{conf_path}"
129
- end
130
- end
131
- end
132
-
133
137
  def assert_files_exist!(*files)
134
138
  options = files.last.is_a?(Hash) ? files.pop : {}
135
139
  file_list = files.collect { |file_path|
@@ -149,6 +153,7 @@ module LeapCli
149
153
  end
150
154
  end
151
155
 
156
+ # takes a list of symbolic paths. returns true if all files exist or are directories.
152
157
  def file_exists?(*files)
153
158
  files.each do |file_path|
154
159
  file_path = Path.named_path(file_path)
@@ -159,9 +164,16 @@ module LeapCli
159
164
  return true
160
165
  end
161
166
 
162
- ##
163
- ## FILES AND DIRECTORIES
164
- ##
167
+ # takes a list of symbolic paths. returns true if all are directories.
168
+ def dir_exists?(*dirs)
169
+ dirs.each do |dir_path|
170
+ dir_path = Path.named_path(dir_path)
171
+ if !Dir.exists?(dir_path)
172
+ return false
173
+ end
174
+ end
175
+ return true
176
+ end
165
177
 
166
178
  #
167
179
  # creates a directory if it doesn't already exist
@@ -343,16 +355,12 @@ module LeapCli
343
355
  end
344
356
 
345
357
  #
346
- # compares md5 fingerprints to see if the contents of a file match the string we have in memory
358
+ # compares md5 fingerprints to see if the contents of a file match the
359
+ # string we have in memory
347
360
  #
348
361
  def file_content_equals?(filepath, contents)
349
362
  filepath = Path.named_path(filepath)
350
- output = `md5sum '#{filepath}'`.strip
351
- if $?.to_i == 0
352
- return output.split(" ").first == Digest::MD5.hexdigest(contents).to_s
353
- else
354
- return false
355
- end
363
+ Digest::MD5.file(filepath).hexdigest == Digest::MD5.hexdigest(contents)
356
364
  end
357
365
 
358
366
  ##
@@ -8,7 +8,7 @@ autoload :OpenSSL, 'openssl'
8
8
 
9
9
  module LeapCli; module Util
10
10
  class Secret
11
- CHARS = ('A'..'Z').to_a + ('a'..'z').to_a + ('0'..'9').to_a + "_".split(//u) - "io01lO".split(//u)
11
+ CHARS = (('A'..'Z').to_a + ('a'..'z').to_a + ('0'..'9').to_a) - "i1loO06G".split(//u)
12
12
  HEX = (0..9).to_a + ('a'..'f').to_a
13
13
 
14
14
  #