bosh-director-core 1.1868.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/bosh/director/core/tar_gzipper.rb +41 -0
- data/lib/bosh/director/core/templates/compressed_rendered_job_templates.rb +31 -0
- data/lib/bosh/director/core/templates/job_instance_renderer.rb +31 -0
- data/lib/bosh/director/core/templates/job_template_loader.rb +56 -0
- data/lib/bosh/director/core/templates/job_template_renderer.rb +53 -0
- data/lib/bosh/director/core/templates/rendered_file_template.rb +5 -0
- data/lib/bosh/director/core/templates/rendered_job_instance.rb +50 -0
- data/lib/bosh/director/core/templates/rendered_job_template.rb +23 -0
- data/lib/bosh/director/core/templates/rendered_templates_archive.rb +16 -0
- data/lib/bosh/director/core/templates/rendered_templates_writer.rb +25 -0
- data/lib/bosh/director/core/templates/src_file_template.rb +5 -0
- data/lib/bosh/director/core/templates.rb +6 -0
- data/lib/bosh/director/core/version.rb +7 -0
- data/lib/bosh/director/core.rb +6 -0
- metadata +128 -0
@@ -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,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
|
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: []
|