MuranoCLI 3.2.1.pre.beta.4 → 3.2.1.pre.beta.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (145) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +4 -0
  3. data/Gemfile +4 -3
  4. data/HISTORY.md +826 -0
  5. data/Rakefile +415 -47
  6. data/docs/release.rst +275 -0
  7. data/lib/MrMurano/Account.rb +46 -47
  8. data/lib/MrMurano/AccountBase.rb +1 -0
  9. data/lib/MrMurano/Business.rb +183 -44
  10. data/lib/MrMurano/Config.rb +1 -0
  11. data/lib/MrMurano/Exchange.rb +3 -4
  12. data/lib/MrMurano/Solution-Services.rb +25 -7
  13. data/lib/MrMurano/Webservice-File.rb +5 -7
  14. data/lib/MrMurano/commands/business.rb +231 -24
  15. data/lib/MrMurano/commands/child.rb +3 -3
  16. data/lib/MrMurano/commands/element.rb +1 -0
  17. data/lib/MrMurano/commands/settings.rb +7 -0
  18. data/lib/MrMurano/http.rb +1 -3
  19. data/lib/MrMurano/progress.rb +12 -2
  20. data/lib/MrMurano/verbosing.rb +7 -7
  21. data/lib/MrMurano/version.rb +1 -1
  22. data/spec/Account_spec.rb +9 -0
  23. data/spec/ProjectFile_spec.rb +7 -9
  24. data/spec/Webservice-File_spec.rb +2 -1
  25. data/spec/cmd_business_spec.rb +1 -1
  26. data/spec/cmd_common.rb +75 -30
  27. data/spec/cmd_content_spec.rb +3 -1
  28. data/spec/cmd_cors_spec.rb +3 -1
  29. data/spec/cmd_device_spec.rb +7 -5
  30. data/spec/cmd_domain_spec.rb +6 -2
  31. data/spec/cmd_help_spec.rb +13 -6
  32. data/spec/cmd_init_spec.rb +19 -10
  33. data/spec/cmd_keystore_spec.rb +3 -1
  34. data/spec/cmd_link_spec.rb +5 -5
  35. data/spec/cmd_setting_application_spec.rb +13 -16
  36. data/spec/cmd_setting_product_spec.rb +14 -14
  37. data/spec/cmd_status_spec.rb +6 -2
  38. data/spec/cmd_syncdown_application_spec.rb +3 -1
  39. data/spec/cmd_syncdown_both_spec.rb +6 -2
  40. data/spec/cmd_syncdown_unit_spec.rb +3 -0
  41. data/spec/cmd_syncup_spec.rb +8 -4
  42. data/spec/cmd_usage_spec.rb +10 -2
  43. data/spec/fixtures/snapshots/murano application setting Writes (using Webservice.cors) a bool value 0.webmock +98 -0
  44. data/spec/fixtures/snapshots/murano application setting Writes (using Webservice.cors) a bool value 1.webmock +98 -0
  45. data/spec/fixtures/snapshots/murano application setting Writes (using Webservice.cors) a bool value No.webmock +98 -0
  46. data/spec/fixtures/snapshots/murano application setting Writes (using Webservice.cors) a bool value Yes.webmock +98 -0
  47. data/spec/fixtures/snapshots/murano application setting Writes (using Webservice.cors) a bool value bob.webmock +72 -0
  48. data/spec/fixtures/snapshots/murano application setting Writes (using Webservice.cors) a bool value false.webmock +98 -0
  49. data/spec/fixtures/snapshots/murano application setting Writes (using Webservice.cors) a bool value off.webmock +98 -0
  50. data/spec/fixtures/snapshots/murano application setting Writes (using Webservice.cors) a bool value on STDIN.webmock +98 -0
  51. data/spec/fixtures/snapshots/murano application setting Writes (using Webservice.cors) a bool value on.webmock +98 -0
  52. data/spec/fixtures/snapshots/murano application setting Writes (using Webservice.cors) a bool value true.webmock +98 -0
  53. data/spec/fixtures/snapshots/murano application setting Writes (using Webservice.cors) a json array blob with STDIN.webmock +98 -0
  54. data/spec/fixtures/snapshots/murano application setting Writes (using Webservice.cors) a json array blob.webmock +98 -0
  55. data/spec/fixtures/snapshots/murano application setting Writes (using Webservice.cors) an array.webmock +98 -0
  56. data/spec/fixtures/snapshots/murano application setting Writes (using Webservice.cors) appends an array.webmock +98 -0
  57. data/spec/fixtures/snapshots/murano application setting reads Webservice.cors to a file.webmock +72 -0
  58. data/spec/fixtures/snapshots/murano application setting reads Webservice.cors.webmock +72 -0
  59. data/spec/fixtures/snapshots/murano business list as json.webmock +27 -0
  60. data/spec/fixtures/snapshots/murano business list as table.webmock +27 -0
  61. data/spec/fixtures/snapshots/murano business list fewer fields.webmock +27 -0
  62. data/spec/fixtures/snapshots/murano business list only ids.webmock +27 -0
  63. data/spec/fixtures/snapshots/murano business list output to file.webmock +27 -0
  64. data/spec/fixtures/snapshots/murano business without project help.webmock +9 -0
  65. data/spec/fixtures/snapshots/murano config Needs a key.webmock +9 -0
  66. data/spec/fixtures/snapshots/murano config Reads a key.webmock +9 -0
  67. data/spec/fixtures/snapshots/murano config Removes a key.webmock +9 -0
  68. data/spec/fixtures/snapshots/murano config Sets a key.webmock +9 -0
  69. data/spec/fixtures/snapshots/murano config Sets a user key.webmock +9 -0
  70. data/spec/fixtures/snapshots/murano content life cycle.webmock +144 -0
  71. data/spec/fixtures/snapshots/murano cors sets CORS.webmock +78 -0
  72. data/spec/fixtures/snapshots/murano cors show CORS.webmock +64 -0
  73. data/spec/fixtures/snapshots/murano device activates.webmock +86 -0
  74. data/spec/fixtures/snapshots/murano device enables a batch.webmock +76 -0
  75. data/spec/fixtures/snapshots/murano device enables and lists.webmock +78 -0
  76. data/spec/fixtures/snapshots/murano device writes and reads.webmock +136 -0
  77. data/spec/fixtures/snapshots/murano domain show domain.webmock +101 -0
  78. data/spec/fixtures/snapshots/murano element edit unknown as unknown element.webmock +43 -0
  79. data/spec/fixtures/snapshots/murano element show --help.webmock +9 -0
  80. data/spec/fixtures/snapshots/murano element show as csv.webmock +43 -0
  81. data/spec/fixtures/snapshots/murano element show as default-table.webmock +43 -0
  82. data/spec/fixtures/snapshots/murano element show as json.webmock +43 -0
  83. data/spec/fixtures/snapshots/murano element show as table truncate.webmock +43 -0
  84. data/spec/fixtures/snapshots/murano element show as table wrap.webmock +43 -0
  85. data/spec/fixtures/snapshots/murano element show as yaml.webmock +43 -0
  86. data/spec/fixtures/snapshots/murano element show using ambiguous name.webmock +43 -0
  87. data/spec/fixtures/snapshots/murano element without project usage.webmock +9 -0
  88. data/spec/fixtures/snapshots/murano exchange with project list as json.webmock +59 -0
  89. data/spec/fixtures/snapshots/murano exchange with project list as table.webmock +59 -0
  90. data/spec/fixtures/snapshots/murano exchange with project list fewer fields.webmock +59 -0
  91. data/spec/fixtures/snapshots/murano exchange with project list only ids.webmock +59 -0
  92. data/spec/fixtures/snapshots/murano exchange with project list output to file.webmock +59 -0
  93. data/spec/fixtures/snapshots/murano exchange with project list purchase is already added ID.webmock +83 -0
  94. data/spec/fixtures/snapshots/murano exchange with project list purchase is ambiguous name.webmock +59 -0
  95. data/spec/fixtures/snapshots/murano exchange without project help.webmock +9 -0
  96. data/spec/fixtures/snapshots/murano help using commander as --help.webmock +9 -0
  97. data/spec/fixtures/snapshots/murano help using commander no args.webmock +9 -0
  98. data/spec/fixtures/snapshots/murano help using subshell no args.webmock +9 -0
  99. data/spec/fixtures/snapshots/murano help using subshell with --help.webmock +9 -0
  100. data/spec/fixtures/snapshots/murano init Won't init in HOME (gracefully).webmock +9 -0
  101. data/spec/fixtures/snapshots/murano init in empty directory with existing project.webmock +201 -0
  102. data/spec/fixtures/snapshots/murano init in empty directory without existing project.webmock +193 -0
  103. data/spec/fixtures/snapshots/murano init in existing project directory with ProjectFile.webmock +213 -0
  104. data/spec/fixtures/snapshots/murano init in existing project directory with SolutionFile 0.2.0.webmock +213 -0
  105. data/spec/fixtures/snapshots/murano init in existing project directory with SolutionFile 0.3.0.webmock +213 -0
  106. data/spec/fixtures/snapshots/murano init in existing project directory without ProjectFile.webmock +213 -0
  107. data/spec/fixtures/snapshots/murano keystore can call other commands.webmock +108 -0
  108. data/spec/fixtures/snapshots/murano keystore clearAll.webmock +124 -0
  109. data/spec/fixtures/snapshots/murano keystore deletes.webmock +112 -0
  110. data/spec/fixtures/snapshots/murano keystore gets.webmock +96 -0
  111. data/spec/fixtures/snapshots/murano keystore infos.webmock +96 -0
  112. data/spec/fixtures/snapshots/murano keystore lists.webmock +96 -0
  113. data/spec/fixtures/snapshots/murano link with project links and lists.webmock +149 -0
  114. data/spec/fixtures/snapshots/murano link with project unlinks.webmock +165 -0
  115. data/spec/fixtures/snapshots/murano link without project help.webmock +9 -0
  116. data/spec/fixtures/snapshots/murano link without project subshell vs inline using commander will not list.webmock +27 -0
  117. data/spec/fixtures/snapshots/murano link without project subshell vs inline using subshell will not list.webmock +27 -0
  118. data/spec/fixtures/snapshots/murano logs when project is setup tail log.webmock +9 -0
  119. data/spec/fixtures/snapshots/murano password Lists when no file.webmock +9 -0
  120. data/spec/fixtures/snapshots/murano password deletes a password.webmock +9 -0
  121. data/spec/fixtures/snapshots/murano password sets a password.webmock +9 -0
  122. data/spec/fixtures/snapshots/murano product setting Writes (using Device2.identity_format) a forced string value on STDIN.webmock +90 -0
  123. data/spec/fixtures/snapshots/murano product setting Writes (using Device2.identity_format) a forced string value.webmock +90 -0
  124. data/spec/fixtures/snapshots/murano product setting Writes (using Device2.identity_format) a number value fiftyHalf.webmock +64 -0
  125. data/spec/fixtures/snapshots/murano product setting Writes (using Device2.identity_format) a number value float 12.67.webmock +90 -0
  126. data/spec/fixtures/snapshots/murano product setting Writes (using Device2.identity_format) a number value integer 12.webmock +90 -0
  127. data/spec/fixtures/snapshots/murano product setting Writes (using Device2.identity_format) a number value on STDIN.webmock +90 -0
  128. data/spec/fixtures/snapshots/murano product setting Writes (using Device2.identity_format) a string value.webmock +90 -0
  129. data/spec/fixtures/snapshots/murano product setting Writes (using Device2.identity_format) merges into a dictionary.webmock +90 -0
  130. data/spec/fixtures/snapshots/murano single sync without ProjectFile syncdown.webmock +322 -0
  131. data/spec/fixtures/snapshots/murano status with ProjectFile status.webmock +153 -0
  132. data/spec/fixtures/snapshots/murano status with Solutionfile 0.2.0 status.webmock +153 -0
  133. data/spec/fixtures/snapshots/murano status with Solutionfile 0.3.0 status.webmock +153 -0
  134. data/spec/fixtures/snapshots/murano status without ProjectFile matches file path.webmock +153 -0
  135. data/spec/fixtures/snapshots/murano status without ProjectFile matches route.webmock +153 -0
  136. data/spec/fixtures/snapshots/murano status without ProjectFile status.webmock +153 -0
  137. data/spec/fixtures/snapshots/murano syncdown stubbed without ProjectFile syncdown.webmock +151 -0
  138. data/spec/fixtures/snapshots/murano syncdown without ProjectFile syncdown.webmock +479 -0
  139. data/spec/fixtures/snapshots/murano syncup without ProjectFile syncup.webmock +357 -0
  140. data/spec/fixtures/snapshots/murano token with project list as table.webmock +9 -0
  141. data/spec/fixtures/snapshots/murano token without project help.webmock +9 -0
  142. data/spec/fixtures/snapshots/murano usage show usage.webmock +93 -0
  143. data/spec/spec_helper.rb +9 -3
  144. data/spec/webmock_snapshot.rb +296 -0
  145. metadata +133 -2
