ec2_amitools 1.0.2
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.
- checksums.yaml +7 -0
- data/README.md +54 -0
- data/bin/console +14 -0
- data/bin/ec2-ami-tools-version +6 -0
- data/bin/ec2-bundle-image +6 -0
- data/bin/ec2-bundle-vol +6 -0
- data/bin/ec2-delete-bundle +6 -0
- data/bin/ec2-download-bundle +6 -0
- data/bin/ec2-migrate-bundle +6 -0
- data/bin/ec2-migrate-manifest +6 -0
- data/bin/ec2-unbundle +6 -0
- data/bin/ec2-upload-bundle +6 -0
- data/bin/setup +8 -0
- data/etc/ec2/amitools/cert-ec2-cn-north-1.pem +28 -0
- data/etc/ec2/amitools/cert-ec2-gov.pem +17 -0
- data/etc/ec2/amitools/cert-ec2.pem +23 -0
- data/etc/ec2/amitools/mappings.csv +9 -0
- data/lib/ec2/amitools/bundle.rb +251 -0
- data/lib/ec2/amitools/bundle_base.rb +58 -0
- data/lib/ec2/amitools/bundleimage.rb +94 -0
- data/lib/ec2/amitools/bundleimageparameters.rb +42 -0
- data/lib/ec2/amitools/bundlemachineparameters.rb +60 -0
- data/lib/ec2/amitools/bundleparameters.rb +120 -0
- data/lib/ec2/amitools/bundlevol.rb +240 -0
- data/lib/ec2/amitools/bundlevolparameters.rb +164 -0
- data/lib/ec2/amitools/crypto.rb +379 -0
- data/lib/ec2/amitools/decryptmanifest.rb +20 -0
- data/lib/ec2/amitools/defaults.rb +12 -0
- data/lib/ec2/amitools/deletebundle.rb +212 -0
- data/lib/ec2/amitools/deletebundleparameters.rb +78 -0
- data/lib/ec2/amitools/downloadbundle.rb +161 -0
- data/lib/ec2/amitools/downloadbundleparameters.rb +84 -0
- data/lib/ec2/amitools/exception.rb +86 -0
- data/lib/ec2/amitools/fileutil.rb +219 -0
- data/lib/ec2/amitools/format.rb +127 -0
- data/lib/ec2/amitools/instance-data.rb +97 -0
- data/lib/ec2/amitools/manifest_wrapper.rb +132 -0
- data/lib/ec2/amitools/manifestv20070829.rb +361 -0
- data/lib/ec2/amitools/manifestv20071010.rb +403 -0
- data/lib/ec2/amitools/manifestv3.rb +331 -0
- data/lib/ec2/amitools/mapids.rb +148 -0
- data/lib/ec2/amitools/migratebundle.rb +222 -0
- data/lib/ec2/amitools/migratebundleparameters.rb +173 -0
- data/lib/ec2/amitools/migratemanifest.rb +225 -0
- data/lib/ec2/amitools/migratemanifestparameters.rb +118 -0
- data/lib/ec2/amitools/minimalec2.rb +116 -0
- data/lib/ec2/amitools/parameter_exceptions.rb +34 -0
- data/lib/ec2/amitools/parameters_base.rb +168 -0
- data/lib/ec2/amitools/region.rb +93 -0
- data/lib/ec2/amitools/s3toolparameters.rb +183 -0
- data/lib/ec2/amitools/showversion.rb +12 -0
- data/lib/ec2/amitools/syschecks.rb +27 -0
- data/lib/ec2/amitools/tool_base.rb +224 -0
- data/lib/ec2/amitools/unbundle.rb +107 -0
- data/lib/ec2/amitools/unbundleparameters.rb +65 -0
- data/lib/ec2/amitools/uploadbundle.rb +361 -0
- data/lib/ec2/amitools/uploadbundleparameters.rb +108 -0
- data/lib/ec2/amitools/util.rb +532 -0
- data/lib/ec2/amitools/version.rb +33 -0
- data/lib/ec2/amitools/xmlbuilder.rb +237 -0
- data/lib/ec2/amitools/xmlutil.rb +55 -0
- data/lib/ec2/common/constants.rb +16 -0
- data/lib/ec2/common/curl.rb +110 -0
- data/lib/ec2/common/headers.rb +95 -0
- data/lib/ec2/common/headersv4.rb +173 -0
- data/lib/ec2/common/http.rb +333 -0
- data/lib/ec2/common/s3support.rb +231 -0
- data/lib/ec2/common/signature.rb +68 -0
- data/lib/ec2/oem/LICENSE.txt +58 -0
- data/lib/ec2/oem/open4.rb +399 -0
- data/lib/ec2/platform/base/architecture.rb +26 -0
- data/lib/ec2/platform/base/constants.rb +54 -0
- data/lib/ec2/platform/base/pipeline.rb +181 -0
- data/lib/ec2/platform/base.rb +57 -0
- data/lib/ec2/platform/current.rb +55 -0
- data/lib/ec2/platform/linux/architecture.rb +35 -0
- data/lib/ec2/platform/linux/constants.rb +23 -0
- data/lib/ec2/platform/linux/fstab.rb +99 -0
- data/lib/ec2/platform/linux/identity.rb +16 -0
- data/lib/ec2/platform/linux/image.rb +811 -0
- data/lib/ec2/platform/linux/mtab.rb +74 -0
- data/lib/ec2/platform/linux/pipeline.rb +40 -0
- data/lib/ec2/platform/linux/rsync.rb +114 -0
- data/lib/ec2/platform/linux/tar.rb +124 -0
- data/lib/ec2/platform/linux/uname.rb +50 -0
- data/lib/ec2/platform/linux.rb +83 -0
- data/lib/ec2/platform/solaris/architecture.rb +28 -0
- data/lib/ec2/platform/solaris/constants.rb +30 -0
- data/lib/ec2/platform/solaris/fstab.rb +43 -0
- data/lib/ec2/platform/solaris/identity.rb +16 -0
- data/lib/ec2/platform/solaris/image.rb +327 -0
- data/lib/ec2/platform/solaris/mtab.rb +29 -0
- data/lib/ec2/platform/solaris/pipeline.rb +40 -0
- data/lib/ec2/platform/solaris/rsync.rb +24 -0
- data/lib/ec2/platform/solaris/tar.rb +36 -0
- data/lib/ec2/platform/solaris/uname.rb +21 -0
- data/lib/ec2/platform/solaris.rb +38 -0
- data/lib/ec2/platform.rb +69 -0
- data/lib/ec2/version.rb +8 -0
- data/lib/ec2_amitools +1 -0
- data/lib/ec2_amitools.rb +7 -0
- metadata +184 -0
@@ -0,0 +1,33 @@
|
|
1
|
+
# Copyright 2008-2014 Amazon.com, Inc. or its affiliates. All Rights
|
2
|
+
# Reserved. Licensed under the Amazon Software License (the
|
3
|
+
# "License"). You may not use this file except in compliance with the
|
4
|
+
# License. A copy of the License is located at
|
5
|
+
# http://aws.amazon.com/asl or in the "license" file accompanying this
|
6
|
+
# file. This file is distributed on an "AS IS" BASIS, WITHOUT
|
7
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See
|
8
|
+
# the License for the specific language governing permissions and
|
9
|
+
# limitations under the License.
|
10
|
+
|
11
|
+
require 'ec2/amitools/manifestv20071010'
|
12
|
+
|
13
|
+
module EC2Version
|
14
|
+
MANIFEST_CLASS = ManifestV20071010
|
15
|
+
MANIFEST_VERSION = MANIFEST_CLASS.version
|
16
|
+
PKG_NAME = 'ec2-ami-tools'
|
17
|
+
PKG_VERSION = '1.5'
|
18
|
+
PKG_RELEASE = '7'
|
19
|
+
|
20
|
+
COPYRIGHT_NOTICE = <<CNOTICE
|
21
|
+
Copyright 2008-2014 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
22
|
+
Licensed under the Amazon Software License (the "License"). You may not use
|
23
|
+
this file except in compliance with the License. A copy of the License is
|
24
|
+
located at http://aws.amazon.com/asl or in the "license" file accompanying this
|
25
|
+
file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
26
|
+
CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
27
|
+
specific language governing permissions and limitations under the License.
|
28
|
+
CNOTICE
|
29
|
+
|
30
|
+
def self.version_copyright_string()
|
31
|
+
"#{PKG_VERSION}.#{PKG_RELEASE} #{MANIFEST_VERSION}\n\n" + COPYRIGHT_NOTICE + "\n"
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,237 @@
|
|
1
|
+
# Copyright 2008-2014 Amazon.com, Inc. or its affiliates. All Rights
|
2
|
+
# Reserved. Licensed under the Amazon Software License (the
|
3
|
+
# "License"). You may not use this file except in compliance with the
|
4
|
+
# License. A copy of the License is located at
|
5
|
+
# http://aws.amazon.com/asl or in the "license" file accompanying this
|
6
|
+
# file. This file is distributed on an "AS IS" BASIS, WITHOUT
|
7
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See
|
8
|
+
# the License for the specific language governing permissions and
|
9
|
+
# limitations under the License.
|
10
|
+
|
11
|
+
# This class makes it easy to build up xml docs, xpath style.
|
12
|
+
# Usage:
|
13
|
+
#
|
14
|
+
# # Create an XMLBuilder:
|
15
|
+
# doc = REXML::Document.new(some_xml)
|
16
|
+
# builder = XMLBuilder.new(doc)
|
17
|
+
# # Add some text elements
|
18
|
+
# builder[/book/title] = 'Atlas Shrugged'
|
19
|
+
# builder[/book/author] = 'Ann Raynd'
|
20
|
+
# # Add an attribute
|
21
|
+
# builder[/book/author@salutation] = 'Mrs.'
|
22
|
+
#
|
23
|
+
# Results in the following xml:
|
24
|
+
# <book>
|
25
|
+
# <title>Atlas Shrugged</title>
|
26
|
+
# <author salutation="Mrs.">Ann Raynd</author>
|
27
|
+
# </book>
|
28
|
+
#
|
29
|
+
# Notes on Usage:
|
30
|
+
# - If the path starts with a '/' the path is absolute.
|
31
|
+
# - If the path does not start with a '/' the path is relative.
|
32
|
+
# - When adding an element the return value is an xml builder object anchored at that path
|
33
|
+
# - When adding an attrubte the return value is ... ??? dunno what is should be. nil?
|
34
|
+
# - To set the element value use XMLBuilder[]=(string) or XMLBuilder[]=(XMLBuilder) or XMLBuilder[]=(node)
|
35
|
+
# - To add an element do builder[path] << string or builder[path] << element or builder[path] << node
|
36
|
+
# - If you assign a nil value the value will not be set and the path elements not created.
|
37
|
+
|
38
|
+
require 'rexml/document'
|
39
|
+
|
40
|
+
class XMLBuilder
|
41
|
+
|
42
|
+
attr_reader :root
|
43
|
+
|
44
|
+
# Create a new XMLBuilder rooted at the given element, or at a new document if no root is given
|
45
|
+
def initialize(root = nil)
|
46
|
+
@root = root || REXML::Document.new()
|
47
|
+
end
|
48
|
+
|
49
|
+
# Retrieve a builder for the element at the given path
|
50
|
+
def [](path)
|
51
|
+
nodes = PathParser.parse(path)
|
52
|
+
rexml_node = nodes.inject(@root) do |rexml_node, parser_node|
|
53
|
+
parser_node.walk_visit(rexml_node)
|
54
|
+
end
|
55
|
+
XMLBuilder.new(nodes.last.retrieve_visit(rexml_node))
|
56
|
+
end
|
57
|
+
|
58
|
+
# Set the value of the element or attribute at the given path
|
59
|
+
def []=(path, value)
|
60
|
+
# Don't create elements or make assignments for nil values
|
61
|
+
return if value.nil?
|
62
|
+
nodes = PathParser.parse(path)
|
63
|
+
rexml_node = nodes.inject(@root) do |rexml_node, parser_node|
|
64
|
+
parser_node.walk_visit(rexml_node)
|
65
|
+
end
|
66
|
+
nodes.last.assign_visit(rexml_node, value)
|
67
|
+
end
|
68
|
+
|
69
|
+
# Parses an xpath like expression
|
70
|
+
class PathParser
|
71
|
+
def PathParser.parse(path)
|
72
|
+
nodes = path.split('/')
|
73
|
+
@nodes = []
|
74
|
+
first = true
|
75
|
+
|
76
|
+
while (nodes.length > 0)
|
77
|
+
node = Node.new(first, nodes)
|
78
|
+
first = false
|
79
|
+
@nodes << Document.new() if node.document
|
80
|
+
@nodes << Element.new(node.element, node.index) if node.element
|
81
|
+
@nodes << Attribute.new(node.attribute) if node.attribute
|
82
|
+
end
|
83
|
+
@nodes
|
84
|
+
end
|
85
|
+
|
86
|
+
# Helper class used by PathParser
|
87
|
+
class Node
|
88
|
+
attr_reader :document
|
89
|
+
attr_reader :element
|
90
|
+
attr_reader :index
|
91
|
+
attr_reader :attribute
|
92
|
+
|
93
|
+
# Regex for parsing path if the form element[index]@attribute
|
94
|
+
# where [index] and @attribute are optional
|
95
|
+
@@attribute_regex = /^@(\w+)$/
|
96
|
+
@@node_regex = /^(\w+)(?:\[(\d+)\])?(?:@(\w+))?$/
|
97
|
+
|
98
|
+
# Nodes is path.split('/')
|
99
|
+
def initialize(allow_document, nodes)
|
100
|
+
if allow_document && nodes[0] == ''
|
101
|
+
@document = true
|
102
|
+
nodes.shift
|
103
|
+
return
|
104
|
+
end
|
105
|
+
nodes.shift while nodes[0] == ''
|
106
|
+
node = nodes.shift
|
107
|
+
if (match = @@node_regex.match(node))
|
108
|
+
@element = match[1]
|
109
|
+
@index = match[2].to_i || 0
|
110
|
+
elsif (match = @@attribute_regex.match(node))
|
111
|
+
@attribute = match[1]
|
112
|
+
else
|
113
|
+
raise 'Invalid path: Node must be of the form element[index] or @attribute' if document
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
# Node classes
|
119
|
+
# Each class represents a node type. An array of these classes is built up when
|
120
|
+
# the path is parsed. Each node is then visited by the current rexml node and
|
121
|
+
# (depending on which visit function is called) the action taken.
|
122
|
+
#
|
123
|
+
# The visit function are:
|
124
|
+
# - walk: Walks down the xml dom
|
125
|
+
# - assign: Assigns the value to rexml node
|
126
|
+
# - retrieve: Retrives the value of the rexml node
|
127
|
+
#
|
128
|
+
# Different node types implement different behaviour types. For example retrieve is
|
129
|
+
# illegal on Attribute nodes, but on Document and Attribute nodes the given node is returned.
|
130
|
+
|
131
|
+
class Document
|
132
|
+
def initialize()
|
133
|
+
end
|
134
|
+
|
135
|
+
# Move to the document node (top of the xml dom)
|
136
|
+
def walk_visit(rexml_node)
|
137
|
+
return rexml_node if rexml_node.is_a?(REXML::Document)
|
138
|
+
raise "No document set on node. #{rexml_node.name}" if rexml_node.document == nil
|
139
|
+
rexml_node.document
|
140
|
+
end
|
141
|
+
|
142
|
+
def assign_visit(document_node, value)
|
143
|
+
raise 'Can only assign REXML::Elements to document nodes' if !value.is_a?(REXML::Element)
|
144
|
+
raise 'Expected a document node' if !document_node.is_a?(REXML::Element)
|
145
|
+
if doc.root
|
146
|
+
doc.replace_child(doc.root, value)
|
147
|
+
else
|
148
|
+
doc.add_element(element)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
def retrieve_visit(document_node)
|
153
|
+
document_node
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
class Element
|
158
|
+
attr_reader :name
|
159
|
+
attr_reader :index
|
160
|
+
|
161
|
+
def initialize(name, index)
|
162
|
+
@name = name
|
163
|
+
@index = index
|
164
|
+
end
|
165
|
+
|
166
|
+
# Move one element down in the dom
|
167
|
+
def walk_visit(rexml_node)
|
168
|
+
elements = rexml_node.get_elements(name)
|
169
|
+
raise "Invalid index #{index} for element #{@name}" if @index > elements.length
|
170
|
+
# Create a node if it doesn't exist
|
171
|
+
if @index == elements.length
|
172
|
+
new_element = REXML::Element.new(@name)
|
173
|
+
rexml_node.add_element(new_element)
|
174
|
+
new_element
|
175
|
+
else
|
176
|
+
elements[@index]
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
def assign_visit(rexml_node, value)
|
181
|
+
if value.is_a?(String)
|
182
|
+
rexml_node.text = value
|
183
|
+
elsif value.is_a?(REXML::Element)
|
184
|
+
value.name = rexml_node.name
|
185
|
+
raise "Node #{rexml_node.name} does not have a parent node" if rexml_node.parent.nil?
|
186
|
+
rexml_node.parent.replace_child(rexml_node, value)
|
187
|
+
else
|
188
|
+
raise 'Can only assign a String or a REXML::Element to an element'
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
def retrieve_visit(rexml_node)
|
193
|
+
rexml_node
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
class Attribute
|
198
|
+
attr_reader :name
|
199
|
+
|
200
|
+
def initialize(name)
|
201
|
+
@name = name
|
202
|
+
end
|
203
|
+
|
204
|
+
# Stays on the same node in the dom
|
205
|
+
def walk_visit(rexml_node)
|
206
|
+
rexml_node
|
207
|
+
end
|
208
|
+
|
209
|
+
def assign_visit(rexml_node, value)
|
210
|
+
raise 'Can only assign an attribute to an element.' if !rexml_node.is_a?(REXML::Element)
|
211
|
+
rexml_node.attributes[@name] = value.to_s
|
212
|
+
end
|
213
|
+
|
214
|
+
def retrieve_visit(rexml_node)
|
215
|
+
raise 'Accessor not valid for paths with an attribute'
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
end
|
221
|
+
|
222
|
+
# Test code
|
223
|
+
if $0 == __FILE__
|
224
|
+
|
225
|
+
def assert_true(expr)
|
226
|
+
raise 'expected true' if !expr
|
227
|
+
end
|
228
|
+
|
229
|
+
doc = REXML::Document.new()
|
230
|
+
builder = XMLBuilder.new(doc)
|
231
|
+
root_builder = builder['/root']
|
232
|
+
root_builder['nested'] = 'more text'
|
233
|
+
root_builder['/root/bnode'] = 'name'
|
234
|
+
root_builder['/root/bnode/@attr'] = 'attr'
|
235
|
+
puts doc
|
236
|
+
end
|
237
|
+
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# Copyright 2008-2014 Amazon.com, Inc. or its affiliates. All Rights
|
2
|
+
# Reserved. Licensed under the Amazon Software License (the
|
3
|
+
# "License"). You may not use this file except in compliance with the
|
4
|
+
# License. A copy of the License is located at
|
5
|
+
# http://aws.amazon.com/asl or in the "license" file accompanying this
|
6
|
+
# file. This file is distributed on an "AS IS" BASIS, WITHOUT
|
7
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See
|
8
|
+
# the License for the specific language governing permissions and
|
9
|
+
# limitations under the License.
|
10
|
+
|
11
|
+
require 'rexml/document'
|
12
|
+
require 'stringio'
|
13
|
+
|
14
|
+
# Module containing utility XML manipulation functions.
|
15
|
+
module XMLUtil
|
16
|
+
# Extract the string representation of the specified XML element name
|
17
|
+
# _element_name_ from the XML string _xml_data_
|
18
|
+
def XMLUtil.get_xml(xml_data, element_name)
|
19
|
+
start_tag = '<'+element_name+'>'
|
20
|
+
end_tag = '</'+element_name+'>'
|
21
|
+
return nil if (start_idx = xml_data.index(start_tag)).nil?
|
22
|
+
return nil if (end_idx = xml_data.index(end_tag)).nil?
|
23
|
+
end_idx += end_tag.size - 1
|
24
|
+
xml_data[start_idx..end_idx]
|
25
|
+
end
|
26
|
+
|
27
|
+
#----------------------------------------------------------------------------#
|
28
|
+
|
29
|
+
# Trivially escape the XML string _xml_, by making the following substitutions:
|
30
|
+
# * & for &
|
31
|
+
# * < for <
|
32
|
+
# * > for >
|
33
|
+
# Return the escaped XML string.
|
34
|
+
def XMLUtil::escape( xml )
|
35
|
+
escaped_xml = xml.gsub( '&', '&' )
|
36
|
+
escaped_xml.gsub!( '<', '<' )
|
37
|
+
escaped_xml.gsub!( '>', '>' )
|
38
|
+
return escaped_xml
|
39
|
+
end
|
40
|
+
|
41
|
+
#----------------------------------------------------------------------------#
|
42
|
+
|
43
|
+
# Trivially unescape the escaped XML string _escaped_xml_, by making the
|
44
|
+
# following substitutions:
|
45
|
+
# * & for &
|
46
|
+
# * < for <
|
47
|
+
# * > for >
|
48
|
+
# Return the XML string.
|
49
|
+
def XMLUtil::unescape( escaped_xml )
|
50
|
+
xml = escaped_xml.gsub( '<', '<' )
|
51
|
+
xml.gsub!( '>', '>' )
|
52
|
+
xml.gsub!( '&', '&' )
|
53
|
+
return xml
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# Copyright 2008-2014 Amazon.com, Inc. or its affiliates. All Rights
|
2
|
+
# Reserved. Licensed under the Amazon Software License (the
|
3
|
+
# "License"). You may not use this file except in compliance with the
|
4
|
+
# License. A copy of the License is located at
|
5
|
+
# http://aws.amazon.com/asl or in the "license" file accompanying this
|
6
|
+
# file. This file is distributed on an "AS IS" BASIS, WITHOUT
|
7
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See
|
8
|
+
# the License for the specific language governing permissions and
|
9
|
+
# limitations under the License.
|
10
|
+
|
11
|
+
module EC2
|
12
|
+
module Common
|
13
|
+
SIGV2 = '2'
|
14
|
+
SIGV4 = '4'
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
# Copyright 2008-2014 Amazon.com, Inc. or its affiliates. All Rights
|
2
|
+
# Reserved. Licensed under the Amazon Software License (the
|
3
|
+
# "License"). You may not use this file except in compliance with the
|
4
|
+
# License. A copy of the License is located at
|
5
|
+
# http://aws.amazon.com/asl or in the "license" file accompanying this
|
6
|
+
# file. This file is distributed on an "AS IS" BASIS, WITHOUT
|
7
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See
|
8
|
+
# the License for the specific language governing permissions and
|
9
|
+
# limitations under the License.
|
10
|
+
|
11
|
+
# -----------------------------------------------------------------------------
|
12
|
+
# This is a light ruby wrapper around the curl command-line utility.
|
13
|
+
# Unless the run with the -f/--fail flag, the curl utility returns an exit-code
|
14
|
+
# of value 0 for requests that produce responses with HTTP errors codes greater
|
15
|
+
# than or equal to 400; it returns 22 and swallows the response. This wrapper
|
16
|
+
# attempts to emulate the -f/--fail flag while making available response codes
|
17
|
+
# with minimal verbosity.
|
18
|
+
# -----------------------------------------------------------------------------
|
19
|
+
require 'ec2/oem/open4'
|
20
|
+
require 'tmpdir'
|
21
|
+
|
22
|
+
module EC2
|
23
|
+
module Common
|
24
|
+
module Curl
|
25
|
+
class Error < RuntimeError
|
26
|
+
attr_reader :code
|
27
|
+
def initialize(message, code=22)
|
28
|
+
super message
|
29
|
+
@code = code
|
30
|
+
end
|
31
|
+
end
|
32
|
+
class Response
|
33
|
+
attr_reader :code, :type
|
34
|
+
def initialize(code, type)
|
35
|
+
@code = code.to_i
|
36
|
+
@type = type
|
37
|
+
end
|
38
|
+
def success?
|
39
|
+
(200..299).include? @code
|
40
|
+
end
|
41
|
+
def redirect?
|
42
|
+
(300..399).include? @code
|
43
|
+
end
|
44
|
+
def text?
|
45
|
+
@type =~ /(text|xml)/
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class Result
|
50
|
+
attr_reader :stdout, :stderr, :status, :response
|
51
|
+
def initialize(stdout, stderr, status, response = nil)
|
52
|
+
unless response.nil? or response.is_a? EC2::Common::Curl::Response
|
53
|
+
raise ArgumentError.new('invalid response argument')
|
54
|
+
end
|
55
|
+
@stdout = stdout
|
56
|
+
@stderr = stderr
|
57
|
+
@status = status
|
58
|
+
@response= response
|
59
|
+
end
|
60
|
+
def success?
|
61
|
+
@status == 0
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.invoke(command, debug=false)
|
66
|
+
invocation = "curl -sSL #{command}"
|
67
|
+
# invocation = "curl -vsSL #{command}" if debug
|
68
|
+
invocation << ' -w "Response-Code: %{http_code}\nContent-Type: %{content_type}"'
|
69
|
+
STDERR.puts invocation if debug
|
70
|
+
pid, stdin, stdout, stderr = Open4::popen4(invocation)
|
71
|
+
pid, status = Process::waitpid2 pid
|
72
|
+
[status, stdout, stderr]
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.print_error(command, status, out, err)
|
76
|
+
puts "----COMMAND------------------"
|
77
|
+
puts command
|
78
|
+
puts "----EXIT-CODE----------------"
|
79
|
+
puts status.exitstatus.inspect
|
80
|
+
puts "----STDOUT-------------------"
|
81
|
+
puts out
|
82
|
+
puts "----STDERR-------------------"
|
83
|
+
puts err
|
84
|
+
puts "-----------------------------"
|
85
|
+
end
|
86
|
+
|
87
|
+
def self.execute(command, debug = false)
|
88
|
+
status, stdout, stderr = self.invoke(command, debug)
|
89
|
+
out = stdout.read
|
90
|
+
err = stderr.read
|
91
|
+
if status.exitstatus == 0
|
92
|
+
code, type = out.chomp.split("\n").zip(['Response-Code', 'Content-Type']).map do |line, name|
|
93
|
+
(m = Regexp.new("^#{name}: (\\S+)$").match(line.chomp)) ? m.captures[0] : nil
|
94
|
+
end
|
95
|
+
if code.nil?
|
96
|
+
self.print_error(command, status, out, err) if debug
|
97
|
+
raise EC2::Common::Curl::Error.new(
|
98
|
+
'Invalid curl output for response-code. Is the server up and reachable?'
|
99
|
+
)
|
100
|
+
end
|
101
|
+
response = EC2::Common::Curl::Response.new(code, type)
|
102
|
+
return EC2::Common::Curl::Result.new(out, err, status.exitstatus, response)
|
103
|
+
else
|
104
|
+
self.print_error(command, status, out, err) if debug
|
105
|
+
return EC2::Common::Curl::Result.new(out, err, status.exitstatus)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|