MuranoCLI 3.2.0.beta.1 → 3.2.0.beta.5
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/.rubocop.yml +4 -1
- data/.trustme.plugin +137 -0
- data/.trustme.sh +217 -117
- data/.trustme.vim +9 -3
- data/Gemfile +9 -3
- data/MuranoCLI.gemspec +8 -5
- data/Rakefile +1 -0
- data/dockers/Dockerfile.2.2.9 +6 -3
- data/dockers/Dockerfile.2.3.6 +6 -3
- data/dockers/Dockerfile.2.4.3 +6 -3
- data/dockers/Dockerfile.2.5.0 +6 -3
- data/dockers/Dockerfile.GemRelease +10 -8
- data/dockers/Dockerfile.m4 +23 -5
- data/dockers/docker-test.sh +65 -28
- data/docs/completions/murano_completion-bash +751 -57
- data/docs/develop.rst +10 -9
- data/lib/MrMurano/AccountBase.rb +95 -6
- data/lib/MrMurano/Commander-Entry.rb +9 -4
- data/lib/MrMurano/Config-Migrate.rb +2 -0
- data/lib/MrMurano/Config.rb +94 -26
- data/lib/MrMurano/Content.rb +1 -1
- data/lib/MrMurano/Exchange.rb +77 -42
- data/lib/MrMurano/Gateway.rb +1 -1
- data/lib/MrMurano/HttpAuthed.rb +20 -7
- data/lib/MrMurano/Logs.rb +10 -1
- data/lib/MrMurano/ProjectFile.rb +1 -1
- data/lib/MrMurano/ReCommander.rb +129 -73
- data/lib/MrMurano/Solution-ServiceConfig.rb +18 -11
- data/lib/MrMurano/Solution-Services.rb +78 -50
- data/lib/MrMurano/Solution-Users.rb +1 -1
- data/lib/MrMurano/Solution.rb +13 -63
- data/lib/MrMurano/SyncUpDown-Core.rb +185 -77
- data/lib/MrMurano/SyncUpDown-Item.rb +29 -4
- data/lib/MrMurano/SyncUpDown.rb +11 -11
- data/lib/MrMurano/Webservice-Cors.rb +1 -1
- data/lib/MrMurano/Webservice-Endpoint.rb +28 -17
- data/lib/MrMurano/Webservice-File.rb +103 -43
- data/lib/MrMurano/commands/domain.rb +1 -0
- data/lib/MrMurano/commands/element.rb +585 -0
- data/lib/MrMurano/commands/exchange.rb +211 -204
- data/lib/MrMurano/commands/gb.rb +1 -0
- data/lib/MrMurano/commands/globals.rb +17 -7
- data/lib/MrMurano/commands/init.rb +115 -101
- data/lib/MrMurano/commands/keystore.rb +1 -1
- data/lib/MrMurano/commands/logs.rb +2 -1
- data/lib/MrMurano/commands/postgresql.rb +17 -7
- data/lib/MrMurano/commands/service.rb +572 -0
- data/lib/MrMurano/commands/show.rb +7 -3
- data/lib/MrMurano/commands/solution.rb +2 -1
- data/lib/MrMurano/commands/solution_picker.rb +31 -15
- data/lib/MrMurano/commands/status.rb +205 -169
- data/lib/MrMurano/commands/sync.rb +70 -38
- data/lib/MrMurano/commands/token.rb +59 -14
- data/lib/MrMurano/commands/usage.rb +1 -0
- data/lib/MrMurano/commands.rb +2 -0
- data/lib/MrMurano/hash.rb +91 -0
- data/lib/MrMurano/http.rb +55 -6
- data/lib/MrMurano/makePretty.rb +47 -0
- data/lib/MrMurano/optparse.rb +60 -45
- data/lib/MrMurano/variegated/TruthyFalsey.rb +48 -0
- data/lib/MrMurano/variegated/ruby_dig.rb +64 -0
- data/lib/MrMurano/verbosing.rb +113 -3
- data/lib/MrMurano/version.rb +1 -1
- data/spec/Account_spec.rb +34 -20
- data/spec/Business_spec.rb +12 -9
- data/spec/Config_spec.rb +7 -1
- data/spec/Content_spec.rb +17 -1
- data/spec/GatewayBase_spec.rb +5 -2
- data/spec/GatewayDevice_spec.rb +4 -2
- data/spec/GatewayResource_spec.rb +4 -1
- data/spec/GatewaySettings_spec.rb +4 -1
- data/spec/HttpAuthed_spec.rb +73 -0
- data/spec/Http_spec.rb +32 -35
- data/spec/ProjectFile_spec.rb +1 -1
- data/spec/Solution-ServiceConfig_spec.rb +4 -1
- data/spec/Solution-ServiceEventHandler_spec.rb +6 -3
- data/spec/Solution-ServiceModules_spec.rb +4 -1
- data/spec/Solution-UsersRoles_spec.rb +4 -1
- data/spec/Solution_spec.rb +4 -1
- data/spec/SyncUpDown_spec.rb +1 -1
- data/spec/Webservice-Cors_spec.rb +4 -1
- data/spec/Webservice-Endpoint_spec.rb +9 -6
- data/spec/Webservice-File_spec.rb +17 -4
- data/spec/Webservice-Setting_spec.rb +6 -2
- data/spec/_workspace.rb +2 -0
- data/spec/cmd_common.rb +42 -13
- data/spec/cmd_content_spec.rb +17 -7
- data/spec/cmd_device_spec.rb +1 -1
- data/spec/cmd_domain_spec.rb +2 -2
- data/spec/cmd_element_spec.rb +400 -0
- data/spec/cmd_exchange_spec.rb +2 -2
- data/spec/cmd_init_spec.rb +59 -25
- data/spec/cmd_keystore_spec.rb +6 -3
- data/spec/cmd_link_spec.rb +10 -5
- data/spec/cmd_logs_spec.rb +1 -1
- data/spec/cmd_setting_application_spec.rb +18 -15
- data/spec/cmd_setting_product_spec.rb +7 -7
- data/spec/cmd_status_spec.rb +27 -17
- data/spec/cmd_syncdown_application_spec.rb +30 -3
- data/spec/cmd_syncdown_both_spec.rb +72 -18
- data/spec/cmd_syncup_spec.rb +71 -5
- data/spec/cmd_token_spec.rb +2 -2
- data/spec/cmd_usage_spec.rb +2 -2
- data/spec/dry_run_formatter.rb +27 -0
- data/spec/fixtures/dumped_config +8 -0
- data/spec/fixtures/exchange_element/element-show.json +1 -0
- data/spec/fixtures/exchange_element/swagger-mur-6407__10k.yaml +282 -0
- data/spec/fixtures/exchange_element/swagger-mur-6407__20k.yaml +588 -0
- data/spec/variegated_TruthyFalsey_spec.rb +29 -0
- metadata +51 -25
|
@@ -5,14 +5,16 @@
|
|
|
5
5
|
# vim:tw=0:ts=2:sw=2:et:ai
|
|
6
6
|
# Unauthorized copying of this file is strictly prohibited.
|
|
7
7
|
|
|
8
|
+
require 'digest/md5'
|
|
8
9
|
require 'digest/sha1'
|
|
9
10
|
require 'http/form_data'
|
|
10
11
|
require 'mime/types'
|
|
11
12
|
require 'net/http'
|
|
12
13
|
require 'pathname'
|
|
13
14
|
require 'uri'
|
|
14
|
-
require 'MrMurano/
|
|
15
|
+
require 'MrMurano/http'
|
|
15
16
|
require 'MrMurano/SyncRoot'
|
|
17
|
+
require 'MrMurano/Webservice'
|
|
16
18
|
|
|
17
19
|
module MrMurano
|
|
18
20
|
module Webservice
|
|
@@ -20,12 +22,18 @@ module MrMurano
|
|
|
20
22
|
class File < WebserviceBase
|
|
21
23
|
# File Specific details on an Item
|
|
22
24
|
class FileItem < Item
|
|
25
|
+
# For the source of truth of the API response, see:
|
|
26
|
+
# pegasus_registry/services/asset.yaml
|
|
23
27
|
# @return [String] path for URL maps to this static file
|
|
24
28
|
attr_accessor :path
|
|
25
29
|
# @return [String] The MIME-Type for this content
|
|
26
30
|
attr_accessor :mime_type
|
|
27
31
|
# @return [String] Checksum for the content.
|
|
28
32
|
attr_accessor :checksum
|
|
33
|
+
# @return [String] MD5 checksum of the stored file. (Same as :checksum.)
|
|
34
|
+
attr_accessor :md5
|
|
35
|
+
# @return [Integer] Size in bytes of the stored file.
|
|
36
|
+
attr_accessor :size
|
|
29
37
|
end
|
|
30
38
|
|
|
31
39
|
def initialize
|
|
@@ -56,7 +64,7 @@ module MrMurano
|
|
|
56
64
|
|
|
57
65
|
##
|
|
58
66
|
# Get one item of the static content.
|
|
59
|
-
def fetch(path, &block)
|
|
67
|
+
def fetch(path, _untainted=false, &block)
|
|
60
68
|
path = path[1..-1] if path[0] == '/'
|
|
61
69
|
path = '/' + URI.encode_www_form_component(path)
|
|
62
70
|
get(path) do |request, http|
|
|
@@ -93,21 +101,47 @@ module MrMurano
|
|
|
93
101
|
super(request) if request.method != 'PUT'
|
|
94
102
|
end
|
|
95
103
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
104
|
+
def ensure_nonempty_upload(local)
|
|
105
|
+
# FIXME/MUR-6479/MUR-6477: (lb): Remove this function when backend fixed.
|
|
106
|
+
#
|
|
107
|
+
# {"statusCode":400,
|
|
108
|
+
# "message":"The \"data\" argument must be one of type
|
|
109
|
+
# string, TypedArray, or DataView",
|
|
110
|
+
# "code":"BadRequestError"
|
|
111
|
+
# }
|
|
102
112
|
local = Pathname.new(local) unless local.is_a? Pathname
|
|
113
|
+
if !local.size.zero?
|
|
114
|
+
yield local
|
|
115
|
+
else
|
|
116
|
+
# Cannot use Tempfile.open because it make filename unique, e.g.,
|
|
117
|
+
# Tempfile.open(local.basename.to_s) { |tmpf| puts tmpf.path }
|
|
118
|
+
# # /tmp/index.html20180413-15436-5i0s0u
|
|
119
|
+
Dir.mktmpdir do |tmpdir|
|
|
120
|
+
# NOTE: Because our class is named File, we have to descope ::File.
|
|
121
|
+
::File.open(::File.join(tmpdir, local.basename.to_s), 'w') do |tmpf|
|
|
122
|
+
tmpf << "\n"
|
|
123
|
+
tmpf.flush
|
|
124
|
+
local = Pathname.new(tmpf.path)
|
|
125
|
+
yield local
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
103
130
|
|
|
131
|
+
def prepare_upload_req(remote)
|
|
104
132
|
path = remote[:path]
|
|
105
133
|
path = path[1..-1] if path[0] == '/'
|
|
134
|
+
# JANKIE: The endpoint ends in /file, and this makes it /fileupload/, ha!
|
|
106
135
|
uri = endpoint('upload/' + URI.encode_www_form_component(path))
|
|
107
136
|
# kludge past for a bit.
|
|
108
|
-
#`curl -s -H 'Authorization: token #{@token}' '#{uri.to_s}'
|
|
137
|
+
#`curl -s -H 'Authorization: token #{@token}' '#{uri.to_s}' \
|
|
138
|
+
# -F file=@#{local.to_s}`
|
|
139
|
+
Net::HTTP::Put.new(uri)
|
|
140
|
+
end
|
|
109
141
|
|
|
110
|
-
|
|
142
|
+
def prepare_upload_form(local, remote)
|
|
143
|
+
# http://stackoverflow.com/questions/184178/
|
|
144
|
+
# ruby-how-to-post-a-file-via-http-as-multipart-form-data
|
|
111
145
|
#
|
|
112
146
|
# Look at: https://github.com/httprb/http
|
|
113
147
|
# If it works well, consider porting over to it.
|
|
@@ -116,36 +150,53 @@ module MrMurano
|
|
|
116
150
|
#
|
|
117
151
|
# Most of these pull into ram. So maybe just go with that. Would guess that
|
|
118
152
|
# truely large static content is rare, and we can optimize/fix that later.
|
|
119
|
-
|
|
120
153
|
file = HTTP::FormData::File.new(local.to_s, content_type: remote[:mime_type])
|
|
121
|
-
|
|
122
|
-
|
|
154
|
+
HTTP::FormData.create(file: file)
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def dump_upload_curl(request, local)
|
|
158
|
+
a = []
|
|
159
|
+
a << %(curl -s -H 'Authorization: #{request['authorization']}')
|
|
160
|
+
a << %(-H 'User-Agent: #{request['User-Agent']}')
|
|
161
|
+
a << %(-X #{request.method})
|
|
162
|
+
a << %('#{request.uri}')
|
|
163
|
+
a << %(-F file=@#{local})
|
|
164
|
+
ccmd = a.join(' ')
|
|
165
|
+
MrMurano::Http.curldebug_log(ccmd, stamp_it: true)
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
##
|
|
169
|
+
# Upload a file
|
|
170
|
+
# @param src [Pathname] Full path of where to upload from
|
|
171
|
+
# @param item [Hash] The item details to upload
|
|
172
|
+
# @param modify [Boolean] True if item exists and this is changing it
|
|
173
|
+
def upload(local, remote, _modify)
|
|
174
|
+
local = Pathname.new(local) unless local.is_a? Pathname
|
|
175
|
+
request, response = try_upload(local, remote)
|
|
176
|
+
return if response.nil?
|
|
177
|
+
if response.is_a?(Net::HTTPBadRequest) && local.size.zero?
|
|
178
|
+
ensure_nonempty_upload(local) do |nonempty_local|
|
|
179
|
+
request, response = try_upload(nonempty_local, remote)
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
return if response.is_a?(Net::HTTPSuccess)
|
|
183
|
+
showHttpError(request, response)
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def try_upload(local, remote)
|
|
187
|
+
req = prepare_upload_req(remote)
|
|
188
|
+
form = prepare_upload_form(local, remote)
|
|
123
189
|
add_headers(req)
|
|
124
190
|
|
|
125
|
-
return unless upload_item_allowed(remote[@itemkey])
|
|
191
|
+
return [nil, nil] unless upload_item_allowed(remote[@itemkey])
|
|
126
192
|
|
|
127
193
|
workit(req) do |request, http|
|
|
128
194
|
request.content_type = form.content_type
|
|
129
195
|
request.content_length = form.content_length
|
|
130
196
|
request.body = form.to_s
|
|
131
|
-
|
|
132
|
-
if $cfg['tool.curldebug']
|
|
133
|
-
a = []
|
|
134
|
-
a << %(curl -s -H 'Authorization: #{request['authorization']}')
|
|
135
|
-
a << %(-H 'User-Agent: #{request['User-Agent']}')
|
|
136
|
-
a << %(-X #{request.method})
|
|
137
|
-
a << %('#{request.uri}')
|
|
138
|
-
a << %(-F file=@#{local})
|
|
139
|
-
if $cfg.curlfile_f.nil?
|
|
140
|
-
puts a.join(' ')
|
|
141
|
-
else
|
|
142
|
-
$cfg.curlfile_f << a.join(' ') + "\n\n"
|
|
143
|
-
$cfg.curlfile_f.flush
|
|
144
|
-
end
|
|
145
|
-
end
|
|
146
|
-
|
|
197
|
+
dump_upload_curl(request, local) if $cfg['tool.curldebug']
|
|
147
198
|
response = http.request(request)
|
|
148
|
-
|
|
199
|
+
[request, response]
|
|
149
200
|
end
|
|
150
201
|
end
|
|
151
202
|
|
|
@@ -153,6 +204,7 @@ module MrMurano
|
|
|
153
204
|
# @param itemkey [Symbol] Key for look up.
|
|
154
205
|
def tolocalname(item, key)
|
|
155
206
|
name = item[key]
|
|
207
|
+
# If service says '/', assume filename is e.g., 'index.html'.
|
|
156
208
|
name = $cfg['files.default_page'] if name == '/'
|
|
157
209
|
name
|
|
158
210
|
end
|
|
@@ -168,20 +220,28 @@ module MrMurano
|
|
|
168
220
|
|
|
169
221
|
mime = MIME::Types.type_for(path.to_s)[0] || MIME::Types['application/octet-stream'][0]
|
|
170
222
|
|
|
171
|
-
#
|
|
172
|
-
#
|
|
173
|
-
#
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
#
|
|
177
|
-
#
|
|
178
|
-
|
|
179
|
-
|
|
223
|
+
# FIXME/2018-04-13: (lb): When did platform switch from SHA1 to MD5?
|
|
224
|
+
# Leaving this dead code block as a reminder to verify the new
|
|
225
|
+
# behavior is the intended behavior.
|
|
226
|
+
xsum_is_sha1 = false
|
|
227
|
+
if xsum_is_sha1
|
|
228
|
+
# It does not actually take the SHA1 of the file.
|
|
229
|
+
# It first converts the file to hex, then takes the SHA1 of that string
|
|
230
|
+
#xsum = Digest::SHA1.file(path.to_s).hexdigest
|
|
231
|
+
xsum = Digest::SHA1.new
|
|
232
|
+
path.open('rb:ASCII-8BIT') do |io|
|
|
233
|
+
# rubocop:disable Lint/AssignmentInCondition
|
|
234
|
+
# "Assignment in condition - you probably meant to use ==."
|
|
235
|
+
while chunk = io.read(1_048_576)
|
|
236
|
+
xsum << Digest.hexencode(chunk)
|
|
237
|
+
end
|
|
180
238
|
end
|
|
239
|
+
else
|
|
240
|
+
xsum = Digest::MD5.file(path.to_s)
|
|
181
241
|
end
|
|
182
|
-
debug "Checking #{name} (#{mime.simplified} #{
|
|
242
|
+
debug "Checking #{name} (#{mime.simplified} #{xsum.hexdigest})"
|
|
183
243
|
|
|
184
|
-
FileItem.new(path: name, mime_type: mime.simplified, checksum:
|
|
244
|
+
FileItem.new(path: name, mime_type: mime.simplified, checksum: xsum.hexdigest)
|
|
185
245
|
end
|
|
186
246
|
|
|
187
247
|
# @param item [FileItem] The item to get a key from
|
|
@@ -202,4 +262,4 @@ module MrMurano
|
|
|
202
262
|
SyncRoot.instance.add('assets', File, 'A', true, %w[files])
|
|
203
263
|
end
|
|
204
264
|
end
|
|
205
|
-
|
|
265
|
+
|