bosh_cli 1.2657.0 → 1.2669.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 600ba43a96360d7442c352820f7d65b32b59768c
4
- data.tar.gz: a4215a827e50ad57105d409ce04c3d304641ecc0
3
+ metadata.gz: 206c482ff9d75e5f49d6bc0950f76bbac870e316
4
+ data.tar.gz: 06edf9a6c160e702431e5efed54cb8bbc16ed4da
5
5
  SHA512:
6
- metadata.gz: 641e53d5f4a266d2a22b648ac0fa726803f96504c00fa2776322dd885ba5868a83c78cfb85e2a84c3e44c79ff2dfa1968b0f892d94c1f8d17f770fa7865e1262
7
- data.tar.gz: b074a90e8e060b6d8d78f1d3c828806390d307086a1812f9f3dd125cc648fbe14969e18e5db02b67d523f2a0e548d6d6c5df5f3565b7b238c3820e9d13d12f36
6
+ metadata.gz: f33ee8ddea4a3920d98e28b99b81d23af167ea7df505740b2ce3b06df28f859f03c62376660a6b17083555b0bd35e13e1c9a6cba49d24042bbed5eee2a725be0
7
+ data.tar.gz: 42ed8b5ca8743042d081163ecb092970489248db2fa75b33466df2effa66ac05383b8e9f861c7e4115d7ac4c12dba309fc1ef4c6aea594a2d7fc4af808bf18ec
data/lib/cli.rb CHANGED
@@ -31,6 +31,8 @@ require 'zlib'
31
31
  require 'archive/tar/minitar'
32
32
  include Archive::Tar
33
33
 
34
+ require 'bosh/template/evaluation_context'
35
+
34
36
  unless defined?(Bosh::Cli::VERSION)
35
37
  require 'cli/version'
36
38
  end
@@ -38,9 +40,10 @@ end
38
40
  require 'common/common'
39
41
  require 'common/exec'
40
42
  require 'common/version/release_version'
43
+ require 'common/version/release_version_list'
41
44
  require 'common/version/bosh_version'
42
45
  require 'common/version/stemcell_version'
43
- require 'common/properties'
46
+ require 'common/version/stemcell_version_list'
44
47
 
45
48
  require 'cli/config'
46
49
  require 'cli/core_ext'
@@ -58,7 +61,10 @@ require 'cli/director_task'
58
61
  require 'cli/line_wrap'
59
62
  require 'cli/backup_destination_path'
60
63
 
61
- require 'cli/versions_index'
64
+ require 'cli/versions/versions_index'
65
+ require 'cli/versions/local_version_storage'
66
+ require 'cli/versions/release_versions_index'
67
+ require 'cli/versions/version_file_resolver'
62
68
  require 'cli/packaging_helper'
63
69
  require 'cli/package_builder'
64
70
  require 'cli/job_builder'
@@ -59,26 +59,6 @@ module Bosh::Cli::Command
59
59
  else
60
60
  say(" not set".make_yellow)
61
61
  end
62
-
63
- if in_release_dir?
64
- nl
65
- say("Release".make_green)
66
-
67
- dev_version = Bosh::Cli::VersionsIndex.new(
68
- File.join(work_dir, "dev_releases")).latest_version
69
-
70
- final_version = Bosh::Cli::VersionsIndex.new(
71
- File.join(work_dir, "releases")).latest_version
72
-
73
- dev = release.dev_name
74
- dev += "/#{dev_version}" if dev && dev_version
75
-
76
- final = release.final_name
77
- final += "/#{final_version}" if final && final_version
78
-
79
- print_value("dev", dev)
80
- print_value("final", final)
81
- end
82
62
  end
83
63
  end
84
64
 
@@ -374,7 +374,7 @@ module Bosh::Cli
374
374
  end
375
375
 
376
376
  stemcells.inject({}) do |hash, (name, versions)|
377
- hash[name] = Bosh::Common::Version::StemcellVersion.parse_list(versions).latest.to_s
377
+ hash[name] = Bosh::Common::Version::StemcellVersionList.parse(versions).latest.to_s
378
378
  hash
379
379
  end
380
380
  end
@@ -1,11 +1,12 @@
1
1
  # Copyright (c) 2009-2012 VMware, Inc.
2
2
 
3
3
  require 'common/deep_copy'
4
+ require 'bosh/template/property_helper'
4
5
 
