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.
@@ -0,0 +1,27 @@
1
+ module Bosh::Cli::Command
2
+ module Release
3
+ class ResetRelease < Base
4
+
5
+ usage 'reset release'
6
+ desc 'Reset dev release'
7
+ def reset
8
+ check_if_release_dir
9
+
10
+ say('Your dev release environment will be completely reset'.make_red)
11
+ if confirmed?
12
+ say('Removing dev_builds index...')
13
+ FileUtils.rm_rf('.dev_builds')
14
+ say('Clearing dev name...')
15
+ release.dev_name = nil
16
+ release.save_config
17
+ say('Removing dev tarballs...')
18
+ FileUtils.rm_rf('dev_releases')
19
+
20
+ say('Release has been reset'.make_green)
21
+ else
22
+ say('Canceled')
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,208 @@
1
+ module Bosh::Cli::Command
2
+ module Release
3
+ class UploadRelease < Base
4
+
5
+ usage 'upload release'
6
+ desc 'Upload release (release_file can be a local file or a remote URI)'
7
+ option '--rebase',
8
+ 'Rebases this release onto the latest version',
9
+ 'known by director (discards local job/package',
10
+ 'versions in favor of versions assigned by director)'
11
+ option '--skip-if-exists', 'skips upload if release already exists'
12
+ def upload(release_file = nil)
13
+ auth_required
14
+
15
+ upload_options = {
16
+ :rebase => options[:rebase],
17
+ :repack => true,
18
+ :skip_if_exists => options[:skip_if_exists],
19
+ }
20
+
21
+ if release_file.nil?
22
+ check_if_release_dir
23
+ release_file = release.latest_release_filename
24
+ if release_file.nil?
25
+ err('The information about latest generated release is missing, please provide release filename')
26
+ end
27
+ unless confirmed?("Upload release `#{File.basename(release_file).make_green}' to `#{target_name.make_green}'")
28
+ err('Canceled upload')
29
+ end
30
+ end
31
+
32
+ if release_file =~ /^#{URI::regexp}$/
33
+ upload_remote_release(release_file, upload_options)
34
+ else
35
+ unless File.exist?(release_file)
36
+ err("Release file doesn't exist")
37
+ end
38
+
39
+ file_type = `file --mime-type -b '#{release_file}'`
40
+
41
+ if file_type =~ /text\/(plain|yaml)/
42
+ upload_manifest(release_file, upload_options)
43
+ else
44
+ upload_tarball(release_file, upload_options)
45
+ end
46
+ end
47
+ end
48
+
49
+ private
50
+
51
+ def upload_manifest(manifest_path, upload_options = {})
52
+ package_matches = match_remote_packages(File.read(manifest_path))
53
+
54
+ find_release_dir(manifest_path)
55
+
56
+ blobstore = release.blobstore
57
+ tmpdir = Dir.mktmpdir
58
+
59
+ compiler = Bosh::Cli::ReleaseCompiler.new(manifest_path, blobstore, package_matches)
60
+ need_repack = true
61
+
62
+ unless compiler.exists?
63
+ compiler.tarball_path = File.join(tmpdir, 'release.tgz')
64
+ compiler.compile
65
+ need_repack = false
66
+ end
67
+
68
+ upload_options[:repack] = need_repack
69
+ upload_tarball(compiler.tarball_path, upload_options)
70
+ end
71
+
72
+ def upload_tarball(tarball_path, upload_options = {})
73
+ tarball = Bosh::Cli::ReleaseTarball.new(tarball_path)
74
+ # Trying to repack release by default
75
+ repack = upload_options[:repack]
76
+ rebase = upload_options[:rebase]
77
+
78
+ say("\nVerifying release...")
79
+ tarball.validate(:allow_sparse => true)
80
+ nl
81
+
82
+ unless tarball.valid?
83
+ err('Release is invalid, please fix, verify and upload again')
84
+ end
85
+
86
+ if should_convert_to_old_format?(tarball.version)
87
+ msg = "You are using CLI > 1.2579.0 with a director that doesn't support " +
88
+ 'the new version format you are using. Upgrade your ' +
89
+ 'director to match the version of your CLI or downgrade your ' +
90
+ 'CLI to 1.2579.0 to avoid versioning mismatch issues.'
91
+
92
+ say(msg.make_yellow)
93
+ tarball_path = tarball.convert_to_old_format
94
+ end
95
+
96
+ remote_release = get_remote_release(tarball.release_name) rescue nil
97
+ if remote_release && !rebase
98
+ version = if new_director?
99
+ Bosh::Common::Version::ReleaseVersion.parse(tarball.version)
100
+ else
101
+ tarball.version
102
+ end
103
+ if remote_release['versions'].include?(version.to_s)
104
+ if upload_options[:skip_if_exists]
105
+ say("Release `#{tarball.release_name}/#{version}' already exists. Skipping upload.")
106
+ return
107
+ else
108
+ err('This release version has already been uploaded')
109
+ end
110
+ end
111
+ end
112
+
113
+ begin
114
+ if repack
115
+ package_matches = match_remote_packages(tarball.manifest)
116
+
117
+ say('Checking if can repack release for faster upload...')
118
+ repacked_path = tarball.repack(package_matches)
119
+
120
+ if repacked_path.nil?
121
+ say('Uploading the whole release'.make_green)
122
+ else
123
+ say("Release repacked (new size is #{pretty_size(repacked_path)})".make_green)
124
+ tarball_path = repacked_path
125
+ end
126
+ end
127
+ rescue Bosh::Cli::DirectorError
128
+ # It's OK for director to choke on getting
129
+ # a release info (think new releases)
130
+ end
131
+
132
+ if rebase
133
+ say("Uploading release (#{'will be rebased'.make_yellow})")
134
+ status, task_id = director.rebase_release(tarball_path)
135
+ task_report(status, task_id, 'Release rebased')
136
+ else
137
+ say("\nUploading release\n")
138
+ status, task_id = director.upload_release(tarball_path)
139
+ task_report(status, task_id, 'Release uploaded')
140
+ end
141
+ end
142
+
143
+ def upload_remote_release(release_location, upload_options = {})
144
+ nl
145
+ if upload_options[:rebase]
146
+ say("Using remote release `#{release_location}' (#{'will be rebased'.make_yellow})")
147
+ status, task_id = director.rebase_remote_release(release_location)
148
+ task_report(status, task_id, 'Release rebased')
149
+ else
150
+ say("Using remote release `#{release_location}'")
151
+ status, task_id = director.upload_remote_release(release_location)
152
+ task_report(status, task_id, 'Release uploaded')
153
+ end
154
+ end
155
+
156
+ # if we aren't already in a release directory, try going up two levels
157
+ # to see if that is a release directory, and then use that as the base
158
+ def find_release_dir(manifest_path)
159
+ unless in_release_dir?
160
+ dir = File.expand_path('../..', manifest_path)
161
+ Dir.chdir(dir)
162
+ if in_release_dir?
163
+ @release = Bosh::Cli::Release.new(dir)
164
+ end
165
+ end
166
+
167
+ end
168
+
169
+ def get_remote_release(name)
170
+ release = director.get_release(name)
171
+
172
+ unless release.is_a?(Hash) &&
173
+ release.has_key?('jobs') &&
174
+ release.has_key?('packages')
175
+ raise Bosh::Cli::DirectorError,
176
+ 'Cannot find version, jobs and packages info in the director response, maybe old director?'
177
+ end
178
+
179
+ release
180
+ end
181
+
182
+ def match_remote_packages(manifest_yaml)
183
+ director.match_packages(manifest_yaml)
184
+ rescue Bosh::Cli::DirectorError
185
+ msg = "You are using CLI >= 0.20 with director that doesn't support " +
186
+ "package matches.\nThis will result in uploading all packages " +
187
+ "and jobs to your director.\nIt is recommended to update your " +
188
+ 'director or downgrade your CLI to 0.19.6'
189
+
190
+ say(msg.make_yellow)
191
+ exit(1) unless confirmed?
192
+ end
193
+
194
+ def should_convert_to_old_format?(version)
195
+ return false if new_director?
196
+ old_format = Bosh::Common::Version::ReleaseVersion.parse(version).to_old_format
197
+ old_format && version != old_format
198
+ end
199
+
200
+ def new_director?
201
+ director_version = director.get_status['version']
202
+ new_format_director_version = '1.2580.0'
203
+ Bosh::Common::Version::BoshVersion.parse(director_version) >=
204
+ Bosh::Common::Version::BoshVersion.parse(new_format_director_version)
205
+ end
206
+ end
207
+ end
208
+ end
@@ -0,0 +1,28 @@
1
+ module Bosh::Cli::Command
2
+ module Release
3
+ class VerifyRelease < Base
4
+
5
+ # bosh verify release
6
+ usage 'verify release'
7
+ desc 'Verify release'
8
+ def verify(tarball_path)
9
+ tarball = Bosh::Cli::ReleaseTarball.new(tarball_path)
10
+
11
+ nl
12
+ say('Verifying release...')
13
+ tarball.validate
14
+ nl
15
+
16
+ if tarball.valid?
17
+ say("`#{tarball_path}' is a valid release".make_green)
18
+ else
19
+ say('Validation errors:'.make_red)
20
+ tarball.errors.each do |error|
21
+ say("- #{error}")
22
+ end
23
+ err("`#{tarball_path}' is not a valid release".make_red)
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -7,13 +7,13 @@ module Bosh::Cli
7
7
  attr_accessor :dry_run
