opendelivery 0.4.4 → 0.4.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- ODUxMWFiZTJmNzMwZWViZGEzNTA4OTU5ZjBjOWIyMmU2NWMzNjViZQ==
4
+ ZTgxZDRiNTAzYWFhNzE0ZDM1OGE3NGE1NDRjYjljYmE0OGUyYjZlYg==
5
5
  data.tar.gz: !binary |-
6
- NDdkNjRiZTcwNmRjNTgxZmRmNGYzYzhjNTEwOTI3ZGQyZDk2NjVjNQ==
6
+ MTUxODE0YzQ4YjdjODgyZWNlNGE5Y2ZiNWFkNmVjMWEzY2YwYjUzNg==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- MDVmNTkwMzU3Nzk1OGI3NzRhZTRkOWYxOGFlNTYyNDAxMjkyNTIyZDRiZWEw
10
- NzI3ZDA0ZTFlZTI1MDk2OWM5NDNjM2NmZGE3MzA1N2Y5OTFjMDkwMmIxZDky
11
- Nzc1OTUxMmU0ZmU3OThmYjVmYjAzZmM3YTBmYjI5NjRiY2YyODQ=
9
+ NmM4ZTdhNmZhNTcyYThjOWRkZjAyNjNhM2RhZjVmOTIxOWE2OTQyM2RmMDJh
10
+ OTRmMWJhMTJkZTQ5Y2M0NjU2MTg0MDY4ODkwY2M0NDc3NWE4ZTcxNjUyYWY4
11
+ MTIyMzdmNzNjOWMzMjZmNDg5Mjg5YWEyNzZhZWY1NjViN2ViYTY=
12
12
  data.tar.gz: !binary |-
13
- NzQzNjBmYWY1MjBlOWMxMDRkZjQ2MjU2NTcyZDRmMDc1NmQ2NjIyNTc1NWM4
14
- NzM5NTZhZGE5MzAyOGFiMmNhZWM0ZjI0ZjY3N2Y1NzM3NTFmNDYxMjk5NjE0
15
- ZGE2ZWVkOTYzODgyOWM5MzMxODAyNzhkY2U2OTk1MTA3YzU3YjA=
13
+ Y2VmNTU0NWFmMDE1ZThjODEzODdlMzU0NmZjNWJiY2IyNDkzZTk3NmI5NDY4
14
+ ZDU3NzA3NWJkZWE3Mzk5ZDEwOTA1N2NiZjc3ZDQzYzJhYzQ5MDllYzZhNzBh
15
+ MTAwZmE4ZjI3MDdkZjIzZTFiNzI1ODg0NDliMTM5MWJjOGFhMjI=
@@ -20,7 +20,7 @@
20
20
  #OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
21
  #THE SOFTWARE.
22
22
 
23
- require 'aws-sdk'
23
+ require 'aws-sdk-core'
24
24
  require 'encrypto_signo'
25
25
 
26
26
  module OpenDelivery
@@ -30,108 +30,67 @@ module OpenDelivery
30
30
  @key_path = File.read(key_path) unless key_path.nil?
31
31
 
32
32
  if region.nil?
33
- @sdb = AWS::SimpleDB.new
33
+ @sdb = Aws::SimpleDB::Client.new
34
34
  else
35
- @sdb = AWS::SimpleDB.new(:region => region)
35
+ @sdb = Aws::SimpleDB::Client.new(:region => region)
36
36
  end
37
37
  end
38
38
 
39
39
  def create(domain)
40
- AWS::SimpleDB.consistent_reads do
41
- @sdb.domains.create(domain)
42
- end
40
+ @sdb.create_domain(domain_name: domain)
43
41
  end
44
42
 
45
43
  def destroy(domain)
46
- AWS::SimpleDB.consistent_reads do
47
- @sdb.domains[domain].delete
48
- end
44
+ @sdb.delete_domain(domain_name: domain)
49
45
  end
50
46
 
51
47
  def destroy_item(domain, item_name)
52
- AWS::SimpleDB.consistent_reads do
53
- @sdb.domains[domain].items[item_name].delete
54
- end
48
+ @sdb.delete_attributes(domain_name: domain,
49
+ item_name: item_name)
55
50
  end
56
51
 
57
52
  def load_stack_properties(domain, stack)
58
- AWS::SimpleDB.consistent_reads do
59
- stack.resources.each do |resource|
60
- set_property(domain, stack.name, resource.resource_type, resource.physical_resource_id)
61
- end
53
+ stack.resources.each do |resource|
54
+ set_property(domain,
55
+ stack.name,
56
+ resource.resource_type,
57
+ resource.physical_resource_id)
62
58
  end
63
59
  end
64
60
 
