chef-workflow 0.1.1 → 0.2.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.
@@ -0,0 +1,72 @@
1
+ require 'chef-workflow/support/db'
2
+
3
+ module ChefWorkflow
4
+ class DatabaseSupport
5
+ class VMGroup
6
+ include Enumerable
7
+
8
+ def initialize(table_name, box_nil)
9
+ raise "Must provide a table name!" unless table_name
10
+ @table_name = table_name
11
+ @box_nil = box_nil
12
+ @db = ChefWorkflow::DatabaseSupport.instance
13
+ create_table
14
+ end
15
+
16
+ def [](key)
17
+ rows = @db.execute("select value from #{@table_name} where name=? order by id", [key])
18
+ if rows.count == 0
19
+ @box_nil ? [] : nil
20
+ else
21
+ rows.to_a.map { |x| Marshal.load(x.first) }
22
+ end
23
+ end
24
+
25
+ def []=(key, value)
26
+ delete(key)
27
+
28
+ return value if value.empty?
29
+
30
+ values = value.map { |x| Marshal.dump(x) }
31
+ value_string = ("(?, ?)," * values.count).chop
32
+
33
+ @db.execute("insert into #{@table_name} (name, value) values #{value_string}", values.map { |x| [key, x] }.flatten)
34
+ end
35
+
36
+ def keys
37
+ @db.execute("select distinct name from #{@table_name}").map(&:first)
38
+ end
39
+
40
+ def delete(key)
41
+ @db.execute("delete from #{@table_name} where name=?", [key])
42
+ end
43
+
44
+ def has_key?(key)
45
+ @db.execute("select count(*) from #{@table_name} where name=?", [key]).first.first.to_i > 0
46
+ end
47
+
48
+ def each
49
+ # XXX very slow, but fuck it
50
+ keys.each do |key|
51
+ yield key, self[key]
52
+ end
53
+ end
54
+
55
+ private
56
+
57
+ def create_table
58
+ @db.execute <<-EOF
59
+ create table if not exists #{@table_name} (
60
+ id integer not null primary key autoincrement,
61
+ name varchar(255) not null,
62
+ value text not null
63
+ )
64
+ EOF
65
+
66
+ @db.execute <<-EOF
67
+ create index if not exists #{@table_name}_name_index on #{@table_name} (name)
68
+ EOF
69
+ end
70
+ end
71
+ end
72
+ end
@@ -1,51 +1,53 @@
1
- #
2
- # mixin to assist with adding debug messages.
3
- #
4
- module DebugSupport
5
-
6
- CHEF_WORKFLOW_DEBUG_DEFAULT = 2
7
-
8
- #
9
- # Conditionally executes based on the level of debugging requested.
10
- #
11
- # `CHEF_WORKFLOW_DEBUG` in the environment is converted to an integer. This
12
- # integer is compared to the first argument. If it is higher than the first
13
- # argument, the block supplied will execute.
14
- #
15
- # Optionally, if there is a `else_block`, this block will be executed if the
16
- # condition is *not* met. This allows a slightly more elegant (if less ugly)
17
- # variant of dealing with the situation where if debugging is on, do one
18
- # thing, and if not, do something else.
19
- #
20
- # Examples:
1
+ module ChefWorkflow
21
2
  #
22
- # if_debug(1) do
23
- # $stderr.puts "Here's a debug message"
24
- # end
3
+ # mixin to assist with adding debug messages.
25
4
  #
