bosh_common 0.5.4 → 1.5.0.pre.1100

Sign up to get free protection for your applications and to get access to all the features.
data/lib/common/common.rb CHANGED
@@ -1,4 +1,6 @@
1
1
  # Copyright (c) 2012 VMware, Inc.
2
+ require 'common/errors'
3
+ require 'common/retryable'
2
4
 
3
5
  module Bosh
4
6
 
@@ -43,5 +45,80 @@ module Bosh
43
45
  end
44
46
 
45
47
  module_function :which
48
+
49
+ # Retries execution of given block until block returns true
50
+ #
51
+ # The block is called with two parameters: the number of tries and the most recent
52
+ # exception. If the block returns true retrying is stopped.
53
+ # Examples:
54
+ # Bosh::Common.retryable do |retries, exception|
55
+ # puts "try #{retries} failed with exception: #{exception}" if retries > 0
56
+ # pick_up_soap
57
+ # end
58
+ #
59
+ # # Wait for EC2 instance to be terminated
60
+ # Bosh::Common.retryable(on: AWS::EC2::Errors::RequestLimitExceeded) do |retries, exception|
61
+ # @ec2.instance['i-a3x5g5'].status == :terminated
62
+ # end
63
+ #
64
+ #
65
+ # @param [Hash] options
66
+ # @options opts [Proc] :ensure
67
+ # Default: `Proc.new {}`
68
+ # Ensure that a block of code is executed, regardless of whether an exception
69
+ # was raised. It doesn't matter if the block exits normally, if it retries
70
+ # to execute block of code, or if it is terminated by an uncaught exception
71
+ # -- the ensure block will get run.
72
+ # Example:
73
+ # f = File.open("testfile")
74
+ #
75
+ # ensure_cb = Proc.new do |retries|
76
+ # puts "total retry attempts: #{retries}"
77
+ #
78
+ # f.close
79
+ # end
80
+ #
81
+ # Bosh::Common.retryable(ensure: ensure_cb) do
82
+ # # process file
83
+ # end
84
+ #
85
+ # @options opts [Regexp] :matching
86
+ # Default: `/.*/`
87
+ # Retry based on the exception message
88
+ # Example:
89
+ # Bosh::Common.retryable(matching: /IO timeout/) do |retries, exception|
90
+ # raise "yo, IO timeout!" if retries == 0
91
+ # end
92
+ #
93
+ # @options opts [Array<ExceptionClass>] :on
94
+ # Default: `[]`
95
+ # The array of exception classes to retry on.
96
+ # Example:
97
+ # Bosh::Common.retryable(on: [StandardError, ArgumentError]) do
98
+ # # do something and retry if StandardError or ArgumentError is raised
99
+ # end
100
+ #
101
+ # @options opts [Proc, Fixnum] :sleep
102
+ # Defaults: `lambda { |tries, _| [2**(tries-1), 10].min }`, 1, 2, 4, 8, 10, 10..10 seconds
103
+ # If a Fixnum is given, sleep that many seconds between retries.
104
+ # If a Proc is given, call it with the expectation that a Fixnum is returned
105
+ # and sleep that many seconds. The Proc will be called with the number of tries
106
+ # and the raised exception (or nil)
107
+ # Example:
108
+ # Bosh::Common.retryable(sleep: lambda { |n,e| logger.info(e.message) if e; 4**n }) { }
109
+ #
110
+ # @options opts [Fixnum] :tries
111
+ # Default: 2
112
+ # Number of times to try
113
+ # Example:
114
+ # Bosh::Common.retryable(tries: 3, on: OpenURI::HTTPError) do
115
+ # xml = open("http://example.com/test.xml").read
116
+ # end
117
+ #
118
+ def retryable(options = {}, &block)
119
+ Bosh::Retryable.new(options).retryer(&block)
120
+ end
121
+
122
+ module_function :retryable
46
123
  end
47
124
  end
@@ -0,0 +1,7 @@
1
+ module Bosh::Common
2
+ module DeepCopy
3
+ def self.copy(object)
4
+ Marshal.load(Marshal.dump(object))
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ # Copyright (c) 2009-2012 VMware, Inc.
2
+
3
+ module Bosh
4
+ module Common
5
+ class RetryCountExceeded < Exception; end
6
+ end
7
+ end
@@ -23,7 +23,7 @@ module Bosh::Common
23
23
  end
