chef-vpc-toolkit 2.0.1 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm 1.8.7@chef_vpc_toolkit
data/CHANGELOG ADDED
@@ -0,0 +1,14 @@
1
+ * Tue Jan 11 2011 Dan Prince <dan.prince@rackspace.com> - 2.1.0
2
+ - Implement 'rake vpn' tasks.
3
+ - Set permission to 0600 on tmp/server_group files.
4
+ - Create config/TOOLKIT_VERSION when running chef-vpc-toolkit -upgrade.
5
+ - Set 'StrictHostKeyChecking no' when using ssh.
6
+
7
+ * Thu Dec 7 2010 Dan Prince <dan.prince@rackspace.com> - 2.0.1
8
+ - Automatically load rake files from the tasks directory.
9
+ - Rename config file from cloud_toolkit.conf to chef_vpc_toolkit.conf.
10
+ - Rename variable that can be used to override default config file location
11
+ to be called CHEF_VPC_TOOLKIT_CONF.
12
+
13
+ * Thu Oct 26 2010 Dan Prince <dan.prince@rackspace.com> - 2.0.0
14
+ - Initial open source release.
data/Rakefile CHANGED
@@ -28,6 +28,7 @@ begin
28
28
  gemspec.add_dependency 'rake'
29
29
  gemspec.add_dependency 'builder'
30
30
  gemspec.add_dependency 'json'
31
+ gemspec.add_dependency 'uuidtools'
31
32
  end
32
33
  rescue LoadError
33
34
  puts "Jeweler not available. Install it with: sudo gem install jeweler"
data/VERSION CHANGED
@@ -1 +1 @@
1
- 2.0.1
1
+ 2.1.0
data/bin/chef-vpc-toolkit CHANGED
@@ -13,17 +13,17 @@ opts = OptionParser.new
13
13
 
14
14
  options[:name] = ""
15
15
  opts.on("-n name", "--name", String,
16
- "Create a new cloud project with the given directory name.") do |name|
16
+ "Create a new project with the given directory name.") do |name|
17
17
  options[:name] = name
18
18
  end
19
19
 
20
20
  options[:upgrade] = false
21
- opts.on("-u", "--upgrade", "Upgrade a cloud project to work with the latest Cloud Toolkit.") do
21
+ opts.on("-u", "--upgrade", "Upgrade a project to work with the latest Chef VPC Toolkit.") do
22
22
  options[:upgrade] = true
23
23
  end
24
24
 
25
25
  opts.on_tail("-v", "--version", "Print version") do
26
- puts "Cloud Toolkit Version: #{Version::VERSION}"
26
+ puts "Chef VPC Toolkit Version: #{Version::VERSION}"
27
27
  exit
28
28
  end
29
29
 
@@ -47,10 +47,10 @@ if options[:upgrade]
47
47
 
48
48
  # Rakefile
49
49
  if not File.exists?("Rakefile") then
50
- puts "Unable to find Rakefile. Run the 'cloud-toolkit -u' commmand from within a cloud project directory."
50
+ puts "Unable to find Rakefile. Run the 'chef-vpc-toolkit -u' commmand from within a project directory."
51
51
  exit 1
52
52
  else
53
- FileUtils.cp("#{Version::CHEF_VPC_TOOLKIT_ROOT}/contrib/Rakefile", "Rakefile")
53
+ FileUtils.cp("#{Version::CHEF_VPC_TOOLKIT_ROOT}/contrib/rake/Rakefile", "Rakefile")
54
54
  end
55
55
 
56
56
  # chef_installer.yml
@@ -58,6 +58,8 @@ if options[:upgrade]
58
58
  FileUtils.mv("config/chef_installer.conf", "config/chef_installer.yml")
59
59
  end
60
60
 
61
+ FileUtils.cp("#{Version::CHEF_VPC_TOOLKIT_ROOT}/VERSION", File.join("config", "TOOLKIT_VERSION"))
62
+
61
63
  else
62
64
  exit_if_nil_or_empty(options, :name)
63
65
 
@@ -5,12 +5,12 @@
5
5
  "servers": {
6
6
  "login": {
7
7
  "image_id": "51",
8
- "flavor_id": "4",
8
+ "flavor_id": "2",
9
9
  "openvpn_server": "true"
10
10
  },
11
11
  "client1": {
12
12
  "image_id": "51",
13
- "flavor_id": "4"
13
+ "flavor_id": "2"
14
14
  }
15
15
  }
16
16
  }
@@ -8,3 +8,7 @@ cloud_servers_vpc_password:
8
8
  # The text editor to use for Chef knife commands. Used when a new server group
9
9
  # is created. Default: vim
10
10
  # knife_editor: vim
11
+ #
12
+ # VPN client name. The name given to this machine when connecting to a
13
+ # server group as a VPN client.
14
+ # vpn_client_name: local
@@ -5,9 +5,9 @@ require 'rubygems'
5
5
  version_file=(File.join(CHEF_VPC_PROJECT, 'config', 'TOOLKIT_VERSION'))
6
6
  toolkit_version=nil
7
7
  if ENV['CHEF_VPC_TOOLKIT_VERSION'] then
8
- toolkit_version=ENV['CHEF_VPC_TOOLKIT_VERSION']
8
+ toolkit_version=ENV['CHEF_VPC_TOOLKIT_VERSION']
9
9
  elsif File.exists?(version_file)
10
- toolkit_version=IO.read(version_file)
10
+ toolkit_version=IO.read(version_file)
11
11
  end
12
12
 
13
13
  #puts "Chef VPC Toolkit Version: #{toolkit_version}"