@@ -24,19 +24,34 @@ module MrMurano
24
24
  include Verbose
25
25
 
26
26
  attr_writer :bid
27
- attr_writer :name
28
- attr_accessor :role
29
27
  attr_reader :meta
30
- attr_reader :ometa
28
+ attr_reader :network_status
29
+ attr_accessor :role
30
+
31
+ # BizAPI responses.
32
+ attr_reader :billing
33
+ attr_reader :members
34
+ attr_reader :network
35
+ attr_reader :owner
36
+ attr_reader :tier
31
37
 
32
38
  def initialize(data=nil)
33
39
  super()
40
+
34
41
  @bid = nil
35
42
  @name = nil
43
+ self.meta = data unless data.nil?
44
+ @network_status = :unknown
45
+ @role = nil
46
+
47
+ @billing = nil
48
+ @network = nil
49
+ @members = nil
50
+ @owner = nil
51
+ @tier = nil
52
+
36
53
  @valid = false
37
54
  @user_bizes = {}
38
- self.meta = data unless data.nil?
39
- @ometa = nil
40
55
  end
41
56
 
42
57
  def valid?
@@ -66,6 +81,18 @@ module MrMurano
66
81
  other.class == self.class && other.state == state
67
82
  end
68
83
 
84
+ def name=(name)
85
+ patch("business/#{bid}", name: name)
86
+ end
87
+
88
+ def email=(email)
89
+ patch("business/#{bid}/billing", email: email)
90
+ end
91
+
92
+ def contact=(contact)
93
+ patch("business/#{bid}/billing", contact: contact)
94
+ end
95
+
69
96
  protected