24
24
 
25
25
  dst_ref[keys[-1]] ||= {}
26
- dst_ref[keys[-1]] = src_ref || default
26
+ dst_ref[keys[-1]] = src_ref.nil? ? default : src_ref
27
27
  end
28
28
 
29
29
  # @param [Hash] collection Property collection
@@ -40,4 +40,4 @@ module Bosh::Common
40
40
  ref
41
41
  end
42
42
  end
43
- end
43
+ end
@@ -73,18 +73,14 @@ module Bosh::Common
73
73
  # @return [Object] Property value
74
74
  # @raise [Bosh::Common::UnknownProperty]
75
75
  def p(*args)
76
- names = args[0]
77
- default_given = args.size > 1
78
- default = args[1]
79
-
80
- names = Array(names) unless names.kind_of?(Array)
76
+ names = Array(args[0])
81
77
 
82
78
  names.each do |name|
83
79
  result = lookup_property(@raw_properties, name)
84
80
  return result unless result.nil?
85
81
  end
86
82
 
87
- return default if default_given
83
+ return args[1] if args.length == 2
88
84
  raise UnknownProperty.new(names)
89
85
  end
90
86
 
@@ -94,11 +90,12 @@ module Bosh::Common
94
90
  def if_p(*names)
95
91
  values = names.map do |name|
96
92
  value = lookup_property(@raw_properties, name)
97
- return if value.nil?
93
+ return ActiveElseBlock.new(self) if value.nil?
98
94
  value
99
95
  end
100
96
 
101
97
  yield *values
98
+ InactiveElseBlock.new
102
99
  end
103
100
 
104
101
  # @return [Object] Object representation where all hashes are unrolled
@@ -115,5 +112,29 @@ module Bosh::Common
115
112
  object
116
113
  end
117
114
  end
115
+
116
+ private
117
+ class ActiveElseBlock
118
+ def initialize(template_context)
119
+ @context = template_context
120
+ end
121
+
122
+ def else
123
+ yield
124
+ end
125
+
126
+ def else_if_p(*names, &block)
127
+ @context.if_p(*names, &block)
128
+ end
129
+ end
130
+
131
+ class InactiveElseBlock
132
+ def else
133
+ end
134
+
135
+ def else_if_p(*names)
136
+ InactiveElseBlock.new
137
+ end
138
+ end
118
139
  end
