leap_cli 1.7.4 → 1.8
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 -13
- data/lib/leap/platform.rb +2 -0
- data/lib/leap_cli.rb +2 -1
- data/lib/leap_cli/bootstrap.rb +197 -0
- data/lib/leap_cli/commands/common.rb +61 -0
- data/lib/leap_cli/commands/new.rb +5 -1
- data/lib/leap_cli/commands/pre.rb +1 -66
- data/lib/leap_cli/config/environment.rb +180 -0
- data/lib/leap_cli/config/manager.rb +100 -197
- data/lib/leap_cli/config/node.rb +2 -2
- data/lib/leap_cli/config/object.rb +56 -43
- data/lib/leap_cli/config/object_list.rb +6 -3
- data/lib/leap_cli/config/provider.rb +11 -0
- data/lib/leap_cli/config/secrets.rb +14 -1
- data/lib/leap_cli/config/tag.rb +2 -2
- data/lib/leap_cli/leapfile.rb +1 -0
- data/lib/leap_cli/log.rb +1 -0
- data/lib/leap_cli/logger.rb +16 -12
- data/lib/leap_cli/markdown_document_listener.rb +3 -1
- data/lib/leap_cli/path.rb +12 -0
- data/lib/leap_cli/remote/leap_plugin.rb +9 -34
- data/lib/leap_cli/remote/puppet_plugin.rb +0 -40
- data/lib/leap_cli/remote/tasks.rb +9 -34
- data/lib/leap_cli/ssh_key.rb +5 -2
- data/lib/leap_cli/version.rb +2 -2
- metadata +5 -18
- data/lib/leap_cli/commands/ca.rb +0 -518
- data/lib/leap_cli/commands/clean.rb +0 -16
- data/lib/leap_cli/commands/compile.rb +0 -340
- data/lib/leap_cli/commands/db.rb +0 -65
- data/lib/leap_cli/commands/deploy.rb +0 -368
- data/lib/leap_cli/commands/env.rb +0 -76
- data/lib/leap_cli/commands/facts.rb +0 -100
- data/lib/leap_cli/commands/inspect.rb +0 -144
- data/lib/leap_cli/commands/list.rb +0 -132
- data/lib/leap_cli/commands/node.rb +0 -165
- data/lib/leap_cli/commands/node_init.rb +0 -169
- data/lib/leap_cli/commands/ssh.rb +0 -220
- data/lib/leap_cli/commands/test.rb +0 -74
- data/lib/leap_cli/commands/user.rb +0 -136
- data/lib/leap_cli/commands/util.rb +0 -50
- data/lib/leap_cli/commands/vagrant.rb +0 -197
@@ -1,74 +0,0 @@
|
|
1
|
-
module LeapCli; module Commands
|
2
|
-
|
3
|
-
desc 'Run tests.'
|
4
|
-
command [:test, :t] do |test|
|
5
|
-
test.desc 'Run the test suit on FILTER nodes.'
|
6
|
-
test.arg_name 'FILTER', :optional => true
|
7
|
-
test.command :run do |run|
|
8
|
-
run.switch 'continue', :desc => 'Continue over errors and failures (default is --no-continue).', :negatable => true
|
9
|
-
run.action do |global_options,options,args|
|
10
|
-
test_order = File.join(Path.platform, 'tests/order.rb')
|
11
|
-
if File.exists?(test_order)
|
12
|
-
require test_order
|
13
|
-
end
|
14
|
-
manager.filter!(args).names_in_test_dependency_order.each do |node_name|
|
15
|
-
node = manager.nodes[node_name]
|
16
|
-
begin
|
17
|
-
ssh_connect(node) do |ssh|
|
18
|
-
ssh.run(test_cmd(options))
|
19
|
-
end
|
20
|
-
rescue Capistrano::CommandError => exc
|
21
|
-
if options[:continue]
|
22
|
-
exit_status(1)
|
23
|
-
else
|
24
|
-
bail!
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
test.desc 'Creates files needed to run tests.'
|
32
|
-
test.command :init do |init|
|
33
|
-
init.action do |global_options,options,args|
|
34
|
-
generate_test_client_openvpn_configs
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
test.default_command :run
|
39
|
-
end
|
40
|
-
|
41
|
-
private
|
42
|
-
|
43
|
-
def test_cmd(options)
|
44
|
-
if options[:continue]
|
45
|
-
"#{Leap::Platform.leap_dir}/bin/run_tests --continue"
|
46
|
-
else
|
47
|
-
"#{Leap::Platform.leap_dir}/bin/run_tests"
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
#
|
52
|
-
# generates a whole bunch of openvpn configs that can be used to connect to different openvpn gateways
|
53
|
-
#
|
54
|
-
def generate_test_client_openvpn_configs
|
55
|
-
assert_config! 'provider.ca.client_certificates.unlimited_prefix'
|
56
|
-
assert_config! 'provider.ca.client_certificates.limited_prefix'
|
57
|
-
template = read_file! Path.find_file(:test_client_openvpn_template)
|
58
|
-
manager.environment_names.each do |env|
|
59
|
-
vpn_nodes = manager.nodes[:environment => env][:services => 'openvpn']['openvpn.allow_limited' => true]
|
60
|
-
if vpn_nodes.any?
|
61
|
-
generate_test_client_cert(provider.ca.client_certificates.limited_prefix) do |key, cert|
|
62
|
-
write_file! [:test_openvpn_config, [env, 'limited'].compact.join('_')], Util.erb_eval(template, binding)
|
63
|
-
end
|
64
|
-
end
|
65
|
-
vpn_nodes = manager.nodes[:environment => env][:services => 'openvpn']['openvpn.allow_unlimited' => true]
|
66
|
-
if vpn_nodes.any?
|
67
|
-
generate_test_client_cert(provider.ca.client_certificates.unlimited_prefix) do |key, cert|
|
68
|
-
write_file! [:test_openvpn_config, [env, 'unlimited'].compact.join('_')], Util.erb_eval(template, binding)
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
end; end
|
@@ -1,136 +0,0 @@
|
|
1
|
-
|
2
|
-
#
|
3
|
-
# perhaps we want to verify that the key files are actually the key files we expect.
|
4
|
-
# we could use 'file' for this:
|
5
|
-
#
|
6
|
-
# > file ~/.gnupg/00440025.asc
|
7
|
-
# ~/.gnupg/00440025.asc: PGP public key block
|
8
|
-
#
|
9
|
-
# > file ~/.ssh/id_rsa.pub
|
10
|
-
# ~/.ssh/id_rsa.pub: OpenSSH RSA public key
|
11
|
-
#
|
12
|
-
|
13
|
-
module LeapCli
|
14
|
-
module Commands
|
15
|
-
|
16
|
-
desc 'Adds a new trusted sysadmin by adding public keys to the "users" directory.'
|
17
|
-
arg_name 'USERNAME' #, :optional => false, :multiple => false
|
18
|
-
command :'add-user' do |c|
|
19
|
-
|
20
|
-
c.switch 'self', :desc => 'Add yourself as a trusted sysadin by choosing among the public keys available for the current user.', :negatable => false
|
21
|
-
c.flag 'ssh-pub-key', :desc => 'SSH public key file for this new user'
|
22
|
-
c.flag 'pgp-pub-key', :desc => 'OpenPGP public key file for this new user'
|
23
|
-
|
24
|
-
c.action do |global_options,options,args|
|
25
|
-
username = args.first
|
26
|
-
if !username.any?
|
27
|
-
if options[:self]
|
28
|
-
username ||= `whoami`.strip
|
29
|
-
else
|
30
|
-
help! "Either USERNAME argument or --self flag is required."
|
31
|
-
end
|
32
|
-
end
|
33
|
-
if Leap::Platform.reserved_usernames.include? username
|
34
|
-
bail! %(The username "#{username}" is reserved. Sorry, pick another.)
|
35
|
-
end
|
36
|
-
|
37
|
-
ssh_pub_key = nil
|
38
|
-
pgp_pub_key = nil
|
39
|
-
|
40
|
-
if options['ssh-pub-key']
|
41
|
-
ssh_pub_key = read_file!(options['ssh-pub-key'])
|
42
|
-
end
|
43
|
-
if options['pgp-pub-key']
|
44
|
-
pgp_pub_key = read_file!(options['pgp-pub-key'])
|
45
|
-
end
|
46
|
-
|
47
|
-
if options[:self]
|
48
|
-
ssh_pub_key ||= pick_ssh_key.to_s
|
49
|
-
pgp_pub_key ||= pick_pgp_key
|
50
|
-
end
|
51
|
-
|
52
|
-
assert!(ssh_pub_key, 'Sorry, could not find SSH public key.')
|
53
|
-
|
54
|
-
if ssh_pub_key
|
55
|
-
write_file!([:user_ssh, username], ssh_pub_key)
|
56
|
-
end
|
57
|
-
if pgp_pub_key
|
58
|
-
write_file!([:user_pgp, username], pgp_pub_key)
|
59
|
-
end
|
60
|
-
|
61
|
-
update_authorized_keys
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
#
|
66
|
-
# let the the user choose among the ssh public keys that we encounter, or just pick the key if there is only one.
|
67
|
-
#
|
68
|
-
def pick_ssh_key
|
69
|
-
ssh_keys = []
|
70
|
-
Dir.glob("#{ENV['HOME']}/.ssh/*.pub").each do |keyfile|
|
71
|
-
ssh_keys << SshKey.load(keyfile)
|
72
|
-
end
|
73
|
-
|
74
|
-
if `which ssh-add`.strip.any?
|
75
|
-
`ssh-add -L 2> /dev/null`.split("\n").compact.each do |line|
|
76
|
-
key = SshKey.load(line)
|
77
|
-
if key
|
78
|
-
key.comment = 'ssh-agent'
|
79
|
-
ssh_keys << key unless ssh_keys.include?(key)
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|
83
|
-
ssh_keys.compact!
|
84
|
-
|
85
|
-
assert! ssh_keys.any?, 'Sorry, could not find any SSH public key for you. Have you run ssh-keygen?'
|
86
|
-
|
87
|
-
if ssh_keys.length > 1
|
88
|
-
key_index = numbered_choice_menu('Choose your SSH public key', ssh_keys.collect(&:summary)) do |line, i|
|
89
|
-
say("#{i+1}. #{line}")
|
90
|
-
end
|
91
|
-
else
|
92
|
-
key_index = 0
|
93
|
-
end
|
94
|
-
|
95
|
-
return ssh_keys[key_index]
|
96
|
-
end
|
97
|
-
|
98
|
-
#
|
99
|
-
# let the the user choose among the gpg public keys that we encounter, or just pick the key if there is only one.
|
100
|
-
#
|
101
|
-
def pick_pgp_key
|
102
|
-
begin
|
103
|
-
require 'gpgme'
|
104
|
-
rescue LoadError
|
105
|
-
log "Skipping OpenPGP setup because gpgme is not installed."
|
106
|
-
return
|
107
|
-
end
|
108
|
-
|
109
|
-
secret_keys = GPGME::Key.find(:secret)
|
110
|
-
if secret_keys.empty?
|
111
|
-
log "Skipping OpenPGP setup because I could not find any OpenPGP keys for you"
|
112
|
-
return nil
|
113
|
-
end
|
114
|
-
|
115
|
-
secret_keys.select!{|key| !key.expired}
|
116
|
-
|
117
|
-
if secret_keys.length > 1
|
118
|
-
key_index = numbered_choice_menu('Choose your OpenPGP public key', secret_keys) do |key, i|
|
119
|
-
key_info = key.to_s.split("\n")[0..1].map{|line| line.sub(/^\s*(sec|uid)\s*/,'')}.join(' -- ')
|
120
|
-
say("#{i+1}. #{key_info}")
|
121
|
-
end
|
122
|
-
else
|
123
|
-
key_index = 0
|
124
|
-
end
|
125
|
-
|
126
|
-
key_id = secret_keys[key_index].sha
|
127
|
-
|
128
|
-
# can't use this, it includes signatures:
|
129
|
-
#puts GPGME::Key.export(key_id, :armor => true, :export_options => :export_minimal)
|
130
|
-
|
131
|
-
# export with signatures removed:
|
132
|
-
return `gpg --armor --export-options export-minimal --export #{key_id}`.strip
|
133
|
-
end
|
134
|
-
|
135
|
-
end
|
136
|
-
end
|
@@ -1,50 +0,0 @@
|
|
1
|
-
module LeapCli; module Commands
|
2
|
-
|
3
|
-
extend self
|
4
|
-
extend LeapCli::Util
|
5
|
-
extend LeapCli::Util::RemoteCommand
|
6
|
-
|
7
|
-
def path(name)
|
8
|
-
Path.named_path(name)
|
9
|
-
end
|
10
|
-
|
11
|
-
#
|
12
|
-
# keeps prompting the user for a numbered choice, until they pick a good one or bail out.
|
13
|
-
#
|
14
|
-
# block is yielded and is responsible for rendering the choices.
|
15
|
-
#
|
16
|
-
def numbered_choice_menu(msg, items, &block)
|
17
|
-
while true
|
18
|
-
say("\n" + msg + ':')
|
19
|
-
items.each_with_index &block
|
20
|
-
say("q. quit")
|
21
|
-
index = ask("number 1-#{items.length}> ")
|
22
|
-
if index.empty?
|
23
|
-
next
|
24
|
-
elsif index =~ /q/
|
25
|
-
bail!
|
26
|
-
else
|
27
|
-
i = index.to_i - 1
|
28
|
-
if i < 0 || i >= items.length
|
29
|
-
bail!
|
30
|
-
else
|
31
|
-
return i
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
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
|
-
end; end
|
@@ -1,197 +0,0 @@
|
|
1
|
-
autoload :IPAddr, 'ipaddr'
|
2
|
-
require 'fileutils'
|
3
|
-
|
4
|
-
module LeapCli; module Commands
|
5
|
-
|
6
|
-
desc "Manage local virtual machines."
|
7
|
-
long_desc "This command provides a convient way to manage Vagrant-based virtual machines. If FILTER argument is missing, the command runs on all local virtual machines. The Vagrantfile is automatically generated in 'test/Vagrantfile'. If you want to run vagrant commands manually, cd to 'test'."
|
8
|
-
command [:local, :l] do |local|
|
9
|
-
local.desc 'Starts up the virtual machine(s)'
|
10
|
-
local.arg_name 'FILTER', :optional => true #, :multiple => false
|
11
|
-
local.command :start do |start|
|
12
|
-
start.flag(:basebox,
|
13
|
-
:desc => "The basebox to use. This value is passed to vagrant as the "+
|
14
|
-
"`config.vm.box` option. The value here should be the name of an installed box or a "+
|
15
|
-
"shorthand name of a box in HashiCorp's Atlas.",
|
16
|
-
:arg_name => 'BASEBOX',
|
17
|
-
:default_value => 'LEAP/wheezy'
|
18
|
-
)
|
19
|
-
start.action do |global_options,options,args|
|
20
|
-
vagrant_command(["up", "sandbox on"], args, options)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
local.desc 'Shuts down the virtual machine(s)'
|
25
|
-
local.arg_name 'FILTER', :optional => true #, :multiple => false
|
26
|
-
local.command :stop do |stop|
|
27
|
-
stop.action do |global_options,options,args|
|
28
|
-
if global_options[:yes]
|
29
|
-
vagrant_command("halt --force", args)
|
30
|
-
else
|
31
|
-
vagrant_command("halt", args)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
local.desc 'Destroys the virtual machine(s), reclaiming the disk space'
|
37
|
-
local.arg_name 'FILTER', :optional => true #, :multiple => false
|
38
|
-
local.command :destroy do |destroy|
|
39
|
-
destroy.action do |global_options,options,args|
|
40
|
-
if global_options[:yes]
|
41
|
-
vagrant_command("destroy --force", args)
|
42
|
-
else
|
43
|
-
vagrant_command("destroy", args)
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
local.desc 'Print the status of local virtual machine(s)'
|
49
|
-
local.arg_name 'FILTER', :optional => true #, :multiple => false
|
50
|
-
local.command :status do |status|
|
51
|
-
status.action do |global_options,options,args|
|
52
|
-
vagrant_command("status", args)
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
local.desc 'Saves the current state of the virtual machine as a new snapshot'
|
57
|
-
local.arg_name 'FILTER', :optional => true #, :multiple => false
|
58
|
-
local.command :save do |status|
|
59
|
-
status.action do |global_options,options,args|
|
60
|
-
vagrant_command("sandbox commit", args)
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
local.desc 'Resets virtual machine(s) to the last saved snapshot'
|
65
|
-
local.arg_name 'FILTER', :optional => true #, :multiple => false
|
66
|
-
local.command :reset do |reset|
|
67
|
-
reset.action do |global_options,options,args|
|
68
|
-
vagrant_command("sandbox rollback", args)
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
public
|
74
|
-
|
75
|
-
#
|
76
|
-
# returns the path to a vagrant ssh key file.
|
77
|
-
#
|
78
|
-
# if the vagrant.key file is owned by root or ourselves, then
|
79
|
-
# we need to make sure that it owned by us and not world readable.
|
80
|
-
#
|
81
|
-
def vagrant_ssh_key_file
|
82
|
-
file_path = File.expand_path('../../../vendor/vagrant_ssh_keys/vagrant.key', File.dirname(__FILE__))
|
83
|
-
Util.assert_files_exist! file_path
|
84
|
-
uid = File.new(file_path).stat.uid
|
85
|
-
if uid == 0 || uid == Process.euid
|
86
|
-
FileUtils.install file_path, '/tmp/vagrant.key', :mode => 0600
|
87
|
-
file_path = '/tmp/vagrant.key'
|
88
|
-
end
|
89
|
-
return file_path
|
90
|
-
end
|
91
|
-
|
92
|
-
protected
|
93
|
-
|
94
|
-
def vagrant_command(cmds, args, options={})
|
95
|
-
vagrant_setup(options)
|
96
|
-
cmds = cmds.to_a
|
97
|
-
if args.empty?
|
98
|
-
nodes = [""]
|
99
|
-
else
|
100
|
-
nodes = manager.filter(args)[:environment => "local"].field(:name)
|
101
|
-
end
|
102
|
-
if nodes.any?
|
103
|
-
vagrant_dir = File.dirname(Path.named_path(:vagrantfile))
|
104
|
-
exec = ["cd #{vagrant_dir}"]
|
105
|
-
cmds.each do |cmd|
|
106
|
-
nodes.each do |node|
|
107
|
-
exec << "vagrant #{cmd} #{node}"
|
108
|
-
end
|
109
|
-
end
|
110
|
-
execute exec.join('; ')
|
111
|
-
else
|
112
|
-
bail! "No nodes found. This command only works on nodes with ip_address in the network #{LeapCli.leapfile.vagrant_network}"
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
private
|
117
|
-
|
118
|
-
def vagrant_setup(options)
|
119
|
-
assert_bin! 'vagrant', 'Vagrant is required for running local virtual machines. Run "sudo apt-get install vagrant".'
|
120
|
-
|
121
|
-
if vagrant_version <= Gem::Version.new('1.0.0')
|
122
|
-
gem_path = assert_run!('vagrant gem which sahara')
|
123
|
-
if gem_path.nil? || gem_path.empty? || gem_path =~ /^ERROR/
|
124
|
-
log :installing, "vagrant plugin 'sahara'"
|
125
|
-
assert_run! 'vagrant gem install sahara -v 0.0.13'
|
126
|
-
end
|
127
|
-
else
|
128
|
-
unless assert_run!('vagrant plugin list | grep sahara | cat').chars.any?
|
129
|
-
log :installing, "vagrant plugin 'sahara'"
|
130
|
-
assert_run! 'vagrant plugin install sahara'
|
131
|
-
end
|
132
|
-
end
|
133
|
-
create_vagrant_file(options)
|
134
|
-
end
|
135
|
-
|
136
|
-
def vagrant_version
|
137
|
-
@vagrant_version ||= Gem::Version.new(assert_run!('vagrant --version').split(' ')[1])
|
138
|
-
end
|
139
|
-
|
140
|
-
def execute(cmd)
|
141
|
-
log 2, :run, cmd
|
142
|
-
exec cmd
|
143
|
-
end
|
144
|
-
|
145
|
-
def create_vagrant_file(options)
|
146
|
-
lines = []
|
147
|
-
netmask = IPAddr.new('255.255.255.255').mask(LeapCli.leapfile.vagrant_network.split('/').last).to_s
|
148
|
-
|
149
|
-
basebox = options[:basebox] || 'LEAP/wheezy'
|
150
|
-
|
151
|
-
if vagrant_version <= Gem::Version.new('1.1.0')
|
152
|
-
lines << %[Vagrant::Config.run do |config|]
|
153
|
-
manager.each_node do |node|
|
154
|
-
if node.vagrant?
|
155
|
-
lines << %[ config.vm.define :#{node.name} do |config|]
|
156
|
-
lines << %[ config.vm.box = "#{basebox}"]
|
157
|
-
lines << %[ config.vm.network :hostonly, "#{node.ip_address}", :netmask => "#{netmask}"]
|
158
|
-
lines << %[ config.vm.customize ["modifyvm", :id, "--natdnshostresolver1", "on"]]
|
159
|
-
lines << %[ config.vm.customize ["modifyvm", :id, "--name", "#{node.name}"]]
|
160
|
-
lines << %[ #{leapfile.custom_vagrant_vm_line}] if leapfile.custom_vagrant_vm_line
|
161
|
-
lines << %[ end]
|
162
|
-
end
|
163
|
-
end
|
164
|
-
else
|
165
|
-
lines << %[Vagrant.configure("2") do |config|]
|
166
|
-
manager.each_node do |node|
|
167
|
-
if node.vagrant?
|
168
|
-
lines << %[ config.vm.define :#{node.name} do |config|]
|
169
|
-
lines << %[ config.vm.box = "#{basebox}"]
|
170
|
-
lines << %[ config.vm.network :private_network, ip: "#{node.ip_address}"]
|
171
|
-
lines << %[ config.vm.provider "virtualbox" do |v|]
|
172
|
-
lines << %[ v.customize ["modifyvm", :id, "--natdnshostresolver1", "on"]]
|
173
|
-
lines << %[ v.name = "#{node.name}"]
|
174
|
-
lines << %[ end]
|
175
|
-
lines << %[ #{leapfile.custom_vagrant_vm_line}] if leapfile.custom_vagrant_vm_line
|
176
|
-
lines << %[ end]
|
177
|
-
end
|
178
|
-
end
|
179
|
-
end
|
180
|
-
|
181
|
-
lines << %[end]
|
182
|
-
lines << ""
|
183
|
-
write_file! :vagrantfile, lines.join("\n")
|
184
|
-
end
|
185
|
-
|
186
|
-
def pick_next_vagrant_ip_address
|
187
|
-
taken_ips = manager.nodes[:environment => "local"].field(:ip_address)
|
188
|
-
if taken_ips.any?
|
189
|
-
highest_ip = taken_ips.map{|ip| IPAddr.new(ip)}.max
|
190
|
-
new_ip = highest_ip.succ
|
191
|
-
else
|
192
|
-
new_ip = IPAddr.new(LeapCli.leapfile.vagrant_network).succ.succ
|
193
|
-
end
|
194
|
-
return new_ip.to_s
|
195
|
-
end
|
196
|
-
|
197
|
-
end; end
|