70
97
 
71
98
  def state
@@ -94,63 +121,173 @@ module MrMurano
94
121
  raise MrMurano::ConfigError.new(Business.missing_business_id_msg) if bid.to_s.empty?
95
122
  end
96
123
 
97
- def must_child!
124
+ def must_child_id!
98
125
  raise MrMurano::ConfigError.new(Business.missing_child_msg) if cid.to_s.empty?
99
126
  end
100
127
 
101
128
  def self.missing_business_id_msg
102
129
  %(
103
- business ID not specified. For hints: #{MrMurano::EXE_NAME} business --help
130
+ The business ID is not specified. For help, run:
131
+
132
+ #{MrMurano::EXE_NAME} business --help
104
133
  ).strip
105
134
  end
106
135
 
107
136
  def self.missing_child_msg
108
137
  %(
109
- network child business ID not specified. For hints: #{MrMurano::EXE_NAME} business --help
138
+ The network child business ID is not specified. For help, run:
139
+
140
+ #{MrMurano::EXE_NAME} business --help
110
141
  ).strip
111
142
  end
112
143
 
113
144
  def pretty_name_and_id
114
- "#{fancy_ticks(Rainbow(name).underline)} <#{bid}>"
145
+ if !name.to_s.empty?
146
+ "#{fancy_ticks(Rainbow(name).underline)} <#{bid}>"
147
+ else
148
+ "<#{bid}>"
149
+ end
150
+ end
151
+
152
+ # ---------------------------------------------------------------------
153
+
154
+ def fetch_member
155
+ whirly_msg("Fetching Business details (#{pretty_name_and_id}) / members...")
156
+ get("business/#{bid}/member/")
157
+ end
158
+
159
+ def fetch_network
160
+ whirly_msg("Fetching Business details (#{pretty_name_and_id}) / network...")
161
+ get("business/#{bid}/network")
162
+ end
163
+
164
+ def fetch_owner
165
+ whirly_msg("Fetching Business details (#{pretty_name_and_id}) / owner...")
166
+ get("business/#{bid}/owner")
167
+ end
168
+
169
+ def fetch_tier
170
+ whirly_msg("Fetching Business details (#{pretty_name_and_id}) / tier...")
171
+ get("business/#{bid}/tier")
115
172
  end