119
- end
140
+ end
@@ -0,0 +1,74 @@
1
+ require_relative 'errors'
2
+
3
+ module Bosh
4
+ class Retryable
5
+ def initialize(options = {})
6
+ opts = validate_options(options)
7
+
8
+ @ensure_callback = opts[:ensure]
9
+ @matching = opts[:matching]
10
+ @on_exception = [opts[:on]].flatten
11
+ @try_count = 0
12
+ @retry_exception = nil
13
+ @retry_limit = opts[:tries]
14
+ @sleeper = opts[:sleep]
15
+ end
16
+
17
+ # this method will loop until the block returns a true value
18
+ def retryer(&block)
19
+ loop do
20
+ @try_count += 1
21
+ y = yield @try_count, @retry_exception
22
+ @retry_exception = nil # no exception was raised in the block
23
+ return y if y
24
+ raise Bosh::Common::RetryCountExceeded if @try_count >= @retry_limit
25
+ wait
26
+ end
27
+ rescue *@on_exception => exception
28
+ raise unless exception.message =~ @matching
29
+ raise if @try_count >= @retry_limit
30
+
31
+ @retry_exception = exception
32
+ wait
33
+ retry
34
+ ensure
35
+ @ensure_callback.call(@try_count)
36
+ end
37
+
38
+ private
39
+
40
+ def validate_options(options)
41
+ merged_options = default_options.merge(options)
42
+ invalid_options = merged_options.keys - default_options.keys
43
+ raise ArgumentError.new("Invalid options: #{invalid_options.join(", ")}") unless invalid_options.empty?
44
+
45
+ merged_options
46
+ end
47
+
48
+ def default_options
49
+ {
50
+ tries: 2,
51
+ sleep: exponential_sleeper,
52
+ on: [],
53
+ matching: /.*/,
54
+ ensure: Proc.new {}
55
+ }
56
+ end
57
+
58
+ def wait
59
+ sleep(@sleeper.respond_to?(:call) ? @sleeper.call(@try_count, @retry_exception) : @sleeper)
60
+ rescue *@on_exception
61
+ # SignalException could be raised while sleeping, so if you want to catch it,
62
+ # it need to be passed in the list of exceptions to ignore
63
+ end
64
+
65
+ def exponential_sleeper
66
+ lambda { |tries, _| [2**(tries-1), 10].min } # 1, 2, 4, 8, 10, 10..10 seconds
67
+ end
68
+
69
+ def sleep(*args, &blk)
70
+ Kernel.sleep(*args, &blk)
71
+ end
72
+ end
73
+ end
74
+
@@ -0,0 +1,12 @@
1
+ require 'common/exec'
2
+
3
+ # Mixin to make it easy to inject an alternate command runner into a class that runs commands.
4
+ module Bosh
5
+ module RunsCommands
6
+ def sh(command)
7
+ (@command_runner || Bosh::Exec).sh(command)
8
+ end
9
+
10
+ attr_accessor :command_runner
11
+ end
12
+ end
data/lib/common/ssl.rb ADDED
@@ -0,0 +1,107 @@
1
+ require 'openssl'
2
+
3
+ module Bosh
4
+ module Ssl
5
+ class Certificate
6
+ class SubjectsDoNotMatchException < RuntimeError;
7
+ end
8
+ class MatchingFileNotFound < RuntimeError;
9
+ end
10
+
11
+ attr_reader :key_path, :certificate_path
12
+
13
+ def initialize(key_path, certificate_path, common_name, chain_path = nil)
14
+ @key_path = key_path
15
+ @certificate_path = certificate_path
16
+ @chain_path = chain_path
17
+ @subject_string = subject_string(common_name)
18
+ end
19
+
20
+ def key
21
+ @key.to_pem
22
+ end
23
+
24
+ def certificate
25
+ @csr_cert.to_pem
26
+ end
27
+
28
+ def chain
29
+ @chain.to_pem if @chain
30
+ end
31
+
32
+ def load_or_create
33
+ @key, @csr_cert = load_or_create_key_and_csr_cert
34
+ @chain = OpenSSL::X509::Certificate.new(File.read(@chain_path)) if @chain_path
35
+
36
+ self
37
+ end
38
+
39
+ private
40
+
41
+ def load_or_create_key_and_csr_cert
42
+ if File.exists?(@key_path) && !File.exists?(@certificate_path)
43
+ raise MatchingFileNotFound, 'The key that matches the given certificate could not be found.'
44
+ end
45
+
46
+ if File.exists?(@certificate_path) && !File.exists?(@key_path)
47
+ raise MatchingFileNotFound, 'The certificate that matches the given key could not be found.'
48
+ end
49
+
50
+ if File.exists?(@key_path) && File.exists?(@certificate_path)
51
+ load_key_and_csr_cert
52
+ else
53
+ create_key_and_csr_cert
54
+ end
55
+ end
56
+
57
+ def load_key_and_csr_cert
58
+ key = OpenSSL::PKey::RSA.new(File.read(@key_path))
59
+ csr_cert = OpenSSL::X509::Certificate.new(File.read(@certificate_path))
60
+
61
+ [key, csr_cert]
62
+ end
63
+
64
+ def create_key_and_csr_cert
65
+ subject = OpenSSL::X509::Name.parse(@subject_string)
66
+ key = OpenSSL::PKey::RSA.new(2048)
67
+ csr = new_csr(key, subject)
68
+ csr_cert = new_csr_certificate(key, csr)
69
+
70
+ File.write(@key_path, key.to_pem)
71
+ File.write(@certificate_path, csr_cert.to_pem)
72
+
73
+ [key, csr_cert]
74
+ end
75
+
76
+ def new_csr(key, subject)
77
+ csr = OpenSSL::X509::Request.new
78
+ csr.version = 0
79
+ csr.subject = subject
80
+ csr.public_key = key.public_key
81
+ csr.sign key, OpenSSL::Digest::SHA1.new
82
+
83
+ csr
84
+ end
85
+
86
+ def new_csr_certificate(key, csr)
87
+ csr_cert = OpenSSL::X509::Certificate.new
88
+ csr_cert.serial = 0
89
+ csr_cert.version = 2
90
+ csr_cert.not_before = Time.now - 60 * 60 * 24
91
+ csr_cert.not_after = Time.now + 94608000
92
+
93
+ csr_cert.subject = csr.subject
94
+ csr_cert.public_key = csr.public_key
95
+ csr_cert.issuer = csr.subject
96
+
97
+ csr_cert.sign key, OpenSSL::Digest::SHA1.new
98
+
99
+ csr_cert
100
+ end
101
+
102
+ def subject_string(common_name)
103
+ "/C=US/O=Pivotal/CN=#{common_name}"
104
+ end
105
+ end
106
+ end
107
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Bosh
4
4
  module Common