8
8
 
9
9
  def init_indices
10
- @dev_index = VersionsIndex.new(@dev_builds_dir)
11
- @dev_storage = LocalVersionStorage.new(@dev_builds_dir)
10
+ @dev_index = Versions::VersionsIndex.new(@dev_builds_dir)
11
+ @dev_storage = Versions::LocalVersionStorage.new(@dev_builds_dir)
12
12
 
13
- @final_index = VersionsIndex.new(@final_builds_dir)
14
- @final_storage = LocalVersionStorage.new(@final_builds_dir)
13
+ @final_index = Versions::VersionsIndex.new(@final_builds_dir)
14
+ @final_storage = Versions::LocalVersionStorage.new(@final_builds_dir)
15
15
 
16
- @final_resolver = VersionFileResolver.new(@final_storage, @blobstore)
16
+ @final_resolver = Versions::VersionFileResolver.new(@final_storage, @blobstore)
17
17
  end
18
18
 
19
19
  def final?
@@ -2,29 +2,30 @@ module Bosh::Cli
2
2
  class ReleaseBuilder
3
3
  include Bosh::Cli::DependencyHelper
4
4
 
5
- DEFAULT_RELEASE_NAME = "bosh_release"
6
-
7
- attr_reader :release, :packages, :jobs, :version, :build_dir, :commit_hash, :uncommitted_changes
5
+ attr_reader :release, :packages, :jobs, :name, :version, :build_dir, :commit_hash, :uncommitted_changes
8
6
 
