bcl 0.7.1 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/LICENSE.md +1 -1
- data/Rakefile +37 -264
- data/bcl.gemspec +3 -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 +24 -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
|