moose-inventory 0.1.0

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 (74) hide show
  1. checksums.yaml +7 -0
  2. data/.coveralls.yml +0 -0
  3. data/.gitignore +17 -0
  4. data/.rubocop.yml +793 -0
  5. data/Gemfile +3 -0
  6. data/Guardfile +38 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +31 -0
  9. data/README.md.orig +35 -0
  10. data/Rakefile +1 -0
  11. data/bin/moose_inventory +10 -0
  12. data/config/dotfiles/coveralls.yml +0 -0
  13. data/config/dotfiles/gitignore +17 -0
  14. data/config/dotfiles/rubocop.yml +793 -0
  15. data/lib/moose/inventory/cli/application.rb +30 -0
  16. data/lib/moose/inventory/cli/formatter.rb +92 -0
  17. data/lib/moose/inventory/cli/group.rb +23 -0
  18. data/lib/moose/inventory/cli/group_add.rb +98 -0
  19. data/lib/moose/inventory/cli/group_addchild.rb +21 -0
  20. data/lib/moose/inventory/cli/group_addhost.rb +97 -0
  21. data/lib/moose/inventory/cli/group_addvar.rb +72 -0
  22. data/lib/moose/inventory/cli/group_get.rb +52 -0
  23. data/lib/moose/inventory/cli/group_list.rb +41 -0
  24. data/lib/moose/inventory/cli/group_rm.rb +77 -0
  25. data/lib/moose/inventory/cli/group_rmchild.rb +20 -0
  26. data/lib/moose/inventory/cli/group_rmhost.rb +89 -0
  27. data/lib/moose/inventory/cli/group_rmvar.rb +65 -0
  28. data/lib/moose/inventory/cli/host.rb +24 -0
  29. data/lib/moose/inventory/cli/host_add.rb +93 -0
  30. data/lib/moose/inventory/cli/host_addgroup.rb +88 -0
  31. data/lib/moose/inventory/cli/host_addvar.rb +76 -0
  32. data/lib/moose/inventory/cli/host_get.rb +59 -0
  33. data/lib/moose/inventory/cli/host_list.rb +40 -0
  34. data/lib/moose/inventory/cli/host_rm.rb +62 -0
  35. data/lib/moose/inventory/cli/host_rmgroup.rb +80 -0
  36. data/lib/moose/inventory/cli/host_rmvar.rb +69 -0
  37. data/lib/moose/inventory/config/config.rb +169 -0
  38. data/lib/moose/inventory/db/db.rb +249 -0
  39. data/lib/moose/inventory/db/exceptions.rb +14 -0
  40. data/lib/moose/inventory/db/models.rb +32 -0
  41. data/lib/moose/inventory/moose_inventory_cli.rb +25 -0
  42. data/lib/moose/inventory/version.rb +7 -0
  43. data/moose-inventory.gemspec +45 -0
  44. data/scripts/guard_quality.sh +3 -0
  45. data/scripts/guard_test.sh +2 -0
  46. data/scripts/reports.sh +4 -0
  47. data/spec/config/config.yml +12 -0
  48. data/spec/lib/moose/inventory/cli/application_spec.rb +15 -0
  49. data/spec/lib/moose/inventory/cli/cli_spec.rb +26 -0
  50. data/spec/lib/moose/inventory/cli/formatter_spec.rb +63 -0
  51. data/spec/lib/moose/inventory/cli/group_add_spec.rb +398 -0
  52. data/spec/lib/moose/inventory/cli/group_addhost_spec.rb +251 -0
  53. data/spec/lib/moose/inventory/cli/group_addvar_spec.rb +235 -0
  54. data/spec/lib/moose/inventory/cli/group_get_spec.rb +107 -0
  55. data/spec/lib/moose/inventory/cli/group_list_spec.rb +79 -0
  56. data/spec/lib/moose/inventory/cli/group_rm_spec.rb +191 -0
  57. data/spec/lib/moose/inventory/cli/group_rmhost_spec.rb +215 -0
  58. data/spec/lib/moose/inventory/cli/group_rmvar_spec.rb +202 -0
  59. data/spec/lib/moose/inventory/cli/group_spec.rb +15 -0
  60. data/spec/lib/moose/inventory/cli/host_add_spec.rb +330 -0
  61. data/spec/lib/moose/inventory/cli/host_addgroup_spec.rb +248 -0
  62. data/spec/lib/moose/inventory/cli/host_addvar_spec.rb +233 -0
  63. data/spec/lib/moose/inventory/cli/host_get_spec.rb +106 -0
  64. data/spec/lib/moose/inventory/cli/host_list_spec.rb +83 -0
  65. data/spec/lib/moose/inventory/cli/host_rm_spec.rb +132 -0
  66. data/spec/lib/moose/inventory/cli/host_rmgroup_spec.rb +245 -0
  67. data/spec/lib/moose/inventory/cli/host_rmvar_spec.rb +206 -0
  68. data/spec/lib/moose/inventory/cli/host_spec.rb +12 -0
  69. data/spec/lib/moose/inventory/config/config_spec.rb +80 -0
  70. data/spec/lib/moose/inventory/db/db_spec.rb +184 -0
  71. data/spec/lib/moose/inventory/db/models_spec.rb +150 -0
  72. data/spec/shared/shared_config_setup.rb +21 -0
  73. data/spec/spec_helper.rb +110 -0
  74. metadata +386 -0