9
7
  # @param [Bosh::Cli::Release] release Current release
10
8
  # @param [Array<Bosh::Cli::PackageBuilder>] packages Built packages
11
9
  # @param [Array<Bosh::Cli::JobBuilder>] jobs Built jobs
12
10
  # @param [Hash] options Release build options
13
- def initialize(release, packages, jobs, options = { })
11
+ def initialize(release, packages, jobs, name, options = { })
14
12
  @release = release
15
13
  @final = options.has_key?(:final) ? !!options[:final] : false
16
14
  @commit_hash = options.fetch(:commit_hash, '00000000')
17
15
  @uncommitted_changes = options.fetch(:uncommitted_changes, true)
18
16
  @packages = packages
19
17
  @jobs = jobs
18
+ @name = name
19
+ raise 'Release name is blank' if name.blank?
20
+
20
21
  @version = options.fetch(:version, nil)
21
22
 
22
23
  raise ReleaseVersionError.new('Version numbers cannot be specified for dev releases') if (@version && !@final)
23
24
 
24
- @final_index = VersionsIndex.new(final_releases_dir)
25
- @dev_index = VersionsIndex.new(dev_releases_dir)
25
+ @final_index = Versions::VersionsIndex.new(final_releases_dir)
26
+ @dev_index = Versions::VersionsIndex.new(dev_releases_dir)
26
27
  @index = @final ? @final_index : @dev_index
