houcho 0.0.6 → 0.0.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 (45) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -1
  3. data/Gemfile.lock +32 -0
  4. data/bin/houcho +3 -262
  5. data/houcho.gemspec +2 -1
  6. data/lib/houcho/attribute.rb +99 -0
  7. data/lib/houcho/ci.rb +18 -13
  8. data/lib/houcho/cli/attribute.rb +70 -0
  9. data/lib/houcho/cli/host.rb +46 -0
  10. data/lib/houcho/cli/outerrole.rb +53 -0
  11. data/lib/houcho/cli/role.rb +69 -0
  12. data/lib/houcho/cli/spec.rb +103 -0
  13. data/lib/houcho/cli.rb +52 -0
  14. data/lib/houcho/config.rb +28 -0
  15. data/lib/houcho/database.rb +99 -0
  16. data/lib/houcho/element.rb +79 -50
  17. data/lib/houcho/host.rb +30 -9
  18. data/lib/houcho/outerrole/cloudforecast.rb +94 -0
  19. data/{templates/role/cf_roles.yaml → lib/houcho/outerrole/yabitz.rb} +0 -0
  20. data/lib/houcho/outerrole.rb +52 -0
  21. data/lib/houcho/repository.rb +59 -0
  22. data/lib/houcho/role.rb +78 -91
  23. data/lib/houcho/spec/runner.rb +156 -85
  24. data/lib/houcho/spec.rb +72 -3
  25. data/lib/houcho/version.rb +1 -1
  26. data/lib/houcho.rb +10 -52
  27. data/spec/houcho_spec.rb +334 -91
  28. metadata +31 -22
  29. data/lib/houcho/cloudforecast/host.rb +0 -25
  30. data/lib/houcho/cloudforecast/role.rb +0 -25
  31. data/lib/houcho/cloudforecast.rb +0 -59
  32. data/lib/houcho/yamlhandle.rb +0 -31
  33. data/spec/spec_helper.rb +0 -15
  34. data/templates/conf/houcho.conf +0 -10
  35. data/templates/conf/kk.rb +0 -14
  36. data/templates/conf/rspec.conf +0 -1
  37. data/templates/master +0 -94
  38. data/templates/role/cloudforecast/.gitkeep +0 -0
  39. data/templates/role/cloudforecast.yaml +0 -0
  40. data/templates/role/hosts.yaml +0 -0
  41. data/templates/role/hosts_ignored.yaml +0 -0
  42. data/templates/role/roles.yaml +0 -0
  43. data/templates/role/specs.yaml +0 -0
  44. data/templates/spec/sample_spec.rb +0 -13
  45. data/templates/spec/spec_helper.rb +0 -29
