bosh-director 1.3215.4.0 → 1.3232.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (147) hide show
  1. checksums.yaml +4 -4
  2. data/bin/bosh-director-console +1 -1
  3. data/bin/bosh-director-drain-workers +8 -2
  4. data/bin/bosh-director-worker +34 -53
  5. data/db/migrations/director/20110617211923_add_deployments_release_versions.rb +2 -2
  6. data/db/migrations/director/20120524175805_add_task_type.rb +23 -23
  7. data/db/migrations/director/20130531172604_add_director_attributes.rb +1 -2
  8. data/db/migrations/director/20140116002324_pivot_director_attributes.rb +1 -2
  9. data/db/migrations/director/20160210201838_denormalize_compiled_package_stemcell_id_to_stemcell_name_and_version.rb +7 -9
  10. data/db/migrations/director/20160211174110_add_events.rb +22 -0
  11. data/db/migrations/director/20160324181932_create_delayed_jobs.rb +22 -0
  12. data/db/migrations/director/20160324182211_add_locks.rb +15 -0
  13. data/db/migrations/director/20160329201256_set_instances_with_nil_serial_to_false.rb +15 -0
  14. data/db/migrations/director/20160331225404_backfill_stemcell_os.rb +9 -0
  15. data/db/migrations/director/20160411104407_add_task_started_at.rb +9 -0
  16. data/lib/bosh/director.rb +9 -2
  17. data/lib/bosh/director/agent_client.rb +22 -9
  18. data/lib/bosh/director/api.rb +0 -1
  19. data/lib/bosh/director/api/api_helper.rb +1 -1
  20. data/lib/bosh/director/api/controllers/base_controller.rb +5 -1
  21. data/lib/bosh/director/api/controllers/cloud_configs_controller.rb +18 -2
  22. data/lib/bosh/director/api/controllers/deployments_controller.rb +16 -9
  23. data/lib/bosh/director/api/controllers/events_controller.rb +37 -0
  24. data/lib/bosh/director/api/controllers/locks_controller.rb +7 -11
  25. data/lib/bosh/director/api/controllers/packages_controller.rb +1 -1
  26. data/lib/bosh/director/api/controllers/runtime_configs_controller.rb +18 -2
  27. data/lib/bosh/director/api/controllers/tasks_controller.rb +7 -2
  28. data/lib/bosh/director/api/deployment_lookup.rb +1 -1
  29. data/lib/bosh/director/api/deployment_manager.rb +1 -1
  30. data/lib/bosh/director/api/event_manager.rb +68 -0
  31. data/lib/bosh/director/api/extensions/scoping.rb +2 -2
  32. data/lib/bosh/director/api/extensions/syslog_request_logger.rb +75 -0
  33. data/lib/bosh/director/api/instance_lookup.rb +2 -2
  34. data/lib/bosh/director/api/instance_manager.rb +2 -2
  35. data/lib/bosh/director/api/local_identity_provider.rb +8 -0
  36. data/lib/bosh/director/api/property_manager.rb +6 -5
  37. data/lib/bosh/director/api/release_manager.rb +3 -3
  38. data/lib/bosh/director/api/resource_manager.rb +2 -2
  39. data/lib/bosh/director/api/resurrector_manager.rb +1 -1
  40. data/lib/bosh/director/api/route_configuration.rb +1 -0
  41. data/lib/bosh/director/api/stemcell_manager.rb +5 -5
  42. data/lib/bosh/director/api/task_manager.rb +1 -0
  43. data/lib/bosh/director/api/task_remover.rb +1 -1
  44. data/lib/bosh/director/api/uaa_identity_provider.rb +9 -1
  45. data/lib/bosh/director/api/user/database_user_manager.rb +1 -1
  46. data/lib/bosh/director/app.rb +1 -1
  47. data/lib/bosh/director/arp_flusher.rb +23 -0
  48. data/lib/bosh/director/cloudcheck_helper.rb +4 -3
  49. data/lib/bosh/director/compile_task.rb +6 -6
  50. data/lib/bosh/director/compile_task_generator.rb +6 -6
  51. data/lib/bosh/director/compiled_release_downloader.rb +4 -4
  52. data/lib/bosh/director/config.rb +29 -87
  53. data/lib/bosh/director/deployment_deleter.rb +6 -6
  54. data/lib/bosh/director/deployment_plan/agent_state_migrator.rb +2 -2
  55. data/lib/bosh/director/deployment_plan/assembler.rb +1 -1
  56. data/lib/bosh/director/deployment_plan/compilation_instance_pool.rb +26 -1
  57. data/lib/bosh/director/deployment_plan/deployment_repo.rb +1 -1
  58. data/lib/bosh/director/deployment_plan/disk_type.rb +1 -1
  59. data/lib/bosh/director/deployment_plan/instance.rb +2 -2
  60. data/lib/bosh/director/deployment_plan/instance_plan.rb +2 -2
  61. data/lib/bosh/director/deployment_plan/instance_spec.rb +2 -0
  62. data/lib/bosh/director/deployment_plan/ip_provider/ip_provider.rb +7 -3
  63. data/lib/bosh/director/deployment_plan/job.rb +12 -10
  64. data/lib/bosh/director/deployment_plan/job_spec_parser.rb +4 -4
  65. data/lib/bosh/director/deployment_plan/links/link.rb +1 -0
  66. data/lib/bosh/director/deployment_plan/links/link_path.rb +18 -19
  67. data/lib/bosh/director/deployment_plan/links/links_resolver.rb +2 -0
  68. data/lib/bosh/director/deployment_plan/links/template_link.rb +1 -1
  69. data/lib/bosh/director/deployment_plan/manual_network.rb +1 -1
  70. data/lib/bosh/director/deployment_plan/manual_network_subnet.rb +6 -6
  71. data/lib/bosh/director/deployment_plan/planner.rb +3 -3
  72. data/lib/bosh/director/deployment_plan/planner_factory.rb +38 -40
  73. data/lib/bosh/director/deployment_plan/release_version.rb +5 -5
  74. data/lib/bosh/director/deployment_plan/runtime_manifest_parser.rb +22 -18
  75. data/lib/bosh/director/deployment_plan/steps/package_compile_step.rb +14 -16
  76. data/lib/bosh/director/deployment_plan/steps/update_step.rb +5 -5
  77. data/lib/bosh/director/deployment_plan/template.rb +61 -1
  78. data/lib/bosh/director/deployment_plan/update_config.rb +1 -1
  79. data/lib/bosh/director/disk_manager.rb +49 -40
  80. data/lib/bosh/director/dns/canonicalizer.rb +2 -2
  81. data/lib/bosh/director/dns/dns_manager.rb +2 -2
  82. data/lib/bosh/director/dns/powerdns.rb +2 -2
  83. data/lib/bosh/director/download_helper.rb +5 -5
  84. data/lib/bosh/director/errand/job_manager.rb +5 -6
  85. data/lib/bosh/director/errand/result.rb +1 -1
  86. data/lib/bosh/director/errand/runner.rb +2 -3
  87. data/lib/bosh/director/event_log.rb +1 -7
  88. data/lib/bosh/director/ext.rb +0 -6
  89. data/lib/bosh/director/instance_deleter.rb +23 -2
  90. data/lib/bosh/director/instance_updater.rb +62 -6
  91. data/lib/bosh/director/instance_updater/state_applier.rb +2 -2
  92. data/lib/bosh/director/job_queue.rb +4 -2
  93. data/lib/bosh/director/job_runner.rb +3 -8
  94. data/lib/bosh/director/jobs/backup.rb +1 -1
  95. data/lib/bosh/director/jobs/base_job.rb +10 -6
  96. data/lib/bosh/director/jobs/cleanup_artifacts.rb +6 -6
  97. data/lib/bosh/director/jobs/db_job.rb +87 -0
  98. data/lib/bosh/director/jobs/delete_deployment.rb +23 -2
  99. data/lib/bosh/director/jobs/delete_deployment_snapshots.rb +1 -1
  100. data/lib/bosh/director/jobs/delete_orphan_disks.rb +2 -2
  101. data/lib/bosh/director/jobs/delete_release.rb +2 -2
  102. data/lib/bosh/director/jobs/delete_stemcell.rb +1 -1
  103. data/lib/bosh/director/jobs/export_release.rb +4 -2
  104. data/lib/bosh/director/jobs/fetch_logs.rb +1 -1
  105. data/lib/bosh/director/jobs/helpers/blob_deleter.rb +1 -1
  106. data/lib/bosh/director/jobs/helpers/name_version_release_deleter.rb +3 -3
  107. data/lib/bosh/director/jobs/helpers/release_version_deleter.rb +1 -1
  108. data/lib/bosh/director/jobs/helpers/stemcell_deleter.rb +2 -12
  109. data/lib/bosh/director/jobs/release/release_job.rb +13 -28
  110. data/lib/bosh/director/jobs/run_errand.rb +6 -6
  111. data/lib/bosh/director/jobs/scheduled_backup.rb +1 -1
  112. data/lib/bosh/director/jobs/scheduled_events_cleanup.rb +31 -0
  113. data/lib/bosh/director/jobs/scheduled_orphan_cleanup.rb +1 -1
  114. data/lib/bosh/director/jobs/snapshot_deployment.rb +4 -1
  115. data/lib/bosh/director/jobs/ssh.rb +36 -14
  116. data/lib/bosh/director/jobs/update_deployment.rb +28 -6
  117. data/lib/bosh/director/jobs/update_release.rb +31 -41
  118. data/lib/bosh/director/jobs/update_stemcell.rb +4 -4
  119. data/lib/bosh/director/jobs/vm_state.rb +1 -2
  120. data/lib/bosh/director/lock.rb +30 -55
  121. data/lib/bosh/director/logs_fetcher.rb +2 -3
  122. data/lib/bosh/director/manifest/changeset.rb +88 -42
  123. data/lib/bosh/director/manifest/manifest.rb +1 -1
  124. data/lib/bosh/director/models.rb +3 -0
  125. data/lib/bosh/director/models/event.rb +18 -0
  126. data/lib/bosh/director/models/lock.rb +9 -0
  127. data/lib/bosh/director/models/release_version.rb +3 -1
  128. data/lib/bosh/director/problem_handlers/base.rb +3 -3
  129. data/lib/bosh/director/problem_handlers/inactive_disk.rb +4 -4
  130. data/lib/bosh/director/problem_handlers/missing_disk.rb +3 -3
  131. data/lib/bosh/director/problem_handlers/missing_vm.rb +1 -1
  132. data/lib/bosh/director/problem_handlers/mount_info_mismatch.rb +3 -3
  133. data/lib/bosh/director/problem_handlers/unresponsive_agent.rb +2 -2
  134. data/lib/bosh/director/problem_resolver.rb +5 -5
  135. data/lib/bosh/director/problem_scanner/problem_register.rb +1 -1
  136. data/lib/bosh/director/problem_scanner/scanner.rb +3 -2
  137. data/lib/bosh/director/scheduler.rb +3 -3
  138. data/lib/bosh/director/sequel.rb +1 -3
  139. data/lib/bosh/director/stopper.rb +1 -1
  140. data/lib/bosh/director/validation_helper.rb +60 -37
  141. data/lib/bosh/director/version.rb +1 -1
  142. data/lib/bosh/director/vm_creator.rb +39 -7
  143. data/lib/bosh/director/vm_deleter.rb +29 -2
  144. data/lib/bosh/director/vm_metadata_updater.rb +4 -0
  145. data/lib/bosh/director/worker.rb +52 -0
  146. metadata +47 -61
  147. data/lib/bosh/director/manifest/redactor.rb +0 -44
