bosh-director-core 1.1868.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,41 @@
1
+ require 'tmpdir'
2
+ require 'open3'
3
+
4
+ module Bosh::Director::Core
5
+ class TarGzipper
6
+ # @param [String] base_dir the directory from which the tar command is run
7
+ # @param [String, Array] sources the relative paths to include
8
+ # @param [String] dest the destination filename for the tgz output
9
+ # @param [Hash] options the options for compress
10
+ # @option options [Boolean] :copy_first copy the source to a temp dir before archiving
11
+ def compress(base_dir, sources, dest, options = {})
12
+ sources = [*sources]
13
+ sources.each do |source|
14
+ if source.include?(File::SEPARATOR)
15
+ raise "Sources must have a path depth of 1 and contain no '#{File::SEPARATOR}'"
16
+ end
17
+ end
18
+
19
+ base_dir_path = Pathname.new(base_dir)
20
+ raise "The base directory #{base_dir} could not be found." unless base_dir_path.exist?
21
+ raise "The base directory #{base_dir} is not an absolute path." unless base_dir_path.absolute?
22
+
23
+ if options[:copy_first]
24
+ Dir.mktmpdir do |tmpdir|
25
+ FileUtils.cp_r(sources.map { |s| File.join(base_dir, s) }, "#{tmpdir}/")
26
+ tar(tmpdir, dest, sources)
27
+ end
28
+ else
29
+ tar(base_dir, dest, sources)
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ def tar(base_dir, dest, sources)
36
+ out, err, status = Open3.capture3('tar', '-C', base_dir, '-czf', dest, *sources)
37
+ raise("tar exited #{status.exitstatus}, output: '#{out}', error: '#{err}'") unless status.success?
38
+ out
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,31 @@
1
+ require 'tmpdir'
2
+ require 'digest/sha1'
3
+ require 'bosh/director/core/templates'
4
+ require 'bosh/director/core/tar_gzipper'
5
+ require 'bosh/director/core/templates/rendered_templates_writer'
6
+
7
+ module Bosh::Director::Core::Templates
8
+ class CompressedRenderedJobTemplates
9
+ def initialize(path)
10
+ @path = path
11
+ end
12
+
13
+ def write(rendered_templates)
14
+ Dir.mktmpdir do |dir|
15
+ writer = RenderedTemplatesWriter.new
16
+ writer.write(rendered_templates, dir)
17
+
18
+ tar_gzipper = Bosh::Director::Core::TarGzipper.new
19
+ tar_gzipper.compress(dir, %w(.), @path)
20
+ end
21
+ end
22
+
23
+ def contents
24
+ File.open(@path, 'r')
25
+ end
26
+
27
+ def sha1
28
+ Digest::SHA1.file(@path).hexdigest
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,31 @@
1
+ require 'bosh/director/core/templates'
2
+ require 'bosh/director/core/templates/rendered_job_instance'
3
+
4
+ module Bosh::Director::Core::Templates
5
+ class JobInstanceRenderer
6
+ def initialize(job, job_template_loader)
7
+ @job = job
8
+ @job_template_loader = job_template_loader
9
+ end
10
+
11
+ def render(instance)
12
+ rendered_templates = job.templates.map do |template|
13
+ job_template_renderer = job_template_renderers[template.name]
14
+ job_template_renderer.render(job.name, instance)
15
+ end
16
+
17
+ RenderedJobInstance.new(rendered_templates)
18
+ end
19
+
20
+ private
21
+
22
+ def job_template_renderers
23
+ @job_template_renderers ||= job.templates.reduce({}) do |hash, template|
24
+ hash[template.name] = job_template_loader.process(template)
25
+ hash
26
+ end
27
+ end
28
+
29
+ attr_reader :job_template_loader, :job
30
+ end
31
+ end
@@ -0,0 +1,56 @@
1
+ require 'bosh/director/core/templates'
2
+ require 'bosh/director/core/templates/job_template_renderer'
3
+ require 'bosh/director/core/templates/src_file_template'
4
+
5
+ module Bosh::Director::Core::Templates
6
+ class JobTemplateLoader
7
+ def initialize(logger)
8
+ @logger = logger
9
+ end
10
+
11
+ def process(job_template)
12
+ template_dir = extract_template(job_template)
13
+ manifest = Psych.load_file(File.join(template_dir, 'job.MF'))
14
+
15
+ monit_template = erb(File.join(template_dir, 'monit'))
16
+ monit_template.filename = File.join(job_template.name, 'monit')
17
+
18
+ templates = []
19
+
20
+ manifest.fetch('templates', {}).each_pair do |src_name, dest_name|
21
+ erb_file = erb(File.join(template_dir, 'templates', src_name))
22
+ erb_file.filename = File.join(job_template.name, src_name)
23
+ templates << SrcFileTemplate.new(src_name, dest_name, erb_file)
24
+ end
25
+
26
+ JobTemplateRenderer.new(job_template.name, monit_template, templates, logger)
27
+ ensure
28
+ FileUtils.rm_rf(template_dir) if template_dir
29
+ end
30
+
31
+ private
32
+
33
+ attr_reader :logger
34
+
35
+ def extract_template(job_template)
36
+ temp_path = job_template.download_blob
37
+ template_dir = Dir.mktmpdir('template_dir')
38
+
39
+ output = `tar -C #{template_dir} -xzf #{temp_path} 2>&1`
40
+ if $?.exitstatus != 0
41
+ raise JobTemplateUnpackFailed,
42
+ "Cannot unpack `#{job_template.name}' job template, " +
43
+ "tar returned #{$?.exitstatus}, " +
44
+ "tar output: #{output}"
45
+ end
46
+
47
+ template_dir
48
+ ensure
49
+ FileUtils.rm_f(temp_path) if temp_path
50
+ end
51
+
52
+ def erb(path)
53
+ ERB.new(File.read(path))
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,53 @@
1
+ require 'bosh/director/core/templates'
2
+ require 'bosh/director/core/templates/rendered_job_template'
3
+ require 'bosh/director/core/templates/rendered_file_template'
4
+ require 'common/properties'
5
+
6
+ module Bosh::Director::Core::Templates
7
+ class JobTemplateRenderer
8
+
9
+ attr_reader :monit_template, :templates
10
+
11
+ def initialize(name, monit_template, templates, logger)
12
+ @name = name
13
+ @monit_template = monit_template
14
+ @templates = templates
15
+ @logger = logger
16
+ end
17
+
18
+ def render(job_name, instance)
19
+ template_context = Bosh::Common::TemplateEvaluationContext.new(instance.spec)
20
+
21
+ monit = render_erb(job_name, monit_template, template_context, instance.index)
22
+
23
+ rendered_templates = templates.map do |template_file|
24
+ file_contents = render_erb(job_name, template_file.erb_file, template_context, instance.index)
25
+ RenderedFileTemplate.new(template_file.src_name, template_file.dest_name, file_contents)
26
+ end
27
+
28
+ RenderedJobTemplate.new(name, monit, rendered_templates)
29
+ end
30
+
31
+ private
32
+
33
+ attr_reader :name, :logger
34
+
35
+ def render_erb(job_name, template, template_context, index)
36
+ template.result(template_context.get_binding)
37
+ # rubocop:disable RescueException
38
+ rescue Exception => e
39
+ logger.debug(e.inspect)
40
+ job_desc = "#{job_name}/#{index}"
41
+ line_index = e.backtrace.index { |l| l.include?(template.filename) }
42
+ line = line_index ? e.backtrace[line_index] : '(unknown):(unknown)'
43
+ template_name, line = line.split(':')
44
+
45
+ message = "Error filling in template `#{File.basename(template_name)}' " +
46
+ "for `#{job_desc}' (line #{line}: #{e})"
47
+
48
+ logger.debug("#{message}\n#{e.backtrace.join("\n")}")
49
+ raise message
50
+ end
51
+ # rubocop:enable RescueException
52
+ end
53
+ end
@@ -0,0 +1,5 @@
1
+ require 'bosh/director/core/templates'
2
+
3
+ module Bosh::Director::Core::Templates
4
+ RenderedFileTemplate = Struct.new(:src_name, :dest_name, :contents)
5
+ end
@@ -0,0 +1,50 @@
1
+ require 'bosh/director/core/templates'
2
+ require 'bosh/director/core/templates/rendered_templates_archive'
3
+ require 'bosh/director/core/templates/compressed_rendered_job_templates'
4
+ require 'digest/sha1'
5
+ require 'tempfile'
6
+
7
+ module Bosh::Director::Core::Templates
8
+ class RenderedJobInstance
9
+ def initialize(job_templates)
10
+ @job_templates = job_templates
11
+ end
12
+
13
+ def configuration_hash
14
+ instance_digest = Digest::SHA1.new
15
+ job_templates.sort { |x, y| x.name <=> y.name }.each do |rendered_job_template|
16
+ bound_templates = ''
17
+ bound_templates << rendered_job_template.monit
18
+
19
+ rendered_job_template.templates.sort { |x, y| x.src_name <=> y.src_name }.each do |template_file|
20
+ bound_templates << template_file.contents
21
+ instance_digest << bound_templates
22
+ end
23
+ end
24
+
25
+ instance_digest.hexdigest
26
+ end
27
+
28
+ def template_hashes
29
+ job_templates.reduce({}) do |h, rendered_job_template|
30
+ h.merge(rendered_job_template.name => rendered_job_template.template_hash)
31
+ end
32
+ end
33
+
34
+ def persist(blobstore)
35
+ file = Tempfile.new('compressed-rendered-job-templates')
36
+
37
+ compressed_archive = CompressedRenderedJobTemplates.new(file.path)
38
+ compressed_archive.write(job_templates)
39
+
40
+ blobstore_id = blobstore.create(compressed_archive.contents)
41
+ RenderedTemplatesArchive.new(blobstore_id, compressed_archive.sha1)
42
+ ensure
43
+ file.close!
44
+ end
45
+
46
+ private
47
+
48
+ attr_reader :job_templates
49
+ end
50
+ end
@@ -0,0 +1,23 @@
1
+ require 'bosh/director/core/templates'
2
+
3
+ module Bosh::Director::Core::Templates
4
+ class RenderedJobTemplate
5
+ attr_reader :name, :monit, :templates
6
+
7
+ def initialize(name, monit, templates)
8
+ @name = name
9
+ @monit = monit
10
+ @templates = templates
11
+ end
12
+
13
+ def template_hash
14
+ template_digest = Digest::SHA1.new
15
+ template_digest << monit
16
+ templates.sort { |x, y| x.src_name <=> y.src_name }.each do |template_file|
17
+ template_digest << template_file.contents
18
+ end
19
+
20
+ template_digest.hexdigest
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,16 @@
1
+ require 'bosh/director/core/templates'
2
+
3
+ module Bosh::Director::Core::Templates
4
+ class RenderedTemplatesArchive
5
+ attr_reader :blobstore_id, :sha1
6
+
7
+ def initialize(blobstore_id, sha1)
8
+ @blobstore_id = blobstore_id
9
+ @sha1 = sha1
10
+ end
11
+
12
+ def spec
13
+ { 'blobstore_id' => @blobstore_id, 'sha1' => @sha1 }
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,25 @@
1
+ require 'bosh/director/core/templates'
2
+ require 'fileutils'
3
+
4
+ module Bosh::Director::Core::Templates
5
+ class RenderedTemplatesWriter
6
+ def write(rendered_templates, output_dir)
7
+ rendered_templates.each do |job_template|
8
+ job_template_dir = File.join(output_dir, job_template.name)
9
+ Dir.mkdir(job_template_dir)
10
+
11
+ File.open(File.join(job_template_dir, 'monit'), 'w') do |f|
12
+ f.write(job_template.monit)
13
+ end
14
+
15
+ job_template.templates.each do |file_template|
16
+ file_template_dest = File.join(job_template_dir, file_template.dest_name)
17
+ FileUtils.mkdir_p(File.dirname(file_template_dest))
18
+ File.open(file_template_dest, 'w') do |f|
19
+ f.write(file_template.contents)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,5 @@
1
+ require 'bosh/director/core/templates'
2
+
3
+ module Bosh::Director::Core::Templates
4
+ SrcFileTemplate = Struct.new(:src_name, :dest_name, :erb_file)
5
+ end
@@ -0,0 +1,6 @@
1
+ require 'bosh/director/core'
2
+
3
+ module Bosh::Director::Core
4
+ module Templates
5
+ end
6
+ end
@@ -0,0 +1,7 @@
1
+ module Bosh
2
+ module Director
3
+ module Core
4
+ VERSION = '1.1868.0'
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,6 @@
1
+ module Bosh
2
+ module Director
3
+ module Core
4
+ end
5
+ end
6
+ end
metadata ADDED
@@ -0,0 +1,128 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bosh-director-core
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.1868.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Pivotal
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-01-29 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bosh_common
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 1.1868.0
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 1.1868.0
30
+ - !ruby/object:Gem::Dependency
31
+ name: rake
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rspec
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: fakefs
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ description: Bosh::Director::Core provides common Director code for Director and Microbosh
79
+ Deployer
80
+ email: support@cloudfoundry.com
81
+ executables: []
82
+ extensions: []
83
+ extra_rdoc_files: []
84
+ files:
85
+ - lib/bosh/director/core.rb
86
+ - lib/bosh/director/core/tar_gzipper.rb
87
+ - lib/bosh/director/core/templates.rb
88
+ - lib/bosh/director/core/templates/compressed_rendered_job_templates.rb
89
+ - lib/bosh/director/core/templates/job_instance_renderer.rb
90
+ - lib/bosh/director/core/templates/job_template_loader.rb
91
+ - lib/bosh/director/core/templates/job_template_renderer.rb
92
+ - lib/bosh/director/core/templates/rendered_file_template.rb
93
+ - lib/bosh/director/core/templates/rendered_job_instance.rb
94
+ - lib/bosh/director/core/templates/rendered_job_template.rb
95
+ - lib/bosh/director/core/templates/rendered_templates_archive.rb
96
+ - lib/bosh/director/core/templates/rendered_templates_writer.rb
97
+ - lib/bosh/director/core/templates/src_file_template.rb
98
+ - lib/bosh/director/core/version.rb
99
+ homepage: https://github.com/cloudfoundry/bosh
100
+ licenses:
101
+ - Apache 2.0
102
+ post_install_message:
103
+ rdoc_options: []
104
+ require_paths:
105
+ - lib
106
+ required_ruby_version: !ruby/object:Gem::Requirement
107
+ none: false
108
+ requirements:
109
+ - - ! '>='
110
+ - !ruby/object:Gem::Version
111
+ version: 1.9.3
112
+ required_rubygems_version: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ segments:
119
+ - 0
120
+ hash: -2612646582658106641
121
+ requirements: []
122
+ rubyforge_project:
123
+ rubygems_version: 1.8.23
124
+ signing_key:
125
+ specification_version: 3
126
+ summary: Bosh::Director::Core provides common Director code for Director and Microbosh
127
+ Deployer
128
+ test_files: []