5
- VERSION = "0.5.4"
5
+ VERSION = '1.5.0.pre.1100'
6
6
  end
7
7
  end
@@ -0,0 +1,53 @@
1
+ module Bosh::Common
2
+ class VersionNumber
3
+ include Comparable
4
+
5
+ def initialize(version_value)
6
+ @version = version_value.to_s
7
+ end
8
+
9
+ def <=>(other)
10
+ v1 = @version
11
+ v2 = other.to_s
12
+ return v1 <=> v2 if [v1, v2].all? { |v| v.to_s.match(/^\d{4}-\d{2}-\d{2}_\d{2}-\d{2}-\d{2}$/) }
13
+
14
+ vp1 = components
15
+ vp2 = other.components
16
+
17
+ [vp1.size, vp2.size].max.times do |i|
18
+ result = vp1[i].to_i <=> vp2[i].to_i
19
+ return result unless result == 0
20
+ end
21
+
22
+ 0
23
+ end
24
+
25
+ def major
26
+ components[0].to_i
27
+ end
28
+
29
+ def minor
30
+ components[1].to_i
31
+ end
32
+
33
+ def components
34
+ @version.split('.')
35
+ end
36
+
37
+ def to_s
38
+ @version
39
+ end
40
+
41
+ def final?
42
+ !@version.end_with?('-dev')
43
+ end
44
+
45
+ def next_minor
46
+ self.class.new("#{major}.#{minor + 1}")
47
+ end
48
+
49
+ def dev
50
+ final? ? self.class.new("#{@version}-dev") : self
51
+ end
52
+ end
53
+ end
metadata CHANGED
@@ -1,23 +1,27 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bosh_common
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.4
5
- prerelease:
4
+ version: 1.5.0.pre.1100
5
+ prerelease: 6
6
6
  platform: ruby
7
7
  authors:
8
8
  - VMware
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-01-01 00:00:00.000000000 Z
12
+ date: 2013-10-12 00:00:00.000000000 Z
13
13
  dependencies: []
14
- description: BOSH common
15
- email: support@vmware.com
14
+ description: ! 'BOSH common
15
+
16
+ a5984f'
17
+ email: support@cloudfoundry.com
16
18
  executables: []
17
19
  extensions: []
18
20
  extra_rdoc_files: []
19
21
  files:
20
22
  - lib/common/common.rb
23
+ - lib/common/deep_copy.rb
24
+ - lib/common/errors.rb
21
25
  - lib/common/exec.rb
22
26
  - lib/common/exec/error.rb
23
27
  - lib/common/exec/result.rb
@@ -25,21 +29,17 @@ files:
25
29
  - lib/common/properties/errors.rb
26
30
  - lib/common/properties/property_helper.rb
27
31
  - lib/common/properties/template_evaluation_context.rb
32
+ - lib/common/retryable.rb
33
+ - lib/common/runs_commands.rb
34
+ - lib/common/ssl.rb
28
35
  - lib/common/thread_formatter.rb
29
36
  - lib/common/thread_pool.rb
