bosh_cli 1.2831.0 → 1.2839.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/cli.rb +7 -3
- data/lib/cli/archive_builder.rb +119 -0
- data/lib/cli/archive_repository.rb +108 -0
- data/lib/cli/archive_repository_provider.rb +12 -0
- data/lib/cli/base_command.rb +1 -1
- data/lib/cli/build_artifact.rb +75 -0
- data/lib/cli/commands/deployment.rb +4 -9
- data/lib/cli/commands/release/create_release.rb +36 -39
- data/lib/cli/glob_match.rb +32 -0
- data/lib/cli/job_property_collection.rb +5 -5
- data/lib/cli/job_property_validator.rb +8 -8
- data/lib/cli/release_builder.rb +43 -44
- data/lib/cli/release_compiler.rb +11 -11
- data/lib/cli/resources/job.rb +190 -0
- data/lib/cli/resources/package.rb +210 -0
- data/lib/cli/version.rb +1 -1
- data/lib/cli/versions/local_version_storage.rb +4 -4
- data/lib/cli/versions/version_file_resolver.rb +1 -3
- metadata +16 -12
- data/lib/cli/job_builder.rb +0 -277
- data/lib/cli/package_builder.rb +0 -316
- data/lib/cli/packaging_helper.rb +0 -217
@@ -0,0 +1,32 @@
|
|
1
|
+
module Bosh::Cli
|
2
|
+
class GlobMatch
|
3
|
+
# Helper class encapsulating the data we know about the glob. We need
|
4
|
+
# both directory and file path, as we match the same path in several
|
5
|
+
# directories (src, src_alt, blobs)
|
6
|
+
attr_reader :dir
|
7
|
+
attr_reader :path
|
8
|
+
|
9
|
+
def initialize(dir, path)
|
10
|
+
@dir = dir
|
11
|
+
@path = path
|
12
|
+
end
|
13
|
+
|
14
|
+
def full_path
|
15
|
+
File.join(dir, path)
|
16
|
+
end
|
17
|
+
|
18
|
+
def <=>(other)
|
19
|
+
@path <=> other.path
|
20
|
+
end
|
21
|
+
|
22
|
+
# GlobMatch will be used as Hash key (as implied by using Set),
|
23
|
+
# hence we need to define both eql? and hash
|
24
|
+
def eql?(other)
|
25
|
+
@path == other.path
|
26
|
+
end
|
27
|
+
|
28
|
+
def hash
|
29
|
+
@path.hash
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -8,12 +8,12 @@ module Bosh::Cli
|
|
8
8
|
include Enumerable
|
9
9
|
include Bosh::Template::PropertyHelper
|
10
10
|
|
11
|
-
# @param [
|
11
|
+
# @param [Bosh::Cli::Resources::Job] job Which job this property collection is for
|
12
12
|
# @param [Hash] global_properties Globally defined properties
|
13
13
|
# @param [Hash] job_properties Properties defined for this job only
|
14
14
|
# @param [Hash] mappings Property mappings for this job
|
15
|
-
def initialize(
|
16
|
-
@
|
15
|
+
def initialize(job, global_properties, job_properties, mappings)
|
16
|
+
@job = job
|
17
17
|
|
18
18
|
@job_properties = Bosh::Common::DeepCopy.copy(job_properties || {})
|
19
19
|
merge(@job_properties, Bosh::Common::DeepCopy.copy(global_properties))
|
@@ -52,7 +52,7 @@ module Bosh::Cli
|
|
52
52
|
|
53
53
|
# @return [void] Modifies @properties
|
54
54
|
def filter_properties
|
55
|
-
if @
|
55
|
+
if @job.properties.empty?
|
56
56
|
# If at least one template doesn't have properties defined, we
|
57
57
|
# need all properties to be available to job (backward-compatibility)
|
58
58
|
@properties = @job_properties
|
@@ -61,7 +61,7 @@ module Bosh::Cli
|
|
61
61
|
|
62
62
|
@properties = {}
|
63
63
|
|
64
|
-
@
|
64
|
+
@job.properties.each_pair do |name, definition|
|
65
65
|
copy_property(
|
66
66
|
@properties, @job_properties, name, definition["default"])
|
67
67
|
end
|
@@ -7,7 +7,7 @@ module Bosh::Cli
|
|
7
7
|
attr_reader :template_errors
|
8
8
|
attr_reader :jobs_without_properties
|
9
9
|
|
10
|
-
# @param [Array<
|
10
|
+
# @param [Array<Bosh::Cli::Resources::Job>] built_jobs Built job templates
|
11
11
|
# @param [Hash] manifest Deployment manifest
|
12
12
|
def initialize(built_jobs, manifest)
|
13
13
|
@built_jobs = {}
|
@@ -44,7 +44,7 @@ module Bosh::Cli
|
|
44
44
|
end
|
45
45
|
|
46
46
|
if job["template"].nil?
|
47
|
-
bad_manifest("Job
|
47
|
+
bad_manifest("Job '#{job_name}' doesn't have a template")
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
@@ -68,7 +68,7 @@ module Bosh::Cli
|
|
68
68
|
built_job = @built_jobs[job_spec["template"]]
|
69
69
|
|
70
70
|
if built_job.nil?
|
71
|
-
raise CliError, "Job
|
71
|
+
raise CliError, "Job '#{job_spec["template"]}' has not been built"
|
72
72
|
end
|
73
73
|
|
74
74
|
collection = JobPropertyCollection.new(
|
@@ -86,8 +86,8 @@ module Bosh::Cli
|
|
86
86
|
'properties' => collection.to_hash
|
87
87
|
}
|
88
88
|
|
89
|
-
built_job.
|
90
|
-
evaluate_template(built_job,
|
89
|
+
built_job.files.each do |file_tuple|
|
90
|
+
evaluate_template(built_job, file_tuple.first, spec)
|
91
91
|
end
|
92
92
|
end
|
93
93
|
|
@@ -104,7 +104,7 @@ module Bosh::Cli
|
|
104
104
|
|
105
105
|
private
|
106
106
|
|
107
|
-
# @param [
|
107
|
+
# @param [Bosh::Cli::Resources::Job] job Job builder
|
108
108
|
# @param [String] template_path Template path
|
109
109
|
# @param [Hash] spec Fake instance spec
|
110
110
|
def evaluate_template(job, template_path, spec)
|
@@ -127,7 +127,7 @@ module Bosh::Cli
|
|
127
127
|
attr_reader :exception
|
128
128
|
attr_reader :line
|
129
129
|
|
130
|
-
# @param [
|
130
|
+
# @param [Bosh::Cli::Resources::Job] job
|
131
131
|
# @param [String] template_path
|
132
132
|
# @param [Exception] exception
|
133
133
|
def initialize(job, template_path, exception)
|
@@ -138,4 +138,4 @@ module Bosh::Cli
|
|
138
138
|
end
|
139
139
|
end
|
140
140
|
end
|
141
|
-
end
|
141
|
+
end
|
data/lib/cli/release_builder.rb
CHANGED
@@ -5,16 +5,16 @@ module Bosh::Cli
|
|
5
5
|
attr_reader :release, :packages, :jobs, :name, :version, :build_dir, :commit_hash, :uncommitted_changes
|
6
6
|
|
7
7
|
# @param [Bosh::Cli::Release] release Current release
|
8
|
-
# @param [Array<Bosh::Cli::
|
9
|
-
# @param [Array<Bosh::Cli::
|
8
|
+
# @param [Array<Bosh::Cli::BuildArtifact>] package_artifacts Built packages
|
9
|
+
# @param [Array<Bosh::Cli::BuildArtifact>] job_artifacts Built jobs
|
10
10
|
# @param [Hash] options Release build options
|
11
|
-
def initialize(release,
|
11
|
+
def initialize(release, package_artifacts, job_artifacts, name, options = { })
|
12
12
|
@release = release
|
13
13
|
@final = options.has_key?(:final) ? !!options[:final] : false
|
14
14
|
@commit_hash = options.fetch(:commit_hash, '00000000')
|
15
15
|
@uncommitted_changes = options.fetch(:uncommitted_changes, true)
|
16
|
-
@packages =
|
17
|
-
@jobs =
|
16
|
+
@packages = package_artifacts # todo
|
17
|
+
@jobs = job_artifacts # todo
|
18
18
|
@name = name
|
19
19
|
raise 'Release name is blank' if name.blank?
|
20
20
|
|
@@ -49,19 +49,18 @@ module Bosh::Cli
|
|
49
49
|
@final
|
50
50
|
end
|
51
51
|
|
52
|
-
# @return [Array] List of
|
53
|
-
# to the previous one.
|
52
|
+
# @return [Array<Bosh::Cli::BuildArtifact>] List of job artifacts
|
53
|
+
# affected by this release compared to the previous one.
|
54
54
|
def affected_jobs
|
55
|
-
result = Set.new(@jobs.select { |
|
56
|
-
return result if @packages.empty?
|
55
|
+
result = Set.new(@jobs.select { |job_artifact| job_artifact.new_version? })
|
56
|
+
return result.to_a if @packages.empty?
|
57
57
|
|
58
|
-
new_package_names = @packages.
|
59
|
-
|
60
|
-
|
61
|
-
end
|
58
|
+
new_package_names = @packages.map do |package_artifact|
|
59
|
+
package_artifact.name if package_artifact.new_version?
|
60
|
+
end.compact
|
62
61
|
|
63
62
|
@jobs.each do |job|
|
64
|
-
result << job if (new_package_names & job.
|
63
|
+
result << job if (new_package_names & job.dependencies).size > 0
|
65
64
|
end
|
66
65
|
|
67
66
|
result.to_a
|
@@ -83,22 +82,25 @@ module Bosh::Cli
|
|
83
82
|
|
84
83
|
# Copies packages into release
|
85
84
|
def copy_packages
|
86
|
-
packages.each do |
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
85
|
+
packages.each do |package_artifact|
|
86
|
+
name = package_artifact.name
|
87
|
+
tarball_path = package_artifact.tarball_path
|
88
|
+
say("%-40s %s" % [name.make_green, pretty_size(tarball_path)])
|
89
|
+
FileUtils.cp(tarball_path,
|
90
|
+
File.join(build_dir, "packages", "#{name}.tgz"),
|
91
91
|
:preserve => true)
|
92
92
|
end
|
93
93
|
@packages_copied = true
|
94
94
|
end
|
95
95
|
|
96
|
-
# Copies jobs into release
|
96
|
+
# Copies jobs into release todo DRY vs copy_packages
|
97
97
|
def copy_jobs
|
98
|
-
jobs.each do |
|
99
|
-
|
100
|
-
|
101
|
-
|
98
|
+
jobs.each do |job_artifact|
|
99
|
+
name = job_artifact.name
|
100
|
+
tarball_path = job_artifact.tarball_path
|
101
|
+
say("%-40s %s" % [name.make_green, pretty_size(tarball_path)])
|
102
|
+
FileUtils.cp(tarball_path,
|
103
|
+
File.join(build_dir, "jobs", "#{name}.tgz"),
|
102
104
|
:preserve => true)
|
103
105
|
end
|
104
106
|
@jobs_copied = true
|
@@ -107,40 +109,37 @@ module Bosh::Cli
|
|
107
109
|
# Generates release manifest
|
108
110
|
def generate_manifest
|
109
111
|
manifest = {}
|
110
|
-
manifest[
|
111
|
-
|
112
|
-
manifest["packages"] = packages.map do |package|
|
112
|
+
manifest['packages'] = packages.map do |build_artifact|
|
113
113
|
{
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
114
|
+
'name' => build_artifact.name,
|
115
|
+
'version' => build_artifact.version,
|
116
|
+
'fingerprint' => build_artifact.fingerprint,
|
117
|
+
'sha1' => build_artifact.sha1,
|
118
|
+
'dependencies' => build_artifact.dependencies,
|
119
119
|
}
|
120
120
|
end
|
121
|
-
|
122
|
-
manifest["jobs"] = jobs.map do |job|
|
121
|
+
manifest['jobs'] = jobs.map do |build_artifact|
|
123
122
|
{
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
123
|
+
'name' => build_artifact.name,
|
124
|
+
'version' => build_artifact.version,
|
125
|
+
'fingerprint' => build_artifact.fingerprint,
|
126
|
+
'sha1' => build_artifact.sha1,
|
128
127
|
}
|
129
128
|
end
|
130
129
|
|
131
|
-
manifest[
|
132
|
-
manifest[
|
130
|
+
manifest['commit_hash'] = commit_hash
|
131
|
+
manifest['uncommitted_changes'] = uncommitted_changes
|
133
132
|
|
134
133
|
unless @name.bosh_valid_id?
|
135
|
-
raise InvalidRelease, "Release name
|
134
|
+
raise InvalidRelease, "Release name '#{@name}' is not a valid BOSH identifier"
|
136
135
|
end
|
137
|
-
manifest[
|
136
|
+
manifest['name'] = @name
|
138
137
|
|
139
138
|
# New release versions are allowed to have the same fingerprint as old versions.
|
140
139
|
# For reverse compatibility, random uuids are stored instead.
|
141
|
-
@index.add_version(SecureRandom.uuid, {
|
140
|
+
@index.add_version(SecureRandom.uuid, { 'version' => version })
|
142
141
|
|
143
|
-
manifest[
|
142
|
+
manifest['version'] = version
|
144
143
|
manifest_yaml = Psych.dump(manifest)
|
145
144
|
|
146
145
|
say("Writing manifest...")
|
data/lib/cli/release_compiler.rb
CHANGED
@@ -14,13 +14,13 @@ module Bosh::Cli
|
|
14
14
|
# @param [Bosh::Blobstore::Client] blobstore Blobstore client
|
15
15
|
# @param [Array] package_matches List of package checksums that director
|
16
16
|
# can match
|
17
|
-
# @param [String]
|
17
|
+
# @param [String] release_source Release directory
|
18
18
|
def initialize(manifest_file, blobstore,
|
19
|
-
package_matches = [],
|
19
|
+
package_matches = [], release_source = nil)
|
20
20
|
|
21
21
|
@blobstore = blobstore
|
22
|
-
@
|
23
|
-
@manifest_file = File.expand_path(manifest_file, @
|
22
|
+
@release_source = release_source || Dir.pwd
|
23
|
+
@manifest_file = File.expand_path(manifest_file, @release_source)
|
24
24
|
@tarball_path = nil
|
25
25
|
|
26
26
|
@build_dir = Dir.mktmpdir
|
@@ -95,18 +95,18 @@ module Bosh::Cli
|
|
95
95
|
|
96
96
|
def find_package(package)
|
97
97
|
name = package.name
|
98
|
-
final_package_dir = File.join(@
|
98
|
+
final_package_dir = File.join(@release_source, '.final_builds', 'packages', name)
|
99
99
|
final_index = Versions::VersionsIndex.new(final_package_dir)
|
100
|
-
dev_package_dir = File.join(@
|
100
|
+
dev_package_dir = File.join(@release_source, '.dev_builds', 'packages', name)
|
101
101
|
dev_index = Versions::VersionsIndex.new(dev_package_dir)
|
102
102
|
find_in_indices(final_index, dev_index, package, 'package')
|
103
103
|
end
|
104
104
|
|
105
105
|
def find_job(job)
|
106
106
|
name = job.name
|
107
|
-
final_jobs_dir = File.join(@
|
107
|
+
final_jobs_dir = File.join(@release_source, '.final_builds', 'jobs', name)
|
108
108
|
final_index = Versions::VersionsIndex.new(final_jobs_dir)
|
109
|
-
dev_jobs_dir = File.join(@
|
109
|
+
dev_jobs_dir = File.join(@release_source, '.dev_builds', 'jobs', name)
|
110
110
|
dev_index = Versions::VersionsIndex.new(dev_jobs_dir)
|
111
111
|
find_in_indices(final_index, dev_index, job, 'job')
|
112
112
|
end
|
@@ -148,9 +148,9 @@ module Bosh::Cli
|
|
148
148
|
# @return [Boolean]
|
149
149
|
def remote_package_exists?(local_package)
|
150
150
|
# If checksum is known to director we can always match it
|
151
|
-
@package_matches.include?(local_package.sha1) ||
|
152
|
-
(local_package.fingerprint &&
|
153
|
-
@package_matches.include?(local_package.fingerprint))
|
151
|
+
@package_matches.include?(local_package.sha1) || # !!! Needs test coverage
|
152
|
+
(local_package.fingerprint && # !!! Needs test coverage
|
153
|
+
@package_matches.include?(local_package.fingerprint)) # !!! Needs test coverage
|
154
154
|
end
|
155
155
|
|
156
156
|
# Checks if local job is already known remotely
|
@@ -0,0 +1,190 @@
|
|
1
|
+
module Bosh::Cli::Resources
|
2
|
+
class Job
|
3
|
+
BUILD_HOOK_FILES = ['prepare']
|
4
|
+
|
5
|
+
# @param [String] directory base Release directory
|
6
|
+
def self.discover(release_base, packages)
|
7
|
+
Dir[File.join(release_base, 'jobs', '*')].inject([]) do |jobs, job_base|
|
8
|
+
next unless File.directory?(job_base)
|
9
|
+
jobs << new(job_base, release_base, packages)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
attr_reader :job_base, :release_base, :package_dependencies
|
14
|
+
|
15
|
+
def initialize(job_base, release_base, packages)
|
16
|
+
@release_base = Pathname.new(release_base)
|
17
|
+
@job_base = Pathname.new(job_base)
|
18
|
+
@package_dependencies = packages
|
19
|
+
end
|
20
|
+
|
21
|
+
def spec
|
22
|
+
@spec ||= load_yaml_file(job_base.join('spec'))
|
23
|
+
rescue
|
24
|
+
raise Bosh::Cli::InvalidJob, 'Job spec is missing'
|
25
|
+
end
|
26
|
+
|
27
|
+
def name
|
28
|
+
spec['name']
|
29
|
+
end
|
30
|
+
|
31
|
+
def dependencies
|
32
|
+
package_dependencies #TODO: should this be packages or package_dependencies?
|
33
|
+
end
|
34
|
+
|
35
|
+
def singular_type
|
36
|
+
'job'
|
37
|
+
end
|
38
|
+
|
39
|
+
def plural_type
|
40
|
+
'jobs'
|
41
|
+
end
|
42
|
+
|
43
|
+
def files
|
44
|
+
validate!
|
45
|
+
|
46
|
+
files = (templates_files + monit_files).map { |absolute_path| [absolute_path, relative_path(absolute_path)] }
|
47
|
+
files << [File.join(job_base, 'spec'), 'job.MF']
|
48
|
+
files
|
49
|
+
end
|
50
|
+
|
51
|
+
# TODO: check dependency packages
|
52
|
+
def validate!
|
53
|
+
if name.blank?
|
54
|
+
raise Bosh::Cli::InvalidJob, 'Job name is missing'
|
55
|
+
end
|
56
|
+
|
57
|
+
unless name.bosh_valid_id?
|
58
|
+
raise Bosh::Cli::InvalidJob, "'#{name}' is not a valid BOSH identifier"
|
59
|
+
end
|
60
|
+
|
61
|
+
unless spec['templates'].is_a?(Hash)
|
62
|
+
raise Bosh::Cli::InvalidJob, "Incorrect templates section in '#{name}' job spec (Hash expected, #{spec['templates'].class} given)"
|
63
|
+
end
|
64
|
+
|
65
|
+
if extra_templates.size > 0
|
66
|
+
raise Bosh::Cli::InvalidJob, "There are unused template files for job '#{name}': #{extra_templates.join(", ")}"
|
67
|
+
end
|
68
|
+
|
69
|
+
if missing_templates.size > 0
|
70
|
+
raise Bosh::Cli::InvalidJob, "Some template files required by '#{name}' job are missing: #{missing_templates.join(", ")}"
|
71
|
+
end
|
72
|
+
|
73
|
+
if missing_packages.size > 0
|
74
|
+
raise Bosh::Cli::InvalidJob, "Some packages required by '#{name}' job are missing: #{missing_packages.join(", ")}"
|
75
|
+
end
|
76
|
+
|
77
|
+
if spec.has_key?('properties')
|
78
|
+
unless spec['properties'].is_a?(Hash)
|
79
|
+
raise Bosh::Cli::InvalidJob, "Incorrect properties section in '#{name}' job spec (Hash expected, #{spec['properties'].class} given)"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
unless monit_files.size > 0
|
84
|
+
raise Bosh::Cli::InvalidJob, "Cannot find monit file for '#{name}'"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def additional_fingerprints
|
89
|
+
[]
|
90
|
+
end
|
91
|
+
|
92
|
+
def format_fingerprint(digest, filename, name, file_mode)
|
93
|
+
"%s%s%s" % [File.basename(filename), digest, file_mode]
|
94
|
+
end
|
95
|
+
|
96
|
+
def run_script(script_name, *args)
|
97
|
+
if BUILD_HOOK_FILES.include?(script_name.to_s)
|
98
|
+
send(:"run_script_#{script_name}", *args)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def properties
|
103
|
+
spec['properties'] || {}
|
104
|
+
end
|
105
|
+
|
106
|
+
private
|
107
|
+
|
108
|
+
def extra_templates
|
109
|
+
return [] if !File.directory?(templates_dir)
|
110
|
+
|
111
|
+
Dir.chdir(templates_dir) do
|
112
|
+
Dir["**/*"].reject do |file|
|
113
|
+
File.directory?(file) || templates.include?(file)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def missing_packages
|
119
|
+
@missing_packages ||= (packages - package_dependencies)
|
120
|
+
end
|
121
|
+
|
122
|
+
def missing_templates
|
123
|
+
templates.select do |template|
|
124
|
+
!File.exists?(File.join(templates_dir, template))
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def monit_files
|
129
|
+
monit = File.join(job_base, 'monit')
|
130
|
+
files = Dir.glob(File.join(job_base, '*.monit'))
|
131
|
+
files << monit if File.exist?(monit)
|
132
|
+
files
|
133
|
+
end
|
134
|
+
|
135
|
+
def packages
|
136
|
+
spec['packages'] || []
|
137
|
+
end
|
138
|
+
|
139
|
+
def relative_path(path)
|
140
|
+
Pathname.new(path).relative_path_from(job_base).to_s
|
141
|
+
end
|
142
|
+
|
143
|
+
def templates
|
144
|
+
spec['templates'].keys
|
145
|
+
end
|
146
|
+
|
147
|
+
def templates_dir
|
148
|
+
@templates_dir ||= job_base.join('templates')
|
149
|
+
end
|
150
|
+
|
151
|
+
def templates_files
|
152
|
+
templates.map { |file| File.join(templates_dir, file) }
|
153
|
+
end
|
154
|
+
|
155
|
+
def run_script_prepare
|
156
|
+
script_path = File.join(job_base, 'prepare')
|
157
|
+
|
158
|
+
return nil unless File.exists?(script_path)
|
159
|
+
|
160
|
+
unless File.executable?(script_path)
|
161
|
+
raise Bosh::Cli::InvalidJob, "Prepare script at '#{script_path}' is not executable"
|
162
|
+
end
|
163
|
+
|
164
|
+
old_env = ENV
|
165
|
+
script_dir = File.dirname(script_path)
|
166
|
+
script_name = File.basename(script_path)
|
167
|
+
|
168
|
+
begin
|
169
|
+
# We need to temporarily delete some rubygems related artefacts
|
170
|
+
# because preparation scripts shouldn't share any assumptions
|
171
|
+
# with CLI itself
|
172
|
+
%w{ BUNDLE_GEMFILE RUBYOPT }.each { |key| ENV.delete(key) }
|
173
|
+
|
174
|
+
output = nil
|
175
|
+
Dir.chdir(script_dir) do
|
176
|
+
cmd = "./#{script_name} 2>&1"
|
177
|
+
output = `#{cmd}`
|
178
|
+
end
|
179
|
+
|
180
|
+
unless $?.exitstatus == 0
|
181
|
+
raise Bosh::Cli::InvalidJob, "'#{script_path}' script failed: #{output}"
|
182
|
+
end
|
183
|
+
|
184
|
+
output
|
185
|
+
ensure
|
186
|
+
ENV.each_pair { |k, v| ENV[k] = old_env[k] }
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|