vcloud-box-spinner 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +8 -0
- data/CHANGELOG +8 -0
- data/Gemfile +4 -0
- data/LICENSE +20 -0
- data/README.md +79 -0
- data/Rakefile +16 -0
- data/bin/vcloud-box-spinner +11 -0
- data/docs/hacking.md +7 -0
- data/docs/json_formats.md +65 -0
- data/docs/uuids.md +41 -0
- data/jenkins.sh +5 -0
- data/lib/fog/vcloud/compute/server_ready.rb +16 -0
- data/lib/fog/vcloud/compute/shared.rb +30 -0
- data/lib/provisioner/blank_provisioner.rb +5 -0
- data/lib/provisioner/cli.rb +151 -0
- data/lib/provisioner/compute_action/create.rb +176 -0
- data/lib/provisioner/compute_action/delete.rb +29 -0
- data/lib/provisioner/compute_node.rb +14 -0
- data/lib/provisioner/errors.rb +6 -0
- data/lib/provisioner/provisioner.rb +134 -0
- data/lib/provisioner/version.rb +3 -0
- data/lib/vcloud_box_provisioner.rb +31 -0
- data/spec/fog/vcloud/compute/shared_spec.rb +64 -0
- data/spec/provisioner/cli_spec.rb +170 -0
- data/spec/provisioner/compute_node_spec.rb +19 -0
- data/spec/provisioner/provisioner_spec.rb +37 -0
- data/spec/spec_helper.rb +23 -0
- data/spec/test_data/machine.json +5 -0
- data/spec/test_data/org.json +18 -0
- data/vcloud-box-spinner.gemspec +34 -0
- metadata +213 -0
@@ -0,0 +1,29 @@
|
|
1
|
+
module Provisioner
|
2
|
+
module ComputeAction
|
3
|
+
module Delete
|
4
|
+
|
5
|
+
def delete_vapp
|
6
|
+
super
|
7
|
+
vapp_href = compute.servers.service.vapps.detect {|v| v.name == options[:vm_name] }.href
|
8
|
+
vapp = compute.servers.service.get_vapp(vapp_href)
|
9
|
+
if vapp.on? or (vapp.off? and vapp.deployed)
|
10
|
+
logger.debug "The vApp is running, stopping it..."
|
11
|
+
vapp.service.undeploy vapp_href
|
12
|
+
logger.debug "Waiting for vApp to stop ..."
|
13
|
+
vapp.wait_for { vapp.off? }
|
14
|
+
end
|
15
|
+
vapp.wait_for { vapp.off? } #double check
|
16
|
+
|
17
|
+
# This is added as vapp after being off, might still
|
18
|
+
# be in a state which isn't ready. This would check
|
19
|
+
# status of each vm associated with vapp
|
20
|
+
vapp.servers.entries.each { |server| server.wait_for { server.ready? } }
|
21
|
+
|
22
|
+
logger.debug "The vApp is not running now ..."
|
23
|
+
logger.debug "Deleting the vApp"
|
24
|
+
vapp.service.delete_vapp vapp_href
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'cgi'
|
2
|
+
require 'builder'
|
3
|
+
require 'fog/vcloud/compute/shared' # our hack
|
4
|
+
require 'fog/vcloud/compute/server_ready' # another hack
|
5
|
+
require 'nokogiri'
|
6
|
+
require 'provisioner/compute_action/create'
|
7
|
+
require 'provisioner/compute_action/delete'
|
8
|
+
|
9
|
+
module Provisioner
|
10
|
+
module ComputeNode
|
11
|
+
include ComputeAction::Create
|
12
|
+
include ComputeAction::Delete
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
module Provisioner
|
2
|
+
class Provisioner
|
3
|
+
AVAILABLE_ACTIONS = ['create', 'delete']
|
4
|
+
|
5
|
+
attr_accessor :options
|
6
|
+
private :options=, :options
|
7
|
+
|
8
|
+
def initialize options
|
9
|
+
options[:provider] = 'vcloud'
|
10
|
+
options[:created_by] = ENV['USER']
|
11
|
+
self.options = options
|
12
|
+
end
|
13
|
+
|
14
|
+
def execute(action)
|
15
|
+
unless AVAILABLE_ACTIONS.include?(action)
|
16
|
+
raise(ConfigurationError, "The action '#{action}' is not a valid action")
|
17
|
+
end
|
18
|
+
send(action)
|
19
|
+
end
|
20
|
+
|
21
|
+
def create
|
22
|
+
logger.debug "Validating options"
|
23
|
+
validate_options
|
24
|
+
logger.debug "Preparing the run"
|
25
|
+
prepare_run
|
26
|
+
logger.debug "Launching servers"
|
27
|
+
launch_servers
|
28
|
+
logger.debug "Done"
|
29
|
+
end
|
30
|
+
private :create
|
31
|
+
|
32
|
+
def delete
|
33
|
+
logger.debug "Validating options"
|
34
|
+
validate_options
|
35
|
+
if ask("Do you really want to delete '#{options[:vm_name]}'? (yes/no) ") == "yes"
|
36
|
+
logger.debug "Proceeding delete operation"
|
37
|
+
delete_vapp
|
38
|
+
else
|
39
|
+
logger.debug "Abandoning delete operation"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
private :delete
|
43
|
+
|
44
|
+
def compute
|
45
|
+
@compute ||= Fog::Compute.new(
|
46
|
+
:provider => options[:provider],
|
47
|
+
:vcloud_username => "#{options[:user]}@#{options[:organisation]}",
|
48
|
+
:vcloud_password => options[:password],
|
49
|
+
:vcloud_host => options[:host],
|
50
|
+
:vcloud_default_vdc => options[:default_vdc],
|
51
|
+
:connection_options => {
|
52
|
+
:ssl_verify_peer => false,
|
53
|
+
:omit_default_port => true
|
54
|
+
}
|
55
|
+
)
|
56
|
+
end
|
57
|
+
private :compute
|
58
|
+
|
59
|
+
def logger
|
60
|
+
options[:logger]
|
61
|
+
end
|
62
|
+
private :logger
|
63
|
+
|
64
|
+
def ssh
|
65
|
+
@ssh ||= begin
|
66
|
+
Provisioner.ssh_client.tap { |client|
|
67
|
+
logger.debug "Using #{client} as my SSH client"
|
68
|
+
}
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def ssh_to hostname, &blk
|
73
|
+
puts "Sshing to #{hostname}"
|
74
|
+
ssh.start hostname,
|
75
|
+
options[:ssh_user],
|
76
|
+
:config => options[:ssh_config],
|
77
|
+
&blk
|
78
|
+
end
|
79
|
+
|
80
|
+
def validate_options
|
81
|
+
unless options[:password] && options[:user] && options[:host]
|
82
|
+
logger.error "VCloud credentials missing"
|
83
|
+
raise ConfigurationError, "VCloud credentials must be specified"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
private :validate_options
|
87
|
+
|
88
|
+
def timestamp
|
89
|
+
@timestamp ||= Time.now.utc.to_i.to_s(36).tap { |ts|
|
90
|
+
logger.debug "The base 36 timestamp for this run in #{ts}"
|
91
|
+
}
|
92
|
+
end
|
93
|
+
private :timestamp
|
94
|
+
|
95
|
+
def launch_server name
|
96
|
+
end
|
97
|
+
private :launch_server
|
98
|
+
|
99
|
+
def notify message, name
|
100
|
+
logger.info "<%s> %s" % [ name, message ]
|
101
|
+
end
|
102
|
+
private :notify
|
103
|
+
|
104
|
+
def launch_servers
|
105
|
+
Parallel.each(options[:num_servers].times, :in_threads => options[:num_servers]) do |number|
|
106
|
+
name = server_name number
|
107
|
+
server = launch_server name
|
108
|
+
bootstrap_server server, name
|
109
|
+
end
|
110
|
+
end
|
111
|
+
private :launch_servers
|
112
|
+
|
113
|
+
def server_name number
|
114
|
+
[
|
115
|
+
options[:platform],
|
116
|
+
timestamp,
|
117
|
+
("%02d" % (number + 1))
|
118
|
+
].compact.join('-')
|
119
|
+
end
|
120
|
+
private :server_name
|
121
|
+
|
122
|
+
def prepare_run
|
123
|
+
end
|
124
|
+
private :prepare_run
|
125
|
+
|
126
|
+
def bootstrap_server server, name
|
127
|
+
end
|
128
|
+
private :bootstrap_server
|
129
|
+
|
130
|
+
def delete_vapp
|
131
|
+
end
|
132
|
+
private
|
133
|
+
end
|
134
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'provisioner/errors'
|
2
|
+
require 'provisioner/provisioner'
|
3
|
+
require 'provisioner/compute_node'
|
4
|
+
require 'provisioner/blank_provisioner'
|
5
|
+
require 'provisioner/cli'
|
6
|
+
require 'provisioner/version'
|
7
|
+
require 'socket'
|
8
|
+
require 'logger'
|
9
|
+
require 'net/ssh'
|
10
|
+
require 'net/scp'
|
11
|
+
require 'erb'
|
12
|
+
require 'parallel'
|
13
|
+
require 'fog'
|
14
|
+
|
15
|
+
module VcloudBoxProvisioner
|
16
|
+
def self.build options = {}
|
17
|
+
options[:logger] ||= default_logger options
|
18
|
+
options[:logger].debug "Building provisioner for #{options.inspect}"
|
19
|
+
Provisioner::BlankProvisioner.new options
|
20
|
+
end
|
21
|
+
|
22
|
+
class << self
|
23
|
+
attr_accessor :ssh_client
|
24
|
+
end
|
25
|
+
self.ssh_client = Net::SSH
|
26
|
+
|
27
|
+
def self.default_logger options
|
28
|
+
Logger.new(STDOUT).tap { |l| l.level = options[:log_level] || Logger::ERROR }
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'fog/vcloud/compute/shared'
|
3
|
+
require 'nokogiri'
|
4
|
+
require 'equivalent-xml'
|
5
|
+
|
6
|
+
describe Fog::Vcloud::Compute::Shared do
|
7
|
+
let (:fog_vcloud_test_class) do
|
8
|
+
Class.new do
|
9
|
+
include Fog::Vcloud::Compute::Shared
|
10
|
+
|
11
|
+
def xmlns
|
12
|
+
{}
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should generate InstantiateVAppTemplateParams' do
|
18
|
+
subject = fog_vcloud_test_class.new
|
19
|
+
fog_xml = subject.send(:generate_instantiate_vapp_template_request, {:name => 'foo',
|
20
|
+
:description => 'bar',
|
21
|
+
:template_uri => 'baz'
|
22
|
+
})
|
23
|
+
parsed = Nokogiri::XML(fog_xml)
|
24
|
+
|
25
|
+
xml = ::Builder::XmlMarkup.new
|
26
|
+
expected = xml.InstantiateVAppTemplateParams({:name => 'foo', :'xml:lang' => 'en'}) {
|
27
|
+
xml.Description('bar')
|
28
|
+
xml.InstantiationParams { }
|
29
|
+
xml.Source(:href => 'baz')
|
30
|
+
xml.AllEULAsAccepted("true")
|
31
|
+
}
|
32
|
+
parsed.should be_equivalent_to Nokogiri::XML(expected)
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'should handle network_uri correctly' do
|
36
|
+
subject = fog_vcloud_test_class.new
|
37
|
+
fog_xml = subject.send(:generate_instantiate_vapp_template_request,
|
38
|
+
{:name => 'foo',
|
39
|
+
:description => 'bar',
|
40
|
+
:template_uri => 'baz',
|
41
|
+
:network_name => 'jimmy',
|
42
|
+
:network_uri => 'http://jimmy.invalid'
|
43
|
+
})
|
44
|
+
|
45
|
+
xml = ::Builder::XmlMarkup.new
|
46
|
+
expected = xml.InstantiateVAppTemplateParams({:name => 'foo', :'xml:lang' => 'en'}) {
|
47
|
+
xml.Description('bar')
|
48
|
+
xml.InstantiationParams {
|
49
|
+
xml.NetworkConfigSection {
|
50
|
+
xml.ovf :Info
|
51
|
+
xml.NetworkConfig(:networkName => 'jimmy') {
|
52
|
+
xml.Configuration {
|
53
|
+
xml.ParentNetwork(:href => 'http://jimmy.invalid')
|
54
|
+
xml.FenceMode 'bridged'
|
55
|
+
}
|
56
|
+
}
|
57
|
+
}
|
58
|
+
}
|
59
|
+
xml.Source(:href => 'baz')
|
60
|
+
xml.AllEULAsAccepted("true")
|
61
|
+
}
|
62
|
+
Nokogiri::XML(fog_xml).should be_equivalent_to Nokogiri::XML(expected)
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,170 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'provisioner/cli'
|
3
|
+
|
4
|
+
MACHINE_METADATA = {
|
5
|
+
:puppetmaster => 'foo.bar.baz',
|
6
|
+
:zone => 'foo',
|
7
|
+
:catalog_id => 'default_catalog_id',
|
8
|
+
}.freeze
|
9
|
+
|
10
|
+
DEFAULTS = {
|
11
|
+
:debug => false,
|
12
|
+
:log_level => 5,
|
13
|
+
:memory => 4096,
|
14
|
+
:num_cores => 2,
|
15
|
+
:num_servers => 1,
|
16
|
+
:platform => "production",
|
17
|
+
:ssh_config => true, # if not specified, use system defaults
|
18
|
+
}
|
19
|
+
|
20
|
+
describe Provisioner::CLI do
|
21
|
+
describe "#defaults" do
|
22
|
+
Provisioner::CLI.defaults.should == DEFAULTS
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "#process" do
|
26
|
+
it 'should set options from built-in defaults' do
|
27
|
+
options = { :machine_metadata => MACHINE_METADATA,
|
28
|
+
:org_config => {} }
|
29
|
+
res = Provisioner::CLI.process(options)
|
30
|
+
res.should include(DEFAULTS)
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should set options from the vCloud config defaults' do
|
34
|
+
config = { :default => { :ip => '5.6.7.8' } }
|
35
|
+
res = Provisioner::CLI.process({:machine_metadata => MACHINE_METADATA,
|
36
|
+
:org_config => config})
|
37
|
+
res.should include(:ip => '5.6.7.8')
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'should set options from the vCloud config based on the specified zone' do
|
41
|
+
config = { :foo => { :ip => '9.8.7.6' } }
|
42
|
+
res = Provisioner::CLI.process({:org_config => config,
|
43
|
+
:machine_metadata => MACHINE_METADATA})
|
44
|
+
res.should include(:ip => '9.8.7.6')
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should set options from the machine template' do
|
48
|
+
options = { :machine_metadata => MACHINE_METADATA.dup.merge( :ip => '1.2.3.4' ),
|
49
|
+
:org_config => {} }
|
50
|
+
res = Provisioner::CLI.process(options)
|
51
|
+
res.should include(:ip => '1.2.3.4')
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'should set options from the command line' do
|
55
|
+
opts = {:ssh_user => 'donald',
|
56
|
+
:org_config => {},
|
57
|
+
:machine_metadata => MACHINE_METADATA }
|
58
|
+
res = Provisioner::CLI.process(opts)
|
59
|
+
res.should include(:ssh_user => 'donald')
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'should override vCloud config defaults with vCloud zone defaults' do
|
63
|
+
config = {
|
64
|
+
:default => { :ip => '1.2.3.4' },
|
65
|
+
:foo => { :ip => '5.6.7.8' }
|
66
|
+
}
|
67
|
+
res = Provisioner::CLI.process({:org_config => config,
|
68
|
+
:machine_metadata => MACHINE_METADATA})
|
69
|
+
res.should include(:ip => '5.6.7.8')
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'should override vCloud zone defaults with machine template options' do
|
73
|
+
options = { :org_config => { :foo => { :ip => '1.2.3.4' } },
|
74
|
+
:machine_metadata => MACHINE_METADATA.dup.merge(:ip => '5.6.7.8')}
|
75
|
+
res = Provisioner::CLI.process(options)
|
76
|
+
res.should include(:ip => '5.6.7.8')
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'should override machine template options with command line options' do
|
80
|
+
options = { :machine_metadata => MACHINE_METADATA.dup.
|
81
|
+
merge(:ssh_user => 'aaron'),
|
82
|
+
:org_config => {},
|
83
|
+
:ssh_user => 'binky' }
|
84
|
+
res = Provisioner::CLI.process(options)
|
85
|
+
res.should include(:ssh_user => 'binky')
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'should use catalog_id if present' do
|
89
|
+
options = { :machine_metadata => MACHINE_METADATA.dup.merge!(
|
90
|
+
:catalog_id => 'wibble',
|
91
|
+
:catalog_items => { :my_cool_template => 'incorrect' },
|
92
|
+
:template_name => 'my_cool_template'
|
93
|
+
),
|
94
|
+
:org_config => {}}
|
95
|
+
res = Provisioner::CLI.process(options)
|
96
|
+
res.should include(:catalog_id => 'wibble')
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'should use template_name to determine catalog_id if catalog_id not present' do
|
100
|
+
tpl = MACHINE_METADATA.dup
|
101
|
+
tpl.delete(:catalog_id)
|
102
|
+
tpl.merge!(
|
103
|
+
:catalog_items => { :my_cool_template => 'https://correct_catalog_id' },
|
104
|
+
:template_name => 'my_cool_template'
|
105
|
+
)
|
106
|
+
res = Provisioner::CLI.process({:machine_metadata => tpl,
|
107
|
+
:org_config => {}})
|
108
|
+
res.should include(:catalog_id => 'https://correct_catalog_id')
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'should require a zone to be set' do
|
112
|
+
tpl = MACHINE_METADATA.dup
|
113
|
+
tpl.delete(:zone)
|
114
|
+
expect do
|
115
|
+
Provisioner::CLI.process({:machine_metadata => tpl})
|
116
|
+
end.to raise_error(Provisioner::ConfigurationError, /zone/)
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
|
121
|
+
describe "#execute" do
|
122
|
+
before :each do silence_output end
|
123
|
+
after :each do silence_output end
|
124
|
+
|
125
|
+
it "should fail if two arguments not provided" do
|
126
|
+
expect {
|
127
|
+
Provisioner::CLI.new(['-u' , 'user', '-p', 'pass']).execute
|
128
|
+
}.to raise_error(SystemExit)
|
129
|
+
end
|
130
|
+
|
131
|
+
it "should call provision a machine" do
|
132
|
+
default_org_config =
|
133
|
+
{ :template_name => "template-name",
|
134
|
+
:host=>"api-end-host",
|
135
|
+
:platform=>"qa",
|
136
|
+
:organisation=>"org-name",
|
137
|
+
:catalog_items => {
|
138
|
+
:"template-name" => "https://vendor-api-endpoint/catalogItem/100"
|
139
|
+
}}
|
140
|
+
zone_org_config =
|
141
|
+
{ :default_vdc=>"https://vendor-api-endpoint/api/vdc/07412",
|
142
|
+
:domain => "tester.default",
|
143
|
+
:network_name => "Default",
|
144
|
+
:network_uri => "https://vendor-api-endpoint/api/network/0352",
|
145
|
+
:vdc_id=>"07412" }
|
146
|
+
machine_metadata = { :zone => "tester",
|
147
|
+
:vm_name => "machine-2",
|
148
|
+
:ip => "192.168.2.2" }
|
149
|
+
expected_opts = DEFAULTS.merge(default_org_config).
|
150
|
+
merge(zone_org_config).
|
151
|
+
merge(machine_metadata).
|
152
|
+
merge({ :user => 'badger',
|
153
|
+
:password => 'eggplant',
|
154
|
+
:catalog_id => "https://vendor-api-endpoint/catalogItem/100"
|
155
|
+
})
|
156
|
+
|
157
|
+
VcloudBoxProvisioner.should_receive(:build).
|
158
|
+
with(expected_opts).
|
159
|
+
and_return(mock(:execute => true))
|
160
|
+
|
161
|
+
cli = Provisioner::CLI.new(['-u', 'badger', '-p', 'eggplant',
|
162
|
+
'-o', 'spec/test_data/org.json',
|
163
|
+
'-m', 'spec/test_data/machine.json',
|
164
|
+
'create'
|
165
|
+
])
|
166
|
+
cli.execute
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'provisioner/compute_node'
|
3
|
+
|
4
|
+
module Provisioner
|
5
|
+
class DummyClass
|
6
|
+
include ComputeNode
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
describe 'Provisoner::ComputeNode' do
|
11
|
+
|
12
|
+
it "should undeploy the vApp is running while delete action" do
|
13
|
+
pending "mock not supported in fog"
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should not undeploy the vApp is stopped while delete action" do
|
17
|
+
pending "mock not supported in fog"
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'provisioner/errors'
|
3
|
+
require 'provisioner/provisioner'
|
4
|
+
|
5
|
+
shared_examples "validate credentials" do |action|
|
6
|
+
it "should error if credentials not provided while perfoming #{action}" do
|
7
|
+
logger = mock(:debug => true, :error => true)
|
8
|
+
expect {
|
9
|
+
Provisioner::Provisioner.new({:logger => logger}).execute(action)
|
10
|
+
}.to raise_error(Provisioner::ConfigurationError,
|
11
|
+
'VCloud credentials must be specified')
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe 'Provisioner::Provisioner' do
|
16
|
+
|
17
|
+
it_should_behave_like "validate credentials", 'create'
|
18
|
+
it_should_behave_like "validate credentials", 'delete'
|
19
|
+
|
20
|
+
it "should error out if action passed isn't present" do
|
21
|
+
logger = mock(:debug => true, :error => true)
|
22
|
+
expect {
|
23
|
+
Provisioner::Provisioner.new({:logger => logger}).execute('disco')
|
24
|
+
}.to raise_error(Provisioner::ConfigurationError,
|
25
|
+
'The action \'disco\' is not a valid action')
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "delete" do
|
29
|
+
it "delete vApp only if you confirm to delete vApp" do
|
30
|
+
pending "mock not supported in fog"
|
31
|
+
end
|
32
|
+
it "don't delete vApp only if you don't confirm to delete vApp" do
|
33
|
+
pending "mock not supported in fog"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
specdir=File.dirname(__FILE__)
|
2
|
+
$:.unshift File.join(specdir, '../lib')
|
3
|
+
$:.unshift File.join(specdir, '..')
|
4
|
+
|
5
|
+
require 'rspec'
|
6
|
+
|
7
|
+
# Redirects stderr and stdout to /dev/null.
|
8
|
+
def silence_output
|
9
|
+
@orig_stderr = $stderr
|
10
|
+
@orig_stdout = $stdout
|
11
|
+
|
12
|
+
# redirect stderr and stdout to /dev/null
|
13
|
+
$stderr = File.new('/dev/null', 'w')
|
14
|
+
$stdout = File.new('/dev/null', 'w')
|
15
|
+
end
|
16
|
+
|
17
|
+
# Replace stdout and stderr so anything else is output correctly.
|
18
|
+
def enable_output
|
19
|
+
$stderr = @orig_stderr
|
20
|
+
$stdout = @orig_stdout
|
21
|
+
@orig_stderr = nil
|
22
|
+
@orig_stdout = nil
|
23
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
{
|
2
|
+
"default": {
|
3
|
+
"template_name": "template-name",
|
4
|
+
"host": "api-end-host",
|
5
|
+
"platform": "qa",
|
6
|
+
"organisation": "org-name",
|
7
|
+
"catalog_items": {
|
8
|
+
"template-name": "https://vendor-api-endpoint/catalogItem/100"
|
9
|
+
}
|
10
|
+
},
|
11
|
+
"tester": {
|
12
|
+
"default_vdc": "https://vendor-api-endpoint/api/vdc/07412",
|
13
|
+
"domain": "tester.default",
|
14
|
+
"network_name": "Default",
|
15
|
+
"network_uri": "https://vendor-api-endpoint/api/network/0352",
|
16
|
+
"vdc_id": "07412"
|
17
|
+
}
|
18
|
+
}
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "provisioner/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "vcloud-box-spinner"
|
7
|
+
s.version = Provisioner::VERSION
|
8
|
+
s.authors = ["Garima Singh"]
|
9
|
+
s.email = ["igarimasingh@gmail.com"]
|
10
|
+
s.homepage = "https://github.com/com/vcloud-box-spinner"
|
11
|
+
s.summary = %q{Provision servers, with vcloud API}
|
12
|
+
s.description = %q{Create new VM and apply an opinionated set of commands to
|
13
|
+
them, using vcloud API. The vcloud-box-spinner is a thin wrapper around fog,
|
14
|
+
which enables you to be able to configure VMs with static IPs}
|
15
|
+
|
16
|
+
s.rubyforge_project = "vcloud-box-spinner"
|
17
|
+
|
18
|
+
s.files = `git ls-files`.split("\n")
|
19
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
20
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
21
|
+
s.require_paths = ["lib"]
|
22
|
+
|
23
|
+
s.add_development_dependency "rake"
|
24
|
+
s.add_development_dependency "minitest"
|
25
|
+
s.add_development_dependency "mocha"
|
26
|
+
s.add_development_dependency "webmock"
|
27
|
+
s.add_development_dependency "rspec", "~> 2.11.0"
|
28
|
+
s.add_development_dependency "equivalent-xml", "~> 0.2.9"
|
29
|
+
s.add_development_dependency "gem_publisher", "~> 1.3.0"
|
30
|
+
s.add_runtime_dependency "fog", "~> 1.0"
|
31
|
+
s.add_runtime_dependency "parallel"
|
32
|
+
s.add_runtime_dependency "highline"
|
33
|
+
s.add_runtime_dependency "nokogiri", "~> 1.5.0"
|
34
|
+
end
|