@@ -38,7 +38,7 @@ module Bosh::Director
38
38
  def perform
39
39
  logger.info("Processing update stemcell")
40
40
 
41
- event_log.begin_stage("Update stemcell", @stemcell_url ? UPDATE_STEPS + 1 : UPDATE_STEPS)
41
+ begin_stage("Update stemcell", @stemcell_url ? UPDATE_STEPS + 1 : UPDATE_STEPS)
42
42
 
43
43
  track_and_log("Downloading remote stemcell") { download_remote_stemcell } if @stemcell_url
44
44
 
@@ -66,7 +66,7 @@ module Bosh::Director
66
66
  @cloud_properties = safe_property(stemcell_manifest, "cloud_properties", :class => Hash, :optional => true)
67
67
  @sha1 = safe_property(stemcell_manifest, "sha1", :class => String)
68
68
 
69
- logger.info("Found stemcell image `#{@name}/#{@version}', " +
69
+ logger.info("Found stemcell image '#{@name}/#{@version}', " +
70
70
  "cloud properties are #{@cloud_properties.inspect}")
71
71
 
72
72
  logger.info("Verifying stemcell image")
@@ -80,7 +80,7 @@ module Bosh::Director
80
80
  track_and_log("Checking if this stemcell already exists") do
81
81
  begin
82
82
  stemcell = @stemcell_manager.find_by_name_and_version @name, @version
83
- raise StemcellAlreadyExists, "Stemcell `#{@name}/#{@version}' already exists" unless @fix
83
+ raise StemcellAlreadyExists, "Stemcell '#{@name}/#{@version}' already exists" unless @fix
84
84
  rescue StemcellNotFound => e
85
85
  stemcell = Models::Stemcell.new
86
86
  stemcell.name = @name
@@ -110,7 +110,7 @@ module Bosh::Director
110
110
  def verify_sha1
111
111
  stemcell_hash = Digest::SHA1.file(@stemcell_path).hexdigest
112
112
  if stemcell_hash != @stemcell_sha1
113
- raise StemcellSha1DoesNotMatch, "Stemcell SHA1 `#{stemcell_hash}' does not match the expected SHA1 `#{@stemcell_sha1}'"
113
+ raise StemcellSha1DoesNotMatch, "Stemcell SHA1 '#{stemcell_hash}' does not match the expected SHA1 '#{@stemcell_sha1}'"
114
114
  end
115
115
  end
116
116
 
@@ -52,6 +52,7 @@ module Bosh::Director
52
52
  :job_name => instance.job,
53
53
  :index => instance.index,
54
54
  :job_state => job_state,
55
+ :state => instance.state,
55
56
  :resource_pool => vm_type_name,
56
57
  :vm_type => vm_type_name,
57
58
  :vitals => job_vitals,
@@ -87,8 +88,6 @@ module Bosh::Director
87
88
  rescue Bosh::Director::RpcTimeout
88
89
  job_state = 'unresponsive agent'
89
90
  end
90
- else
91
- job_state = 'missing vm'
92
91
  end
93
92
 
94
93
  return job_state, job_vitals, processes, ips
@@ -1,6 +1,6 @@
1
1
  module Bosh::Director
2
2
 
3
- # Distributed lock backed by Redis.
3
+ # Distributed lock backed by DB.
4
4
  class Lock
5
5
 
6
6
  # Error returned when Lock could not be acquired.
@@ -14,7 +14,7 @@ module Bosh::Director
14
14
  # lock
15
15
  def initialize(name, opts = {})
16
16
  @name = name
17
- @id = SecureRandom.uuid
17
+ @uid = SecureRandom.uuid
18
18
  @timeout = opts[:timeout] || 1.0
19
19
  @expiration = opts[:expiration] || 10.0
20
20
  @logger = Config.logger
@@ -30,24 +30,21 @@ module Bosh::Director
30
30
  acquire
31
31
 
32
32
  @refresh_thread = Thread.new do
33
- redis = Config.redis
34
33
  sleep_interval = [1.0, @expiration/2].max
35
34
  begin
36
- loop do
37
- @logger.debug("Renewing lock: #@name, id: #@id")
38
- redis.watch(@name)
39
- existing_lock = redis.get(@name)
40
- lock_id = existing_lock.split(":")[1]
41
- break if lock_id != @id
35
+ stopped = false
36
+ until stopped
37
+ @logger.debug("Renewing lock: #@name")
42
38
  lock_expiration = Time.now.to_f + @expiration + 1
43
- redis.multi do
44
- redis.set(@name, "#{lock_expiration}:#@id")
39
+
40
+ if Models::Lock.where(name: @name, uid: @uid).update(expired_at: Time.at(lock_expiration)) == 0
41
+ stopped = true
45
42
  end
46
- sleep(sleep_interval)
43
+
44
+ sleep(sleep_interval) unless stopped
47
45
  end
48
46
  ensure
49
47
  @logger.debug("Lock renewal thread exiting")
50
- redis.quit
51
48
  end
52
49
  end
53
50
 
@@ -72,65 +69,43 @@ module Bosh::Director
72
69
 
73
70
  def acquire
74
71
  @logger.debug("Acquiring lock: #@name")
75
- redis = Config.redis
76
72
  started = Time.now
77
73
 
78
74
  lock_expiration = Time.now.to_f + @expiration + 1
79
- until redis.setnx(@name, "#{lock_expiration}:#@id")
80
- existing_lock = redis.get(@name)
81
- @logger.debug("Lock #@name is already locked by someone " +
82
- "else: #{existing_lock}")
83
- if lock_expired?(existing_lock)
84
- @logger.debug("Lock #@name is already expired, " +
85
- "trying to take it back, id: #@id")
86
- replaced_lock = redis.getset(@name, "#{lock_expiration}:#@id")
87
- if replaced_lock == existing_lock
88
- @logger.debug("Lock #@name was revoked and relocked")
89
- break
90
- else
91
- @logger.debug("Lock #@name was acquired by someone else, " +
92
- "trying again")
75
+ acquired = false
76
+ until acquired
77
+ begin
78
+ Models::Lock.create(name: @name, uid: @uid, expired_at: Time.at(lock_expiration))
79
+ acquired = true
80
+ rescue Sequel::DatabaseError
81
+ affected_locks = Models::Lock.where(name: @name).where{ expired_at < Time.now }.update(uid: @uid, expired_at: Time.at(lock_expiration))
82
+ if affected_locks == 1
83
+ acquired = true
93
84
  end
94
85
  end
95
86
 
96
- raise TimeoutError, "Redis lock #{@name} is acquired by another thread" if Time.now - started > @timeout
97
-
98
- sleep(0.5)
99
-
100
- lock_expiration = Time.now.to_f + @expiration + 1
87
+ unless acquired
88
+ raise TimeoutError, "Failed to acquire lock for #{@name} uid: #{@uid}" if Time.now - started > @timeout
89
+ sleep(0.5)
90
+ lock_expiration = Time.now.to_f + @expiration + 1
91
+ end
101
92
  end
102
93
 
103
94
  @lock_expiration = lock_expiration
104
95
  @logger.debug("Acquired lock: #@name")
105
96
  end
106
97
 
98
+
107
99
  def delete
108
- @logger.debug("Deleting lock: #@name")
109
- redis = Config.redis
110
-
111
- redis.watch(@name)
112
- existing_lock = redis.get(@name)
113
- if existing_lock.nil?
114
- @logger.debug("Lost lock #@name")
115
- redis.unwatch
100
+ if Models::Lock.where(name: @name, uid: @uid).delete > 0
101
+ @logger.debug("Deleted lock: #{@name} uid: #{@uid}")
116
102
  else
117
- lock_id = existing_lock.split(":")[1]
118
- if lock_id == @id
119
- redis.multi do
120
- redis.del(@name)
121
- end
122
- else
123
- redis.unwatch
124
- end
125
- @logger.debug("Deleted lock: #@name")
103
+ @logger.debug("Can not find lock: #{@name} - uid: #{@uid}")
126
104
  end
127
105
  end
128
106
 
129
- def lock_expired?(lock)
130
- existing_lock_expiration = lock.split(":")[0].to_f
131
- lock_time_left = existing_lock_expiration - Time.now.to_f
132
- @logger.info("Lock: #{lock} expires in #{lock_time_left} seconds")
133
- lock_time_left < 0
107
+ def lock_expired?(lock_record)
108
+ lock_record.expired_at < Time.now
134
109
  end
135
110
  end
136
111
  end
@@ -3,8 +3,7 @@ module Bosh::Director
3
3
  # @param [Bosh::Director::EventLog::Log] event_log
4
4
  # @param [Bosh::Director::Api::InstanceManager] instance_manager
5
5
  # @param [Bosh::Director::LogBundlesCleaner] log_bundles_cleaner
6
- def initialize(event_log, instance_manager, log_bundles_cleaner, logger)
7
- @event_log = event_log
6
+ def initialize(instance_manager, log_bundles_cleaner, logger)
8
7
  @instance_manager = instance_manager
9
8
  @log_bundles_cleaner = log_bundles_cleaner
10
9
  @logger = logger
@@ -21,7 +20,7 @@ module Bosh::Director
21
20
  agent = @instance_manager.agent_client_for(instance)
22
21
  blobstore_id = nil
23
22
 
24
- stage = @event_log.begin_stage("Fetching logs for #{instance.job}/#{instance.uuid} (#{instance.index})", 1)
23
+ stage = Config.event_log.begin_stage("Fetching logs for #{instance.job}/#{instance.uuid} (#{instance.index})", 1)
25
24
  stage.advance_and_track('Finding and packing log files') do
26
25
  fetch_logs_result = agent.fetch_logs(log_type, filters)
27
26
  blobstore_id = fetch_logs_result['blobstore_id']
@@ -1,24 +1,21 @@
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
1
  module Bosh::Director
9
2
  class Changeset
10
3
  KEY_NAME = 'name'
11
4
 
12
- def initialize(before, after, redact = true, redacted_before = nil, redacted_after = nil)
13
- @redact = redact
14
- @redacted_before = redacted_before.nil? ? Redactor.redact_properties(Bosh::Common::DeepCopy.copy(before), redact) : redacted_before
15
- @redacted_after = redacted_after.nil? ? Redactor.redact_properties(Bosh::Common::DeepCopy.copy(after), redact) : redacted_after
5
+ REDACT_KEY_NAMES = %w(
6
+ properties
7
+ bosh
8
+ )
9
+
10
+ def initialize(before, after, redacted_before = nil, redacted_after = nil)
11
+ @redacted_before = redacted_before.nil? ? Changeset.redact_properties!(Bosh::Common::DeepCopy.copy(before)) : redacted_before
12
+ @redacted_after = redacted_after.nil? ? Changeset.redact_properties!(Bosh::Common::DeepCopy.copy(after)) : redacted_after
16
13
 
17
14
  @before = before
18
15
  @after = after
19
16
 
20
17
  if @before && @after
21
- @merged = @before.deep_merge(@after)
18
+ @merged = deep_merge(@before, @after)
22
19
  elsif @before
23
20
  @merged = @before
24
21
  else
@@ -26,64 +23,113 @@ module Bosh::Director
26
23
  end
27
24
  end
28
25
 
29
- def diff(indent = 0)
30
- lines = DiffLines.new
26
+ # redacts properties from ruby object to avoid having to use a regex to redact properties from diff output
27
+ # please do not use regexes for diffing/redacting
28
+ def self.redact_properties!(obj, redact_key_is_ancestor = false)
29
+ if redact_key_is_ancestor
30
+ if obj.respond_to?(:key?)
31
+ obj.keys.each{ |key|
32
+ if obj[key].respond_to?(:each)
33
+ redact_properties!(obj[key], true)
34
+ else
35
+ obj[key] = '<redacted>'
36
+ end
37
+ }
38
+ elsif obj.respond_to?(:each_index)
39
+ obj.each_index { |i|
40
+ if obj[i].respond_to?(:each)
41
+ redact_properties!(obj[i], true)
42
+ else
43
+ obj[i] = '<redacted>'
44
+ end
45
+ }
46
+ end
47
+ else
48
+ if obj.respond_to?(:each)
49
+ obj.each{ |a|
50
+ if obj.respond_to?(:key?) && REDACT_KEY_NAMES.any? { |key| key == a.first } && a.last.respond_to?(:key?)
51
+ redact_properties!(a.last, true)
52
+ else
53
+ redact_properties!(a.respond_to?(:last) ? a.last : a)
54
+ end
31
55
 
32
- @merged.each_pair do |key, value|
33
- if @before.nil? || @before[key].nil?
34
- lines.concat(yaml_lines({key => @redacted_after[key]}, indent, 'added'))
56
+ }
57
+ end
58
+ end
35
59
 
36
- elsif @after.nil? || @after[key].nil?
37
- lines.concat(yaml_lines({key => @redacted_before[key]}, indent, 'removed'))
60
+ obj
61
+ end
38
62
 
39
- elsif @before[key].is_a?(Array) && @after[key].is_a?(Array)
40
- lines.concat(compare_arrays(@before[key], @after[key], @redacted_before[key], @redacted_after[key], key, indent))
63
+ def diff(redact=true, indent = 0)
64
+ lines = DiffLines.new
41
65
 
42
- elsif value.is_a?(Hash)
43
- changeset = Changeset.new(@before[key], @after[key],@redact, @redacted_before[key], @redacted_after[key])
44
- diff_lines = changeset.diff(indent+1)
45
- unless diff_lines.empty?
46
- lines << Line.new(indent, "#{key}:", nil)
47
- lines.concat(diff_lines)
48
- end
66
+ if redact
67
+ output_values_before = @redacted_before
68
+ output_values_after = @redacted_after
69
+ else
70
+ output_values_before = @before
71
+ output_values_after = @after
72
+ end
49
73
 
50
- elsif @before[key] != @after[key]
51
- lines.concat(yaml_lines({key => @redacted_before[key]}, indent, 'removed'))
52
- lines.concat(yaml_lines({key => @redacted_after[key]}, indent, 'added'))
74
+ @merged.each_pair do |key, value|
75
+ if @before[key] != @after[key]
76
+ if @before.nil? || @before[key].nil?
77
+ lines.concat(yaml_lines({key => output_values_after[key]}, indent, 'added'))
78
+
79
+ elsif @after.nil? || @after[key].nil?
80
+ lines.concat(yaml_lines({key => output_values_before[key]}, indent, 'removed'))
81
+
82
+ elsif @before[key].is_a?(Array) && @after[key].is_a?(Array)
83
+ lines.concat(compare_arrays(@before[key], @after[key], output_values_before[key], output_values_after[key], key, redact, indent))
84
+
85
+ elsif @before[key].is_a?(Hash) && @after[key].is_a?(Hash)
86
+ changeset = Changeset.new(@before[key], @after[key], output_values_before[key], output_values_after[key])
87
+ diff_lines = changeset.diff(redact, indent+1)
88
+ unless diff_lines.empty?
89
+ lines << Line.new(indent, "#{key}:", nil)
90
+ lines.concat(diff_lines)
91
+ end
92
+
93
+ else
94
+ lines.concat(yaml_lines({key => output_values_before[key]}, indent, 'removed'))
95
+ lines.concat(yaml_lines({key => output_values_after[key]}, indent, 'added'))
96
+ end
53
97
  end
54
98
  end
55
99
  lines
56
100
  end
57
101
 
102
+ private
103
+
104
+ def deep_merge(first, second)
105
+ merger = proc { |key, v1, v2| Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : v2 }
106
+ first.merge(second, &merger)
107
+ end
108
+
58
109
  def yaml_lines(value, indent, state)
59
110
  lines = DiffLines.new
60
- value.to_yaml(indent: Line::INDENT).gsub("---\n", '').split("\n").each do |line|
111
+ value.to_yaml(indent: Line::INDENT).gsub(/^---\n/, '').split("\n").each do |line|
61
112
  lines << Line.new(indent, line, state)
62
113
  end
63
114
  lines
64
115
  end
65
116
 
66
- def compare_arrays(old_value, new_value, redacted_old_value, redacted_new_value, parent_name, indent)
117
+ def compare_arrays(old_value, new_value, output_old_value, output_new_value, parent_name, redact, indent)
67
118
  # combine arrays of redacted and unredacted values. unredacted arrays for diff logic, and redacted arrays for output
68
- combined_old_value = old_value.zip redacted_old_value
69
- combined_new_value = new_value.zip redacted_new_value
70
-
119
+ combined_old_value = old_value.zip output_old_value
120
+ combined_new_value = new_value.zip output_new_value
71
121
  added = combined_new_value - combined_old_value
72
122
  removed = combined_old_value - combined_new_value
73
123
 
74
124
  lines = DiffLines.new
75
125
 
76
126
  added.each do |pair|
77
-
78
127
  elem = pair.first
79
128
  redacted_elem = pair.last
80
-
81
129
  if elem.is_a?(Hash)
82
130
  using_names = (added+removed).all? { |e| e.first['name'] }
83
-
84
131
  using_ranges = (added+removed).all? { |e| e.first['range'] }
85
132
  if using_names || using_ranges
86
- #clean up duplicate values
87
133
  if using_names
88
134
  removed_same_name_element = removed.find { |e| e.first['name'] == elem['name'] }
89
135
  elsif using_ranges
@@ -92,8 +138,8 @@ module Bosh::Director
92
138
  removed.delete(removed_same_name_element)
93
139
 
94
140
  if removed_same_name_element
95
- changeset = Changeset.new(removed_same_name_element.first, elem, @redact, removed_same_name_element.last, redacted_elem)
96
- diff_lines = changeset.diff(indent+1)
141
+ changeset = Changeset.new(removed_same_name_element.first, elem, removed_same_name_element.last, redacted_elem)
142
+ diff_lines = changeset.diff(redact, indent+1)
97
143
 
98
144
  unless diff_lines.empty?
99
145
  # write name if elem has been changed
@@ -33,7 +33,7 @@ module Bosh::Director
33
33
  end
34
34
 
35
35
  def diff(other_manifest, redact)
36
- Changeset.new(to_hash, other_manifest.to_hash, redact).diff.order
36
+ Changeset.new(to_hash, other_manifest.to_hash).diff(redact).order
37
37
  end
38
38
 
39
39
  def to_hash
@@ -23,6 +23,9 @@ require 'bosh/director/models/template'
23
23
  require 'bosh/director/models/user'
24
24
  require 'bosh/director/models/persistent_disk'
25
25
  require 'bosh/director/models/rendered_templates_archive'
26
+ require 'bosh/director/models/lock'
27
+ require 'delayed_job_sequel'
28
+ require 'bosh/director/models/event'
26
29
 
27
30
  module Bosh::Director
28
31
  module Models
@@ -0,0 +1,18 @@
1
+ # Copyright (c) 2009-2012 VMware, Inc.
2
+
3
+ module Bosh::Director::Models
4
+ class Event < Sequel::Model(Bosh::Director::Config.db)
5
+ def validate
6
+ validates_presence [:timestamp, :action, :object_type]
7
+ end
8
+
9
+ def context
10
+ return {} if context_json.nil?
11
+ Yajl::Parser.parse(context_json)
12
+ end
13
+
14
+ def context=(data)
15
+ self.context_json = Yajl::Encoder.encode(data)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,9 @@
1
+ module Bosh::Director::Models
2
+ class Lock < Sequel::Model(Bosh::Director::Config.db)
3
+ def validate
4
+ validates_presence [:name,:expired_at, :uid]
5
+ validates_unique [:name, :uid]
6
+ end
7
+
8
+ end
9
+ end
@@ -12,7 +12,9 @@ module Bosh::Director::Models
12
12
  end
13
13
 
14
14
  def package_by_name(package_name)
15
- packages_by_name.fetch(package_name)
15
+ packages_by_name.fetch(package_name) do
16
+ raise "Package name '#{package_name}' not found in release '#{release.name}/#{version}'"
17
+ end
16
18
  end
17
19
 
18
20
  private