leap_cli 1.7.4 → 1.8

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.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/bin/leap +6 -13
  3. data/lib/leap/platform.rb +2 -0
  4. data/lib/leap_cli.rb +2 -1
  5. data/lib/leap_cli/bootstrap.rb +197 -0
  6. data/lib/leap_cli/commands/common.rb +61 -0
  7. data/lib/leap_cli/commands/new.rb +5 -1
  8. data/lib/leap_cli/commands/pre.rb +1 -66
  9. data/lib/leap_cli/config/environment.rb +180 -0
  10. data/lib/leap_cli/config/manager.rb +100 -197
  11. data/lib/leap_cli/config/node.rb +2 -2
  12. data/lib/leap_cli/config/object.rb +56 -43
  13. data/lib/leap_cli/config/object_list.rb +6 -3
  14. data/lib/leap_cli/config/provider.rb +11 -0
  15. data/lib/leap_cli/config/secrets.rb +14 -1
  16. data/lib/leap_cli/config/tag.rb +2 -2
  17. data/lib/leap_cli/leapfile.rb +1 -0
  18. data/lib/leap_cli/log.rb +1 -0
  19. data/lib/leap_cli/logger.rb +16 -12
  20. data/lib/leap_cli/markdown_document_listener.rb +3 -1
  21. data/lib/leap_cli/path.rb +12 -0
  22. data/lib/leap_cli/remote/leap_plugin.rb +9 -34
  23. data/lib/leap_cli/remote/puppet_plugin.rb +0 -40
  24. data/lib/leap_cli/remote/tasks.rb +9 -34
  25. data/lib/leap_cli/ssh_key.rb +5 -2
  26. data/lib/leap_cli/version.rb +2 -2
  27. metadata +5 -18
  28. data/lib/leap_cli/commands/ca.rb +0 -518
  29. data/lib/leap_cli/commands/clean.rb +0 -16
  30. data/lib/leap_cli/commands/compile.rb +0 -340
  31. data/lib/leap_cli/commands/db.rb +0 -65
  32. data/lib/leap_cli/commands/deploy.rb +0 -368
  33. data/lib/leap_cli/commands/env.rb +0 -76
  34. data/lib/leap_cli/commands/facts.rb +0 -100
  35. data/lib/leap_cli/commands/inspect.rb +0 -144
  36. data/lib/leap_cli/commands/list.rb +0 -132
  37. data/lib/leap_cli/commands/node.rb +0 -165
  38. data/lib/leap_cli/commands/node_init.rb +0 -169
  39. data/lib/leap_cli/commands/ssh.rb +0 -220
  40. data/lib/leap_cli/commands/test.rb +0 -74
  41. data/lib/leap_cli/commands/user.rb +0 -136
  42. data/lib/leap_cli/commands/util.rb +0 -50
  43. 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