27
- @release_storage = LocalVersionStorage.new(@index.storage_dir, release_name)
28
+ @release_storage = Versions::LocalVersionStorage.new(@index.storage_dir, @name)
28
29
 
29
30
  if @version && @release_storage.has_file?(@version)
30
31
  raise ReleaseVersionError.new('Release version already exists')
@@ -38,12 +39,6 @@ module Bosh::Cli
38
39
  end
39
40
  end
40
41
 
41
- # @return [String] Release name
42
- def release_name
43
- name = @final ? @release.final_name : @release.dev_name
44
- name.blank? ? DEFAULT_RELEASE_NAME : name
45
- end
46
-
47
42
  # @return [String] Release version
48
43
  def version
49
44
  @version ||= assign_version.to_s
@@ -136,11 +131,10 @@ module Bosh::Cli
136
131
  manifest["commit_hash"] = commit_hash
137
132
  manifest["uncommitted_changes"] = uncommitted_changes
138
133
 
139
- manifest["name"] = release_name
140
-
141
- unless manifest["name"].bosh_valid_id?
142
- raise InvalidRelease, "Release name `#{manifest["name"]}' is not a valid BOSH identifier"
134
+ unless @name.bosh_valid_id?
135
+ raise InvalidRelease, "Release name `#{@name}' is not a valid BOSH identifier"
143
136
  end
137
+ manifest["name"] = @name
144
138
 
145
139
  # New release versions are allowed to have the same fingerprint as old versions.
146
140
  # For reverse compatibility, random uuids are stored instead.
@@ -192,25 +186,25 @@ module Bosh::Cli
192
186
  end
193
187
 
194
188
  def final_releases_dir
195
- File.join(@release.dir, "releases")
189
+ File.join(@release.dir, 'releases', @name)
196
190
  end
197
191
 
198
192
  def dev_releases_dir
199
- File.join(@release.dir, "dev_releases")
193
+ File.join(@release.dir, 'dev_releases', @name)
200
194
  end
201
195
 
202
196
  def tarball_path
203
- File.join(releases_dir, "#{release_name}-#{version}.tgz")
197
+ File.join(releases_dir, "#{@name}-#{version}.tgz")
204
198
  end
205
199
 
206
200
  def manifest_path
207
- File.join(releases_dir, "#{release_name}-#{version}.yml")
201
+ File.join(releases_dir, "#{@name}-#{version}.yml")
208
202
  end
209
203
 
210
204
  private
211
205
 
212
206
  def assign_version
213
- latest_final_version = ReleaseVersionsIndex.new(@final_index).latest_version
207
+ latest_final_version = Versions::ReleaseVersionsIndex.new(@final_index).latest_version
214
208
  latest_final_version ||= Bosh::Common::Version::ReleaseVersion.parse('0')
215
209
 
216
210
  if @final
@@ -218,7 +212,7 @@ module Bosh::Cli
218
212
  latest_final_version.increment_release
219
213
  else
220
214
  # Increment or Reset the post-release segment
221
- dev_versions = ReleaseVersionsIndex.new(@dev_index).versions
215
+ dev_versions = Versions::ReleaseVersionsIndex.new(@dev_index).versions
222
216
  latest_dev_version = dev_versions.latest_with_pre_release(latest_final_version)