5
6
  module Bosh::Cli
6
7
  class JobPropertyCollection
7
8
  include Enumerable
8
- include Bosh::Common::PropertyHelper
9
+ include Bosh::Template::PropertyHelper
9
10
 
10
11
  # @param [JobBuilder] job_builder Which job this property collection is for
11
12
  # @param [Hash] global_properties Globally defined properties
@@ -1,4 +1,5 @@
1
1
  # Copyright (c) 2009-2012 VMware, Inc.
2
+ require 'bosh/template/evaluation_context'
2
3
 
3
4
  module Bosh::Cli
4
5
  class JobPropertyValidator
@@ -108,7 +109,7 @@ module Bosh::Cli
108
109
  # @param [Hash] spec Fake instance spec
109
110
  def evaluate_template(job, template_path, spec)
110
111
  erb = ERB.new(File.read(template_path))
111
- context = Bosh::Common::TemplateEvaluationContext.new(spec)
112
+ context = Bosh::Template::EvaluationContext.new(spec)
112
113
  begin
113
114
  erb.result(context.get_binding)
114
115
  rescue Exception => e
@@ -8,7 +8,12 @@ module Bosh::Cli
8
8
 
9
9
  def init_indices
10
10
  @dev_index = VersionsIndex.new(@dev_builds_dir)
11
+ @dev_storage = LocalVersionStorage.new(@dev_builds_dir)
12
+
11
13
  @final_index = VersionsIndex.new(@final_builds_dir)
14
+ @final_storage = LocalVersionStorage.new(@final_builds_dir)
15
+
16
+ @final_resolver = VersionFileResolver.new(@final_storage, @blobstore)
12
17
  end
13
18
 
14
19
  def final?
@@ -55,47 +60,22 @@ module Bosh::Cli
55
60
  end
56
61
 
57
62
  blobstore_id = item['blobstore_id']
58
- version = fingerprint
63
+ version = item['version'] || fingerprint
64
+ sha1 = item['sha1']
59
65
 
60
66
  if blobstore_id.nil?
61
67
  say('No blobstore id'.make_red)
62
68
  return nil
63
69
  end
64
70
 
65
- filename = @final_index.filename(version)
66
- need_fetch = true
67
-
68
- if File.exists?(filename)
69
- say('FOUND LOCAL'.make_green)
70
- if file_checksum(filename) == item['sha1']
71
- @tarball_path = filename
72
- need_fetch = false
73
- else
74
- say('LOCAL CHECKSUM MISMATCH'.make_red)
75
- need_fetch = true
76
- end
77
- end
71
+ desc = "#{name} (#{version})"
78
72
 
79
- if need_fetch
80
- say("Downloading `#{name} (#{version})'...".make_green)
81
- tmp_file = File.open(File.join(Dir.mktmpdir, name), 'w')
82
- @blobstore.get(blobstore_id, tmp_file)
83
- tmp_file.close
84
- if Digest::SHA1.file(tmp_file.path).hexdigest == item['sha1']
85
- @tarball_path = @final_index.add_version(fingerprint,
86
- item,
87
- tmp_file.path)
88
- else
89
- err("`#{name}' (#{version}) is corrupted in blobstore " +
90
- "(id=#{blobstore_id}), " +
91
- 'please remove it manually and re-generate the final release')
92
- end
93
- end
73
+ @tarball_path = @final_resolver.find_file(blobstore_id, sha1, version, "package #{desc}")
94
74
 
95
75
  @version = version
96
76
  @used_final_version = true
97
77
  true
98
- rescue Bosh::Blobstore::NotFound => e
78
+ rescue Bosh::Blobstore::NotFound
99
79
  raise BlobstoreError, "Final version of `#{name}' not found in blobstore"
100
80
  rescue Bosh::Blobstore::BlobstoreError => e
101
81
  raise BlobstoreError, "Blobstore error: #{e}"
@@ -110,24 +90,31 @@ module Bosh::Cli
110
90
  return nil
111
91
  end
112
92
 
113
- version = fingerprint
114
- filename = @dev_index.filename(version)
93
+ version = @dev_index['version'] || fingerprint
115
94
 
116
- if File.exists?(filename)
117
- say('FOUND LOCAL'.make_green)
118
- else
95
+ if !@dev_storage.has_file?(version)
119
96
  say('TARBALL MISSING'.make_red)