@@ -22,7 +22,8 @@ Dir[File.join("#{ChefVPCToolkit::Version::CHEF_VPC_TOOLKIT_ROOT}/rake", '*.rake'
22
22
  import(rakefile)
23
23
  end
24
24
 
25
- Dir[File.join(File.dirname("__FILE__"), 'tasks', '*.rake')].each do |rakefile|
26
- puts rakefile
25
+ if File.exist?(File.join(CHEF_VPC_PROJECT, 'tasks')) then
26
+ Dir[File.join(File.dirname("__FILE__"), 'tasks', '*.rake')].each do |rakefile|
27
27
  import(rakefile)
28
+ end
28
29
  end
@@ -4,3 +4,4 @@ require 'chef-vpc-toolkit/cloud_servers_vpc'
4
4
  require 'chef-vpc-toolkit/http_util'
5
5
  require 'chef-vpc-toolkit/ssh_util'
6
6
  require 'chef-vpc-toolkit/version'
7
+ require 'chef-vpc-toolkit/vpn_network_manager'
@@ -166,7 +166,7 @@ local REPOS_BASEDIR=${2:-"/root/cookbook-repos"}
166
166
  for CB_REPO in $COOKBOOK_URLS; do
167
167
  echo -n "Downloading $CB_REPO..."
168
168
  if [ "http:" == ${CB_REPO:0:5} ] || [ "https:" == ${CB_REPO:0:6} ]; then
169
- wget "$CB_REPO" -O "/tmp/cookbook-repo.tar.gz" &> /dev/null || { echo "Failed to download cookbook tarball."; return 1; }
169
+ wget --no-check-certificate "$CB_REPO" -O "/tmp/cookbook-repo.tar.gz" &> /dev/null || { echo "Failed to download cookbook tarball."; return 1; }
170
170
  else
171
171
  download_cloud_file "$CB_REPO" "/tmp/cookbook-repo.tar.gz"
172
172
  fi
@@ -34,8 +34,9 @@ validation_key "/etc/chef/validation.pem"
34
34
  client_key "/etc/chef/client.pem"
35
35
  EOF_CAT
36
36
 
37
- cp /usr/lib/ruby/gems/1.8/gems/chef-0.9.8/distro/redhat/etc/init.d/chef-client /etc/init.d/
38
- cp /usr/lib/ruby/gems/1.8/gems/chef-0.9.8/distro/redhat/etc/logrotate.d/chef-client /etc/logrotate.d/
37
+ CHEF_GEM_DIR=$(gem contents chef | sed -e "s|\(.*chef-0.9.8\).*|\1|" | head -n 1)
38
+ cp $CHEF_GEM_DIR/distro/redhat/etc/init.d/chef-client /etc/init.d/
39
+ cp $CHEF_GEM_DIR/distro/redhat/etc/logrotate.d/chef-client /etc/logrotate.d/
39
40
  chmod 755 /etc/init.d/chef-client
40
41
 
41
42
  }
@@ -72,7 +72,7 @@ end
72
72
  os_type=machine_os_types[options['chef_server_name']]
73
73
 
74
74
  data=%x{
75
- ssh root@#{options['ssh_gateway_ip']} bash <<-"EOF_GATEWAY"
75
+ ssh -o "StrictHostKeyChecking no" root@#{options['ssh_gateway_ip']} bash <<-"EOF_GATEWAY"
76
76
  ssh #{options['chef_server_name']} bash <<-"EOF_BASH"
77
77
  echo "Installing Chef server on: $HOSTNAME"
78
78
  EOF_BASH
@@ -81,7 +81,7 @@ EOF_GATEWAY
81
81
  puts data
82
82
 
83
83
  data=%x{
84
- ssh root@#{options['ssh_gateway_ip']} bash <<-"EOF_GATEWAY"
84
+ ssh -o "StrictHostKeyChecking no" root@#{options['ssh_gateway_ip']} bash <<-"EOF_GATEWAY"
85
85
  ssh #{options['chef_server_name']} bash <<-"EOF_BASH"
86
86
  #{IO.read(File.dirname(__FILE__) + "/cloud_files.bash")}
87
87
  #{IO.read(File.dirname(__FILE__) + "/chef_bootstrap/#{os_type}.bash")}
@@ -115,7 +115,7 @@ end
115
115
  def self.client_validation_key(options)
116
116
 
117
117
  client_validation_key=%x{
118
- ssh root@#{options['ssh_gateway_ip']} bash <<-"EOF_GATEWAY"
118
+ ssh -o "StrictHostKeyChecking no" root@#{options['ssh_gateway_ip']} bash <<-"EOF_GATEWAY"
119
119
  ssh #{options['chef_server_name']} bash <<-"EOF_BASH"
120
120
  #{IO.read(CHEF_INSTALL_FUNCTIONS)}
121
121
  print_client_validation_key
@@ -146,7 +146,7 @@ def self.install_chef_client(options, client_name, client_validation_key, os_typ
146
146
  puts "Installing Chef client on: #{client_name}"
147
147
 
148
148
  data=%x{
149
- ssh root@#{options['ssh_gateway_ip']} bash <<-"EOF_GATEWAY"
149
+ ssh -o "StrictHostKeyChecking no" root@#{options['ssh_gateway_ip']} bash <<-"EOF_GATEWAY"
150
150
  ssh #{client_name} bash <<-"EOF_BASH"
151
151
  #{IO.read(File.dirname(__FILE__) + "/cloud_files.bash")}
152
152
  #{IO.read(File.dirname(__FILE__) + "/chef_bootstrap/#{os_type}.bash")}
@@ -192,15 +192,16 @@ json.each_pair do |bag_name, items_json|
192
192
  end
193
193
 
194
194
  data=%x{
195
- ssh root@#{options['ssh_gateway_ip']} bash <<-"EOF_GATEWAY"
195
+ ssh -o "StrictHostKeyChecking no" root@#{options['ssh_gateway_ip']} bash <<-"EOF_GATEWAY"
196
196
  #{IO.read(CHEF_INSTALL_FUNCTIONS)}
197
197
  #{databag_cmds}
198
198
  EOF_GATEWAY
199
199
  }
200
- puts "OK."
201
200
 
202
201
  end
203
202
 
203
+ puts "OK."
204
+
204
205
  end
205
206
 
206
207
  def self.knife_readd_node(options, client_name)
@@ -214,7 +215,7 @@ run_list=node_json['run_list'].inspect
214
215
  node_json.delete("run_list")
215
216
  attributes=node_json.to_json.to_s
216
217
  data=%x{
217
- ssh root@#{options['ssh_gateway_ip']} bash <<-"EOF_GATEWAY"
218
+ ssh -o "StrictHostKeyChecking no" root@#{options['ssh_gateway_ip']} bash <<-"EOF_GATEWAY"
218
219
  #{IO.read(CHEF_INSTALL_FUNCTIONS)}
219
220
  knife_delete_node '#{client_name}'
220
221
  knife_add_node '#{client_name}' '#{run_list}' '#{attributes}'
@@ -224,7 +225,7 @@ EOF_GATEWAY
224
225
  end
225
226
 
226
227
  def self.tail_log(gateway_ip, server_name, log_file="/var/log/chef/client.log", num_lines="100")
227
- %x{ssh root@#{gateway_ip} ssh #{server_name} tail -n #{num_lines} #{log_file}}
228
+ %x{ssh -o "StrictHostKeyChecking no" root@#{gateway_ip} ssh #{server_name} tail -n #{num_lines} #{log_file}}
228
229
  end
229
230
 
230
231
  def self.rsync_cookbook_repos(options, local_dir="#{CHEF_VPC_PROJECT}/cookbook-repos/", remote_directory="/root/cookbook-repos")
@@ -232,7 +233,7 @@ def self.rsync_cookbook_repos(options, local_dir="#{CHEF_VPC_PROJECT}/cookbook-r
232
233
  if File.exists?(local_dir) then
233
234
  $stdout.printf "Syncing local Chef cookbook repositories..."
234
235
  configs=Util.load_configs
235
- %x{ssh root@#{options['ssh_gateway_ip']} bash <<-"EOF_SSH"
236
+ %x{ssh -o "StrictHostKeyChecking no" root@#{options['ssh_gateway_ip']} bash <<-"EOF_SSH"
236
237
  mkdir -p #{remote_directory}
237
238
  if [ -f /usr/bin/yum ]; then
238
239
  rpm -q rsync &> /dev/null || yum install -y -q rsync
@@ -251,7 +252,7 @@ def self.rsync_cookbook_repos(options, local_dir="#{CHEF_VPC_PROJECT}/cookbook-r
251
252
  end
252
253
 
253
254
  data=%x{
254
- ssh root@#{options['ssh_gateway_ip']} bash <<-"EOF_SSH"
255
+ ssh -o "StrictHostKeyChecking no" root@#{options['ssh_gateway_ip']} bash <<-"EOF_SSH"
255
256
  #{IO.read(File.dirname(__FILE__) + "/cloud_files.bash")}
256
257
  #{IO.read(CHEF_INSTALL_FUNCTIONS)}
257
258
 
@@ -83,7 +83,8 @@ module CloudServersVPC
83
83
  hash["description"]=sg.elements["description"].text
84
84
  hash["id"]=sg.elements["id"].text
85
85
  hash["domain-name"]=sg.elements["domain-name"].text
86
-
86
+ hash["vpn-network"]=sg.elements["vpn-network"].text
87
+ hash["vpn-subnet"]=sg.elements["vpn-subnet"].text
87
88
  hash["servers"]={}
88
89
  REXML::XPath.each(dom, "//server") do |server|
89
90
  server_name=server.elements["name"].text
@@ -180,6 +181,21 @@ module CloudServersVPC
180
181
 
181
182
  end
182
183
 
184
+ # Return the name of the VPN server within a server group
185
+ def self.vpn_server_name(hash)
186
+
187
+ hash["servers"].each_pair do |name, hash|
188
+ if hash['openvpn-server'] and hash['openvpn-server'] == "true" then
189
+ if block_given? then
190
+ yield name
191
+ else
192
+ return name
193
+ end
194
+ end
195
+ end
196
+
197
+ end
198
+
183
199
  # default timeout of 20 minutes
184
200
  def self.poll_until_online(group_id, timeout=1200)
185
201
 
@@ -229,6 +245,8 @@ module CloudServersVPC
229
245
  "centos"
230
246
  when 187811 # Centos 5.4
231
247
  "centos"
248
+ when 71 # Fedora 14
249
+ "fedora"
232
250
  when 53 # Fedora 13
233
251
  "fedora"
234
252
  when 17 # Fedora 12
@@ -280,6 +298,96 @@ module CloudServersVPC
280
298
 
281
299
  end
282
300
 
301
+ def self.client_hash(xml)
302
+
303
+ hash={}
304
+ dom = REXML::Document.new(xml)
305
+ REXML::XPath.each(dom, "/client") do |client|
306
+
307
+ hash["name"]=client.elements["name"].text
308
+ hash["description"]=client.elements["description"].text
309
+ hash["id"]=client.elements["id"].text
310
+ hash["status"]=client.elements["status"].text
311
+ hash["server-group-id"]=client.elements["server-group-id"].text
312
+ hash["vpn-network-interfaces"]=[]
313
+ REXML::XPath.each(dom, "//vpn-network-interface") do |vni|
314
+ client_attributes={
315
+ "id" => vni.elements["id"].text,
316
+ "vpn-ip-addr" => vni.elements["vpn-ip-addr"].text,
317
+ "ptp-ip-addr" => vni.elements["ptp-ip-addr"].text,
318
+ "client-key" => vni.elements["client-key"].text,
319
+ "client-cert" => vni.elements["client-cert"].text,
320
+ "ca-cert" => vni.elements["ca-cert"].text
321
+ }
322
+ hash["vpn-network-interfaces"] << client_attributes
323
+ end
324
+ end
325
+
326
+ hash
327
+
328
+ end
329
+
330
+ def self.poll_client(client_id, timeout=300)
331
+
332
+ configs=Util.load_configs
333
+
334
+ online = false
335
+ count=0
336
+ until online or (count*5) >= timeout.to_i do
337
+ count+=1
338
+ begin
339
+ xml=HttpUtil.get(
340
+ configs["cloud_servers_vpc_url"]+"/clients/#{client_id}.xml",
341
+ configs["cloud_servers_vpc_username"],
342
+ configs["cloud_servers_vpc_password"]
343
+ )
344
+ hash=CloudServersVPC.client_hash(xml)
345
+
346
+ if hash["status"] == "Online" then
347
+ online = true
348
+ else
349
+ yield hash if block_given?
350
+ sleep 5
351
+ end
352
+ rescue EOFError
353
+ end
354
+ end
355
+ if (count*20) >= timeout.to_i then
356
+ raise "Timeout waiting for client to come online."
357
+ end
358
+
359
+ end
360
+
361
+ def self.client_xml_for_id(configs, dir, id=nil)
362
+
363
+ xml=HttpUtil.get(
364
+ configs["cloud_servers_vpc_url"]+"/clients/#{id}.xml",
365
+ configs["cloud_servers_vpc_username"],
366
+ configs["cloud_servers_vpc_password"]
367
+ )
368
+
369
+ end
370
+
371
+ def self.create_client(server_group_hash, client_name)
372
+
373
+ configs=Util.load_configs
374
+
375
+ xml = Builder::XmlMarkup.new
376
+ xml.client do |client|
377
+ client.name(client_name)
378
+ client.description("Toolkit Client: #{client_name}")
379
+ client.tag! "server-group-id", server_group_hash['id']
380
+ end
381
+
382
+ HttpUtil.post(
383
+ configs["cloud_servers_vpc_url"]+"/clients.xml",
384
+ xml.target!,
385
+ configs["cloud_servers_vpc_username"],
386
+ configs["cloud_servers_vpc_password"]
387
+ )
388
+
389
+ end
390
+
283
391
  end
284
392
 
285
393
  end
@@ -72,6 +72,7 @@ def self.post(url_string, post_data, auth_user=nil, auth_password=nil)
72
72
  when Net::HTTPSuccess
73
73
  return response.body
74
74
  else
75
+ puts response.body
75
76
  response.error!
76
77
  end
77
78
  end
@@ -1,9 +1,14 @@
1
1
  require 'yaml'
2
+ require 'socket'
2
3
 
3
4
  module ChefVPCToolkit
4
5
 
5
6
  module Util
6
7
 
8
+ def self.hostname
9
+ Socket.gethostname
10
+ end
11
+
7
12
  def self.load_configs
8
13
 
9
14
  config_file=ENV['CHEF_VPC_TOOLKIT_CONF']
@@ -0,0 +1,227 @@
1
+ require 'json'
2
+ require 'builder'
3
+ require 'rexml/document'
4
+ require 'rexml/xpath'
5
+ require 'uuidtools'
6
+ require 'ipaddr'
7
+ require 'fileutils'
8
+ require 'tempfile'
9
+
10
+ module ChefVPCToolkit
11
+
12
+ module VpnNetworkManager
13
+
14
+ CERT_DIR=File.join(ENV['HOME'], '.pki', 'openvpn')
15
+
16
+ def self.configure_gconf(group_hash, client_hash)
17
+
18
+ ca_cert=File.join(CERT_DIR, group_hash['id'], 'ca.crt')
19
+ client_cert=File.join(CERT_DIR, group_hash['id'], 'client.crt')
20
+ client_key=File.join(CERT_DIR, group_hash['id'], 'client.key')
21
+
22
+ vpn_interface=client_hash['vpn-network-interfaces'][0]
23
+
24
+ FileUtils.mkdir_p(File.join(CERT_DIR, group_hash['id']))
25
+ File::chmod(0700, File.join(ENV['HOME'], '.pki'))
26
+ File::chmod(0700, CERT_DIR)
27
+
28
+ File.open(ca_cert, 'w') { |f| f.write(vpn_interface['ca-cert']) }
29
+ File.open(client_cert, 'w') { |f| f.write(vpn_interface['client-cert']) }
30
+ File.open(client_key, 'w') do |f|
31
+ f.write(vpn_interface['client-key'])
32
+ f.chmod(0600)
33
+ end
34
+
35
+ xml = Builder::XmlMarkup.new
36
+ xml.gconfentryfile do |file|
37
+ file.entrylist({ "base" => "/system/networking/connections/vpc_#{group_hash['id']}"}) do |entrylist|
38
+
39
+ entrylist.entry do |entry|
40
+ entry.key("connection/autoconnect")
41
+ entry.value do |value|
42
+ value.bool("false")
43
+ end
44
+ end
45
+ entrylist.entry do |entry|
46
+ entry.key("connection/id")
47
+ entry.value do |value|
48
+ value.string("VPC Group: #{group_hash['id']}")
49
+ end
50
+ end
51
+ entrylist.entry do |entry|
52
+ entry.key("connection/name")
53
+ entry.value do |value|
54
+ value.string("connection")
55
+ end
56
+ end
57
+ entrylist.entry do |entry|
58
+ entry.key("connection/timestamp")
59
+ entry.value do |value|
60
+ value.string(Time.now.to_i.to_s)
61
+ end
62
+ end
63
+ entrylist.entry do |entry|
64
+ entry.key("connection/type")
65
+ entry.value do |value|
66
+ value.string("vpn")
67
+ end
68
+ end
69
+ entrylist.entry do |entry|
70
+ entry.key("connection/uuid")
71
+ entry.value do |value|
72
+ value.string(UUIDTools::UUID.random_create)
73
+ end
74
+ end
75
+ entrylist.entry do |entry|
76
+ entry.key("ipv4/addresses")
77
+ entry.value do |value|
78
+ value.list("type" => "int") do |list|
79
+ end
80
+ end
81
+ end
82
+ entrylist.entry do |entry|
83
+ entry.key("ipv4/dns")
84
+ entry.value do |value|
85
+ value.list("type" => "int") do |list|
86
+ ip=IPAddr.new(group_hash['vpn-network'].chomp("0")+"1")
87
+ list.value do |lv|
88
+ lv.int(ip_to_integer(ip.to_s))
89
+ end
90
+ end
91
+ end
92
+ end
93
+ entrylist.entry do |entry|
94
+ entry.key("ipv4/dns-search")
95
+ entry.value do |value|
96
+ value.list("type" => "string") do |list|
97
+ list.value do |lv|
98
+ lv.string(group_hash['domain-name'])
99
+ end
100
+ end
101
+ end
102
+ end
103
+ entrylist.entry do |entry|
104
+ entry.key("ipv4/ignore-auto-dns")
105
+ entry.value do |value|
106
+ value.bool("true")
107
+ end
108
+ end
109
+ entrylist.entry do |entry|
110
+ entry.key("ipv4/method")
111
+ entry.value do |value|
112
+ value.string("auto")
113
+ end
114
+ end
115
+ entrylist.entry do |entry|
116
+ entry.key("ipv4/name")
117
+ entry.value do |value|
118
+ value.string("ipv4")
119
+ end
120
+ end
121
+ entrylist.entry do |entry|
122
+ entry.key("ipv4/never-default")
123
+ entry.value do |value|
124
+ value.bool("true")
125
+ end
126
+ end
127
+ entrylist.entry do |entry|
128
+ entry.key("ipv4/routes")
129
+ entry.value do |value|
130
+ value.list("type" => "int") do |list|
131
+ end
132
+ end
133
+ end
134
+ entrylist.entry do |entry|
135
+ entry.key("vpn/ca")
136
+ entry.value do |value|
137
+ value.string(ca_cert)
138
+ end
139
+ end
140
+ entrylist.entry do |entry|
141
+ entry.key("vpn/cert")
142
+ entry.value do |value|
143
+ value.string(client_cert)
144
+ end
145
+ end
146
+ entrylist.entry do |entry|
147
+ entry.key("vpn/comp-lzo")
148
+ entry.value do |value|
149
+ value.string("yes")
150
+ end
151
+ end
152
+ entrylist.entry do |entry|
153
+ entry.key("vpn/connection-type")
154
+ entry.value do |value|
155
+ value.string("tls")
156
+ end
157
+ end
158
+ entrylist.entry do |entry|
159
+ entry.key("vpn/key")
160
+ entry.value do |value|
161
+ value.string(client_key)
162
+ end
163
+ end
164
+ entrylist.entry do |entry|
165
+ entry.key("vpn/proto-tcp")
166
+ entry.value do |value|
167
+ value.string("yes")
168
+ end
169
+ end
170
+ entrylist.entry do |entry|
171
+ entry.key("vpn/remote")
172
+ entry.value do |value|
173
+ value.string(group_hash['vpn-gateway'])
174
+ end
175
+ end
176
+ entrylist.entry do |entry|
177
+ entry.key("vpn/service-type")
178
+ entry.value do |value|
179
+ value.string("org.freedesktop.NetworkManager.openvpn")
180
+ end
181
+ end
182
+ end
183
+
184
+ end
185
+
186
+ Tempfile.open('w') do |f|
187
+ f.write(xml.target!)
188
+ f.flush
189
+ puts %x{gconftool-2 --load #{f.path}}
190
+ end
191
+
192
+ return true
193
+
194
+ end
195
+
196
+ def self.unset_gconf_config(server_group_id)
197
+ puts %x{gconftool-2 --recursive-unset /system/networking/connections/vpc_#{server_group_id}}
198
+ end
199
+
200
+ def self.delete_certs(server_group_id)
201
+ FileUtils.rm_rf(File.join(CERT_DIR, server_group_id))
202
+ end
203
+
204
+ def self.connect(server_group_id)
205
+ puts %x{#{sudo_display} nmcli con up id "VPC Group: #{server_group_id}"}
206
+ end
207
+
208
+ def self.disconnect(server_group_id)
209
+ puts %x{#{sudo_display} nmcli con down id "VPC Group: #{server_group_id}"}
210
+ end
211
+
212
+ def self.ip_to_integer(ip_string)
213
+ return 0 if ip_string.nil?
214
+ ip_arr=ip_string.each(".").collect{ |s| s.chomp(".").to_i}
215
+ return ip_arr[0] + ip_arr[1]*2**8 + ip_arr[2]*2**16 + ip_arr[3]*2**24
216
+ end
217
+
218
+ def self.sudo_display
219
+ if ENV['DISPLAY'].nil? or ENV['DISPLAY'] != ":0.0" then
220
+ "sudo"
221
+ else
222
+ ""
223
+ end
224
+ end
225
+
226
+ end
227
+ end
@@ -2,8 +2,10 @@
2
2
 
3
3
  namespace :group do
4
4
  TMP_SG=File.join(CHEF_VPC_PROJECT, 'tmp', 'server_groups')
5
+ TMP_CLIENTS=File.join(CHEF_VPC_PROJECT, 'tmp', 'clients')
5
6
 
6
7
  directory TMP_SG
8
+ directory TMP_CLIENTS
7
9
 
8
10
  desc "Create a new group of cloud servers"
9
11
  task :create => [ TMP_SG, "chef:validate_json" ] do
@@ -20,7 +22,10 @@ namespace :group do
20
22
 
21
23
  hash=CloudServersVPC.server_group_hash(resp)
22
24
  out_file=hash["id"]+".xml"
23
- File.open(File.join(TMP_SG, out_file), 'w') { |f| f.write(resp) }
25
+ File.open(File.join(TMP_SG, out_file), 'w') do |f|
26
+ f.chmod(0600)
27
+ f.write(resp)
28
+ end
24
29
  puts "Cloud server group ID #{hash['id']} created."
25
30
 
26
31
  end
@@ -51,13 +56,16 @@ namespace :group do
51
56
  xml=CloudServersVPC.server_group_xml_for_id(configs, File.join(TMP_SG, '*.xml'), id)
52
57
 
53
58
  hash=CloudServersVPC.server_group_hash(xml)
54
- File.open(File.join(TMP_SG, "#{hash['id']}.xml"), 'w') { |f| f.write(xml) }
59
+ File.open(File.join(TMP_SG, "#{hash['id']}.xml"), 'w') do |f|
60
+ f.chmod(0600)
61
+ f.write(xml)
62
+ end
55
63
  CloudServersVPC.print_server_group(hash)
56
64
 
57
65
  end
58
66
 
59
67
  desc "Delete a cloud server group"
60
- task :delete do
68
+ task :delete => "vpn:delete" do
61
69
  id=ENV['GROUP_ID']
62
70
  configs=Util.load_configs
63
71
  hash=Util.hash_for_group
@@ -72,6 +80,7 @@ namespace :group do
72
80
  configs["cloud_servers_vpc_password"]
73
81
  )
74
82
  File.delete(File.join(TMP_SG, "#{id}.xml"))
83
+
75
84
  end
76
85
 
77
86
  desc "Force clean the cached server group files"
@@ -203,10 +212,106 @@ namespace :share do
203
212
 
204
213
  end
205
214
 
215
+ namespace :vpn do
216
+
217
+ desc "Connect to a server group as a VPN client."
218
+ task :connect do
219
+
220
+ puts "Creating VPN Connection..."
221
+ configs=Util.load_configs
222
+ group_hash=Util.hash_for_group(configs)
223
+ if not File.exists?(File.join(TMP_CLIENTS, group_hash['id']+'.xml')) then
224
+ Rake::Task['vpn:create_client'].invoke
225
+ Rake::Task['vpn:poll_client'].invoke
226
+ end
227
+ client_hash=CloudServersVPC.client_hash(IO.read(File.join(TMP_CLIENTS, group_hash['id']+'.xml')))
228
+ ChefVPCToolkit::VpnNetworkManager.configure_gconf(group_hash, client_hash)
229
+ ChefVPCToolkit::VpnNetworkManager.connect(group_hash['id'])
230
+
231
+ end
232
+
233
+ desc "Disconnect from a server group as a VPN client."
234
+ task :disconnect do
235
+
236
+ configs=Util.load_configs
237
+ group_hash=Util.hash_for_group(configs)
238
+ ChefVPCToolkit::VpnNetworkManager.disconnect(group_hash['id'])
239
+
240
+ vpn_server_ip=group_hash["vpn-network"].chomp("0")+"1"
241
+ SshUtil.remove_known_hosts_ip(vpn_server_ip)
242
+ SshUtil.remove_known_hosts_ip("#{CloudServersVPC.vpn_server_name(group_hash)},#{vpn_server_ip}")
243
+
244
+ end
245
+
246
+ desc "Delete VPN config information."
247
+ task :delete do
248
+
249
+ configs=Util.load_configs
250
+ group_hash=Util.hash_for_group(configs)
251
+ group_id=group_hash['id']
252
+ ChefVPCToolkit::VpnNetworkManager.unset_gconf_config(group_id)
253
+ ChefVPCToolkit::VpnNetworkManager.delete_certs(group_id)
254
+ client_file=File.join(TMP_CLIENTS, "#{group_id}.xml")
255
+
256
+ vpn_server_ip=group_hash["vpn-network"].chomp("0")+"1"
257
+ SshUtil.remove_known_hosts_ip(vpn_server_ip)
258
+ SshUtil.remove_known_hosts_ip("#{CloudServersVPC.vpn_server_name(group_hash)},#{vpn_server_ip}")
259
+
260
+ if File.exists?(client_file) then
261
+ File.delete(client_file)
262
+ end
263
+
264
+ end
265
+
266
+ desc "Create a new VPN client."
267
+ task :create_client => [ TMP_CLIENTS ] do
268
+
269
+ configs=Util.load_configs
270
+ group_hash=Util.hash_for_group(configs)
271
+
272
+ vpn_client_name=Util.hostname
273
+ if not configs['vpn_client_name'].nil? then
274
+ vpn_client_name=configs['vpn_client_name']
275
+ end
276
+
277
+ xml=CloudServersVPC.create_client(group_hash, vpn_client_name)
278
+ client_hash=CloudServersVPC.client_hash(xml)
279
+ out_file=group_hash["id"]+".xml"
280
+ File.open(File.join(TMP_CLIENTS, out_file), 'w') do |f|
281
+ f.chmod(0600)
282
+ f.write(xml)
283
+ end
284
+ puts "Client ID #{client_hash['id']} created."
285
+
286
+ end
287
+
288
+ desc "Poll until a client is online"
289
+ task :poll_client => TMP_CLIENTS do
290
+ timeout=ENV['VPN_CLIENT_TIMEOUT']
291
+ if timeout.nil? or timeout.empty? then
292
+ timeout=300 # defaults to 5 minutes
293
+ end
294
+ configs=Util.load_configs
295
+ group_hash=Util.hash_for_group
296
+ client_hash=CloudServersVPC.client_hash(IO.read(File.join(TMP_CLIENTS, group_hash['id']+'.xml')))
297
+ puts "Polling for client VPN cert to be created (this may take a minute)...."
298
+ CloudServersVPC.poll_client(client_hash["id"], timeout)
299
+ xml=CloudServersVPC.client_xml_for_id(configs, TMP_CLIENTS, client_hash["id"])
300
+ out_file=group_hash["id"]+".xml"
301
+ File.open(File.join(TMP_CLIENTS, out_file), 'w') do |f|
302
+ f.chmod(0600)
303
+ f.write(xml)
304
+ end
305
+ puts "Client VPN certs are ready to use."
306
+
307
+ end
308
+
309
+ end
310
+
206
311
  desc "SSH into the most recently created VPN gateway server."
207
312
  task :ssh do
208
313
  hash=Util.hash_for_group
209
- exec("ssh root@#{hash['vpn-gateway']}")
314
+ exec("ssh -o \"StrictHostKeyChecking no\" root@#{hash['vpn-gateway']}")
210
315
  end
211
316
 
212
317
  desc "Create a server group, install chef, sync share data and cookbooks."
@@ -236,6 +341,10 @@ task :rechef => [ "server:rebuild", "group:poll" ] do
236
341
 
237
342
  end
238
343
 
344
+ desc "Alias to the vpn:connect task."
345
+ task :vpn => "vpn:connect"
346
+
347
+
239
348
  desc "Print help and usage information"
240
349
  task :usage do
241
350
 
@@ -6,72 +6,8 @@ module ChefVPCToolkit
6
6
 
7
7
  class CloudServersVPCTest < Test::Unit::TestCase
8
8
 
9
- SERVER_GROUP_XML = %{
10
- <?xml version="1.0" encoding="UTF-8"?>
11
- <server-group>
12
- <created-at type="datetime">2010-10-15T15:15:58-04:00</created-at>
13
- <description>test description</description>
14
- <domain-name>mydomain.net</domain-name>
15
- <historical type="boolean">false</historical>
16
- <id type="integer">1759</id>
17
- <last-used-ip-address>172.19.0.2</last-used-ip-address>
18
- <name>test</name>
19
- <owner-name>dan.prince</owner-name>
20
- <updated-at type="datetime">2010-10-15T15:15:58-04:00</updated-at>
21
- <user-id type="integer">3</user-id>
22
- <vpn-network>172.19.0.0</vpn-network>
23
- <vpn-subnet>255.255.128.0</vpn-subnet>
24
- <servers type="array">
25
- <server>
26
- <account-id type="integer">3</account-id>
27
- <cloud-server-id-number type="integer">1</cloud-server-id-number>
28
- <created-at type="datetime">2010-10-15T15:15:58-04:00</created-at>
29
- <description>login1</description>
30
- <error-message nil="true"></error-message>
31
- <external-ip-addr>184.106.205.120</external-ip-addr>
32
- <flavor-id type="integer">4</flavor-id>
33
- <historical type="boolean">false</historical>
34
- <id type="integer">5513</id>
35
- <image-id type="integer">14</image-id>
36
- <internal-ip-addr>10.179.107.203</internal-ip-addr>
37
- <name>login1</name>
38
- <openvpn-server type="boolean">true</openvpn-server>
39
- <retry-count type="integer">0</retry-count>
40
- <server-group-id type="integer">1759</server-group-id>
41
- <status>Online</status>
42
- <updated-at type="datetime">2010-10-15T15:18:22-04:00</updated-at>
43
- <vpn-network-interfaces type="array"/>
44
- </server>
45
- <server>
46
- <account-id type="integer">3</account-id>
47
- <cloud-server-id-number type="integer">2</cloud-server-id-number>
48
- <created-at type="datetime">2010-10-15T15:15:58-04:00</created-at>
49
- <description>test1</description>
50
- <error-message nil="true"></error-message>
51
- <external-ip-addr>184.106.205.121</external-ip-addr>
52
- <flavor-id type="integer">49</flavor-id>
53
- <historical type="boolean">false</historical>
54
- <id type="integer">5513</id>
55
- <image-id type="integer">49</image-id>
56
- <internal-ip-addr>10.179.107.204</internal-ip-addr>
57
- <name>test1</name>
58
- <openvpn-server type="boolean">false</openvpn-server>
59
- <retry-count type="integer">0</retry-count>
60
- <server-group-id type="integer">1759</server-group-id>
61
- <status>Online</status>
62
- <updated-at type="datetime">2010-10-15T15:18:22-04:00</updated-at>
63
- <vpn-network-interfaces type="array"/>
64
- </server>
65
- </servers>
66
- </server-group>
67
- }
68
-
69
9
  def test_os_types
70
10
 
71
- #response = mock()
72
- #response.stubs(:code => "200", :body => json_response)
73
-
74
- #@conn.stubs(:csreq).returns(response)
75
11
  hash=CloudServersVPC.server_group_hash(SERVER_GROUP_XML)
76
12
  os_types=CloudServersVPC.os_types(hash)
77
13
 
@@ -169,6 +105,25 @@ SERVER_GROUP_XML = %{
169
105
 
170
106
  end
171
107
 
108
+ def test_create_client
109
+
110
+ response={}
111
+ response.stubs(:code).returns('200')
112
+ HttpUtil.stubs(:post).returns(response)
113
+
114
+ hash=CloudServersVPC.server_group_hash(SERVER_GROUP_XML)
115
+
116
+ assert "200", CloudServersVPC.create_client(hash, "test1").code
117
+
118
+ end
119
+
120
+ def test_vpn_server_name
121
+
122
+ hash=CloudServersVPC.server_group_hash(SERVER_GROUP_XML)
123
+ assert_equal "login1", CloudServersVPC.vpn_server_name(hash)
124
+
125
+ end
126
+
172
127
  end
173
128
 
174
129
  end
@@ -0,0 +1,21 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ require 'tempfile'
4
+
5
+ module ChefVPCToolkit
6
+
7
+ class SshUtilTest < Test::Unit::TestCase
8
+
9
+ def test_remove_known_hosts_ip
10
+
11
+ t=Tempfile.new('ssh_test')
12
+ t.write(%{login,172.19.0.1 ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAu1Xfhjj0hZwDIXWa6Gd/Qk/S9VwO5ec9+u6CMLMteQY4seeXmpu643k8zCa6yLuDXyzucknfrsxtOKJVQ6F5glXW6+Ko/zPiPNQbeC6GIKDs2a3m6A5OJSqRHqoy0RTJu11Acs3tkWUgmvBKFX7jxEZuHJM1kI0/xP0JlO0zOVr8+9Wg6Zy5KfVnEsgbdaEvpk3Rrtt5Lm42w/uxvPTFY7AWBhUfloYqBQrX6zd8d17jHLCnukHmvdR7eVGihXREtvDjX4ycG1o5/9amLWR0ELVFkFiXPHyWCuyl21j5uI7Ro9P2pga5ypnDB+N1BjFJHSMMofT40XOBkzAxBUrLgw==\n})
13
+ t.flush
14
+ SshUtil.remove_known_hosts_ip('login,172.19.0.1', t.path)
15
+ assert_equal "", IO.read(t.path)
16
+
17
+ end
18
+
19
+ end
20
+
21
+ end
data/test/test_helper.rb CHANGED
@@ -12,7 +12,7 @@ require 'fileutils'
12
12
 
13
13
  class TmpDir
14
14
 
15
- def self.new_tmp_dir(prefix="chef-cloud-toolkit")
15
+ def self.new_tmp_dir(prefix="chef-vpc-toolkit")
16
16
 
17
17
  tmp_file=Tempfile.new prefix
18
18
  path=tmp_file.path
@@ -23,3 +23,152 @@ class TmpDir
23
23
  end
24
24
 
25
25
  end
26
+
27
+ SERVER_GROUP_XML = %{
28
+ <?xml version="1.0" encoding="UTF-8"?>
29
+ <server-group>
30
+ <created-at type="datetime">2010-10-15T15:15:58-04:00</created-at>
31
+ <description>test description</description>
32
+ <domain-name>mydomain.net</domain-name>
33
+ <historical type="boolean">false</historical>
34
+ <id type="integer">1759</id>
35
+ <last-used-ip-address>172.19.0.2</last-used-ip-address>
36
+ <name>test</name>
37
+ <owner-name>dan.prince</owner-name>
38
+ <updated-at type="datetime">2010-10-15T15:15:58-04:00</updated-at>
39
+ <user-id type="integer">3</user-id>
40
+ <vpn-network>172.19.0.0</vpn-network>
41
+ <vpn-subnet>255.255.128.0</vpn-subnet>
42
+ <servers type="array">
43
+ <server>
44
+ <account-id type="integer">3</account-id>
45
+ <cloud-server-id-number type="integer">1</cloud-server-id-number>
46
+ <created-at type="datetime">2010-10-15T15:15:58-04:00</created-at>
47
+ <description>login1</description>
48
+ <error-message nil="true"></error-message>
49
+ <external-ip-addr>184.106.205.120</external-ip-addr>
50
+ <flavor-id type="integer">4</flavor-id>
51
+ <historical type="boolean">false</historical>
52
+ <id type="integer">5513</id>
53
+ <image-id type="integer">14</image-id>
54
+ <internal-ip-addr>10.179.107.203</internal-ip-addr>
55
+ <name>login1</name>
56
+ <openvpn-server type="boolean">true</openvpn-server>
57
+ <retry-count type="integer">0</retry-count>
58
+ <server-group-id type="integer">1759</server-group-id>
59
+ <status>Online</status>
60
+ <updated-at type="datetime">2010-10-15T15:18:22-04:00</updated-at>
61
+ <vpn-network-interfaces type="array"/>
62
+ </server>
63
+ <server>
64
+ <account-id type="integer">3</account-id>
65
+ <cloud-server-id-number type="integer">2</cloud-server-id-number>
66
+ <created-at type="datetime">2010-10-15T15:15:58-04:00</created-at>
67
+ <description>test1</description>
68
+ <error-message nil="true"></error-message>
69
+ <external-ip-addr>184.106.205.121</external-ip-addr>
70
+ <flavor-id type="integer">49</flavor-id>
71
+ <historical type="boolean">false</historical>
72
+ <id type="integer">5513</id>
73
+ <image-id type="integer">49</image-id>
74
+ <internal-ip-addr>10.179.107.204</internal-ip-addr>
75
+ <name>test1</name>
76
+ <openvpn-server type="boolean">false</openvpn-server>
77
+ <retry-count type="integer">0</retry-count>
78
+ <server-group-id type="integer">1759</server-group-id>
79
+ <status>Online</status>
80
+ <updated-at type="datetime">2010-10-15T15:18:22-04:00</updated-at>
81
+ <vpn-network-interfaces type="array"/>
82
+ </server>
83
+ </servers>
84
+ </server-group>
85
+ }
86
+
87
+ CLIENT_XML = %{
88
+ <client>
89
+ <created-at type="datetime">2011-01-09T19:37:32-05:00</created-at>
90
+ <description>Toolkit Client: local</description>
91
+ <id type="integer">5</id>
92
+ <is-windows type="boolean">false</is-windows>
93
+ <name>local</name>
94
+ <server-group-id type="integer">11</server-group-id>
95
+ <status>Online</status>
96
+ <updated-at type="datetime">2011-01-09T19:37:37-05:00</updated-at>
97
+ <vpn-network-interfaces type="array">
98
+ <vpn-network-interface>
99
+ <ca-cert>-----BEGIN CERTIFICATE-----
100
+ MIIDyDCCAzGgAwIBAgIJAORNZNRpPx87MA0GCSqGSIb3DQEBBQUAMIGfMQswCQYD
101
+ VQQGEwJVUzELMAkGA1UECBMCVkExEzARBgNVBAcTCkJsYWNrc2J1cmcxEjAQBgNV
102
+ BAoTCVJhY2tzcGFjZTEXMBUGA1UECxMOSW5mcmFzdHJ1Y3R1cmUxDjAMBgNVBAMT
103
+ BWxvZ2luMQ4wDAYDVQQpEwVsb2dpbjEhMB8GCSqGSIb3DQEJARYSY29icmFAc25h
104
+ a2VvaWwuY29tMB4XDTExMDExMDAwMzI1NVoXDTIxMDEwNzAwMzI1NVowgZ8xCzAJ
105
+ BgNVBAYTAlVTMQswCQYDVQQIEwJWQTETMBEGA1UEBxMKQmxhY2tzYnVyZzESMBAG
106
+ A1UEChMJUmFja3NwYWNlMRcwFQYDVQQLEw5JbmZyYXN0cnVjdHVyZTEOMAwGA1UE
107
+ AxMFbG9naW4xDjAMBgNVBCkTBWxvZ2luMSEwHwYJKoZIhvcNAQkBFhJjb2JyYUBz
108
+ bmFrZW9pbC5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAL0xIVIfh8rA
109
+ OCfc4BbWG+W+53iP9J6Fqhya5HSrYw3pdUCdimRBwQ0HoEnHndz2soRYc2Wtat8L
110
+ qqoS/qZMBbqerzEUFHumSKLADT3y8G1gkiGsb1fBZPmExPYyG/UQQUfK7CIM/L/m
111
+ W6Ji5ZEfTF9QPwHj3kVU99VUvm/BS8wXAgMBAAGjggEIMIIBBDAdBgNVHQ4EFgQU
112
+ dOvLRyxDa2Xso59PFLf22sZQ07wwgdQGA1UdIwSBzDCByYAUdOvLRyxDa2Xso59P
113
+ FLf22sZQ07yhgaWkgaIwgZ8xCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJWQTETMBEG
114
+ A1UEBxMKQmxhY2tzYnVyZzESMBAGA1UEChMJUmFja3NwYWNlMRcwFQYDVQQLEw5J
115
+ bmZyYXN0cnVjdHVyZTEOMAwGA1UEAxMFbG9naW4xDjAMBgNVBCkTBWxvZ2luMSEw
116
+ HwYJKoZIhvcNAQkBFhJjb2JyYUBzbmFrZW9pbC5jb22CCQDkTWTUaT8fOzAMBgNV
117
+ HRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAAVXIxOocwXi05004m9Znff6/cAj
118
+ 2osr72g/Xux++lVqiSHf+T/R4QywsXy9//vKeXVEIyaaP9ImnWbbzHFFI+NStP4n
119
+ LILyv+/eOuZ6Dv7Vv6ZacjI3fexcXYr5VW52HHbb/M7G1ePAfdAixUHNH7lh58dY
120
+ WDzmJicksUYlyvI+
121
+ -----END CERTIFICATE-----
122
+ </ca-cert>
123
+ <client-cert>-----BEGIN CERTIFICATE-----
124
+ MIIEDjCCA3egAwIBAgIBAzANBgkqhkiG9w0BAQUFADCBnzELMAkGA1UEBhMCVVMx
125
+ CzAJBgNVBAgTAlZBMRMwEQYDVQQHEwpCbGFja3NidXJnMRIwEAYDVQQKEwlSYWNr
126
+ c3BhY2UxFzAVBgNVBAsTDkluZnJhc3RydWN0dXJlMQ4wDAYDVQQDEwVsb2dpbjEO
127
+ MAwGA1UEKRMFbG9naW4xITAfBgkqhkiG9w0BCQEWEmNvYnJhQHNuYWtlb2lsLmNv
128
+ bTAeFw0xMTAxMTAwMDM3MzVaFw0yMTAxMDcwMDM3MzVaMIGfMQswCQYDVQQGEwJV
129
+ UzELMAkGA1UECBMCVkExEzARBgNVBAcTCkJsYWNrc2J1cmcxEjAQBgNVBAoTCVJh
130
+ Y2tzcGFjZTEXMBUGA1UECxMOSW5mcmFzdHJ1Y3R1cmUxDjAMBgNVBAMTBWxvY2Fs
131
+ MQ4wDAYDVQQpEwVsb2dpbjEhMB8GCSqGSIb3DQEJARYSY29icmFAc25ha2VvaWwu
132
+ Y29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCefsUr0T4oQUjKjW7Dpx0t
133
+ KwwafBF2HUW7CI75apeTjSBgYC1CHC6cggfFkUTFvndzspbGaeuJeYtvcvkAa2BD
134
+ p4jlSJgEXa+Uy1UAj1y06BePLNbKF4EfgEGf3eIWcdOtLYbOg4k33uNgto168iVO
135
+ owWOR+B2/z73NIHWxvtF3wIDAQABo4IBVjCCAVIwCQYDVR0TBAIwADAtBglghkgB
136
+ hvhCAQ0EIBYeRWFzeS1SU0EgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQW
137
+ BBSRXbeuamcuma4yo5B8IYSGGT3fNjCB1AYDVR0jBIHMMIHJgBR068tHLENrZeyj
138
+ n08Ut/baxlDTvKGBpaSBojCBnzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlZBMRMw
139
+ EQYDVQQHEwpCbGFja3NidXJnMRIwEAYDVQQKEwlSYWNrc3BhY2UxFzAVBgNVBAsT
140
+ DkluZnJhc3RydWN0dXJlMQ4wDAYDVQQDEwVsb2dpbjEOMAwGA1UEKRMFbG9naW4x
141
+ ITAfBgkqhkiG9w0BCQEWEmNvYnJhQHNuYWtlb2lsLmNvbYIJAORNZNRpPx87MBMG
142
+ A1UdJQQMMAoGCCsGAQUFBwMCMAsGA1UdDwQEAwIHgDANBgkqhkiG9w0BAQUFAAOB
143
+ gQApPAG1suVSPugJyQGfBaL8H+7VJdAGXnc6INX5s1AxJ3mvp4o6PQ7ytP4v/QkJ
144
+ ZVMgWV8immfa3PboFgT00qqpbC2Vbf4RR972IEQfGuJLLl4YLrJsbloV9hBamKS7
145
+ Z1lllmEHxFWpNK2FLSZNaeQABZyvzfZYkk6zsHoY8XsCBg==
146
+ -----END CERTIFICATE-----
147
+ </client-cert>
148
+ <client-key>-----BEGIN RSA PRIVATE KEY-----
149
+ MIICXQIBAAKBgQCefsUr0T4oQUjKjW7Dpx0tKwwafBF2HUW7CI75apeTjSBgYC1C
150
+ HC6cggfFkUTFvndzspbGaeuJeYtvcvkAa2BDp4jlSJgEXa+Uy1UAj1y06BePLNbK
151
+ F4EfgEGf3eIWcdOtLYbOg4k33uNgto168iVOowWOR+B2/z73NIHWxvtF3wIDAQAB
152
+ AoGAf3tFykWl8ij4jHsP8Wz0CcWLGa5bOR64XIS4wyKaQoML3JjfLkKOtzHbYGzE
153
+ 3Syi1bt6jKLbYZsSrRTT9SNorB3M2HI/uu1NHVyJ8fqxSJs9wQWv26XcMq6iPXR6
154
+ JQmiG44r0NoHtDOw0NCoo+9il4wjTIVSwN58x69EO1hsWokCQQDREYW73F536KzN
155
+ GSsLy+8VsaRiHCboi7lZwITGt4xFhykP/P5R/mNMTklVpJENuZH5jhiBr8r2O/XE
156
+ NQpIEZiFAkEAwhL4EnXax5p50g2CpkJM2B9F/p3IjjMs/sdUh4/RvAVkVAzz7uOh
157
+ TjtrL0T6480wA7rk3324IG5x4XTgXYVkEwJBAKkg7LgJ0N5d+xS8TIdxhctd9uZr
158
+ ccpj5iDGTmNXbwF8EurdNnvsODYtisPeqn2Y5o8ktYyMQrupy+rbIaMloOUCQAsI
159
+ pQ33oV6jy7VDi2AEePX4oTQeqF5dTnuVvZqPdK8p51BYBC5axrr56dggJdt5uPcd
160
+ UxHZxfQiE1tsF615ff0CQQCjeBskODATJkbN0kw+6FIF9m7QoEAYtJD1jLiY/2Sv
161
+ QRiYX+gvycrIph1yyIGA1qeHYnjhQp4ZijhcwSFUAAyF
162
+ -----END RSA PRIVATE KEY-----
163
+ </client-key>
164
+ <created-at type="datetime">2011-01-09T19:37:32-05:00</created-at>
165
+ <id type="integer">15</id>
166
+ <interfacable-id type="integer">5</interfacable-id>
167
+ <interfacable-type>Client</interfacable-type>
168
+ <ptp-ip-addr>172.19.0.6</ptp-ip-addr>
169
+ <updated-at type="datetime">2011-01-09T19:37:36-05:00</updated-at>
170
+ <vpn-ip-addr>172.19.0.5</vpn-ip-addr>
171
+ </vpn-network-interface>
172
+ </vpn-network-interfaces>
173
+ </client>
174
+ }
data/test/util_test.rb ADDED
@@ -0,0 +1,15 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ module ChefVPCToolkit
4
+
5
+ class UtilTest < Test::Unit::TestCase
6
+
7
+ def test_hostname
8
+
9
+ assert_not_nil Util.hostname
10
+
11
+ end
12
+
13
+ end
14
+
15
+ end
@@ -0,0 +1,35 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ require 'tempfile'
4
+
5
+ module ChefVPCToolkit
6
+
7
+ class VpnNetworkManagerTest < Test::Unit::TestCase
8
+
9
+ def setup
10
+ tmpdir=TmpDir.new_tmp_dir
11
+ File.open(File.join(tmpdir, "gconftool-2"), 'w') do |f|
12
+ f.write("#!/bin/bash\nexit 0")
13
+ f.chmod(0755)
14
+ end
15
+ ENV['PATH']=tmpdir+":"+ENV['PATH']
16
+ end
17
+
18
+ def teardown
19
+ group_hash=CloudServersVPC.server_group_hash(SERVER_GROUP_XML)
20
+ VpnNetworkManager.delete_certs(group_hash['id'])
21
+ end
22
+
23
+ def test_configure_gconf
24
+ group_hash=CloudServersVPC.server_group_hash(SERVER_GROUP_XML)
25
+ client_hash=CloudServersVPC.client_hash(CLIENT_XML)
26
+ assert VpnNetworkManager.configure_gconf(group_hash, client_hash)
27
+ end
28
+
29
+ def test_ip_to_integer
30
+ assert_equal 16782252, VpnNetworkManager.ip_to_integer("172.19.0.1")
31
+ end
32
+
33
+ end
34
+
35
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chef-vpc-toolkit
3
3
  version: !ruby/object:Gem::Version
4
- hash: 13
4
+ hash: 11
5
5
  prerelease: false
6
6
  segments:
7
7
  - 2
8
- - 0
9
8
  - 1
10
- version: 2.0.1
9
+ - 0
10
+ version: 2.1.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Dan Prince
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-12-07 00:00:00 -05:00
18
+ date: 2011-01-11 00:00:00 -05:00
19
19
  default_executable: chef-vpc-toolkit
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -60,6 +60,20 @@ dependencies:
60
60
  version: "0"
61
61
  type: :runtime
62
62
  version_requirements: *id003
63
+ - !ruby/object:Gem::Dependency
64
+ name: uuidtools
65
+ prerelease: false
66
+ requirement: &id004 !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ hash: 3
72
+ segments:
73
+ - 0
74
+ version: "0"
75
+ type: :runtime
76
+ version_requirements: *id004
63
77
  description: The Chef VPC Toolkit is a set of Rake tasks that provide a framework to help automate the creation and configuration of cloud server groups for development or testing. Requires Cloud Servers VPC.
64
78
  email: dan.prince@rackspace.com
65
79
  executables:
@@ -70,6 +84,8 @@ extra_rdoc_files:
70
84
  - README.rdoc
71
85
  files:
72
86
  - .gitignore
87
+ - .rvmrc
88
+ - CHANGELOG
73
89
  - COPYING
74
90
  - README.rdoc
75
91
  - Rakefile
@@ -111,9 +127,13 @@ files:
111
127
  - lib/chef-vpc-toolkit/ssh_util.rb
112
128
  - lib/chef-vpc-toolkit/util.rb
113
129
  - lib/chef-vpc-toolkit/version.rb
130
+ - lib/chef-vpc-toolkit/vpn_network_manager.rb
114
131
  - rake/chef_vpc_toolkit.rake
115
132
  - test/cloud_servers_vpc_test.rb
133
+ - test/ssh_util_test.rb
116
134
  - test/test_helper.rb
135
+ - test/util_test.rb
136
+ - test/vpn_network_manager_test.rb
117
137
  has_rdoc: true
118
138
  homepage: http://github.com/rackspace/chef-vpc-toolkit
119
139
  licenses: []
@@ -149,5 +169,8 @@ signing_key:
149
169
  specification_version: 3
150
170
  summary: Rake tasks to automate and configure server groups in the cloud with Chef.
151
171
  test_files:
172
+ - test/util_test.rb
173
+ - test/ssh_util_test.rb
152
174
  - test/test_helper.rb
153
175
  - test/cloud_servers_vpc_test.rb
176
+ - test/vpn_network_manager_test.rb