bosh-director 1.3178.0 → 1.3181.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 50418ce75a28cf747cafa90bd0233596b8d2fe1c
4
- data.tar.gz: c4866efc86924bd8295b6707f97ebcd41ee36331
3
+ metadata.gz: c97780b3dff8eed73c5d5be903e89db7379d5783
4
+ data.tar.gz: b44b5e4a56222f11ebbd158edd38a4ee12d931c8
5
5
  SHA512:
6
- metadata.gz: dabe39be4831b8f56640c70904dfc40b834d81e0fb8d28280654a411613a88402913385382a719b6f217d5938f1e6018313344669362f59e8add41a2104c6395
7
- data.tar.gz: 855d438e111d8bc3412ebf9b9a5a52741a623c26061886a38ba3d80f9e0279713e78355f04b9151f91eff409b95fe1b61b5ef1919746afbdc514c5e5b6f4488e
6
+ metadata.gz: 9906d59e3d0f2b08d4dad7c5bc3de47fb01dc528506a7b8d662cb0b0c4e6724dbb2c5a90871d893bef2f8cbbd8c560545c9b6149e69753b7510a4a6ee9b846d2
7
+ data.tar.gz: 6c32ef7e74cb561aec71c44bd28ddb66bb178bca559cf9c092417bc18bece0d008b62c3bb67f49bb523cb01efa34d345fb35be0fcced1e753cf48fc10d280c02
data/lib/bosh/director.rb CHANGED
@@ -92,6 +92,10 @@ require 'bosh/director/transactor'
92
92
  require 'bosh/director/sequel'
93
93
  require 'common/thread_pool'
94
94
 
95
+ require 'bosh/director/manifest/manifest'
96
+ require 'bosh/director/manifest/changeset'
97
+ require 'bosh/director/manifest/diff_lines'
98
+
95
99
  require 'bosh/director/log_bundles_cleaner'
96
100
  require 'bosh/director/logs_fetcher'
97
101
 
@@ -18,6 +18,10 @@ module Bosh
18
18
  list(1).first
19
19
  end
20
20
 
21
+ def find_by_id(id)
22
+ Bosh::Director::Models::CloudConfig.find(id: id)
23
+ end
24
+
21
25
  private
22
26
 
23
27
  def validate_manifest!(cloud_config)
@@ -205,7 +205,7 @@ module Bosh::Director
205
205
 
206
206
  post '/:deployment/properties', :consumes => [:json] do
207
207
  payload = json_decode(request.body)
208
- @property_manager.create_property(params[:deployment], payload['name'], payload['value'])
208
+ @property_manager.create_property(params[:deployment], payload['name'], payload['value'] )
209
209
  status(204)
210
210
  end
211
211
 
@@ -267,12 +267,44 @@ module Bosh::Director
267
267
  options = {}
268
268
  options['recreate'] = true if params['recreate'] == 'true'
269
269
  options['skip_drain'] = params['skip_drain'] if params['skip_drain']
270
- latest_cloud_config = Bosh::Director::Api::CloudConfigManager.new.latest
270
+ if params['context']
271
+ @logger.debug("Deploying with context #{params['context']}")
272
+ context = JSON.parse(params['context'])
273
+ cloud_config = Api::CloudConfigManager.new.find_by_id(context['cloud_config_id'])
274
+ else
275
+ cloud_config =Api::CloudConfigManager.new.latest
276
+ end
271
277
 
272
- task = @deployment_manager.create_deployment(current_user, request.body, latest_cloud_config, options)
278
+ task = @deployment_manager.create_deployment(current_user, request.body, cloud_config, options)
273
279
  redirect "/tasks/#{task.id}"
274
280
  end
275
281
 