30
37
  - lib/common/version.rb
38
+ - lib/common/version_number.rb
31
39
  - README
32
- - Rakefile
33
- - spec/assets/foo1
34
- - spec/assets/foo2
35
- - spec/spec_helper.rb
36
- - spec/unit/common_spec.rb
37
- - spec/unit/exec_spec.rb
38
- - spec/unit/properties/property_helper_spec.rb
39
- - spec/unit/properties/template_evaluation_context_spec.rb
40
- - spec/unit/thread_pool_spec.rb
41
- homepage: http://www.vmware.com
42
- licenses: []
40
+ homepage: https://github.com/cloudfoundry/bosh
41
+ licenses:
42
+ - Apache 2.0
43
43
  post_install_message:
44
44
  rdoc_options: []
45
45
  require_paths:
@@ -49,26 +49,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
49
49
  requirements:
50
50
  - - ! '>='
51
51
  - !ruby/object:Gem::Version
52
- version: '0'
52
+ version: 1.9.3
53
53
  required_rubygems_version: !ruby/object:Gem::Requirement
54
54
  none: false
55
55
  requirements:
56
- - - ! '>='
56
+ - - ! '>'
57
57
  - !ruby/object:Gem::Version
58
- version: '0'
58
+ version: 1.3.1
59
59
  requirements: []
60
60
  rubyforge_project:
61
- rubygems_version: 1.8.24
61
+ rubygems_version: 1.8.23
62
62
  signing_key:
63
63
  specification_version: 3
64
64
  summary: BOSH common