116
173
 
117
174
  # ---------------------------------------------------------------------
118
175
 
119
- #def projects?(id)
120
- # ret = get("business/#{id}/overview")
121
- # return false unless ret.is_a?(Hash)
122
- # return false unless ret.key?(:tier)
123
- # tier = ret[:tier]
124
- # return false unless tier.is_a?(Hash)
125
- # return false unless tier.key?(:enableProjects)
126
- # tier[:enableProjects]
127
- #end
128
-
129
- def overview(&block)
130
- # TODO: (PL) - The overview endpoint has been split up into smaller
131
- # endpoints that should be used instead of this one
176
+ def overview(detailed: false, networks: false)
177
+ @meta ||= {}
178
+
179
+ # (lb): 2018-08-08: The base Business endpoint contains 3 fields, e.g.,
180
+ # {:name=>"Exosite LLC", :email=>"mur.cli@exosite.com", :contact=>"MurCLI"}
181
+ # but note that :email and :contact are deprecated (and should come from billing/).
182
+ whirly_msg("Fetching Business details (#{pretty_name_and_id}) / name...")
183
+ bid_data = get("business/#{bid}")
184
+ @name = bid_data[:name]
185
+ @meta[:name] = bid_data[:name]
186
+ # (lb): There are 2 paths to setting @valid=true: Get list of businesses,
187
+ # via Account.businesses, which calls meta= (which also sets @role); or
188
+ # get specific business, which calls this method, overview (which does
189
+ # not set @role unless detailed=true).
190
+ @valid = true
191
+
192
+ prepare_details_info if detailed
193
+ prepare_network_info if networks
194
+ end
195
+
196
+ def prepare_details_info
197
+ # The billing/ endpoint contains, e.g.,
198
+ # {:balance=>0, :overdue=>0, :terms=>0, :email=>"...", :contact=>"..."}
199
+ whirly_msg("Fetching Business details (#{pretty_name_and_id}) / billing...")
200
+ @billing = get("business/#{bid}/billing") if @billing.nil? # Leverages ChargeOver
201
+ unless @billing.nil?
202
+ @meta[:email] = @billing[:email]
203
+ @meta[:contact] = @billing[:contact]
204
+ # (lb): There are some other potentially interesting fields, like
205
+ # @billing[:lineitems] (which for my businesses is empty, so...).
206
+ end
207
+
208
+ # Retrieve Business tier info.
209
+ @tier = fetch_tier if @tier.nil?
210
+ @meta[:tier] = @tier[:name] unless @tier.nil?
211
+
212
+ # Retrieve Business member list.
213
+ # NOTE: The owner/ endpoint (fetch_owner) reflects the Business Network,
214
+ # and not the User members of the Business.
215
+ @members = fetch_member if @members.nil?
216
+ @meta[:role] = 'N/A'
217
+ @members.each do |member|
218
+ next unless member[:email] == $cfg['user.name']
219
+ # (lb): 2018-08-08: Note that :membership is deprecated; use :role instead.
220
+ @meta[:role] = member[:role]
221
+ break
222
+ end
223
+
224
+ # (lb): 2018-08-08: Deprecated endpoints (listed to avoid future confusion):
132
225
  #
