houcho 0.0.6 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
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