282
+ post '/:deployment/diff', :consumes => :yaml do
283
+ deployment = Models::Deployment[name: params[:deployment]]
284
+ if deployment
285
+ before_manifest = Manifest.load_from_text(deployment.manifest, deployment.cloud_config)
286
+ before_manifest.resolve_aliases
287
+ else
288
+ before_manifest = Manifest.load_from_text(nil, nil)
289
+ end
290
+
291
+ after_cloud_config = Bosh::Director::Api::CloudConfigManager.new.latest
292
+ after_manifest = Manifest.load_from_text(
293
+ request.body,
294
+ after_cloud_config
295
+ )
296
+ after_manifest.resolve_aliases
297
+
298
+ diff = before_manifest.diff(after_manifest)
299
+
300
+ json_encode({
301
+ 'context' => {
302
+ 'cloud_config_id' => after_cloud_config ? after_cloud_config.id : nil,
303
+ },
304
+ 'diff' => diff.map { |l| [l.to_s, l.status] }
305
+ })
306
+ end
307
+
276
308
  post '/:deployment_name/errands/:errand_name/runs' do
277
309
  deployment_name = params[:deployment_name]
278
310
  errand_name = params[:errand_name]
@@ -5,23 +5,7 @@ module Bosh::Director
5
5
 
6
6
  def get_all_releases
7
7
  releases = Models::Release.order_by(:name.asc).map do |release|