133
- # Here are all the goodies that the overview endpoint returns:
134
- # {:name=>"XXX", :email=>"XXX", :contact=>"XXX",
135
- # :billing=>{
136
- # :terms=>0, :balance=>0, :overdue=>0},
137
- # :tier=>{
138
- # :name=>"Community", :id=>"free", :price=>0, :users=>nil, :domains=>0,
139
- # :ssl=>false, :rebrand=>false, :billing=>false, :multisolution=>true,
140
- # :phonesupport=>false, :supportLevel=>"Community", :servicesTier=>"Core",
141
- # :onboarding=>{}, :enableMurano=>true, :enableProjects=>true},
142
- # :accountManager=>{
143
- # :name=>"", :email=>"", :phone=>""},
144
- # :accountLimits=>{
145
- # :teamMembers=>1, :solutionApis=>1, :productModels=>1,
146
- # :perModelDevices=>10, :perApiUsers=>10}, :lineitems=>[]}
147
- # EXPLAIN/2017-06-30: Which value(s) tell us if ADC is enabled?
148
- whirly_start('Fetching Business...')
149
- data = get("business/#{bid}/overview", &block)
150
- whirly_stop
151
- @valid = !data.nil?
152
- @name = data[:name] if @valid
153
- @ometa = data
226
+ # get("business/#{bid}/overview")
227
+ # Split into separate endpoints, like /billing, /tier, etc.
228
+ #
229
+ # get("business/#{bid}/lineitems")
230
+ # Incorporated into /billing, e.g., @billing[:lineitems]
231
+ #
232
+ # Other endpoints:
233
+ #
234
+ # get("business/#{bid}/creditcard")
235
+ # (lb): I'm not sure if this works, because I use a dummy card.
236
+ #
237
+ # get("business/#{bid}/transaction")
238
+ # (lb): I saw this documented, but got `404: Not Found`.
239
+ #
240
+ # get("business/#{bid}/tierset")
241
+ # Describes all the tiers offered by the platform.
242
+ #
243
+ # Handled by specific commands:
244
+ #
245
+ # get("business/#{bid}/network")
246
+ # See commands/network.rb.
247
+ #
248
+ # get("business/#{bid}/usage")
249
+ # See commands/usage.rb.
250
+ end
251
+
252
+ # ---------------------------------------------------------------------
253
+
254
+ def prepare_network_info
255
+ @tier = fetch_tier if @tier.nil?
256
+ network_enabled = @tier[:features][:network]
257
+
258
+ if network_enabled
259
+ # Parents of business networks.
260
+ fetch_network_info_parent
261
+ else
262
+ # Check if the biz is a child of a network.
263
+ maybe_add_network_info_child
264
+ end
265
+ end
266
+
267
+ def fetch_network_info_parent
268
+ @meta[:network_relationship] = 'parent'
269
+ @network = fetch_network if @network.nil?
270
+ network_name = @network[:name]
271
+ if network_name
272
+ @meta[:network_name] = network_name
273
+ @network_status = :parent_configured
274
+ else
275
+ @meta[:network_name] = '<Not configured>'
276
+ @network_status = :parent_unconfigured
277
+ end
278
+ end
279
+
280
+ def maybe_add_network_info_child
281
+ @owner = fetch_owner if @owner.nil?
282
+ if !@owner.empty?
283
+ @meta[:network_relationship] = 'child'
284
+ @meta[:network_name] = @owner[:network][:name]
285
+ @network_status = :child_configured
286
+ else
287
+ @meta[:network_relationship] = ''
288
+ @meta[:network_name] = 'N/A'
289
+ @network_status = :child_unconfigured
290
+ end
154
291
  end