@@ -0,0 +1,69 @@
1
+ require "thor"
2
+ require "houcho/role"
3
+
4
+ module Houcho
5
+ module CLI
6
+ class Role < Thor
7
+ namespace :role
8
+
9
+ @@r = Houcho::Role.new
10
+
11
+ desc 'create [role1 role2 role3...]', 'cretate role'
12
+ def create(*args)
13
+ Houcho::CLI::Main.empty_args(self, shell, __method__) if args.empty?
14
+ @@r.create(args)
15
+ rescue Houcho::RoleExistenceException => e
16
+ puts e.message
17
+ exit!
18
+ end
19
+
20
+ desc 'delete [role1 role2 role3...]', 'delete a role'
21
+ def delete(*args)
22
+ Houcho::CLI::Main.empty_args(self, shell, __method__) if args.empty?
23
+ @@r.delete(args)
24
+ rescue SQLite3::ConstraintException => e
25
+ puts e.message
26
+ exit!
27
+ end
28
+
29
+ desc 'rename [exist role] [name]', 'rename a role'
30
+ def rename(exist_role, name)
31
+ @@r.rename(exist_role, name)
32
+ rescue SQLite3::ConstraintException, SQLite3::SQLException => e
33
+ puts e.message
34
+ exit!
35
+ end
36
+
37
+ desc 'details [role1 role2...]', 'show details about role'
38
+ def details(*args)
39
+ Houcho::CLI::Main.empty_args(self, shell, __method__) if args.empty?
40
+ Houcho::CLI::Main.puts_details(@@r.details(args))
41
+ end
42
+
43
+ desc 'list', 'show all of roles'
44
+ def list
45
+ puts @@r.list.join("\n")
46
+ end
47
+
48
+ desc 'exec (role1 role2..) [options]', 'run role'
49
+ option :exclude_hosts, :type => :array, :desc => '--exclude-hosts host1 host2 host3...'
50
+ option :dry_run, :type => :boolean, :default => false, :desc => 'show commands that may exexute'
51
+ def exec(*args)
52
+ Houcho::CLI::Main.empty_args(self, shell, __method__) if args.empty?
53
+ runner = Houcho::Spec::Runner.new
54
+
55
+ begin
56
+ exit! unless runner.execute_role(
57
+ args,
58
+ (options[:exclude_hosts] || []),
59
+ options[:dry_run],
60
+ true #output to console
61
+ )
62
+ rescue Houcho::SpecFileException => e
63
+ puts e.message
64
+ exit!
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,103 @@
1
+ require 'thor'
2
+ require 'houcho/spec'
3
+ require 'houcho/spec/runner'
4
+
5
+ module Houcho
6
+ module CLI
7
+ class Spec < Thor
8
+ namespace :spec
9
+
10
+ @@s = Houcho::Spec.new
11
+
12
+ desc 'list', 'show all of spec list'
13
+ def list
14
+ puts @@s.list.sort.join("\n")
15
+ end
16
+
17
+
18
+ desc 'attach [spec1 spec2 spec3...] --roles [role1 role2...]', 'attach spec to role'
19
+ option :roles, :type => :array, :required => true, :desc => 'specify the roles separated by spaces.'
20
+ def attach(*args)
21
+ @@s.attach(args, options[:roles])
22
+ rescue RoleExistenceException, SpecFileException, SQLite3::ConstraintException => e
23
+ puts e.message
24
+ exit!
25
+ end
26
+
27
+
28
+ desc 'detach [spec1 spec2 spec3...]', 'detach spec from spec'
29
+ option :roles, :type => :array, :required => true, :desc => 'specify the roles separated by spaces.'
30
+ def detach(*args)
31
+ @@s.detach(args, options[:roles])
32
+ rescue RoleExistenceException, SQLite3::ConstraintException => e
33
+ puts e.message
34
+ exit!
35
+ end
36
+
37
+
38
+ desc "rename [from] [to]", "rename spec file"
39
+ def rename(from, to)
40
+ @@s.rename(from, to)
41
+ rescue SpecFileException => e
42
+ puts e.message
43
+ exit!
44
+ end
45
+
46
+
47
+ desc "delete [spec1 spec2 spec3...]", "delete spec file from houcho repository."
48
+ option :force, :aliases => "-f", :type => :boolean, :desc => "delete spec force together with attachment."
49
+ def delete(*args)
50
+ if options[:force]
51
+ @@s.delete_file!(args)
52
+ else
53
+ @@s.delete_file(args)
54
+ end
55
+ rescue SpecFileException => e
56
+ puts e.message
57
+ exit!
58
+ end
59
+
60
+
61
+ desc 'details [spec1 spec2 spec3...]', 'show details about spec'
62
+ def details(*args)
63
+ Houcho::CLI::Main.puts_details(@@s.details(args))
64
+ end
65
+
66
+
67
+ desc 'check [spec1 spec2...]', 'run the spec sampled appropriately to the associated host'
68
+ option :samples, :type => :numeric, :default => 5, :desc => 'number of sample hosts'
69
+ def check(*args)
70
+ Houcho::CLI::Main.empty_args(self, shell, __method__) if args.empty?
71
+ runner = Houcho::Spec::Runner.new
72
+
73
+ begin
74
+ exit! unless runner.check(args, options[:samples], false, true)
75
+ rescue SpecFileException => e
76
+ puts e.message
77
+ exit!
78
+ end
79
+ end
80
+
81
+
82
+ desc 'exec [spec1 spec2..]', 'run spec'
83
+ option :hosts, :type => :array, :desc => '--hosts host1 host2 host3...', :required => true
84
+ option :dry_run, :type => :boolean, :default => false, :desc => 'show commands that may exexute'
85
+ def exec(*args)
86
+ Houcho::CLI::Main.empty_args(self, shell, __method__) if args.empty?
87
+ runner = Houcho::Spec::Runner.new
88
+
89
+ begin
90
+ exit! unless runner.execute_manually(
91
+ options[:hosts],
92
+ args,
93
+ options[:dry_run],
94
+ true #output to console
95
+ )
96
+ rescue Houcho::SpecFileException => e
97
+ puts e.message
98
+ exit!
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
data/lib/houcho/cli.rb ADDED
@@ -0,0 +1,52 @@
1
+ require "thor"
2
+ require "rainbow"
3
+ require "houcho/repository"
4
+
5
+ module Houcho::CLI
6
+ class Main < Thor
7
+ if File.exist?("#{Houcho::Config::APPROOT}/houcho.db")
8
+ require "houcho/cli/role"
9
+ require "houcho/cli/spec"
10
+ require "houcho/cli/host"
11
+ require "houcho/cli/outerrole"
12
+ require "houcho/cli/attribute"
13
+ register(Houcho::CLI::Role, "role", "role [create|delete|rename|list|details|exec]", "operation of roles")
14
+ register(Houcho::CLI::Host, "host", "host [attach|detach|list|details]", "operation of hosts")
15
+ register(Houcho::CLI::Spec, "spec", "spec [attach|detach|list|details|rename|delete|exec|check]", "operation of specs")
16
+ register(Houcho::CLI::OuterRole, "outerrole", "outerrole [attach|detach|list|details|load]", "operation of outer roles")
17
+ register(Houcho::CLI::Attribute, "attr", "attr [set|get|delete]", "operation of attribute")
18
+ end
19
+
20
+ desc "init","set houcho repository on directory set environment variable HOUCHO_ROOT"
21
+ def init
22
+ Houcho::Repository.init
23
+ end
24
+
25
+ def self.empty_args(klass, chell, mesod)
26
+ klass.class.task_help(chell, mesod)
27
+ exit
28
+ end
29
+
30
+ def self.puts_details(e, indentsize = 0, cnt = 1)
31
+ case e
32
+ when Array
33
+ e.sort.each.with_index(1) do |v, i|
34
+ (indentsize-1).times {print ' '}
35
+ print i != e.size ? '├─ ' : '└─ '
36
+ puts v
37
+ end
38
+ puts ''
39
+ when Hash
40
+ e.each do |k,v|
41
+ if indentsize != 0
42
+ (indentsize).times {print ' '}
43
+ end
44
+ title = k.to_s.color(0,255,0)
45
+ title = '[' + k.to_s.color(219,112,147) + ']' if indentsize == 0
46
+ puts title
47
+ puts_details(v, indentsize+1, cnt+1)
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,28 @@
1
+ require "yaml"
2
+
3
+ module Houcho
4
+ module Config
5
+ APPROOT = ENV["HOUCHO_ROOT"] ? ENV["HOUCHO_ROOT"] : "/etc/houcho"
6
+
7
+ SPECDIR = "#{APPROOT}/spec"
8
+ SCRIPTDIR = "#{APPROOT}/script"
9
+
10
+ OUTERROLESOURCEDIR = "#{APPROOT}/outerrole"
11
+ CFYAMLDIR = "#{OUTERROLESOURCEDIR}/cloudforecast"
12
+
13
+ LOGDIR = "#{APPROOT}/log"
14
+ SPECLOG = "#{LOGDIR}/serverspec.log"
15
+
16
+ FILE = "#{Houcho::Config::APPROOT}/houcho.conf"
17
+ begin
18
+ conf = YAML.load_file(FILE)
19
+ rescue
20
+ end
21
+ if conf
22
+ UKIGUMO = conf["ukigumo"]
23
+ IKACHAN = conf["ikachan"]
24
+ GIT = conf["git"]
25
+ RSPEC = conf["rspec"]
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,99 @@
1
+ require "sqlite3"
2
+ require "houcho/config"
3
+
4
+ module Houcho
5
+ class Database
6
+ attr_reader :handle
7
+
8
+ def initialize
9
+ @handle = SQLite3::Database.new("#{Houcho::Config::APPROOT}/houcho.db")
10
+ @handle.execute("PRAGMA foreign_keys = ON")
11
+ end
12
+
13
+ def create_tables
14
+ @handle.execute_batch <<-SQL
15
+ CREATE TABLE IF NOT EXISTS role (
16
+ id INTEGER NOT NULL PRIMARY KEY,
17
+ name VARCHAR NOT NULL UNIQUE
18
+ );
19
+
20
+ CREATE TABLE IF NOT EXISTS host (
21
+ id INTEGER NOT NULL PRIMARY KEY,
22
+ name VARCHAR NOT NULL UNIQUE
23
+ );
24
+
25
+ CREATE TABLE IF NOT EXISTS role_host (
26
+ role_id INTEGER NOT NULL,
27
+ host_id INTEGER NOT NULL,
28
+ UNIQUE(role_id, host_id),
29
+ FOREIGN KEY (role_id) REFERENCES role (id) ON DELETE RESTRICT,
30
+ FOREIGN KEY (host_id) REFERENCES host (id) ON DELETE RESTRICT
31
+ );
32
+
33
+ CREATE TABLE IF NOT EXISTS serverspec (
34
+ id INTEGER NOT NULL PRIMARY KEY,
35
+ name VARCHAR NOT NULL UNIQUE
36
+ );
37
+
38
+ CREATE TABLE IF NOT EXISTS role_serverspec (
39
+ role_id INTEGER NOT NULL,
40
+ serverspec_id INTEGER NOT NULL,
41
+ UNIQUE(role_id, serverspec_id),
42
+ FOREIGN KEY (role_id) REFERENCES role (id) ON DELETE RESTRICT,
43
+ FOREIGN KEY (serverspec_id) REFERENCES serverspec (id) ON DELETE RESTRICT
44
+ );
45
+
46
+ CREATE TABLE IF NOT EXISTS script (
47
+ id INTEGER NOT NULL PRIMARY KEY,
48
+ name VARCHAR NOT NULL UNIQUE
49
+ );
50
+
51
+ CREATE TABLE IF NOT EXISTS role_script (
52
+ role_id INTEGER NOT NULL,
53
+ script_id INTEGER NOT NULL,
54
+ UNIQUE(role_id, script_id),
55
+ FOREIGN KEY (role_id) REFERENCES role (id) ON DELETE RESTRICT,
56
+ FOREIGN KEY (script_id) REFERENCES script (id) ON DELETE RESTRICT
57
+ );
58
+
59
+ CREATE TABLE IF NOT EXISTS outerrole (
60
+ id INTEGER NOT NULL PRIMARY KEY,
61
+ name VARCHAR NOT NULL UNIQUE,
62
+ data_source VARCHAR NOT NULL
63
+ );
64
+
65
+ CREATE TABLE IF NOT EXISTS outerrole_host (
66
+ outerrole_id INTEGER NOT NULL,
67
+ host_id INTEGER NOT NULL,
68
+ UNIQUE(outerrole_id, host_id),
69
+ FOREIGN KEY (outerrole_id) REFERENCES outerrole (id) ON DELETE RESTRICT,
70
+ FOREIGN KEY (host_id) REFERENCES host (id) ON DELETE RESTRICT
71
+ );
72
+
73
+ CREATE TABLE IF NOT EXISTS role_outerrole (
74
+ role_id INTEGER NOT NULL,
75
+ outerrole_id INTEGER NOT NULL,
76
+ UNIQUE(role_id, outerrole_id),
77
+ FOREIGN KEY (role_id) REFERENCES role (id) ON DELETE RESTRICT,
78
+ FOREIGN KEY (outerrole_id) REFERENCES outerrole (id) ON DELETE RESTRICT
79
+ );
80
+
81
+ CREATE TABLE IF NOT EXISTS attribute (
82
+ id INTEGER NOT NULL PRIMARY KEY,
83
+ name VARCHAR NOT NULL UNIQUE
84
+ );
85
+
86
+ CREATE TABLE IF NOT EXISTS attribute_value (
87
+ id INTEGER NOT NULL PRIMARY KEY,
88
+ attr_id INTEGER NOT NULL,
89
+ element_type INTEGER NOT NULL,
90
+ element_id INTEGER NOT NULL,
91
+ value VARCHAR NOT NULL,
92
+ COMMENT "element_type => {0:role, 1:outerrole, 2:host}",
93
+ UNIQUE(attr_id, element_type, element_id),
94
+ FOREIGN KEY (attr_id) REFERENCES attribute (id) ON DELETE RESTRICT
95
+ );
96
+ SQL
97
+ end
98
+ end
99
+ end
@@ -1,80 +1,109 @@
1
+ require 'houcho/role'
2
+ require "houcho/database"
3
+
1
4
  module Houcho
