bcl 0.7.1 → 0.9.0
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/CHANGELOG.md +12 -0
- data/LICENSE.md +1 -1
- data/Rakefile +37 -264
- data/bcl.gemspec +4 -3
- data/lib/bcl/base_xml.rb +2 -32
- data/lib/bcl/component.rb +2 -32
- data/lib/bcl/component_from_spreadsheet.rb +2 -32
- data/lib/bcl/component_methods.rb +61 -441
- data/lib/bcl/core_ext.rb +2 -32
- data/lib/bcl/tar_ball.rb +2 -66
- data/lib/bcl/version.rb +3 -33
- data/lib/bcl.rb +2 -32
- data/schemas/v3/measure_v3.xsd +1 -6
- metadata +38 -10
@@ -1,36 +1,6 @@
|
|
1
1
|
# *******************************************************************************
|
2
|
-
# OpenStudio(R), Copyright (c)
|
3
|
-
#
|
4
|
-
# Redistribution and use in source and binary forms, with or without
|
5
|
-
# modification, are permitted provided that the following conditions are met:
|
6
|
-
#
|
7
|
-
# (1) Redistributions of source code must retain the above copyright notice,
|
8
|
-
# this list of conditions and the following disclaimer.
|
9
|
-
#
|
10
|
-
# (2) Redistributions in binary form must reproduce the above copyright notice,
|
11
|
-
# this list of conditions and the following disclaimer in the documentation
|
12
|
-
# and/or other materials provided with the distribution.
|
13
|
-
#
|
14
|
-
# (3) Neither the name of the copyright holder nor the names of any contributors
|
15
|
-
# may be used to endorse or promote products derived from this software without
|
16
|
-
# specific prior written permission from the respective party.
|
17
|
-
#
|
18
|
-
# (4) Other than as required in clauses (1) and (2), distributions in any form
|
19
|
-
# of modifications or other derivative works may not use the "OpenStudio"
|
20
|
-
# trademark, "OS", "os", or any other confusingly similar designation without
|
21
|
-
# specific prior written permission from Alliance for Sustainable Energy, LLC.
|
22
|
-
#
|
23
|
-
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS
|
24
|
-
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
25
|
-
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
26
|
-
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE
|
27
|
-
# UNITED STATES GOVERNMENT, OR THE UNITED STATES DEPARTMENT OF ENERGY, NOR ANY OF
|
28
|
-
# THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
29
|
-
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
30
|
-
# OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
31
|
-
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
32
|
-
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
33
|
-
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
2
|
+
# OpenStudio(R), Copyright (c) Alliance for Sustainable Energy, LLC.
|
3
|
+
# See also https://openstudio.net/license
|
34
4
|
# *******************************************************************************
|
35
5
|
|
36
6
|
module BCL
|
@@ -44,121 +14,32 @@ module BCL
|
|
44
14
|
def initialize
|
45
15
|
@parsed_measures_path = './measures/parsed'
|
46
16
|
@config = nil
|
47
|
-
@session = nil
|
48
|
-
@access_token = nil
|
49
17
|
@http = nil
|
50
|
-
@api_version =
|
51
|
-
@group_id = nil
|
52
|
-
@logged_in = false
|
18
|
+
@api_version = nil
|
53
19
|
|
20
|
+
# load configs from file or default
|
54
21
|
load_config
|
55
|
-
end
|
56
22
|
|
57
|
-
|
58
|
-
|
59
|
-
if url.nil?
|
60
|
-
url = @config[:server][:url]
|
61
|
-
end
|
23
|
+
# configure connection
|
24
|
+
url = @config[:server][:url]
|
62
25
|
# look for http vs. https
|
63
26
|
if url.include? 'https'
|
64
27
|
port = 443
|
65
28
|
else
|
66
29
|
port = 80
|
67
30
|
end
|
31
|
+
|
68
32
|
# strip out http(s)
|
69
33
|
url = url.gsub('http://', '')
|
70
34
|
url = url.gsub('https://', '')
|
71
35
|
|
72
|
-
if username.nil? || password.nil?
|
73
|
-
# log in via cached credentials
|
74
|
-
username = @config[:server][:user][:username]
|
75
|
-
password = @config[:server][:user][:password]
|
76
|
-
@group_id = group_id || @config[:server][:user][:group]
|
77
|
-
puts "logging in using credentials in .bcl/config.yml: Connecting to #{url} on port #{port} as #{username} with group #{@group_id}"
|
78
|
-
else
|
79
|
-
@group_id = group_id || @config[:server][:user][:group]
|
80
|
-
puts "logging in using credentials in function arguments: Connecting to #{url} on port #{port} as #{username} with group #{@group_id}"
|
81
|
-
end
|
82
|
-
|
83
|
-
if @group_id.nil?
|
84
|
-
puts '[WARNING] You did not set a group ID in your config.yml file or pass in a group ID. You can retrieve your group ID from the node number of your group page (e.g., https://bcl.nrel.gov/node/32). Will continue, but you will not be able to upload content.'
|
85
|
-
end
|
86
|
-
|
87
36
|
@http = Net::HTTP.new(url, port)
|
88
37
|
@http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
89
38
|
if port == 443
|
90
39
|
@http.use_ssl = true
|
91
40
|
end
|
92
41
|
|
93
|
-
|
94
|
-
|
95
|
-
login_path = '/api/user/login.json'
|
96
|
-
headers = { 'Content-Type' => 'application/json' }
|
97
|
-
|
98
|
-
res = @http.post(login_path, data, headers)
|
99
|
-
|
100
|
-
# for debugging:
|
101
|
-
# res.each do |key, value|
|
102
|
-
# puts "#{key}: #{value}"
|
103
|
-
# end
|
104
|
-
|
105
|
-
if res.code == '200'
|
106
|
-
puts 'Login Successful'
|
107
|
-
|
108
|
-
bnes = ''
|
109
|
-
bni = ''
|
110
|
-
junkout = res['set-cookie'].split(';')
|
111
|
-
junkout.each do |line|
|
112
|
-
if line.match?(/BNES_SESS/)
|
113
|
-
bnes = line.match(/(BNES_SESS.*)/)[0]
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
junkout.each do |line|
|
118
|
-
if line.match?(/BNI/)
|
119
|
-
bni = line.match(/(BNI.*)/)[0]
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
# puts "DATA: #{data}"
|
124
|
-
session_name = ''
|
125
|
-
sessid = ''
|
126
|
-
json = JSON.parse(res.body)
|
127
|
-
json.each do |key, val|
|
128
|
-
if key == 'session_name'
|
129
|
-
session_name = val
|
130
|
-
elsif key == 'sessid'
|
131
|
-
sessid = val
|
132
|
-
end
|
133
|
-
end
|
134
|
-
|
135
|
-
@session = session_name + '=' + sessid + ';' + bni + ';' + bnes
|
136
|
-
|
137
|
-
# get access token
|
138
|
-
token_path = '/services/session/token'
|
139
|
-
token_headers = { 'Content-Type' => 'application/json', 'Cookie' => @session }
|
140
|
-
# puts "token_headers = #{token_headers.inspect}"
|
141
|
-
access_token = @http.post(token_path, '', token_headers)
|
142
|
-
if access_token.code == '200'
|
143
|
-
@access_token = access_token.body
|
144
|
-
else
|
145
|
-
puts 'Unable to get access token; uploads will not work'
|
146
|
-
puts "error code: #{access_token.code}"
|
147
|
-
puts "error info: #{access_token.body}"
|
148
|
-
end
|
149
|
-
|
150
|
-
# puts "access_token = *#{@access_token}*"
|
151
|
-
# puts "cookie = #{@session}"
|
152
|
-
|
153
|
-
res
|
154
|
-
else
|
155
|
-
|
156
|
-
puts "error code: #{res.code}"
|
157
|
-
puts "error info: #{res.body}"
|
158
|
-
puts 'continuing as unauthenticated sessions (you can still search and download)'
|
159
|
-
|
160
|
-
res
|
161
|
-
end
|
42
|
+
puts "Connecting to BCL at URL: #{@config[:server][:url]}"
|
162
43
|
end
|
163
44
|
|
164
45
|
# retrieve measures for parsing metadata.
|
@@ -169,10 +50,18 @@ module BCL
|
|
169
50
|
# raise "Please login before performing this action" if @session.nil?
|
170
51
|
|
171
52
|
# make sure filter_term includes bundle
|
172
|
-
if
|
173
|
-
filter_term
|
174
|
-
|
175
|
-
filter_term
|
53
|
+
if @api_version == 2.0
|
54
|
+
if filter_term.nil?
|
55
|
+
filter_term = 'fq[]=bundle%3Anrel_measure'
|
56
|
+
elsif !filter_term.include? 'bundle'
|
57
|
+
filter_term += '&fq[]=bundle%3Anrel_measure'
|
58
|
+
end
|
59
|
+
else
|
60
|
+
if filter_term.nil?
|
61
|
+
filter_term = 'fq=bundle%3Ameasure'
|
62
|
+
elsif !filter_term.include? 'bundle'
|
63
|
+
filter_term += '&fq=bundle%3Ameasure'
|
64
|
+
end
|
176
65
|
end
|
177
66
|
|
178
67
|
# use provided search term or nil.
|
@@ -186,183 +75,6 @@ module BCL
|
|
186
75
|
end
|
187
76
|
end
|
188
77
|
|
189
|
-
# evaluate the response from the API in a consistent manner
|
190
|
-
def evaluate_api_response(api_response)
|
191
|
-
valid = false
|
192
|
-
result = { error: 'could not get json from http post response' }
|
193
|
-
case api_response.code
|
194
|
-
when '200'
|
195
|
-
puts " Response Code: #{api_response.code}"
|
196
|
-
if api_response.body.empty?
|
197
|
-
puts ' 200 BUT ERROR: Returned body was empty. Possible causes:'
|
198
|
-
puts ' - BSD tar on Mac OSX vs gnutar'
|
199
|
-
result = { error: 'returned 200, but returned body was empty' }
|
200
|
-
valid = false
|
201
|
-
else
|
202
|
-
puts ' 200 - Successful Upload'
|
203
|
-
result = JSON.parse api_response.body
|
204
|
-
valid = true
|
205
|
-
end
|
206
|
-
when '404'
|
207
|
-
puts " Error Code: #{api_response.code} - #{api_response.body}"
|
208
|
-
puts ' - check these common causes first:'
|
209
|
-
puts " - you are trying to update content that doesn't exist"
|
210
|
-
puts " - you are not an 'administrator member' of the group you're trying to upload to"
|
211
|
-
result = JSON.parse api_response.body
|
212
|
-
valid = false
|
213
|
-
when '406'
|
214
|
-
puts " Error Code: #{api_response.code}"
|
215
|
-
# try to parse the response a bit
|
216
|
-
error = JSON.parse api_response.body
|
217
|
-
puts "temp error: #{error}"
|
218
|
-
if error.key?('form_errors')
|
219
|
-
if error['form_errors'].key?('field_tar_file')
|
220
|
-
result = { error: error['form_errors']['field_tar_file'] }
|
221
|
-
elsif error['form_errors'].key?('og_group_ref][und][0][default')
|
222
|
-
result = { error: error['form_errors']['og_group_ref][und][0][default'] }
|
223
|
-
end
|
224
|
-
else
|
225
|
-
result = error
|
226
|
-
end
|
227
|
-
valid = false
|
228
|
-
when '500'
|
229
|
-
puts " Error Code: #{api_response.code}"
|
230
|
-
result = { error: api_response.message }
|
231
|
-
# fail 'server exception'
|
232
|
-
valid = false
|
233
|
-
else
|
234
|
-
puts " Response: #{api_response.code} - #{api_response.body}"
|
235
|
-
valid = false
|
236
|
-
end
|
237
|
-
|
238
|
-
[valid, result]
|
239
|
-
end
|
240
|
-
|
241
|
-
# Construct the post parameter for the API content.json end point.
|
242
|
-
# param(@update) is a boolean that triggers whether to use content_type or uuid
|
243
|
-
def construct_post_data(filepath, update, content_type_or_uuid)
|
244
|
-
# TODO: remove special characters in the filename; they create firewall errors
|
245
|
-
# filename = filename.gsub(/\W/,'_').gsub(/___/,'_').gsub(/__/,'_').chomp('_').strip
|
246
|
-
|
247
|
-
file_b64 = Base64.encode64(File.binread(filepath))
|
248
|
-
|
249
|
-
data = {}
|
250
|
-
data['file'] = {
|
251
|
-
'file' => file_b64,
|
252
|
-
'filesize' => File.size(filepath).to_s,
|
253
|
-
'filename' => File.basename(filepath)
|
254
|
-
}
|
255
|
-
|
256
|
-
data['node'] = {}
|
257
|
-
|
258
|
-
# Only include the content type if this is an update
|
259
|
-
if update
|
260
|
-
data['node']['uuid'] = content_type_or_uuid
|
261
|
-
else
|
262
|
-
data['node']['type'] = content_type_or_uuid
|
263
|
-
end
|
264
|
-
|
265
|
-
# TODO: remove this field_component_tags once BCL is fixed
|
266
|
-
data['node']['field_component_tags'] = { 'und' => '1289' }
|
267
|
-
data['node']['og_group_ref'] = { 'und' => ['target_id' => @group_id] }
|
268
|
-
|
269
|
-
# NOTE THIS ONLY WORKS IF YOU ARE A BCL SITE ADMIN
|
270
|
-
data['node']['publish'] = '1'
|
271
|
-
|
272
|
-
data
|
273
|
-
end
|
274
|
-
|
275
|
-
# pushes component to the bcl and publishes them (if logged-in as BCL Website Admin user).
|
276
|
-
# username, password, and group_id are set in the ~/.bcl/config.yml file
|
277
|
-
def push_content(filename_and_path, write_receipt_file, content_type)
|
278
|
-
raise 'Please login before pushing components' if @session.nil?
|
279
|
-
raise 'Do not have a valid access token; try again' if @access_token.nil?
|
280
|
-
|
281
|
-
data = construct_post_data(filename_and_path, false, content_type)
|
282
|
-
|
283
|
-
path = '/api/content.json'
|
284
|
-
headers = { 'Content-Type' => 'application/json', 'X-CSRF-Token' => @access_token, 'Cookie' => @session }
|
285
|
-
|
286
|
-
res = @http.post(path, JSON.dump(data), headers)
|
287
|
-
|
288
|
-
valid, json = evaluate_api_response(res)
|
289
|
-
|
290
|
-
if valid
|
291
|
-
# write out a receipt file into the same directory of the component with the same file name as
|
292
|
-
# the component
|
293
|
-
if write_receipt_file
|
294
|
-
File.open("#{File.dirname(filename_and_path)}/#{File.basename(filename_and_path, '.tar.gz')}.receipt", 'w') do |file|
|
295
|
-
file << Time.now.to_s
|
296
|
-
end
|
297
|
-
end
|
298
|
-
end
|
299
|
-
|
300
|
-
[valid, json]
|
301
|
-
end
|
302
|
-
|
303
|
-
# pushes updated content to the bcl and publishes it (if logged-in as BCL Website Admin user).
|
304
|
-
# username and password set in ~/.bcl/config.yml file
|
305
|
-
def update_content(filename_and_path, write_receipt_file, uuid = nil)
|
306
|
-
raise 'Please login before pushing components' unless @session
|
307
|
-
|
308
|
-
# get the UUID if zip or xml file
|
309
|
-
version_id = nil
|
310
|
-
if uuid.nil?
|
311
|
-
puts File.extname(filename_and_path).downcase
|
312
|
-
if filename_and_path.match?(/^.*.tar.gz$/i)
|
313
|
-
uuid, version_id = uuid_vid_from_tarball(filename_and_path)
|
314
|
-
puts "Parsed uuid out of tar.gz file with value #{uuid}"
|
315
|
-
end
|
316
|
-
else
|
317
|
-
# verify the uuid via regex
|
318
|
-
unless uuid.match?(/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/)
|
319
|
-
raise "uuid of #{uuid} is invalid"
|
320
|
-
end
|
321
|
-
end
|
322
|
-
raise 'Please pass in a tar.gz file or pass in the uuid' unless uuid
|
323
|
-
|
324
|
-
data = construct_post_data(filename_and_path, true, uuid)
|
325
|
-
|
326
|
-
path = '/api/content.json'
|
327
|
-
headers = { 'Content-Type' => 'application/json', 'X-CSRF-Token' => @access_token, 'Cookie' => @session }
|
328
|
-
|
329
|
-
res = @http.post(path, JSON.dump(data), headers)
|
330
|
-
|
331
|
-
valid, json = evaluate_api_response(res)
|
332
|
-
|
333
|
-
if valid
|
334
|
-
# write out a receipt file into the same directory of the component with the same file name as
|
335
|
-
# the component
|
336
|
-
if write_receipt_file
|
337
|
-
File.open("#{File.dirname(filename_and_path)}/#{File.basename(filename_and_path, '.tar.gz')}.receipt", 'w') do |file|
|
338
|
-
file << Time.now.to_s
|
339
|
-
end
|
340
|
-
end
|
341
|
-
end
|
342
|
-
|
343
|
-
[valid, json]
|
344
|
-
end
|
345
|
-
|
346
|
-
def push_contents(array_of_components, skip_files_with_receipts, content_type)
|
347
|
-
logs = []
|
348
|
-
array_of_components.each do |comp|
|
349
|
-
receipt_file = File.dirname(comp) + '/' + File.basename(comp, '.tar.gz') + '.receipt'
|
350
|
-
log_message = ''
|
351
|
-
if skip_files_with_receipts && File.exist?(receipt_file)
|
352
|
-
log_message = "skipping because found receipt #{comp}"
|
353
|
-
puts log_message
|
354
|
-
else
|
355
|
-
log_message = "pushing content #{File.basename(comp, '.tar.gz')}"
|
356
|
-
puts log_message
|
357
|
-
valid, res = push_content(comp, true, content_type)
|
358
|
-
log_message += " #{valid} #{res.inspect.chomp}"
|
359
|
-
end
|
360
|
-
logs << log_message
|
361
|
-
end
|
362
|
-
|
363
|
-
logs
|
364
|
-
end
|
365
|
-
|
366
78
|
# Unpack the tarball in memory and extract the XML file to read the UUID and Version ID
|
367
79
|
def uuid_vid_from_tarball(path_to_tarball)
|
368
80
|
uuid = nil
|
@@ -422,43 +134,18 @@ module BCL
|
|
422
134
|
[uuid, vid]
|
423
135
|
end
|
424
136
|
|
425
|
-
def update_contents(array_of_tarball_components, skip_files_with_receipts)
|
426
|
-
logs = []
|
427
|
-
array_of_tarball_components.each do |comp|
|
428
|
-
receipt_file = File.dirname(comp) + '/' + File.basename(comp, '.tar.gz') + '.receipt'
|
429
|
-
log_message = ''
|
430
|
-
if skip_files_with_receipts && File.exist?(receipt_file)
|
431
|
-
log_message = "skipping update because found receipt #{File.basename(comp)}"
|
432
|
-
puts log_message
|
433
|
-
else
|
434
|
-
uuid, vid = uuid_vid_from_tarball(comp)
|
435
|
-
if uuid.nil?
|
436
|
-
log_message = "ERROR: uuid not found for #{File.basename(comp)}"
|
437
|
-
puts log_message
|
438
|
-
else
|
439
|
-
log_message = "pushing updated content #{File.basename(comp)}"
|
440
|
-
puts log_message
|
441
|
-
valid, res = update_content(comp, true, uuid)
|
442
|
-
log_message += " #{valid} #{res.inspect.chomp}"
|
443
|
-
end
|
444
|
-
end
|
445
|
-
logs << log_message
|
446
|
-
end
|
447
|
-
logs
|
448
|
-
end
|
449
|
-
|
450
137
|
def search_by_uuid(uuid, vid = nil)
|
451
138
|
full_url = '/api/search.json'
|
452
|
-
action = nil
|
453
139
|
|
454
140
|
# add api_version
|
455
|
-
if @api_version
|
456
|
-
|
141
|
+
if @api_version == 2.0
|
142
|
+
# uuid
|
143
|
+
full_url += "?api_version=#{@api_version}"
|
144
|
+
full_url += "&fq[]=ss_uuid:#{uuid}"
|
145
|
+
else
|
146
|
+
# uuid
|
147
|
+
full_url += "&fq=uuid:#{uuid}"
|
457
148
|
end
|
458
|
-
full_url += "?api_version=#{@api_version}"
|
459
|
-
|
460
|
-
# uuid
|
461
|
-
full_url += "&fq[]=ss_uuid:#{uuid}"
|
462
149
|
|
463
150
|
res = @http.get(full_url)
|
464
151
|
res = JSON.parse res.body
|
@@ -474,20 +161,9 @@ module BCL
|
|
474
161
|
else
|
475
162
|
content = content['component']
|
476
163
|
end
|
477
|
-
|
478
|
-
# TODO: check version_modified date if it exists?
|
479
|
-
if !vid.nil? && content['vuuid'] == vid
|
480
|
-
# no update needed
|
481
|
-
action = 'noop'
|
482
|
-
else
|
483
|
-
# vid doesn't match: update existing
|
484
|
-
action = 'update'
|
485
|
-
end
|
486
|
-
else
|
487
|
-
# no uuid found: push new
|
488
|
-
action = 'push'
|
489
164
|
end
|
490
|
-
|
165
|
+
|
166
|
+
content
|
491
167
|
end
|
492
168
|
|
493
169
|
# Simple method to search bcl and return the result as hash with symbols
|
@@ -508,22 +184,30 @@ module BCL
|
|
508
184
|
full_url += '*.json'
|
509
185
|
end
|
510
186
|
|
511
|
-
# add api_version
|
512
|
-
if @api_version
|
513
|
-
|
187
|
+
# add api_version (legacy NREL is 2.0, otherwise use new syntax and ignore version)
|
188
|
+
if @api_version.nil?
|
189
|
+
# see if we can extract it from filter_str:
|
190
|
+
tmp = filter_str.match(/api_version=\d{1,}.\d{1,}/)
|
191
|
+
if tmp
|
192
|
+
@api_version = tmp.to_s.gsub(/api_version=/, '').to_f
|
193
|
+
puts "@api_version from filter_str: #{@api_version}"
|
194
|
+
end
|
514
195
|
end
|
515
|
-
|
196
|
+
|
197
|
+
if @api_version == 2.0
|
198
|
+
full_url += "?api_version=#{@api_version}"
|
199
|
+
end
|
200
|
+
puts "@api_version: #{@api_version}"
|
516
201
|
|
517
202
|
# add filters
|
518
|
-
|
519
|
-
# strip out api_version from filters, if included
|
520
|
-
if filter_str.include? 'api_version='
|
521
|
-
filter_str = filter_str.gsub(
|
522
|
-
filter_str = filter_str.gsub(
|
203
|
+
if !filter_str.nil?
|
204
|
+
# strip out api_version from filters, if included & @api_version is defined
|
205
|
+
if (filter_str.include? 'api_version=')
|
206
|
+
filter_str = filter_str.gsub(/&api_version=\d{1,}.\d{1,}/, '')
|
207
|
+
filter_str = filter_str.gsub(/api_version=\d{1,}.\d{1,}/, '')
|
523
208
|
end
|
524
209
|
full_url = full_url + '&' + filter_str
|
525
210
|
end
|
526
|
-
|
527
211
|
# simple search vs. all results
|
528
212
|
if !all
|
529
213
|
puts "search url: #{full_url}"
|
@@ -572,14 +256,16 @@ module BCL
|
|
572
256
|
receipt_file = File.dirname(comp) + '/' + File.basename(comp, '.tar.gz') + '.receipt'
|
573
257
|
if File.exist?(receipt_file)
|
574
258
|
FileUtils.remove_file(receipt_file)
|
575
|
-
|
576
259
|
end
|
577
260
|
end
|
578
261
|
end
|
579
262
|
|
580
263
|
def list_all_measures
|
581
|
-
|
582
|
-
|
264
|
+
if @api_version == 2.0
|
265
|
+
json = search(nil, 'fq[]=bundle%3Anrel_measure&show_rows=100')
|
266
|
+
else
|
267
|
+
json = search(nil, 'fq=bundle%3Ameasure&show_rows=100')
|
268
|
+
end
|
583
269
|
json
|
584
270
|
end
|
585
271
|
|
@@ -607,93 +293,27 @@ module BCL
|
|
607
293
|
config_filename = File.expand_path('~/.bcl/config.yml')
|
608
294
|
|
609
295
|
if File.exist?(config_filename)
|
610
|
-
puts "loading config
|
296
|
+
puts "loading URL config from #{config_filename}"
|
611
297
|
@config = YAML.load_file(config_filename)
|
612
298
|
else
|
613
|
-
#
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
@config = YAML.load_file(config_filename)
|
299
|
+
# use default URL
|
300
|
+
@config = {
|
301
|
+
server: {
|
302
|
+
url: 'https://bcl.nrel.gov'
|
303
|
+
}
|
304
|
+
}
|
620
305
|
end
|
621
306
|
end
|
622
307
|
|
308
|
+
# unused
|
623
309
|
def default_yaml
|
624
310
|
settings = {
|
625
311
|
server: {
|
626
|
-
url: 'https://bcl.nrel.gov'
|
627
|
-
user: {
|
628
|
-
username: 'ENTER_BCL_USERNAME',
|
629
|
-
password: 'ENTER_BCL_PASSWORD',
|
630
|
-
group: 'ENTER_GROUP_ID'
|
631
|
-
}
|
312
|
+
url: 'https://bcl.nrel.gov'
|
632
313
|
}
|
633
314
|
}
|
634
315
|
|
635
316
|
settings
|
636
317
|
end
|
637
318
|
end
|
638
|
-
|
639
|
-
# TODO: make this extend the component_xml class (or create a super class around components)
|
640
|
-
|
641
|
-
def self.gather_components(component_dir, chunk_size = 0, delete_previousgather = false, destination = nil)
|
642
|
-
if destination.nil?
|
643
|
-
@dest_filename = 'components'
|
644
|
-
else
|
645
|
-
@dest_filename = destination
|
646
|
-
end
|
647
|
-
@dest_file_ext = 'tar.gz'
|
648
|
-
|
649
|
-
# store the starting directory
|
650
|
-
current_dir = Dir.pwd
|
651
|
-
|
652
|
-
# an array to hold reporting info about the batches
|
653
|
-
gather_components_report = []
|
654
|
-
|
655
|
-
# go to the directory containing the components
|
656
|
-
Dir.chdir(component_dir)
|
657
|
-
|
658
|
-
# delete any old versions of the component chunks
|
659
|
-
FileUtils.rm_rf('./gather') if delete_previousgather
|
660
|
-
|
661
|
-
# gather all the components into array
|
662
|
-
targzs = Pathname.glob('./**/*.tar.gz')
|
663
|
-
tar_cnt = 0
|
664
|
-
chunk_cnt = 0
|
665
|
-
targzs.each do |targz|
|
666
|
-
if chunk_size != 0 && (tar_cnt % chunk_size) == 0
|
667
|
-
chunk_cnt += 1
|
668
|
-
end
|
669
|
-
tar_cnt += 1
|
670
|
-
|
671
|
-
destination_path = "./gather/#{chunk_cnt}"
|
672
|
-
FileUtils.mkdir_p(destination_path)
|
673
|
-
destination_file = "#{destination_path}/#{File.basename(targz.to_s)}"
|
674
|
-
# puts "copying #{targz.to_s} to #{destination_file}"
|
675
|
-
FileUtils.cp(targz.to_s, destination_file)
|
676
|
-
end
|
677
|
-
|
678
|
-
# gather all the .tar.gz files into a single tar.gz
|
679
|
-
(1..chunk_cnt).each do |cnt|
|
680
|
-
currentdir = Dir.pwd
|
681
|
-
|
682
|
-
paths = []
|
683
|
-
Pathname.glob("./gather/#{cnt}/*.tar.gz").each do |pt|
|
684
|
-
paths << File.basename(pt.to_s)
|
685
|
-
end
|
686
|
-
|
687
|
-
Dir.chdir("./gather/#{cnt}")
|
688
|
-
destination = "#{@dest_filename}_#{cnt}.#{@dest_file_ext}"
|
689
|
-
puts "tarring batch #{cnt} of #{chunk_cnt} to #{@dest_filename}_#{cnt}.#{@dest_file_ext}"
|
690
|
-
BCL.tarball(destination, paths)
|
691
|
-
Dir.chdir(currentdir)
|
692
|
-
|
693
|
-
# move the tarball back a directory
|
694
|
-
FileUtils.move("./gather/#{cnt}/#{destination}", "./gather/#{destination}")
|
695
|
-
end
|
696
|
-
|
697
|
-
Dir.chdir(current_dir)
|
698
|
-
end
|
699
319
|
end
|
data/lib/bcl/core_ext.rb
CHANGED
@@ -1,36 +1,6 @@
|
|
1
1
|
# *******************************************************************************
|
2
|
-
# OpenStudio(R), Copyright (c)
|
3
|
-
#
|
4
|
-
# Redistribution and use in source and binary forms, with or without
|
5
|
-
# modification, are permitted provided that the following conditions are met:
|
6
|
-
#
|
7
|
-
# (1) Redistributions of source code must retain the above copyright notice,
|
8
|
-
# this list of conditions and the following disclaimer.
|
9
|
-
#
|
10
|
-
# (2) Redistributions in binary form must reproduce the above copyright notice,
|
11
|
-
# this list of conditions and the following disclaimer in the documentation
|
12
|
-
# and/or other materials provided with the distribution.
|
13
|
-
#
|
14
|
-
# (3) Neither the name of the copyright holder nor the names of any contributors
|
15
|
-
# may be used to endorse or promote products derived from this software without
|
16
|
-
# specific prior written permission from the respective party.
|
17
|
-
#
|
18
|
-
# (4) Other than as required in clauses (1) and (2), distributions in any form
|
19
|
-
# of modifications or other derivative works may not use the "OpenStudio"
|
20
|
-
# trademark, "OS", "os", or any other confusingly similar designation without
|
21
|
-
# specific prior written permission from Alliance for Sustainable Energy, LLC.
|
22
|
-
#
|
23
|
-
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS
|
24
|
-
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
25
|
-
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
26
|
-
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE
|
27
|
-
# UNITED STATES GOVERNMENT, OR THE UNITED STATES DEPARTMENT OF ENERGY, NOR ANY OF
|
28
|
-
# THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
29
|
-
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
30
|
-
# OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
31
|
-
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
32
|
-
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
33
|
-
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
2
|
+
# OpenStudio(R), Copyright (c) Alliance for Sustainable Energy, LLC.
|
3
|
+
# See also https://openstudio.net/license
|
34
4
|
# *******************************************************************************
|
35
5
|
|
36
6
|
class String
|