knife-topo 0.0.3 → 0.0.4
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.
- data/README.md +101 -21
- data/lib/chef/knife/topo/version.rb +1 -1
- data/lib/chef/knife/topo_bootstrap.rb +1 -1
- data/lib/chef/knife/topo_cookbook_create.rb +9 -11
- data/lib/chef/knife/topo_create.rb +1 -0
- data/lib/chef/knife/topo_export.rb +14 -12
- data/lib/chef/knife/topology_helper.rb +38 -15
- data/test-repo/Instructions.md +131 -0
- data/test-repo/Vagrantfile +5 -10
- data/test-repo/Vagrantfile_bridged +59 -0
- data/test-repo/cookbooks/testapp/recipes/appserver.rb +1 -1
- data/test-repo/cookbooks/testapp/recipes/deploy.rb +1 -1
- data/test-repo/topology.json +38 -13
- metadata +4 -4
- data/test-repo/Instructions.txt +0 -48
- data/test-repo/multipletopology.json +0 -117
data/README.md
CHANGED
@@ -1,9 +1,13 @@
|
|
1
1
|
knife topo
|
2
2
|
==========
|
3
3
|
|
4
|
-
This Chef Knife plugin
|
5
|
-
|
6
|
-
multiple nodes
|
4
|
+
This Chef Knife plugin allows you to create and update topologies
|
5
|
+
consisting of multiple nodes. You may find it useful if you are
|
6
|
+
regularly updating a system consisting of multiple nodes, and would
|
7
|
+
like to manage its dynamic configuration (like software versions)
|
8
|
+
through a single (json) configuration file. It may also be useful
|
9
|
+
if you are regularly bringing up multi-node systems with similar
|
10
|
+
topologies but differences in their configuration details.
|
7
11
|
|
8
12
|
# Installation #
|
9
13
|
|
@@ -20,7 +24,7 @@ This plugin has been tested with Chef Version 11.12 on Ubuntu 14.04 LTS.
|
|
20
24
|
|
21
25
|
# Usage #
|
22
26
|
|
23
|
-
Define one or more
|
27
|
+
Define one or more topologies in a [topology file](#markdown-header-topology-file).
|
24
28
|
|
25
29
|
Import the topology file into your local chef repo using
|
26
30
|
[knife topo import](#markdown-header-knife-topo-import). Create and optionally
|
@@ -30,14 +34,15 @@ using [knife topo update](#markdown-header-knife-topo-update).
|
|
30
34
|
|
31
35
|
# Getting Started #
|
32
36
|
|
33
|
-
Try out this plugin using a [test repo](knife-topo/src/master/test-repo)
|
34
|
-
download from Github or is included in the installed gem. See the
|
35
|
-
[Instructions](knife-topo/src/master/test-repo/Instructions.
|
37
|
+
Try out this plugin using a [test repo](knife-topo/src/master/test-repo)
|
38
|
+
which you can download from Github or is included in the installed gem. See the
|
39
|
+
[Instructions](knife-topo/src/master/test-repo/Instructions.md) for a
|
40
|
+
demo script, explanation, and troubleshooting.
|
36
41
|
|
37
42
|
The instructions assume you have
|
38
43
|
[chefDK](http://www.getchef.com/downloads/chef-dk/)
|
39
44
|
or equivalent installed and working with Vagrant and VirtualBox, but
|
40
|
-
|
45
|
+
none of these are requirements for this plugin.
|
41
46
|
|
42
47
|
# Topology File #
|
43
48
|
|
@@ -72,17 +77,7 @@ The `name` is how you will refer to the topology in the
|
|
72
77
|
The `chef-environment` and `normal` attributes defined
|
73
78
|
here will be applied to all nodes in the topology, unless alternative
|
74
79
|
values are provided for a specific node. The `tags`
|
75
|
-
will be added to each node.
|
76
|
-
specified using the dot notation, as shown above, or may be expanded as
|
77
|
-
a JSON structure, i.e., the above is equivalent to:
|
78
|
-
```json
|
79
|
-
{
|
80
|
-
"normal": {
|
81
|
-
"topo": {
|
82
|
-
"blueprint": "blah"
|
83
|
-
}
|
84
|
-
}
|
85
|
-
}
|
80
|
+
will be added to each node.
|
86
81
|
|
87
82
|
## Node List
|
88
83
|
Each topology contains a list of `nodes`.
|
@@ -94,8 +89,8 @@ Each topology contains a list of `nodes`.
|
|
94
89
|
"nodes": {
|
95
90
|
"buildserver": {
|
96
91
|
"name": "buildserver01",
|
97
|
-
"ssh_host": "
|
98
|
-
"ssh_port": "
|
92
|
+
"ssh_host": "192.168.1.201",
|
93
|
+
"ssh_port": "2224",
|
99
94
|
"chef_environment": "dev",
|
100
95
|
"run_list": ["role[base-ubuntu]", "ypo::db", "recipe[ypo::appserver]"],
|
101
96
|
"normal": {
|
@@ -121,8 +116,63 @@ bootstrap a node.
|
|
121
116
|
|
122
117
|
## Topology Cookbook Attributes
|
123
118
|
|
119
|
+
Each topology may have attributes that are set via
|
120
|
+
an attribute file in a topology-specific cookbook. Each
|
121
|
+
attribute file is described in an entry in the 'cookbook_attributes'
|
122
|
+
array.
|
123
|
+
|
124
|
+
```json
|
125
|
+
"cookbook_attributes": [
|
126
|
+
{
|
127
|
+
"cookbook": "testsys_test1",
|
128
|
+
"filename": "softwareversion",
|
129
|
+
"normal":
|
130
|
+
{
|
131
|
+
"nodejs":
|
132
|
+
{
|
133
|
+
"version": "0.28"
|
134
|
+
},
|
135
|
+
|
136
|
+
"testapp":
|
137
|
+
{
|
138
|
+
"version": "0.0.3"
|
139
|
+
},
|
140
|
+
|
141
|
+
"mongodb":
|
142
|
+
{
|
143
|
+
"package_version": "2.6.1"
|
144
|
+
}
|
145
|
+
},
|
146
|
+
"conditional" : [
|
147
|
+
{
|
148
|
+
"qualifier": "node_type",
|
149
|
+
"value" : "buildserver",
|
150
|
+
"normal":
|
151
|
+
{
|
152
|
+
"mongodb":
|
153
|
+
{
|
154
|
+
"package_version": "2.5.1"
|
155
|
+
}
|
156
|
+
}
|
157
|
+
}
|
158
|
+
]
|
159
|
+
}
|
160
|
+
]
|
161
|
+
```
|
162
|
+
|
163
|
+
Attributes listed directly under an attribute priority (e.g. 'normal'
|
164
|
+
in the above) will generate an entry in the attribute file such as:
|
124
165
|
|
166
|
+
normal['mongodb'][package_version] = "2.6.1"
|
167
|
+
|
168
|
+
Attributes listed under the `conditional` property will generate an
|
169
|
+
entry in the attribute file such as:
|
125
170
|
|
171
|
+
```ruby
|
172
|
+
if (node['topo']['node_type'] == "buildserver")
|
173
|
+
normal['mongodb'][package_version] = "2.5.1"
|
174
|
+
end
|
175
|
+
```
|
126
176
|
|
127
177
|
# Subcommands #
|
128
178
|
|
@@ -185,12 +235,42 @@ user name of vagrant, password of vagrant, and running using sudo.
|
|
185
235
|
Generates the topology cookbook attribute files and attributes described in the
|
186
236
|
'cookbook_attributes' property.
|
187
237
|
|
238
|
+
### Options:
|
239
|
+
|
240
|
+
The knife topo cookbook create subcommand supports the following additional options.
|
241
|
+
|
242
|
+
Option | Description
|
243
|
+
------------ | -----------
|
244
|
+
See [knife cookbook create](http://docs.opscode.com/chef/knife.html#cookbook) |
|
245
|
+
|
246
|
+
### Examples:
|
247
|
+
The following will generate the topology cookbook attribute files for
|
248
|
+
topology test1.
|
249
|
+
|
250
|
+
$ knife topo cookbook create test1
|
251
|
+
|
252
|
+
## knife topo cookbook upload
|
253
|
+
|
254
|
+
knife topo cookbook upload TOPOLOGY
|
255
|
+
|
256
|
+
Uploads the topology cookbook attribute files.
|
257
|
+
|
258
|
+
### Options:
|
259
|
+
|
260
|
+
The knife topo cookbook upload subcommand supports the following additional options.
|
261
|
+
|
262
|
+
Option | Description
|
263
|
+
------------ | -----------
|
264
|
+
See [knife cookbook upload](http://docs.opscode.com/chef/knife.html#cookbook) |
|
265
|
+
|
266
|
+
|
188
267
|
### Examples:
|
189
268
|
The following will generate the topology cookbook attribute files for
|
190
269
|
topology test1.
|
191
270
|
|
192
271
|
$ knife topo cookbook create test1
|
193
272
|
|
273
|
+
|
194
274
|
## knife topo create
|
195
275
|
|
196
276
|
knife topo create TOPOLOGY
|
@@ -79,7 +79,7 @@ class Chef
|
|
79
79
|
end
|
80
80
|
|
81
81
|
end
|
82
|
-
ui.info "
|
82
|
+
ui.info "Bootstrapped #{nodes.length - (@failed.length + skipped)} nodes and skipped #{skipped} nodes of #{nodes.length} in topology #{@bag_name}/#{@topo_name}"
|
83
83
|
ui.warn "#{@failed.length} nodes [ #{@failed.join(', ')} ] failed to bootstrap" if @failed.length > 0
|
84
84
|
else
|
85
85
|
ui.info "No nodes found for topology #{@topo_name}"
|
@@ -150,23 +150,21 @@ class Chef
|
|
150
150
|
end
|
151
151
|
|
152
152
|
# Print out qualified attributes
|
153
|
-
def print_qualified_attr(file,
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
file.puts "end"
|
158
|
-
end
|
153
|
+
def print_qualified_attr(file, qualifier_hash)
|
154
|
+
file.puts "if node['topo']['#{qualifier_hash['qualifier']}'] == \"#{qualifier_hash['value']}\""
|
155
|
+
print_priority_attrs(file, qualifier_hash, 2)
|
156
|
+
file.puts "end"
|
159
157
|
end
|
160
158
|
|
161
159
|
# Process the attributes not needing qualification
|
162
160
|
print_priority_attrs(file, attrs)
|
163
161
|
file.puts
|
164
162
|
|
165
|
-
# Process attributes that need to be qualified
|
166
|
-
|
167
|
-
|
168
|
-
file.puts "# Attributes for specific #{qualifier}"
|
169
|
-
print_qualified_attr(file,
|
163
|
+
# Process attributes that need to be qualified
|
164
|
+
if attrs['conditional']
|
165
|
+
attrs['conditional'].each do |qualified_attrs|
|
166
|
+
file.puts "# Attributes for specific #{qualified_attrs['qualifier']}"
|
167
|
+
print_qualified_attr(file, qualified_attrs)
|
170
168
|
end
|
171
169
|
end
|
172
170
|
|
@@ -101,30 +101,32 @@ class Chef
|
|
101
101
|
|
102
102
|
# get actual node properties for export
|
103
103
|
def node_export (node_name)
|
104
|
+
|
105
|
+
node_data = {}
|
106
|
+
|
104
107
|
begin
|
105
|
-
node = Chef::Node.load(node_name)
|
108
|
+
node = Chef::Node.load(node_name)
|
109
|
+
|
110
|
+
node_data['name'] = node.name
|
111
|
+
node_data['tags'] = node.tags
|
112
|
+
node_data['chef_environment'] = node.chef_environment
|
113
|
+
node_data['normal'] = node.normal
|
114
|
+
node_data['run_list'] = node.run_list
|
115
|
+
|
106
116
|
rescue Net::HTTPServerException => e
|
107
117
|
raise unless e.to_s =~ /^404/
|
108
118
|
node = empty_node(node_name)
|
109
119
|
end
|
110
|
-
props = %w{name chef_environment normal run_list recipes}
|
111
|
-
node_data = {}
|
112
|
-
|
113
|
-
props.each do |prop|
|
114
|
-
node_data[prop] = node[prop] if node.has_key?(prop)
|
115
|
-
end
|
116
120
|
|
117
|
-
node_data[tags] = node_data[normal][tags]
|
118
|
-
|
119
121
|
node_data
|
120
122
|
end
|
121
123
|
|
122
124
|
# merge hash properties with the actual node properties
|
123
125
|
def merge_node_properties!(nodes, node_name)
|
124
126
|
# find out if the node is already in the array
|
125
|
-
|
126
|
-
if
|
127
|
-
|
127
|
+
found = nodes.index{|n| n["name"] == node_name }
|
128
|
+
if found
|
129
|
+
nodes[found] = node_export(node_name)
|
128
130
|
else
|
129
131
|
nodes.push(node_export(node_name))
|
130
132
|
end
|
@@ -81,22 +81,37 @@ class Chef
|
|
81
81
|
|
82
82
|
chef_env
|
83
83
|
end
|
84
|
+
|
85
|
+
# recursive merge that retains all keys
|
86
|
+
def prop_merge!(hash, other_hash)
|
87
|
+
other_hash.each do |key, val|
|
88
|
+
if val.kind_of?(Hash) && hash[key]
|
89
|
+
prop_merge!(hash[key], val)
|
90
|
+
else
|
91
|
+
hash[key] = val
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
hash
|
96
|
+
end
|
84
97
|
|
85
98
|
# Merges topology properties into nodes, returning the merged nodes
|
86
99
|
def merge_topo_properties(nodes, topo_hash)
|
87
100
|
|
88
|
-
if nodes
|
89
|
-
merged_nodes = nodes.clone
|
101
|
+
if nodes && nodes.length > 0
|
102
|
+
merged_nodes = nodes ? nodes.clone : {}
|
90
103
|
merged_nodes.each do |nodeprops|
|
91
104
|
|
105
|
+
normal_defaults = topo_hash['normal'] ? topo_hash['normal'].clone : {}
|
106
|
+
nodeprops['normal'] ||= {}
|
107
|
+
nodeprops['normal'] = prop_merge!(normal_defaults, nodeprops['normal'])
|
108
|
+
|
92
109
|
nodeprops['chef_environment'] ||= topo_hash['chef_environment'] if topo_hash['chef_environment']
|
93
110
|
|
94
111
|
# merge in the topology tags
|
95
|
-
nodeprops['tags']
|
96
|
-
|
97
|
-
|
98
|
-
nodeprops['normal'] = normal_defaults.merge(nodeprops['normal'] || {})
|
99
|
-
|
112
|
+
nodeprops['tags'] ||= []
|
113
|
+
nodeprops['tags'] |= topo_hash['tags'] if topo_hash['tags'] && topo_hash['tags'].length > 0
|
114
|
+
|
100
115
|
end
|
101
116
|
end
|
102
117
|
|
@@ -115,8 +130,14 @@ class Chef
|
|
115
130
|
nodes.each do |updates|
|
116
131
|
node_name = updates['name']
|
117
132
|
begin
|
133
|
+
|
118
134
|
# load then update and save the node
|
119
135
|
node = Chef::Node.load(node_name)
|
136
|
+
|
137
|
+
if updates['chef_environment'] && updates['chef_environment'] != node['chef_environment']
|
138
|
+
check_chef_env(topo['chef_environment'])
|
139
|
+
end
|
140
|
+
|
120
141
|
if updated_values = update_node_with_values(node, updates)
|
121
142
|
ui.info "Updating #{updated_values.join(', ')} on node #{node.name}"
|
122
143
|
node.save
|
@@ -142,7 +163,15 @@ class Chef
|
|
142
163
|
# Make updates into the original node, returning the list of updated properties.
|
143
164
|
def update_node_with_values(node, updates)
|
144
165
|
updated_properties = []
|
166
|
+
|
167
|
+
# merge the normal attributes (but not tags)
|
168
|
+
normal_updates = updates['normal'] || {}
|
169
|
+
normal_updates.delete('tags')
|
170
|
+
original_normal = node.normal.clone()
|
171
|
+
prop_merge!(node.normal, normal_updates)
|
172
|
+
updated_properties << 'normal' if (original_normal != node.normal)
|
145
173
|
|
174
|
+
# merge with existing runlist
|
146
175
|
if updates['run_list']
|
147
176
|
updated_run_list = RunList.new
|
148
177
|
updates['run_list'].each { |e| updated_run_list << e }
|
@@ -152,25 +181,19 @@ class Chef
|
|
152
181
|
end
|
153
182
|
end
|
154
183
|
|
184
|
+
# update chef env
|
155
185
|
new_chef_environment = updates['chef_environment']
|
156
186
|
if new_chef_environment && new_chef_environment != node.chef_environment
|
157
187
|
updated_properties << 'chef_environment'
|
158
188
|
node.chef_environment(new_chef_environment)
|
159
189
|
end
|
160
190
|
|
191
|
+
# merge tags
|
161
192
|
orig_num_tags = node.tags.length
|
162
193
|
updates['tags'] ||= [] # make sure tags are initialized
|
163
194
|
node.tag(*updates['tags'])
|
164
195
|
updated_properties << 'tags' if node.tags.length > orig_num_tags
|
165
196
|
|
166
|
-
normal_updates = updates['normal'] || {}
|
167
|
-
normal_updates.each do |key, value|
|
168
|
-
if (value != node.normal[key])
|
169
|
-
updated_properties << "normal.#{key}"
|
170
|
-
node.normal[key] = value
|
171
|
-
end
|
172
|
-
end
|
173
|
-
|
174
197
|
# return false if no updates, else return array of property names
|
175
198
|
updated_properties.length > 0 && updated_properties
|
176
199
|
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
##Setup
|
2
|
+
|
3
|
+
Assumptions for this demo: chefDK, Vagrant, VirtualBox and chef-zero
|
4
|
+
|
5
|
+
* [chefDK](http://www.getchef.com/downloads/chef-dk/)
|
6
|
+
|
7
|
+
* [Vagrant](https://www.vagrantup.com/downloads.html)
|
8
|
+
|
9
|
+
* [VirtualBox](https://www.virtualbox.org/wiki/Downloads)
|
10
|
+
|
11
|
+
If you have chefDK installed, you can use the embedded chef-zero at
|
12
|
+
/opt/chefdk/embedded/bin/chef-zero
|
13
|
+
|
14
|
+
or install it:
|
15
|
+
|
16
|
+
sudo gem install chef-zero
|
17
|
+
|
18
|
+
Copy `test-repo` into a working directory, either downloading it from
|
19
|
+
github or copying it from the installed knife-topo gem. You can use:
|
20
|
+
|
21
|
+
gem env
|
22
|
+
|
23
|
+
to get the path to your gems and then
|
24
|
+
|
25
|
+
```
|
26
|
+
cp -R <gem-path>/gems/knife-topo/test-repo ~
|
27
|
+
cd ~/test-repo
|
28
|
+
```
|
29
|
+
|
30
|
+
## Demo
|
31
|
+
|
32
|
+
This demo will create and bootstrap two nodes in a topology called test1:
|
33
|
+
|
34
|
+
* an application server with a specific version of nodejs (0.10.28), running
|
35
|
+
a test application
|
36
|
+
* a database server with a specific version of mongodb (2.6.1)
|
37
|
+
|
38
|
+
Each node in the topology will be tagged with 'testsys' and will
|
39
|
+
have an 'owner' and 'node_type' normal attribute.
|
40
|
+
|
41
|
+
The test1 topology will also contain a third node called buildserver01,
|
42
|
+
which is created but not bootstrapped. This node:
|
43
|
+
|
44
|
+
* Is in a different chef environment ('dev')
|
45
|
+
* Requires a different version of mongodb
|
46
|
+
|
47
|
+
In this demo
|
48
|
+
|
49
|
+
### Running the demo
|
50
|
+
|
51
|
+
From the test-repo, do the following. Note: you may be prompted to select the network to bridge to
|
52
|
+
|
53
|
+
vagrant up
|
54
|
+
|
55
|
+
This will start the virtual machines on a
|
56
|
+
private network using vagrant. Once the virtual machines are created,
|
57
|
+
start chef-zero listening on the same private network:
|
58
|
+
|
59
|
+
chef-zero -H 10.0.1.1
|
60
|
+
|
61
|
+
In another terminal, in test-repo:
|
62
|
+
|
63
|
+
```
|
64
|
+
berks install
|
65
|
+
berks upload
|
66
|
+
```
|
67
|
+
|
68
|
+
To create and bootstrap the test1 topology:
|
69
|
+
|
70
|
+
```
|
71
|
+
knife topo import topology.json
|
72
|
+
knife topo create test1 --bootstrap -x vagrant -P vagrant --sudo
|
73
|
+
```
|
74
|
+
|
75
|
+
To check the bootstrap has succeeded, browse to:
|
76
|
+
[http://localhost:3031](http://localhost:3031).
|
77
|
+
You should see a "Welcome" message.
|
78
|
+
|
79
|
+
You can see the results on the Chef server
|
80
|
+
using standard knife commands, for example:
|
81
|
+
|
82
|
+
```
|
83
|
+
knife node list
|
84
|
+
knife node show appserver01
|
85
|
+
knife node show appserver01 -a normal
|
86
|
+
knife data bag show topologies test1
|
87
|
+
```
|
88
|
+
|
89
|
+
You can try your own modifications to the topologies.json file. To
|
90
|
+
update the topology with the modified configuration:
|
91
|
+
|
92
|
+
```
|
93
|
+
knife topo import your_topology.json
|
94
|
+
knife topo update test1
|
95
|
+
```
|
96
|
+
|
97
|
+
|
98
|
+
####Troubleshooting
|
99
|
+
|
100
|
+
If you are having trouble with berks (`read server certificate B:
|
101
|
+
certificate verify failed (Faraday::SSLError)`
|
102
|
+
try following the instructions
|
103
|
+
[here](https://gist.github.com/fnichol/867550#the-manual-way-boring)
|
104
|
+
to add CA certificates for OpenSSL
|
105
|
+
|
106
|
+
If the bootstrap fails with 'ERROR: 412 "Precondition Failed"', make sure
|
107
|
+
you have run `berks upload` since you started chef-zero.
|
108
|
+
|
109
|
+
I encountered some problems getting chef-zero to run on a private network
|
110
|
+
on Windows 8.1 (it responded really really slowly).
|
111
|
+
If you have similar problems, you can use hosted Chef
|
112
|
+
(sign up for a free account [here](https://manage.opscode.com/signup))
|
113
|
+
or your own Chef server. Copy your knife settings and certificates (e.g.,
|
114
|
+
the contents of chef-repo/.chef in the "Getting Started" download) into
|
115
|
+
test-repo/.chef, and replace the Vagrantfile in test-repo with
|
116
|
+
Vagrantfile_bridged (which will allow the VMs to connect to addresses
|
117
|
+
outside of the host).
|
118
|
+
|
119
|
+
If you modify the cookbook_attributes for mongodb and this causes
|
120
|
+
a downgrade, the Chef run may fail to converge.
|
121
|
+
There is an [issue](https://github.com/edelight/chef-mongodb/pull/305)
|
122
|
+
in the current cookbook which has been fixed but
|
123
|
+
not released (as of 19 July 2014). Run the following to remove the
|
124
|
+
installed mongodb and then retry the knife topo bootstrap:
|
125
|
+
|
126
|
+
vagrant ssh dbserver -c 'sudo apt-get remove mongodb'
|
127
|
+
|
128
|
+
If you have changed the nodejs version, you need to also change the
|
129
|
+
SHA256 checksum. This can be found at
|
130
|
+
http://nodejs.org/dist/v0.xx.xx/SHASUMS256.txt. The one you want is
|
131
|
+
for 'node-v0.xx.xx-linux-x64.tar.gz'
|
data/test-repo/Vagrantfile
CHANGED
@@ -19,11 +19,11 @@ qual = "0#{id}"
|
|
19
19
|
nodes = {
|
20
20
|
:dbserver => {
|
21
21
|
:hostname => "dbserver#{qual}",
|
22
|
-
:
|
22
|
+
:private_ipaddress => "10.0.#{id}.2"
|
23
23
|
},
|
24
24
|
:appserver => {
|
25
25
|
:hostname => "appserver#{qual}",
|
26
|
-
:
|
26
|
+
:private_ipaddress => "10.0.#{id}.3",
|
27
27
|
:forwardports => [
|
28
28
|
{
|
29
29
|
:guest => 3001,
|
@@ -39,14 +39,9 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
|
|
39
39
|
nodes.each do |node, options|
|
40
40
|
config.vm.define node do |node_config|
|
41
41
|
|
42
|
-
# setup networking using private network, with port forwarding where needed to access
|
43
|
-
|
44
|
-
|
45
|
-
if options.has_key?(:public)
|
46
|
-
node_config.vm.network net_type, ip: options[:ipaddress]
|
47
|
-
else
|
48
|
-
node_config.vm.network net_type, ip: options[:ipaddress]
|
49
|
-
end
|
42
|
+
# setup networking using private network, with port forwarding where needed to access, and optional bridge
|
43
|
+
node_config.vm.network :public_network if options.has_key?(:public)
|
44
|
+
node_config.vm.network :private_network, ip: options[:private_ipaddress] if options.has_key?(:private_ipaddress)
|
50
45
|
|
51
46
|
if options.has_key?(:forwardports)
|
52
47
|
options[:forwardports].each do |port|
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# -*- mode: ruby -*-
|
2
|
+
# vi: set ft=ruby :
|
3
|
+
|
4
|
+
# This Vagrantfile was inspired by Joshua Timberman's blog
|
5
|
+
# http://jtimberman.housepub.org/blog/2012/03/18/multivm-vagrantfile-for-chef/
|
6
|
+
|
7
|
+
#
|
8
|
+
# Vagrantfile for two-machine test topology. Runs with a bridged network
|
9
|
+
# and port forwarding from 3001 on appserver guest, to port 303n on host (i.e. 3031 for topo with id 1).
|
10
|
+
# ipaddresses are 10.0.1.2, 10.0.1.3 for dbserver, appserver.
|
11
|
+
|
12
|
+
# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
|
13
|
+
VAGRANTFILE_API_VERSION = "2"
|
14
|
+
|
15
|
+
id = 1
|
16
|
+
qual = "0#{id}"
|
17
|
+
|
18
|
+
# Define the options for each node
|
19
|
+
nodes = {
|
20
|
+
:dbserver => {
|
21
|
+
:hostname => "dbserver#{qual}",
|
22
|
+
:private_ipaddress => "10.0.#{id}.2",
|
23
|
+
:public => true
|
24
|
+
},
|
25
|
+
:appserver => {
|
26
|
+
:hostname => "appserver#{qual}",
|
27
|
+
:private_ipaddress => "10.0.#{id}.3",
|
28
|
+
:public => true,
|
29
|
+
:forwardports => [
|
30
|
+
{
|
31
|
+
:guest => 3001,
|
32
|
+
:host => (3030 + id)
|
33
|
+
}
|
34
|
+
]
|
35
|
+
}
|
36
|
+
}
|
37
|
+
|
38
|
+
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
|
39
|
+
|
40
|
+
# setup each node using config ("options") defined above
|
41
|
+
nodes.each do |node, options|
|
42
|
+
config.vm.define node do |node_config|
|
43
|
+
|
44
|
+
# setup networking using private network, with port forwarding where needed to access, and optional bridge
|
45
|
+
node_config.vm.network :public_network if options.has_key?(:public)
|
46
|
+
node_config.vm.network :private_network, ip: options[:private_ipaddress] if options.has_key?(:private_ipaddress)
|
47
|
+
|
48
|
+
node_config.vm.hostname = options[:hostname]
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# Setup the generic config across both servers
|
53
|
+
config.vm.box = "ubuntu64"
|
54
|
+
|
55
|
+
# The url from where the 'config.vm.box' box will be fetched if it
|
56
|
+
# doesn't already exist on the user's system.
|
57
|
+
config.vm.box_url = "http://files.vagrantup.com/precise64.box"
|
58
|
+
|
59
|
+
end
|
data/test-repo/topology.json
CHANGED
@@ -22,7 +22,8 @@
|
|
22
22
|
[
|
23
23
|
"recipe[apt]",
|
24
24
|
"recipe[testapp::appserver]",
|
25
|
-
"testapp::deploy"
|
25
|
+
"testapp::deploy",
|
26
|
+
"testsys_test1"
|
26
27
|
],
|
27
28
|
|
28
29
|
"normal":
|
@@ -39,7 +40,8 @@
|
|
39
40
|
"run_list":
|
40
41
|
[
|
41
42
|
"recipe[apt]",
|
42
|
-
"recipe[testapp::db]"
|
43
|
+
"recipe[testapp::db]",
|
44
|
+
"testsys_test1"
|
43
45
|
],
|
44
46
|
|
45
47
|
"tags":
|
@@ -54,22 +56,49 @@
|
|
54
56
|
"node_type": "dbserver"
|
55
57
|
}
|
56
58
|
}
|
59
|
+
},
|
60
|
+
{
|
61
|
+
"name": "buildserver01",
|
62
|
+
"chef_environment": "dev",
|
63
|
+
"run_list":
|
64
|
+
[
|
65
|
+
"recipe[apt]",
|
66
|
+
"recipe[testapp::db]",
|
67
|
+
"recipe[testapp::appserver]",
|
68
|
+
"recipe[testapp::deploy]",
|
69
|
+
"testsys_test1"
|
70
|
+
],
|
71
|
+
|
72
|
+
"tags":
|
73
|
+
[
|
74
|
+
],
|
75
|
+
|
76
|
+
"normal":
|
77
|
+
{
|
78
|
+
"topo":
|
79
|
+
{
|
80
|
+
"node_type": "buildserver"
|
81
|
+
}
|
82
|
+
}
|
57
83
|
}
|
58
84
|
],
|
59
85
|
|
60
86
|
"cookbook_attributes":
|
61
87
|
[
|
62
88
|
{
|
89
|
+
"cookbook": "testsys_test1",
|
90
|
+
"filename": "softwareversion",
|
63
91
|
"normal":
|
64
|
-
{
|
92
|
+
{
|
65
93
|
"nodejs":
|
66
94
|
{
|
67
|
-
"version": "0.28"
|
95
|
+
"version": "0.10.28",
|
96
|
+
"checksum_linux_x64": "5f41f4a90861bddaea92addc5dfba5357de40962031c2281b1683277a0f75932"
|
68
97
|
},
|
69
98
|
|
70
99
|
"testapp":
|
71
100
|
{
|
72
|
-
"version": "
|
101
|
+
"version": "0.0.3"
|
73
102
|
},
|
74
103
|
|
75
104
|
"mongodb":
|
@@ -77,11 +106,10 @@
|
|
77
106
|
"package_version": "2.6.1"
|
78
107
|
}
|
79
108
|
},
|
80
|
-
|
81
|
-
"node_type":
|
82
|
-
{
|
83
|
-
"buildserver":
|
109
|
+
"conditional" : [
|
84
110
|
{
|
111
|
+
"qualifier": "node_type",
|
112
|
+
"value" : "buildserver",
|
85
113
|
"normal":
|
86
114
|
{
|
87
115
|
"mongodb":
|
@@ -90,10 +118,7 @@
|
|
90
118
|
}
|
91
119
|
}
|
92
120
|
}
|
93
|
-
|
94
|
-
|
95
|
-
"cookbook": "testsys_test1",
|
96
|
-
"filename": "softwareversion"
|
121
|
+
]
|
97
122
|
}
|
98
123
|
]
|
99
124
|
}
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: knife-topo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-07-
|
12
|
+
date: 2014-07-20 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: Knife plugin that to manage topologies of nodes
|
15
15
|
email:
|
@@ -30,8 +30,8 @@ files:
|
|
30
30
|
- test-repo/topology.json
|
31
31
|
- test-repo/Berksfile
|
32
32
|
- test-repo/Vagrantfile
|
33
|
-
- test-repo/
|
34
|
-
- test-repo/
|
33
|
+
- test-repo/Instructions.md
|
34
|
+
- test-repo/Vagrantfile_bridged
|
35
35
|
- test-repo/cookbooks/testapp/recipes/appserver.rb
|
36
36
|
- test-repo/cookbooks/testapp/recipes/deploy.rb
|
37
37
|
- test-repo/cookbooks/testapp/recipes/default.rb
|
data/test-repo/Instructions.txt
DELETED
@@ -1,48 +0,0 @@
|
|
1
|
-
# Assumptions for this demo: chefDK, Vagrant, VirtualBox and chef-zero
|
2
|
-
|
3
|
-
# chefDK can be obtained from:
|
4
|
-
http://www.getchef.com/downloads/chef-dk/
|
5
|
-
|
6
|
-
# vagrant can be installed from:
|
7
|
-
https://www.vagrantup.com/downloads.html
|
8
|
-
|
9
|
-
# VirtualBox can be obtained from:
|
10
|
-
https://www.virtualbox.org/wiki/Downloads
|
11
|
-
|
12
|
-
# If you have chefDK installed, you can use the embedded chef-zero
|
13
|
-
/opt/chefdk/embedded/bin/chef-zero
|
14
|
-
|
15
|
-
# or install it
|
16
|
-
sudo gem install chef-zero
|
17
|
-
|
18
|
-
# Copy test-repo into a working directory, either downloading it from github or copying it from the installed
|
19
|
-
# knife-topo gem. You can use
|
20
|
-
gem env
|
21
|
-
# to get the path to your gems and then
|
22
|
-
cp -R <path-to-gem>/knife-topo/test-repo ~
|
23
|
-
cd ~/test-repo
|
24
|
-
|
25
|
-
# From the test-repo, do the following to start the virtual machines on a private network using vagrant -
|
26
|
-
# Note: you may be prompted to select the network to bridge to
|
27
|
-
vagrant up
|
28
|
-
|
29
|
-
# Once the virtual machines are created, start chef-zero listening on the same private network:
|
30
|
-
chef-zero -H 10.0.1.1
|
31
|
-
|
32
|
-
# In another terminal, in test-repo:
|
33
|
-
berks install
|
34
|
-
berks upload
|
35
|
-
|
36
|
-
# To create and bootstrap the test1 topology
|
37
|
-
knife topo import exchange.json
|
38
|
-
knife topo create sys1_test test1
|
39
|
-
knife topo bootstrap sys1_test test1 -x vagrant -P vagrant --sudo
|
40
|
-
|
41
|
-
|
42
|
-
# To check the bootstrap has succeeded, browse to:
|
43
|
-
http://localhost:3031
|
44
|
-
# You should see a "Welcome" message
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
@@ -1,117 +0,0 @@
|
|
1
|
-
[{
|
2
|
-
"name": "test1",
|
3
|
-
"chef_environment": "test",
|
4
|
-
"tags":
|
5
|
-
[
|
6
|
-
"testsys"
|
7
|
-
],
|
8
|
-
"normal":
|
9
|
-
{
|
10
|
-
"owner": {
|
11
|
-
"name": "Christine Draper",
|
12
|
-
"phone": "512-xxx-xxxx",
|
13
|
-
"email": "christine_draper@thirdwaveinsights.com"
|
14
|
-
}
|
15
|
-
},
|
16
|
-
"nodes":
|
17
|
-
{
|
18
|
-
"appserver":
|
19
|
-
{
|
20
|
-
"name": "appserver01",
|
21
|
-
"ssh_host": "10.0.1.3",
|
22
|
-
"run_list":
|
23
|
-
[
|
24
|
-
"recipe[apt]",
|
25
|
-
"recipe[testapp::appserver]",
|
26
|
-
"testapp::deploy"
|
27
|
-
],
|
28
|
-
|
29
|
-
"normal":
|
30
|
-
{
|
31
|
-
"topo":
|
32
|
-
{
|
33
|
-
"node_type": "appserver"
|
34
|
-
}
|
35
|
-
}
|
36
|
-
},
|
37
|
-
|
38
|
-
"dbserver":
|
39
|
-
{
|
40
|
-
"name": "dbserver01",
|
41
|
-
"ssh_host": "10.0.1.2",
|
42
|
-
"run_list":
|
43
|
-
[
|
44
|
-
"recipe[apt]",
|
45
|
-
"recipe[testapp::db]"
|
46
|
-
],
|
47
|
-
|
48
|
-
"tags":
|
49
|
-
[
|
50
|
-
"testapp_database"
|
51
|
-
],
|
52
|
-
|
53
|
-
"normal":
|
54
|
-
{
|
55
|
-
"topo":
|
56
|
-
{
|
57
|
-
"node_type": "dbserver"
|
58
|
-
}
|
59
|
-
}
|
60
|
-
}
|
61
|
-
},
|
62
|
-
|
63
|
-
"cookbook_attributes":
|
64
|
-
[
|
65
|
-
{
|
66
|
-
"normal":
|
67
|
-
{
|
68
|
-
"nodejs":
|
69
|
-
{
|
70
|
-
"version": "0.28"
|
71
|
-
},
|
72
|
-
|
73
|
-
"testapp":
|
74
|
-
{
|
75
|
-
"version": "1.0"
|
76
|
-
},
|
77
|
-
|
78
|
-
"mongodb":
|
79
|
-
{
|
80
|
-
"package_version": "2.6.1"
|
81
|
-
}
|
82
|
-
},
|
83
|
-
|
84
|
-
"node_type":
|
85
|
-
{
|
86
|
-
"buildserver":
|
87
|
-
{
|
88
|
-
"normal":
|
89
|
-
{
|
90
|
-
"mongodb":
|
91
|
-
{
|
92
|
-
"package_version": "2.5.1"
|
93
|
-
}
|
94
|
-
}
|
95
|
-
}
|
96
|
-
},
|
97
|
-
|
98
|
-
"cookbook": "testsys_test1",
|
99
|
-
"filename": "softwareversion"
|
100
|
-
}
|
101
|
-
]
|
102
|
-
},
|
103
|
-
{
|
104
|
-
"name": "test2",
|
105
|
-
"chef_environment": "test",
|
106
|
-
"tags":
|
107
|
-
[
|
108
|
-
"testsys"
|
109
|
-
],
|
110
|
-
"normal":
|
111
|
-
{
|
112
|
-
"owner": "John Sweitzer"
|
113
|
-
},
|
114
|
-
"nodes":
|
115
|
-
{
|
116
|
-
}
|
117
|
-
}]
|