leap_cli 1.6.2 → 1.7.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
  #