vcloud-box-spinner 0.2.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/.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
|