topo-provision 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +201 -0
- data/README.md +100 -0
- data/bin/topo-provision +23 -0
- data/lib/topo/converter.rb +80 -0
- data/lib/topo/converter/cloudformation/converter.rb +219 -0
- data/lib/topo/exporter.rb +15 -0
- data/lib/topo/loader.rb +31 -0
- data/lib/topo/provision.rb +3 -0
- data/lib/topo/provision/aws/generator.rb +55 -0
- data/lib/topo/provision/aws/generators/aws_auto_scaling_group.rb +61 -0
- data/lib/topo/provision/aws/generators/aws_launch_configuration.rb +65 -0
- data/lib/topo/provision/aws/generators/context.rb +33 -0
- data/lib/topo/provision/aws/generators/load_balancer.rb +47 -0
- data/lib/topo/provision/aws/generators/machine.rb +36 -0
- data/lib/topo/provision/aws/generators/machine_image.rb +38 -0
- data/lib/topo/provision/aws/generators/node_group.rb +64 -0
- data/lib/topo/provision/cli.rb +95 -0
- data/lib/topo/provision/generator.rb +185 -0
- data/lib/topo/provision/generators/chef_node.rb +35 -0
- data/lib/topo/provision/generators/context.rb +70 -0
- data/lib/topo/provision/generators/load_balancer.rb +40 -0
- data/lib/topo/provision/generators/machine.rb +50 -0
- data/lib/topo/provision/generators/machine_image.rb +43 -0
- data/lib/topo/provision/generators/node_group.rb +74 -0
- data/lib/topo/provision/generators/resource.rb +91 -0
- data/lib/topo/provision/generators/templates/context.erb +8 -0
- data/lib/topo/provision/generators/templates/machine_deploy.erb +11 -0
- data/lib/topo/provision/generators/templates/machine_stop.erb +5 -0
- data/lib/topo/provision/generators/templates/node_group_action.erb +6 -0
- data/lib/topo/provision/generators/templates/node_group_deploy.erb +5 -0
- data/lib/topo/provision/generators/templates/resource_deploy.erb +5 -0
- data/lib/topo/provision/generators/templates/resource_undeploy.erb +5 -0
- data/lib/topo/provision/topology_generator.rb +84 -0
- data/lib/topo/provision/vagrant/generator.rb +33 -0
- data/lib/topo/provision/version.rb +5 -0
- data/lib/topo/topology.rb +61 -0
- data/lib/topo/utils/output.rb +31 -0
- data/lib/topo/utils/parsegen.rb +101 -0
- metadata +126 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 9f98f28285a7ba5c4b90fb7a393dd8c8ccf45fdc
|
4
|
+
data.tar.gz: 6fa3d26529b683afb9b21a9be162d48a937d8f09
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d42c65bdfb1750c68da96e253bfc8def52a02f7694bdb3ad3a593fb7cf7b1dc503e45f7c6c215e0b790592c330cf3a17fa7d693c8b3d274de4dc0029ba169aea
|
7
|
+
data.tar.gz: 1dab45430c5a965f54202ffabd2a7c347fb4d39ef2e764d269cd7ff5c2cde273dac09144fdc2b9e2730d765e680c1436175bbebc03410a40721b41a3059d7c48
|
data/LICENSE
ADDED
@@ -0,0 +1,201 @@
|
|
1
|
+
Apache License
|
2
|
+
Version 2.0, January 2004
|
3
|
+
http://www.apache.org/licenses/
|
4
|
+
|
5
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
6
|
+
|
7
|
+
1. Definitions.
|
8
|
+
|
9
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
10
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
11
|
+
|
12
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
13
|
+
the copyright owner that is granting the License.
|
14
|
+
|
15
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
16
|
+
other entities that control, are controlled by, or are under common
|
17
|
+
control with that entity. For the purposes of this definition,
|
18
|
+
"control" means (i) the power, direct or indirect, to cause the
|
19
|
+
direction or management of such entity, whether by contract or
|
20
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
21
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
22
|
+
|
23
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
24
|
+
exercising permissions granted by this License.
|
25
|
+
|
26
|
+
"Source" form shall mean the preferred form for making modifications,
|
27
|
+
including but not limited to software source code, documentation
|
28
|
+
source, and configuration files.
|
29
|
+
|
30
|
+
"Object" form shall mean any form resulting from mechanical
|
31
|
+
transformation or translation of a Source form, including but
|
32
|
+
not limited to compiled object code, generated documentation,
|
33
|
+
and conversions to other media types.
|
34
|
+
|
35
|
+
"Work" shall mean the work of authorship, whether in Source or
|
36
|
+
Object form, made available under the License, as indicated by a
|
37
|
+
copyright notice that is included in or attached to the work
|
38
|
+
(an example is provided in the Appendix below).
|
39
|
+
|
40
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
41
|
+
form, that is based on (or derived from) the Work and for which the
|
42
|
+
editorial revisions, annotations, elaborations, or other modifications
|
43
|
+
represent, as a whole, an original work of authorship. For the purposes
|
44
|
+
of this License, Derivative Works shall not include works that remain
|
45
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
46
|
+
the Work and Derivative Works thereof.
|
47
|
+
|
48
|
+
"Contribution" shall mean any work of authorship, including
|
49
|
+
the original version of the Work and any modifications or additions
|
50
|
+
to that Work or Derivative Works thereof, that is intentionally
|
51
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
52
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
53
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
54
|
+
means any form of electronic, verbal, or written communication sent
|
55
|
+
to the Licensor or its representatives, including but not limited to
|
56
|
+
communication on electronic mailing lists, source code control systems,
|
57
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
58
|
+
Licensor for the purpose of discussing and improving the Work, but
|
59
|
+
excluding communication that is conspicuously marked or otherwise
|
60
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
61
|
+
|
62
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
63
|
+
on behalf of whom a Contribution has been received by Licensor and
|
64
|
+
subsequently incorporated within the Work.
|
65
|
+
|
66
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
67
|
+
this License, each Contributor hereby grants to You a perpetual,
|
68
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
69
|
+
copyright license to reproduce, prepare Derivative Works of,
|
70
|
+
publicly display, publicly perform, sublicense, and distribute the
|
71
|
+
Work and such Derivative Works in Source or Object form.
|
72
|
+
|
73
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
74
|
+
this License, each Contributor hereby grants to You a perpetual,
|
75
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
76
|
+
(except as stated in this section) patent license to make, have made,
|
77
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
78
|
+
where such license applies only to those patent claims licensable
|
79
|
+
by such Contributor that are necessarily infringed by their
|
80
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
81
|
+
with the Work to which such Contribution(s) was submitted. If You
|
82
|
+
institute patent litigation against any entity (including a
|
83
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
84
|
+
or a Contribution incorporated within the Work constitutes direct
|
85
|
+
or contributory patent infringement, then any patent licenses
|
86
|
+
granted to You under this License for that Work shall terminate
|
87
|
+
as of the date such litigation is filed.
|
88
|
+
|
89
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
90
|
+
Work or Derivative Works thereof in any medium, with or without
|
91
|
+
modifications, and in Source or Object form, provided that You
|
92
|
+
meet the following conditions:
|
93
|
+
|
94
|
+
(a) You must give any other recipients of the Work or
|
95
|
+
Derivative Works a copy of this License; and
|
96
|
+
|
97
|
+
(b) You must cause any modified files to carry prominent notices
|
98
|
+
stating that You changed the files; and
|
99
|
+
|
100
|
+
(c) You must retain, in the Source form of any Derivative Works
|
101
|
+
that You distribute, all copyright, patent, trademark, and
|
102
|
+
attribution notices from the Source form of the Work,
|
103
|
+
excluding those notices that do not pertain to any part of
|
104
|
+
the Derivative Works; and
|
105
|
+
|
106
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
107
|
+
distribution, then any Derivative Works that You distribute must
|
108
|
+
include a readable copy of the attribution notices contained
|
109
|
+
within such NOTICE file, excluding those notices that do not
|
110
|
+
pertain to any part of the Derivative Works, in at least one
|
111
|
+
of the following places: within a NOTICE text file distributed
|
112
|
+
as part of the Derivative Works; within the Source form or
|
113
|
+
documentation, if provided along with the Derivative Works; or,
|
114
|
+
within a display generated by the Derivative Works, if and
|
115
|
+
wherever such third-party notices normally appear. The contents
|
116
|
+
of the NOTICE file are for informational purposes only and
|
117
|
+
do not modify the License. You may add Your own attribution
|
118
|
+
notices within Derivative Works that You distribute, alongside
|
119
|
+
or as an addendum to the NOTICE text from the Work, provided
|
120
|
+
that such additional attribution notices cannot be construed
|
121
|
+
as modifying the License.
|
122
|
+
|
123
|
+
You may add Your own copyright statement to Your modifications and
|
124
|
+
may provide additional or different license terms and conditions
|
125
|
+
for use, reproduction, or distribution of Your modifications, or
|
126
|
+
for any such Derivative Works as a whole, provided Your use,
|
127
|
+
reproduction, and distribution of the Work otherwise complies with
|
128
|
+
the conditions stated in this License.
|
129
|
+
|
130
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
131
|
+
any Contribution intentionally submitted for inclusion in the Work
|
132
|
+
by You to the Licensor shall be under the terms and conditions of
|
133
|
+
this License, without any additional terms or conditions.
|
134
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
135
|
+
the terms of any separate license agreement you may have executed
|
136
|
+
with Licensor regarding such Contributions.
|
137
|
+
|
138
|
+
6. Trademarks. This License does not grant permission to use the trade
|
139
|
+
names, trademarks, service marks, or product names of the Licensor,
|
140
|
+
except as required for reasonable and customary use in describing the
|
141
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
142
|
+
|
143
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
144
|
+
agreed to in writing, Licensor provides the Work (and each
|
145
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
146
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
147
|
+
implied, including, without limitation, any warranties or conditions
|
148
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
149
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
150
|
+
appropriateness of using or redistributing the Work and assume any
|
151
|
+
risks associated with Your exercise of permissions under this License.
|
152
|
+
|
153
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
154
|
+
whether in tort (including negligence), contract, or otherwise,
|
155
|
+
unless required by applicable law (such as deliberate and grossly
|
156
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
157
|
+
liable to You for damages, including any direct, indirect, special,
|
158
|
+
incidental, or consequential damages of any character arising as a
|
159
|
+
result of this License or out of the use or inability to use the
|
160
|
+
Work (including but not limited to damages for loss of goodwill,
|
161
|
+
work stoppage, computer failure or malfunction, or any and all
|
162
|
+
other commercial damages or losses), even if such Contributor
|
163
|
+
has been advised of the possibility of such damages.
|
164
|
+
|
165
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
166
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
167
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
168
|
+
or other liability obligations and/or rights consistent with this
|
169
|
+
License. However, in accepting such obligations, You may act only
|
170
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
171
|
+
of any other Contributor, and only if You agree to indemnify,
|
172
|
+
defend, and hold each Contributor harmless for any liability
|
173
|
+
incurred by, or claims asserted against, such Contributor by reason
|
174
|
+
of your accepting any such warranty or additional liability.
|
175
|
+
|
176
|
+
END OF TERMS AND CONDITIONS
|
177
|
+
|
178
|
+
APPENDIX: How to apply the Apache License to your work.
|
179
|
+
|
180
|
+
To apply the Apache License to your work, attach the following
|
181
|
+
boilerplate notice, with the fields enclosed by brackets "{}"
|
182
|
+
replaced with your own identifying information. (Don't include
|
183
|
+
the brackets!) The text should be enclosed in the appropriate
|
184
|
+
comment syntax for the file format. We also recommend that a
|
185
|
+
file or class name and description of purpose be included on the
|
186
|
+
same "printed page" as the copyright notice for easier
|
187
|
+
identification within third-party archives.
|
188
|
+
|
189
|
+
Copyright 2015 ThirdWave Insights, LLC
|
190
|
+
|
191
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
192
|
+
you may not use this file except in compliance with the License.
|
193
|
+
You may obtain a copy of the License at
|
194
|
+
|
195
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
196
|
+
|
197
|
+
Unless required by applicable law or agreed to in writing, software
|
198
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
199
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
200
|
+
See the License for the specific language governing permissions and
|
201
|
+
limitations under the License.
|
data/README.md
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
# Topo::Provision
|
2
|
+
|
3
|
+
This utility allows you to generate chef-provisioning recipes from
|
4
|
+
a topology JSON file.
|
5
|
+
|
6
|
+
The format is an extended version of the JSON used by the knife-topo
|
7
|
+
plugin. In addition, it is possible to convert from other formats. The
|
8
|
+
only converter currently implemented is for CloudFormation.
|
9
|
+
|
10
|
+
This utility IS NOT READY FOR PRODUCTION USE. It is best described as a
|
11
|
+
"proof of concept". It has been tested with a pre-release version of
|
12
|
+
chef-provisioning 1.0.
|
13
|
+
|
14
|
+
## Features
|
15
|
+
|
16
|
+
'Nodes' in the topology JSON are generated as machine resources, if
|
17
|
+
provisioning is specified; otherwise they are generated as chef nodes.
|
18
|
+
|
19
|
+
'Node groups' in the topology JSON are generated as combinations of
|
20
|
+
different resources, depending on the driver and options specified.
|
21
|
+
Currently, for AWS if 'auto_scaling' is specified, it
|
22
|
+
generates a machine_image (unless an explicit image_id) is specified;
|
23
|
+
a launch configuration and an auto-scaling group. For vagrant, the action
|
24
|
+
is to generate multiple machines using machine_batch.
|
25
|
+
|
26
|
+
'Services' can be used to specify other sorts of resource, such as
|
27
|
+
a load balancer.
|
28
|
+
|
29
|
+
Node attributes can use a special topo_ref to indicate when an attribute
|
30
|
+
should be set based on attributes of another node. topo-provision will
|
31
|
+
generate the appropriate 'lazy' evaluation of the attribute value using
|
32
|
+
a node search, and will use the information to order the resources in the
|
33
|
+
generated recipe appropriately.
|
34
|
+
|
35
|
+
## Usage
|
36
|
+
|
37
|
+
$ topo-provision topofile.json
|
38
|
+
|
39
|
+
$ topo-provision cloudformation_template --format=cloudformation --output-topo cloudformation.json
|
40
|
+
|
41
|
+
$ topo-provision topofile.json --output topo_deploy.json
|
42
|
+
|
43
|
+
$ topo-provision topofile.json --action=undeploy --output topo_undeploy.json
|
44
|
+
|
45
|
+
$ topo-provision --help
|
46
|
+
|
47
|
+
## Structure
|
48
|
+
|
49
|
+
### Generators
|
50
|
+
|
51
|
+
Driver Generators support a particular chef provisioning driver, e.g. vagrant,
|
52
|
+
aws, fog. They live in `lib/topo/provision/#{driver}/` and register themselves using the
|
53
|
+
name of the driver. They should extend the base `Topo::Provision::Generator`
|
54
|
+
class and override its methods as needed to process the topo elements (context, node, service)
|
55
|
+
and call the appropriate Resource Generators.
|
56
|
+
|
57
|
+
Resource Generators live in `lib/topo/provision/#{driver}/generators` and
|
58
|
+
should extend `Topo::Provision::ResourceGenerator`. They are initialized
|
59
|
+
from a topo context, node or service element and generate the actual output
|
60
|
+
for the actions that are supported on the specific resource type (e.g. deploy, undeploy, stop).
|
61
|
+
|
62
|
+
The Topology Generator `Topo::Provision::TopologyGenerator` is the top-level generator that calls the appropriate
|
63
|
+
driver generators and generates a resource graph based on topo_ref dependencies, that it traverses in either
|
64
|
+
a forward or reverse direction, depending on the actions.
|
65
|
+
|
66
|
+
### Converters
|
67
|
+
|
68
|
+
Converters accept a format other than topology JSON, and convert it to
|
69
|
+
the standard topo format. They live in `lib/topo/converter` and register themselves using the
|
70
|
+
name that should be passed in using the --format option. They should extend
|
71
|
+
`Topo::Converter` and provide a 'convert' method that takes a data hash and returns a topo hash.
|
72
|
+
|
73
|
+
|
74
|
+
## Known Limitations
|
75
|
+
|
76
|
+
Only supports the vagrant and aws drivers.
|
77
|
+
|
78
|
+
Only covers the following resources:
|
79
|
+
* machine
|
80
|
+
* machine_image (as part of creating a node group)
|
81
|
+
* load_balancer
|
82
|
+
* aws_auto_scaling_group (as part of creating a node group)
|
83
|
+
* aws_launch_configuration (as part of creating a node group)
|
84
|
+
|
85
|
+
## Future Directions
|
86
|
+
|
87
|
+
Here's some things I would like to do, beyond extending current support:
|
88
|
+
* Support network resources
|
89
|
+
* Have generators analyse for dependencies (e.g. name refs to other
|
90
|
+
resources) and include these in the topo ordering as well as explicit topo_refs
|
91
|
+
* Allow users to customize behavior by providing alternative generators
|
92
|
+
|
93
|
+
|
94
|
+
## Contributing
|
95
|
+
|
96
|
+
1. Fork it ( https://github.com/christinedraper/topo-provision/fork )
|
97
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
98
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
99
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
100
|
+
5. Create a new Pull Request
|
data/bin/topo-provision
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
#
|
4
|
+
# Author:: Christine Draper (<christine_draper@thirdwaveinsights.com>)
|
5
|
+
# Copyright:: Copyright (c) 2015 ThirdWave Insights LLC
|
6
|
+
# License:: Apache License, Version 2.0
|
7
|
+
#
|
8
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
9
|
+
# you may not use this file except in compliance with the License.
|
10
|
+
# You may obtain a copy of the License at
|
11
|
+
#
|
12
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
13
|
+
#
|
14
|
+
# Unless required by applicable law or agreed to in writing, software
|
15
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
16
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
17
|
+
# See the License for the specific language governing permissions and
|
18
|
+
# limitations under the License.
|
19
|
+
#
|
20
|
+
|
21
|
+
require 'topo/provision/cli'
|
22
|
+
|
23
|
+
Topo::Provision::CLI.new.run
|
@@ -0,0 +1,80 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Christine Draper (<christine_draper@thirdwaveinsights.com>)
|
3
|
+
# Copyright:: Copyright (c) 2015 ThirdWave Insights LLC
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
#
|
20
|
+
# The converter class converts data in a given format into raw "topo" format data
|
21
|
+
#
|
22
|
+
|
23
|
+
require 'topo/utils/parsegen'
|
24
|
+
|
25
|
+
module Topo
|
26
|
+
class Converter
|
27
|
+
|
28
|
+
include Topo::ParseGen
|
29
|
+
|
30
|
+
attr_accessor :topology
|
31
|
+
|
32
|
+
# Converters for each format
|
33
|
+
@@converter_classes = {}
|
34
|
+
|
35
|
+
def self.register_converter(format, class_name)
|
36
|
+
@@converter_classes[format] = class_name
|
37
|
+
end
|
38
|
+
|
39
|
+
self.register_converter("default", self.name)
|
40
|
+
self.register_converter("topo", self.name)
|
41
|
+
|
42
|
+
# Get the right converter for the input format
|
43
|
+
def self.converter(format)
|
44
|
+
converter_class = @@converter_classes[format]
|
45
|
+
|
46
|
+
unless converter_class
|
47
|
+
begin
|
48
|
+
require "topo/converter/#{format}/converter"
|
49
|
+
converter_class = @@converter_classes[format]
|
50
|
+
rescue LoadError
|
51
|
+
STDERR.puts("#{format} is not a known format for the topology file")
|
52
|
+
exit 1
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
Object::const_get(converter_class).new(format)
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.convert(data, format)
|
60
|
+
converter = self.converter(format)
|
61
|
+
converter.convert(data)
|
62
|
+
end
|
63
|
+
|
64
|
+
attr_accessor :input
|
65
|
+
|
66
|
+
def initialize(format, data=nil)
|
67
|
+
@format = format
|
68
|
+
@input = data
|
69
|
+
@output = { "nodes" => [], "services" => [], "network" => [], "provisioning" => {} }
|
70
|
+
end
|
71
|
+
|
72
|
+
# Other format converters should override this method to convert to topo format data
|
73
|
+
def convert(data=nil)
|
74
|
+
@input = data if data
|
75
|
+
@output = @input
|
76
|
+
@output
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,219 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Christine Draper (<christine_draper@thirdwaveinsights.com>)
|
3
|
+
# Copyright:: Copyright (c) 2015 ThirdWave Insights LLC
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
#
|
20
|
+
#
|
21
|
+
|
22
|
+
module Topo
|
23
|
+
module Provision
|
24
|
+
class CloudFormationConverter < Topo::Converter
|
25
|
+
|
26
|
+
Topo::Converter.register_converter("cloudformation", self.name)
|
27
|
+
|
28
|
+
def convert(data)
|
29
|
+
@input = data if data
|
30
|
+
|
31
|
+
@output['name'] = @input['name'] || "CloudFormation"
|
32
|
+
|
33
|
+
create_provisioning
|
34
|
+
|
35
|
+
@input['Resources'].each do |name, resource|
|
36
|
+
convert_resource(name, resource)
|
37
|
+
end
|
38
|
+
|
39
|
+
@output
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
def create_provisioning
|
44
|
+
@output['provisioning'] = {'driver' => "aws", 'machine_options'=> { }}
|
45
|
+
end
|
46
|
+
|
47
|
+
FIELDS = {
|
48
|
+
:boolean => {
|
49
|
+
:bootstrap_options => %w[disable_api_termination associate_public_ip_address
|
50
|
+
ebs_optimized dedicated_tenancy monitoring monitoring_enabled ],
|
51
|
+
:network_interface => %w[ requester_managed source_dest_check delete_on_termination ],
|
52
|
+
:block_device_mapping_ebs => %w[delete_on_termination]
|
53
|
+
|
54
|
+
},
|
55
|
+
:integer => {
|
56
|
+
:listener => %w[instance_port load_balancer_port],
|
57
|
+
:network_interface => %w[ device_index ],
|
58
|
+
:block_device_mapping_ebs => %w[volume_size iops],
|
59
|
+
:auto_scaling_group => %w[max_size min_size desired_capacity cooldown default_cooldown health_check_grace_period]
|
60
|
+
},
|
61
|
+
:maptov1 => {
|
62
|
+
:listener => { "load_balancer_port" => "port" },
|
63
|
+
:bootstrap_options => { "monitoring" => "monitoring_enabled" },
|
64
|
+
:launch_config => { "monitoring" => "detailed_instance_monitoring" }
|
65
|
+
}
|
66
|
+
}
|
67
|
+
|
68
|
+
# CloudFormation keys are camelcase - convert to underscore
|
69
|
+
# CloudFormation values are all strings - convert to proper type
|
70
|
+
# CloudFormation is using AWS V2, chef-provisioning-aws is using AWS V1
|
71
|
+
def convert_resource(name, resource)
|
72
|
+
|
73
|
+
props = value_from_path(resource, ["Properties"]) || {}
|
74
|
+
props = keys_to_underscore props
|
75
|
+
|
76
|
+
case resource['Type']
|
77
|
+
when "AWS::EC2::Instance"
|
78
|
+
@output['nodes'] << convert_instance(name, resource)
|
79
|
+
|
80
|
+
when "AWS::ElasticLoadBalancing::LoadBalancer"
|
81
|
+
listeners = value_from_path(props, ["listeners"]) || []
|
82
|
+
props["listeners"] = listeners.map{|listener|
|
83
|
+
fields_to_v1(:listener, fields_to_i(:listener, keys_to_underscore(listener)))
|
84
|
+
}
|
85
|
+
@output['services'] << { "name" => name, "type" => "load_balancer",
|
86
|
+
"provisioning" => { "load_balancer_options" => props } }
|
87
|
+
|
88
|
+
when "AWS::AutoScaling::AutoScalingGroup"
|
89
|
+
@output['nodes'] << convert_auto_scaling_group(name, resource)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def convert_instance(name, resource)
|
94
|
+
|
95
|
+
instance = {
|
96
|
+
"name" => name,
|
97
|
+
"provisioning" => { "machine_options" => {} }
|
98
|
+
}
|
99
|
+
|
100
|
+
props = value_from_path(resource, ["Properties"]) || {}
|
101
|
+
props = keys_to_underscore props
|
102
|
+
props = fields_to_v1(:bootstrap_options, fields_to_bool(:bootstrap_options, props))
|
103
|
+
|
104
|
+
# Need to convert object arrays (TODO helpers)
|
105
|
+
if props["tags"]
|
106
|
+
props["tags"].each_with_index do | tag, index |
|
107
|
+
props["tags"][index] = keys_to_underscore(tag)
|
108
|
+
STDERR.puts "WARN: Setting AWS tags on instances is not supported yet"
|
109
|
+
instance["provisioning"]["tags"] = props["tags"]
|
110
|
+
props.delete("tags")
|
111
|
+
end
|
112
|
+
end
|
113
|
+
if props["network_interfaces"]
|
114
|
+
props["network_interfaces"].each_with_index do | network_interface, index |
|
115
|
+
temp = fields_to_i(:network_interface, keys_to_underscore(network_interface))
|
116
|
+
temp = fields_to_bool(:network_interface, temp)
|
117
|
+
props["network_interfaces"][index] = temp
|
118
|
+
# if one of the network interfaces had associate_public_ip_address: true, then
|
119
|
+
# set that in bootstrap
|
120
|
+
if temp['associate_public_ip_address']
|
121
|
+
props['associate_public_ip_address'] = temp['associate_public_ip_address']
|
122
|
+
end
|
123
|
+
end
|
124
|
+
STDERR.puts "WARN: Setting network_interfaces on instances is not supported"
|
125
|
+
instance["provisioning"]["network_interfaces"] = props["network_interfaces"]
|
126
|
+
props.delete("network_interfaces")
|
127
|
+
end
|
128
|
+
|
129
|
+
instance["provisioning"]["machine_options"]["bootstrap_options"] = props
|
130
|
+
|
131
|
+
instance
|
132
|
+
|
133
|
+
end
|
134
|
+
|
135
|
+
def convert_auto_scaling_group(name, resource)
|
136
|
+
|
137
|
+
node = {
|
138
|
+
"name" => name,
|
139
|
+
"provisioning" => { "machine_options" => {}, "node_group" => { "auto_scaling" => {}} }
|
140
|
+
}
|
141
|
+
# find asg properties
|
142
|
+
asg_props = value_from_path(resource, %w[Properties]).clone || {}
|
143
|
+
asg_props = fields_to_i(:auto_scaling_group, keys_to_underscore(asg_props))
|
144
|
+
asg_props.delete("launch_configuration_name")
|
145
|
+
asg_props.delete("load_balancer_names")
|
146
|
+
%w[availability_zones load_balancers].each do |key|
|
147
|
+
node["provisioning"]["node_group"]["auto_scaling"][key] = asg_props[key] if asg_props.key? key
|
148
|
+
asg_props.delete(key)
|
149
|
+
end
|
150
|
+
node["provisioning"]["node_group"]["auto_scaling"]["group_options"] = asg_props
|
151
|
+
|
152
|
+
# find the launch config
|
153
|
+
lc_name = value_from_path(resource, %w[Properties LaunchConfigurationName Ref])
|
154
|
+
lc_props = keys_to_underscore(value_from_path(@input, ['Resources', lc_name, 'Properties'])) || {}
|
155
|
+
lc_props = fields_to_bool(:bootstrap_options, lc_props)
|
156
|
+
node["provisioning"]["node_group"]["auto_scaling"]["launch_configuration_options"] = lc_props
|
157
|
+
|
158
|
+
# find the load balancers
|
159
|
+
lb_refs = value_from_path(resource, %w[Properties LoadBalancerNames]) || []
|
160
|
+
load_balancers = lb_refs.map{|lb_ref| lb_ref['Ref'] }
|
161
|
+
# TODO should this be a topo ref instead? - needs to pick up load balancer name
|
162
|
+
if load_balancers.length > 0
|
163
|
+
node["provisioning"]["node_group"]["auto_scaling"]["load_balancers"] = load_balancers
|
164
|
+
end
|
165
|
+
|
166
|
+
node
|
167
|
+
|
168
|
+
end
|
169
|
+
|
170
|
+
|
171
|
+
|
172
|
+
def camel_to_underscore(str)
|
173
|
+
str.gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
174
|
+
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
175
|
+
downcase
|
176
|
+
end
|
177
|
+
|
178
|
+
def keys_to_underscore(hash)
|
179
|
+
converted = Hash[hash.map{|key, val|
|
180
|
+
if (val.kind_of? Hash)
|
181
|
+
[ camel_to_underscore(key), keys_to_underscore(val) ]
|
182
|
+
else
|
183
|
+
[camel_to_underscore(key), val]
|
184
|
+
end
|
185
|
+
}]
|
186
|
+
end
|
187
|
+
|
188
|
+
#
|
189
|
+
def fields_to_i(field_name, hash)
|
190
|
+
FIELDS[:integer][field_name].each do | key |
|
191
|
+
hash[key] = hash[key].to_i if hash.key? key
|
192
|
+
end
|
193
|
+
|
194
|
+
hash
|
195
|
+
end
|
196
|
+
|
197
|
+
def fields_to_bool(field_name, hash)
|
198
|
+
FIELDS[:boolean][field_name].each do | key |
|
199
|
+
if hash.key? key
|
200
|
+
hash[key] = (hash[key].downcase == "true")
|
201
|
+
end
|
202
|
+
end
|
203
|
+
hash
|
204
|
+
end
|
205
|
+
|
206
|
+
def fields_to_v1(field_name, hash)
|
207
|
+
FIELDS[:maptov1][field_name].each do | key, value |
|
208
|
+
if hash.key? key
|
209
|
+
hash[value] = hash[key]
|
210
|
+
hash.delete(key)
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
hash
|
215
|
+
end
|
216
|
+
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|