155
292
 
156
293
  # ---------------------------------------------------------------------
@@ -239,7 +376,9 @@ module MrMurano
239
376
  ## Given a type (:application or :product), return a Solution instance.
240
377
  def solution_from_type!(type)
241
378
  type = type.to_s.to_sym
242
- raise "Unknown type(#{type})" unless type.to_s.empty? || ALLOWED_TYPES.include?(type)
379
+ unless type.to_s.empty? || ALLOWED_TYPES.include?(type)
380
+ raise "Unknown type(#{type})"
381
+ end
243
382
  api_id = MrMurano::Solution::INVALID_API_ID
244
383
  if type == :application
245
384
  sol = MrMurano::Application.new(api_id)
@@ -60,6 +60,7 @@ module MrMurano
60
60
  self[:data] = IniFile.new(filename: path.to_s) if self[:data].nil?
61
61
  self[:data].save
62
62
  path.chmod(0o600)
63
+ nil
63
64
  end
64
65
  end
65
66
 
@@ -42,8 +42,8 @@ module MrMurano
42
42
  end
43
43
 
44
44
  def elements(skip_purchased: false, **opts)
45
- # Get the user's Business metadata, including their Business tier.
46
- overview if @ometa.nil?
45
+ # Get the user's Business tier data.
46
+ @tier = fetch_tier if @tier.nil?
47
47
 
48
48
  elems = nil
49
49
  id_maybe = opts[:filter_id] || opts[:filter_fuzzy]