2
- module Element
5
+ class Element
6
+ def initialize(type)
7
+ @db = Houcho::Database.new.handle
8
+ @role = Houcho::Role.new
9
+ @type = type
10
+ end
3
11
 
4
- def elements(index = nil)
5
- if index
6
- (@elements.data[index]||[]).uniq
7
- else
8
- @elements.data.values.flatten.uniq
9
- end
12
+
13
+ def id(name)
14
+ @db.execute("SELECT id FROM #{@type} WHERE name = '#{name}'").flatten.first
10
15
  end
11
16
 
12
17
 
13
- def attach(elements, roles)
14
- elements = [elements] if elements.class == String
15
- roles = [roles] if roles.class == String
18
+ def list(role_id = nil)
19
+ sql = "SELECT T1.name FROM #{@type} T1"
20
+ sql += " JOIN role_#{@type} T2 ON T1.id = T2.#{@type}_id WHERE T2.role_id = #{role_id}" if role_id
16
21
 
17
- invalid_roles = []
18
- roles.each do |role|
19
- index = Role.index(role)
20
- if ! index
21
- invalid_roles << role
22
- next
23
- end
22
+ @db.execute(sql).flatten
23
+ end
24
24
 
25
- @elements.data[index] ||= []
26
- @elements.data[index] = (@elements.data[index] + elements).sort.uniq
25
+
26
+ def details(elements)
27
+ elements = elements.is_a?(Array) ? elements : [elements]
28
+ result = {}
29
+
30
+ elements.each do |element|
31
+ roles = @db.execute("
32
+ SELECT role.name
33
+ FROM role, #{@type}, role_#{@type}
34
+ WHERE role_#{@type}.#{@type}_id = #{@type}.id
35
+ AND role_#{@type}.role_id = role.id
36
+ AND #{@type}.name = ?
37
+ ", element).flatten.sort.uniq
38
+
39
+ result[element] = { "role" => roles }
27
40
  end
28
41
 
29
- @elements.save_to_file
30
- raise("role(#{invalid_roles.join(',')}) does not exist") if ! invalid_roles.size.zero?
42
+ result
31
43
  end
32
44
 
33
45
 
34
- def detach(elements, roles)
35
- elements = [elements] if elements.class == String
36
- roles = [roles] if roles.class == String
46
+ def attach(elements, roles)
47
+ elements = [elements] unless elements.is_a?(Array)
48
+ roles = [roles] unless roles.is_a?(Array)
37
49
 
38
- invalid_roles = []
39
50
  roles.each do |role|
40
- index = Role.index(role)
41
- if ! index
42
- invalid_roles << role
43
- next
44
- end
51
+ role_id = @role.id(role)
52
+ raise RoleExistenceException, "role does not exist - #{role}" unless role_id
45
53
 
46
- @elements.data[index] -= elements
47
- end
54
+ @db.transaction do
48
55
 
49
- @elements.save_to_file
50
- raise("role(#{invalid_roles.join(',')}) does not exist") if ! invalid_roles.size.zero?
51
- end
56
+ elements.each do |element|
57
+ @db.execute("INSERT INTO #{@type}(name) VALUES(?)", element) unless id(element)
52
58
 
59
+ begin
60
+ @db.execute("INSERT INTO role_#{@type} VALUES(?,?)", role_id, id(element))
61
+ rescue SQLite3::ConstraintException
62
+ next
63
+ end
64
+ end
53
65
 
54
- def attached?(index, element)
55
- return false if ! @elements.data.has_key?(index)
56
- @elements.data[index].include?(element)
66
+ end #end of transaction
67
+ end
57
68
  end
58
69
 
59
70
 
60
- def has_data?(index)
61
- return false if ! @elements.data.has_key?(index)
62
- @elements.data[index].size != 0
71
+ def detach_from_all(elements)
72
+ roles = []
73
+ details(elements).each do |e, r|
74
+ roles = roles.concat(r["role"]||[]).uniq
75
+ end
76
+
77
+ detach(elements, roles)
63
78
  end
64
79
 
65
80
 
66
- def indexes(element)
67
- return [] if ! @elements.data.values.flatten.include?(element)
68
- @elements.data.select {|index, elems|elems.include?(element)}.keys
69
- end
81
+ def detach(elements, roles)
82
+ elements = [elements] unless elements.is_a?(Array)
83
+ roles = [roles] unless roles.is_a?(Array)
70
84
 
85
+ roles.each do |role|
86
+ role_id = @role.id(role)
87
+ raise RoleExistenceException, "role does not exist - #{role}" if role_id.nil?
88
+
89
+ @db.transaction do
90
+
91
+ elements.each do |element|
92
+ @db.execute(
93
+ "DELETE FROM role_#{@type} WHERE role_id = ? AND #{@type}_id = ?",
94
+ role_id,
95
+ id(element)
96
+ )
97
+
98
+ begin
99
+ @db.execute("DELETE FROM #{@type} WHERE name = ?", element)
100
+ rescue SQLite3::ConstraintException, "foreign key constraint failed"
101
+ next
102
+ end
103
+ end
71
104
 
72
- def details(elements)
73
- result = {}
74
- elements.each do |element|
75
- result[element] = { 'role' => self.indexes(element).map {|index|Role.name(index)} }
105
+ end #end of transaction
76
106
  end
77
- result
78
107
  end
79
108
  end
80
109
  end
data/lib/houcho/host.rb CHANGED
@@ -1,22 +1,43 @@
1
+ require "houcho/element"
2
+ require "houcho/attribute"
3
+
1
4
  module Houcho
2
- class Host
3
- @elements = YamlHandle::Editor.new('./role/hosts.yaml')
4
- extend Element
5
+ class HostExistenceException < Exception; end
6
+
7
+ class Host < Element
8
+ include Houcho::Attribute
9
+
10
+ def initialize
11
+ super("host")
12
+ @type_id = 2
13
+ end
5
14
 
6
- def self.details(hosts)
15
+ def details(hosts)
16
+ hosts = hosts.is_a?(Array) ? hosts : [hosts]
7
17
  result = {}
8
18
 
9
19
  hosts.each do |host|
10
- roles = self.indexes(host).map {|index|Role.name(index)}
11
- cfroles = CloudForecast::Host.new.roles(host)
20
+ roles = super(host)[host]["role"]
21
+ outerroles = @db.execute("
22
+ SELECT role.name
23
+ FROM outerrole role, outerrole_host oh
24
+ WHERE role.id = oh.outerrole_id
25
+ AND oh.host_id = ?
26
+ ", id(host)).flatten.sort.uniq
12
27
 
13
- result[host] = {}
14
- result[host]['role'] = roles if ! roles.empty?
15
- result[host]['cf'] = cfroles if ! cfroles.empty?
28
+ result[host] = {}
29
+ result[host]["role"] = roles if ! roles.empty?
30
+ result[host]["outer role"] = outerroles if ! outerroles.empty?
16
31
 
17
32
  result.delete(host) if result[host].keys.empty?
18
33
  end
34
+
19
35
  result
20
36
  end
37
+
38
+ private
39
+ def raise_target_does_not_exist(target)
40
+ raise HostExistenceException, "host does not exist - #{target}"
41
+ end
21
42
  end
22
43
  end
@@ -0,0 +1,94 @@
1
+ require "houcho/config"
2
+ require "houcho/database"
3
+ require "yaml"
4
+
5
+ module Houcho
6
+
7
+ class OuterRole
8
+ class CloudForecast; end
9
+ class << CloudForecast
10
+ def load
11
+ cfdir = Houcho::Config::CFYAMLDIR
12
+
13
+ Dir::entries(cfdir).each do |file|
14
+ next if file !~ /\.yaml$/
15
+ yaml = "#{cfdir}/#{file}"
16
+ group = load_group(yaml)
17
+ cfrole = create_cf_role(yaml, group)
18
+
19
+ save_cf_role(cfrole)
20
+ end
21
+ end
22
+
23
+
24
+ private
25
+ def load_group(yaml)
26
+ group = []
27
+
28
+ File.open(yaml).each_line do |line|
29
+ next unless line =~ /^---/
30
+ if line =~ /^---\s+#(?<group>.+)\n/
31
+ group << $~[:group].gsub(/\s+/, "_")
32
+ else
33
+ group << "NOGROUP"
34
+ end
35
+ end
36
+
37
+ group
38
+ end
39
+
40
+
41
+ def create_cf_role(yaml, group)
42
+ cfrole = {}
43
+
44
+ YAML.load_stream(File.open(yaml)).each_with_index do |doc, i|
45
+ label = "NOLABEL"
46
+
47
+ doc["servers"].each do |servers|
48
+ label = servers["label"].gsub(/\s+/, '_') if servers["label"]
49
+ outerrole = "#{group[i]}::#{label}::#{servers["config"].sub(/\.yaml$/, "")}"
50
+ hosts = servers["hosts"].map { |host| host.split(/\s+/)[1] }
51
+
52
+ cfrole[outerrole] = hosts
53
+ end
54
+ end
55
+
56
+ cfrole
57
+ end
58
+
59
+
60
+ def save_cf_role(cfrole)
61
+ db = Houcho::Database.new.handle
62
+ db.transaction do
63
+
64
+ cfrole.each do |outerrole, hosts|
65
+ begin
66
+ db.execute("INSERT INTO outerrole(name, data_source) VALUES(?,?)", outerrole, "CloudForecast")
67
+ rescue SQLite3::ConstraintException, "column name is not unique"
68
+ ensure
69
+ outerrole_id = db.execute("SELECT id FROM outerrole WHERE name = ?", outerrole).flatten.first
70
+ end
71
+
72
+ hosts.each do |host|
73
+ begin
74
+ db.execute("INSERT INTO host(name) VALUES(?)", host)
75
+ rescue SQLite3::ConstraintException, "column name is not unique"
76
+ ensure
77
+ begin
78
+ db.execute(
79
+ "INSERT INTO outerrole_host(outerrole_id, host_id) VALUES(?,?)",
80
+ outerrole_id,
81
+ db.execute("SELECT id FROM host WHERE name = ?", host).flatten.first
82
+ )
83
+ rescue SQLite3::ConstraintException, "column name is not unique"
84
+ end
85
+ end
86
+ end
87
+ end
88
+
89
+ end #end of transaction
90
+ end
91
+ end
92
+ end
93
+
94
+ end