itamae-mitsurin 0.9 → 0.10

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.
@@ -1,123 +1,88 @@
1
1
  require 'json'
2
2
  require 'highline'
3
+ require 'itamae-mitsurin/mitsurin/task_base'
3
4
  include Rake::DSL if defined? Rake::DSL
4
5
 
5
6
  module Itamae
6
7
  module Mitsurin
7
8
  class ServerspecTask
8
9
 
9
- class << self
10
+ TaskBase = ItamaeMitsurin::Mitsurin::TaskBase
10
11
 
11
- task :spec => 'spec:all'
12
- task :default => :spec
12
+ namespace :spec do
13
+ all = []
14
+ Dir.glob("tmp-nodes/**/*.json").each do |node_file|
13
15
 
14
- def self.get_roles(node_file)
15
- roles = []
16
- JSON.parse(File.read(node_file))['run_list'].each do |role|
17
- roles << role.gsub(/role\[(.+)\]/, '\1') if /role\[(.+)\]/ === role
18
- end
19
- roles
20
- end
16
+ file_name = File.basename(node_file, '.json')
17
+ node_attr = JSON.parse(File.read(node_file), symbolize_names: true)
21
18
 
22
- def self.get_recipes(role)
23
- recipes = []
24
- JSON.parse(File.read("roles/#{role}.json"))['run_list'].each do |recipe|
25
- if /recipe\[(.+)::(.+)\]/ === recipe
26
- recipes << {recipe.gsub(/recipe\[(.+)::(.+)\]/, '\1') => recipe.gsub(/recipe\[(.+)::(.+)\]/, '\2')}
27
- else
28
- recipes << {recipe.gsub(/recipe\[(.+)\]/, '\1') => nil}
29
- end
30
- end
31
- recipes
32
- end
19
+ desc "Spec to #{file_name}"
20
+ task node_attr[:environments][:hostname].split(".")[0] do
33
21
 
34
- def self.get_node_recipes(node_file)
35
- recipes = []
36
- JSON.parse(File.read(node_file))['run_list'].each do |recipe|
37
- if /recipe\[(.+)::(.+)\]/ === recipe
38
- recipes << {recipe.gsub(/recipe\[(.+)::(.+)\]/, '\1') => recipe.gsub(/recipe\[(.+)::(.+)\]/, '\2')}
39
- else
40
- recipes << {recipe.gsub(/recipe\[(.+)\]/, '\1') => nil} unless /role\[(.+)\]/ === recipe
22
+ begin
23
+ recipes = []
24
+ TaskBase.get_roles(node_file).each do |role|
25
+ recipes << TaskBase.get_recipes(role)
41
26
  end
42
- end
43
- recipes
44
- end
45
-
46
- hl = HighLine.new
47
-
48
- namespace :spec do
49
- all = []
50
- Dir.glob("tmp-nodes/**/*.json").each do |node_file|
51
-
52
- file_name = File.basename(node_file, '.json')
53
- node_attr = JSON.parse(File.read(node_file), symbolize_names: true)
54
-
55
- desc "Spec to #{file_name}"
56
- task node_attr[:environments][:hostname].split(".")[0] do
57
-
58
- begin
59
- recipes = []
60
- get_roles(node_file).each do |role|
61
- recipes << get_recipes(role)
62
- end
63
- get_node_recipes(node_file).each do |recipe|
64
- recipes << recipe
65
- end
66
- rescue Exception => e
67
- puts e.class.to_s + ", " + e.backtrace[0].to_s
68
- puts "nodefile or role error, nodefile:#{node_file} reason:#{e.message}"
69
- exit 1
70
- else
71
- recipes << {'_base' => nil}
72
- recipes.flatten!
27
+ TaskBase.get_node_recipes(node_file).each do |recipe|
28
+ recipes << recipe
73
29
  end
