bosh_cli 0.16 → 0.17
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.
- data/Rakefile +2 -1
- data/lib/cli.rb +2 -0
- data/lib/cli/blob_manager.rb +377 -0
- data/lib/cli/commands/base.rb +4 -74
- data/lib/cli/commands/blob_management.rb +47 -0
- data/lib/cli/commands/release.rb +37 -16
- data/lib/cli/runner.rb +14 -10
- data/lib/cli/templates/help_message.erb +3 -2
- data/lib/cli/version.rb +1 -1
- data/spec/unit/blob_manager_spec.rb +291 -0
- data/spec/unit/cli_commands_spec.rb +37 -170
- data/spec/unit/runner_spec.rb +5 -0
- metadata +157 -89
- data/lib/cli/commands/blob.rb +0 -125
data/lib/cli/commands/blob.rb
DELETED
@@ -1,125 +0,0 @@
|
|
1
|
-
# Copyright (c) 2009-2012 VMware, Inc.
|
2
|
-
|
3
|
-
module Bosh::Cli::Command
|
4
|
-
class Blob < Base
|
5
|
-
|
6
|
-
def upload_blob(*params)
|
7
|
-
check_if_blobs_supported
|
8
|
-
force = !params.delete("--force").nil?
|
9
|
-
|
10
|
-
blobs = params.map{ |param| get_blob_name(param) }
|
11
|
-
total = blobs.size
|
12
|
-
blob_index = get_blobs_index
|
13
|
-
|
14
|
-
blobs.each_with_index do |blob_name, idx|
|
15
|
-
count = idx + 1
|
16
|
-
blob_file = File.join(BLOBS_DIR, blob_name)
|
17
|
-
blob_sha = Digest::SHA1.file(blob_file).hexdigest
|
18
|
-
|
19
|
-
if blob_index[blob_name] && !force
|
20
|
-
# We already have this binary on record
|
21
|
-
if blob_index[blob_name]["sha"] == blob_sha
|
22
|
-
say("[#{count}/#{total}] Skipping #{blob_name}".green)
|
23
|
-
next
|
24
|
-
end
|
25
|
-
# Local copy is different from the remote copy
|
26
|
-
if interactive?
|
27
|
-
confirm = ask("\nBlob #{blob_name} changed, " +
|
28
|
-
"do you want to update the binary [yN]: ")
|
29
|
-
if confirm.empty? || !(confirm =~ /y(es)?$/i)
|
30
|
-
say("[#{count}/#{total}] Skipping #{blob_name}".green)
|
31
|
-
next
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
# TODO: We could use the sha and try to avoid
|
37
|
-
# uploading duplicated objects.
|
38
|
-
say("[#{count}/#{total}] Uploading #{blob_name}".green)
|
39
|
-
blob_id = blobstore.create(File.open(blob_file, "r"))
|
40
|
-
blob_index[blob_name] = { "object_id" => blob_id, "sha" => blob_sha }
|
41
|
-
end
|
42
|
-
|
43
|
-
# update the index file
|
44
|
-
index_file = Tempfile.new("tmp_blob_index")
|
45
|
-
dump_yaml_to_file(blob_index, index_file)
|
46
|
-
index_file.close
|
47
|
-
FileUtils.mv(index_file.path, File.join(work_dir, BLOBS_INDEX_FILE))
|
48
|
-
end
|
49
|
-
|
50
|
-
def sync_blobs(*options)
|
51
|
-
check_if_blobs_supported
|
52
|
-
force = options.include?("--force")
|
53
|
-
|
54
|
-
blob_index = get_blobs_index
|
55
|
-
total = blob_index.size
|
56
|
-
count = 0
|
57
|
-
|
58
|
-
blob_index.each_pair do |name, blob_info|
|
59
|
-
count += 1
|
60
|
-
blob_file = File.join(work_dir, BLOBS_DIR, name)
|
61
|
-
|
62
|
-
# check if we have conflicting blobs
|
63
|
-
if File.file?(blob_file) && !force
|
64
|
-
blob_sha = Digest::SHA1.file(blob_file).hexdigest
|
65
|
-
if blob_sha == blob_info["sha"]
|
66
|
-
say("[#{count}/#{total}] Skipping blob #{name}".green)
|
67
|
-
next
|
68
|
-
end
|
69
|
-
|
70
|
-
if interactive?
|
71
|
-
confirm = ask("\nLocal blob (#{name}) conflicts with " +
|
72
|
-
"remote object, overwrite local copy? [yN]: ")
|
73
|
-
if confirm.empty? || !(confirm =~ /y(es)?$/i)
|
74
|
-
say("[#{count}/#{total}] Skipping blob #{name}".green)
|
75
|
-
next
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
79
|
-
say("[#{count}/#{total}] Updating #{blob_file}".green)
|
80
|
-
fetch_blob(blob_file, blob_info)
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
def blobs_info
|
85
|
-
blob_status(true)
|
86
|
-
end
|
87
|
-
|
88
|
-
private
|
89
|
-
|
90
|
-
# Sanity check the input file and returns the blob_name
|
91
|
-
def get_blob_name(file)
|
92
|
-
err("Invalid file #{file}") unless File.file?(file)
|
93
|
-
blobs_dir = File.join(realpath(work_dir), "#{BLOBS_DIR}/")
|
94
|
-
file_path = realpath(File.expand_path(file))
|
95
|
-
|
96
|
-
if file_path[0..blobs_dir.length - 1] != blobs_dir
|
97
|
-
err("#{file_path} is NOT under #{blobs_dir}")
|
98
|
-
end
|
99
|
-
file_path[blobs_dir.length..file_path.length]
|
100
|
-
end
|
101
|
-
|
102
|
-
# Download the blob (blob_info) into dst_file
|
103
|
-
def fetch_blob(dst_file, blob_info)
|
104
|
-
object_id = blob_info["object_id"]
|
105
|
-
|
106
|
-
# fetch the blob
|
107
|
-
new_blob = Tempfile.new("new_blob_file")
|
108
|
-
blobstore.get(object_id, new_blob)
|
109
|
-
new_blob.close
|
110
|
-
|
111
|
-
if blob_info["sha"] != Digest::SHA1.file(new_blob.path).hexdigest
|
112
|
-
err("Fatal error: " +
|
113
|
-
"Inconsistent checksum for object #{blob_info["object_id"]}")
|
114
|
-
end
|
115
|
-
|
116
|
-
FileUtils.mkdir_p(File.dirname(dst_file))
|
117
|
-
FileUtils.chmod(0644, new_blob.path)
|
118
|
-
FileUtils.mv(new_blob.path, dst_file)
|
119
|
-
end
|
120
|
-
|
121
|
-
def realpath(path)
|
122
|
-
Pathname.new(path).realpath.to_s
|
123
|
-
end
|
124
|
-
end
|
125
|
-
end
|