leap_cli 1.8.1 → 1.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/leap +6 -12
- data/lib/leap_cli.rb +3 -23
- data/lib/leap_cli/bootstrap.rb +36 -12
- data/lib/leap_cli/commands/common.rb +88 -46
- data/lib/leap_cli/commands/new.rb +24 -17
- data/lib/leap_cli/commands/pre.rb +3 -1
- data/lib/leap_cli/core_ext/hash.rb +19 -0
- data/lib/leap_cli/leapfile.rb +47 -32
- data/lib/leap_cli/log.rb +196 -88
- data/lib/leap_cli/path.rb +5 -5
- data/lib/leap_cli/util.rb +28 -18
- data/lib/leap_cli/version.rb +8 -3
- data/vendor/acme-client/lib/acme-client.rb +1 -0
- data/vendor/acme-client/lib/acme/client.rb +122 -0
- data/vendor/acme-client/lib/acme/client/certificate.rb +30 -0
- data/vendor/acme-client/lib/acme/client/certificate_request.rb +111 -0
- data/vendor/acme-client/lib/acme/client/crypto.rb +98 -0
- data/vendor/acme-client/lib/acme/client/error.rb +16 -0
- data/vendor/acme-client/lib/acme/client/faraday_middleware.rb +123 -0
- data/vendor/acme-client/lib/acme/client/resources.rb +5 -0
- data/vendor/acme-client/lib/acme/client/resources/authorization.rb +44 -0
- data/vendor/acme-client/lib/acme/client/resources/challenges.rb +6 -0
- data/vendor/acme-client/lib/acme/client/resources/challenges/base.rb +43 -0
- data/vendor/acme-client/lib/acme/client/resources/challenges/dns01.rb +19 -0
- data/vendor/acme-client/lib/acme/client/resources/challenges/http01.rb +18 -0
- data/vendor/acme-client/lib/acme/client/resources/challenges/tls_sni01.rb +24 -0
- data/vendor/acme-client/lib/acme/client/resources/registration.rb +37 -0
- data/vendor/acme-client/lib/acme/client/self_sign_certificate.rb +60 -0
- data/vendor/acme-client/lib/acme/client/version.rb +7 -0
- data/vendor/base32/lib/base32.rb +67 -0
- data/vendor/certificate_authority/lib/certificate_authority.rb +2 -1
- data/vendor/certificate_authority/lib/certificate_authority/certificate.rb +4 -4
- data/vendor/certificate_authority/lib/certificate_authority/certificate_revocation_list.rb +7 -5
- data/vendor/certificate_authority/lib/certificate_authority/core_extensions.rb +46 -0
- data/vendor/certificate_authority/lib/certificate_authority/distinguished_name.rb +6 -2
- data/vendor/certificate_authority/lib/certificate_authority/extensions.rb +10 -3
- data/vendor/certificate_authority/lib/certificate_authority/key_material.rb +11 -9
- data/vendor/certificate_authority/lib/certificate_authority/ocsp_handler.rb +3 -3
- data/vendor/certificate_authority/lib/certificate_authority/pkcs11_key_material.rb +0 -2
- data/vendor/certificate_authority/lib/certificate_authority/serial_number.rb +8 -2
- data/vendor/certificate_authority/lib/certificate_authority/validations.rb +31 -0
- data/vendor/rsync_command/lib/rsync_command.rb +49 -12
- metadata +50 -91
- data/lib/leap/platform.rb +0 -90
- data/lib/leap_cli/config/environment.rb +0 -180
- data/lib/leap_cli/config/filter.rb +0 -178
- data/lib/leap_cli/config/manager.rb +0 -419
- data/lib/leap_cli/config/node.rb +0 -77
- data/lib/leap_cli/config/object.rb +0 -428
- data/lib/leap_cli/config/object_list.rb +0 -209
- data/lib/leap_cli/config/provider.rb +0 -22
- data/lib/leap_cli/config/secrets.rb +0 -87
- data/lib/leap_cli/config/sources.rb +0 -11
- data/lib/leap_cli/config/tag.rb +0 -25
- data/lib/leap_cli/lib_ext/capistrano_connections.rb +0 -16
- data/lib/leap_cli/logger.rb +0 -237
- data/lib/leap_cli/remote/leap_plugin.rb +0 -192
- data/lib/leap_cli/remote/puppet_plugin.rb +0 -26
- data/lib/leap_cli/remote/rsync_plugin.rb +0 -35
- data/lib/leap_cli/remote/tasks.rb +0 -51
- data/lib/leap_cli/ssh_key.rb +0 -195
- data/lib/leap_cli/util/remote_command.rb +0 -158
- data/lib/leap_cli/util/secret.rb +0 -55
- data/lib/leap_cli/util/x509.rb +0 -33
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c76581ff17beffa03bea2e6447ec048d9282cd43
|
4
|
+
data.tar.gz: e1b082558769fad1644c0bf78afa138aa66fcb15
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fc24e99df33af964af23fdff085bb2a87808a92138545378c70fd43e0a1c0581394c3d7c9faffa774feffb063c3da491f7a892267beb985672d736c603aff79a
|
7
|
+
data.tar.gz: 67c3838bc0eeaf0bd72eaf1d6c843fbfeca25414bec9ccc4120cf2e514cb2f157cad942fd4b7c67b4d9803097e11694ff0360f4eb0cf0b1e312bf0734fce1449
|
data/bin/leap
CHANGED
@@ -14,6 +14,7 @@ else
|
|
14
14
|
$VERBOSE=nil
|
15
15
|
DEBUG=false
|
16
16
|
end
|
17
|
+
TEST = false
|
17
18
|
|
18
19
|
LEAP_CLI_BASE_DIR = File.expand_path('..', File.dirname(File.symlink?(__FILE__) ? File.readlink(__FILE__) : __FILE__))
|
19
20
|
|
@@ -27,8 +28,6 @@ rescue LoadError
|
|
27
28
|
end
|
28
29
|
|
29
30
|
require 'gli'
|
30
|
-
require 'highline'
|
31
|
-
require 'forwardable'
|
32
31
|
require 'leap_cli/lib_ext/gli' # our custom extensions to gli
|
33
32
|
|
34
33
|
#
|
@@ -40,16 +39,6 @@ require 'leap_cli/lib_ext/gli' # our custom extensions to gli
|
|
40
39
|
#
|
41
40
|
module LeapCli::Commands
|
42
41
|
extend GLI::App
|
43
|
-
extend Forwardable
|
44
|
-
|
45
|
-
# delegate highline methods to make them available to sub-commands
|
46
|
-
@terminal = HighLine.new
|
47
|
-
def_delegator :@terminal, :ask, 'self.ask'
|
48
|
-
def_delegator :@terminal, :agree, 'self.agree'
|
49
|
-
def_delegator :@terminal, :choose, 'self.choose'
|
50
|
-
def_delegator :@terminal, :say, 'self.say'
|
51
|
-
def_delegator :@terminal, :color, 'self.color'
|
52
|
-
def_delegator :@terminal, :list, 'self.list'
|
53
42
|
|
54
43
|
# make config manager available as 'manager'
|
55
44
|
def self.manager
|
@@ -90,6 +79,9 @@ module LeapCli::Commands
|
|
90
79
|
|
91
80
|
# run command
|
92
81
|
begin
|
82
|
+
if ARGV.any?
|
83
|
+
LeapCli.log_raw(:log, nil, "COMMAND") { 'leap ' + ARGV.join(' ') }
|
84
|
+
end
|
93
85
|
exit_status = run(ARGV)
|
94
86
|
exit(LeapCli::Util.exit_status || exit_status)
|
95
87
|
rescue StandardError => exc
|
@@ -102,6 +94,8 @@ module LeapCli::Commands
|
|
102
94
|
end
|
103
95
|
if DEBUG
|
104
96
|
raise exc
|
97
|
+
else
|
98
|
+
exit(1)
|
105
99
|
end
|
106
100
|
end
|
107
101
|
end
|
data/lib/leap_cli.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module LeapCli
|
2
|
-
module Commands; end # for commands in leap_cli/commands
|
3
|
-
module Macro; end # for macros in leap_platform/
|
2
|
+
module Commands; end # for commands in leap_platform/lib/leap_cli/commands
|
3
|
+
module Macro; end # for macros in leap_platform/lib/leap_cli/macros
|
4
4
|
end
|
5
5
|
|
6
6
|
$ruby_version = RUBY_VERSION.split('.').collect{ |i| i.to_i }.extend(Comparable)
|
@@ -11,11 +11,8 @@ $:.unshift(File.expand_path('../leap_cli/override',__FILE__))
|
|
11
11
|
# for a few gems, things will break if using earlier versions.
|
12
12
|
# enforce the compatible versions here:
|
13
13
|
require 'rubygems'
|
14
|
-
gem 'net-ssh', '~> 2.7'
|
15
14
|
gem 'gli', '~> 2.12', '>= 2.12.0'
|
16
15
|
|
17
|
-
require 'leap/platform'
|
18
|
-
|
19
16
|
require 'leap_cli/version'
|
20
17
|
require 'leap_cli/exceptions'
|
21
18
|
|
@@ -32,30 +29,13 @@ require 'leap_cli/core_ext/yaml'
|
|
32
29
|
require 'leap_cli/log'
|
33
30
|
require 'leap_cli/path'
|
34
31
|
require 'leap_cli/util'
|
35
|
-
require 'leap_cli/util/secret'
|
36
|
-
require 'leap_cli/util/remote_command'
|
37
|
-
require 'leap_cli/util/x509'
|
38
|
-
require 'leap_cli/logger'
|
39
32
|
require 'leap_cli/bootstrap'
|
40
33
|
|
41
|
-
require 'leap_cli/ssh_key'
|
42
|
-
require 'leap_cli/config/object'
|
43
|
-
require 'leap_cli/config/node'
|
44
|
-
require 'leap_cli/config/tag'
|
45
|
-
require 'leap_cli/config/provider'
|
46
|
-
require 'leap_cli/config/secrets'
|
47
|
-
require 'leap_cli/config/object_list'
|
48
|
-
require 'leap_cli/config/filter'
|
49
|
-
require 'leap_cli/config/environment'
|
50
|
-
require 'leap_cli/config/manager'
|
51
|
-
|
52
34
|
require 'leap_cli/markdown_document_listener'
|
53
35
|
|
54
36
|
#
|
55
37
|
# allow everyone easy access to log() command.
|
56
38
|
#
|
57
39
|
module LeapCli
|
58
|
-
|
59
|
-
Config::Manager.send(:include, LeapCli::Log)
|
60
|
-
extend LeapCli::Log
|
40
|
+
extend LeapCli::LogCommand
|
61
41
|
end
|
data/lib/leap_cli/bootstrap.rb
CHANGED
@@ -5,8 +5,8 @@
|
|
5
5
|
|
6
6
|
module LeapCli
|
7
7
|
module Bootstrap
|
8
|
-
extend LeapCli::Log
|
9
8
|
extend self
|
9
|
+
extend LeapCli::LogCommand
|
10
10
|
|
11
11
|
#
|
12
12
|
# the argument leapfile_path is only used for tests
|
@@ -36,9 +36,11 @@ module LeapCli
|
|
36
36
|
# called from leap executable.
|
37
37
|
#
|
38
38
|
def load_libraries(app)
|
39
|
-
if LeapCli.log_level >= 2
|
39
|
+
if LeapCli.logger.log_level >= 2
|
40
40
|
log_version
|
41
41
|
end
|
42
|
+
add_platform_lib_to_path
|
43
|
+
load_platform_libraries
|
42
44
|
load_commands(app)
|
43
45
|
load_macros
|
44
46
|
end
|
@@ -72,14 +74,14 @@ module LeapCli
|
|
72
74
|
options = parse_logging_options(argv)
|
73
75
|
verbose = (options[:verbose] || 1).to_i
|
74
76
|
if verbose
|
75
|
-
LeapCli.
|
77
|
+
LeapCli.logger.log_level = verbose
|
76
78
|
end
|
77
79
|
if options[:log]
|
78
|
-
LeapCli.log_file = options[:log]
|
79
|
-
LeapCli
|
80
|
+
LeapCli.logger.log_file = options[:log]
|
81
|
+
LeapCli.logger.log_raw(:log) { $0 + ' ' + argv.join(' ')}
|
80
82
|
end
|
81
83
|
unless options[:color].nil?
|
82
|
-
LeapCli.log_in_color = options[:color]
|
84
|
+
LeapCli.logger.log_in_color = options[:color]
|
83
85
|
end
|
84
86
|
end
|
85
87
|
|
@@ -97,17 +99,16 @@ module LeapCli
|
|
97
99
|
if !Path.platform || !File.directory?(Path.platform)
|
98
100
|
bail! { log :missing, "platform directory '#{Path.platform}'" }
|
99
101
|
end
|
100
|
-
if LeapCli.log_file.nil? && LeapCli.leapfile.log
|
101
|
-
LeapCli.log_file = LeapCli.leapfile.log
|
102
|
+
if LeapCli.logger.log_file.nil? && LeapCli.leapfile.log
|
103
|
+
LeapCli.logger.log_file = LeapCli.leapfile.log
|
102
104
|
end
|
103
105
|
elsif !leapfile_optional?(argv)
|
104
106
|
puts
|
105
107
|
puts " ="
|
106
|
-
log :
|
107
|
-
" =
|
108
|
+
log :NOTE, "There is no `Leapfile` in this directory, or any parent directory.\n"+
|
109
|
+
" = "+
|
108
110
|
"Without this file, most commands will not be available."
|
109
111
|
puts " ="
|
110
|
-
puts
|
111
112
|
end
|
112
113
|
end
|
113
114
|
|
@@ -158,7 +159,9 @@ module LeapCli
|
|
158
159
|
# Yes, hacky.
|
159
160
|
#
|
160
161
|
def leapfile_optional?(argv)
|
161
|
-
if
|
162
|
+
if TEST
|
163
|
+
return true
|
164
|
+
elsif argv.include?('--version')
|
162
165
|
return true
|
163
166
|
else
|
164
167
|
without_flags = argv.select {|i| i !~ /^-/}
|
@@ -193,5 +196,26 @@ module LeapCli
|
|
193
196
|
end
|
194
197
|
end
|
195
198
|
|
199
|
+
#
|
200
|
+
# makes all the ruby libraries in the leap_platform/lib directory
|
201
|
+
# available for inclusion.
|
202
|
+
#
|
203
|
+
def add_platform_lib_to_path
|
204
|
+
if Path.platform
|
205
|
+
path = File.join(Path.platform, 'lib')
|
206
|
+
$LOAD_PATH.unshift(path) unless $LOAD_PATH.include?(path)
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
#
|
211
|
+
# loads libraries that live in the platform and should
|
212
|
+
# always be available.
|
213
|
+
#
|
214
|
+
def load_platform_libraries
|
215
|
+
if Path.platform
|
216
|
+
require 'leap_cli/load_libraries'
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
196
220
|
end
|
197
221
|
end
|
@@ -1,61 +1,103 @@
|
|
1
|
-
|
2
|
-
# Some common helpers available to all LeapCli::Commands
|
3
|
-
#
|
4
|
-
# This also includes utility methods, and makes all instance
|
5
|
-
# methods available as class methods.
|
6
|
-
#
|
1
|
+
require 'readline'
|
7
2
|
|
8
|
-
module LeapCli
|
9
|
-
module Commands
|
3
|
+
module LeapCli; module Commands
|
10
4
|
|
11
|
-
|
12
|
-
|
13
|
-
extend LeapCli::Util
|
14
|
-
extend LeapCli::Util::RemoteCommand
|
5
|
+
extend LeapCli::LogCommand
|
6
|
+
extend LeapCli::Util
|
15
7
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
Path.named_path(name)
|
20
|
-
end
|
8
|
+
def path(name)
|
9
|
+
Path.named_path(name)
|
10
|
+
end
|
21
11
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
12
|
+
#
|
13
|
+
# keeps prompting the user for a numbered choice, until they pick a good one or bail out.
|
14
|
+
#
|
15
|
+
# block is yielded and is responsible for rendering the choices.
|
16
|
+
#
|
17
|
+
def numbered_choice_menu(msg, items, &block)
|
18
|
+
while true
|
19
|
+
say("\n" + msg + ':')
|
20
|
+
items.each_with_index(&block)
|
21
|
+
say("q. quit")
|
22
|
+
index = ask("number 1-#{items.length}> ")
|
23
|
+
if index.nil? || index.empty?
|
24
|
+
next
|
25
|
+
elsif index =~ /q/
|
26
|
+
bail!
|
27
|
+
else
|
28
|
+
i = index.to_i - 1
|
29
|
+
if i < 0 || i >= items.length
|
36
30
|
bail!
|
37
31
|
else
|
38
|
-
i
|
39
|
-
if i < 0 || i >= items.length
|
40
|
-
bail!
|
41
|
-
else
|
42
|
-
return i
|
43
|
-
end
|
32
|
+
return i
|
44
33
|
end
|
45
34
|
end
|
46
35
|
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def parse_node_list(nodes)
|
39
|
+
if nodes.is_a? Config::Object
|
40
|
+
Config::ObjectList.new(nodes)
|
41
|
+
elsif nodes.is_a? Config::ObjectList
|
42
|
+
nodes
|
43
|
+
elsif nodes.is_a? String
|
44
|
+
manager.filter!(nodes)
|
45
|
+
else
|
46
|
+
bail! "argument error"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def say(statement)
|
51
|
+
if ends_in_whitespace?(statement)
|
52
|
+
$stdout.print(statement)
|
53
|
+
$stdout.flush
|
54
|
+
else
|
55
|
+
$stdout.puts(statement)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def ask(question, options={})
|
60
|
+
default = options[:default]
|
61
|
+
if default
|
62
|
+
if ends_in_whitespace?(question)
|
63
|
+
question = question + "|" + default + "| "
|
64
|
+
else
|
65
|
+
question = question + "|" + default + "|"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
response = Readline.readline(question, true) # set to false if ever reading passwords.
|
69
|
+
if response
|
70
|
+
response = response.strip
|
71
|
+
if response.empty?
|
72
|
+
return default
|
73
|
+
else
|
74
|
+
return response
|
75
|
+
end
|
76
|
+
else
|
77
|
+
return default
|
78
|
+
end
|
79
|
+
end
|
47
80
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
elsif
|
54
|
-
|
81
|
+
def agree(question, options={})
|
82
|
+
while true
|
83
|
+
response = ask(question, options)
|
84
|
+
if response.nil?
|
85
|
+
say('Please enter "yes" or "no".')
|
86
|
+
elsif ["y","yes", "ye"].include?(response.downcase)
|
87
|
+
return true
|
88
|
+
elsif ["n", "no"].include?(response.downcase)
|
89
|
+
return false
|
55
90
|
else
|
56
|
-
|
91
|
+
say('Please enter "yes" or "no".')
|
57
92
|
end
|
58
93
|
end
|
94
|
+
end
|
59
95
|
|
96
|
+
private
|
97
|
+
|
98
|
+
# true if str ends in whitespace before a color escape code.
|
99
|
+
def ends_in_whitespace?(str)
|
100
|
+
/[ \t](\e\[\d+(;\d+)*m)?\Z/ =~ str
|
60
101
|
end
|
61
|
-
|
102
|
+
|
103
|
+
end; end
|
@@ -4,7 +4,6 @@ module LeapCli; module Commands
|
|
4
4
|
|
5
5
|
desc 'Creates a new provider instance in the specified directory, creating it if necessary.'
|
6
6
|
arg_name 'DIRECTORY'
|
7
|
-
#skips_pre
|
8
7
|
command :new do |c|
|
9
8
|
c.flag 'name', :desc => "The name of the provider." #, :default_value => 'Example'
|
10
9
|
c.flag 'domain', :desc => "The primary domain of the provider." #, :default_value => 'example.org'
|
@@ -12,19 +11,7 @@ module LeapCli; module Commands
|
|
12
11
|
c.flag 'contacts', :desc => "Default email address contacts." #, :default_value => 'root'
|
13
12
|
|
14
13
|
c.action do |global, options, args|
|
15
|
-
|
16
|
-
# this should not be needed, but GLI is not making it required.
|
17
|
-
bail! "Argument DIRECTORY is required."
|
18
|
-
end
|
19
|
-
directory = File.expand_path(args.first)
|
20
|
-
create_provider_directory(global, directory)
|
21
|
-
options[:domain] ||= ask_string("The primary domain of the provider: ") {|q| q.default = 'example.org'}
|
22
|
-
options[:name] ||= ask_string("The name of the provider: ") {|q| q.default = 'Example'}
|
23
|
-
options[:platform] ||= ask_string("File path of the leap_platform directory: ") {|q| q.default = File.expand_path('../leap_platform', directory)}
|
24
|
-
options[:platform] = "./" + options[:platform] unless options[:platform] =~ /^\//
|
25
|
-
options[:contacts] ||= ask_string("Default email address contacts: ") {|q| q.default = 'root@' + options[:domain]}
|
26
|
-
options[:platform] = relative_path(options[:platform])
|
27
|
-
create_initial_provider_files(directory, global, options)
|
14
|
+
new_provider_action(global, options, args)
|
28
15
|
end
|
29
16
|
end
|
30
17
|
|
@@ -32,13 +19,33 @@ module LeapCli; module Commands
|
|
32
19
|
|
33
20
|
DEFAULT_REPO = 'https://leap.se/git/leap_platform.git'
|
34
21
|
|
22
|
+
def new_provider_action(global, options, args)
|
23
|
+
unless args.first
|
24
|
+
# this should not be needed, but GLI is not making it required.
|
25
|
+
bail! "Argument DIRECTORY is required."
|
26
|
+
end
|
27
|
+
directory = File.expand_path(args.first)
|
28
|
+
create_provider_directory(global, directory)
|
29
|
+
options[:domain] ||= ask_string("The primary domain of the provider: ",
|
30
|
+
default: 'example.org')
|
31
|
+
options[:name] ||= ask_string("The name of the provider: ",
|
32
|
+
default: 'Example')
|
33
|
+
options[:platform] ||= ask_string("File path of the leap_platform directory: ",
|
34
|
+
default: File.expand_path('../leap_platform', directory))
|
35
|
+
options[:platform] = "./" + options[:platform] unless options[:platform] =~ /^\//
|
36
|
+
options[:contacts] ||= ask_string("Default email address contacts: ",
|
37
|
+
default: 'root@' + options[:domain])
|
38
|
+
options[:platform] = relative_path(options[:platform])
|
39
|
+
create_initial_provider_files(directory, global, options)
|
40
|
+
end
|
41
|
+
|
35
42
|
#
|
36
43
|
# don't let the user specify any of the following: y, yes, n, no
|
37
44
|
# they must actually input a real string
|
38
45
|
#
|
39
|
-
def ask_string(str,
|
46
|
+
def ask_string(str, options={})
|
40
47
|
while true
|
41
|
-
value = ask(str,
|
48
|
+
value = ask(str, options)
|
42
49
|
if value =~ /^(y|yes|n|no)$/i
|
43
50
|
say "`#{value}` is not a valid value. Try again"
|
44
51
|
else
|
@@ -54,7 +61,7 @@ module LeapCli; module Commands
|
|
54
61
|
unless directory && directory.any?
|
55
62
|
help! "Directory name is required."
|
56
63
|
end
|
57
|
-
unless File.
|
64
|
+
unless File.exist?(directory)
|
58
65
|
if global[:yes] || agree("Create directory #{directory}? ")
|
59
66
|
ensure_dir directory
|
60
67
|
else
|
@@ -1,9 +1,11 @@
|
|
1
|
-
|
2
1
|
#
|
3
2
|
# check to make sure we can find the root directory of the platform
|
4
3
|
#
|
5
4
|
module LeapCli; module Commands
|
6
5
|
|
6
|
+
extend self # this is a trick to make all instance methods
|
7
|
+
# available as class methods.
|
8
|
+
|
7
9
|
desc 'Verbosity level 0..5'
|
8
10
|
arg_name 'LEVEL'
|
9
11
|
default_value '1'
|