120
97
  return nil
121
98
  end
122
99
 
123
- if file_checksum(filename) == item['sha1']
124
- @tarball_path = filename
125
- @version = version
126
- @used_dev_version = true
127
- else
100
+ say('FOUND LOCAL'.make_green)
101
+ @tarball_path = @dev_storage.get_file(version)
102
+
103
+ if file_checksum(@tarball_path) != item['sha1']
128
104
  say("`#{name} (#{version})' tarball corrupted".make_red)
129
105
  return nil
130
106
  end
107
+
108
+ if final? && !dry_run?
109
+ # copy from dev index/storage to final index/storage
110
+ @final_index.add_version(fingerprint, item)
111
+ @tarball_path = @final_storage.put_file(version, @tarball_path)
112
+ item['sha1'] = Digest::SHA1.file(@tarball_path).hexdigest
113
+ @final_index.update_version(fingerprint, item)
114
+ end
115
+
116
+ @version = version
117
+ @used_dev_version = true
131
118
  end
132
119
 
133
120
  def generate_tarball
@@ -150,12 +137,18 @@ module Bosh::Cli
150
137
  }
151
138
 
152
139
  if final?
153
- @final_index.add_version(fingerprint, item, tmp_file.path)
154
- @tarball_path = @final_index.filename(version)
140
+ # add version (with its validation) before adding sha1
141
+ @final_index.add_version(fingerprint, item)
142
+ @tarball_path = @final_storage.put_file(fingerprint, tmp_file.path)
143
+ item['sha1'] = file_checksum(@tarball_path)
144
+ @final_index.update_version(fingerprint, item)
155
145
  elsif dry_run?
156
146
  else
157
- @dev_index.add_version(fingerprint, item, tmp_file.path)
158
- @tarball_path = @dev_index.filename(version)
147
+ # add version (with its validation) before adding sha1
148
+ @dev_index.add_version(fingerprint, item)
149
+ @tarball_path = @dev_storage.put_file(fingerprint, tmp_file.path)
150
+ item['sha1'] = file_checksum(@tarball_path)
151
+ @dev_index.update_version(fingerprint, item)
159
152
  end
160
153
 
161
154
  @version = version
@@ -167,29 +160,25 @@ module Bosh::Cli
167
160
  def upload_tarball(path)
168
161
  item = @final_index[fingerprint]
169
162
 
170
- say("Uploading final version #{version}...")
163
+ unless item
164
+ say("Failed to find entry `#{fingerprint}' in index, check local storage")
165
+ return
166
+ end
171
167
 
172
- if item
173
- say('This package has already been uploaded')
168
+ if item['blobstore_id']
174
169
  return
175
170
  end
176
171
 
177
- version = fingerprint
172
+ say("Uploading final version `#{version}'...")
178
173
 
179
174
  blobstore_id = nil
180
175
  File.open(path, 'r') do |f|
181
176
  blobstore_id = @blobstore.create(f)
182
177
  end
183
178
 
184
- item = {
185
- 'blobstore_id' => blobstore_id,
186
- 'version' => version
187
- }
188
-
189
- say("Uploaded, blobstore id #{blobstore_id}")
190
- @final_index.add_version(fingerprint, item, path)
191
- @tarball_path = @final_index.filename(version)
192
- @version = version
179
+ say("Uploaded, blobstore id `#{blobstore_id}'")
180
+ item['blobstore_id'] = blobstore_id
181
+ @final_index.update_version(fingerprint, item)
193
182
  @promoted = true
194
183
  true
195
184
  rescue Bosh::Blobstore::BlobstoreError => e
@@ -226,4 +215,3 @@ module Bosh::Cli
226
215
  end
227
216
  end
228
217
  end
229
-
@@ -21,11 +21,14 @@ module Bosh::Cli
21
21
 
22
22
  raise ReleaseVersionError.new('Version numbers cannot be specified for dev releases') if (@version && !@final)
23
23
 
24
- @final_index = VersionsIndex.new(final_releases_dir, release_name)
25
- @dev_index = VersionsIndex.new(dev_releases_dir, release_name)
24
+ @final_index = VersionsIndex.new(final_releases_dir)
25
+ @dev_index = VersionsIndex.new(dev_releases_dir)
26
26
  @index = @final ? @final_index : @dev_index