@@ -172,7 +172,7 @@ module MrMurano
172
172
  elems.each do |elem|
173
173
  if elem.purchaseId.nil?
174
174
  available.push(elem)
175
- if !@ometa[:tier].nil? && elem.tiers.include?(@ometa[:tier][:id])
175
+ if !@tier.nil? && elem.tiers.include?(@tier[:id])
176
176
  elem.statusable = :available
177
177
  else
178
178
  elem.statusable = :upgrade
@@ -181,7 +181,6 @@ module MrMurano
181
181
  purchased.push(elem)
182
182
  elem.statusable = :added
183
183
  end
184
- #@ometa[:status] = elem.status
185
184
  end
186
185
 
187
186
  [elems, available, purchased]
@@ -223,11 +223,21 @@ module MrMurano
223
223
  cache_file = $cfg.file_at(cache_file_name)
224
224
  if cache_file.file?
225
225
  cache_file.open('r+') do |io|
226
- cache = YAML.load(io)
227
- cache ||= {}
228
- io.rewind
229
- cache[local_path.to_s] = entry
230
- io << cache.to_yaml
226
+ # Try to load a pre-existing cache.
227
+ begin
228
+ cache = YAML.load(io)
229
+ cache ||= {}
230
+ io.rewind
231
+ cache[local_path.to_s] = entry
232
+ io << cache.to_yaml
233
+ rescue StandardError => err
234
+ # TODO: (tvc): add error handling here, this should help us
235
+ # understand why this fails sometimes
236
+ warning("ERROR: Failed to load the cache file at: #{cache_file}")
237
+ warning(err.to_s)
238
+ # (lb): I'm suspect that this stack trace will actually be useful.
239
+ warning(err.backtrace.inspect)
240
+ end
231
241
  end
232
242
  else
233
243
  cache_file.open('w') do |io|
@@ -365,7 +375,7 @@ module MrMurano
365
375
  root = root.expand_path
366
376
  if path.basename.sub(/\.lua$/i, '').to_s.include?('.')
367
377
  warning(
368
- "WARNING: Do not use periods in filenames." +
378
+ 'WARNING: Do not use periods in filenames.' \
369
379
  " Rename: #{fancy_ticks(path.basename)}"
370
380
  )
371
381
  end
@@ -373,7 +383,7 @@ module MrMurano
373
383
  break if ancestor == root
374
384
  if ancestor.basename.to_s.include?('.')
375
385
  warning(
376
- "WARNING: Do not use periods in directory names." +
386
+ 'WARNING: Do not use periods in directory names.' \
377
387
  " Rename: #{fancy_ticks(ancestor.basename)}"
378
388
  )
379
389
  end
@@ -401,6 +411,14 @@ module MrMurano
401
411
  # :updated_at
402
412
  # @return [String] Internal Alias name
403
413
  attr_accessor :alias
414
+ # (lb): 2018-08-09: This has been missing until now, when the
415
+ # recently added warning in Item's []= started complaining
416
+ # about it.
417
+ # (lb): FIXME/2018-08-09: Do we need to leverage this attribute
418
+ # at all? For now we're just consuming it from the platform,
419
+ # but we not using it (though we use script_key elsewhere in
420
+ # the code).
421
+ attr_accessor :script_key
404
422
  # @return [String] Timestamp when this was created.
405
423
  attr_accessor :created_at
406
424
  # @return [String] The soln's product.id or application.id (Murano's api_id).
@@ -245,15 +245,13 @@ module MrMurano
245
245
  xsum_is_sha1 = false
246
246
  if xsum_is_sha1
247
247
  digobj = remote_item_checksum_sha1(path)
248
- else
248
+ elsif file_size.zero?
249
249
  # MD5 of the empty string is not empty (it's d41d8cd98f00b204e9800998ecf8427e)
250
250
  # but BizAPI (or Pegasus; whomever) sends an empty string for an empty file.
251
- if file_size.zero?
252
- checksum = ''
253
- digobj = nil
254
- else
255
- digobj = remote_item_checksum_md5(path)
256
- end
251
+ checksum = ''
252
+ digobj = nil
253
+ else
254
+ digobj = remote_item_checksum_md5(path)
257
255
  end
258
256
 
259
257
  checksum = digobj.hexdigest unless digobj.nil?