bosh_cli 1.2671.0 → 1.2682.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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