27
+ @release_storage = LocalVersionStorage.new(@index.storage_dir, release_name)
27
28
 
28
- raise ReleaseVersionError.new('Release version already exists') if (@version && @index.version_exists?(@version))
29
+ if @version && @release_storage.has_file?(@version)
30
+ raise ReleaseVersionError.new('Release version already exists')
31
+ end
29
32
 
30
33
  @build_dir = Dir.mktmpdir
31
34
 
@@ -136,19 +139,12 @@ module Bosh::Cli
136
139
  manifest["name"] = release_name
137
140
 
138
141
  unless manifest["name"].bosh_valid_id?
139
- raise InvalidRelease, "Release name `#{manifest["name"]}' " +
140
- "is not a valid BOSH identifier"
142
+ raise InvalidRelease, "Release name `#{manifest["name"]}' is not a valid BOSH identifier"
141
143
  end
142
144
 
143
- fingerprint = make_fingerprint(manifest)
144
-
145
- if @index[fingerprint]
146
- old_version = @index[fingerprint]["version"]
147
- say("This version is no different from version #{old_version}")
148
- @version = old_version
149
- else
150
- @index.add_version(fingerprint, { "version" => version })
151
- end
145
+ # New release versions are allowed to have the same fingerprint as old versions.
146
+ # For reverse compatibility, random uuids are stored instead.
147
+ @index.add_version(SecureRandom.uuid, { "version" => version })
152
148
 
153
149
  manifest["version"] = version
154
150
  manifest_yaml = Psych.dump(manifest)
@@ -167,7 +163,7 @@ module Bosh::Cli
167
163
 
168
164
  def generate_tarball
169
165
  generate_manifest unless @manifest_generated
170
- return if @index.version_exists?(version)
166
+ return if @release_storage.has_file?(@version)
171
167
 
172
168
  unless @jobs_copied
173
169
  header("Copying jobs...")
@@ -211,22 +207,10 @@ module Bosh::Cli
211
207
  File.join(releases_dir, "#{release_name}-#{version}.yml")
212
208
  end
213
209
 
214
- def make_fingerprint(item)
215
- case item
216
- when Array
217
- source = item.map { |e| make_fingerprint(e) }.sort.join("")
218
- when Hash
219
- source = item.keys.sort.map{ |k| make_fingerprint(item[k]) }.join("")
220
- else
221
- source = item.to_s
222
- end
223
- Digest::SHA1.hexdigest(source)
224
- end
225
-
226
210
  private
227
211
 
228
212
  def assign_version
229
- latest_final_version = Bosh::Common::Version::ReleaseVersion.parse_list(@final_index.versions).latest
213
+ latest_final_version = ReleaseVersionsIndex.new(@final_index).latest_version
230
214
  latest_final_version ||= Bosh::Common::Version::ReleaseVersion.parse('0')
231
215
 
232
216
  if @final
@@ -234,7 +218,7 @@ module Bosh::Cli
234
218
  latest_final_version.increment_release
235
219
  else
236
220
  # Increment or Reset the post-release segment
237
- dev_versions = Bosh::Common::Version::ReleaseVersion.parse_list(@dev_index.versions)
221
+ dev_versions = ReleaseVersionsIndex.new(@dev_index).versions
238
222
  latest_dev_version = dev_versions.latest_with_pre_release(latest_final_version)
239
223
 
240
224
  if latest_dev_version
@@ -45,9 +45,7 @@ module Bosh::Cli
45
45
  quit("You already have this version in `#{tarball_path.make_green}'")
46
46
  end
47
47
 
48
- FileUtils.cp(@manifest_file,
49
- File.join(@build_dir, "release.MF"),
50
- :preserve => true)
48
+ FileUtils.cp(@manifest_file, File.join(@build_dir, "release.MF"), :preserve => true)
51
49
 
52
50
  header("Copying packages")
53
51
  @packages.each do |package|
@@ -56,11 +54,8 @@ module Bosh::Cli
56
54
  say("SKIP".make_yellow)
57
55
  next
58
56
  end