223
217
 
224
218
  if latest_dev_version
@@ -94,18 +94,20 @@ module Bosh::Cli
94
94
  end
95
95
 
96
96
  def find_package(package)
97
- final_package_dir = File.join(@release_dir, ".final_builds", "packages", package.name)
98
- final_index = VersionsIndex.new(final_package_dir)
99
- dev_package_dir = File.join(@release_dir, ".dev_builds", "packages", package.name)
100
- dev_index = VersionsIndex.new(dev_package_dir)
97
+ name = package.name
98
+ final_package_dir = File.join(@release_dir, '.final_builds', 'packages', name)
99
+ final_index = Versions::VersionsIndex.new(final_package_dir)
100
+ dev_package_dir = File.join(@release_dir, '.dev_builds', 'packages', name)
101
+ dev_index = Versions::VersionsIndex.new(dev_package_dir)
101
102
  find_in_indices(final_index, dev_index, package, 'package')
102
103
  end
103
104
 
104
105
  def find_job(job)
105
- final_jobs_dir = File.join(@release_dir, ".final_builds", "jobs", job.name)
106
- final_index = VersionsIndex.new(final_jobs_dir)
107
- dev_jobs_dir = File.join(@release_dir, ".dev_builds", "jobs", job.name)
108
- dev_index = VersionsIndex.new(dev_jobs_dir)
106
+ name = job.name
107
+ final_jobs_dir = File.join(@release_dir, '.final_builds', 'jobs', name)
108
+ final_index = Versions::VersionsIndex.new(final_jobs_dir)
109
+ dev_jobs_dir = File.join(@release_dir, '.dev_builds', 'jobs', name)
110
+ dev_index = Versions::VersionsIndex.new(dev_jobs_dir)
109
111
  find_in_indices(final_index, dev_index, job, 'job')
110
112
  end
111
113
 
@@ -133,9 +135,9 @@ module Bosh::Cli
133
135
  sha1 = found_build["sha1"]
134
136
  blobstore_id = found_build["blobstore_id"]
135
137
 
136
- storage = LocalVersionStorage.new(index.storage_dir)
138
+ storage = Versions::LocalVersionStorage.new(index.storage_dir)
137
139
 
138
- resolver = VersionFileResolver.new(storage, @blobstore)
140
+ resolver = Versions::VersionFileResolver.new(storage, @blobstore)
139
141
  resolver.find_file(blobstore_id, sha1, version, "#{build_type} #{desc}")
140
142
  rescue Bosh::Blobstore::BlobstoreError => e
141
143
  raise BlobstoreError, "Blobstore error: #{e}"
@@ -0,0 +1,42 @@
1
+ module Bosh::Cli::SourceControl
2
+ class GitIgnore
3
+
4
+ RELEASE_IGNORE_PATTERNS = [
5
+ 'config/dev.yml',
6
+ 'config/private.yml',
7
+ 'releases/*.tgz',
8
+ 'releases/**/*.tgz',
9
+ 'dev_releases',
10
+ '.blobs',
11
+ 'blobs',
12
+ '.dev_builds',
13
+ '.idea',
14
+ '.DS_Store',
15
+ '.final_builds/jobs/**/*.tgz',
16
+ '.final_builds/packages/**/*.tgz',
17
+ '*.swp',
18
+ '*~',
19
+ '*#',
20
+ '#*',
21
+ ]
22
+
23
+ def initialize(dir)
24
+ @dir = dir
25
+ end
26
+
27
+ def update
28
+ file_path = File.join(@dir, '.gitignore')
29
+
30
+ found_patterns = []
31
+ if File.exist?(file_path)
32
+ File.open(file_path, 'r').each_line { |line| found_patterns << line.chomp }
33
+ end
34
+
35
+ File.open(file_path, 'a') do |f|
36
+ RELEASE_IGNORE_PATTERNS.each do |pattern|
37
+ f.print(pattern + "\n") unless found_patterns.include?(pattern)
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end