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.
Files changed (111) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +4 -1
  3. data/.trustme.plugin +137 -0
  4. data/.trustme.sh +217 -117
  5. data/.trustme.vim +9 -3
  6. data/Gemfile +9 -3
  7. data/MuranoCLI.gemspec +8 -5
  8. data/Rakefile +1 -0
  9. data/dockers/Dockerfile.2.2.9 +6 -3
  10. data/dockers/Dockerfile.2.3.6 +6 -3
  11. data/dockers/Dockerfile.2.4.3 +6 -3
  12. data/dockers/Dockerfile.2.5.0 +6 -3
  13. data/dockers/Dockerfile.GemRelease +10 -8
  14. data/dockers/Dockerfile.m4 +23 -5
  15. data/dockers/docker-test.sh +65 -28
  16. data/docs/completions/murano_completion-bash +751 -57
  17. data/docs/develop.rst +10 -9
  18. data/lib/MrMurano/AccountBase.rb +95 -6
  19. data/lib/MrMurano/Commander-Entry.rb +9 -4
  20. data/lib/MrMurano/Config-Migrate.rb +2 -0
  21. data/lib/MrMurano/Config.rb +94 -26
  22. data/lib/MrMurano/Content.rb +1 -1
  23. data/lib/MrMurano/Exchange.rb +77 -42
  24. data/lib/MrMurano/Gateway.rb +1 -1
  25. data/lib/MrMurano/HttpAuthed.rb +20 -7
  26. data/lib/MrMurano/Logs.rb +10 -1
  27. data/lib/MrMurano/ProjectFile.rb +1 -1
  28. data/lib/MrMurano/ReCommander.rb +129 -73
  29. data/lib/MrMurano/Solution-ServiceConfig.rb +18 -11
  30. data/lib/MrMurano/Solution-Services.rb +78 -50
  31. data/lib/MrMurano/Solution-Users.rb +1 -1
  32. data/lib/MrMurano/Solution.rb +13 -63
  33. data/lib/MrMurano/SyncUpDown-Core.rb +185 -77
  34. data/lib/MrMurano/SyncUpDown-Item.rb +29 -4
  35. data/lib/MrMurano/SyncUpDown.rb +11 -11
  36. data/lib/MrMurano/Webservice-Cors.rb +1 -1
  37. data/lib/MrMurano/Webservice-Endpoint.rb +28 -17
  38. data/lib/MrMurano/Webservice-File.rb +103 -43
  39. data/lib/MrMurano/commands/domain.rb +1 -0
  40. data/lib/MrMurano/commands/element.rb +585 -0
  41. data/lib/MrMurano/commands/exchange.rb +211 -204
  42. data/lib/MrMurano/commands/gb.rb +1 -0
  43. data/lib/MrMurano/commands/globals.rb +17 -7
  44. data/lib/MrMurano/commands/init.rb +115 -101
  45. data/lib/MrMurano/commands/keystore.rb +1 -1
  46. data/lib/MrMurano/commands/logs.rb +2 -1
  47. data/lib/MrMurano/commands/postgresql.rb +17 -7
  48. data/lib/MrMurano/commands/service.rb +572 -0
  49. data/lib/MrMurano/commands/show.rb +7 -3
  50. data/lib/MrMurano/commands/solution.rb +2 -1
  51. data/lib/MrMurano/commands/solution_picker.rb +31 -15
  52. data/lib/MrMurano/commands/status.rb +205 -169
  53. data/lib/MrMurano/commands/sync.rb +70 -38
  54. data/lib/MrMurano/commands/token.rb +59 -14
  55. data/lib/MrMurano/commands/usage.rb +1 -0
  56. data/lib/MrMurano/commands.rb +2 -0
  57. data/lib/MrMurano/hash.rb +91 -0
  58. data/lib/MrMurano/http.rb +55 -6
  59. data/lib/MrMurano/makePretty.rb +47 -0
  60. data/lib/MrMurano/optparse.rb +60 -45
  61. data/lib/MrMurano/variegated/TruthyFalsey.rb +48 -0
  62. data/lib/MrMurano/variegated/ruby_dig.rb +64 -0
  63. data/lib/MrMurano/verbosing.rb +113 -3
  64. data/lib/MrMurano/version.rb +1 -1
  65. data/spec/Account_spec.rb +34 -20
  66. data/spec/Business_spec.rb +12 -9
  67. data/spec/Config_spec.rb +7 -1
  68. data/spec/Content_spec.rb +17 -1
  69. data/spec/GatewayBase_spec.rb +5 -2
  70. data/spec/GatewayDevice_spec.rb +4 -2
  71. data/spec/GatewayResource_spec.rb +4 -1
  72. data/spec/GatewaySettings_spec.rb +4 -1
  73. data/spec/HttpAuthed_spec.rb +73 -0
  74. data/spec/Http_spec.rb +32 -35
  75. data/spec/ProjectFile_spec.rb +1 -1
  76. data/spec/Solution-ServiceConfig_spec.rb +4 -1
  77. data/spec/Solution-ServiceEventHandler_spec.rb +6 -3
  78. data/spec/Solution-ServiceModules_spec.rb +4 -1
  79. data/spec/Solution-UsersRoles_spec.rb +4 -1
  80. data/spec/Solution_spec.rb +4 -1
  81. data/spec/SyncUpDown_spec.rb +1 -1
  82. data/spec/Webservice-Cors_spec.rb +4 -1
  83. data/spec/Webservice-Endpoint_spec.rb +9 -6
  84. data/spec/Webservice-File_spec.rb +17 -4
  85. data/spec/Webservice-Setting_spec.rb +6 -2
  86. data/spec/_workspace.rb +2 -0
  87. data/spec/cmd_common.rb +42 -13
  88. data/spec/cmd_content_spec.rb +17 -7
  89. data/spec/cmd_device_spec.rb +1 -1
  90. data/spec/cmd_domain_spec.rb +2 -2
  91. data/spec/cmd_element_spec.rb +400 -0
  92. data/spec/cmd_exchange_spec.rb +2 -2
  93. data/spec/cmd_init_spec.rb +59 -25
  94. data/spec/cmd_keystore_spec.rb +6 -3
  95. data/spec/cmd_link_spec.rb +10 -5
  96. data/spec/cmd_logs_spec.rb +1 -1
  97. data/spec/cmd_setting_application_spec.rb +18 -15
  98. data/spec/cmd_setting_product_spec.rb +7 -7
  99. data/spec/cmd_status_spec.rb +27 -17
  100. data/spec/cmd_syncdown_application_spec.rb +30 -3
  101. data/spec/cmd_syncdown_both_spec.rb +72 -18
  102. data/spec/cmd_syncup_spec.rb +71 -5
  103. data/spec/cmd_token_spec.rb +2 -2
  104. data/spec/cmd_usage_spec.rb +2 -2
  105. data/spec/dry_run_formatter.rb +27 -0
  106. data/spec/fixtures/dumped_config +8 -0
  107. data/spec/fixtures/exchange_element/element-show.json +1 -0
  108. data/spec/fixtures/exchange_element/swagger-mur-6407__10k.yaml +282 -0
  109. data/spec/fixtures/exchange_element/swagger-mur-6407__20k.yaml +588 -0
  110. data/spec/variegated_TruthyFalsey_spec.rb +29 -0
  111. 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/Webservice'
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
- # Upload a file
98
- # @param src [Pathname] Full path of where to upload from
99
- # @param item [Hash] The item details to upload
100
- # @param modify [Boolean] True if item exists already and this is changing it
101
- def upload(local, remote, _modify)
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}' -F file=@#{local.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
- # http://stackoverflow.com/questions/184178/ruby-how-to-post-a-file-via-http-as-multipart-form-data
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
- form = HTTP::FormData.create(file: file)
122
- req = Net::HTTP::Put.new(uri)
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
- showHttpError(request, response) unless response.is_a?(Net::HTTPSuccess)
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
- # It does not actually take the SHA1 of the file.
172
- # It first converts the file to hex, then takes the SHA1 of that string
173
- #sha1 = Digest::SHA1.file(path.to_s).hexdigest
174
- sha1 = Digest::SHA1.new
175
- path.open('rb:ASCII-8BIT') do |io|
176
- # rubocop:disable Lint/AssignmentInCondition
177
- # "Assignment in condition - you probably meant to use ==."
178
- while chunk = io.read(1_048_576)
179
- sha1 << Digest.hexencode(chunk)
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} #{sha1.hexdigest})"
242
+ debug "Checking #{name} (#{mime.simplified} #{xsum.hexdigest})"
183
243
 
184
- FileItem.new(path: name, mime_type: mime.simplified, checksum: sha1.hexdigest)
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
- # vim: set ai et sw=2 ts=2 :
265
+
@@ -8,6 +8,7 @@
8
8
  require 'MrMurano/ReCommander'
9
9
  require 'MrMurano/Solution'
10
10
  require 'MrMurano/commands/solution'
11
+ require 'MrMurano/commands/solution_picker'
11
12
 
12
13
  command :domain do |c|
13
14
  c.syntax = %(murano domain)