30
+ rescue Exception => e
31
+ puts e.class.to_s + ", " + e.backtrace[0].to_s
32
+ puts "nodefile or role error, nodefile:#{node_file} reason:#{e.message}"
33
+ exit 1
34
+ else
35
+ recipes << {'_base' => nil}
36
+ recipes.flatten!
37
+ end
74
38
 
75
- node_name = node_attr[:environments][:hostname]
76
- ssh_user = node_attr[:environments][:ssh_user]
77
- ssh_password = node_attr[:environments][:ssh_password]
78
- sudo_password = node_attr[:environments][:sudo_password]
79
- ssh_port = node_attr[:environments][:ssh_port]
80
- ssh_key = node_attr[:environments][:ssh_key]
39
+ node_name = node_attr[:environments][:hostname]
40
+ ssh_user = node_attr[:environments][:ssh_user]
41
+ ssh_password = node_attr[:environments][:ssh_password]
42
+ sudo_password = node_attr[:environments][:sudo_password]
43
+ ssh_port = node_attr[:environments][:ssh_port]
44
+ ssh_key = node_attr[:environments][:ssh_key]
81
45
 
82
- node_short = node_name.split(".")[0]
46
+ node_short = node_name.split(".")[0]
83
47
  all << node_short
84
48
 
85
49
  desc "Run spec to #{file_name}"
86
- ENV['TARGET_HOST'] = node_name
87
- ENV['NODE_FILE'] = node_file
88
- ENV['SSH_PASSWORD'] = ssh_password
89
- ENV['SUDO_PASSWORD'] = sudo_password
90
- ENV['SSH_KEY'] = "keys/#{ssh_key}"
91
- ENV['SSH_PORT'] = ssh_port
92
- ENV['SSH_USER'] = ssh_user
93
-
94
- specs = "bundle exec rspec"
95
-
96
- # recipe load to_spec
97
- spec_pattern = []
98
- recipes.each do |spec_h|
99
- if spec_h["#{spec_h.keys.join}"].nil?
100
- spec_pattern <<
101
- " #{Dir.glob("site-cookbooks/**/#{spec_h.keys.join}/spec/default_spec.rb").join}"
102
- else
103
- spec_pattern <<
104
- " #{Dir.glob("site-cookbooks/**/#{spec_h.keys.join}/spec/#{spec_h["#{spec_h.keys.join}"]}_spec.rb").join}"
105
- end
50
+ ENV['TARGET_HOST'] = node_name
51
+ ENV['NODE_FILE'] = node_file
52
+ ENV['SSH_PASSWORD'] = ssh_password
53
+ ENV['SUDO_PASSWORD'] = sudo_password
54
+ ENV['SSH_KEY'] = "keys/#{ssh_key}"
55
+ ENV['SSH_PORT'] = ssh_port
56
+ ENV['SSH_USER'] = ssh_user
57
+
58
+ specs = "bundle exec rspec"
59
+
60
+ # recipe load to_spec
61
+ spec_pattern = []
62
+ recipes.each do |spec_h|
63
+ if spec_h["#{spec_h.keys.join}"].nil?
64
+ spec_pattern <<
65
+ " #{Dir.glob("site-cookbooks/**/#{spec_h.keys.join}/spec/default_spec.rb").join}"
66
+ else
67
+ spec_pattern <<
68
+ " #{Dir.glob("site-cookbooks/**/#{spec_h.keys.join}/spec/#{spec_h["#{spec_h.keys.join}"]}_spec.rb").join}"
106
69
  end