26
- # This will print "here's a debug message" to standard error if debugging is
27
- # set to 1 or greater.
28
- #
29
- # do_thing = lambda { run_thing }
30
- # if_debug(2, &do_thing) do
31
- # $stderr.puts "Doing this thing"
32
- # do_thing.call
33
- # end
34
- #
35
- # If debugging is set to 2 or higher, "Doing this thing" will be printed to
36
- # standard error and then `run_thing` will be executed. If lower than 2 or
37
- # off, will just execute `run_thing`.
38
- #
39
- def if_debug(minimum=1, else_block=nil)
40
- $CHEF_WORKFLOW_DEBUG ||=
41
- ENV.has_key?("CHEF_WORKFLOW_DEBUG") ?
42
- ENV["CHEF_WORKFLOW_DEBUG"].to_i :
43
- CHEF_WORKFLOW_DEBUG_DEFAULT
5
+ module DebugSupport
6
+
7
+ CHEF_WORKFLOW_DEBUG_DEFAULT = 2
8
+
9
+ #
10
+ # Conditionally executes based on the level of debugging requested.
11
+ #
12
+ # `CHEF_WORKFLOW_DEBUG` in the environment is converted to an integer. This
13
+ # integer is compared to the first argument. If it is higher than the first
14
+ # argument, the block supplied will execute.
15
+ #
16
+ # Optionally, if there is a `else_block`, this block will be executed if the
17
+ # condition is *not* met. This allows a slightly more elegant (if less ugly)
18
+ # variant of dealing with the situation where if debugging is on, do one
19
+ # thing, and if not, do something else.
20
+ #
21
+ # Examples:
22
+ #
23
+ # if_debug(1) do
24
+ # $stderr.puts "Here's a debug message"
25
+ # end
26
+ #
27
+ # This will print "here's a debug message" to standard error if debugging is
28
+ # set to 1 or greater.
29
+ #
30
+ # do_thing = lambda { run_thing }
31
+ # if_debug(2, &do_thing) do
32
+ # $stderr.puts "Doing this thing"
33
+ # do_thing.call
34
+ # end
35
+ #
36
+ # If debugging is set to 2 or higher, "Doing this thing" will be printed to
37
+ # standard error and then `run_thing` will be executed. If lower than 2 or
38
+ # off, will just execute `run_thing`.
39
+ #
40
+ def if_debug(minimum=1, else_block=nil)
41
+ $CHEF_WORKFLOW_DEBUG ||=
42
+ ENV.has_key?("CHEF_WORKFLOW_DEBUG") ?
43
+ ENV["CHEF_WORKFLOW_DEBUG"].to_i :
44
+ CHEF_WORKFLOW_DEBUG_DEFAULT
44
45
 
45
- if $CHEF_WORKFLOW_DEBUG >= minimum
46
- yield if block_given?
47
- elsif else_block
48
- else_block.call
46
+ if $CHEF_WORKFLOW_DEBUG >= minimum
47
+ yield if block_given?
48
+ elsif else_block
49
+ else_block.call
50
+ end
49
51
  end
50
52
  end
51
53
  end
@@ -4,167 +4,169 @@ require 'chef-workflow/support/general'
4
4
  require 'chef-workflow/support/debug'
5
5
  require 'chef-workflow/support/attr'
6
6
 
7
- class EC2Support
8
- extend AttrSupport
9
- include DebugSupport
10
-
11
- fancy_attr :access_key_id
12
- fancy_attr :secret_access_key
13
- fancy_attr :ami
14
- fancy_attr :instance_type
15
- fancy_attr :region
16
- fancy_attr :ssh_key
17
- fancy_attr :security_groups
18
- fancy_attr :security_group_open_ports
19
- fancy_attr :provision_wait
20
-
21
- def initialize
22
- self.security_groups :auto
23
- self.security_group_open_ports [22, 4000]
24
- self.provision_wait 300
25
- end
7
+ module ChefWorkflow
8
+ class EC2Support
9
+ extend ChefWorkflow::AttrSupport
10
+ include ChefWorkflow::DebugSupport
11
+
12
+ fancy_attr :access_key_id
13
+ fancy_attr :secret_access_key
14
+ fancy_attr :ami
15
+ fancy_attr :instance_type
16
+ fancy_attr :region
17
+ fancy_attr :ssh_key
18
+ fancy_attr :security_groups
19
+ fancy_attr :security_group_open_ports
20
+ fancy_attr :provision_wait
21
+
22
+ def initialize
23
+ self.security_groups :auto
24
+ self.security_group_open_ports [22, 4000]
25
+ self.provision_wait 300
26
+ end
26
27
 
27
- def ec2_obj
28
- args =
29
- if access_key_id and secret_access_key
30
- {
31
- :access_key_id => access_key_id,
32
- :secret_access_key => secret_access_key
33
- }
34
- else
35
- {
36
- :access_key_id => ENV["AWS_ACCESS_KEY_ID"],
37
- :secret_access_key => ENV["AWS_SECRET_ACCESS_KEY"]
38
- }
39
- end
28
+ def ec2_obj
29
+ args =
30
+ if access_key_id and secret_access_key
31
+ {
32
+ :access_key_id => access_key_id,
33
+ :secret_access_key => secret_access_key
34
+ }
35
+ else
36
+ {
37
+ :access_key_id => ENV["AWS_ACCESS_KEY_ID"],
38
+ :secret_access_key => ENV["AWS_SECRET_ACCESS_KEY"]
39
+ }
40
+ end
40
41
 