@@ -0,0 +1,30 @@
1
+ require 'thor'
2
+ require_relative '../version.rb'
3
+ require_relative '../config/config.rb'
4
+ require_relative './group.rb'
5
+ require_relative './host.rb'
6
+
7
+ module Moose
8
+ module Inventory
9
+ module Cli
10
+ ##
11
+ # TODO: Documentation
12
+ class Application < Thor
13
+ desc 'version', 'Get the code version'
14
+ def version
15
+ puts "Version #{Moose::Inventory::VERSION}"
16
+ end
17
+
18
+ desc 'group ACTION',
19
+ 'Manipulate groups in the inventory. ' \
20
+ 'ACTION can be add, rm, addhost, rmhost, addvar, rmvar'
21
+ subcommand 'group', Moose::Inventory::Cli::Group
22
+
23
+ desc 'host ACTION',
24
+ 'Manipulate hosts in the inventory. ' \
25
+ 'ACTION can be add, rm, addgroup, rmgroup, addvar, rmvar'
26
+ subcommand 'host', Moose::Inventory::Cli::Host
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,92 @@
1
+ require 'json'
2
+ require 'yaml'
3
+ require 'indentation'
4
+
5
+ module Moose
6
+ module Inventory
7
+ module Cli
8
+ ##
9
+ # TODO: Documentation
10
+ module Formatter
11
+ # rubocop:disable Style/ModuleFunction
12
+ extend self
13
+ # rubocop:enable Style/ModuleFunction
14
+
15
+ def self.dump(arg, format = nil)
16
+ out(arg, format)
17
+ end
18
+
19
+ def self.out(arg, format = nil)
20
+ return if arg.nil?
21
+
22
+ if format.nil?
23
+ format = Moose::Inventory::Config._confopts[:format].downcase
24
+ end
25
+
26
+ case format
27
+ when 'yaml','y'
28
+ $stdout.puts arg.to_yaml
29
+
30
+ when 'prettyjson','pjson','p'
31
+ $stdout.puts JSON.pretty_generate(arg)
32
+
33
+ when 'json','j'
34
+ $stdout.puts arg.to_json
35
+
36
+ else
37
+ abort("Output format '#{format}' is not yet supported.")
38
+ end
39
+ end
40
+
41
+ #---------------
42
+ attr_accessor :indent
43
+
44
+ def reset_indent
45
+ @indent = 2
46
+ end
47
+
48
+ def puts(indent, msg, stream='STDOUT')
49
+ case stream
50
+ when 'STDOUT'
51
+ $stdout.puts msg.indent(indent)
52
+ when 'STDERR'
53
+ $stderr.puts msg.indent(indent)
54
+ else
55
+ abort("Output stream '#{stream}' is not known.")
56
+ end
57
+ end
58
+
59
+ def print(indent, msg, stream='STDOUT')
60
+ case stream
61
+ when 'STDOUT'
62
+ $stdout.print msg.indent(indent)
63
+ when 'STDERR'
64
+ $stderr.print msg.indent(indent)
65
+ else
66
+ abort("Output stream '#{stream}' is not known.")
67
+ end
68
+ end
69
+
70
+ def info(indent, msg, stream='STDOUT')
71
+ case stream
72
+ when 'STDOUT'
73
+ $stdout.print "INFO: {msg}"
74
+ when 'STDERR'
75
+ $stderr.print "INFO: {msg}"
76
+ else
77
+ abort("Output stream '#{stream}' is not known.")
78
+ end
79
+ end
80
+
81
+ def warn(msg)
82
+ $stderr.print "WARNING: #{msg}"
83
+ end
84
+
85
+ def error(msg)
86
+ $stderr.print "ERROR: #{msg}"
87
+ end
88
+
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,23 @@
1
+ require 'thor'
2
+ require_relative './formatter.rb'
3
+
4
+ module Moose
5
+ module Inventory
6
+ module Cli
7
+ ##
8
+ # Class implementing the "group" methods of the CLI
9
+ class Group < Thor
10
+ require_relative 'group_add'
11
+ require_relative 'group_get'
12
+ require_relative 'group_list'
13
+ require_relative 'group_rm'
14
+ require_relative 'group_addchild'
15
+ require_relative 'group_rmchild'
16
+ require_relative 'group_addhost'
17
+ require_relative 'group_rmhost'
18
+ require_relative 'group_addvar'
19
+ require_relative 'group_rmvar'
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,98 @@
1
+ require 'thor'
2
+ require_relative './formatter.rb'
3
+
4
+ module Moose
5
+ module Inventory
6
+ module Cli
7
+ ##
8
+ # Implementation of the "group add" method of the CLI
9
+ class Group
10
+ #==========================
11
+ desc 'add NAME', 'Add a group NAME to the inventory'
12
+ option :hosts
13
+ # rubocop:disable Metrics/LineLength
14
+ def add(*argv) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
15
+ # rubocop:enable Metrics/LineLength
16
+ if argv.length < 1
17
+ abort("ERROR: Wrong number of arguments, #{argv.length} for 1 or more.")
18
+ end
19
+
20
+ # Arguments
21
+ names = argv.uniq.map(&:downcase)
22
+ options[:hosts] = '' if options[:hosts].nil?
23
+ hosts = options[:hosts].downcase.split(',').uniq
24
+
25
+ # sanity
26
+ if names.include?('ungrouped')
27
+ abort("ERROR: Cannot manually manipulate the automatic group 'ungrouped'\n")
28
+ end
29
+
30
+ # Convenience
31
+ db = Moose::Inventory::DB
32
+ fmt = Moose::Inventory::Cli::Formatter
33
+
34
+ # Transaction
35
+ warn_count = 0
36
+ db.transaction do # Transaction start
37
+ names.each do |name|
38
+ # Add the group
39
+ puts "Add group '#{name}':"
40
+ group = db.models[:group].find(name: name)
41
+ hosts_ds = nil
42
+ fmt.puts 2, "- create group..."
43
+ if group.nil?
44
+ group = db.models[:group].create(name: name)
45
+ fmt.puts 4, '- OK'
46
+ else
47
+ warn_count += 1
48
+ fmt.warn "Group '#{name}' already exists, skipping creation.\n"
49
+ fmt.puts 4, "- already exists, skipping."
50
+ hosts_ds = group.hosts_dataset
51
+ fmt.puts 4, '- OK'
52
+ end
53
+
54
+ # Associate with hosts
55
+ hosts.each do |h|
56
+ next if h.nil? || h.empty?
57
+ fmt.puts 2, "- add association {group:#{name} <-> host:#{ h }}..."
58
+ host = db.models[:host].find(name: h)
59
+ if host.nil?
60
+ warn_count += 1
61
+ fmt.warn "Host '#{h}' doesn't exist, but will be created.\n"
62
+ fmt.puts 4, "- host doesn't exist, creating now..."
63
+ host = db.models[:host].create(name: h)
64
+ fmt.puts 6, "- OK"
65
+ end
66
+ if !hosts_ds.nil? && !hosts_ds[name: h].nil?
67
+ warn_count += 1
68
+ fmt.warn "Association {group:#{name} <-> host:#{ h }}"\
69
+ " already exists, skipping creation.\n"
70
+ fmt.puts 4, "- already exists, skipping."
71
+ else
72
+ group.add_host(host)
73
+ end
74
+ fmt.puts 4, '- OK'
75
+
76
+ # Handle the host's automatic 'ungrouped' group
77
+ ungrouped = host.groups_dataset[name: 'ungrouped']
78
+ unless ungrouped.nil?
79
+ fmt.puts 2, "- remove automatic association {group:ungrouped"\
80
+ " <-> host:#{ h }}..."
81
+ host.remove_group( ungrouped ) unless ungrouped.nil?
82
+ fmt.puts 4, '- OK'
83
+ end
84
+ end
85
+ fmt.puts 2, '- all OK'
86
+ end
87
+ end # Transaction end
88
+ if warn_count == 0
89
+ puts 'Succeeded'
90
+ else
91
+ puts 'Succeeded, with warnings.'
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
98
+
@@ -0,0 +1,21 @@
1
+ require 'thor'
2
+ require_relative './formatter.rb'
3
+
4
+ module Moose
5
+ module Inventory
6
+ module Cli
7
+ ##
8
+ # Implemention of the "group addchild" methods of the CLI
9
+ class Group < Thor # rubocop:disable ClassLength
10
+ #==========================
11
+ desc 'addchild [options] NAME CHILDNAME',
12
+ 'Associate a child-group CHILDNAME with the group NAME'
13
+ option :allowcreate, type: :boolean
14
+ def addchild
15
+ abort("The 'groups addchild GROUP' method is not yet implemented")
16
+ puts 'group addchild'
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,97 @@
1
+ require 'thor'
2
+ require_relative './formatter.rb'
3
+
4
+ module Moose
5
+ module Inventory
6
+ module Cli
7
+ ##
8
+ # Implementation of the "group addhost" method of the CLI
9
+ class Group
10
+ #==========================
11
+ desc 'addhost NAME HOSTNAME',
12
+ 'Associate a host HOSTNAME with the group NAME'
13
+ def addhost(*args) # rubocop:disable Metrics/AbcSize
14
+ # Sanity
15
+ if args.length < 2
16
+ abort("ERROR: Wrong number of arguments, #{args.length} for 2 or more.")
17
+ end
18
+
19
+ # Arguments
20
+ name = args[0].downcase
21
+ hosts = args.slice(1, args.length - 1).uniq.map(&:downcase)
22
+
23
+ # Sanity
24
+ if name == 'ungrouped'
25
+ abort("ERROR: Cannot manually manipulate the automatic group 'ungrouped'.")
26
+ end
27
+
28
+ # Convenience
29
+ db = Moose::Inventory::DB
30
+ fmt = Moose::Inventory::Cli::Formatter
31
+
32
+ # Transaction
33
+ warn_count = 0
34
+ begin
35
+ db.transaction do # Transaction start
36
+ puts "Associate group '#{name}' with host(s) '#{hosts.join(',')}':"
37
+ # Get the target group
38
+ fmt.puts 2, "- retrieve group '#{name}'..."
39
+ group = db.models[:group].find(name: name)
40
+ if group.nil?
41
+ abort("ERROR: The group '#{name}' does not exist.")
42
+ end
43
+ fmt.puts 4, '- OK'
44
+
45
+ # Associate group with the hosts
46
+ ungrouped = db.models[:group].find_or_create(name: 'ungrouped')
47
+ hosts_ds = group.hosts_dataset
48
+ hosts.each do |h| # rubocop:disable Style/Next
49
+ fmt.puts 2, "- add association {group:#{name} <-> host:#{ h }}..."
50
+
51
+ # Check against existing associations
52
+ unless hosts_ds[name: h].nil?
53
+ warn_count += 1
54
+ fmt.warn "Association {group:#{name} <-> host:#{ h }} already"\
55
+ " exists, skipping.\n"
56
+ fmt.puts 4, '- already exists, skipping.'
57
+ fmt.puts 4, '- OK'
58
+ next
59
+ end
60
+
61
+ # Add new association
62
+ host = db.models[:host].find(name: h)
63
+ if host.nil?
64
+ warn_count += 1
65
+ fmt.warn "Host '#{h}' does not exist and will be created.\n"
66
+ fmt.puts 4, '- host does not exist, creating now...'
67
+ host = db.models[:host].create(name: h)
68
+ fmt.puts 6, '- OK'
69
+ end
70
+
71
+ group.add_host(host)
72
+ fmt.puts 4, '- OK'
73
+
74
+ # Remove the host from the ungrouped group, if necessary
75
+ unless host.groups_dataset[name: 'ungrouped'].nil?
76
+ fmt.puts 2,'- remove automatic association '\
77
+ "{group:ungrouped <-> host:#{h}}..."
78
+ host.remove_group(ungrouped)
79
+ fmt.puts 4, '- OK'
80
+ end
81
+ end
82
+ fmt.puts 2, '- all OK'
83
+ end # Transaction end
84
+ rescue db.exceptions[:moose] => e
85
+ abort("ERROR: #{e.message}")
86
+ end
87
+ if warn_count == 0
88
+ puts 'Succeeded.'
89
+ else
90
+ puts 'Succeeded, with warnings.'
91
+ end
92
+ end
93
+
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,72 @@
1
+ require 'thor'
2
+ require_relative './formatter.rb'
3
+
4
+ module Moose
5
+ module Inventory
6
+ module Cli
7
+ ##
8
+ # Implementation of the "group addvar" method of the CLI
9
+ class Group
10
+ #==========================
11
+ desc 'addvar NAME VARNAME=VALUE',
12
+ 'Add a variable VARNAME with value VALUE to the group NAME'
13
+ def addvar(*args)
14
+ if args.length < 2
15
+ abort('ERROR: Wrong number of arguments, '\
16
+ "#{args.length} for 2 or more.")
17
+ end
18
+ # Convenience
19
+ db = Moose::Inventory::DB
20
+ fmt = Moose::Inventory::Cli::Formatter
21
+
22
+ # Arguments
23
+ name = args[0].downcase
24
+ vars = args.slice(1, args.length - 1).uniq
25
+
26
+ # Transaction
27
+ db.transaction do # Transaction start
28
+ puts "Add variables '#{vars.join(",")}' to group '#{name}':"
29
+ fmt.puts 2,"- retrieve group '#{name}'..."
30
+ group = db.models[:group].find(name: name)
31
+ if group.nil?
32
+ fail db.exceptions[:moose],
33
+ "The group '#{name}' does not exist."
34
+ end
35
+ fmt.puts 4, '- OK'
36
+
37
+ groupvars_ds = group.groupvars_dataset
38
+ vars.each do |v|
39
+ fmt.puts 2, "- add variable '#{v}'..."
40
+ vararray = v.split('=')
41
+
42
+ if v.start_with?('=') || v.end_with?('=') || vararray.length != 2
43
+ fail db.exceptions[:moose],
44
+ "Incorrect format in '{#{v}}'. Expected 'key=value'."
45
+ end
46
+
47
+ # Check against existing associations
48
+ groupvar = groupvars_ds[name: vararray[0]]
49
+ if !groupvar.nil?
50
+ unless groupvar[:value] == vararray[1]
51
+ fmt.puts 4, '- already exists, applying as an update...'
52
+ update = db.models[:groupvar].find(id: groupvar[:id])
53
+ update[:value] = vararray[1]
54
+ update.save
55
+ end
56
+ else
57
+ # groupvar doesn't exist, so create and associate
58
+ groupvar = db.models[:groupvar].create(name: vararray[0],
59
+ value: vararray[1])
60
+ group.add_groupvar(groupvar)
61
+ end
62
+ fmt.puts 4, '- OK'
63
+ end
64
+ fmt.puts 2, '- all OK'
65
+ end # Transaction end
66
+
67
+ puts 'Succeeded.'
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,52 @@
1
+ require 'thor'
2
+ require_relative './formatter.rb'
3
+
4
+ module Moose
5
+ module Inventory
6
+ module Cli
7
+ ##
8
+ # Implementation of the "group get" method of the CLI
9
+ class Group
10
+ desc 'get GROUP_1 [GROUP_2 ...]', 'Get groups GROUP_n from the inventory'
11
+ def get(*argv) # rubocop:disable Metrics/AbcSize
12
+ if argv.length < 1
13
+ abort('ERROR: Wrong number of arguments, '\
14
+ "#{argv.length} for 1 or more")
15
+ end
16
+
17
+ # Convenience
18
+ db = Moose::Inventory::DB
19
+ fmt = Moose::Inventory::Cli::Formatter
20
+
21
+ # Arguments
22
+ names = argv.uniq.map(&:downcase)
23
+
24
+ # Process
25
+ results = {}
26
+ names.each do |name|
27
+ group = db.models[:group].find(name: name)
28
+
29
+ unless group.nil?
30
+ hosts = group.hosts_dataset.map(:name)
31
+
32
+ groupvars = {}
33
+ group.groupvars_dataset.each do |gv|
34
+ groupvars[gv[:name].to_sym] = gv[:value]
35
+ end
36
+
37
+ results[group[:name].to_sym] = {}
38
+ unless hosts.length == 0
39
+ results[group[:name].to_sym][:hosts] = hosts
40
+ end
41
+ unless groupvars.length == 0
42
+ results[group[:name].to_sym][:groupvars] = groupvars
43
+ end
44
+ end
45
+ end
46
+
47
+ fmt.dump(results)
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end