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,76 +0,0 @@
1
- module LeapCli
2
- module Commands
3
-
4
- desc "Manipulate and query environment information."
5
- long_desc "The 'environment' node property can be used to isolate sets of nodes into entirely separate environments. "+
6
- "A node in one environment will never interact with a node from another environment. "+
7
- "Environment pinning works by modifying your ~/.leaprc file and is dependent on the "+
8
- "absolute file path of your provider directory (pins don't apply if you move the directory)"
9
- command [:env, :e] do |c|
10
- c.desc "List the available environments. The pinned environment, if any, will be marked with '*'. Will also set the pin if run with an environment argument."
11
- c.arg_name 'ENVIRONMENT', :optional => true
12
- c.command :ls do |ls|
13
- ls.action do |global_options, options, args|
14
- environment = get_env_from_args(args)
15
- if environment
16
- pin(environment)
17
- LeapCli.leapfile.load
18
- end
19
- print_envs
20
- end
21
- end
22
-
23
- c.desc 'Pin the environment to ENVIRONMENT. All subsequent commands will only apply to nodes in this environment.'
24
- c.arg_name 'ENVIRONMENT'
25
- c.command :pin do |pin|
26
- pin.action do |global_options,options,args|
27
- environment = get_env_from_args(args)
28
- if environment
29
- pin(environment)
30
- else
31
- bail! "There is no environment `#{environment}`"
32
- end
33
- end
34
- end
35
-
36
- c.desc "Unpin the environment. All subsequent commands will apply to all nodes."
37
- c.command :unpin do |unpin|
38
- unpin.action do |global_options, options, args|
39
- LeapCli.leapfile.unset('environment')
40
- log 0, :saved, "~/.leaprc, removing environment property."
41
- end
42
- end
43
-
44
- c.default_command :ls
45
- end
46
-
47
- protected
48
-
49
- def get_env_from_args(args)
50
- environment = args.first
51
- if environment == 'default' || (environment && manager.environment_names.include?(environment))
52
- return environment
53
- else
54
- return nil
55
- end
56
- end
57
-
58
- def pin(environment)
59
- LeapCli.leapfile.set('environment', environment)
60
- log 0, :saved, "~/.leaprc with environment set to #{environment}."
61
- end
62
-
63
- def print_envs
64
- envs = ["default"] + manager.environment_names.compact.sort
65
- envs.each do |env|
66
- if env
67
- if LeapCli.leapfile.environment == env
68
- puts "* #{env}"
69
- else
70
- puts " #{env}"
71
- end
72
- end
73
- end
74
- end
75
- end
76
- end
@@ -1,100 +0,0 @@
1
- #
2
- # Gather facter facts
3
- #
4
-
5
- module LeapCli; module Commands
6
-
7
- desc 'Gather information on nodes.'
8
- command :facts do |facts|
9
- facts.desc 'Query servers to update facts.json.'
10
- facts.long_desc "Queries every node included in FILTER and saves the important information to facts.json"
11
- facts.arg_name 'FILTER'
12
- facts.command :update do |update|
13
- update.action do |global_options,options,args|
14
- update_facts(global_options, options, args)
15
- end
16
- end
17
- end
18
-
19
- protected
20
-
21
- def facter_cmd
22
- 'facter --json ' + Leap::Platform.facts.join(' ')
23
- end
24
-
25
- def remove_node_facts(name)
26
- if file_exists?(:facts)
27
- update_facts_file({name => nil})
28
- end
29
- end
30
-
31
- def update_node_facts(name, facts)
32
- update_facts_file({name => facts})
33
- end
34
-
35
- def rename_node_facts(old_name, new_name)
36
- if file_exists?(:facts)
37
- facts = JSON.parse(read_file(:facts) || {})
38
- facts[new_name] = facts[old_name]
39
- facts[old_name] = nil
40
- update_facts_file(facts, true)
41
- end
42
- end
43
-
44
- #
45
- # if overwrite = true, then ignore existing facts.json.
46
- #
47
- def update_facts_file(new_facts, overwrite=false)
48
- replace_file!(:facts) do |content|
49
- if overwrite || content.nil? || content.empty?
50
- old_facts = {}
51
- else
52
- old_facts = manager.facts
53
- end
54
- facts = old_facts.merge(new_facts)
55
- facts.each do |name, value|
56
- if value.is_a? String
57
- if value == ""
58
- value = nil
59
- else
60
- value = JSON.parse(value) rescue JSON::ParserError
61
- end
62
- end
63
- if value.is_a? Hash
64
- value.delete_if {|key,v| v.nil?}
65
- end
66
- facts[name] = value
67
- end
68
- facts.delete_if do |name, value|
69
- value.nil? || value.empty?
70
- end
71
- if facts.empty?
72
- "{}\n"
73
- else
74
- JSON.sorted_generate(facts) + "\n"
75
- end
76
- end
77
- end
78
-
79
- private
80
-
81
- def update_facts(global_options, options, args)
82
- nodes = manager.filter(args, :local => false, :disabled => false)
83
- new_facts = {}
84
- ssh_connect(nodes) do |ssh|
85
- ssh.leap.run_with_progress(facter_cmd) do |response|
86
- node = manager.node(response[:host])
87
- if node
88
- new_facts[node.name] = response[:data].strip
89
- else
90
- log :warning, 'Could not find node for hostname %s' % response[:host]
91
- end
92
- end
93
- end
94
- # only overwrite the entire facts file if and only if we are gathering facts
95
- # for all nodes in all environments.
96
- overwrite_existing = args.empty? && LeapCli.leapfile.environment.nil?
97
- update_facts_file(new_facts, overwrite_existing)
98
- end
99
-
100
- end; end
@@ -1,144 +0,0 @@
1
- module LeapCli; module Commands
2
-
3
- desc 'Prints details about a file. Alternately, the argument FILE can be the name of a node, service or tag.'
4
- arg_name 'FILE'
5
- command [:inspect, :i] do |c|
6
- c.switch 'base', :desc => 'Inspect the FILE from the provider_base (i.e. without local inheritance).', :negatable => false
7
- c.action do |global_options,options,args|
8
- object = args.first
9
- assert! object, 'A file path or node/service/tag name is required'
10
- method = inspection_method(object)
11
- if method && defined?(method)
12
- self.send(method, object, options)
13
- else
14
- log "Sorry, I don't know how to inspect that."
15
- end
16
- end
17
- end
18
-
19
- private
20
-
21
- FTYPE_MAP = {
22
- "PEM certificate" => :inspect_x509_cert,
23
- "PEM RSA private key" => :inspect_x509_key,
24
- "OpenSSH RSA public key" => :inspect_ssh_pub_key,
25
- "PEM certificate request" => :inspect_x509_csr
26
- }
27
-
28
- def inspection_method(object)
29
- if File.exists?(object)
30
- ftype = `file #{object}`.split(':').last.strip
31
- log 2, "file is of type '#{ftype}'"
32
- if FTYPE_MAP[ftype]
33
- FTYPE_MAP[ftype]
34
- elsif File.extname(object) == ".json"
35
- full_path = File.expand_path(object, Dir.pwd)
36
- if path_match?(:node_config, full_path)
37
- :inspect_node
38
- elsif path_match?(:service_config, full_path)
39
- :inspect_service
40
- elsif path_match?(:tag_config, full_path)
41
- :inspect_tag
42
- elsif path_match?(:provider_config, full_path) || path_match?(:provider_env_config, full_path)
43
- :inspect_provider
44
- elsif path_match?(:common_config, full_path)
45
- :inspect_common
46
- else
47
- nil
48
- end
49
- end
50
- elsif manager.nodes[object]
51
- :inspect_node
52
- elsif manager.services[object]
53
- :inspect_service
54
- elsif manager.tags[object]
55
- :inspect_tag
56
- elsif object == "common"
57
- :inspect_common
58
- elsif object == "provider"
59
- :inspect_provider
60
- else
61
- nil
62
- end
63
- end
64
-
65
- #
66
- # inspectors
67
- #
68
-
69
- def inspect_x509_key(file_path, options)
70
- assert_bin! 'openssl'
71
- puts assert_run! 'openssl rsa -in %s -text -check' % file_path
72
- end
73
-
74
- def inspect_x509_cert(file_path, options)
75
- assert_bin! 'openssl'
76
- puts assert_run! 'openssl x509 -in %s -text -noout' % file_path
77
- log 0, :"SHA256 fingerprint", X509.fingerprint("SHA256", file_path)
78
- end
79
-
80
- def inspect_x509_csr(file_path, options)
81
- assert_bin! 'openssl'
82
- puts assert_run! 'openssl req -text -noout -verify -in %s' % file_path
83
- end
84
-
85
- #def inspect_ssh_pub_key(file_path)
86
- #end
87
-
88
- def inspect_node(arg, options)
89
- inspect_json manager.nodes[name(arg)]
90
- end
91
-
92
- def inspect_service(arg, options)
93
- if options[:base]
94
- inspect_json manager.base_services[name(arg)]
95
- else
96
- inspect_json manager.services[name(arg)]
97
- end
98
- end
99
-
100
- def inspect_tag(arg, options)
101
- if options[:base]
102
- inspect_json manager.base_tags[name(arg)]
103
- else
104
- inspect_json manager.tags[name(arg)]
105
- end
106
- end
107
-
108
- def inspect_provider(arg, options)
109
- if options[:base]
110
- inspect_json manager.base_provider
111
- elsif arg =~ /provider\.(.*)\.json/
112
- inspect_json manager.env($1).provider
113
- else
114
- inspect_json manager.provider
115
- end
116
- end
117
-
118
- def inspect_common(arg, options)
119
- if options[:base]
120
- inspect_json manager.base_common
121
- else
122
- inspect_json manager.common
123
- end
124
- end
125
-
126
- #
127
- # helpers
128
- #
129
-
130
- def name(arg)
131
- File.basename(arg).sub(/\.json$/, '')
132
- end
133
-
134
- def inspect_json(config)
135
- if config
136
- puts JSON.sorted_generate(config)
137
- end
138
- end
139
-
140
- def path_match?(path_symbol, path)
141
- Dir.glob(Path.named_path([path_symbol, '*'])).include?(path)
142
- end
143
-
144
- end; end
@@ -1,132 +0,0 @@
1
- require 'command_line_reporter'
2
-
3
- module LeapCli; module Commands
4
-
5
- desc 'List nodes and their classifications'
6
- long_desc 'Prints out a listing of nodes, services, or tags. ' +
7
- 'If present, the FILTER can be a list of names of nodes, services, or tags. ' +
8
- 'If the name is prefixed with +, this acts like an AND condition. ' +
9
- "For example:\n\n" +
10
- "`leap list node1 node2` matches all nodes named \"node1\" OR \"node2\"\n\n" +
11
- "`leap list openvpn +local` matches all nodes with service \"openvpn\" AND tag \"local\""
12
-
13
- arg_name 'FILTER', :optional => true
14
- command [:list,:ls] do |c|
15
- c.flag 'print', :desc => 'What attributes to print (optional)'
16
- c.switch 'disabled', :desc => 'Include disabled nodes in the list.', :negatable => false
17
- c.action do |global_options,options,args|
18
- # don't rely on default manager(), because we want to pass custom options to load()
19
- manager = LeapCli::Config::Manager.new
20
- if global_options[:color]
21
- colors = ['cyan', 'white']
22
- else
23
- colors = [nil, nil]
24
- end
25
- puts
26
- manager.load(:include_disabled => options['disabled'], :continue_on_error => true)
27
- if options['print']
28
- print_node_properties(manager.filter(args), options['print'])
29
- else
30
- if args.any?
31
- NodeTable.new(manager.filter(args), colors).run
32
- else
33
- environment = LeapCli.leapfile.environment || '_all_'
34
- TagTable.new('SERVICES', manager.env(environment).services, colors).run
35
- TagTable.new('TAGS', manager.env(environment).tags, colors).run
36
- NodeTable.new(manager.filter(), colors).run
37
- end
38
- end
39
- end
40
- end
41
-
42
- private
43
-
44
- def self.print_node_properties(nodes, properties)
45
- properties = properties.split(',')
46
- max_width = nodes.keys.inject(0) {|max,i| [i.size,max].max}
47
- nodes.each_node do |node|
48
- value = properties.collect{|prop|
49
- prop_value = node[prop]
50
- if prop_value.nil?
51
- "null"
52
- elsif prop_value == ""
53
- "empty"
54
- elsif prop_value.is_a? LeapCli::Config::Object
55
- node[prop].dump_json(:compact) # TODO: add option of getting pre-evaluation values.
56
- else
57
- prop_value.to_s
58
- end
59
- }.join(', ')
60
- printf("%#{max_width}s %s\n", node.name, value)
61
- end
62
- puts
63
- end
64
-
65
- class TagTable
66
- include CommandLineReporter
67
- def initialize(heading, tag_list, colors)
68
- @heading = heading
69
- @tag_list = tag_list
70
- @colors = colors
71
- end
72
- def run
73
- tags = @tag_list.keys.select{|tag| tag !~ /^_/}.sort # sorted list of tags, excluding _partials
74
- max_width = [20, (tags+[@heading]).inject(0) {|max,i| [i.size,max].max}].max
75
- table :border => false do
76
- row :color => @colors[0] do
77
- column @heading, :align => 'right', :width => max_width
78
- column "NODES", :width => HighLine::SystemExtensions.terminal_size.first - max_width - 2, :padding => 2
79
- end
80
- tags.each do |tag|
81
- next if @tag_list[tag].node_list.empty?
82
- row :color => @colors[1] do
83
- column tag
84
- column @tag_list[tag].node_list.keys.sort.join(', ')
85
- end
86
- end
87
- end
88
- vertical_spacing
89
- end
90
- end
91
-
92
- #
93
- # might be handy: HighLine::SystemExtensions.terminal_size.first
94
- #
95
- class NodeTable
96
- include CommandLineReporter
97
- def initialize(node_list, colors)
98
- @node_list = node_list
99
- @colors = colors
100
- end
101
- def run
102
- rows = @node_list.keys.sort.collect do |node_name|
103
- [node_name, @node_list[node_name].services.sort.join(', '), @node_list[node_name].tags.sort.join(', ')]
104
- end
105
- unless rows.any?
106
- puts Paint["no results", :red]
107
- puts
108
- return
109
- end
110
- padding = 2
111
- max_node_width = [20, (rows.map{|i|i[0]} + ["NODES"] ).inject(0) {|max,i| [i.size,max].max}].max
112
- max_service_width = (rows.map{|i|i[1]} + ["SERVICES"]).inject(0) {|max,i| [i.size+padding+padding,max].max}
113
- max_tag_width = (rows.map{|i|i[2]} + ["TAGS"] ).inject(0) {|max,i| [i.size,max].max}
114
- table :border => false do
115
- row :color => @colors[0] do
116
- column "NODES", :align => 'right', :width => max_node_width
117
- column "SERVICES", :width => max_service_width, :padding => 2
118
- column "TAGS", :width => max_tag_width
119
- end
120
- rows.each do |r|
121
- row :color => @colors[1] do
122
- column r[0]
123
- column r[1]
124
- column r[2]
125
- end
126
- end
127
- end
128
- vertical_spacing
129
- end
130
- end
131
-
132
- end; end