65
- def get_encrypted_property(domain, item_name, key, index=0, name=nil)
66
- value = get_property(domain, item_name, key, index, name)
67
- decrypted_value = EncryptoSigno.decrypt(@key_path, value.chomp)
61
+ def get_encrypted_property(domain, item_name, key)
62
+ value = get_property(domain, item_name, key)
63
+ EncryptoSigno.decrypt(@key_path, value.chomp)
68
64
  end
69
65
 
70
- # Look for AWS::Some:Type|MyItemName or just AWS::Some::Type.
71
-
72
- def get_property(domain, item_name, key, index=0, name=nil)
73
- property_value = nil
74
- attribute = nil
75
-
76
- AWS::SimpleDB.consistent_reads do
77
- item = @sdb.domains[domain].items[item_name]
78
- if !item.nil?
79
- item.attributes.each do |att|
80
- col_name = nil
81
-
82
- att_array = att.name.split('|')
83
- col_title = att_array.first
84
-
85
- if att_array.length > 1
86
- col_name = att_array[1]
87
- end
66
+ def get_property(domain, item_name, key)
67
+ get_attributes_response = @sdb.get_attributes(domain_name: domain,
68
+ item_name: item_name,
69
+ attribute_names: [key],
70
+ consistent_read: true)
88
71
 
89
- if col_title == key
90
- # Found a column with first portion that matches our search 'key'
91
- # Now, determine if we need to match the "|name" name criteria.
92
-
93
- if name.nil?
94
- # Not given a name to search for, just return the first one
95
- # we have found.
96
- attribute = att
97
- break
98
- else
99
-
100
- # Give a 'name' search criteria, so match it against this column
101
- if name == col_name
102
- # 'name' criteria matches "|name" value, found a match
103
- attribute = att
104
- break
105
- else
106
- # 'name' criteria did not match, keep searching
107
- end
108
-
109
- end
110
- end
111
- end
112
- if !attribute.nil?
113
- value = attribute.values[index]
114
- if !value.nil?
115
- property_value = value.chomp
116
- end
117
- end
118
- end
72
+ if get_attributes_response.attributes.empty?
73
+ nil
74
+ else
75
+ get_attributes_response.attributes.first.value.chomp
119
76
  end
120
- return property_value
121
77
  end
122
78
 
123
- def set_encrypted_property(domain, item_name, key, value, name=nil)
79
+ def set_encrypted_property(domain, item_name, key, value)
124
80
  encrypted_value = EncryptoSigno.encrypt(@key_path, value.chomp)
125
- set_property(domain, item_name, key, encrypted_value, name)
81
+ set_property(domain, item_name, key, encrypted_value)
126
82
  end
127
83
 
128
- def set_property(domain, item_name, key, value, name=nil)
129
- if name then key = key + "|" + name end
130
-
131
- AWS::SimpleDB.consistent_reads do
132
- item = @sdb.domains[domain].items[item_name]
133
- item.attributes.set(key => [value])
134
- end
84
+ def set_property(domain, item_name, key, value)
85
+ @sdb.put_attributes(domain_name: domain,
86
+ item_name: item_name,
87
+ attributes: [
88
+ {
89
+ name: key,
90
+ value: value,
91
+ replace: true,
92
+ }
93
+ ])
135
94
  end
136
95
 
137
96
  def load_domain(domain, json_file)
@@ -140,9 +99,15 @@ module OpenDelivery
140
99
 
141
100
  obj.each do |item, attributes|
142
101
  attributes.each do |key,value|
143
- AWS::SimpleDB.consistent_reads do
144
- @sdb.domains[domain].items[item].attributes.set(key => [value])
145
- end
102
+ @sdb.put_attributes(domain_name: domain,
103
+ item_name: item,
104
+ attributes: [
105
+ {
106
+ name: key,
107
+ value: value,
108
+ replace: true,
109
+ }
110
+ ])
146
111
  end
147
112
  end
148
113
  end
data/lib/opendelivery.rb CHANGED
@@ -20,12 +20,7 @@
20
20
  #OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
21
  #THE SOFTWARE.
22
22
 
23
- require 'opendelivery/source_control.rb'
24
23
  require 'opendelivery/domain.rb'
25
- require 'opendelivery/machine_image.rb'
26
- require 'opendelivery/stack.rb'
27
- require 'opendelivery/storage.rb'
28
-
29
24
 
30
25
  module OpenDelivery
31
26
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: opendelivery
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.4
4
+ version: 0.4.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian Jakovich
@@ -83,33 +83,33 @@ dependencies:
83
83
  - !ruby/object:Gem::Version
84
84
  version: 2.9.0
85
85
  - !ruby/object:Gem::Dependency
86
- name: encrypto_signo
86
+ name: aws-sdk
87
87
  requirement: !ruby/object:Gem::Requirement