59
- package_filename = find_package(package)
60
- if package_filename.nil?
61
- err("Cannot find package `#{package.name} (#{package.version})'")
62
- end
63
- FileUtils.cp(package_filename,
57
+ package_file_path = find_package(package)
58
+ FileUtils.cp(package_file_path,
64
59
  File.join(@packages_dir, "#{package.name}.tgz"),
65
60
  :preserve => true)
66
61
  end
@@ -72,11 +67,8 @@ module Bosh::Cli
72
67
  say("SKIP".make_yellow)
73
68
  next
74
69
  end
75
- job_filename = find_job(job)
76
- if job_filename.nil?
77
- err("Cannot find job `#{job.name} (#{job.version})")
78
- end
79
- FileUtils.cp(job_filename,
70
+ job_file_path = find_job(job)
71
+ FileUtils.cp(job_file_path,
80
72
  File.join(@jobs_dir, "#{job.name}.tgz"),
81
73
  :preserve => true)
82
74
  end
@@ -102,63 +94,49 @@ module Bosh::Cli
102
94
  end
103
95
 
104
96
  def find_package(package)
105
- final_index = VersionsIndex.new(
106
- File.join(@release_dir, ".final_builds", "packages", package.name))
107
- dev_index = VersionsIndex.new(
108
- File.join(@release_dir, ".dev_builds", "packages", package.name))
109
- find_in_indices(final_index, dev_index, 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)
101
+ find_in_indices(final_index, dev_index, package, 'package')
110
102
  end
111
103
 
112
104
  def find_job(job)
113
- final_index = VersionsIndex.new(
114
- File.join(@release_dir, ".final_builds", "jobs", job.name))
115
- dev_index = VersionsIndex.new(
116
- File.join(@release_dir, ".dev_builds", "jobs", job.name))
117
- find_in_indices(final_index, dev_index, 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)
109
+ find_in_indices(final_index, dev_index, job, 'job')
118
110
  end
119
111
 
120
- def find_in_indices(final_index, dev_index, object)
121
- desc = "#{object.name} (#{object.version})"
112
+ def find_version_by_sha1(index, sha1)
113
+ index.select{ |_, build| build['sha1'] == sha1 }.values.first
114
+ end
115
+
116
+ def find_in_indices(final_index, dev_index, build, build_type)
117
+ desc = "#{build.name} (#{build.version})"
122
118
 
123
119
  index = final_index
124
- build_data = index.find_by_checksum(object.sha1)
120
+ found_build = find_version_by_sha1(index, build.sha1)
125
121
 
126
- if build_data.nil?
122
+ if found_build.nil?
127
123
  index = dev_index
128
- build_data = index.find_by_checksum(object.sha1)
124
+ found_build = find_version_by_sha1(index, build.sha1)
129
125
  end
130
126
 
131
- if build_data.nil?
127
+ if found_build.nil?
132
128
  say("MISSING".make_red)
133
- err("Cannot find object with given checksum")
129
+ err("Cannot find #{build_type} with checksum `#{build.sha1}'")
134
130
  end
135
131
 
136
- version = build_data["version"]
137
- sha1 = build_data["sha1"]
138
- blobstore_id = build_data["blobstore_id"]
139
- filename = index.filename(version)
132
+ version = found_build["version"]
133
+ sha1 = found_build["sha1"]
134
+ blobstore_id = found_build["blobstore_id"]
140
135
 
141
- if File.exists?(filename)
142
- say("FOUND LOCAL".make_green)
143
- if Digest::SHA1.file(filename) != sha1
144
- err("#{desc} is corrupted locally")
145
- end
146
- elsif blobstore_id
147
- say("FOUND REMOTE".make_yellow)
148
- say("Downloading #{blobstore_id.to_s.make_green}...")
149
- tmp_file = Tempfile.new("")
150
- @blobstore.get(blobstore_id, tmp_file)
151
- tmp_file.close
152
-
153
- if Digest::SHA1.file(tmp_file.path).hexdigest == sha1
154
- FileUtils.mv(tmp_file.path, filename)
155
- else
156
- err("#{desc} is corrupted in blobstore (id=#{blobstore_id})")
157
- end
158
- end
159
-
160
- File.exists?(filename) ? filename : nil
136
+ storage = LocalVersionStorage.new(index.storage_dir)
161
137
 
138
+ resolver = VersionFileResolver.new(storage, @blobstore)
139
+ resolver.find_file(blobstore_id, sha1, version, "#{build_type} #{desc}")
162
140
  rescue Bosh::Blobstore::BlobstoreError => e
163
141
  raise BlobstoreError, "Blobstore error: #{e}"
164
142
  end
@@ -180,5 +158,4 @@ module Bosh::Cli
180
158
  false
181
159
  end
182
160
  end
183
-
184
161
  end
data/lib/cli/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  module Bosh
2
2
  module Cli
3
- VERSION = '1.2657.0'
3
+ VERSION = '1.2669.0'
4
4
  end
5
5
  end
@@ -0,0 +1,41 @@
1
+ module Bosh::Cli
2
+ class LocalVersionStorage
3
+
4
+ class Sha1MismatchError < StandardError; end
5
+
6
+ attr_reader :storage_dir
7
+
8
+ def initialize(storage_dir, name_prefix=nil)
9
+ @storage_dir = storage_dir
10
+ @name_prefix = name_prefix
11
+ end
12
+
13
+ def put_file(version, src_file_path)
14
+ destination = file_path(version)
15
+ unless File.exist?(src_file_path)
16
+ raise "Trying to store non-existant file `#{src_file_path}' for version `#{version}'"
17
+ end
18
+ FileUtils.cp(src_file_path, destination, :preserve => true)
19
+
20
+ File.expand_path(destination)
21
+ end
22
+
23
+ def get_file(version)
24
+ destination = file_path(version)
25
+ unless File.exist?(destination)
26
+ raise "Trying to retrieve non-existant file `#{destination}' for version `#{version}'"
27
+ end
28
+
29
+ File.expand_path(destination)
30
+ end
31
+
32
+ def has_file?(version)
33
+ File.exists?(file_path(version))
34
+ end
35
+
36
+ def file_path(version)
37
+ name = @name_prefix.blank? ? "#{version}.tgz" : "#{@name_prefix}-#{version}.tgz"
38
+ File.join(@storage_dir, name)
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,18 @@
1
+ module Bosh::Cli
2
+ class ReleaseVersionsIndex
3
+
4
+ def initialize(versions_index)
5
+ @versions_index = versions_index
6
+ end
7
+
8
+ def latest_version
9
+ version_strings = @versions_index.version_strings
10
+ return nil if version_strings.empty?
11
+ Bosh::Common::Version::ReleaseVersionList.parse(version_strings).latest
12
+ end
13
+
14
+ def versions
15
+ Bosh::Common::Version::ReleaseVersionList.parse(@versions_index.version_strings)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,49 @@
1
+ module Bosh::Cli
2
+ class VersionFileResolver
3
+
4
+ def initialize(storage, blobstore, tmpdir=Dir.tmpdir)
5
+ @storage = storage
6
+ @blobstore = blobstore
7
+ @tmpdir = tmpdir
8
+ end
9
+
10
+ def find_file(blobstore_id, sha1, version, desc)
11
+ if @storage.has_file?(version)
12
+ say('FOUND LOCAL'.make_green)
13
+ file_path = @storage.get_file(version)
14
+ file_sha1 = Digest::SHA1.file(file_path).hexdigest
15
+ if file_sha1 == sha1
16
+ return file_path
17
+ end
18
+ say("SHA1 `#{file_sha1}' of #{desc} does not match expected SHA1 `#{sha1}'".make_red)
19
+ end
20
+
21
+ if blobstore_id.nil?
22
+ err("Cannot find #{desc}")
23
+ end
24
+
25
+ say('FOUND REMOTE'.make_yellow)
26
+ say("Downloading #{desc} from blobstore (id=#{blobstore_id})...".make_green)
27
+
28
+ tmp_file_path = File.join(@tmpdir, "bosh-tmp-file-#{SecureRandom.uuid}")
29
+ begin
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')
39
+ end
40
+
41
+ @storage.put_file(version, tmp_file_path)
42
+ ensure
43
+ FileUtils.rm(tmp_file_path, :force => true)
44
+ end
45
+ end
46
+
47
+
48
+ end
49
+ end
@@ -0,0 +1,119 @@
1
+ module Bosh::Cli
2
+ class VersionsIndex
3
+
4
+ attr_reader :index_file
5
+ attr_reader :storage_dir
6
+
7
+ def initialize(storage_dir)
8
+ @storage_dir = File.expand_path(storage_dir)
9
+ @index_file = File.join(@storage_dir, 'index.yml')
10
+
11
+ if File.file?(@index_file)
12
+ init_index(load_yaml_file(@index_file, nil))
13
+ else
14
+ init_index({})
15
+ end
16
+ end
17
+
18
+ def [](key)
19
+ @data['builds'][key]
20
+ end
21
+
22
+ def each_pair(&block)
23
+ @data['builds'].each_pair(&block)
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
33
+ end
34
+
35
+ def select(&block)
36
+ @data['builds'].select(&block)
37
+ end
38
+
39
+ # both (tmp_file_path=nil only used by release)
40
+ def add_version(new_key, new_build)
41
+ version = new_build['version']
42
+
43
+ if version.blank?
44
+ raise InvalidIndex, "Cannot save index entry without a version: `#{new_build}'"
45
+ end
46
+
47
+ if @data['builds'][new_key]
48
+ raise "Trying to add duplicate entry `#{new_key}' into index `#{@index_file}'"
49
+ end
50
+
51
+ self.each_pair do |key, build|
52
+ if build['version'] == version && key != new_key
53
+ raise "Trying to add duplicate version `#{version}' into index `#{@index_file}'"
54
+ end
55
+ end
56
+
57
+ create_directories
58
+
59
+ @data['builds'][new_key] = new_build
60
+
61
+ File.open(@index_file, 'w') do |f|
62
+ f.write(Psych.dump(@data))
63
+ end
64
+
65
+ version
66
+ end
67
+
68
+ def update_version(key, new_build)
69
+ old_build = @data['builds'][key]
70
+ unless old_build
71
+ raise "Cannot update non-existent entry with key `#{key}'"
72
+ end
73
+
74
+ if new_build['version'] != old_build['version']
75
+ raise "Cannot update entry `#{old_build}' with a different version: `#{new_build}'"
76
+ end
77
+
78
+ @data['builds'][key] = new_build
79
+
80
+ File.open(@index_file, 'w') do |f|
81
+ f.write(Psych.dump(@data))
82
+ end
83
+ end
84
+
85
+ def version_strings
86
+ @data['builds'].map { |_, build| build['version'].to_s }
87
+ end
88
+
89
+ def to_s
90
+ @data['builds'].to_s
91
+ end
92
+
93
+ private
94
+
95
+ def create_directories
96
+ begin
97
+ FileUtils.mkdir_p(@storage_dir)
98
+ rescue SystemCallError => e
99
+ raise InvalidIndex, "Cannot create index storage directory: #{e}"
100
+ end
101
+
102
+ begin
103
+ FileUtils.touch(@index_file)
104
+ rescue SystemCallError => e
105
+ raise InvalidIndex, "Cannot create index file: #{e}"
106
+ end
107
+ end
108
+
109
+ 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
116
+ @data['builds'] ||= {}
117
+ end
118
+ end
119
+ 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.2657.0
4
+ version: 1.2669.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-24 00:00:00.000000000 Z
11
+ date: 2014-07-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bosh_common
@@ -16,14 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 1.2657.0
19
+ version: 1.2669.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.2657.0
26
+ version: 1.2669.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: bosh-template
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 1.2669.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 1.2669.0
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: json_pure
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -72,14 +86,14 @@ dependencies:
72
86
  requirements:
73
87
  - - '='
74
88
  - !ruby/object:Gem::Version
75
- version: 2.2.4
89
+ version: 2.4.0
76
90
  type: :runtime
77
91
  prerelease: false
78
92
  version_requirements: !ruby/object:Gem::Requirement
79
93
  requirements:
80
94
  - - '='
81
95
  - !ruby/object:Gem::Version
82
- version: 2.2.4
96
+ version: 2.4.0
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: terminal-table
85
99
  requirement: !ruby/object:Gem::Requirement
@@ -100,14 +114,14 @@ dependencies:
100
114
  requirements:
101
115
  - - "~>"
102
116
  - !ruby/object:Gem::Version
103
- version: 1.2657.0
117
+ version: 1.2669.0
104
118
  type: :runtime
105
119
  prerelease: false
106
120
  version_requirements: !ruby/object:Gem::Requirement
107
121
  requirements:
108
122
  - - "~>"
109
123
  - !ruby/object:Gem::Version
110
- version: 1.2657.0
124
+ version: 1.2669.0
111
125
  - !ruby/object:Gem::Dependency
112
126
  name: net-ssh
113
127
  requirement: !ruby/object:Gem::Requirement
@@ -180,7 +194,7 @@ dependencies:
180
194
  version: 0.5.4
181
195
  description: |-
182
196
  BOSH CLI
183
- a6c527
197
+ bf0b96
184
198
  email: support@cloudfoundry.com
185
199
  executables:
186
200
  - bosh
@@ -268,7 +282,10 @@ files:
268
282
  - lib/cli/task_tracking/total_duration.rb
269
283
  - lib/cli/validation.rb
270
284
  - lib/cli/version.rb
271
- - lib/cli/versions_index.rb
285
+ - lib/cli/versions/local_version_storage.rb
286
+ - lib/cli/versions/release_versions_index.rb
287
+ - lib/cli/versions/version_file_resolver.rb
288
+ - lib/cli/versions/versions_index.rb
272
289
  - lib/cli/vm_state.rb
273
290
  - lib/cli/yaml_helper.rb
274
291
  homepage: https://github.com/cloudfoundry/bosh
@@ -1,111 +0,0 @@
1
- module Bosh::Cli
2
- class VersionsIndex
3
-
4
- def initialize(storage_dir, name_prefix = nil)
5
- @storage_dir = File.expand_path(storage_dir)
6
- @index_file = File.join(@storage_dir, "index.yml")
7
- @name_prefix = name_prefix
8
-
9
- if File.file?(@index_file)
10
- init_index(load_yaml_file(@index_file, nil))
11
- else
12
- init_index({})
13
- end
14
- end
15
-
16
- def find_by_checksum(checksum)
17
- @data["builds"].each_pair do |fingerprint, build_data|
18
- return build_data if build_data["sha1"] == checksum
19
- end
20
- nil
21
- end
22
-
23
- def [](fingerprint)
24
- @data["builds"][fingerprint]
25
- end
26
-
27
- def latest_version
28
- builds = @data["builds"].values
29
-
30
- return nil if builds.empty?
31
-
32
- version_strings = builds.map { |b| b["version"] }
33
- Bosh::Common::Version::ReleaseVersion.parse_list(version_strings).latest.to_s
34
- end
35
-
36
- def version_exists?(version)
37
- File.exists?(filename(version))
38
- end
39
-
40
- def add_version(fingerprint, item, tmp_file_path = nil)
41
- version = item["version"]
42
-
43
- if version.blank?
44
- raise InvalidIndex,
45
- "Cannot save index entry without knowing its version"
46
- end
47
-
48
- create_directories
49
-
50
- if tmp_file_path
51
- FileUtils.cp(tmp_file_path, filename(version), :preserve => true)
52
- end
53
-
54
- @data["builds"].each_pair do |fp, build|
55
- if build["version"] == version && fp != fingerprint
56
- raise "Trying to add duplicate version `#{version}' " +
57
- "into index `#{@index_file}'"
58
- end
59
- end
60
-
61
- @data["builds"][fingerprint] = item
62
- if tmp_file_path
63
- file_sha1 = Digest::SHA1.file(tmp_file_path).hexdigest
64
- @data["builds"][fingerprint]["sha1"] = file_sha1
65
- end
66
-
67
- File.open(@index_file, "w") do |f|
68
- f.write(Psych.dump(@data))
69
- end
70
-
71
- File.expand_path(filename(version))
72
- end
73
-
74
- def filename(version)
75
- name = @name_prefix.blank? ?
76
- "#{version}.tgz" : "#{@name_prefix}-#{version}.tgz"
77
- File.join(@storage_dir, name)
78
- end
79
-
80
- def versions
81
- @data['builds'].map { |_, build| build['version'] }
82
- end
83
-
84
- private
85
-
86
- def create_directories
87
- begin
88
- FileUtils.mkdir_p(@storage_dir)
89
- rescue SystemCallError => e
90
- raise InvalidIndex, "Cannot create index storage directory: #{e}"
91
- end
92
-
93
- begin
94
- FileUtils.touch(@index_file)
95
- rescue SystemCallError => e
96
- raise InvalidIndex, "Cannot create index file: #{e}"
97
- end
98
- end
99
-
100
- def init_index(data)
101
- data ||= {}
102
-
103
- unless data.kind_of?(Hash)
104
- raise InvalidIndex, "Invalid versions index data type, " +
105
- "#{data.class} given, Hash expected"
106
- end
107
- @data = data
108
- @data["builds"] ||= {}
109
- end
110
- end
111
- end