moose-inventory 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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,41 @@
1
+ require 'thor'
2
+ require_relative './formatter.rb'
3
+
4
+ module Moose
5
+ module Inventory
6
+ module Cli
7
+ ##
8
+ # Implementation of the "group list" method of the CLI
9
+ class Group
10
+ #==========================
11
+ desc 'list',
12
+ 'List the groups, together with any associated hosts and groupvars'
13
+ option :ansiblestyle, type: :boolean
14
+ def list # rubocop:disable Metrics/AbcSize
15
+ # Convenience
16
+ db = Moose::Inventory::DB
17
+
18
+ # Process
19
+ results = {}
20
+ db.models[:group].all.each do |group|
21
+ hosts = group.hosts_dataset.map(:name)
22
+
23
+ groupvars = {}
24
+ group.groupvars_dataset.each do |gv|
25
+ groupvars[gv[:name].to_sym] = gv[:value]
26
+ end
27
+
28
+ results[group[:name].to_sym] = {}
29
+ unless hosts.length == 0
30
+ results[group[:name].to_sym][:hosts] = hosts
31
+ end
32
+ unless groupvars.length == 0
33
+ results[group[:name].to_sym][:groupvars] = groupvars
34
+ end
35
+ end
36
+ Formatter.out(results)
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,77 @@
1
+ require 'thor'
2
+ require_relative './formatter.rb'
3
+
4
+ module Moose
5
+ module Inventory
6
+ module Cli
7
+ ##
8
+ # Implementation of "group rm" methods of the CLI
9
+ class Group
10
+
11
+ #==========================
12
+ desc 'rm NAME',
13
+ 'Remove a group NAME from the inventory'
14
+ def rm(*argv) # rubocop:disable Metrics/AbcSize
15
+ #
16
+ # Sanity
17
+ if argv.length < 1
18
+ abort('ERROR: Wrong number of arguments, '\
19
+ "#{argv.length} for 1 or more.")
20
+ end
21
+
22
+ # Convenience
23
+ db = Moose::Inventory::DB
24
+ fmt = Moose::Inventory::Cli::Formatter
25
+
26
+ # Arguments
27
+ names = argv.uniq.map(&:downcase)
28
+
29
+ # sanity
30
+ if names.include?('ungrouped')
31
+ abort("Cannot manually manipulate the automatic group 'ungrouped'\n")
32
+ end
33
+
34
+ # Transaction
35
+ warn_count = 0
36
+ db.transaction do # Transaction start
37
+ names.each do |name|
38
+ puts "Remove group '#{name}':"
39
+ fmt.puts 2, "- Retrieve group '#{name}'..."
40
+ group = db.models[:group].find(name: name)
41
+ if group.nil?
42
+ warn_count += 1
43
+ fmt.warn "Group '#{ name }' does not exist, skipping.\n"
44
+ fmt.puts 4, "- No such group, skipping."
45
+ end
46
+ fmt.puts 4, "- OK"
47
+ unless group.nil?
48
+ # Handle automatic group for any associated hosts
49
+ hosts_ds = group.hosts_dataset
50
+ hosts_ds.each do |host|
51
+ host_groups_ds = host.groups_dataset
52
+ if host_groups_ds.count == 1 # We're the only group
53
+ fmt.puts 2, "- Adding automatic association {group:ungrouped <-> host:#{host[:name]}}..."
54
+ ungrouped = db.models[:group].find_or_create(name: 'ungrouped')
55
+ host.add_group(ungrouped)
56
+ fmt.puts 4, "- OK"
57
+ end
58
+ end
59
+ # Remove the group
60
+ fmt.puts 2, "- Destroy group '#{name}'..."
61
+ group.remove_all_hosts
62
+ group.destroy
63
+ fmt.puts 4, "- OK"
64
+ end
65
+ fmt.puts 2, "- All OK"
66
+ end
67
+ end # Transaction end
68
+ if warn_count == 0
69
+ puts "Succeeded."
70
+ else
71
+ puts "Succeeded, with warnings."
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,20 @@
1
+ require 'thor'
2
+ require_relative './formatter.rb'
3
+
4
+ module Moose
5
+ module Inventory
6
+ module Cli
7
+ ##
8
+ # Implemention of the "group rmchild" methods of the CLI
9
+ class Group < Thor # rubocop:disable ClassLength
10
+ #==========================
11
+ desc 'rmchild NAME CHILDNAME',
12
+ 'Dissociate a child-group CHILDNAME from the group NAME'
13
+ def rmchild
14
+ abort("The 'groups rmchild GROUP' method is not yet implemented")
15
+ puts 'group rmchild'
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,89 @@
1
+ require 'thor'
2
+ require_relative './formatter.rb'
3
+
4
+ module Moose
5
+ module Inventory
6
+ module Cli
7
+ ##
8
+ # Implementation of the "group rmhost" method of the CLI
9
+ class Group
10
+
11
+ #==========================
12
+ desc 'rmhost GROUPNAME HOSTNAME_1 [HOSTNAME_2 ...]',
13
+ 'Dissociate the hosts HOSTNAME_n from the group NAME'
14
+ # rubocop:disable Metrics/LineLength
15
+ def rmhost(*args) # rubocop:disable Metrics/AbcSize, Metrics/PerceivedComplexity, Metrics/MethodLength, Metrics/CyclomaticComplexity
16
+ # rubocop:enable Metrics/LineLength
17
+ # Sanity
18
+ if args.length < 2
19
+ abort("ERROR: Wrong number of arguments, #{args.length} for 2 or more.")
20
+ end
21
+
22
+ # Arguments
23
+ name = args[0].downcase
24
+ hosts = args.slice(1, args.length - 1).uniq.map(&:downcase)
25
+
26
+ # Sanity
27
+ if name == 'ungrouped'
28
+ abort("ERROR: Cannot manually manipulate the automatic group 'ungrouped'.")
29
+ end
30
+
31
+ # Convenience
32
+ db = Moose::Inventory::DB
33
+ fmt = Moose::Inventory::Cli::Formatter
34
+
35
+ # Transaction
36
+ warn_count = 0
37
+ begin
38
+ db.transaction do # Transaction start
39
+ # Get the target group
40
+ puts "Dissociate group '#{name}' from host(s) '#{hosts.join(',')}':"
41
+ fmt.puts 2, "- retrieve group '#{name}'..."
42
+ group = db.models[:group].find(name: name)
43
+ if group.nil?
44
+ abort("ERROR: The group '#{name}' does not exist.")
45
+ end
46
+ fmt.puts 4, '- OK'
47
+
48
+ # dissociate group from the hosts
49
+ ungrouped = db.models[:group].find_or_create(name: 'ungrouped')
50
+ hosts_ds = group.hosts_dataset
51
+ hosts.each do |h| # rubocop:disable Style/Next
52
+ fmt.puts 2, "- remove association {group:#{name} <-> host:#{ h }}..."
53
+
54
+ # Check against existing associations
55
+ if hosts_ds[name: h].nil?
56
+ warn_count += 1
57
+ fmt.warn "Association {group:#{name} <-> host:#{ h }} doesn't"\
58
+ " exist, skipping.\n"
59
+ fmt.puts 4, '- doesn\'t exist, skipping.'
60
+ fmt.puts 4, '- OK'
61
+ next
62
+ end
63
+
64
+ host = db.models[:host].find(name: h)
65
+ group.remove_host(host) unless host.nil?
66
+ fmt.puts 4,'- OK'
67
+
68
+ # Add the host to the ungrouped group if not in any other group
69
+ if host.groups_dataset.count == 0
70
+ fmt.puts 2, "- add automatic association {group:ungrouped <-> host:#{h}}..."
71
+ host.add_group(ungrouped)
72
+ fmt.puts 4, '- OK'
73
+ end
74
+ end
75
+ fmt.puts 2, '- all OK'
76
+ end # Transaction end
77
+ rescue db.exceptions[:moose] => e
78
+ abort("ERROR: #{e.message}")
79
+ end
80
+ if warn_count == 0
81
+ puts 'Succeeded.'
82
+ else
83
+ puts 'Succeeded, with warnings.'
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,65 @@
1
+ require 'thor'
2
+ require_relative './formatter.rb'
3
+
4
+ module Moose
5
+ module Inventory
6
+ module Cli
7
+ ##
8
+ # Implementation of the "group rmvar" method of the CLI
9
+ class Group
10
+ #==========================
11
+ desc 'rmvar NAME VARNAME',
12
+ 'Remove a variable VARNAME from the group NAME'
13
+ def rmvar(*args)
14
+ if args.length < 2
15
+ abort('ERROR: Wrong number of arguments, ' \
16
+ "#{args.length} for 2 or more.")
17
+ end
18
+
19
+ # Convenience
20
+ db = Moose::Inventory::DB
21
+ fmt = Moose::Inventory::Cli::Formatter
22
+
23
+ # Arguments
24
+ name = args[0].downcase
25
+ vars = args.slice(1, args.length - 1).uniq
26
+
27
+ # Transaction
28
+ db.transaction do # Transaction start
29
+ puts "Remove variable(s) '#{vars.join(",")}' from group '#{name}':"
30
+
31
+ fmt.puts 2, "- retrieve group '#{name}'..."
32
+ group = db.models[:group].find(name: name)
33
+ if group.nil?
34
+ fail db.exceptions[:moose],
35
+ "The group '#{name}' does not exist."
36
+ end
37
+ fmt.puts 4, '- OK'
38
+
39
+ groupvars_ds = group.groupvars_dataset
40
+ vars.each do |v|
41
+ fmt.puts 2, "- remove variable '#{v}'..."
42
+ vararray = v.split('=')
43
+ if v.start_with?('=') || v.scan('=').count > 1
44
+ fail db.exceptions[:moose],
45
+ "Incorrect format in {#{v}}. " \
46
+ 'Expected \'key\' or \'key=value\'.'
47
+ end
48
+
49
+ # Check against existing associations
50
+ groupvar = groupvars_ds[name: vararray[0]]
51
+ unless groupvar.nil?
52
+ # remove the association
53
+ group.remove_groupvar(groupvar)
54
+ groupvar.destroy
55
+ end
56
+ fmt.puts 4, '- OK'
57
+ end
58
+ fmt.puts 2, '- all OK'
59
+ end # Transaction end
60
+ puts 'Succeeded.'
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,24 @@
1
+ require 'thor'
2
+ require 'json'
3
+
4
+ require_relative './formatter.rb'
5
+ require_relative '../db/exceptions.rb'
6
+
7
+ module Moose
8
+ module Inventory
9
+ module Cli
10
+ ##
11
+ # Class implementing the "host" methods of the CLI
12
+ class Host < Thor # rubocop:disable Metrics/ClassLength
13
+ require_relative 'host_add'
14
+ require_relative 'host_get'
15
+ require_relative 'host_list'
16
+ require_relative 'host_rm'
17
+ require_relative 'host_addgroup'
18
+ require_relative 'host_rmgroup'
19
+ require_relative 'host_addvar'
20
+ require_relative 'host_rmvar'
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,93 @@
1
+ require 'thor'
2
+ require 'json'
3
+ require 'indentation'
4
+
5
+ require_relative './formatter.rb'
6
+ require_relative '../db/exceptions.rb'
7
+
8
+ module Moose
9
+ module Inventory
10
+ module Cli
11
+ ##
12
+ # Class implementing the "host" methods of the CLI
13
+ class Host
14
+ #==========================
15
+ desc 'add HOSTNAME_1 [HOSTNAME_2 ...]',
16
+ 'Add a hosts HOSTNAME_n to the inventory'
17
+ option :groups
18
+ # rubocop:disable Metrics/LineLength
19
+ def add(*argv) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
20
+ # rubocop:enable Metrics/LineLength
21
+ if argv.length < 1
22
+ abort('ERROR: Wrong number of arguments, '\
23
+ "#{argv.length} for 1 or more.")
24
+ end
25
+
26
+ # Convenience
27
+ db = Moose::Inventory::DB
28
+ fmt = Moose::Inventory::Cli::Formatter
29
+
30
+ # Arguments
31
+ names = argv.uniq.map(&:downcase)
32
+
33
+ # split(/\W+/) splits on hyphens too, which is not what we want
34
+ #groups = options[:groups].downcase.split(/\W+/).uniq
35
+ options[:groups].nil? && options[:groups] = ''
36
+ groups = options[:groups].downcase.split(',').uniq
37
+
38
+ # Sanity
39
+ if groups.include?('ungrouped')
40
+ abort("ERROR: Cannot manually manipulate "\
41
+ "the automatic group 'ungrouped'.")
42
+ end
43
+
44
+ # Process
45
+ db.transaction do # Transaction start
46
+ fmt.reset_indent
47
+
48
+ names.each do |name|
49
+ puts "Add host '#{name}':"
50
+ fmt.puts 2, "- Creating host '#{name}'..."
51
+ host = db.models[:host].find(name: name)
52
+ groups_ds = nil
53
+ if host.nil?
54
+ host = db.models[:host].create(name: name)
55
+ else
56
+ fmt.warn "The host '#{name}' already exists, skipping creation.\n"
57
+ groups_ds = host.groups_dataset
58
+ end
59
+ fmt.puts 4, "- OK"
60
+
61
+ groups.each do |g|
62
+ next if g.nil? || g.empty?
63
+ fmt.puts 2, "- Adding association {host:#{name} <-> group:#{g}}..."
64
+ group = db.models[:group].find(name: g)
65
+ if group.nil?
66
+ fmt.warn "The group '#{g}' doesn't exist, but will be created.\n"
67
+ group = db.models[:group].create(name: g)
68
+ end
69
+ if !groups_ds.nil? && groups_ds[name: g].nil?
70
+ fmt.warn "Association {host:#{name} <-> group:#{ g }} already exists, skipping creation.\n"
71
+ else
72
+ host.add_group(group)
73
+ end
74
+ fmt.puts 4, '- OK'
75
+ end
76
+
77
+ # Handle the automatic 'ungrouped' group
78
+ groups_ds = host.groups_dataset
79
+ if !groups_ds.nil? && groups_ds.count == 0
80
+ fmt.puts 2, "- Adding automatic association {host:#{name} <-> group:ungrouped}..."
81
+ ungrouped = db.models[:group].find_or_create(name: 'ungrouped')
82
+ host.add_group(ungrouped)
83
+ fmt.puts 4, "- OK"
84
+ end
85
+ fmt.puts 2, "- All OK"
86
+ end
87
+ end # Transaction end
88
+ puts 'Succeeded'
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,88 @@
1
+ require 'thor'
2
+ require 'json'
3
+
4
+ require_relative './formatter.rb'
5
+ require_relative '../db/exceptions.rb'
6
+
7
+ module Moose
8
+ module Inventory
9
+ module Cli
10
+ ##
11
+ # implementation of the "addgroup" method of the CLI
12
+ class Host
13
+ desc 'addgroup HOSTNAME GROUPNAME [GROUPNAME ...]',
14
+ 'Associate the host with a group'
15
+ # rubocop:disable Metrics/LineLength
16
+ def addgroup(*args) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
17
+ # rubocop:enable Metrics/LineLength
18
+ # Sanity
19
+ if args.length < 2
20
+ abort('ERROR: Wrong number of arguments, '\
21
+ "#{args.length} for 2 or more.")
22
+ end
23
+
24
+ # Convenience
25
+ db = Moose::Inventory::DB
26
+ fmt = Moose::Inventory::Cli::Formatter
27
+
28
+ # Arguments
29
+ name = args[0].downcase
30
+ groups = args.slice(1, args.length - 1).uniq.map(&:downcase)
31
+
32
+ # Sanity
33
+ if groups.include?('ungrouped')
34
+ abort 'ERROR: Cannot manually manipulate the automatic '\
35
+ 'group \'ungrouped\'.'
36
+ end
37
+
38
+ # Transaction
39
+ db.transaction do # Transaction start
40
+ puts "Associate host '#{name}' with groups '#{groups.join(',')}':"
41
+ # Get the target host
42
+ fmt.puts 2, "- Retrieve host '#{name}'..."
43
+ host = db.models[:host].find(name: name)
44
+ if host.nil?
45
+ fail db.exceptions[:moose], "The host '#{name}' "\
46
+ 'was not found in the database.'
47
+ end
48
+ fmt.puts 4, '- OK'
49
+
50
+ # Associate host with the groups
51
+ groups_ds = host.groups_dataset
52
+ groups.each do |g|
53
+ fmt.puts 2, "- Add association {host:#{name} <-> group:#{ g }}..."
54
+
55
+ # Check against existing associations
56
+ if !groups_ds[name: g].nil?
57
+ fmt.warn "Association {host:#{name} <-> group:#{g}} already exists, skipping."
58
+ fmt.puts 4, "- Already exists, skipping."
59
+ else
60
+ # Add new association
61
+ group = db.models[:group].find(name: g)
62
+ if group.nil?
63
+ fmt.warn "Group '#{g}' does not exist and will be created."
64
+ fmt.puts 4, "- Group does not exist, creating now..."
65
+ group = db.models[:group].create(name: g)
66
+ fmt.puts 6, "- OK"
67
+ end
68
+ host.add_group(group)
69
+ end
70
+ fmt.puts 4, '- OK'
71
+ end
72
+
73
+ # Handle 'ungrouped' group automation
74
+ unless groups_ds[name: 'ungrouped'].nil?
75
+ fmt.puts 2, '- Remove automatic association '\
76
+ "{host:#{name} <-> group:ungrouped}..."
77
+ ungrouped = db.models[:group].find(name: 'ungrouped')
78
+ host.remove_group(ungrouped) unless ungrouped.nil?
79
+ fmt.puts 4, '- OK'
80
+ end
81
+ fmt.puts 2, '- All OK'
82
+ end # Transaction end
83
+ puts 'Succeeded'
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end