hula 0.7.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LEGAL +13 -0
- data/lib/hula/bosh_director.rb +246 -0
- data/lib/hula/bosh_manifest/job.rb +35 -0
- data/lib/hula/bosh_manifest.rb +102 -0
- data/lib/hula/cloud_foundry/service_broker.rb +36 -0
- data/lib/hula/cloud_foundry.rb +308 -0
- data/lib/hula/command_runner.rb +38 -0
- data/lib/hula/helpers/socket_tools.rb +44 -0
- data/lib/hula/helpers/timeout_tools.rb +27 -0
- data/lib/hula/http_proxy_upstream_socks.rb +72 -0
- data/lib/hula/service_broker/api.rb +123 -0
- data/lib/hula/service_broker/catalog.rb +43 -0
- data/lib/hula/service_broker/client.rb +69 -0
- data/lib/hula/service_broker/errors.rb +24 -0
- data/lib/hula/service_broker/http_json_client.rb +90 -0
- data/lib/hula/service_broker/instance_binding.rb +30 -0
- data/lib/hula/service_broker/plan.rb +32 -0
- data/lib/hula/service_broker/service.rb +47 -0
- data/lib/hula/service_broker/service_instance.rb +24 -0
- data/lib/hula/socks4_proxy_ssh.rb +118 -0
- data/lib/hula/version.rb +13 -0
- data/lib/hula.rb +16 -0
- metadata +235 -0
@@ -0,0 +1,69 @@
|
|
1
|
+
# Copyright (c) 2014-2015 Pivotal Software, Inc.
|
2
|
+
# All rights reserved.
|
3
|
+
# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
4
|
+
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
5
|
+
# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
6
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
7
|
+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
8
|
+
# USE OR OTHER DEALINGS IN THE SOFTWARE.
|
9
|
+
#
|
10
|
+
|
11
|
+
require 'hula/service_broker/api'
|
12
|
+
|
13
|
+
require 'forwardable'
|
14
|
+
|
15
|
+
module Hula
|
16
|
+
module ServiceBroker
|
17
|
+
class Client
|
18
|
+
|
19
|
+
extend Forwardable
|
20
|
+
def_delegators :api,
|
21
|
+
:catalog,
|
22
|
+
:debug,
|
23
|
+
:deprovision_instance,
|
24
|
+
:bind_instance,
|
25
|
+
:unbind_instance,
|
26
|
+
:url
|
27
|
+
|
28
|
+
def initialize(args = {})
|
29
|
+
api_args = args.reject { |k, _v| k == :api }
|
30
|
+
@api = args.fetch(:api) { Api.new(api_args) }
|
31
|
+
end
|
32
|
+
|
33
|
+
def provision_and_bind(service_name, plan_name, &block)
|
34
|
+
raise Error, 'no block given' unless block_given?
|
35
|
+
provision_instance(service_name, plan_name) do |service_instance|
|
36
|
+
bind_instance(service_instance, &block)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def provision_instance(service_name, plan_name, &block)
|
41
|
+
plan = catalog.service_plan(service_name, plan_name)
|
42
|
+
service_instance = api.provision_instance(plan)
|
43
|
+
return service_instance unless block
|
44
|
+
|
45
|
+
begin
|
46
|
+
block.call(service_instance)
|
47
|
+
ensure
|
48
|
+
api.deprovision_instance(service_instance)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def bind_instance(service_instance, &block)
|
53
|
+
binding = api.bind_instance(service_instance)
|
54
|
+
return binding unless block
|
55
|
+
|
56
|
+
begin
|
57
|
+
block.call(binding, service_instance)
|
58
|
+
ensure
|
59
|
+
api.unbind_instance(binding)
|
60
|
+
sleep 1
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
attr_reader :api
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# Copyright (c) 2014-2015 Pivotal Software, Inc.
|
2
|
+
# All rights reserved.
|
3
|
+
# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
4
|
+
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
5
|
+
# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
6
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
7
|
+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
8
|
+
# USE OR OTHER DEALINGS IN THE SOFTWARE.
|
9
|
+
#
|
10
|
+
|
11
|
+
module Hula
|
12
|
+
module ServiceBroker
|
13
|
+
class Error < StandardError; end
|
14
|
+
|
15
|
+
class NotInCatalog < Error; end
|
16
|
+
class PlanNotFoundError < NotInCatalog; end
|
17
|
+
class ServiceNotFoundError < NotInCatalog; end
|
18
|
+
|
19
|
+
class JsonParseError < Error; end
|
20
|
+
class TimeoutError < Error; end
|
21
|
+
class HTTPError < Error; end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# Copyright (c) 2014-2015 Pivotal Software, Inc.
|
2
|
+
# All rights reserved.
|
3
|
+
# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
4
|
+
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
5
|
+
# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
6
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
7
|
+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
8
|
+
# USE OR OTHER DEALINGS IN THE SOFTWARE.
|
9
|
+
#
|
10
|
+
|
11
|
+
require 'net/http'
|
12
|
+
|
13
|
+
require 'hula/service_broker/errors'
|
14
|
+
|
15
|
+
module Hula
|
16
|
+
module ServiceBroker
|
17
|
+
|
18
|
+
class HttpProxyNull
|
19
|
+
def http_host
|
20
|
+
nil
|
21
|
+
end
|
22
|
+
def http_port
|
23
|
+
nil
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class HttpJsonClient
|
28
|
+
def initialize(http_proxy: HttpProxyNull.new)
|
29
|
+
@http_proxy = http_proxy
|
30
|
+
end
|
31
|
+
|
32
|
+
def get(uri, auth: nil)
|
33
|
+
request = Net::HTTP::Get.new(uri)
|
34
|
+
request.basic_auth auth.fetch(:username), auth.fetch(:password) unless auth.nil?
|
35
|
+
send_request(request)
|
36
|
+
end
|
37
|
+
|
38
|
+
def put(uri, body: nil, auth: nil)
|
39
|
+
request = Net::HTTP::Put.new(uri)
|
40
|
+
request.body = JSON.generate(body) if body
|
41
|
+
request.basic_auth auth.fetch(:username), auth.fetch(:password) unless auth.nil?
|
42
|
+
send_request(request)
|
43
|
+
end
|
44
|
+
|
45
|
+
def delete(uri, auth: nil)
|
46
|
+
request = Net::HTTP::Delete.new(uri)
|
47
|
+
request.basic_auth auth.fetch(:username), auth.fetch(:password) unless auth.nil?
|
48
|
+
send_request(request)
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
attr_reader :http_proxy
|
54
|
+
|
55
|
+
def send_request(request)
|
56
|
+
uri = request.uri
|
57
|
+
make_request(uri.hostname, uri.port, uri.scheme, request)
|
58
|
+
end
|
59
|
+
|
60
|
+
def make_request(host, port, scheme, request)
|
61
|
+
response = Net::HTTP.start(
|
62
|
+
host,
|
63
|
+
port,
|
64
|
+
http_proxy.http_host,
|
65
|
+
http_proxy.http_port,
|
66
|
+
use_ssl: scheme == 'https',
|
67
|
+
verify_mode: OpenSSL::SSL::VERIFY_NONE
|
68
|
+
) { |http| http.request(request) }
|
69
|
+
|
70
|
+
handle(response)
|
71
|
+
rescue Timeout::Error => e
|
72
|
+
raise TimeoutError, e
|
73
|
+
end
|
74
|
+
|
75
|
+
def handle(response)
|
76
|
+
unless response.is_a?(Net::HTTPSuccess)
|
77
|
+
fail HTTPError, [
|
78
|
+
response.uri.to_s,
|
79
|
+
response.code,
|
80
|
+
response.body
|
81
|
+
].join("\n\n")
|
82
|
+
end
|
83
|
+
|
84
|
+
JSON.parse(response.body, symbolize_names: true)
|
85
|
+
rescue JSON::ParserError => e
|
86
|
+
raise JsonParseError, e
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# Copyright (c) 2014-2015 Pivotal Software, Inc.
|
2
|
+
# All rights reserved.
|
3
|
+
# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
4
|
+
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
5
|
+
# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
6
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
7
|
+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
8
|
+
# USE OR OTHER DEALINGS IN THE SOFTWARE.
|
9
|
+
#
|
10
|
+
|
11
|
+
module Hula
|
12
|
+
module ServiceBroker
|
13
|
+
class InstanceBinding
|
14
|
+
attr_reader :id, :credentials, :service_instance
|
15
|
+
|
16
|
+
def initialize(id:, credentials:, service_instance:)
|
17
|
+
@id = id
|
18
|
+
@credentials = credentials
|
19
|
+
@service_instance = service_instance
|
20
|
+
end
|
21
|
+
|
22
|
+
def ==(other)
|
23
|
+
is_a?(other.class) &&
|
24
|
+
id == other.id &&
|
25
|
+
credentials == other.credentials &&
|
26
|
+
service_instance == other.service_instance
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# Copyright (c) 2014-2015 Pivotal Software, Inc.
|
2
|
+
# All rights reserved.
|
3
|
+
# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
4
|
+
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
5
|
+
# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
6
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
7
|
+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
8
|
+
# USE OR OTHER DEALINGS IN THE SOFTWARE.
|
9
|
+
#
|
10
|
+
|
11
|
+
module Hula
|
12
|
+
module ServiceBroker
|
13
|
+
class Plan
|
14
|
+
def initialize(args = {})
|
15
|
+
@id = args.fetch(:id)
|
16
|
+
@name = args.fetch(:name)
|
17
|
+
@description = args.fetch(:description)
|
18
|
+
@service_id = args.fetch(:service_id)
|
19
|
+
end
|
20
|
+
|
21
|
+
attr_reader :id, :name, :description, :service_id
|
22
|
+
|
23
|
+
def ==(other)
|
24
|
+
is_a?(other.class) &&
|
25
|
+
id == other.id &&
|
26
|
+
name == other.name &&
|
27
|
+
description == other.description &&
|
28
|
+
service_id == other.service_id
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# Copyright (c) 2014-2015 Pivotal Software, Inc.
|
2
|
+
# All rights reserved.
|
3
|
+
# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
4
|
+
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
5
|
+
# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
6
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
7
|
+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
8
|
+
# USE OR OTHER DEALINGS IN THE SOFTWARE.
|
9
|
+
#
|
10
|
+
|
11
|
+
require 'hula/service_broker/errors'
|
12
|
+
require 'hula/service_broker/plan'
|
13
|
+
|
14
|
+
module Hula
|
15
|
+
module ServiceBroker
|
16
|
+
class Service
|
17
|
+
def initialize(args = {})
|
18
|
+
@id = args.fetch(:id)
|
19
|
+
@name = args.fetch(:name)
|
20
|
+
@description = args.fetch(:description)
|
21
|
+
@bindable = !!args.fetch(:bindable)
|
22
|
+
@plans = args.fetch(:plans).map { |p| Plan.new(p.merge(service_id: self.id)) }
|
23
|
+
end
|
24
|
+
|
25
|
+
attr_reader :id, :name, :description, :bindable, :plans
|
26
|
+
|
27
|
+
def ==(other)
|
28
|
+
is_a?(other.class) &&
|
29
|
+
id == other.id &&
|
30
|
+
name == other.name &&
|
31
|
+
description == other.description &&
|
32
|
+
bindable == other.bindable &&
|
33
|
+
plans == other.plans
|
34
|
+
end
|
35
|
+
|
36
|
+
def plan(plan_name)
|
37
|
+
plans.find { |p| p.name == plan_name } or
|
38
|
+
fail(PlanNotFoundError, [
|
39
|
+
%{Unknown plan with name: #{plan_name.inspect}},
|
40
|
+
" Known plan names are: #{plans.map(&:name).inspect}"
|
41
|
+
].join("\n")
|
42
|
+
)
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# Copyright (c) 2014-2015 Pivotal Software, Inc.
|
2
|
+
# All rights reserved.
|
3
|
+
# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
4
|
+
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
5
|
+
# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
6
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
7
|
+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
8
|
+
# USE OR OTHER DEALINGS IN THE SOFTWARE.
|
9
|
+
#
|
10
|
+
|
11
|
+
module Hula
|
12
|
+
module ServiceBroker
|
13
|
+
class ServiceInstance
|
14
|
+
def initialize(id:)
|
15
|
+
@id = id
|
16
|
+
end
|
17
|
+
attr_reader :id
|
18
|
+
|
19
|
+
def ==(other)
|
20
|
+
is_a?(other.class) && id == other.id
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
# Copyright (c) 2014-2015 Pivotal Software, Inc.
|
2
|
+
# All rights reserved.
|
3
|
+
# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
4
|
+
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
5
|
+
# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
6
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
7
|
+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
8
|
+
# USE OR OTHER DEALINGS IN THE SOFTWARE.
|
9
|
+
#
|
10
|
+
|
11
|
+
require 'hula/helpers/socket_tools'
|
12
|
+
require 'pty'
|
13
|
+
require 'expect'
|
14
|
+
|
15
|
+
module Hula
|
16
|
+
class Socks4ProxySsh
|
17
|
+
class FailedToStart < StandardError; end
|
18
|
+
class DieSignal < StandardError; end
|
19
|
+
|
20
|
+
include Helpers::SocketTools
|
21
|
+
|
22
|
+
def initialize(
|
23
|
+
ssh_host:,
|
24
|
+
ssh_username:,
|
25
|
+
ssh_password:,
|
26
|
+
socks_host: 'localhost',
|
27
|
+
socks_port: free_port,
|
28
|
+
ssh_bin: 'ssh',
|
29
|
+
retry_count: 10
|
30
|
+
)
|
31
|
+
@ssh_bin = String(ssh_bin)
|
32
|
+
@ssh_host = String(ssh_host)
|
33
|
+
@ssh_username = String(ssh_username)
|
34
|
+
@ssh_password = String(ssh_password)
|
35
|
+
@socks_port = String(socks_port)
|
36
|
+
@socks_host = String(socks_host)
|
37
|
+
@retry_count = retry_count
|
38
|
+
end
|
39
|
+
|
40
|
+
attr_reader :socks_port, :socks_host
|
41
|
+
|
42
|
+
def stop
|
43
|
+
return unless @thread
|
44
|
+
@thread.raise(DieSignal)
|
45
|
+
@thread.join
|
46
|
+
@thread = nil
|
47
|
+
end
|
48
|
+
|
49
|
+
def start
|
50
|
+
@thread ||= begin
|
51
|
+
thread = start_ssh_socks_thread
|
52
|
+
wait_for_port(:host => socks_host, :port => socks_port, timeout_seconds: 30)
|
53
|
+
thread
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
attr_reader :ssh_host, :ssh_username, :ssh_password, :ssh_bin
|
60
|
+
|
61
|
+
def start_ssh_socks_thread
|
62
|
+
# We need to shell out to ssh as this has a SOCKS proxy facility
|
63
|
+
# However, there's a problem. SSH does not provide an argument for passing in a password
|
64
|
+
# We don't have keys available so we need to use expect to feed the password into the prompt
|
65
|
+
Thread.new(
|
66
|
+
ssh_command,
|
67
|
+
ssh_password
|
68
|
+
) do |ssh_command, ssh_password|
|
69
|
+
tries_remaining = @retry_count
|
70
|
+
|
71
|
+
while true
|
72
|
+
puts "--- SSH Gateway attempt #{@retry_count + 1 - tries_remaining}"
|
73
|
+
sleep 1
|
74
|
+
|
75
|
+
begin
|
76
|
+
ssh_out, ssh_in, pid = PTY.spawn(*ssh_command)
|
77
|
+
# On BOSH lite a password is used, however on aws an identity is used
|
78
|
+
# The below statment will wait on a aws run and the pid is never returned
|
79
|
+
ssh_out.expect(/[Pp]assword\:/) { |r| ssh_in.print("#{ssh_password}\n") }
|
80
|
+
Process.wait(pid)
|
81
|
+
|
82
|
+
tries_remaining -= 1
|
83
|
+
if tries_remaining < 0
|
84
|
+
raise FailedToStart, "SSH finished early - SSH Socks Proxy could not be setup or failed"
|
85
|
+
end
|
86
|
+
rescue Errno::EIO
|
87
|
+
tries_remaining -= 1
|
88
|
+
# Can't read or write to dead process
|
89
|
+
|
90
|
+
if tries_remaining < 0
|
91
|
+
raise FailedToStart, "SSH finished early EIO - SSH Socks Proxy could not be setup or failed"
|
92
|
+
end
|
93
|
+
rescue DieSignal
|
94
|
+
Process.kill('KILL', pid) rescue Errno::ESRCH
|
95
|
+
Process.wait(pid) rescue Errno::ECHILD
|
96
|
+
break
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end.tap do |thread|
|
100
|
+
thread.abort_on_exception = true
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def ssh_command
|
105
|
+
[
|
106
|
+
ssh_bin,
|
107
|
+
'-D', "#{socks_host}:#{socks_port}",
|
108
|
+
'-N',
|
109
|
+
"#{ssh_username}@#{ssh_host}",
|
110
|
+
'-o', 'UserKnownHostsFile=/dev/null',
|
111
|
+
'-o', 'StrictHostKeyChecking=no',
|
112
|
+
'-o', 'NumberOfPasswordPrompts=1',
|
113
|
+
'-o', 'StrictHostKeyChecking=no'
|
114
|
+
]
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
end
|
data/lib/hula/version.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# Copyright (c) 2014-2015 Pivotal Software, Inc.
|
2
|
+
# All rights reserved.
|
3
|
+
# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
4
|
+
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
5
|
+
# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
6
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
7
|
+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
8
|
+
# USE OR OTHER DEALINGS IN THE SOFTWARE.
|
9
|
+
#
|
10
|
+
|
11
|
+
module Hula
|
12
|
+
VERSION = '0.7.1'
|
13
|
+
end
|
data/lib/hula.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# Copyright (c) 2014-2015 Pivotal Software, Inc.
|
2
|
+
# All rights reserved.
|
3
|
+
# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
4
|
+
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
5
|
+
# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
6
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
7
|
+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
8
|
+
# USE OR OTHER DEALINGS IN THE SOFTWARE.
|
9
|
+
#
|
10
|
+
|
11
|
+
require 'hula/version'
|
12
|
+
require 'hula/bosh_director'
|
13
|
+
require 'hula/cloud_foundry'
|
14
|
+
|
15
|
+
module Hula
|
16
|
+
end
|