MuranoCLI 3.0.0 → 3.0.1
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 +50 -27
- data/.trustme.vim +12 -8
- data/bin/murano +23 -8
- data/docs/basic_example.rst +1 -1
- data/docs/completions/murano_completion-bash +88 -0
- data/lib/MrMurano/Account.rb +3 -3
- data/lib/MrMurano/Business.rb +6 -6
- data/lib/MrMurano/Config-Migrate.rb +1 -3
- data/lib/MrMurano/Config.rb +16 -8
- data/lib/MrMurano/Content.rb +56 -45
- data/lib/MrMurano/Gateway.rb +62 -21
- data/lib/MrMurano/Mock.rb +27 -19
- data/lib/MrMurano/Passwords.rb +7 -7
- data/lib/MrMurano/ReCommander.rb +171 -28
- data/lib/MrMurano/Setting.rb +38 -40
- data/lib/MrMurano/Solution-ServiceConfig.rb +2 -1
- data/lib/MrMurano/Solution-Services.rb +196 -61
- data/lib/MrMurano/Solution-Users.rb +7 -7
- data/lib/MrMurano/Solution.rb +22 -8
- data/lib/MrMurano/SolutionId.rb +10 -4
- data/lib/MrMurano/SubCmdGroupContext.rb +14 -5
- data/lib/MrMurano/SyncAllowed.rb +42 -0
- data/lib/MrMurano/SyncUpDown.rb +122 -65
- data/lib/MrMurano/Webservice-Cors.rb +9 -3
- data/lib/MrMurano/Webservice-Endpoint.rb +39 -33
- data/lib/MrMurano/Webservice-File.rb +35 -24
- data/lib/MrMurano/commands/business.rb +18 -18
- data/lib/MrMurano/commands/content.rb +3 -2
- data/lib/MrMurano/commands/devices.rb +137 -22
- data/lib/MrMurano/commands/globals.rb +8 -2
- data/lib/MrMurano/commands/keystore.rb +3 -2
- data/lib/MrMurano/commands/link.rb +13 -13
- data/lib/MrMurano/commands/login.rb +3 -2
- data/lib/MrMurano/commands/mock.rb +4 -3
- data/lib/MrMurano/commands/password.rb +4 -2
- data/lib/MrMurano/commands/postgresql.rb +5 -3
- data/lib/MrMurano/commands/settings.rb +78 -62
- data/lib/MrMurano/commands/show.rb +79 -74
- data/lib/MrMurano/commands/solution.rb +6 -4
- data/lib/MrMurano/commands/solution_picker.rb +5 -4
- data/lib/MrMurano/commands/status.rb +15 -4
- data/lib/MrMurano/commands/timeseries.rb +3 -2
- data/lib/MrMurano/commands/tsdb.rb +3 -2
- data/lib/MrMurano/hash.rb +6 -6
- data/lib/MrMurano/http.rb +66 -67
- data/lib/MrMurano/makePretty.rb +18 -12
- data/lib/MrMurano/progress.rb +9 -2
- data/lib/MrMurano/verbosing.rb +14 -2
- data/lib/MrMurano/version.rb +2 -2
- data/spec/GatewayDevice_spec.rb +190 -149
- data/spec/Mock_spec.rb +3 -3
- data/spec/Solution-ServiceEventHandler_spec.rb +170 -137
- data/spec/SyncUpDown_spec.rb +205 -191
- metadata +3 -2
@@ -1,4 +1,4 @@
|
|
1
|
-
# Last Modified: 2017.08.
|
1
|
+
# Last Modified: 2017.08.22 /coding: utf-8
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
# Copyright © 2016-2017 Exosite LLC.
|
@@ -10,7 +10,7 @@ require 'MrMurano/Business'
|
|
10
10
|
require 'MrMurano/ReCommander'
|
11
11
|
require 'MrMurano/Solution'
|
12
12
|
|
13
|
-
command
|
13
|
+
command :show do |c|
|
14
14
|
c.syntax = %(murano show)
|
15
15
|
c.summary = %(Show readable information about the current configuration)
|
16
16
|
c.description = %(
|
@@ -18,89 +18,94 @@ Show readable information about the current configuration.
|
|
18
18
|
).strip
|
19
19
|
c.project_not_required = true
|
20
20
|
|
21
|
-
c.
|
22
|
-
if args.include?('help')
|
23
|
-
::Commander::UI.enable_paging
|
24
|
-
say MrMurano::SubCmdGroupHelp.new(c).get_help
|
25
|
-
else
|
26
|
-
acc = MrMurano::Account.instance
|
27
|
-
biz = MrMurano::Business.new
|
28
|
-
|
29
|
-
selected_business = nil
|
30
|
-
selected_business_id = $cfg['business.id']
|
31
|
-
unless selected_business_id.to_s.empty?
|
32
|
-
acc.businesses.each do |sol|
|
33
|
-
selected_business = sol if sol.bizid == selected_business_id
|
34
|
-
end
|
35
|
-
end
|
21
|
+
c.option '--[no-]ids', 'Show IDs'
|
36
22
|
|
37
|
-
|
38
|
-
|
39
|
-
unless selected_application_id.to_s.empty?
|
40
|
-
MrMurano::Verbose.whirly_start('Fetching Applications...')
|
41
|
-
biz.applications.each do |sol|
|
42
|
-
selected_application = sol if sol.apiId == selected_application_id
|
43
|
-
end
|
44
|
-
MrMurano::Verbose.whirly_stop
|
45
|
-
end
|
23
|
+
c.action do |args, options|
|
24
|
+
c.verify_arg_count!(args)
|
46
25
|
|
47
|
-
|
48
|
-
|
49
|
-
unless selected_product_id.to_s.empty?
|
50
|
-
MrMurano::Verbose.whirly_start('Fetching Products...')
|
51
|
-
biz.products.each do |sol|
|
52
|
-
selected_product = sol if sol.apiId == selected_product_id
|
53
|
-
end
|
54
|
-
MrMurano::Verbose.whirly_stop
|
55
|
-
end
|
26
|
+
acc = MrMurano::Account.instance
|
27
|
+
biz = MrMurano::Business.new
|
56
28
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
29
|
+
selected_business = nil
|
30
|
+
selected_business_id = $cfg['business.id']
|
31
|
+
unless selected_business_id.to_s.empty?
|
32
|
+
acc.businesses.each do |sol|
|
33
|
+
selected_business = sol if sol.bizid == selected_business_id
|
61
34
|
end
|
35
|
+
end
|
62
36
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
37
|
+
selected_application = nil
|
38
|
+
selected_application_id = $cfg['application.id']
|
39
|
+
unless selected_application_id.to_s.empty?
|
40
|
+
MrMurano::Verbose.whirly_start('Fetching Applications...')
|
41
|
+
biz.applications.each do |sol|
|
42
|
+
selected_application = sol if sol.apiId == selected_application_id
|
68
43
|
end
|
44
|
+
MrMurano::Verbose.whirly_stop
|
45
|
+
end
|
69
46
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
elsif selected_application_id
|
77
|
-
#puts 'selected application not in business'
|
78
|
-
puts "application ID from config is not in business (#{selected_application_id})"
|
79
|
-
id_not_in_biz = true
|
80
|
-
elsif !selected_business
|
81
|
-
puts 'application ID depends on business ID'
|
82
|
-
else
|
83
|
-
#puts 'no application selected'
|
84
|
-
puts 'application ID not found in config'
|
47
|
+
selected_product = nil
|
48
|
+
selected_product_id = $cfg['product.id']
|
49
|
+
unless selected_product_id.to_s.empty?
|
50
|
+
MrMurano::Verbose.whirly_start('Fetching Products...')
|
51
|
+
biz.products.each do |sol|
|
52
|
+
selected_product = sol if sol.apiId == selected_product_id
|
85
53
|
end
|
54
|
+
MrMurano::Verbose.whirly_stop
|
55
|
+
end
|
86
56
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
57
|
+
if $cfg['user.name']
|
58
|
+
puts %(user: #{$cfg['user.name']})
|
59
|
+
else
|
60
|
+
puts 'no user selected'
|
61
|
+
end
|
62
|
+
|
63
|
+
if selected_business
|
64
|
+
biz_info = %(business: #{selected_business.name})
|
65
|
+
biz_info += %( <#{selected_business.bid}>) if options.ids
|
66
|
+
puts biz_info
|
67
|
+
else
|
68
|
+
#puts 'no business selected'
|
69
|
+
MrMurano::Verbose.error MrMurano::Business.missing_business_id_msg
|
70
|
+
end
|
101
71
|
|
102
|
-
|
72
|
+
id_not_in_biz = false
|
73
|
+
|
74
|
+
# E.g., {:bizid=>"ABC", :type=>"application", :apiId=>"XXX", :sid=>"XXX",
|
75
|
+
# :name=>"ABC", :domain=>"ABC.apps.exosite.io" }
|
76
|
+
if selected_application
|
77
|
+
sol_info = %(application: https://#{selected_application.domain})
|
78
|
+
sol_info += %( <#{selected_application.sid}>) if options.ids
|
79
|
+
puts sol_info
|
80
|
+
elsif selected_application_id
|
81
|
+
#puts 'selected application not in business'
|
82
|
+
puts "application ID from config is not in business (#{selected_application_id})"
|
83
|
+
id_not_in_biz = true
|
84
|
+
elsif !selected_business
|
85
|
+
puts 'application ID depends on business ID'
|
86
|
+
else
|
87
|
+
#puts 'no application selected'
|
88
|
+
puts 'application ID not found in config'
|
103
89
|
end
|
90
|
+
|
91
|
+
# E.g., {:bizid=>"ABC", :type=>"product", :apiId=>"XXX", :sid=>"XXX",
|
92
|
+
# :name=>"ABC", :domain=>"ABC.m2.exosite.io" }
|
93
|
+
if selected_product
|
94
|
+
sol_info = %(product: #{selected_product.name})
|
95
|
+
sol_info += %( <#{selected_product.sid}>) if options.ids
|
96
|
+
puts sol_info
|
97
|
+
elsif selected_product_id
|
98
|
+
#puts 'selected product not in business'
|
99
|
+
puts "product ID from config is not in business (#{selected_product_id})"
|
100
|
+
id_not_in_biz = true
|
101
|
+
elsif !selected_business
|
102
|
+
puts 'product ID depends on business ID'
|
103
|
+
else
|
104
|
+
#puts 'no product selected'
|
105
|
+
puts 'product ID not found in config'
|
106
|
+
end
|
107
|
+
|
108
|
+
MrMurano::SolutionBase.warn_configfile_env_maybe if id_not_in_biz
|
104
109
|
end
|
105
110
|
end
|
106
111
|
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Last Modified: 2017.08.
|
1
|
+
# Last Modified: 2017.08.23 /coding: utf-8
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
# Copyright © 2016-2017 Exosite LLC.
|
@@ -19,9 +19,10 @@ command :solution do |c|
|
|
19
19
|
Commands for working with Application and Product solutions.
|
20
20
|
).strip
|
21
21
|
c.project_not_required = true
|
22
|
+
c.subcmdgrouphelp = true
|
22
23
|
|
23
24
|
c.action do |_args, _options|
|
24
|
-
::Commander::UI.enable_paging
|
25
|
+
::Commander::UI.enable_paging unless $cfg['tool.no-page']
|
25
26
|
say MrMurano::SubCmdGroupHelp.new(c).get_help
|
26
27
|
end
|
27
28
|
end
|
@@ -156,7 +157,7 @@ def cmd_solution_del_get_names_and_ids!(biz, args, options)
|
|
156
157
|
end
|
157
158
|
solz = must_fetch_solutions!(options, args, biz)
|
158
159
|
solz.each do |sol|
|
159
|
-
nmorids += [[sol.sid, "
|
160
|
+
nmorids += [[sol.sid, "#{MrMurano::Verbose.fancy_ticks(sol.name)} <#{sol.sid}>", sol]]
|
160
161
|
end
|
161
162
|
nmorids
|
162
163
|
end
|
@@ -230,7 +231,8 @@ def solution_delete(name_or_id, use_sol: nil, type: :all, yes: false)
|
|
230
231
|
n_faulted = 0
|
231
232
|
if solz.empty?
|
232
233
|
if !name_or_id.empty?
|
233
|
-
MrMurano::Verbose.
|
234
|
+
name_or_id_q = MrMurano::Verbose.fancy_ticks(name_or_id)
|
235
|
+
MrMurano::Verbose.error("No solution matching #{name_or_id_q} found")
|
234
236
|
else
|
235
237
|
MrMurano::Verbose.error(MSG_SOLUTIONS_NONE_FOUND)
|
236
238
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Last Modified: 2017.08.
|
1
|
+
# Last Modified: 2017.08.23 /coding: utf-8
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
# Copyright © 2016-2017 Exosite LLC.
|
@@ -156,12 +156,12 @@ def must_fetch_solutions!(options, args=[], biz=nil)
|
|
156
156
|
|
157
157
|
if args.none? && !any_solution_pickers!(options)
|
158
158
|
if !options.all
|
159
|
-
if $cfg['application.id']
|
159
|
+
if %i[all application].include?(options.type) && $cfg['application.id']
|
160
160
|
solz += solution_get_solutions(
|
161
161
|
biz, :application, sid: $cfg['application.id']
|
162
162
|
)
|
163
163
|
end
|
164
|
-
if $cfg['product.id']
|
164
|
+
if %i[all product].include?(options.type) && $cfg['product.id']
|
165
165
|
solz += solution_get_solutions(
|
166
166
|
biz, :product, sid: $cfg['product.id']
|
167
167
|
)
|
@@ -449,7 +449,8 @@ module MrMurano
|
|
449
449
|
say "Found #{sol.type_name} #{sol.pretty_desc}"
|
450
450
|
elsif !@searching
|
451
451
|
# The solution ID in the config was not found for this business.
|
452
|
-
|
452
|
+
tried_sid = MrMurano::Verbose.fancy_ticks(tried_sid)
|
453
|
+
say "The #{sol.type_name} ID #{tried_sid} from the config was not found"
|
453
454
|
end
|
454
455
|
puts ''
|
455
456
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Last Modified: 2017.08.
|
1
|
+
# Last Modified: 2017.08.22 /coding: utf-8
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
# Copyright © 2016-2017 Exosite LLC.
|
@@ -109,6 +109,7 @@ Endpoints can be selected with a "#<method>#<path glob>" pattern.
|
|
109
109
|
unless item[:pp_desc].to_s.empty? || item[:pp_desc] == item[:synckey]
|
110
110
|
desc += " (#{item[:pp_desc]})"
|
111
111
|
end
|
112
|
+
# NOTE: This path is the endpoint path.
|
112
113
|
desc += " [#{item[:method]} #{item[:path]}]" if item[:method] && item[:path]
|
113
114
|
desc
|
114
115
|
end
|
@@ -149,6 +150,16 @@ Endpoints can be selected with a "#<method>#<path glob>" pattern.
|
|
149
150
|
end
|
150
151
|
end
|
151
152
|
|
153
|
+
unless ret[:clash].empty?
|
154
|
+
pretty_group_header(
|
155
|
+
ret[:clash], 'Conflicting items', 'in conflict', options.grouped
|
156
|
+
)
|
157
|
+
ret[:clash].each do |item|
|
158
|
+
abbrev = $cfg['tool.ascii'] && 'x' || '✗'
|
159
|
+
interject " #{abbrev} #{item[:pp_type]} #{highlight_del(fmtr(item, options))}"
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
152
163
|
return unless options.show_all
|
153
164
|
interject 'Unchanged:' if options.grouped
|
154
165
|
ret[:unchg].each { |item| interject " #{item[:pp_type]} #{fmtr(item, options)}" }
|
@@ -171,15 +182,15 @@ Endpoints can be selected with a "#<method>#<path glob>" pattern.
|
|
171
182
|
Rainbow(msg).red.bright
|
172
183
|
end
|
173
184
|
|
174
|
-
@grouped = { toadd: [], todel: [], tomod: [], unchg: [], skipd: [] }
|
185
|
+
@grouped = { toadd: [], todel: [], tomod: [], unchg: [], skipd: [], clash: [] }
|
175
186
|
def gmerge(ret, type, desc, options)
|
176
187
|
if options.grouped
|
177
188
|
out = @grouped
|
178
189
|
else
|
179
|
-
out = { toadd: [], todel: [], tomod: [], unchg: [], skipd: [] }
|
190
|
+
out = { toadd: [], todel: [], tomod: [], unchg: [], skipd: [], clash: [] }
|
180
191
|
end
|
181
192
|
|
182
|
-
%i[toadd todel tomod unchg skipd].each do |kind|
|
193
|
+
%i[toadd todel tomod unchg skipd clash].each do |kind|
|
183
194
|
ret[kind].each do |item|
|
184
195
|
item = item.to_h
|
185
196
|
item[:pp_type] = type
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Last Modified: 2017.08.
|
1
|
+
# Last Modified: 2017.08.22 /coding: utf-8
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
# Copyright © 2016-2017 Exosite LLC.
|
@@ -42,9 +42,10 @@ The timeseries sub-commands let you interact directly with the Timeseries
|
|
42
42
|
instance in a solution. This allows for easier debugging, being able to
|
43
43
|
quickly try out different queries or write test data.
|
44
44
|
).strip
|
45
|
+
c.subcmdgrouphelp = true
|
45
46
|
|
46
47
|
c.action do |_args, _options|
|
47
|
-
::Commander::UI.enable_paging
|
48
|
+
::Commander::UI.enable_paging unless $cfg['tool.no-page']
|
48
49
|
say MrMurano::SubCmdGroupHelp.new(c).get_help
|
49
50
|
end
|
50
51
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Last Modified: 2017.08.
|
1
|
+
# Last Modified: 2017.08.22 /coding: utf-8
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
# Copyright © 2016-2017 Exosite LLC.
|
@@ -59,9 +59,10 @@ solution. This allows for easier debugging, being able to quickly try out
|
|
59
59
|
different queries or write test data.
|
60
60
|
).strip
|
61
61
|
c.project_not_required = true
|
62
|
+
c.subcmdgrouphelp = true
|
62
63
|
|
63
64
|
c.action do |_args, _options|
|
64
|
-
::Commander::UI.enable_paging
|
65
|
+
::Commander::UI.enable_paging unless $cfg['tool.no-page']
|
65
66
|
say MrMurano::SubCmdGroupHelp.new(c).get_help
|
66
67
|
end
|
67
68
|
end
|
data/lib/MrMurano/hash.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Last Modified: 2017.08.
|
1
|
+
# Last Modified: 2017.08.20 /coding: utf-8
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
# Copyright © 2016-2017 Exosite LLC.
|
@@ -14,8 +14,8 @@ class Hash
|
|
14
14
|
# Take keys of hash and transform those to symbols.
|
15
15
|
def self.transform_keys_to_symbols(value)
|
16
16
|
return value.map { |v| Hash.transform_keys_to_symbols(v) } if value.is_a?(Array)
|
17
|
-
return value
|
18
|
-
value.inject({}) { |memo, (k,v)| memo[k.to_sym] = Hash.transform_keys_to_symbols(v); memo }
|
17
|
+
return value unless value.is_a?(Hash)
|
18
|
+
value.inject({}) { |memo, (k, v)| memo[k.to_sym] = Hash.transform_keys_to_symbols(v); memo }
|
19
19
|
end
|
20
20
|
|
21
21
|
# From:
|
@@ -24,8 +24,8 @@ class Hash
|
|
24
24
|
# Take keys of hash and transform those to strings.
|
25
25
|
def self.transform_keys_to_strings(value)
|
26
26
|
return value.map { |v| Hash.transform_keys_to_strings(v) } if value.is_a?(Array)
|
27
|
-
return value
|
28
|
-
value.inject({}) { |memo, (k,v)| memo[k.to_s] = Hash.transform_keys_to_strings(v); memo }
|
27
|
+
return value unless value.is_a?(Hash)
|
28
|
+
value.inject({}) { |memo, (k, v)| memo[k.to_s] = Hash.transform_keys_to_strings(v); memo }
|
29
29
|
end
|
30
30
|
|
31
31
|
# From Rails.
|
@@ -35,7 +35,7 @@ class Hash
|
|
35
35
|
if this_value.is_a?(Hash) && other_value.is_a?(Hash)
|
36
36
|
self[current_key] = this_value.deep_merge(other_value, &block)
|
37
37
|
elsif block_given? && key?(current_key)
|
38
|
-
self[current_key] =
|
38
|
+
self[current_key] = yield(current_key, this_value, other_value)
|
39
39
|
else
|
40
40
|
self[current_key] = other_value
|
41
41
|
end
|
data/lib/MrMurano/http.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Last Modified: 2017.08.
|
1
|
+
# Last Modified: 2017.08.20 /coding: utf-8
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
# Copyright © 2016-2017 Exosite LLC.
|
@@ -30,50 +30,48 @@ module MrMurano
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def ensure_token!(tok)
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
end
|
33
|
+
return unless tok.nil?
|
34
|
+
error 'Not logged in!'
|
35
|
+
exit 1
|
37
36
|
end
|
38
37
|
|
39
38
|
def json_opts
|
40
|
-
return @json_opts unless
|
39
|
+
return @json_opts unless !defined?(@json_opts) || @json_opts.nil?
|
41
40
|
@json_opts = {
|
42
|
-
:
|
43
|
-
:
|
44
|
-
:
|
41
|
+
allow_nan: true,
|
42
|
+
symbolize_names: true,
|
43
|
+
create_additions: false,
|
45
44
|
}
|
46
45
|
end
|
47
46
|
|
48
47
|
def curldebug(request)
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
else
|
67
|
-
a << %{-d '#{request.body}'}
|
68
|
-
end
|
69
|
-
end
|
70
|
-
if $cfg.curlfile_f.nil?
|
71
|
-
MrMurano::Progress.instance.whirly_interject { puts a.join(' ') }
|
48
|
+
return unless $cfg['tool.curldebug']
|
49
|
+
formp = (request.content_type =~ %r{multipart/form-data})
|
50
|
+
a = []
|
51
|
+
a << %(curl -s)
|
52
|
+
if request.key?('Authorization')
|
53
|
+
a << %(-H 'Authorization: #{request['Authorization']}')
|
54
|
+
end
|
55
|
+
a << %(-H 'User-Agent: #{request['User-Agent']}')
|
56
|
+
a << %(-H 'Content-Type: #{request.content_type}') unless formp
|
57
|
+
a << %(-X #{request.method})
|
58
|
+
a << %('#{request.uri}')
|
59
|
+
unless request.body.nil?
|
60
|
+
if formp
|
61
|
+
m = request.body.match(
|
62
|
+
/form-data;\s+name="(?<name>[^"]+)";\s+filename="(?<filename>[^"]+)"/
|
63
|
+
)
|
64
|
+
a << %(-F #{m[:name]}=@#{m[:filename]}) unless m.nil?
|
72
65
|
else
|
73
|
-
|
74
|
-
$cfg.curlfile_f.flush
|
66
|
+
a << %(-d '#{request.body}')
|
75
67
|
end
|
76
68
|
end
|
69
|
+
if $cfg.curlfile_f.nil?
|
70
|
+
MrMurano::Progress.instance.whirly_interject { puts a.join(' ') }
|
71
|
+
else
|
72
|
+
$cfg.curlfile_f << a.join(' ') + "\n\n"
|
73
|
+
$cfg.curlfile_f.flush
|
74
|
+
end
|
77
75
|
end
|
78
76
|
|
79
77
|
# Default endpoint unless Class overrides it.
|
@@ -83,18 +81,19 @@ module MrMurano
|
|
83
81
|
|
84
82
|
def http
|
85
83
|
uri = URI('https://' + $cfg['net.host'])
|
86
|
-
if
|
84
|
+
if !defined?(@http) || @http.nil?
|
87
85
|
@http = Net::HTTP.new(uri.host, uri.port)
|
88
86
|
@http.use_ssl = true
|
89
87
|
@http.start
|
90
88
|
end
|
91
89
|
@http
|
92
90
|
end
|
91
|
+
|
93
92
|
def http_reset
|
94
93
|
@http = nil
|
95
94
|
end
|
96
95
|
|
97
|
-
def
|
96
|
+
def add_headers(request)
|
98
97
|
request.content_type = 'application/json'
|
99
98
|
# 2017-08-14: MrMurano::Account overrides the token method, and
|
100
99
|
# it doesn't exit if no token, and then we end up here.
|
@@ -104,24 +103,24 @@ module MrMurano
|
|
104
103
|
request
|
105
104
|
end
|
106
105
|
|
106
|
+
# rubocop:disable Style/MethodName "Use snake_case for method names."
|
107
|
+
# 2017-08-20: isJSON and showHttpError are grandparented into lint exceptions.
|
107
108
|
def isJSON(data)
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
[false, data]
|
112
|
-
end
|
109
|
+
[true, JSON.parse(data, json_opts)]
|
110
|
+
rescue
|
111
|
+
[false, data]
|
113
112
|
end
|
114
113
|
|
115
114
|
def showHttpError(request, response)
|
116
115
|
if $cfg['tool.debug']
|
117
|
-
puts "Sent #{request.method} #{request.uri
|
118
|
-
request.each_capitalized{|k,v| puts "> #{k}: #{v}"}
|
116
|
+
puts "Sent #{request.method} #{request.uri}"
|
117
|
+
request.each_capitalized { |k, v| puts "> #{k}: #{v}" }
|
119
118
|
if request.body.nil?
|
120
119
|
else
|
121
120
|
puts ">> #{request.body[0..156]}"
|
122
121
|
end
|
123
122
|
puts "Got #{response.code} #{response.message}"
|
124
|
-
response.each_capitalized{|k,v| puts "< #{k}: #{v}"}
|
123
|
+
response.each_capitalized { |k, v| puts "< #{k}: #{v}" }
|
125
124
|
end
|
126
125
|
isj, jsn = isJSON(response.body)
|
127
126
|
resp = "Request Failed: #{response.code}: "
|
@@ -130,25 +129,25 @@ module MrMurano
|
|
130
129
|
# to support Ruby 3.0 frozen string literals.
|
131
130
|
if $cfg['tool.fullerror']
|
132
131
|
resp += JSON.pretty_generate(jsn)
|
133
|
-
elsif jsn.
|
134
|
-
resp += "[#{jsn[:statusCode]}] " if jsn.
|
135
|
-
resp += jsn[:message] if jsn.
|
132
|
+
elsif jsn.is_a? Hash
|
133
|
+
resp += "[#{jsn[:statusCode]}] " if jsn.key? :statusCode
|
134
|
+
resp += jsn[:message] if jsn.key? :message
|
136
135
|
else
|
137
136
|
resp += jsn.to_s
|
138
137
|
end
|
139
138
|
else
|
140
|
-
resp += (jsn
|
139
|
+
resp += (jsn || 'nil')
|
141
140
|
end
|
142
141
|
# assuming verbosing was included.
|
143
142
|
error resp
|
144
143
|
end
|
145
144
|
|
146
|
-
def workit(request
|
145
|
+
def workit(request)
|
147
146
|
curldebug(request)
|
148
147
|
if block_given?
|
149
|
-
yield request, http
|
148
|
+
yield request, http
|
150
149
|
else
|
151
|
-
response = http
|
150
|
+
response = http.request(request)
|
152
151
|
case response
|
153
152
|
when Net::HTTPSuccess
|
154
153
|
workit_response(response)
|
@@ -174,13 +173,13 @@ module MrMurano
|
|
174
173
|
def get(path='', query=nil, &block)
|
175
174
|
uri = endpoint(path)
|
176
175
|
uri.query = URI.encode_www_form(query) unless query.nil?
|
177
|
-
workit(
|
176
|
+
workit(add_headers(Net::HTTP::Get.new(uri)), &block)
|
178
177
|
end
|
179
178
|
|
180
179
|
def post(path='', body={}, &block)
|
181
180
|
uri = endpoint(path)
|
182
181
|
req = Net::HTTP::Post.new(uri)
|
183
|
-
|
182
|
+
add_headers(req)
|
184
183
|
req.body = JSON.generate(body)
|
185
184
|
workit(req, &block)
|
186
185
|
end
|
@@ -188,7 +187,7 @@ module MrMurano
|
|
188
187
|
def postf(path='', form={}, &block)
|
189
188
|
uri = endpoint(path)
|
190
189
|
req = Net::HTTP::Post.new(uri)
|
191
|
-
|
190
|
+
add_headers(req)
|
192
191
|
req.content_type = 'application/x-www-form-urlencoded; charset=utf-8'
|
193
192
|
req.form_data = form
|
194
193
|
workit(req, &block)
|
@@ -197,7 +196,7 @@ module MrMurano
|
|
197
196
|
def put(path='', body={}, &block)
|
198
197
|
uri = endpoint(path)
|
199
198
|
req = Net::HTTP::Put.new(uri)
|
200
|
-
|
199
|
+
add_headers(req)
|
201
200
|
req.body = JSON.generate(body)
|
202
201
|
workit(req, &block)
|
203
202
|
end
|
@@ -205,14 +204,14 @@ module MrMurano
|
|
205
204
|
def patch(path='', body={}, &block)
|
206
205
|
uri = endpoint(path)
|
207
206
|
req = Net::HTTP::Patch.new(uri)
|
208
|
-
|
207
|
+
add_headers(req)
|
209
208
|
req.body = JSON.generate(body)
|
210
209
|
workit(req, &block)
|
211
210
|
end
|
212
211
|
|
213
212
|
def delete(path='', &block)
|
214
213
|
uri = endpoint(path)
|
215
|
-
workit(
|
214
|
+
workit(add_headers(Net::HTTP::Delete.new(uri)), &block)
|
216
215
|
end
|
217
216
|
end
|
218
217
|
end
|
@@ -238,17 +237,17 @@ if RUBY_VERSION == '2.0.0'
|
|
238
237
|
end
|
239
238
|
|
240
239
|
D "opening connection to #{conn_address}:#{conn_port}..."
|
241
|
-
s = Timeout.timeout(@open_timeout, Net::OpenTimeout)
|
240
|
+
s = Timeout.timeout(@open_timeout, Net::OpenTimeout) do
|
242
241
|
TCPSocket.open(conn_address, conn_port, @local_host, @local_port)
|
243
|
-
|
242
|
+
end
|
244
243
|
s.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
|
245
|
-
D
|
244
|
+
D 'opened'
|
246
245
|
if use_ssl?
|
247
|
-
ssl_parameters =
|
246
|
+
ssl_parameters = {}
|
248
247
|
iv_list = instance_variables
|
249
248
|
SSL_IVNAMES.each_with_index do |ivname, i|
|
250
|
-
if iv_list.include?(ivname)
|
251
|
-
|
249
|
+
if iv_list.include?(ivname)
|
250
|
+
value = instance_variable_get(ivname)
|
252
251
|
ssl_parameters[SSL_ATTRIBUTES[i]] = value if value
|
253
252
|
end
|
254
253
|
end
|
@@ -257,7 +256,7 @@ if RUBY_VERSION == '2.0.0'
|
|
257
256
|
D "starting SSL for #{conn_address}:#{conn_port}..."
|
258
257
|
s = OpenSSL::SSL::SSLSocket.new(s, @ssl_context)
|
259
258
|
s.sync_close = true
|
260
|
-
D
|
259
|
+
D 'SSL established'
|
261
260
|
end
|
262
261
|
@socket = BufferedIO.new(s)
|
263
262
|
@socket.read_timeout = @read_timeout
|
@@ -281,8 +280,8 @@ if RUBY_VERSION == '2.0.0'
|
|
281
280
|
end
|
282
281
|
# Server Name Indication (SNI) RFC 3546
|
283
282
|
s.hostname = @address if s.respond_to? :hostname=
|
284
|
-
if @ssl_session
|
285
|
-
|
283
|
+
if @ssl_session &&
|
284
|
+
Time.now < @ssl_session.time + @ssl_session.timeout
|
286
285
|
s.session = @ssl_session if @ssl_session
|
287
286
|
end
|
288
287
|
Timeout.timeout(@open_timeout, Net::OpenTimeout) { s.connect }
|
@@ -292,7 +291,7 @@ if RUBY_VERSION == '2.0.0'
|
|
292
291
|
@ssl_session = s.session
|
293
292
|
rescue => exception
|
294
293
|
D "Conn close because of connect error #{exception}"
|
295
|
-
@socket.close if @socket
|
294
|
+
@socket.close if @socket && !@socket.closed?
|
296
295
|
raise exception
|
297
296
|
end
|
298
297
|
end
|