88
88
  requirements:
89
- - - '='
89
+ - - ~>
90
90
  - !ruby/object:Gem::Version
91
- version: 1.0.0
92
- type: :runtime
91
+ version: '1.0'
92
+ type: :development
93
93
  prerelease: false
94
94
  version_requirements: !ruby/object:Gem::Requirement
95
95
  requirements:
96
- - - '='
96
+ - - ~>
97
97
  - !ruby/object:Gem::Version
98
- version: 1.0.0
98
+ version: '1.0'
99
99
  - !ruby/object:Gem::Dependency
100
- name: aws-sdk
100
+ name: encrypto_signo
101
101
  requirement: !ruby/object:Gem::Requirement
102
102
  requirements:
103
- - - ~>
103
+ - - '='
104
104
  - !ruby/object:Gem::Version
105
- version: '1.0'
105
+ version: 1.0.0
106
106
  type: :runtime
107
107
  prerelease: false
108
108
  version_requirements: !ruby/object:Gem::Requirement
109
109
  requirements:
110
- - - ~>
110
+ - - '='
111
111
  - !ruby/object:Gem::Version
112
- version: '1.0'
112
+ version: 1.0.0
113
113
  - !ruby/object:Gem::Dependency
114
114
  name: aws-sdk-core
115
115
  requirement: !ruby/object:Gem::Requirement
@@ -146,11 +146,6 @@ extra_rdoc_files: []
146
146
  files:
147
147
  - lib/opendelivery.rb
148
148
  - lib/opendelivery/domain.rb
149
- - lib/opendelivery/machine_image.rb
150
- - lib/opendelivery/source_control.rb
151
- - lib/opendelivery/stack.rb
152
- - lib/opendelivery/storage.rb
153
- - lib/opsworks.rb
154
149
  homepage: http://stelligent.com
155
150
  licenses:
156
151
  - MIT
@@ -164,7 +159,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
164
159
  requirements:
165
160
  - - ! '>='
166
161
  - !ruby/object:Gem::Version
167
- version: 1.9.3
162
+ version: 2.0.0
168
163
  required_rubygems_version: !ruby/object:Gem::Requirement
169
164
  requirements:
170
165
  - - ! '>='