41
- ec2 = AWS::EC2.new(args)
42
- ec2.regions[region]
43
- end
42
+ ec2 = AWS::EC2.new(args)
43
+ ec2.regions[region]
44
+ end
44
45
 
45
- #
46
- # Only used if security_groups is set to auto. Returns the filename to
47
- # marshal the automatically created security groups to.
48
- #
49
- def security_group_setting_path
50
- File.join(GeneralSupport.singleton.workflow_dir, 'security-groups')
51
- end
46
+ #
47
+ # Only used if security_groups is set to auto. Returns the filename to
48
+ # marshal the automatically created security groups to.
49
+ #
50
+ def security_group_setting_path
51
+ File.join(ChefWorkflow::GeneralSupport.workflow_dir, 'security-groups')
52
+ end
53
+
54
+ #
55
+ # Creates a security group and saves it to the security_group_setting_path.
56
+ #
57
+ def create_security_group
58
+ aws_ec2 = ec2_obj
52
59
 
53
- #
54
- # Creates a security group and saves it to the security_group_setting_path.
55
- #
56
- def create_security_group
57
- aws_ec2 = ec2_obj
60
+ name = nil
58
61
 
59
- name = nil
62
+ loop do
63
+ name = 'chef-workflow-' + (0..rand(10).to_i).map { rand(0..9).to_s }.join("")
60
64
 
61
- loop do
62
- name = 'chef-workflow-' + (0..rand(10).to_i).map { rand(0..9).to_s }.join("")
65
+ if_debug(3) do
66
+ $stderr.puts "Seeing if security group name #{name} is taken"
67
+ end
63
68
 
64
- if_debug(3) do
65
- $stderr.puts "Seeing if security group name #{name} is taken"
69
+ break unless aws_ec2.security_groups[name].exists?
70
+ sleep 0.3
66
71
  end
67
72
 
68
- break unless aws_ec2.security_groups[name].exists?
69
- sleep 0.3
70
- end
73
+ group = aws_ec2.security_groups.create(name)
71
74
 
72
- group = aws_ec2.security_groups.create(name)
75
+ security_group_open_ports.each do |port|
76
+ group.authorize_ingress(:tcp, port)
77
+ group.authorize_ingress(:udp, port)
78
+ end
79
+
80
+ group.authorize_ingress(:tcp, (0..65535), group)
81
+ group.authorize_ingress(:udp, (0..65535), group)
73
82
 
74
- security_group_open_ports.each do |port|
75
- group.authorize_ingress(:tcp, port)
76
- group.authorize_ingress(:udp, port)
83
+ # XXX I think the name should be enough, but maybe this'll cause a problem.
84
+ File.binwrite(security_group_setting_path, Marshal.dump([name]))
85
+ return [name]
77
86
  end
78
87
 
79
- group.authorize_ingress(:tcp, (0..65535), group)
80
- group.authorize_ingress(:udp, (0..65535), group)
88
+ #
89
+ # Loads any stored security groups. Returns nil if it can't.
90
+ #
91
+ def load_security_group
92
+ Marshal.load(File.binread(security_group_setting_path)) rescue nil
93
+ end
81
94
 
82
- # XXX I think the name should be enough, but maybe this'll cause a problem.
83
- File.binwrite(security_group_setting_path, Marshal.dump([name]))
84
- return [name]
85
- end
95
+ #
96
+ # Ensures security groups exist.
97
+ #
98
+ # If @security_groups is :auto, creates one and sets it up with the
99
+ # security_group_open_ports on TCP and UDP.
100
+ #
101
+ # If @security_groups is an array of group names or a single group name,
102
+ # asserts they exist. If they do not exist, it raises.
103
+ #
104
+ def assert_security_groups
105
+ aws_ec2 = ec2_obj
106
+
107
+ if security_groups == :auto
108
+ loaded_groups = load_security_group
109
+
110
+ # this will make it hit the second block everytime from now on (and
111
+ # bootstrap it recursively)
112
+ if loaded_groups
113
+ self.security_groups loaded_groups
114
+ assert_security_groups
115
+ else
116
+ self.security_groups create_security_group
117
+ end
118
+ else
119
+ self.security_groups = [security_groups] unless security_groups.kind_of?(Array)
86
120
 