65
- test_files:
66
- - spec/assets/foo1
67
- - spec/assets/foo2
68
- - spec/spec_helper.rb
69
- - spec/unit/common_spec.rb
70
- - spec/unit/exec_spec.rb
71
- - spec/unit/properties/property_helper_spec.rb
72
- - spec/unit/properties/template_evaluation_context_spec.rb
73
- - spec/unit/thread_pool_spec.rb
74
- has_rdoc:
65
+ test_files: []
data/Rakefile DELETED
@@ -1,50 +0,0 @@
1
- # Copyright (c) 2009-2012 VMware, Inc.
2
-
3
- $:.unshift(File.expand_path("../../rake", __FILE__))
4
-
5
- ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __FILE__)
6
-
7
- require "rubygems"
8
- require "bundler"
9
- Bundler.setup(:default, :test)
10
-
11
- require "rake"
12
- begin
13
- require "rspec/core/rake_task"
14
- rescue LoadError
15
- end
16
-
17
- require "bundler_task"
18
- require "ci_task"
19
-
20
- gem_helper = Bundler::GemHelper.new(Dir.pwd)
21
-
22
- desc "Build BOSH Common gem into the pkg directory"
23
- task "build" do
24
- gem_helper.build_gem
25
- end
26
-
27
- desc "Build and install BOSH Common into system gems"
28
- task "install" do
29
- Rake::Task["bundler:install"].invoke
30
- gem_helper.install_gem
31
- end
32
-
33
- BundlerTask.new
34
-
35
- if defined?(RSpec)
36
- namespace :spec do
37
- desc "Run Unit Tests"
38
- rspec_task = RSpec::Core::RakeTask.new(:unit) do |t|
39
- t.pattern = "spec/unit/**/*_spec.rb"
40
- t.rspec_opts = %w(--format progress --colour)
41
- end
42
-
43
- CiTask.new do |task|
44
- task.rspec_task = rspec_task
45
- end
46
- end
47
-
48
- desc "Run tests"
49
- task :spec => %w(spec:unit)
50
- end
data/spec/assets/foo1 DELETED
File without changes
data/spec/assets/foo2 DELETED
File without changes
data/spec/spec_helper.rb DELETED
@@ -1,13 +0,0 @@
1
- # Copyright (c) 2009-2012 VMware, Inc.
2
-
3
- ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", __FILE__)
4
-
5
- require "rubygems"
6
- require "bundler"
7
- Bundler.setup(:default, :test)
8
-
9
- require "rspec"
10
-
11
- def asset(file)
12
- File.expand_path(File.join(File.dirname(__FILE__), "assets", file))
13
- end
@@ -1,59 +0,0 @@
1
- # Copyright (c) 2012 VMware, Inc.
2
-
3
- require "spec_helper"
4
-
5
- require "common/common"
6
-
7
- describe Bosh::Common do
8
-
9
- describe "#symbolize_keys" do
10
- ORIGINAL = {
11
- "foo1" => "bar",
12
- :foo2 => "bar",
13
- "foo3" => {
14
- "foo4" => "bar"
15
- }
16
- }.freeze
17
-
18
- EXPECTED = {
19
- :foo1 => "bar",
20
- :foo2 => "bar",
21
- :foo3 => {
22
- :foo4 => "bar"
23
- }
24
- }.freeze
25
-
26
- it "should not modify the original hash" do
27
- duplicate = ORIGINAL.dup
28
- Bosh::Common.symbolize_keys(ORIGINAL)
29
- ORIGINAL.should == duplicate
30
- end
31
-
32
- it "should return a new hash with all keys as symbols" do
33
- Bosh::Common.symbolize_keys(ORIGINAL).should == EXPECTED
34
- end
35
- end
36
-
37
- describe "#which" do
38
- let(:path) {
39
- path = ENV["PATH"]
40
- path += ":#{File.expand_path('../../assets', __FILE__)}"
41
- }
42
-
43
- it "should return the path when it finds the executable" do
44
- Bosh::Common.which("foo1", path).should_not be_nil
45
- end
46
-
47
- it "should return the path when it finds an executable" do
48
- Bosh::Common.which(%w[foo2 foo1], path).should match(%r{/foo1$})
49
- end
50
-
51
- it "should return nil when it isn't executable" do
52
- Bosh::Common.which("foo2", path).should be_nil
53
- end
54
-
55
- it "should return nil when it doesn't find an executable" do
56
- Bosh::Common.which("foo1").should be_nil
57
- end
58
- end
59
- end
@@ -1,114 +0,0 @@
1
- # Copyright (c) 2012 VMware, Inc.
2
-
3
- require "spec_helper"
4
- require "common/exec"
5
-
6
- describe Bosh::Exec do
7
- let(:opts) { {} }
8
-
9
- context "existing command" do
10
-
11
- context "executes successfully" do
12
- it "should not fail" do
13
- Bosh::Exec.sh("ls /", opts).failed?.should be_false
14
- end
15
-
16
- it "should execute block" do
17
- block = false
18
- Bosh::Exec.sh("ls /", opts) do
19
- block = true
20
- end
21
- block.should be_true
22
- end
23
- end
24
-
25
- context "fails to execute" do
26
- it "should raise error by default" do
27
- expect {
28
- Bosh::Exec.sh("ls /asdasd 2>&1", opts)
29
- }.to raise_error { |error|
30
- error.should be_a Bosh::Exec::Error
31
- error.output.should match /No such file or directory/
32
- }
33
- end
34
-
35
- it "should yield block on false" do
36
- opts[:yield] = :on_false
37
- block = false
38
- Bosh::Exec.sh("ls /asdasd 2>&1", opts) do
39
- block = true
40
- end
41
- block.should be_true
42
- end
43
-
44
- it "should return result" do
45
- opts[:on_error] = :return
46
- Bosh::Exec.sh("ls /asdasd 2>&1", opts).failed?.should be_true
47
- end
48
- end
49
-
50
- end
51
-
52
- context "missing command" do
53
- it "should raise error by default" do
54
- expect {
55
- Bosh::Exec.sh("/asdasd 2>&1", opts)
56
- }.to raise_error Bosh::Exec::Error
57
- end
58
-
59
- it "should not raise error when requested" do
60
- opts[:on_error] = :return
61
- expect {
62
- Bosh::Exec.sh("/asdasd 2>&1", opts)
63
- }.to_not raise_error Bosh::Exec::Error
64
- end
65
-
66
- it "should execute block when requested" do
67
- opts[:yield] = :on_false
68
- expect {
69
- Bosh::Exec.sh("/asdasd 2>&1", opts) do
70
- raise "foo"
71
- end
72
- }.to raise_error "foo"
73
- end
74
-
75
- end
76
-
77
- context "mock" do
78
- it "should be possible fake result" do
79
- cmd = "ls /"
80
- result = Bosh::Exec::Result.new(cmd, "output", 0)
81
- Bosh::Exec.should_receive(:sh).with(cmd).and_return(result)
82
- result = Bosh::Exec.sh(cmd)
83
- result.success?.should be_true
84
- end
85
- end
86
-
87
- context "module" do
88
- it "should be possible to invoke as a module" do
89
- Bosh::Exec.sh("ls /").success?.should be_true
90
- end
91
- end
92
-
93
- context "include" do
94
- class IncludeTest
95
- include Bosh::Exec
96
- def run
97
- sh("ls /")
98
- end
99
-
100
- def self.run
101
- sh("ls /")
102
- end
103
- end
104
-
105
- it "should add instance method" do
106
- inc = IncludeTest.new
107
- inc.run.success?.should be_true
108
- end
109
-
110
- it "should add class method" do
111
- IncludeTest.run.success?.should be_true
112
- end
113
- end
114
- end
@@ -1,39 +0,0 @@
1
- # Copyright (c) 2012 VMware, Inc.
2
-
3
- require "spec_helper"
4
- require "common/properties"
5
-
6
- describe Bosh::Common::PropertyHelper do
7
-
8
- before(:each) do
9
- @helper = Object.new
10
- @helper.extend(Bosh::Common::PropertyHelper)
11
- end
12
-
13
- it "can copy named property from one collection to another" do
14
- dst = {}
15
- src = {"foo" => {"bar" => "baz", "secret" => "zazzle"}}
16
-
17
- @helper.copy_property(dst, src, "foo.bar")
18
- dst.should == {"foo" => {"bar" => "baz"}}
19
-
20
- @helper.copy_property(dst, src, "no.such.prop", "default")
21
- dst.should == {
22
- "foo" => {"bar" => "baz"},
23
- "no" => {
24
- "such" => {"prop" => "default"}
25
- }
26
- }
27
- end
28
-
29
- it "can lookup the property in a Hash using dot-syntax" do
30
- properties = {
31
- "foo" => {"bar" => "baz"},
32
- "router" => {"token" => "foo"}
33
- }
34
-
35
- @helper.lookup_property(properties, "foo.bar").should == "baz"
36
- @helper.lookup_property(properties, "router").should == {"token" => "foo"}
37
- @helper.lookup_property(properties, "no.prop").should be_nil
38
- end
39
- end
@@ -1,112 +0,0 @@
1
- # Copyright (c) 2012 VMware, Inc.
2
-
3
- require "spec_helper"
4
- require "common/properties"
5
-
6
- describe Bosh::Common::TemplateEvaluationContext do
7
-
8
- def eval_template(erb, context)
9
- ERB.new(erb).result(context.get_binding)
10
- end
11
-
12
- def make(spec)
13
- Bosh::Common::TemplateEvaluationContext.new(spec)
14
- end
15
-
16
- before(:each) do
17
- @spec = {
18
- "job" => {
19
- "name" => "foobar"
20
- },
21
- "properties" => {
22
- "foo" => "bar",
23
- "router" => {"token" => "zbb"},
24
- "vtrue" => true,
25
- "vfalse" => false
26
- },
27
- "index" => 0,
28
- }
29
-
30
- @context = make(@spec)
31
- end
32
-
33
- it "unrolls properties into OpenStruct" do
34
- eval_template("<%= properties.foo %>", @context).should == "bar"
35
- end
36
-
37
- it "retains raw_properties" do
38
- eval_template("<%= raw_properties['router']['token'] %>", @context).
39
- should == "zbb"
40
- end
41
-
42
- it "supports looking up template index" do
43
- eval_template("<%= spec.index %>", @context).should == "0"
44
- end
45
-
46
- it "supports 'p' helper" do
47
- eval_template("<%= p('router.token') %>", @context).should == "zbb"
48
-
49
- eval_template("<%= p('vtrue') %>", @context).should == "true"
50
- eval_template("<%= p('vfalse') %>", @context).should == "false"
51
-
52
- expect {
53
- eval_template("<%= p('bar.baz') %>", @context)
54
- }.to raise_error(Bosh::Common::UnknownProperty,
55
- "Can't find property `[\"bar.baz\"]'")
56
- eval_template("<%= p('bar.baz', 22) %>", @context).should == "22"
57
- end
58
-
59
- it "supports chaining property lookup via 'p' helper" do
60
- eval_template(<<-TMPL, @context).strip.should == "zbb"
61
- <%= p(%w(a b router.token c)) %>
62
- TMPL
63
-
64
- expect {
65
- eval_template(<<-TMPL, @context)
66
- <%= p(%w(a b c)) %>
67
- TMPL
68
- }.to raise_error(Bosh::Common::UnknownProperty,
69
- "Can't find property `[\"a\", \"b\", \"c\"]'")
70
-
71
- eval_template(<<-TMPL, @context).strip.should == "22"
72
- <%= p(%w(a b c), 22) %>
73
- TMPL
74
- end
75
-
76
- it "allows 'false' and 'nil' defaults for 'p' helper" do
77
- eval_template(<<-TMPL, @context).strip.should == "false"
78
- <%= p(%w(a b c), false) %>
79
- TMPL
80
-
81
- eval_template(<<-TMPL, @context).strip.should == ""
82
- <%= p(%w(a b c), nil) %>
83
- TMPL
84
- end
85
-
86
- it "supports 'if_p' helper" do
87
- template = <<-TMPL
88
- <% if_p("router.token") do |token| %>
89
- <%= token %>
90
- <% end %>
91
- TMPL
92
-
93
- eval_template(template, @context).strip.should == "zbb"
94
-
95
- template = <<-TMPL
96
- <% if_p("router.token", "foo") do |token, foo| %>
97
- <%= token %>, <%= foo %>
98
- <% end %>
99
- TMPL
100
-
101
- eval_template(template, @context).strip.should == "zbb, bar"
102
-
103
- template = <<-TMPL
104
- <% if_p("router.token", "no.such.prop") do |token, none| %>
105
- test output
106
- <% end %>
107
- TMPL
108
-
109
- eval_template(template, @context).strip.should == ""
110
- end
111
-
112
- end
@@ -1,69 +0,0 @@
1
- # Copyright (c) 2009-2012 VMware, Inc.
2
-
3
- require File.expand_path("../../spec_helper", __FILE__)
4
-
5
- require "common/thread_pool"
6
-
7
- describe Bosh::ThreadPool do
8
-
9
- before(:all) do
10
- @logger = Logger.new(STDOUT)
11
- @logger.level = Logger::INFO
12
- end
13
-
14
- it "should respect max threads" do
15
- max = 0
16
- current = 0
17
- lock = Mutex.new
18
-
19
- Bosh::ThreadPool.new(:max_threads => 2, :logger => @logger).wrap do |pool|
20
- 4.times do
21
- pool.process do
22
- lock.synchronize do
23
- current += 1
24
- max = current if current > max
25
- end
26
- sleep(0.050)
27
- lock.synchronize do
28
- max = current if current > max
29
- current -= 1
30
- end
31
- end
32
- end
33
- end
34
- max.should be <= 2
35
- end
36
-
37
- it "should raise exceptions" do
38
- lambda {
39
- Bosh::ThreadPool.new(:max_threads => 2, :logger => @logger).wrap do |pool|
40
- 5.times do |index|
41
- pool.process do
42
- sleep(0.050)
43
- raise "bad" if index == 4
44
- end
45
- end
46
- end
47
- }.should raise_exception("bad")
48
- end
49
-
50
- it "should stop processing new work when there was an exception" do
51
- max = 0
52
- lock = Mutex.new
53
-
54
- lambda {
55
- Bosh::ThreadPool.new(:max_threads => 1, :logger => @logger).wrap do |pool|
56
- 10.times do |index|
57
- pool.process do
58
- lock.synchronize { max = index if index > max }
59
- sleep(0.050)
60
- raise "bad" if index == 4
61
- end
62
- end
63
- end
64
- }.should raise_exception("bad")
65
-
66
- max.should be == 4
67
- end
68
-
69
- end