MuranoCLI 3.2.0.beta.1 → 3.2.0.beta.5

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