87
- #
88
- # Loads any stored security groups. Returns nil if it can't.
89
- #
90
- def load_security_group
91
- Marshal.load(File.binread(security_group_setting_path)) rescue nil
92
- end
121
+ self.security_groups.each do |group|
122
+ #
123
+ # just retry this until it works -- some stupid flexible proxy in aws-sdk will bark about a missing method otherwise.
124
+ #
93
125
 
94
- #
95
- # Ensures security groups exist.
96
- #
97
- # If @security_groups is :auto, creates one and sets it up with the
98
- # security_group_open_ports on TCP and UDP.
99
- #
100
- # If @security_groups is an array of group names or a single group name,
101
- # asserts they exist. If they do not exist, it raises.
102
- #
103
- def assert_security_groups
104
- aws_ec2 = ec2_obj
105
-
106
- if security_groups == :auto
107
- loaded_groups = load_security_group
108
-
109
- # this will make it hit the second block everytime from now on (and
110
- # bootstrap it recursively)
111
- if loaded_groups
112
- self.security_groups loaded_groups
113
- assert_security_groups
114
- else
115
- self.security_groups create_security_group
116
- end
117
- else
118
- self.security_groups = [security_groups] unless security_groups.kind_of?(Array)
119
-
120
- self.security_groups.each do |group|
121
- #
122
- # just retry this until it works -- some stupid flexible proxy in aws-sdk will bark about a missing method otherwise.
123
- #
124
-
125
- begin
126
- aws_ec2.security_groups[group]
127
- rescue
128
- sleep 1
129
- retry
130
- end
126
+ begin
127
+ aws_ec2.security_groups[group]
128
+ rescue
129
+ sleep 1
130
+ retry
131
+ end
131
132
 
132
- raise "EC2 security group #{group} does not exist and it should." unless aws_ec2.security_groups[group]
133
+ raise "EC2 security group #{group} does not exist and it should." unless aws_ec2.security_groups[group]
134
+ end
133
135
  end
134
136
  end
135
- end
136
137
 
137
- def find_secgroup_running_instances(group_name)
138
- # exponential complexity with API calls? NO PROBLEM
139
- ec2_obj.instances.select do |i|
140
- i.status != :terminated &&
141
- i.security_groups.find { |s| s.name == group_name }
138
+ def find_secgroup_running_instances(group_name)
139
+ # exponential complexity with API calls? NO PROBLEM
140
+ ec2_obj.instances.select do |i|
141
+ i.status != :terminated &&
142
+ i.security_groups.find { |s| s.name == group_name }
143
+ end
142
144
  end
143
- end
144
145
 
145
- def destroy_security_group
146
- if File.exist?(security_group_setting_path)
147
- group_name = Marshal.load(File.binread(security_group_setting_path)).first
146
+ def destroy_security_group
147
+ if File.exist?(security_group_setting_path)
148
+ group_name = Marshal.load(File.binread(security_group_setting_path)).first
148
149
 
149
- until (instances = find_secgroup_running_instances(group_name)).empty?
150
- if_debug(1) do
151
- $stderr.puts "Trying to destroy security group #{group_name}, but instances are still bound to it."
152
- $stderr.puts instances.map(&:id).inspect
153
- $stderr.puts "Terminating instances, sleeping, and trying again."
154
- end
155
-
156
- instances.each do |i|
157
- i.terminate rescue nil
150
+ until (instances = find_secgroup_running_instances(group_name)).empty?
151
+ if_debug(1) do
152
+ $stderr.puts "Trying to destroy security group #{group_name}, but instances are still bound to it."
153
+ $stderr.puts instances.map(&:id).inspect
154
+ $stderr.puts "Terminating instances, sleeping, and trying again."
155
+ end
156
+
157
+ instances.each do |i|
158
+ i.terminate rescue nil
159
+ end
160
+
161
+ sleep 10
158
162
  end
159
163
 
160
- sleep 10
164
+ ec2_obj.security_groups.find { |g| g.name == group_name }.delete
161
165
  end
162
-
163
- ec2_obj.security_groups.find { |g| g.name == group_name }.delete
164
166
  end
165
- end
166
167
 
167
- include GenericSupport
168
+ include ChefWorkflow::GenericSupport
169
+ end
168
170
  end
169
171
 
170
- EC2Support.configure
172
+ ChefWorkflow::EC2Support.configure