107
- spec_pattern.sort_by! {|item| File.dirname(item)}
108
- specs << spec_pattern.join
109
- run_list_noti = []
110
- spec_pattern.each {|c_spec| run_list_noti << c_spec.split("/") [2]}
111
- puts hl.color(%!Run Serverspec to \"#{node_name}\"!, :red)
112
- puts hl.color(%!Run List to \"#{run_list_noti.uniq.join(", ")}\"!, :green)
113
- st = system specs
114
- exit 1 unless st
115
70
  end
116
- task :all => all
117
- task :default => :all
71
+
72
+ spec_pattern.sort_by! {|item| File.dirname(item)}
73
+ specs << spec_pattern.join
74
+ run_list_noti = []
75
+ spec_pattern.each {|c_spec| run_list_noti << c_spec.split("/") [2]}
76
+ puts TaskBase.hl.color(%!Run Serverspec to \"#{node_name}\"!, :red)
77
+ puts TaskBase.hl.color(%!Run List to \"#{run_list_noti.uniq.join(", ")}\"!, :green)
78
+ st = system specs
79
+ exit 1 unless st
118
80
  end
81
+ task :all => all
82
+ task :default => :all
119
83
  end
120
84
  end
85
+
121
86
  end
122
87
  end
123
88
  end
@@ -0,0 +1,72 @@
1
+
2
+ module ItamaeMitsurin
3
+ module Mitsurin
4
+ module TaskBase
5
+
6
+ class << self
7
+ class ::Hash
8
+ def deep_merge(other)
9
+ merger = lambda {|key, v1, v2| Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : v2}
10
+ self.merge(other, &merger)
11
+ end
12
+
13
+ def deep_merge!(other)
14
+ merger = lambda {|key, v1, v2| Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : v2}
15
+ self.merge!(other, &merger)
16
+ end
17
+ end
18
+
19
+ def get_roles(node_file)
20
+ roles = []
21
+ JSON.parse(File.read(node_file))['run_list'].each do |role|
22
+ roles << role.gsub(/role\[(.+)\]/, '\1') if /role\[(.+)\]/ === role
23
+ end
24
+ roles
25
+ end
26
+
27
+ def get_recipes(role)
28
+ recipes = []
29
+ JSON.parse(File.read("roles/#{role}.json"))['run_list'].each do |recipe|
30
+ if /recipe\[(.+)::(.+)\]/ === recipe
31
+ recipes << {recipe.gsub(/recipe\[(.+)::(.+)\]/, '\1') => recipe.gsub(/recipe\[(.+)::(.+)\]/, '\2')}
32
+ else
33
+ recipes << {recipe.gsub(/recipe\[(.+)\]/, '\1') => nil}
34
+ end
35
+ end
36
+ recipes
37
+ end
38
+
39
+ def get_node_recipes(node_file)
40
+ recipes = []
41
+ JSON.parse(File.read(node_file))['run_list'].each do |recipe|
42
+ if /recipe\[(.+)::(.+)\]/ === recipe
43
+ recipes << {recipe.gsub(/recipe\[(.+)::(.+)\]/, '\1') => recipe.gsub(/recipe\[(.+)::(.+)\]/, '\2')}
44
+ else
45
+ recipes << {recipe.gsub(/recipe\[(.+)\]/, '\1') => nil} unless /role\[(.+)\]/ === recipe
46
+ end
47
+ end
48
+ recipes
49
+ end
50
+
51
+ def jq(*objs)
52
+ par = nil
53
+ objs.each {|obj| par = JSON::pretty_generate(obj, :allow_nan => true, :max_nesting => false)}
54
+ return par
55
+ end
56
+
57
+ def write_json(filename)
58
+ File.open "tmp-nodes/#{filename}.json", 'w' do |f|
59
+ f.flock File::LOCK_EX
60
+ yield f
61
+ f.flock File::LOCK_UN
62
+ end
63
+ end
64
+
65
+ def hl
66
+ HighLine.new
67
+ end
68
+ end
69
+
70
+ end
71
+ end
72
+ end
@@ -19,6 +19,7 @@ require 'itamae-mitsurin/resource/gem_package'
19
19
  require 'itamae-mitsurin/resource/aws_ebs_volume'
20
20
  require 'itamae-mitsurin/resource/aws_route53_rrset'
21
21
  require 'itamae-mitsurin/resource/aws_route53_rrset_alias'
22
+ require 'itamae-mitsurin/resource/aws_ec2_instance'
22
23
 
23
24
  module ItamaeMitsurin
24
25
  module Resource
@@ -2,92 +2,85 @@ require 'itamae-mitsurin'
2
2
  require 'itamae-mitsurin/mitsurin'
3
3
 
4
4
  module ItamaeMitsurin
5
- module Resource
6
- class AwsEbsVolume < Base
7
- define_attribute :action, default: :create
8
- define_attribute :name, type: String, default_name: true
9
- define_attribute :region, type: String
10
- define_attribute :availability_zone, type: String
11
- define_attribute :device, type: String
12
- define_attribute :instance_id, type: String
13
- define_attribute :volume_type, type: String
14
- define_attribute :size, type: Integer
5
+ module Resource
6
+ class AwsEbsVolume < Base
15
7
 
16
- def action_create(options)
17
- ec2 = ::Aws::EC2::Client.new(region: attributes.region)
18
- volumes = ec2.describe_volumes(
8
+ define_attribute :action, default: :create
9
+ define_attribute :name, type: String, default_name: true
10
+ define_attribute :region, type: String
11
+ define_attribute :availability_zone, type: String
12
+ define_attribute :device, type: String
13
+ define_attribute :instance_id, type: String
14
+ define_attribute :volume_type, type: String
15
+ define_attribute :size, type: Integer
16
+
17
+ def action_create(options)
18
+ ec2 = ::Aws::EC2::Client.new(region: attributes.region)
19
+ volumes = ec2.describe_volumes({
20
+ filters: [
19
21
  {
20
- filters: [
21
- {
22
- name: 'tag:Name',
23
- values: [ attributes.name ],
24
- },
25
- ],
26
- }
27
- ).volumes
22
+ name: 'tag:Name',
23
+ values: [ attributes.name ],
24
+ },
25
+ ],
26
+ }).volumes
28
27
 
29
- if volumes.empty?
30
- @volume = ec2.create_volume(
31
- size: attributes[:size], # attributes.size returns the size of attributes hash
32
- availability_zone: attributes.availability_zone,
33
- volume_type: attributes.volume_type,
34
- )
35
- ec2.wait_until(:volume_available, volume_ids: [ @volume.volume_id ])
28
+ if volumes.empty?
29
+ @volume = ec2.create_volume(
30
+ size: attributes[:size], # attributes.size returns the size of attributes hash
31
+ availability_zone: attributes.availability_zone,
32
+ volume_type: attributes.volume_type,
33
+ )
34
+ ec2.wait_until(:volume_available, volume_ids: [ @volume.volume_id ])
36
35
 
37
- ec2.create_tags(
36
+ ec2.create_tags({
37
+ resources: [ @volume.volume_id ],
38
+ tags: [
38
39
  {
39
- resources: [ @volume.volume_id ],
40
- tags: [
41
- {
42
- key: 'Name',
43
- value: attributes.name,
44
- },
45
- ],
46
- }
47
- )
48
-
49
- ItamaeMitsurin.logger.color(:green) do
50
- ItamaeMitsurin.info "create volume compleated!"
51
- end
52
- updated!
53
- else
54
- @volume = volumes[0]
55
- end
40
+ key: 'Name',
41
+ value: attributes.name,
42
+ },
43
+ ],
44
+ })
56
45
 
46
+ ItamaeMitsurin.logger.color(:green) do
47
+ ItamaeMitsurin.info "create volume compleated!"
48
+ end
49
+ updated!
50
+ else
51
+ @volume = volumes[0]
57
52
  end
53
+ end
58
54
 
59
- def action_attach(options)
60
- ec2 = ::Aws::EC2::Client.new(region: attributes.region)
61
- volumes = ec2.describe_volumes(
55
+ def action_attach(options)
56
+ ec2 = ::Aws::EC2::Client.new(region: attributes.region)
57
+ volumes = ec2.describe_volumes({
58
+ filters: [
62
59
  {
63
- filters: [
64
- {
65
- name: 'tag:Name',
66
- values: [ attributes.name ],
67
- },
68
- ],
69
- }
70
- ).volumes
71
-
72
- unless volumes.empty?
73
- @volume = ec2.attach_volume({
74
- volume_id: @volume.volume_id,
75
- instance_id: attributes.instance_id,
76
- device: attributes.device
77
- })
78
- ec2.wait_until(:volume_in_use, volume_ids: [ @volume.volume_id ])
60
+ name: 'tag:Name',
61
+ values: [ attributes.name ],
62
+ },
63
+ ],
64
+ }).volumes
79
65
 
66
+ unless volumes.empty?
67
+ @volume = ec2.attach_volume({
68
+ volume_id: @volume.volume_id,
69
+ instance_id: attributes.instance_id,
70
+ device: attributes.device
71
+ })
72
+ ec2.wait_until(:volume_in_use, volume_ids: [ @volume.volume_id ])
80
73
 
81
- ItamaeMitsurin.logger.color(:green) do
82
- ItamaeMitsurin.info "attach volume compleated!"
83
- end
84
- updated!
85
- else
86
- @volume = volumes[0]
87
- end
88
74
 
75
+ ItamaeMitsurin.logger.color(:green) do
76
+ ItamaeMitsurin.info "attach volume compleated!"
77
+ end
78
+ updated!
79
+ else
80
+ @volume = volumes[0]
89
81
  end
90
82
  end
91
83
  end
84
+ end
92
85
  end
93
86
 
@@ -5,12 +5,12 @@ module ItamaeMitsurin
5
5
  module Resource
6
6
  class AwsEc2Instance < Base
7
7
 
8
- define_attribute :region, type: String
8
+ define_attribute :region, type: String, required: true
9
9
  define_attribute :action, default: :create
10
10
  define_attribute :dry_run, type: [TrueClass, FalseClass], default_name: false
11
11
  define_attribute :name, type: String, default_name: true
12
12
  define_attribute :image_id, type: String, required: true
13
- define_attribute :key_name, type: String, required: true
13
+ define_attribute :key_name, type: String
14
14
  define_attribute :security_group_ids, type: Array
15
15
  define_attribute :user_data, type: String
16
16
  define_attribute :instance_type, type: String, required: true
@@ -18,11 +18,11 @@ module ItamaeMitsurin
18
18
  define_attribute :ramdisk_id, type: String
19
19
  define_attribute :device_name, type: String
20
20
  define_attribute :snapshot_id, type: String
21
- define_attribute :volume_size, type: Integer
21
+ define_attribute :volume_size, type: Integer, required: true
22
22
  define_attribute :delete_on_termination, type: [TrueClass, FalseClass], default: true
23
23
  define_attribute :volume_type, type: String, default: "gp2"
24
24
  define_attribute :iops, type: Integer
25
- define_attribute :encrypted, type: [TrueClass, FalseClass]
25
+ define_attribute :encrypted, type: TrueClass
26
26
  define_attribute :monitoring, type: [TrueClass, FalseClass], default: false
27
27
  define_attribute :subnet_id, type: String
28
28
  define_attribute :disable_api_termination, type: [TrueClass, FalseClass], default: false
@@ -32,7 +32,7 @@ module ItamaeMitsurin
32
32
  define_attribute :additional_info, type: String
33
33
  define_attribute :network_interface_id, type: String
34
34
  define_attribute :device_index, type: String
35
- define_attribute :subnet_id, type: String
35
+ define_attribute :subnet_id, type: String, required: true
36
36
  define_attribute :private_ip_address, type: String
37
37
  define_attribute :groups, type: Array
38
38
  define_attribute :private_ip_address, type: String