@@ -1,78 +0,0 @@
1
- #Copyright (c) 2014 Stelligent Systems LLC
2
- #
3
- #MIT LICENSE
4
- #
5
- #Permission is hereby granted, free of charge, to any person obtaining a copy
6
- #of this software and associated documentation files (the "Software"), to deal
7
- #in the Software without restriction, including without limitation the rights
8
- #to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- #copies of the Software, and to permit persons to whom the Software is
10
- #furnished to do so, subject to the following conditions:
11
- #
12
- #The above copyright notice and this permission notice shall be included in
13
- #all copies or substantial portions of the Software.
14
- #
15
- #THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- #IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- #FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- #AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- #LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- #OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
- #THE SOFTWARE.
22
-
23
- require 'aws-sdk'
24
-
25
- module OpenDelivery
26
- class MachineImage
27
-
28
- def initialize(region=nil)
29
- if region.nil?
30
- @ec2 = AWS::EC2.new
31
- @sdb = AWS::SimpleDB.new
32
- @auto_scale = AWS::AutoScaling.new
33
- @domain = OpenDelivery::Domain.new
34
- else
35
- @ec2 = AWS::EC2.new(:region => region)
36
- @sdb = AWS::SimpleDB.new(:region => region)
37
- @auto_scale = AWS::AutoScaling.new(:region => region)
38
- @domain = OpenDelivery::Domain.new(:region => region)
39
- end
40
- end
41
-
42
- def create(domain, stack_name)
43
- instance_id = prep_instance(domain, stack_name)
44
- image = @ec2.images.create(
45
- instance_id: instance_id,
46
- name: image_name)
47
-
48
- wait_for_image(image)
49
- end
50
-
51
- protected
52
-
53
- def wait_for_image(image)
54
- # Waiting for AWS to realize the image is ready to start
55
- sleep 10
56
-
57
- while image.state != :available
58
- sleep 10
59
- case image.state
60
- when :failed
61
- image.delete
62
- raise RuntimeError, 'Image Creation Failed'
63
- end
64
- end
65
- end
66
-
67
- def prep_instance(domain, stack_name)
68
- group_name = @domain.get_property(domain, stack_name, "AWS::AutoScaling::AutoScalingGroup")
69
- instance = @auto_scale.groups[group_name].auto_scaling_instances.first.id
70
- @ec2.instances[instance].stop
71
-
72
- while @ec2.instances[instance].status != :stopped
73
- sleep 10
74
- end
75
- return instance
76
- end
77
- end
78
- end
@@ -1,101 +0,0 @@
1
- #Copyright (c) 2014 Stelligent Systems LLC
2
- #
3
- #MIT LICENSE
4
- #
5
- #Permission is hereby granted, free of charge, to any person obtaining a copy
6
- #of this software and associated documentation files (the "Software"), to deal
7
- #in the Software without restriction, including without limitation the rights
8
- #to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- #copies of the Software, and to permit persons to whom the Software is
10
- #furnished to do so, subject to the following conditions:
11
- #
12
- #The above copyright notice and this permission notice shall be included in
13
- #all copies or substantial portions of the Software.
14
- #
15
- #THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- #IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- #FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- #AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- #LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- #OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
- #THE SOFTWARE.
22
-
23
- module OpenDelivery
24
- class SourceControl
25
- def initialize(dir)
26
- @dir = dir
27
- end
28
-
29
- def log(lines=10)
30
- Dir.chdir(@dir) do
31
- `git log --stat -n #{lines}`
32
- end
33
- end
34
-
35
- def status
36
- Dir.chdir(@dir) do
37
- `git status -sb`
38
- end
39
- end
40
-
41
- def remove_missing_files(status)
42
- removed_files = []
43
- files = find_removed_files(status)
44
- files.each do |file|
45
- Dir.chdir(@dir) do
46
- removed_files << `git rm -rf #{file}`
47
- end
48
- end
49
- removed_files
50
- end
51
-
52
- def add(files)
53
- Dir.chdir(@dir) do
54
- `git add #{files} -v`
55
- end
56
- end
57
-
58
- def commit(message)
59
- Dir.chdir(@dir) do
60
- `git commit -m "#{message}"`
61
- end
62
- end
63
-
64
- def push
65
- Dir.chdir(@dir) do
66
- `git push`
67
- end
68
- end
69
-
70
- def pull
71
- Dir.chdir(@dir) do
72
- @result = `git pull`
73
- end
74
- if $?.to_i != 0
75
- raise "Your pull failed. Probably because of a merge conflict!"
76
- end
77
- @result
78
- end
79
-
80
- def conflicted(status)
81
- status.each_line do |stat|
82
- if stat.match(/^UU /) || stat.match(/^U /) || stat.match(/^U /)
83
- raise "You have file conflicts when trying to merge. Because this could end up horribly, we won't try to automatically fix these conflicts. Please go an manually merge the files!"
84
- end
85
- end
86
- end
87
-
88
- protected
89
-
90
-
91
- def find_removed_files(status)
92
- statuses = []
93
- status.each_line do |stat|
94
- if stat.match(/^ D /)
95
- statuses << stat.split[1]
96
- end
97
- end
98
- statuses
99
- end
100
- end
101
- end
@@ -1,177 +0,0 @@
1
- #Copyright (c) 2014 Stelligent Systems LLC
2
- #
3
- #MIT LICENSE
4
- #
5
- #Permission is hereby granted, free of charge, to any person obtaining a copy
6
- #of this software and associated documentation files (the "Software"), to deal
7
- #in the Software without restriction, including without limitation the rights
8
- #to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- #copies of the Software, and to permit persons to whom the Software is
10
- #furnished to do so, subject to the following conditions:
11
- #
12
- #The above copyright notice and this permission notice shall be included in
13
- #all copies or substantial portions of the Software.
14
- #
15
- #THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- #IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- #FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- #AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- #LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- #OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
- #THE SOFTWARE.
22
-
23
- require 'aws-sdk'
24
-
25
- module OpenDelivery
26
- class Stack
27
-
28
- def initialize(region=nil)
29
- if region.nil?
30
- @cfn = AWS::CloudFormation.new
31
- @autoscaling = AWS::AutoScaling.new
32
- else
33
- @autoscaling = AWS::AutoScaling.new(:region => region)
34
- @cfn = AWS::CloudFormation.new(:region => region)
35
- end
36
- @domain = OpenDelivery::Domain.new(region)
37
- end
38
-
39
-
40
- SUCCESS_STATUSES = [ "CREATE_COMPLETE",
41
- "UPDATE_COMPLETE" ]
42
-
43
- FAILURE_STATUSES = [ "CREATE_FAILED",
44
- "ROLLBACK_FAILED",
45
- "ROLLBACK_COMPLETE",
46
- "DELETE_FAILED",
47
- "UPDATE_ROLLBACK_FAILED",
48
- "UPDATE_ROLLBACK_COMPLETE",
49
- "DELETE_COMPLETE" ]
50
-
51
- PROGRESS_STATUSES = [ "CREATE_IN_PROGRESS",
52
- "ROLLBACK_IN_PROGRESS",
53
- "DELETE_IN_PROGRESS",
54
- "UPDATE_IN_PROGRESS",
55
- "UPDATE_COMPLETE_CLEANUP_IN_PROGRESS",
56
- "UPDATE_ROLLBACK_IN_PROGRESS",
57
- "UPDATE_ROLLBACK_COMPLETE_CLEANUP_IN_PROGRESS" ]
58
-
59
- def watch(stack_name, sleep_time, silent=false)
60
- success = false
61
- begin
62
- stack = @cfn.stacks[stack_name]
63
- success = watch_loop(stack, sleep_time, silent)
64
- rescue AWS::CloudFormation::Errors::ValidationError => msg
65
- print_status "Exception raised: #{msg}"
66
- success = false
67
- end
68
- return success
69
- end
70
-
71
-
72
- def create(stack_name, template, parameters = {}, wait=false, domain=nil, tags = {})
73
- @cfn.stacks.create(stack_name,
74
- File.open(template, "r").read,
75
- :parameters => parameters,
76
- :tags => tags,
77
- :capabilities => ["CAPABILITY_IAM"],
78
- :disable_rollback => true)
79
- end
80
-
81
- def destroy(stack_name, domain=nil, wait=false)
82
- stack = @cfn.stacks[stack_name]
83
- if stack.exists?
84
- resume_scaling_activities(stack_name)
85
- stack.delete
86
- while wait and stack.exists?
87
- sleep 20
88
- end
89
- @domain.destroy_item(domain, stack_name)
90
- else
91
- raise "Stack: #{stack_name} doesn't exist, therefore it cannot be destroyed"
92
- end
93
- end
94
-
95
- def list
96
- @cfn.stacks.each do |stack|
97
- puts "Stack Name: #{stack.name} | Status: #{stack.status}"
98
- end
99
- end
100
-
101
- def resume_scaling_activities(stack_name)
102
- stack = @cfn.stacks[stack_name]
103
- stack.resources.each do |resource|
104
- if resource.resource_type == "AWS::AutoScaling::AutoScalingGroup"
105
- begin
106
- @autoscaling.groups[resource.physical_resource_id].resume_all_processes
107
- rescue Exception => e
108
- puts "ASG operation failed with [#{e.message}]"
109
- end
110
- end
111
- end
112
- end
113
-
114
- protected
115
-
116
- def wait_for_stack(stack, wait)
117
- if wait
118
- while stack.status != "CREATE_COMPLETE"
119
- sleep 20
120
-
121
- if FAILURE_STATUSES.include? stack.status
122
- stack.delete
123
- end
124
- end
125
- end
126
- end
127
-
128
- def print_status(status, silent=false)
129
- timestamp = Time.now.strftime("%Y.%m.%d %H:%M:%S:%L")
130
- unless silent
131
- puts "#{timestamp}: #{status}"
132
- end
133
- end
134
-
135
- def watch_loop(stack, sleep_time, silent)
136
- keep_watching = true
137
- success = false
138
- abort_count = 10
139
- while(keep_watching) do
140
- begin
141
- stack_status = stack.status
142
- if (SUCCESS_STATUSES.include? stack_status)
143
- status = "Success: #{stack_status}"
144
- print_status(status, silent)
145
- success = true
146
- keep_watching = false
147
- elsif (PROGRESS_STATUSES.include? stack_status)
148
- status = "In Progress: #{stack_status}"
149
- print_status(status, silent)
150
- success = false
151
- keep_watching = true
152
- elsif (FAILURE_STATUSES.include? stack_status)
153
- status = "Failed: #{stack_status}"
154
- print_status(status, silent)
155
- success = false
156
- keep_watching = false
157
- else
158
- status = "didn't find #{stack_status} in the list of expected statuses"
159
- print_status(status, silent)
160
- success = false
161
- abort_count = abort_count - 1
162
- # if we get too many unknown statuses, assume something has gone horribly wrong and quit.
163
- keep_watching = (abort_count > 0)
164
- end
165
- rescue AWS::CloudFormation::Errors::Throttling
166
- status = "Rate limit exceeded, retrying..."
167
- print_status(status, silent)
168
- sleep(sleep_time * 0.1)
169
- end
170
- if keep_watching
171
- sleep(sleep_time)
172
- end
173
- end
174
- return success
175
- end
176
- end
177
- end
@@ -1,74 +0,0 @@
1
- #Copyright (c) 2014 Stelligent Systems LLC
2
- #
3
- #MIT LICENSE
4
- #
5
- #Permission is hereby granted, free of charge, to any person obtaining a copy
6
- #of this software and associated documentation files (the "Software"), to deal
7
- #in the Software without restriction, including without limitation the rights
8
- #to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- #copies of the Software, and to permit persons to whom the Software is
10
- #furnished to do so, subject to the following conditions:
11
- #
12
- #The above copyright notice and this permission notice shall be included in
13
- #all copies or substantial portions of the Software.
14
- #
15
- #THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- #IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- #FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- #AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- #LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- #OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
- #THE SOFTWARE.
22
-
23
- require 'aws-sdk'
24
-
25
- module OpenDelivery
26
- class Storage
27
-
28
- def initialize(region=nil)
29
- if region.nil?
30
- @s3 = AWS::S3.new
31
- else
32
- @s3 = AWS::S3.new(:region => region)
33
- end
34
- end
35
-
36
- def copy(bucket, key, desired_key)
37
- @s3.buckets[bucket].objects[key].copy_to(desired_key)
38
- end
39
-
40
- def upload(bucket, file, key)
41
- @s3.buckets[bucket].objects[key].write(:file => file)
42
- end
43
-
44
- def download(bucket, key, output_directory)
45
- # Puke if the bucket doesn't exist
46
- raise "Bucket #{bucket} doesn't exist" unless @s3.buckets[bucket].exists?
47
-
48
- # Puke if the key doesn't exist. This can cause problems with some bucket policies, so we catch and re-throw
49
- begin
50
- raise "File with key #{key} doesn't exist in bucket #{bucket}" unless @s3.buckets[bucket].objects[key].exists?
51
- rescue Exception => e
52
- raise "Exception [#{e.message}] occurred downloading key #{key} from bucket #{bucket}"
53
- end
54
-
55
- obj = @s3.buckets[bucket].objects[key]
56
-
57
- base = Pathname.new("#{obj.key}").basename
58
-
59
- Dir.mkdir(output_directory) unless File.exists?(output_directory)
60
-
61
- File.open("#{output_directory}/#{base}", 'wb') do |file|
62
- obj.read do |chunk|
63
- file.write(chunk)
64
- end
65
- end
66
- end
67
-
68
- def add_timestamp(identifier, artifact)
69
- timestamp = Time.now.strftime("%Y.%m.%d.%H.%M.%S.%L")
70
- stamped_artifact = "#{artifact}-#{identifier}-#{timestamp}"
71
- return stamped_artifact
72
- end
73
- end
74
- end
data/lib/opsworks.rb DELETED
@@ -1,320 +0,0 @@
1
- #Copyright (c) 2014 Stelligent Systems LLC
2
- #
3
- #MIT LICENSE
4
- #
5
- #Permission is hereby granted, free of charge, to any person obtaining a copy
6
- #of this software and associated documentation files (the "Software"), to deal
7
- #in the Software without restriction, including without limitation the rights
8
- #to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- #copies of the Software, and to permit persons to whom the Software is
10
- #furnished to do so, subject to the following conditions:
11
- #
12
- #The above copyright notice and this permission notice shall be included in
13
- #all copies or substantial portions of the Software.
14
- #
15
- #THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- #IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- #FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- #AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- #LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- #OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
- #THE SOFTWARE.
22
-
23
- require 'aws-sdk'
24
-
25
- module OpsWorks
26
-
27
- def create_and_launch_stack(stack_description)
28
- stack_id = create_stack(stack_description)
29
- launch_stack(stack_id)
30
- deploy_apps(stack_id)
31
- stack_id
32
- end
33
-
34
- def create_and_launch_stack_in_order(stack_description, layers_by_order)
35
- stack_id = create_stack(stack_description)
36
- launch_stack_in_order(stack_id, layers_by_order)
37
- deploy_apps(stack_id)
38
- stack_id
39
- end
40
-
41
- def create_stack(stack_description)
42
- opsworks_client = AWS::OpsWorks::Client::V20130218.new
43
-
44
- response = opsworks_client.create_stack(stack_description.stack_description)
45
- stack_id = response[:stack_id]
46
-
47
- wait_on_opsworks_sg_creation(stack_description.stack_description[:vpc_id]) if stack_description.stack_description[:vpc_id]
48
-
49
- layer_descriptions = stack_description.layer_descriptions
50
- layer_descriptions.each do |layer_description|
51
- layer_description[:layer][:stack_id] = stack_id
52
-
53
- response = opsworks_client.create_layer(layer_description[:layer])
54
- layer_id = response[:layer_id]
55
- layer_description[:layer][:layer_id] = layer_id
56
-
57
- layer_description[:instances].each do |instance_description|
58
- instance_description[:stack_id] = stack_id
59
- instance_description[:layer_ids] = [layer_id]
60
-
61
- save_off = instance_description[:extra_layers]
62
- instance_description.delete :extra_layers
63
- response = opsworks_client.create_instance(instance_description)
64
- instance_description[:instance_id] = response[:instance_id]
65
- instance_description[:extra_layers] = save_off
66
- end
67
- end
68
-
69
- layer_descriptions.each do |layer_description|
70
- layer_description[:instances].each do |instance_description|
71
- if instance_description[:extra_layers]
72
- instance_description[:extra_layers].each do |extra_layer_name|
73
- found_extra_layer = layer_descriptions.find { |desc| desc[:layer][:name] == extra_layer_name }
74
-
75
- raise "missing extra layer: #{extra_layer_name}" unless found_extra_layer
76
- instance_description[:layer_ids] << found_extra_layer[:layer][:layer_id]
77
- response = opsworks_client.update_instance(:instance_id => instance_description[:instance_id],
78
- :layer_ids => instance_description[:layer_ids])
79
- end
80
- end
81
- end
82
- end
83
-
84
- stack_description.app_descriptions.each do |app_description|
85
- app_description[:stack_id] = stack_id
86
- response = opsworks_client.create_app(app_description)
87
- end
88
-
89
- stack_id
90
- end
91
-
92
- def launch_stack(stack_id)
93
- opsworks_client = AWS::OpsWorks::Client::V20130218.new
94
-
95
- opsworks_client.start_stack(:stack_id => stack_id)
96
-
97
- wait_on_setup(stack_id)
98
-
99
- wait_on_all_configures(stack_id)
100
- end
101
-
102
-
103
- def launch_stack_in_order(stack_id, layers_by_order)
104
- opsworks_client = AWS::OpsWorks::Client::V20130218.new
105
-
106
- layers_by_order.each do |layer_names|
107
- layer_names.each do |layer_name|
108
-
109
- response = opsworks_client.describe_layers( :stack_id => stack_id)
110
- layer = response[:layers].find { |layer| layer[:shortname] == layer_name }
111
- raise "layer #{layer_name} not found in stack: #{stack_id}" if layer.nil?
112
-
113
- response = opsworks_client.describe_instances( :layer_id => layer[:layer_id])
114
- response[:instances].each do |instance|
115
- opsworks_client.start_instance( :instance_id => instance[:instance_id])
116
- end
117
- end
118
-
119
- layer_names.each do |layer_name|
120
- response = opsworks_client.describe_layers( :stack_id => stack_id)
121
- layer = response[:layers].find { |layer| layer[:shortname] == layer_name }
122
- raise "layer #{layer_name} not found in stack: #{stack_id}" if layer.nil?
123
-
124
- wait_on_layer_setup(layer[:layer_id])
125
- wait_on_layer_configures(layer[:layer_id])
126
- end
127
- end
128
- end
129
-
130
- def deploy_apps(stack_id)
131
- deployment_ids = []
132
- opsworks_client = AWS::OpsWorks::Client::V20130218.new
133
- response = opsworks_client.describe_apps(:stack_id => stack_id)
134
- response[:apps].each do |app|
135
-
136
- puts "DEPLOYING THE APP: #{app}"
137
- response = opsworks_client.create_deployment(:stack_id => stack_id,
138
- :app_id => app[:app_id],
139
- :command => {
140
- :name => 'deploy',
141
- :args => deployment_args_factory(app)
142
- })
143
- deployment_ids << response[:deployment_id]
144
- end
145
-
146
- max_attempts = 250
147
- num_attempts = 0
148
-
149
- deployments_complete = false
150
- until deployments_complete
151
- response = opsworks_client.describe_deployments(:deployment_ids => deployment_ids)
152
- deployments_complete = response[:deployments].inject(true) do |status, deployment|
153
- puts "Deployment status: #{deployment[:status]}"
154
-
155
- if deployment[:status] == 'failed'
156
- raise 'deployment failed'
157
- end
158
-
159
- status and (deployment[:status] == 'successful')
160
- end
161
- num_attempts += 1
162
- if num_attempts >= max_attempts
163
- raise 'stuck waiting on configure command max attempts'
164
- end
165
- sleep 10
166
- end
167
- deployment_ids
168
- end
169
-
170
- def discover_private_ips(stack_id, layer_name)
171
- opsworks_client = AWS::OpsWorks::Client::V20130218.new
172
- response = opsworks_client.describe_layers( :stack_id => stack_id)
173
- layer = response[:layers].find { |layer| layer[:name] == layer_name }
174
- raise "layer #{layer_name} not found in stack: #{stack_id}" if layer.nil?
175
-
176
- response = opsworks_client.describe_instances( :layer_id => layer[:layer_id] )
177
- response[:instances].collect { |instance| instance[:private_ip] }
178
- end
179
-
180
- def discover_public_ips(stack_id, layer_name)
181
- opsworks_client = AWS::OpsWorks::Client::V20130218.new
182
- response = opsworks_client.describe_layers( :stack_id => stack_id)
183
- layer = response[:layers].find { |layer| layer[:name] == layer_name }
184
- raise "layer #{layer_name} not found in stack: #{stack_id}" if layer.nil?
185
-
186
- response = opsworks_client.describe_instances( :layer_id => layer[:layer_id] )
187
- response[:instances].collect { |instance| instance[:public_ip] }
188
- end
189
-
190
- protected
191
-
192
- def deployment_args_factory(app)
193
- if app[:type] == 'rails'
194
- {
195
- 'migrate' => %w{true}
196
- }
197
- else
198
- {}
199
- end
200
- end
201
-
202
- private
203
-
204
- def wait_on_opsworks_sg_creation(vpc_id)
205
- opsworks_security_group_names.each do |sg_name|
206
- while AWS.ec2.security_groups.filter('vpc-id', vpc_id).filter('group-name', sg_name).count == 0
207
- puts "Waiting on #{sg_name}, #{a = a ? a+1 : 1}"
208
- sleep 1
209
- end
210
- end
211
- end
212
-
213
- def opsworks_security_group_names
214
- %w{AWS-OpsWorks-Default-Server AWS-OpsWorks-Blank-Server AWS-OpsWorks-Custom-Server AWS-OpsWorks-Rails-App-Server AWS-OpsWorks-PHP-App-Server}
215
- end
216
-
217
-
218
- def complete(status)
219
- failure(status) or success(status)
220
- end
221
-
222
- def failure(status)
223
- %w{setup_failed start_failed terminated connection_lost}.include? status
224
- end
225
-
226
- def success(status)
227
- %w{online}.include? status
228
- end
229
-
230
- def wait_on_setup(stack_id)
231
- opsworks_client = AWS::OpsWorks::Client::V20130218.new
232
-
233
- setup_complete = false
234
- until setup_complete
235
- response = opsworks_client.describe_instances(:stack_id => stack_id)
236
- setup_complete = response[:instances].inject(true) do |status, instance|
237
- if failure(instance[:status])
238
- raise 'setup failed'
239
- end
240
-
241
- instance_status(instance)
242
-
243
- status and complete(instance[:status])
244
- end
245
- sleep 10
246
- end
247
- end
248
-
249
- def wait_on_layer_setup(layer_id)
250
- opsworks_client = AWS::OpsWorks::Client::V20130218.new
251
-
252
- setup_complete = false
253
- until setup_complete
254
- response = opsworks_client.describe_instances(:layer_id => layer_id)
255
- setup_complete = response[:instances].inject(true) do |status, instance|
256
- if failure(instance[:status])
257
- raise 'setup failed'
258
- end
259
-
260
- instance_status(instance)
261
-
262
- status and complete(instance[:status])
263
- end
264
- sleep 10
265
- end
266
- end
267
-
268
- def instance_status(instance)
269
- puts "Instance: #{instance[:instance_id]} has status #{instance[:status]}"
270
- end
271
-
272
- def configure_status(configure_command)
273
- puts "Configure command: #{configure_command}"
274
- end
275
-
276
- def wait_on_all_configures(stack_id)
277
- opsworks_client = AWS::OpsWorks::Client::V20130218.new
278
- response = opsworks_client.describe_instances(:stack_id => stack_id)
279
- response[:instances].each do |instance|
280
- wait_on_configure(instance[:instance_id])
281
- end
282
- end
283
-
284
- def wait_on_layer_configures(layer_id)
285
- opsworks_client = AWS::OpsWorks::Client::V20130218.new
286
- response = opsworks_client.describe_instances(:layer_id => layer_id)
287
- response[:instances].each do |instance|
288
- wait_on_configure(instance[:instance_id])
289
- end
290
- end
291
-
292
- def wait_on_configure(instance_id)
293
- opsworks_client = AWS::OpsWorks::Client::V20130218.new
294
-
295
- max_attempts = 250
296
- num_attempts = 0
297
-
298
- while true
299
- response = opsworks_client.describe_commands(:instance_id => instance_id)
300
- configure_command = response[:commands].find { |command| command[:type] == 'configure' }
301
-
302
- configure_status(configure_command)
303
-
304
- unless configure_command.nil?
305
- #i guess just bail if superseded, waiting on configure events is somewhat dubious after seeing more complex stacks in action anyway!
306
- if %w{successful superseded}.include? configure_command[:status]
307
- return
308
- elsif configure_command[:status] == 'failed'
309
- raise 'configure failed'
310
- end
311
- end
312
- num_attempts += 1
313
- if num_attempts >= max_attempts
314
- raise 'stuck waiting on configure command max attempts'
315
- end
316
- sleep 10
317
- end
318
- end
319
-
320
- end