bosh_cli 1.2671.0 → 1.2682.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 +8 -1
- data/lib/cli/commands/release/create_release.rb +279 -0
- data/lib/cli/commands/release/delete_release.rb +32 -0
- data/lib/cli/commands/release/init_release.rb +45 -0
- data/lib/cli/commands/release/list_releases.rb +123 -0
- data/lib/cli/commands/release/reset_release.rb +27 -0
- data/lib/cli/commands/release/upload_release.rb +208 -0
- data/lib/cli/commands/release/verify_release.rb +28 -0
- data/lib/cli/packaging_helper.rb +5 -5
- data/lib/cli/release_builder.rb +17 -23
- data/lib/cli/release_compiler.rb +12 -10
- data/lib/cli/source_control/git_ignore.rb +42 -0
- data/lib/cli/version.rb +1 -1
- data/lib/cli/versions/local_version_storage.rb +1 -1
- data/lib/cli/versions/multi_release_support.rb +24 -0
- data/lib/cli/versions/release_versions_index.rb +1 -1
- data/lib/cli/versions/releases_dir_migrator.rb +108 -0
- data/lib/cli/versions/version_file_resolver.rb +2 -11
- data/lib/cli/versions/versions_index.rb +61 -27
- metadata +19 -10
- data/lib/cli/commands/release.rb +0 -684
data/lib/cli/version.rb
CHANGED
@@ -0,0 +1,24 @@
|
|
1
|
+
module Bosh::Cli::Versions
|
2
|
+
class MultiReleaseSupport
|
3
|
+
|
4
|
+
def initialize(work_dir, default_release_name, ui)
|
5
|
+
@work_dir = work_dir
|
6
|
+
@default_release_name = default_release_name
|
7
|
+
@ui = ui
|
8
|
+
end
|
9
|
+
|
10
|
+
def migrate
|
11
|
+
dev_releases_path = File.join(@work_dir, 'dev_releases')
|
12
|
+
migrator = ReleasesDirMigrator.new(dev_releases_path, @default_release_name, @ui, 'DEV')
|
13
|
+
dev_release_migrated = migrator.migrate
|
14
|
+
|
15
|
+
final_releases_path = File.join(@work_dir, 'releases')
|
16
|
+
migrator = ReleasesDirMigrator.new(final_releases_path, @default_release_name, @ui, 'FINAL')
|
17
|
+
final_releases_migrated = migrator.migrate
|
18
|
+
|
19
|
+
if final_releases_migrated || dev_release_migrated
|
20
|
+
Bosh::Cli::SourceControl::GitIgnore.new(@work_dir).update
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
# This class migrates the releases directory and its index.yml files from format v1 -> v2
|
2
|
+
module Bosh::Cli::Versions
|
3
|
+
class ReleasesDirMigrator
|
4
|
+
|
5
|
+
def initialize(releases_path, default_release_name, ui, release_type_name)
|
6
|
+
@releases_path = releases_path
|
7
|
+
@default_release_name = default_release_name
|
8
|
+
@ui = ui
|
9
|
+
@release_type_name = release_type_name
|
10
|
+
end
|
11
|
+
|
12
|
+
def needs_migration?
|
13
|
+
index_path = File.join(@releases_path, 'index.yml')
|
14
|
+
return false unless File.exists?(index_path)
|
15
|
+
|
16
|
+
index = VersionsIndex.load_index_yaml(index_path)
|
17
|
+
format_version_string = index['format-version']
|
18
|
+
return true if format_version_string.nil?
|
19
|
+
|
20
|
+
begin
|
21
|
+
SemiSemantic::Version.parse(format_version_string) < VersionsIndex::CURRENT_INDEX_VERSION
|
22
|
+
rescue ArgumentError, SemiSemantic::ParseError
|
23
|
+
raise InvalidIndex, "Invalid versions index version in `#{index_path}', " +
|
24
|
+
"`#{format_version_string}' given, SemiSemantic version expected"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def migrate
|
29
|
+
return false unless needs_migration?
|
30
|
+
|
31
|
+
unless Dir.exist?(@releases_path)
|
32
|
+
raise "Releases path `#{@releases_path}' does not exist"
|
33
|
+
end
|
34
|
+
|
35
|
+
@ui.header("Migrating #{@release_type_name} releases".make_green)
|
36
|
+
|
37
|
+
old_index = VersionsIndex.new(@releases_path)
|
38
|
+
|
39
|
+
migrated_releases = Set.new
|
40
|
+
|
41
|
+
release_versions_to_migrate.each do |data|
|
42
|
+
release_name = data[:name]
|
43
|
+
if migrated_releases.add?(release_name)
|
44
|
+
@ui.say("Migrating release: #{release_name}")
|
45
|
+
end
|
46
|
+
|
47
|
+
release_path = File.join(@releases_path, release_name)
|
48
|
+
|
49
|
+
FileUtils.mkdir_p(release_path) unless Dir.exist?(release_path)
|
50
|
+
|
51
|
+
# move version record to new index file in release_path
|
52
|
+
index_key = old_index.find_key_by_version(data[:version])
|
53
|
+
index_value = old_index[index_key]
|
54
|
+
old_index.remove_version(index_key)
|
55
|
+
new_index = VersionsIndex.new(release_path)
|
56
|
+
new_index.add_version(index_key, index_value)
|
57
|
+
|
58
|
+
# move tarball and manifest to release_path
|
59
|
+
FileUtils.mv(data[:manifest_path], release_path)
|
60
|
+
FileUtils.mv(data[:tarball_path], release_path) if File.exist?(data[:tarball_path])
|
61
|
+
end
|
62
|
+
|
63
|
+
@ui.say("Migrating default release: #{@default_release_name}")
|
64
|
+
create_release_symlink
|
65
|
+
|
66
|
+
# initialize release name & format-version in index.yml
|
67
|
+
old_index.save
|
68
|
+
|
69
|
+
true
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def release_versions_to_migrate
|
75
|
+
release_versions_data.select { |v| v[:name] != @default_release_name }
|
76
|
+
end
|
77
|
+
|
78
|
+
def release_versions_data
|
79
|
+
release_manifest_paths.map do |file_path|
|
80
|
+
manifest_hash = load_yaml_file(file_path, nil)
|
81
|
+
return {} unless manifest_hash.kind_of?(Hash)
|
82
|
+
{
|
83
|
+
name: manifest_hash['name'],
|
84
|
+
version: manifest_hash['version'],
|
85
|
+
manifest_path: file_path,
|
86
|
+
tarball_path: file_path[0...-4] + '.tgz',
|
87
|
+
}
|
88
|
+
end.select do |version_record|
|
89
|
+
# ignore invalid manifests
|
90
|
+
version_record != {}
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def release_manifest_paths
|
95
|
+
index_path = File.join(@releases_path, 'index.yml')
|
96
|
+
Dir.glob(File.join(@releases_path, '*.yml')).select do |file_path|
|
97
|
+
file_path != index_path
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def create_release_symlink
|
102
|
+
# symlink must be relative in order to be portable (ex: git clone)
|
103
|
+
Dir.chdir(@releases_path) do
|
104
|
+
File.symlink('.', @default_release_name)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
module Bosh::Cli
|
1
|
+
module Bosh::Cli::Versions
|
2
2
|
class VersionFileResolver
|
3
3
|
|
4
4
|
def initialize(storage, blobstore, tmpdir=Dir.tmpdir)
|
@@ -28,14 +28,7 @@ module Bosh::Cli
|
|
28
28
|
tmp_file_path = File.join(@tmpdir, "bosh-tmp-file-#{SecureRandom.uuid}")
|
29
29
|
begin
|
30
30
|
File.open(tmp_file_path, 'w') do |tmp_file|
|
31
|
-
@blobstore.get(blobstore_id, tmp_file)
|
32
|
-
end
|
33
|
-
|
34
|
-
file_sha1 = Digest::SHA1.file(tmp_file_path).hexdigest
|
35
|
-
if file_sha1 != sha1
|
36
|
-
err("SHA1 `#{file_sha1}' of #{desc} from blobstore (id=#{blobstore_id}) " +
|
37
|
-
"does not match expected SHA1 `#{sha1}'" +
|
38
|
-
'please remove it manually and re-create the release')
|
31
|
+
@blobstore.get(blobstore_id, tmp_file, sha1: sha1)
|
39
32
|
end
|
40
33
|
|
41
34
|
@storage.put_file(version, tmp_file_path)
|
@@ -43,7 +36,5 @@ module Bosh::Cli
|
|
43
36
|
FileUtils.rm(tmp_file_path, :force => true)
|
44
37
|
end
|
45
38
|
end
|
46
|
-
|
47
|
-
|
48
39
|
end
|
49
40
|
end
|
@@ -1,5 +1,27 @@
|
|
1
|
-
module Bosh::Cli
|
1
|
+
module Bosh::Cli::Versions
|
2
2
|
class VersionsIndex
|
3
|
+
include Enumerable
|
4
|
+
|
5
|
+
CURRENT_INDEX_VERSION = SemiSemantic::Version.parse('2')
|
6
|
+
|
7
|
+
def self.load_index_yaml(index_path)
|
8
|
+
contents = load_yaml_file(index_path, nil)
|
9
|
+
# Psych.load returns false if file is empty
|
10
|
+
return nil if contents === false
|
11
|
+
unless contents.kind_of?(Hash)
|
12
|
+
raise Bosh::Cli::InvalidIndex, "Invalid versions index data type, #{contents.class} given, Hash expected"
|
13
|
+
end
|
14
|
+
contents
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.write_index_yaml(index_path, contents)
|
18
|
+
unless contents.kind_of?(Hash)
|
19
|
+
raise Bosh::Cli::InvalidIndex, "Invalid versions index data type, #{contents.class} given, Hash expected"
|
20
|
+
end
|
21
|
+
File.open(index_path, 'w') do |f|
|
22
|
+
f.write(Psych.dump(contents))
|
23
|
+
end
|
24
|
+
end
|
3
25
|
|
4
26
|
attr_reader :index_file
|
5
27
|
attr_reader :storage_dir
|
@@ -9,7 +31,7 @@ module Bosh::Cli
|
|
9
31
|
@index_file = File.join(@storage_dir, 'index.yml')
|
10
32
|
|
11
33
|
if File.file?(@index_file)
|
12
|
-
init_index(
|
34
|
+
init_index(VersionsIndex.load_index_yaml(@index_file))
|
13
35
|
else
|
14
36
|
init_index({})
|
15
37
|
end
|
@@ -19,17 +41,8 @@ module Bosh::Cli
|
|
19
41
|
@data['builds'][key]
|
20
42
|
end
|
21
43
|
|
22
|
-
def
|
23
|
-
@data['builds'].
|
24
|
-
end
|
25
|
-
|
26
|
-
def latest_version
|
27
|
-
builds = @data['builds'].values
|
28
|
-
|
29
|
-
return nil if builds.empty?
|
30
|
-
|
31
|
-
version_strings = builds.map { |b| b['version'] }
|
32
|
-
Bosh::Common::Version::ReleaseVersionList.parse(version_strings).latest.to_s
|
44
|
+
def each(&block)
|
45
|
+
@data['builds'].each(&block)
|
33
46
|
end
|
34
47
|
|
35
48
|
def select(&block)
|
@@ -41,15 +54,15 @@ module Bosh::Cli
|
|
41
54
|
version = new_build['version']
|
42
55
|
|
43
56
|
if version.blank?
|
44
|
-
raise InvalidIndex, "Cannot save index entry without a version: `#{new_build}'"
|
57
|
+
raise Bosh::Cli::InvalidIndex, "Cannot save index entry without a version: `#{new_build}'"
|
45
58
|
end
|
46
59
|
|
47
60
|
if @data['builds'][new_key]
|
48
61
|
raise "Trying to add duplicate entry `#{new_key}' into index `#{@index_file}'"
|
49
62
|
end
|
50
63
|
|
51
|
-
|
52
|
-
if build['version'] == version
|
64
|
+
each do |key, build|
|
65
|
+
if key != new_key && build['version'] == version
|
53
66
|
raise "Trying to add duplicate version `#{version}' into index `#{@index_file}'"
|
54
67
|
end
|
55
68
|
end
|
@@ -58,9 +71,7 @@ module Bosh::Cli
|
|
58
71
|
|
59
72
|
@data['builds'][new_key] = new_build
|
60
73
|
|
61
|
-
|
62
|
-
f.write(Psych.dump(@data))
|
63
|
-
end
|
74
|
+
save
|
64
75
|
|
65
76
|
version
|
66
77
|
end
|
@@ -77,9 +88,24 @@ module Bosh::Cli
|
|
77
88
|
|
78
89
|
@data['builds'][key] = new_build
|
79
90
|
|
80
|
-
|
81
|
-
|
91
|
+
save
|
92
|
+
end
|
93
|
+
|
94
|
+
def remove_version(key)
|
95
|
+
build = @data['builds'][key]
|
96
|
+
unless build
|
97
|
+
raise "Cannot remove non-existent entry with key `#{key}'"
|
82
98
|
end
|
99
|
+
|
100
|
+
@data['builds'].delete(key)
|
101
|
+
|
102
|
+
save
|
103
|
+
end
|
104
|
+
|
105
|
+
def find_key_by_version(version)
|
106
|
+
key_and_build = find { |_, build| build['version'] == version }
|
107
|
+
|
108
|
+
key_and_build.first unless key_and_build.nil?
|
83
109
|
end
|
84
110
|
|
85
111
|
def version_strings
|
@@ -90,6 +116,18 @@ module Bosh::Cli
|
|
90
116
|
@data['builds'].to_s
|
91
117
|
end
|
92
118
|
|
119
|
+
def format_version
|
120
|
+
format_version_string = @data['format-version']
|
121
|
+
SemiSemantic::Version.parse(format_version_string)
|
122
|
+
rescue ArgumentError, SemiSemantic::ParseError
|
123
|
+
raise InvalidIndex, "Invalid versions index version in `#{@index_file}', " +
|
124
|
+
"`#{format_version_string}' given, SemiSemantic version expected"
|
125
|
+
end
|
126
|
+
|
127
|
+
def save
|
128
|
+
VersionsIndex.write_index_yaml(@index_file, @data)
|
129
|
+
end
|
130
|
+
|
93
131
|
private
|
94
132
|
|
95
133
|
def create_directories
|
@@ -107,13 +145,9 @@ module Bosh::Cli
|
|
107
145
|
end
|
108
146
|
|
109
147
|
def init_index(data)
|
110
|
-
data
|
111
|
-
|
112
|
-
unless data.kind_of?(Hash)
|
113
|
-
raise InvalidIndex, "Invalid versions index data type, #{data.class} given, Hash expected"
|
114
|
-
end
|
115
|
-
@data = data
|
148
|
+
@data = data || {}
|
116
149
|
@data['builds'] ||= {}
|
150
|
+
@data['format-version'] ||= CURRENT_INDEX_VERSION.to_s
|
117
151
|
end
|
118
152
|
end
|
119
153
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bosh_cli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2682.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- VMware
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-07
|
11
|
+
date: 2014-08-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bosh_common
|
@@ -16,28 +16,28 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 1.
|
19
|
+
version: 1.2682.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.
|
26
|
+
version: 1.2682.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: bosh-template
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 1.
|
33
|
+
version: 1.2682.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.
|
40
|
+
version: 1.2682.0
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: json_pure
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -114,14 +114,14 @@ dependencies:
|
|
114
114
|
requirements:
|
115
115
|
- - "~>"
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version: 1.
|
117
|
+
version: 1.2682.0
|
118
118
|
type: :runtime
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
122
|
- - "~>"
|
123
123
|
- !ruby/object:Gem::Version
|
124
|
-
version: 1.
|
124
|
+
version: 1.2682.0
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
126
|
name: net-ssh
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -194,7 +194,7 @@ dependencies:
|
|
194
194
|
version: 0.5.4
|
195
195
|
description: |-
|
196
196
|
BOSH CLI
|
197
|
-
|
197
|
+
4f6636
|
198
198
|
email: support@cloudfoundry.com
|
199
199
|
executables:
|
200
200
|
- bosh
|
@@ -232,7 +232,13 @@ files:
|
|
232
232
|
- lib/cli/commands/misc.rb
|
233
233
|
- lib/cli/commands/package.rb
|
234
234
|
- lib/cli/commands/property_management.rb
|
235
|
-
- lib/cli/commands/release.rb
|
235
|
+
- lib/cli/commands/release/create_release.rb
|
236
|
+
- lib/cli/commands/release/delete_release.rb
|
237
|
+
- lib/cli/commands/release/init_release.rb
|
238
|
+
- lib/cli/commands/release/list_releases.rb
|
239
|
+
- lib/cli/commands/release/reset_release.rb
|
240
|
+
- lib/cli/commands/release/upload_release.rb
|
241
|
+
- lib/cli/commands/release/verify_release.rb
|
236
242
|
- lib/cli/commands/snapshot.rb
|
237
243
|
- lib/cli/commands/ssh.rb
|
238
244
|
- lib/cli/commands/stemcell.rb
|
@@ -270,6 +276,7 @@ files:
|
|
270
276
|
- lib/cli/release_tarball.rb
|
271
277
|
- lib/cli/resurrection.rb
|
272
278
|
- lib/cli/runner.rb
|
279
|
+
- lib/cli/source_control/git_ignore.rb
|
273
280
|
- lib/cli/stemcell.rb
|
274
281
|
- lib/cli/task_tracking.rb
|
275
282
|
- lib/cli/task_tracking/event_log_renderer.rb
|
@@ -283,7 +290,9 @@ files:
|
|
283
290
|
- lib/cli/validation.rb
|
284
291
|
- lib/cli/version.rb
|
285
292
|
- lib/cli/versions/local_version_storage.rb
|
293
|
+
- lib/cli/versions/multi_release_support.rb
|
286
294
|
- lib/cli/versions/release_versions_index.rb
|
295
|
+
- lib/cli/versions/releases_dir_migrator.rb
|
287
296
|
- lib/cli/versions/version_file_resolver.rb
|
288
297
|
- lib/cli/versions/versions_index.rb
|
289
298
|
- lib/cli/vm_state.rb
|
data/lib/cli/commands/release.rb
DELETED
@@ -1,684 +0,0 @@
|
|
1
|
-
module Bosh::Cli::Command
|
2
|
-
class Release < Base
|
3
|
-
DEFAULT_RELEASE_NAME = 'bosh-release'
|
4
|
-
|
5
|
-
include Bosh::Cli::DependencyHelper
|
6
|
-
|
7
|
-
# bosh init release
|
8
|
-
usage 'init release'
|
9
|
-
desc 'Initialize release directory'
|
10
|
-
option '--git', 'initialize git repository'
|
11
|
-
def init(base = nil)
|
12
|
-
if base
|
13
|
-
FileUtils.mkdir_p(base)
|
14
|
-
Dir.chdir(base)
|
15
|
-
end
|
16
|
-
|
17
|
-
err('Release already initialized') if in_release_dir?
|
18
|
-
git_init if options[:git]
|
19
|
-
|
20
|
-
%w[config jobs packages src blobs].each do |dir|
|
21
|
-
FileUtils.mkdir(dir)
|
22
|
-
end
|
23
|
-
|
24
|
-
# Initialize an empty blobs index
|
25
|
-
File.open(File.join('config', 'blobs.yml'), 'w') do |f|
|
26
|
-
Psych.dump({}, f)
|
27
|
-
end
|
28
|
-
|
29
|
-
say('Release directory initialized'.make_green)
|
30
|
-
end
|
31
|
-
|
32
|
-
# bosh create release
|
33
|
-
usage 'create release'
|
34
|
-
desc 'Create release (assumes current directory to be a release repository)'
|
35
|
-
option '--force', 'bypass git dirty state check'
|
36
|
-
option '--final', 'create final release'
|
37
|
-
option '--with-tarball', 'create release tarball'
|
38
|
-
option '--dry-run', 'stop before writing release manifest'
|
39
|
-
option '--version VERSION', 'specify a custom version number (ex: 1.0.0 or 1.0-beta.2+dev.10)'
|
40
|
-
def create(manifest_file = nil)
|
41
|
-
check_if_release_dir
|
42
|
-
|
43
|
-
if manifest_file && File.file?(manifest_file)
|
44
|
-
if options[:version]
|
45
|
-
err('Cannot specify a custom version number when creating from a manifest. The manifest already specifies a version.'.make_red)
|
46
|
-
end
|
47
|
-
|
48
|
-
say('Recreating release from the manifest')
|
49
|
-
Bosh::Cli::ReleaseCompiler.compile(manifest_file, release.blobstore)
|
50
|
-
release_filename = manifest_file
|
51
|
-
else
|
52
|
-
version = options[:version]
|
53
|
-
version = Bosh::Common::Version::ReleaseVersion.parse(version).to_s unless version.nil?
|
54
|
-
|
55
|
-
release_filename = create_from_spec(version)
|
56
|
-
end
|
57
|
-
|
58
|
-
if release_filename
|
59
|
-
release.latest_release_filename = release_filename
|
60
|
-
release.save_config
|
61
|
-
end
|
62
|
-
rescue SemiSemantic::ParseError
|
63
|
-
err("Invalid version: `#{version}'. Please specify a valid version (ex: 1.0.0 or 1.0-beta.2+dev.10).".make_red)
|
64
|
-
rescue Bosh::Cli::ReleaseVersionError => e
|
65
|
-
err(e.message.make_red)
|
66
|
-
end
|
67
|
-
|
68
|
-
# bosh verify release
|
69
|
-
usage 'verify release'
|
70
|
-
desc 'Verify release'
|
71
|
-
def verify(tarball_path)
|
72
|
-
tarball = Bosh::Cli::ReleaseTarball.new(tarball_path)
|
73
|
-
|
74
|
-
nl
|
75
|
-
say('Verifying release...')
|
76
|
-
tarball.validate
|
77
|
-
nl
|
78
|
-
|
79
|
-
if tarball.valid?
|
80
|
-
say("`#{tarball_path}' is a valid release".make_green)
|
81
|
-
else
|
82
|
-
say('Validation errors:'.make_red)
|
83
|
-
tarball.errors.each do |error|
|
84
|
-
say("- #{error}")
|
85
|
-
end
|
86
|
-
err("`#{tarball_path}' is not a valid release".make_red)
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
usage 'upload release'
|
91
|
-
desc 'Upload release (release_file can be a local file or a remote URI)'
|
92
|
-
option '--rebase',
|
93
|
-
'Rebases this release onto the latest version',
|
94
|
-
'known by director (discards local job/package',
|
95
|
-
'versions in favor of versions assigned by director)'
|
96
|
-
option '--skip-if-exists', 'skips upload if release already exists'
|
97
|
-
def upload(release_file = nil)
|
98
|
-
auth_required
|
99
|
-
|
100
|
-
upload_options = {
|
101
|
-
:rebase => options[:rebase],
|
102
|
-
:repack => true,
|
103
|
-
:skip_if_exists => options[:skip_if_exists],
|
104
|
-
}
|
105
|
-
|
106
|
-
if release_file.nil?
|
107
|
-
check_if_release_dir
|
108
|
-
release_file = release.latest_release_filename
|
109
|
-
if release_file.nil?
|
110
|
-
err('The information about latest generated release is missing, please provide release filename')
|
111
|
-
end
|
112
|
-
unless confirmed?("Upload release `#{File.basename(release_file).make_green}' to `#{target_name.make_green}'")
|
113
|
-
err('Canceled upload')
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
if release_file =~ /^#{URI::regexp}$/
|
118
|
-
upload_remote_release(release_file, upload_options)
|
119
|
-
else
|
120
|
-
unless File.exist?(release_file)
|
121
|
-
err("Release file doesn't exist")
|
122
|
-
end
|
123
|
-
|
124
|
-
file_type = `file --mime-type -b '#{release_file}'`
|
125
|
-
|
126
|
-
if file_type =~ /text\/(plain|yaml)/
|
127
|
-
upload_manifest(release_file, upload_options)
|
128
|
-
else
|
129
|
-
upload_tarball(release_file, upload_options)
|
130
|
-
end
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
usage 'reset release'
|
135
|
-
desc 'Reset dev release'
|
136
|
-
def reset
|
137
|
-
check_if_release_dir
|
138
|
-
|
139
|
-
say('Your dev release environment will be completely reset'.make_red)
|
140
|
-
if confirmed?
|
141
|
-
say('Removing dev_builds index...')
|
142
|
-
FileUtils.rm_rf('.dev_builds')
|
143
|
-
say('Clearing dev name...')
|
144
|
-
release.dev_name = nil
|
145
|
-
release.save_config
|
146
|
-
say('Removing dev tarballs...')
|
147
|
-
FileUtils.rm_rf('dev_releases')
|
148
|
-
|
149
|
-
say('Release has been reset'.make_green)
|
150
|
-
else
|
151
|
-
say('Canceled')
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
|
-
usage 'releases'
|
156
|
-
desc 'Show the list of available releases'
|
157
|
-
option '--jobs', 'include job templates'
|
158
|
-
def list
|
159
|
-
auth_required
|
160
|
-
releases = director.list_releases.sort do |r1, r2|
|
161
|
-
r1['name'] <=> r2['name']
|
162
|
-
end
|
163
|
-
|
164
|
-
err('No releases') if releases.empty?
|
165
|
-
|
166
|
-
currently_deployed = false
|
167
|
-
uncommited_changes = false
|
168
|
-
if releases.first.has_key? 'release_versions'
|
169
|
-
releases_table = build_releases_table(releases, options)
|
170
|
-
currently_deployed, uncommited_changes = release_version_details(releases)
|
171
|
-
elsif releases.first.has_key? 'versions'
|
172
|
-
releases_table = build_releases_table_for_old_director(releases)
|
173
|
-
currently_deployed, uncommited_changes = release_version_details_for_old_director(releases)
|
174
|
-
end
|
175
|
-
|
176
|
-
nl
|
177
|
-
say(releases_table.render)
|
178
|
-
|
179
|
-
say('(*) Currently deployed') if currently_deployed
|
180
|
-
say('(+) Uncommitted changes') if uncommited_changes
|
181
|
-
nl
|
182
|
-
say('Releases total: %d' % releases.size)
|
183
|
-
end
|
184
|
-
|
185
|
-
usage 'delete release'
|
186
|
-
desc 'Delete release (or a particular release version)'
|
187
|
-
option '--force', 'ignore errors during deletion'
|
188
|
-
def delete(name, version = nil)
|
189
|
-
auth_required
|
190
|
-
force = !!options[:force]
|
191
|
-
|
192
|
-
desc = "#{name}"
|
193
|
-
desc << "/#{version}" if version
|
194
|
-
|
195
|
-
if force
|
196
|
-
say("Deleting `#{desc}' (FORCED DELETE, WILL IGNORE ERRORS)".make_red)
|
197
|
-
else
|
198
|
-
say("Deleting `#{desc}'".make_red)
|
199
|
-
end
|
200
|
-
|
201
|
-
if confirmed?
|
202
|
-
status, task_id = director.delete_release(name, force: force, version: version)
|
203
|
-
task_report(status, task_id, "Deleted `#{desc}'")
|
204
|
-
else
|
205
|
-
say('Canceled deleting release'.make_green)
|
206
|
-
end
|
207
|
-
end
|
208
|
-
|
209
|
-
private
|
210
|
-
|
211
|
-
def upload_manifest(manifest_path, upload_options = {})
|
212
|
-
package_matches = match_remote_packages(File.read(manifest_path))
|
213
|
-
|
214
|
-
find_release_dir(manifest_path)
|
215
|
-
|
216
|
-
blobstore = release.blobstore
|
217
|
-
tmpdir = Dir.mktmpdir
|
218
|
-
|
219
|
-
compiler = Bosh::Cli::ReleaseCompiler.new(manifest_path, blobstore, package_matches)
|
220
|
-
need_repack = true
|
221
|
-
|
222
|
-
unless compiler.exists?
|
223
|
-
compiler.tarball_path = File.join(tmpdir, 'release.tgz')
|
224
|
-
compiler.compile
|
225
|
-
need_repack = false
|
226
|
-
end
|
227
|
-
|
228
|
-
upload_options[:repack] = need_repack
|
229
|
-
upload_tarball(compiler.tarball_path, upload_options)
|
230
|
-
end
|
231
|
-
|
232
|
-
def upload_tarball(tarball_path, upload_options = {})
|
233
|
-
tarball = Bosh::Cli::ReleaseTarball.new(tarball_path)
|
234
|
-
# Trying to repack release by default
|
235
|
-
repack = upload_options[:repack]
|
236
|
-
rebase = upload_options[:rebase]
|
237
|
-
|
238
|
-
say("\nVerifying release...")
|
239
|
-
tarball.validate(:allow_sparse => true)
|
240
|
-
nl
|
241
|
-
|
242
|
-
unless tarball.valid?
|
243
|
-
err('Release is invalid, please fix, verify and upload again')
|
244
|
-
end
|
245
|
-
|
246
|
-
if should_convert_to_old_format?(tarball.version)
|
247
|
-
msg = "You are using CLI > 1.2579.0 with a director that doesn't support " +
|
248
|
-
'the new version format you are using. Upgrade your ' +
|
249
|
-
'director to match the version of your CLI or downgrade your ' +
|
250
|
-
'CLI to 1.2579.0 to avoid versioning mismatch issues.'
|
251
|
-
|
252
|
-
say(msg.make_yellow)
|
253
|
-
tarball_path = tarball.convert_to_old_format
|
254
|
-
end
|
255
|
-
|
256
|
-
remote_release = get_remote_release(tarball.release_name) rescue nil
|
257
|
-
if remote_release && !rebase
|
258
|
-
if remote_release['versions'].include?(tarball.version)
|
259
|
-
if upload_options[:skip_if_exists]
|
260
|
-
say("Release `#{tarball.release_name}/#{tarball.version}' already exists. Skipping upload.")
|
261
|
-
return
|
262
|
-
else
|
263
|
-
err('This release version has already been uploaded')
|
264
|
-
end
|
265
|
-
end
|
266
|
-
end
|
267
|
-
|
268
|
-
begin
|
269
|
-
if repack
|
270
|
-
package_matches = match_remote_packages(tarball.manifest)
|
271
|
-
|
272
|
-
say('Checking if can repack release for faster upload...')
|
273
|
-
repacked_path = tarball.repack(package_matches)
|
274
|
-
|
275
|
-
if repacked_path.nil?
|
276
|
-
say('Uploading the whole release'.make_green)
|
277
|
-
else
|
278
|
-
say("Release repacked (new size is #{pretty_size(repacked_path)})".make_green)
|
279
|
-
tarball_path = repacked_path
|
280
|
-
end
|
281
|
-
end
|
282
|
-
rescue Bosh::Cli::DirectorError
|
283
|
-
# It's OK for director to choke on getting
|
284
|
-
# a release info (think new releases)
|
285
|
-
end
|
286
|
-
|
287
|
-
if rebase
|
288
|
-
say("Uploading release (#{'will be rebased'.make_yellow})")
|
289
|
-
status, task_id = director.rebase_release(tarball_path)
|
290
|
-
task_report(status, task_id, 'Release rebased')
|
291
|
-
else
|
292
|
-
say("\nUploading release\n")
|
293
|
-
status, task_id = director.upload_release(tarball_path)
|
294
|
-
task_report(status, task_id, 'Release uploaded')
|
295
|
-
end
|
296
|
-
end
|
297
|
-
|
298
|
-
def upload_remote_release(release_location, upload_options = {})
|
299
|
-
nl
|
300
|
-
if upload_options[:rebase]
|
301
|
-
say("Using remote release `#{release_location}' (#{'will be rebased'.make_yellow})")
|
302
|
-
status, task_id = director.rebase_remote_release(release_location)
|
303
|
-
task_report(status, task_id, 'Release rebased')
|
304
|
-
else
|
305
|
-
say("Using remote release `#{release_location}'")
|
306
|
-
status, task_id = director.upload_remote_release(release_location)
|
307
|
-
task_report(status, task_id, 'Release uploaded')
|
308
|
-
end
|
309
|
-
end
|
310
|
-
|
311
|
-
def create_from_spec(version)
|
312
|
-
final = options[:final]
|
313
|
-
force = options[:force]
|
314
|
-
manifest_only = !options[:with_tarball]
|
315
|
-
dry_run = options[:dry_run]
|
316
|
-
|
317
|
-
err("Can't create final release without blobstore secret") if final && !release.has_blobstore_secret?
|
318
|
-
|
319
|
-
dirty_blob_check(force)
|
320
|
-
|
321
|
-
raise_dirty_state_error if dirty_state? && !force
|
322
|
-
|
323
|
-
if final
|
324
|
-
confirm_final_release(dry_run)
|
325
|
-
save_final_release_name if release.final_name.blank?
|
326
|
-
header('Building FINAL release'.make_green)
|
327
|
-
else
|
328
|
-
save_dev_release_name if release.dev_name.blank?
|
329
|
-
header('Building DEV release'.make_green)
|
330
|
-
end
|
331
|
-
|
332
|
-
header('Building packages')
|
333
|
-
packages = build_packages(dry_run, final)
|
334
|
-
|
335
|
-
header('Building jobs')
|
336
|
-
jobs = build_jobs(packages.map(&:name), dry_run, final)
|
337
|
-
|
338
|
-
header('Building release')
|
339
|
-
release_builder = build_release(dry_run, final, jobs, manifest_only, packages, version)
|
340
|
-
|
341
|
-
header('Release summary')
|
342
|
-
show_summary(release_builder)
|
343
|
-
nl
|
344
|
-
|
345
|
-
return nil if dry_run
|
346
|
-
|
347
|
-
say("Release version: #{release_builder.version.to_s.make_green}")
|
348
|
-
say("Release manifest: #{release_builder.manifest_path.make_green}")
|
349
|
-
|
350
|
-
unless manifest_only
|
351
|
-
say("Release tarball (#{pretty_size(release_builder.tarball_path)}): " +
|
352
|
-
release_builder.tarball_path.make_green)
|
353
|
-
end
|
354
|
-
|
355
|
-
release.save_config
|
356
|
-
|
357
|
-
release_builder.manifest_path
|
358
|
-
end
|
359
|
-
|
360
|
-
def confirm_final_release(dry_run)
|
361
|
-
confirmed = non_interactive? || agree("Are you sure you want to generate #{'final'.make_red} version? ")
|
362
|
-
if !dry_run && !confirmed
|
363
|
-
say('Canceled release generation'.make_green)
|
364
|
-
exit(1)
|
365
|
-
end
|
366
|
-
end
|
367
|
-
|
368
|
-
def dirty_blob_check(force)
|
369
|
-
blob_manager.sync
|
370
|
-
if blob_manager.dirty?
|
371
|
-
blob_manager.print_status
|
372
|
-
if force
|
373
|
-
say("Proceeding with dirty blobs as '--force' is given".make_red)
|
374
|
-
else
|
375
|
-
err("Please use '--force' or upload new blobs")
|
376
|
-
end
|
377
|
-
end
|
378
|
-
end
|
379
|
-
|
380
|
-
def build_packages(dry_run, final)
|
381
|
-
packages = Bosh::Cli::PackageBuilder.discover(
|
382
|
-
work_dir,
|
383
|
-
:final => final,
|
384
|
-
:blobstore => release.blobstore,
|
385
|
-
:dry_run => dry_run
|
386
|
-
)
|
387
|
-
|
388
|
-
packages.each do |package|
|
389
|
-
say("Building #{package.name.make_green}...")
|
390
|
-
package.build
|
391
|
-
nl
|
392
|
-
end
|
393
|
-
|
394
|
-
if packages.size > 0
|
395
|
-
package_index = packages.inject({}) do |index, package|
|
396
|
-
index[package.name] = package.dependencies
|
397
|
-
index
|
398
|
-
end
|
399
|
-
sorted_packages = tsort_packages(package_index)
|
400
|
-
header('Resolving dependencies')
|
401
|
-
say('Dependencies resolved, correct build order is:')
|
402
|
-
sorted_packages.each do |package_name|
|
403
|
-
say('- %s' % [package_name])
|
404
|
-
end
|
405
|
-
nl
|
406
|
-
end
|
407
|
-
|
408
|
-
packages
|
409
|
-
end
|
410
|
-
|
411
|
-
def build_release(dry_run, final, jobs, manifest_only, packages, version)
|
412
|
-
release_builder = Bosh::Cli::ReleaseBuilder.new(release, packages, jobs, final: final,
|
413
|
-
commit_hash: commit_hash, version: version,
|
414
|
-
uncommitted_changes: dirty_state?)
|
415
|
-
|
416
|
-
unless dry_run
|
417
|
-
if manifest_only
|
418
|
-
release_builder.build(:generate_tarball => false)
|
419
|
-
else
|
420
|
-
release_builder.build(:generate_tarball => true)
|
421
|
-
end
|
422
|
-
end
|
423
|
-
|
424
|
-
release_builder
|
425
|
-
end
|
426
|
-
|
427
|
-
def build_jobs(built_package_names, dry_run, final)
|
428
|
-
jobs = Bosh::Cli::JobBuilder.discover(
|
429
|
-
work_dir,
|
430
|
-
:final => final,
|
431
|
-
:blobstore => release.blobstore,
|
432
|
-
:dry_run => dry_run,
|
433
|
-
:package_names => built_package_names
|
434
|
-
)
|
435
|
-
|
436
|
-
jobs.each do |job|
|
437
|
-
say("Building #{job.name.make_green}...")
|
438
|
-
job.build
|
439
|
-
nl
|
440
|
-
end
|
441
|
-
|
442
|
-
jobs
|
443
|
-
end
|
444
|
-
|
445
|
-
def save_final_release_name
|
446
|
-
release.final_name = DEFAULT_RELEASE_NAME
|
447
|
-
if interactive?
|
448
|
-
release.final_name = ask('Please enter final release name: ').to_s
|
449
|
-
err('Canceled release creation, no name given') if release.final_name.blank?
|
450
|
-
end
|
451
|
-
release.save_config
|
452
|
-
end
|
453
|
-
|
454
|
-
def save_dev_release_name
|
455
|
-
if interactive?
|
456
|
-
release.dev_name = ask('Please enter development release name: ') do |q|
|
457
|
-
q.default = release.final_name if release.final_name
|
458
|
-
end.to_s
|
459
|
-
err('Canceled release creation, no name given') if release.dev_name.blank?
|
460
|
-
else
|
461
|
-
release.dev_name = release.final_name ? release.final_name : DEFAULT_RELEASE_NAME
|
462
|
-
end
|
463
|
-
release.save_config
|
464
|
-
end
|
465
|
-
|
466
|
-
def git_init
|
467
|
-
out = %x{git init 2>&1}
|
468
|
-
if $? != 0
|
469
|
-
say("error running 'git init':\n#{out}")
|
470
|
-
else
|
471
|
-
File.open('.gitignore', 'w') do |f|
|
472
|
-
f << <<-EOS.gsub(/^\s{10}/, '')
|
473
|
-
config/dev.yml
|
474
|
-
config/private.yml
|
475
|
-
releases/*.tgz
|
476
|
-
dev_releases
|
477
|
-
.blobs
|
478
|
-
blobs
|
479
|
-
.dev_builds
|
480
|
-
.idea
|
481
|
-
.DS_Store
|
482
|
-
.final_builds/jobs/**/*.tgz
|
483
|
-
.final_builds/packages/**/*.tgz
|
484
|
-
*.swp
|
485
|
-
*~
|
486
|
-
*#
|
487
|
-
#*
|
488
|
-
EOS
|
489
|
-
end
|
490
|
-
end
|
491
|
-
rescue Errno::ENOENT
|
492
|
-
say("Unable to run 'git init'".make_red)
|
493
|
-
end
|
494
|
-
|
495
|
-
# if we aren't already in a release directory, try going up two levels
|
496
|
-
# to see if that is a release directory, and then use that as the base
|
497
|
-
def find_release_dir(manifest_path)
|
498
|
-
unless in_release_dir?
|
499
|
-
dir = File.expand_path('../..', manifest_path)
|
500
|
-
Dir.chdir(dir)
|
501
|
-
if in_release_dir?
|
502
|
-
@release = Bosh::Cli::Release.new(dir)
|
503
|
-
end
|
504
|
-
end
|
505
|
-
|
506
|
-
end
|
507
|
-
|
508
|
-
def show_summary(builder)
|
509
|
-
packages_table = table do |t|
|
510
|
-
t.headings = %w(Name Version Notes)
|
511
|
-
builder.packages.each do |package|
|
512
|
-
t << artefact_summary(package)
|
513
|
-
end
|
514
|
-
end
|
515
|
-
|
516
|
-
jobs_table = table do |t|
|
517
|
-
t.headings = %w(Name Version Notes)
|
518
|
-
builder.jobs.each do |job|
|
519
|
-
t << artefact_summary(job)
|
520
|
-
end
|
521
|
-
end
|
522
|
-
|
523
|
-
say('Packages')
|
524
|
-
say(packages_table)
|
525
|
-
nl
|
526
|
-
say('Jobs')
|
527
|
-
say(jobs_table)
|
528
|
-
|
529
|
-
affected_jobs = builder.affected_jobs
|
530
|
-
|
531
|
-
if affected_jobs.size > 0
|
532
|
-
nl
|
533
|
-
say('Jobs affected by changes in this release')
|
534
|
-
|
535
|
-
affected_jobs_table = table do |t|
|
536
|
-
t.headings = %w(Name Version)
|
537
|
-
affected_jobs.each do |job|
|
538
|
-
t << [job.name, job.version]
|
539
|
-
end
|
540
|
-
end
|
541
|
-
|
542
|
-
say(affected_jobs_table)
|
543
|
-
end
|
544
|
-
end
|
545
|
-
|
546
|
-
def artefact_summary(artefact)
|
547
|
-
result = []
|
548
|
-
result << artefact.name
|
549
|
-
result << artefact.version
|
550
|
-
result << artefact.notes.join(', ')
|
551
|
-
result
|
552
|
-
end
|
553
|
-
|
554
|
-
def get_remote_release(name)
|
555
|
-
release = director.get_release(name)
|
556
|
-
|
557
|
-
unless release.is_a?(Hash) &&
|
558
|
-
release.has_key?('jobs') &&
|
559
|
-
release.has_key?('packages')
|
560
|
-
raise Bosh::Cli::DirectorError,
|
561
|
-
'Cannot find version, jobs and packages info in the director response, maybe old director?'
|
562
|
-
end
|
563
|
-
|
564
|
-
release
|
565
|
-
end
|
566
|
-
|
567
|
-
def match_remote_packages(manifest_yaml)
|
568
|
-
director.match_packages(manifest_yaml)
|
569
|
-
rescue Bosh::Cli::DirectorError
|
570
|
-
msg = "You are using CLI >= 0.20 with director that doesn't support " +
|
571
|
-
"package matches.\nThis will result in uploading all packages " +
|
572
|
-
"and jobs to your director.\nIt is recommended to update your " +
|
573
|
-
'director or downgrade your CLI to 0.19.6'
|
574
|
-
|
575
|
-
say(msg.make_yellow)
|
576
|
-
exit(1) unless confirmed?
|
577
|
-
end
|
578
|
-
|
579
|
-
def build_releases_table_for_old_director(releases)
|
580
|
-
table do |t|
|
581
|
-
t.headings = 'Name', 'Versions'
|
582
|
-
releases.each do |release|
|
583
|
-
versions = release['versions'].sort { |v1, v2|
|
584
|
-
Bosh::Common::Version::ReleaseVersion.parse_and_compare(v1, v2)
|
585
|
-
}.map { |v| ((release['in_use'] || []).include?(v)) ? "#{v}*" : v }
|
586
|
-
|
587
|
-
t << [release['name'], versions.join(', ')]
|
588
|
-
end
|
589
|
-
end
|
590
|
-
end
|
591
|
-
|
592
|
-
# Builds table of release information
|
593
|
-
# Default headings: "Name", "Versions", "Commit Hash"
|
594
|
-
# Extra headings: options[:job] => "Jobs"
|
595
|
-
def build_releases_table(releases, options = {})
|
596
|
-
show_jobs = options[:jobs]
|
597
|
-
table do |t|
|
598
|
-
t.headings = 'Name', 'Versions', 'Commit Hash'
|
599
|
-
t.headings << 'Jobs' if show_jobs
|
600
|
-
releases.each do |release|
|
601
|
-
versions, commit_hashes = formatted_versions(release).transpose
|
602
|
-
row = [release['name'], versions.join("\n"), commit_hashes.join("\n")]
|
603
|
-
if show_jobs
|
604
|
-
jobs = formatted_jobs(release).transpose
|
605
|
-
row << jobs.join("\n")
|
606
|
-
end
|
607
|
-
t << row
|
608
|
-
end
|
609
|
-
end
|
610
|
-
end
|
611
|
-
|
612
|
-
def formatted_versions(release)
|
613
|
-
sort_versions(release['release_versions']).map { |v| formatted_version_and_commit_hash(v) }
|
614
|
-
end
|
615
|
-
|
616
|
-
def sort_versions(versions)
|
617
|
-
versions.sort { |v1, v2| Bosh::Common::Version::ReleaseVersion.parse_and_compare(v1['version'], v2['version']) }
|
618
|
-
end
|
619
|
-
|
620
|
-
def formatted_version_and_commit_hash(version)
|
621
|
-
version_number = version['version'] + (version['currently_deployed'] ? '*' : '')
|
622
|
-
commit_hash = version['commit_hash'] + (version['uncommitted_changes'] ? '+' : '')
|
623
|
-
[version_number, commit_hash]
|
624
|
-
end
|
625
|
-
|
626
|
-
def formatted_jobs(release)
|
627
|
-
sort_versions(release['release_versions']).map do |v|
|
628
|
-
if job_names = v['job_names']
|
629
|
-
[job_names.join(', ')]
|
630
|
-
else
|
631
|
-
['n/a '] # with enough whitespace to match "Jobs" header
|
632
|
-
end
|
633
|
-
end
|
634
|
-
end
|
635
|
-
|
636
|
-
def commit_hash
|
637
|
-
status = Bosh::Exec.sh('git show-ref --head --hash=8 2> /dev/null')
|
638
|
-
status.output.split.first
|
639
|
-
rescue Bosh::Exec::Error => e
|
640
|
-
'00000000'
|
641
|
-
end
|
642
|
-
|
643
|
-
def release_version_details(releases)
|
644
|
-
currently_deployed = false
|
645
|
-
uncommitted_changes = false
|
646
|
-
releases.each do |release|
|
647
|
-
release['release_versions'].each do |version|
|
648
|
-
currently_deployed ||= version['currently_deployed']
|
649
|
-
uncommitted_changes ||= version['uncommitted_changes']
|
650
|
-
if currently_deployed && uncommitted_changes
|
651
|
-
return true, true
|
652
|
-
end
|
653
|
-
end
|
654
|
-
end
|
655
|
-
return currently_deployed, uncommitted_changes
|
656
|
-
end
|
657
|
-
|
658
|
-
def release_version_details_for_old_director(releases)
|
659
|
-
currently_deployed = false
|
660
|
-
# old director did not support uncommitted changes
|
661
|
-
uncommitted_changes = false
|
662
|
-
releases.each do |release|
|
663
|
-
currently_deployed ||= release['in_use'].any?
|
664
|
-
if currently_deployed
|
665
|
-
return true, uncommitted_changes
|
666
|
-
end
|
667
|
-
end
|
668
|
-
return currently_deployed, uncommitted_changes
|
669
|
-
end
|
670
|
-
|
671
|
-
def should_convert_to_old_format?(version)
|
672
|
-
director_version = director.get_status['version']
|
673
|
-
new_format_director_version = '1.2580.0'
|
674
|
-
if Bosh::Common::Version::BoshVersion.parse(director_version) >=
|
675
|
-
Bosh::Common::Version::BoshVersion.parse(new_format_director_version)
|
676
|
-
return false
|
677
|
-
end
|
678
|
-
|
679
|
-
old_format = Bosh::Common::Version::ReleaseVersion.parse(version).to_old_format
|
680
|
-
old_format && version != old_format
|
681
|
-
end
|
682
|
-
|
683
|
-
end
|
684
|
-
end
|