8
- sorted_version_tuples = release.versions_dataset.all.map do |version|
9
- {
10
- provided: version,
11
- parsed: Bosh::Common::Version::ReleaseVersion.parse(version.values[:version])
12
- }
13
- end.sort_by { |rv| rv[:parsed] }
14
- release_versions = sorted_version_tuples.map do |version|
15
- provided = version[:provided]
16
- {
17
- 'version' => provided.version.to_s,
18
- 'commit_hash' => provided.commit_hash,
19
- 'uncommitted_changes' => provided.uncommitted_changes,
20
- 'currently_deployed' => !provided.deployments.empty?,
21
- 'job_names' => provided.templates.map(&:name),
22
- }
23
- end
24
-
8
+ release_versions = sorted_release_versions(release)
25
9
  {
26
10
  'name' => release.name,
27
11
  'release_versions' => release_versions
@@ -31,6 +15,27 @@ module Bosh::Director
31
15
  releases
32
16
  end
33
17
 
18
+ def sorted_release_versions(release)
19
+ sorted_version_tuples = release.versions_dataset.all.map do |version|
20
+ {
21
+ provided: version,
22
+ parsed: Bosh::Common::Version::ReleaseVersion.parse(version.values[:version])
23
+ }
24
+ end.sort_by { |rv| rv[:parsed] }
25
+ release_versions = sorted_version_tuples.map do |version|
26
+ provided = version[:provided]
27
+ {
28
+ 'version' => provided.version.to_s,
29
+ 'commit_hash' => provided.commit_hash,
30
+ 'uncommitted_changes' => provided.uncommitted_changes,
31
+ 'currently_deployed' => !provided.deployments.empty?,
32
+ 'job_names' => provided.templates.map(&:name),
33
+ }
34
+ end
35
+
36
+ release_versions
37
+ end
38
+
34
39
  def find_by_name(name)
35
40
  release = Models::Release[:name => name]
36
41
  if release.nil?
@@ -303,6 +303,25 @@ module Bosh::Director
303
303
  Thread.current[:bosh] ||= {}
304
304
  end
305
305
 
306
+ def generate_temp_dir
307
+ temp_dir = Dir.mktmpdir
308
+ ENV["TMPDIR"] = temp_dir
309
+ FileUtils.mkdir_p(temp_dir)
310
+ at_exit do
311
+ begin
312
+ if $!
313
+ status = $!.is_a?(::SystemExit) ? $!.status : 1
314
+ else
315
+ status = 0
316
+ end
317
+ FileUtils.rm_rf(temp_dir)
318
+ ensure
319
+ exit status
320
+ end
321
+ end
322
+ temp_dir
323
+ end
324
+
306
325
  def patch_sqlite
307
326
  return if @patched_sqlite
308
327
  @patched_sqlite = true
@@ -26,7 +26,12 @@ module Bosh::Director
26
26
  rescue => e
27
27
  unless instance.nil? || instance_plan.nil?
28
28
  @instance_reuser.remove_instance(instance)
29
- delete_instance(instance_plan)
29
+
30
+ if Config.keep_unreachable_vms
31
+ @logger.info('Keeping reused compilation VM for debugging')
32
+ else
33
+ delete_instance(instance_plan)
34
+ end
30
35
  end
31
36
  raise e
32
37
  end
@@ -34,11 +39,18 @@ module Bosh::Director
34
39
 
35
40
  def with_single_use_vm(stemcell)
36
41
  begin
42
+ keep_failing_vm = false
37
43
  instance_plan, instance = create_instance_plan(stemcell)
38
44
  configure_instance_plan(instance_plan)
39
45
  yield instance
46
+ rescue => e
47
+ @logger.info('Keeping single-use compilation VM for debugging')
48
+ keep_failing_vm = Config.keep_unreachable_vms
49
+ raise e
40
50
  ensure
41
- delete_instance(instance_plan) unless instance.nil?
51
+ unless instance.nil? || keep_failing_vm
52
+ delete_instance(instance_plan)
53
+ end
42
54
  end
43
55
  end
44
56
 
@@ -29,9 +29,9 @@ module Bosh::Director::DeploymentPlan
29
29
  end
30
30
 
31
31
  def allocate_dynamic_ip(reservation, subnet)
32
- item = (0...subnet.range.size).find { |i| available_for_dynamic?(subnet.range[i], subnet) }
33
-
34
32
  @mutex.synchronize do
33
+ item = (0...subnet.range.size).find { |i| available_for_dynamic?(subnet.range[i], subnet) }
34
+
35
35
  if item.nil?
36
36
  entry = @recently_released_ips.find do |entry|
37
37
  entry[:network_name] == subnet.network_name && subnet.range.contains?(entry[:ip])
@@ -72,11 +72,8 @@ module Bosh::Director::DeploymentPlan
72
72
  return false unless subnet.range.contains?(ip)
73
73
  return false if subnet.static_ips.include?(ip.to_i)
74
74
  return false if subnet.restricted_ips.include?(ip.to_i)
75
-
76
- @mutex.synchronize do
77
- return false if @recently_released_ips.include?({ip: ip.to_i, network_name: subnet.network_name})
78
- return false if @ips.include?({ip: ip.to_i, network_name: subnet.network_name})
79
- end
75
+ return false if @recently_released_ips.include?({ip: ip.to_i, network_name: subnet.network_name})
76
+ return false if @ips.include?({ip: ip.to_i, network_name: subnet.network_name})
80
77
 
81
78
  true
82
79
  end
@@ -33,21 +33,20 @@ module Bosh
33
33
  end
34
34
 
35
35
  def create_from_model(deployment_model, options={})
36
- manifest_hash = Psych.load(deployment_model.manifest)
37
- cloud_config_model = deployment_model.cloud_config
38
- create_from_manifest(manifest_hash, cloud_config_model, options)
36
+ manifest = Manifest.load_from_text(deployment_model.manifest, deployment_model.cloud_config)
37
+ create_from_manifest(manifest, deployment_model.cloud_config, options)
39
38
  end
40
39
 
41
- def create_from_manifest(manifest_hash, cloud_config, options)
42
- parse_from_manifest(manifest_hash, cloud_config, options)
40
+ def create_from_manifest(manifest, cloud_config, options)
41
+ parse_from_manifest(manifest, cloud_config, options)
43
42
  end
44
43
 
45
44
  private
46
45
 
47
- def parse_from_manifest(manifest_hash, cloud_config, options)
48
- cloud_config_hash = cloud_config.nil? ? nil : cloud_config.manifest
49
- @manifest_validator.validate(manifest_hash, cloud_config_hash)
50
- deployment_manifest, cloud_manifest = @deployment_manifest_migrator.migrate(manifest_hash, cloud_config_hash)
46
+ def parse_from_manifest(manifest, cloud_config, options)
47
+ manifest.resolve_aliases
48
+ @manifest_validator.validate(manifest.manifest_hash, manifest.cloud_config_hash)
49
+ deployment_manifest, cloud_manifest = @deployment_manifest_migrator.migrate(manifest.manifest_hash, manifest.cloud_config_hash)
51
50
  @logger.debug("Migrated deployment manifest:\n#{deployment_manifest}")
52
51
  @logger.debug("Migrated cloud config manifest:\n#{cloud_manifest}")
53
52
  name = deployment_manifest['name']
@@ -38,10 +38,6 @@ module Bosh::Director
38
38
  @model = nil
39
39
  end
40
40
 
41
- def is_using_latest_version?
42
- @version == 'latest'
43
- end
44
-
45
41
  def is_using_os?
46
42
  !@os.nil? && @name.nil?
47
43
  end
@@ -62,13 +58,9 @@ module Bosh::Director
62
58
  end
63
59
 
64
60
  def add_stemcell_model
65
- if is_using_latest_version?
66
- @model = is_using_os? ? @manager.latest_by_os(@os) : @manager.latest_by_name(@name)
67
- else
68
- @model = is_using_os? ?
69
- @manager.find_by_os_and_version(@os, @version) :
70
- @manager.find_by_name_and_version(@name, @version)
71
- end
61
+ @model = is_using_os? ?
62
+ @manager.find_by_os_and_version(@os, @version) :
63
+ @manager.find_by_name_and_version(@name, @version)
72
64
 
73
65
  @name = @model.name
74
66
  @os = @model.operating_system
@@ -23,18 +23,16 @@ module Bosh::Director
23
23
 
24
24
  def perform
25
25
  deployment_model = @deployment_manager.find_by_name(@deployment_name)
26
- deployment_manifest_hash = Psych.load(deployment_model.manifest)
27
- deployment_name = deployment_manifest_hash['name']
26
+ deployment_manifest = Manifest.load_from_text(deployment_model.manifest, deployment_model.cloud_config)
27
+ deployment_name = deployment_manifest.to_hash['name']
28
28
  with_deployment_lock(deployment_name) do
29
- cloud_config_model = deployment_model.cloud_config
30
-
31
29
  deployment = nil
32
30
  job = nil
33
31
 
34
32
  event_log.begin_stage('Preparing deployment', 1)
35
33
  event_log.track('Preparing deployment') do
36
34
  planner_factory = DeploymentPlan::PlannerFactory.create(logger)
37
- deployment = planner_factory.create_from_manifest(deployment_manifest_hash, cloud_config_model, {})
35
+ deployment = planner_factory.create_from_manifest(deployment_manifest, deployment_model.cloud_config, {})
38
36
  deployment.bind_models
39
37
  job = deployment.job(@errand_name)
40
38
 
@@ -21,8 +21,6 @@ module Bosh::Director
21
21
 
22
22
  manifest_text = File.read(@manifest_file_path)
23
23
  logger.debug("Manifest:\n#{manifest_text}")
24
- deployment_manifest_hash = Psych.load(manifest_text)
25
-
26
24
  cloud_config_model = Bosh::Director::Models::CloudConfig[@cloud_config_id]
27
25
  if cloud_config_model.nil?
28
26
  logger.debug("No cloud config uploaded yet.")
@@ -30,7 +28,8 @@ module Bosh::Director
30
28
  logger.debug("Cloud config:\n#{cloud_config_model.manifest}")
31
29
  end
32
30
 
33
- deployment_name = deployment_manifest_hash['name']
31
+ deployment_manifest = Manifest.load_from_text(manifest_text, cloud_config_model)
32
+ deployment_name = deployment_manifest.to_hash['name']
34
33
  with_deployment_lock(deployment_name) do
35
34
  @notifier = DeploymentPlan::Notifier.new(deployment_name, Config.nats_rpc, logger)
36
35
  @notifier.send_start_event
@@ -40,7 +39,7 @@ module Bosh::Director
40
39
  event_log.begin_stage('Preparing deployment', 1)
41
40
  event_log.track('Preparing deployment') do
42
41
  planner_factory = DeploymentPlan::PlannerFactory.create(logger)
43
- deployment_plan = planner_factory.create_from_manifest(deployment_manifest_hash, cloud_config_model, @options)
42
+ deployment_plan = planner_factory.create_from_manifest(deployment_manifest, cloud_config_model, @options)
44
43
  deployment_plan.bind_models
45
44
  end
46
45
 
@@ -0,0 +1,115 @@
1
+ class ::Hash
2
+ def deep_merge(second)
3
+ merger = proc { |key, v1, v2| Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : v2 }
4
+ self.merge(second, &merger)
5
+ end
6
+ end
7
+
8
+ module Bosh::Director
9
+ class Changeset
10
+ KEY_NAME = 'name'
11
+
12
+ def initialize(before, after)
13
+ @before = before
14
+ @after = after
15
+ if @before && @after
16
+ @merged = @before.deep_merge(@after)
17
+ elsif @before
18
+ @merged = @before
19
+ else
20
+ @merged = @after
21
+ end
22
+ end
23
+
24
+ def diff(indent = 0)
25
+ lines = DiffLines.new
26
+
27
+ @merged.each_pair do |key, value|
28
+ if @before.nil? || @before[key].nil?
29
+ lines.concat(yaml_lines({key => value}, indent, 'added'))
30
+
31
+ elsif @after.nil? || @after[key].nil?
32
+ lines.concat(yaml_lines({key => value}, indent, 'removed'))
33
+
34
+ elsif @before[key].is_a?(Array) && @after[key].is_a?(Array)
35
+ lines.concat(compare_arrays(@before[key], @after[key], key, indent))
36
+
37
+ elsif value.is_a?(Hash)
38
+ changeset = Changeset.new(@before[key], @after[key])
39
+ diff_lines = changeset.diff(indent+1)
40
+ unless diff_lines.empty?
41
+ lines << Line.new(indent, "#{key}:", nil)
42
+ lines.concat(diff_lines)
43
+ end
44
+
45
+ elsif @before[key] != @after[key]
46
+ lines << Line.new(indent, "#{key}: #{@before[key]}", 'removed')
47
+ lines << Line.new(indent, "#{key}: #{@after[key]}", 'added')
48
+ end
49
+ end
50
+ lines
51
+ end
52
+
53
+ def yaml_lines(value, indent, state)
54
+ lines = DiffLines.new
55
+ value.to_yaml(indent: Line::INDENT).gsub("---\n", '').split("\n").each do |line|
56
+ lines << Line.new(indent, line, state)
57
+ end
58
+ lines
59
+ end
60
+
61
+ def compare_arrays(old_value, new_value, parent_name, indent)
62
+ added = new_value - old_value
63
+ removed = old_value - new_value
64
+
65
+ lines = DiffLines.new
66
+
67
+ added.each do |elem|
68
+ if elem.is_a?(Hash)
69
+ using_names = (added+removed).all? { |e| e['name'] }
70
+ using_ranges = (added+removed).all? { |e| e['range'] }
71
+ if using_names || using_ranges
72
+ if using_names
73
+ removed_same_name_element = removed.find { |e| e['name'] == elem['name'] }
74
+ elsif using_ranges
75
+ removed_same_name_element = removed.find { |e| e['range'] == elem['range'] }
76
+ end
77
+ removed.delete(removed_same_name_element)
78
+
79
+ if removed_same_name_element
80
+ changeset = Changeset.new(removed_same_name_element, elem)
81
+ diff_lines = changeset.diff(indent+1)
82
+
83
+ unless diff_lines.empty?
84
+ # write name if elem has been changed
85
+ if using_names
86
+ lines.concat(yaml_lines([{'name' => elem['name']}], indent, nil))
87
+ elsif using_ranges
88
+ lines.concat(yaml_lines([{'range' => elem['range']}], indent, nil))
89
+ end
90
+ lines.concat(diff_lines)
91
+ end
92
+ else
93
+ lines.concat(yaml_lines([elem], indent, 'added'))
94
+ end
95
+
96
+ else
97
+ lines.concat(yaml_lines([elem], indent, 'added'))
98
+ end
99
+ else
100
+ lines.concat(yaml_lines([elem], indent, 'added'))
101
+ end
102
+ end
103
+
104
+ unless removed.empty?
105
+ lines.concat(yaml_lines(removed, indent, 'removed'))
106
+ end
107
+
108
+ unless lines.empty?
109
+ lines.unshift(Line.new(indent, "#{parent_name}:", nil))
110
+ end
111
+
112
+ lines
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,83 @@
1
+ module Bosh::Director
2
+ class Line < Struct.new(:indent, :text, :status)
3
+ INDENT = 2
4
+
5
+ def to_s
6
+ "#{' ' * INDENT * indent}#{text}"
7
+ end
8
+
9
+ def full_indent
10
+ indent + text[/^ */].size / INDENT
11
+ end
12
+ end
13
+
14
+ class DiffLines < Array
15
+ MANIFEST_KEYS_ORDER = %w(
16
+ azs
17
+ vm_types
18
+ resource_pools
19
+ compilation
20
+ networks
21
+ disk_types
22
+ disk_pools
23
+ name
24
+ director_uuid
25
+ stemcells
26
+ releases
27
+ update
28
+ jobs
29
+ )
30
+
31
+ def order
32
+ sections = {}
33
+ key = nil
34
+
35
+ self.each do |line|
36
+ if line.indent == 0 && line.text !~ /^[ -]/
37
+ key = line.text
38
+ sections[key] = []
39
+ end
40
+
41
+ sections[key] << line
42
+ end
43
+
44
+ ordered_lines = []
45
+ MANIFEST_KEYS_ORDER.each do |manifest_key|
46
+ section_name = manifest_key + ':'
47
+ lines = sections[section_name]
48
+ ordered_lines += lines.to_a
49
+ sections.delete(section_name)
50
+ end
51
+
52
+ sections.each do |_, section_lines|
53
+ section_lines.each do |line|
54
+ ordered_lines << line
55
+ end
56
+ end
57
+
58
+ self.replace(ordered_lines)
59
+ end
60
+
61
+ def redact_properties
62
+ i = 0
63
+ while i < self.size
64
+ line = self[i]
65
+
66
+ if line.text =~ /\bproperties:/
67
+ properties_indent = line.full_indent
68
+ i += 1
69
+ line = self[i]
70
+
71
+ while line && line.full_indent > properties_indent
72
+ line.text.gsub!(/: .+/, ': <redacted>') # readact hash values
73
+ line.text.gsub!(/- [^:]+$/, '- <redacted>') # redact array values
74
+ i += 1
75
+ line = self[i]
76
+ end
77
+ end
78
+ i += 1
79
+ end
80
+ self
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,72 @@
1
+ module Bosh::Director
2
+ class Manifest
3
+ def self.load_from_text(manifest_text, cloud_config)
4
+ cloud_config_hash = cloud_config.nil? ? nil : cloud_config.manifest
5
+ manifest_hash = manifest_text.nil? ? {} : Psych.load(manifest_text)
6
+ new(manifest_hash, cloud_config_hash)
7
+ end
8
+
9
+ attr_reader :manifest_hash, :cloud_config_hash
10
+
11
+ def initialize(manifest_hash, cloud_config_hash)
12
+ @manifest_hash = manifest_hash
13
+ @cloud_config_hash = cloud_config_hash
14
+ end
15
+
16
+ def resolve_aliases
17
+ hashed = to_hash
18
+ hashed['resource_pools'].to_a.each do |rp|
19
+ rp['stemcell']['version'] = resolve_stemcell_version(rp['stemcell'])
20
+ end
21
+
22
+ hashed['stemcells'].to_a.each do |stemcell|
23
+ stemcell['version'] = resolve_stemcell_version(stemcell)
24
+ end
25
+
26
+ hashed['releases'].to_a.each do |release|
27
+ release['version'] = resolve_release_version(release)
28
+ end
29
+ end
30
+
31
+ def diff(other_manifest)
32
+ Changeset.new(to_hash, other_manifest.to_hash).diff.order.redact_properties
33
+ end
34
+
35
+ def to_hash
36
+ @manifest_hash.merge(@cloud_config_hash || {})
37
+ end
38
+
39
+ private
40
+
41
+ def resolve_stemcell_version(stemcell)
42
+ stemcell_manager = Api::StemcellManager.new
43
+
44
+ unless stemcell.is_a?(Hash)
45
+ raise 'Invalid stemcell spec in the deployment manifest'
46
+ end
47
+
48
+ if stemcell['version'] == 'latest'
49
+ if stemcell['os']
50
+ latest_stemcell = stemcell_manager.latest_by_os(stemcell['os'])
51
+ elsif stemcell['name']
52
+ latest_stemcell = stemcell_manager.latest_by_name(stemcell['name'])
53
+ else
54
+ raise 'Stemcell definition must contain either name or os'
55
+ end
56
+ return latest_stemcell[:version].to_s
57
+ end
58
+
59
+ stemcell['version'].to_s
60
+ end
61
+
62
+ def resolve_release_version(release_def)
63
+ release_manager = Api::ReleaseManager.new
64
+ if release_def['version'] == 'latest'
65
+ release = release_manager.find_by_name(release_def['name'])
66
+ return release_manager.sorted_release_versions(release).last['version']
67
+ end
68
+
69
+ release_def['version'].to_s
70
+ end
71
+ end
72
+ end
@@ -1,5 +1,5 @@
1
1
  module Bosh
2
2
  module Director
3
- VERSION = '1.3178.0'
3
+ VERSION = '1.3181.0'
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bosh-director
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3178.0
4
+ version: 1.3181.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - VMware
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-01-15 00:00:00.000000000 Z
11
+ date: 2016-01-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bosh_common
@@ -16,98 +16,98 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 1.3178.0
19
+ version: 1.3181.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 1.3178.0
26
+ version: 1.3181.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bosh_cpi
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 1.3178.0
33
+ version: 1.3181.0
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 1.3178.0
40
+ version: 1.3181.0
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: bosh-registry
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: 1.3178.0
47
+ version: 1.3181.0
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: 1.3178.0
54
+ version: 1.3181.0
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: blobstore_client
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: 1.3178.0
61
+ version: 1.3181.0
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: 1.3178.0
68
+ version: 1.3181.0
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: bosh-core
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: 1.3178.0
75
+ version: 1.3181.0
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: 1.3178.0
82
+ version: 1.3181.0
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: bosh-director-core
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: 1.3178.0
89
+ version: 1.3181.0
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: 1.3178.0
96
+ version: 1.3181.0
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: bosh-template
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: 1.3178.0
103
+ version: 1.3181.0
104
104
  type: :runtime
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
- version: 1.3178.0
110
+ version: 1.3181.0
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: bosh_openstack_cpi
113
113
  requirement: !ruby/object:Gem::Requirement
@@ -874,6 +874,9 @@ files:
874
874
  - lib/bosh/director/lock_helper.rb
875
875
  - lib/bosh/director/log_bundles_cleaner.rb
876
876
  - lib/bosh/director/logs_fetcher.rb
877
+ - lib/bosh/director/manifest/changeset.rb
878
+ - lib/bosh/director/manifest/diff_lines.rb
879
+ - lib/bosh/director/manifest/manifest.rb
877
880
  - lib/bosh/director/models.rb
878
881
  - lib/bosh/director/models/cloud_config.rb
879
882
  - lib/bosh/director/models/compiled_package.rb