bcl 0.7.0 → 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 +13 -0
- data/Gemfile +1 -9
- data/LICENSE.md +27 -0
- data/Rakefile +40 -232
- data/bcl.gemspec +26 -17
- data/lib/bcl/base_xml.rb +4 -18
- data/lib/bcl/component.rb +4 -18
- data/lib/bcl/component_from_spreadsheet.rb +4 -18
- data/lib/bcl/component_methods.rb +63 -427
- data/lib/bcl/core_ext.rb +4 -18
- data/lib/bcl/tar_ball.rb +4 -52
- data/lib/bcl/version.rb +5 -19
- data/lib/bcl.rb +4 -18
- data/schemas/v3/measure_v3.xsd +1 -6
- metadata +63 -18
- data/License.txt +0 -65
@@ -1,21 +1,7 @@
|
|
1
|
-
|
2
|
-
#
|
3
|
-
#
|
4
|
-
#
|
5
|
-
# This library is free software; you can redistribute it and/or
|
6
|
-
# modify it under the terms of the GNU Lesser General Public
|
7
|
-
# License as published by the Free Software Foundation; either
|
8
|
-
# version 2.1 of the License, or (at your option) any later version.
|
9
|
-
#
|
10
|
-
# This library is distributed in the hope that it will be useful,
|
11
|
-
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
13
|
-
# Lesser General Public License for more details.
|
14
|
-
#
|
15
|
-
# You should have received a copy of the GNU Lesser General Public
|
16
|
-
# License along with this library; if not, write to the Free Software
|
17
|
-
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
18
|
-
######################################################################
|
1
|
+
# *******************************************************************************
|
2
|
+
# OpenStudio(R), Copyright (c) Alliance for Sustainable Energy, LLC.
|
3
|
+
# See also https://openstudio.net/license
|
4
|
+
# *******************************************************************************
|
19
5
|
|
20
6
|
module BCL
|
21
7
|
class ComponentMethods
|
@@ -28,121 +14,32 @@ module BCL
|
|
28
14
|
def initialize
|
29
15
|
@parsed_measures_path = './measures/parsed'
|
30
16
|
@config = nil
|
31
|
-
@session = nil
|
32
|
-
@access_token = nil
|
33
17
|
@http = nil
|
34
|
-
@api_version =
|
35
|
-
@group_id = nil
|
36
|
-
@logged_in = false
|
18
|
+
@api_version = nil
|
37
19
|
|
20
|
+
# load configs from file or default
|
38
21
|
load_config
|
39
|
-
end
|
40
22
|
|
41
|
-
|
42
|
-
|
43
|
-
if url.nil?
|
44
|
-
url = @config[:server][:url]
|
45
|
-
end
|
23
|
+
# configure connection
|
24
|
+
url = @config[:server][:url]
|
46
25
|
# look for http vs. https
|
47
26
|
if url.include? 'https'
|
48
27
|
port = 443
|
49
28
|
else
|
50
29
|
port = 80
|
51
30
|
end
|
31
|
+
|
52
32
|
# strip out http(s)
|
53
33
|
url = url.gsub('http://', '')
|
54
34
|
url = url.gsub('https://', '')
|
55
35
|
|
56
|
-
if username.nil? || password.nil?
|
57
|
-
# log in via cached credentials
|
58
|
-
username = @config[:server][:user][:username]
|
59
|
-
password = @config[:server][:user][:password]
|
60
|
-
@group_id = group_id || @config[:server][:user][:group]
|
61
|
-
puts "logging in using credentials in .bcl/config.yml: Connecting to #{url} on port #{port} as #{username} with group #{@group_id}"
|
62
|
-
else
|
63
|
-
@group_id = group_id || @config[:server][:user][:group]
|
64
|
-
puts "logging in using credentials in function arguments: Connecting to #{url} on port #{port} as #{username} with group #{@group_id}"
|
65
|
-
end
|
66
|
-
|
67
|
-
if @group_id.nil?
|
68
|
-
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.'
|
69
|
-
end
|
70
|
-
|
71
36
|
@http = Net::HTTP.new(url, port)
|
72
37
|
@http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
73
38
|
if port == 443
|
74
39
|
@http.use_ssl = true
|
75
40
|
end
|
76
41
|
|
77
|
-
|
78
|
-
|
79
|
-
login_path = '/api/user/login.json'
|
80
|
-
headers = { 'Content-Type' => 'application/json' }
|
81
|
-
|
82
|
-
res = @http.post(login_path, data, headers)
|
83
|
-
|
84
|
-
# for debugging:
|
85
|
-
# res.each do |key, value|
|
86
|
-
# puts "#{key}: #{value}"
|
87
|
-
# end
|
88
|
-
|
89
|
-
if res.code == '200'
|
90
|
-
puts 'Login Successful'
|
91
|
-
|
92
|
-
bnes = ''
|
93
|
-
bni = ''
|
94
|
-
junkout = res['set-cookie'].split(';')
|
95
|
-
junkout.each do |line|
|
96
|
-
if line.match?(/BNES_SESS/)
|
97
|
-
bnes = line.match(/(BNES_SESS.*)/)[0]
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
junkout.each do |line|
|
102
|
-
if line.match?(/BNI/)
|
103
|
-
bni = line.match(/(BNI.*)/)[0]
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
# puts "DATA: #{data}"
|
108
|
-
session_name = ''
|
109
|
-
sessid = ''
|
110
|
-
json = JSON.parse(res.body)
|
111
|
-
json.each do |key, val|
|
112
|
-
if key == 'session_name'
|
113
|
-
session_name = val
|
114
|
-
elsif key == 'sessid'
|
115
|
-
sessid = val
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
@session = session_name + '=' + sessid + ';' + bni + ';' + bnes
|
120
|
-
|
121
|
-
# get access token
|
122
|
-
token_path = '/services/session/token'
|
123
|
-
token_headers = { 'Content-Type' => 'application/json', 'Cookie' => @session }
|
124
|
-
# puts "token_headers = #{token_headers.inspect}"
|
125
|
-
access_token = @http.post(token_path, '', token_headers)
|
126
|
-
if access_token.code == '200'
|
127
|
-
@access_token = access_token.body
|
128
|
-
else
|
129
|
-
puts 'Unable to get access token; uploads will not work'
|
130
|
-
puts "error code: #{access_token.code}"
|
131
|
-
puts "error info: #{access_token.body}"
|
132
|
-
end
|
133
|
-
|
134
|
-
# puts "access_token = *#{@access_token}*"
|
135
|
-
# puts "cookie = #{@session}"
|
136
|
-
|
137
|
-
res
|
138
|
-
else
|
139
|
-
|
140
|
-
puts "error code: #{res.code}"
|
141
|
-
puts "error info: #{res.body}"
|
142
|
-
puts 'continuing as unauthenticated sessions (you can still search and download)'
|
143
|
-
|
144
|
-
res
|
145
|
-
end
|
42
|
+
puts "Connecting to BCL at URL: #{@config[:server][:url]}"
|
146
43
|
end
|
147
44
|
|
148
45
|
# retrieve measures for parsing metadata.
|
@@ -153,10 +50,18 @@ module BCL
|
|
153
50
|
# raise "Please login before performing this action" if @session.nil?
|
154
51
|
|
155
52
|
# make sure filter_term includes bundle
|
156
|
-
if
|
157
|
-
filter_term
|
158
|
-
|
159
|
-
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
|
160
65
|
end
|
161
66
|
|
162
67
|
# use provided search term or nil.
|
@@ -170,183 +75,6 @@ module BCL
|
|
170
75
|
end
|
171
76
|
end
|
172
77
|
|
173
|
-
# evaluate the response from the API in a consistent manner
|
174
|
-
def evaluate_api_response(api_response)
|
175
|
-
valid = false
|
176
|
-
result = { error: 'could not get json from http post response' }
|
177
|
-
case api_response.code
|
178
|
-
when '200'
|
179
|
-
puts " Response Code: #{api_response.code}"
|
180
|
-
if api_response.body.empty?
|
181
|
-
puts ' 200 BUT ERROR: Returned body was empty. Possible causes:'
|
182
|
-
puts ' - BSD tar on Mac OSX vs gnutar'
|
183
|
-
result = { error: 'returned 200, but returned body was empty' }
|
184
|
-
valid = false
|
185
|
-
else
|
186
|
-
puts ' 200 - Successful Upload'
|
187
|
-
result = JSON.parse api_response.body
|
188
|
-
valid = true
|
189
|
-
end
|
190
|
-
when '404'
|
191
|
-
puts " Error Code: #{api_response.code} - #{api_response.body}"
|
192
|
-
puts ' - check these common causes first:'
|
193
|
-
puts " - you are trying to update content that doesn't exist"
|
194
|
-
puts " - you are not an 'administrator member' of the group you're trying to upload to"
|
195
|
-
result = JSON.parse api_response.body
|
196
|
-
valid = false
|
197
|
-
when '406'
|
198
|
-
puts " Error Code: #{api_response.code}"
|
199
|
-
# try to parse the response a bit
|
200
|
-
error = JSON.parse api_response.body
|
201
|
-
puts "temp error: #{error}"
|
202
|
-
if error.key?('form_errors')
|
203
|
-
if error['form_errors'].key?('field_tar_file')
|
204
|
-
result = { error: error['form_errors']['field_tar_file'] }
|
205
|
-
elsif error['form_errors'].key?('og_group_ref][und][0][default')
|
206
|
-
result = { error: error['form_errors']['og_group_ref][und][0][default'] }
|
207
|
-
end
|
208
|
-
else
|
209
|
-
result = error
|
210
|
-
end
|
211
|
-
valid = false
|
212
|
-
when '500'
|
213
|
-
puts " Error Code: #{api_response.code}"
|
214
|
-
result = { error: api_response.message }
|
215
|
-
# fail 'server exception'
|
216
|
-
valid = false
|
217
|
-
else
|
218
|
-
puts " Response: #{api_response.code} - #{api_response.body}"
|
219
|
-
valid = false
|
220
|
-
end
|
221
|
-
|
222
|
-
[valid, result]
|
223
|
-
end
|
224
|
-
|
225
|
-
# Construct the post parameter for the API content.json end point.
|
226
|
-
# param(@update) is a boolean that triggers whether to use content_type or uuid
|
227
|
-
def construct_post_data(filepath, update, content_type_or_uuid)
|
228
|
-
# TODO: remove special characters in the filename; they create firewall errors
|
229
|
-
# filename = filename.gsub(/\W/,'_').gsub(/___/,'_').gsub(/__/,'_').chomp('_').strip
|
230
|
-
|
231
|
-
file_b64 = Base64.encode64(File.binread(filepath))
|
232
|
-
|
233
|
-
data = {}
|
234
|
-
data['file'] = {
|
235
|
-
'file' => file_b64,
|
236
|
-
'filesize' => File.size(filepath).to_s,
|
237
|
-
'filename' => File.basename(filepath)
|
238
|
-
}
|
239
|
-
|
240
|
-
data['node'] = {}
|
241
|
-
|
242
|
-
# Only include the content type if this is an update
|
243
|
-
if update
|
244
|
-
data['node']['uuid'] = content_type_or_uuid
|
245
|
-
else
|
246
|
-
data['node']['type'] = content_type_or_uuid
|
247
|
-
end
|
248
|
-
|
249
|
-
# TODO: remove this field_component_tags once BCL is fixed
|
250
|
-
data['node']['field_component_tags'] = { 'und' => '1289' }
|
251
|
-
data['node']['og_group_ref'] = { 'und' => ['target_id' => @group_id] }
|
252
|
-
|
253
|
-
# NOTE THIS ONLY WORKS IF YOU ARE A BCL SITE ADMIN
|
254
|
-
data['node']['publish'] = '1'
|
255
|
-
|
256
|
-
data
|
257
|
-
end
|
258
|
-
|
259
|
-
# pushes component to the bcl and publishes them (if logged-in as BCL Website Admin user).
|
260
|
-
# username, password, and group_id are set in the ~/.bcl/config.yml file
|
261
|
-
def push_content(filename_and_path, write_receipt_file, content_type)
|
262
|
-
raise 'Please login before pushing components' if @session.nil?
|
263
|
-
raise 'Do not have a valid access token; try again' if @access_token.nil?
|
264
|
-
|
265
|
-
data = construct_post_data(filename_and_path, false, content_type)
|
266
|
-
|
267
|
-
path = '/api/content.json'
|
268
|
-
headers = { 'Content-Type' => 'application/json', 'X-CSRF-Token' => @access_token, 'Cookie' => @session }
|
269
|
-
|
270
|
-
res = @http.post(path, JSON.dump(data), headers)
|
271
|
-
|
272
|
-
valid, json = evaluate_api_response(res)
|
273
|
-
|
274
|
-
if valid
|
275
|
-
# write out a receipt file into the same directory of the component with the same file name as
|
276
|
-
# the component
|
277
|
-
if write_receipt_file
|
278
|
-
File.open("#{File.dirname(filename_and_path)}/#{File.basename(filename_and_path, '.tar.gz')}.receipt", 'w') do |file|
|
279
|
-
file << Time.now.to_s
|
280
|
-
end
|
281
|
-
end
|
282
|
-
end
|
283
|
-
|
284
|
-
[valid, json]
|
285
|
-
end
|
286
|
-
|
287
|
-
# pushes updated content to the bcl and publishes it (if logged-in as BCL Website Admin user).
|
288
|
-
# username and password set in ~/.bcl/config.yml file
|
289
|
-
def update_content(filename_and_path, write_receipt_file, uuid = nil)
|
290
|
-
raise 'Please login before pushing components' unless @session
|
291
|
-
|
292
|
-
# get the UUID if zip or xml file
|
293
|
-
version_id = nil
|
294
|
-
if uuid.nil?
|
295
|
-
puts File.extname(filename_and_path).downcase
|
296
|
-
if filename_and_path.match?(/^.*.tar.gz$/i)
|
297
|
-
uuid, version_id = uuid_vid_from_tarball(filename_and_path)
|
298
|
-
puts "Parsed uuid out of tar.gz file with value #{uuid}"
|
299
|
-
end
|
300
|
-
else
|
301
|
-
# verify the uuid via regex
|
302
|
-
unless uuid.match?(/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/)
|
303
|
-
raise "uuid of #{uuid} is invalid"
|
304
|
-
end
|
305
|
-
end
|
306
|
-
raise 'Please pass in a tar.gz file or pass in the uuid' unless uuid
|
307
|
-
|
308
|
-
data = construct_post_data(filename_and_path, true, uuid)
|
309
|
-
|
310
|
-
path = '/api/content.json'
|
311
|
-
headers = { 'Content-Type' => 'application/json', 'X-CSRF-Token' => @access_token, 'Cookie' => @session }
|
312
|
-
|
313
|
-
res = @http.post(path, JSON.dump(data), headers)
|
314
|
-
|
315
|
-
valid, json = evaluate_api_response(res)
|
316
|
-
|
317
|
-
if valid
|
318
|
-
# write out a receipt file into the same directory of the component with the same file name as
|
319
|
-
# the component
|
320
|
-
if write_receipt_file
|
321
|
-
File.open("#{File.dirname(filename_and_path)}/#{File.basename(filename_and_path, '.tar.gz')}.receipt", 'w') do |file|
|
322
|
-
file << Time.now.to_s
|
323
|
-
end
|
324
|
-
end
|
325
|
-
end
|
326
|
-
|
327
|
-
[valid, json]
|
328
|
-
end
|
329
|
-
|
330
|
-
def push_contents(array_of_components, skip_files_with_receipts, content_type)
|
331
|
-
logs = []
|
332
|
-
array_of_components.each do |comp|
|
333
|
-
receipt_file = File.dirname(comp) + '/' + File.basename(comp, '.tar.gz') + '.receipt'
|
334
|
-
log_message = ''
|
335
|
-
if skip_files_with_receipts && File.exist?(receipt_file)
|
336
|
-
log_message = "skipping because found receipt #{comp}"
|
337
|
-
puts log_message
|
338
|
-
else
|
339
|
-
log_message = "pushing content #{File.basename(comp, '.tar.gz')}"
|
340
|
-
puts log_message
|
341
|
-
valid, res = push_content(comp, true, content_type)
|
342
|
-
log_message += " #{valid} #{res.inspect.chomp}"
|
343
|
-
end
|
344
|
-
logs << log_message
|
345
|
-
end
|
346
|
-
|
347
|
-
logs
|
348
|
-
end
|
349
|
-
|
350
78
|
# Unpack the tarball in memory and extract the XML file to read the UUID and Version ID
|
351
79
|
def uuid_vid_from_tarball(path_to_tarball)
|
352
80
|
uuid = nil
|
@@ -406,43 +134,18 @@ module BCL
|
|
406
134
|
[uuid, vid]
|
407
135
|
end
|
408
136
|
|
409
|
-
def update_contents(array_of_tarball_components, skip_files_with_receipts)
|
410
|
-
logs = []
|
411
|
-
array_of_tarball_components.each do |comp|
|
412
|
-
receipt_file = File.dirname(comp) + '/' + File.basename(comp, '.tar.gz') + '.receipt'
|
413
|
-
log_message = ''
|
414
|
-
if skip_files_with_receipts && File.exist?(receipt_file)
|
415
|
-
log_message = "skipping update because found receipt #{File.basename(comp)}"
|
416
|
-
puts log_message
|
417
|
-
else
|
418
|
-
uuid, vid = uuid_vid_from_tarball(comp)
|
419
|
-
if uuid.nil?
|
420
|
-
log_message = "ERROR: uuid not found for #{File.basename(comp)}"
|
421
|
-
puts log_message
|
422
|
-
else
|
423
|
-
log_message = "pushing updated content #{File.basename(comp)}"
|
424
|
-
puts log_message
|
425
|
-
valid, res = update_content(comp, true, uuid)
|
426
|
-
log_message += " #{valid} #{res.inspect.chomp}"
|
427
|
-
end
|
428
|
-
end
|
429
|
-
logs << log_message
|
430
|
-
end
|
431
|
-
logs
|
432
|
-
end
|
433
|
-
|
434
137
|
def search_by_uuid(uuid, vid = nil)
|
435
138
|
full_url = '/api/search.json'
|
436
|
-
action = nil
|
437
139
|
|
438
140
|
# add api_version
|
439
|
-
if @api_version
|
440
|
-
|
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}"
|
441
148
|
end
|
442
|
-
full_url += "?api_version=#{@api_version}"
|
443
|
-
|
444
|
-
# uuid
|
445
|
-
full_url += "&fq[]=ss_uuid:#{uuid}"
|
446
149
|
|
447
150
|
res = @http.get(full_url)
|
448
151
|
res = JSON.parse res.body
|
@@ -458,20 +161,9 @@ module BCL
|
|
458
161
|
else
|
459
162
|
content = content['component']
|
460
163
|
end
|
461
|
-
|
462
|
-
# TODO: check version_modified date if it exists?
|
463
|
-
if !vid.nil? && content['vuuid'] == vid
|
464
|
-
# no update needed
|
465
|
-
action = 'noop'
|
466
|
-
else
|
467
|
-
# vid doesn't match: update existing
|
468
|
-
action = 'update'
|
469
|
-
end
|
470
|
-
else
|
471
|
-
# no uuid found: push new
|
472
|
-
action = 'push'
|
473
164
|
end
|
474
|
-
|
165
|
+
|
166
|
+
content
|
475
167
|
end
|
476
168
|
|
477
169
|
# Simple method to search bcl and return the result as hash with symbols
|
@@ -492,22 +184,30 @@ module BCL
|
|
492
184
|
full_url += '*.json'
|
493
185
|
end
|
494
186
|
|
495
|
-
# add api_version
|
496
|
-
if @api_version
|
497
|
-
|
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
|
498
195
|
end
|
499
|
-
|
196
|
+
|
197
|
+
if @api_version == 2.0
|
198
|
+
full_url += "?api_version=#{@api_version}"
|
199
|
+
end
|
200
|
+
puts "@api_version: #{@api_version}"
|
500
201
|
|
501
202
|
# add filters
|
502
|
-
|
503
|
-
# strip out api_version from filters, if included
|
504
|
-
if filter_str.include? 'api_version='
|
505
|
-
filter_str = filter_str.gsub(
|
506
|
-
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,}/, '')
|
507
208
|
end
|
508
209
|
full_url = full_url + '&' + filter_str
|
509
210
|
end
|
510
|
-
|
511
211
|
# simple search vs. all results
|
512
212
|
if !all
|
513
213
|
puts "search url: #{full_url}"
|
@@ -556,14 +256,16 @@ module BCL
|
|
556
256
|
receipt_file = File.dirname(comp) + '/' + File.basename(comp, '.tar.gz') + '.receipt'
|
557
257
|
if File.exist?(receipt_file)
|
558
258
|
FileUtils.remove_file(receipt_file)
|
559
|
-
|
560
259
|
end
|
561
260
|
end
|
562
261
|
end
|
563
262
|
|
564
263
|
def list_all_measures
|
565
|
-
|
566
|
-
|
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
|
567
269
|
json
|
568
270
|
end
|
569
271
|
|
@@ -591,93 +293,27 @@ module BCL
|
|
591
293
|
config_filename = File.expand_path('~/.bcl/config.yml')
|
592
294
|
|
593
295
|
if File.exist?(config_filename)
|
594
|
-
puts "loading config
|
296
|
+
puts "loading URL config from #{config_filename}"
|
595
297
|
@config = YAML.load_file(config_filename)
|
596
298
|
else
|
597
|
-
#
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
@config = YAML.load_file(config_filename)
|
299
|
+
# use default URL
|
300
|
+
@config = {
|
301
|
+
server: {
|
302
|
+
url: 'https://bcl.nrel.gov'
|
303
|
+
}
|
304
|
+
}
|
604
305
|
end
|
605
306
|
end
|
606
307
|
|
308
|
+
# unused
|
607
309
|
def default_yaml
|
608
310
|
settings = {
|
609
311
|
server: {
|
610
|
-
url: 'https://bcl.nrel.gov'
|
611
|
-
user: {
|
612
|
-
username: 'ENTER_BCL_USERNAME',
|
613
|
-
password: 'ENTER_BCL_PASSWORD',
|
614
|
-
group: 'ENTER_GROUP_ID'
|
615
|
-
}
|
312
|
+
url: 'https://bcl.nrel.gov'
|
616
313
|
}
|
617
314
|
}
|
618
315
|
|
619
316
|
settings
|
620
317
|
end
|
621
318
|
end
|
622
|
-
|
623
|
-
# TODO: make this extend the component_xml class (or create a super class around components)
|
624
|
-
|
625
|
-
def self.gather_components(component_dir, chunk_size = 0, delete_previousgather = false, destination = nil)
|
626
|
-
if destination.nil?
|
627
|
-
@dest_filename = 'components'
|
628
|
-
else
|
629
|
-
@dest_filename = destination
|
630
|
-
end
|
631
|
-
@dest_file_ext = 'tar.gz'
|
632
|
-
|
633
|
-
# store the starting directory
|
634
|
-
current_dir = Dir.pwd
|
635
|
-
|
636
|
-
# an array to hold reporting info about the batches
|
637
|
-
gather_components_report = []
|
638
|
-
|
639
|
-
# go to the directory containing the components
|
640
|
-
Dir.chdir(component_dir)
|
641
|
-
|
642
|
-
# delete any old versions of the component chunks
|
643
|
-
FileUtils.rm_rf('./gather') if delete_previousgather
|
644
|
-
|
645
|
-
# gather all the components into array
|
646
|
-
targzs = Pathname.glob('./**/*.tar.gz')
|
647
|
-
tar_cnt = 0
|
648
|
-
chunk_cnt = 0
|
649
|
-
targzs.each do |targz|
|
650
|
-
if chunk_size != 0 && (tar_cnt % chunk_size) == 0
|
651
|
-
chunk_cnt += 1
|
652
|
-
end
|
653
|
-
tar_cnt += 1
|
654
|
-
|
655
|
-
destination_path = "./gather/#{chunk_cnt}"
|
656
|
-
FileUtils.mkdir_p(destination_path)
|
657
|
-
destination_file = "#{destination_path}/#{File.basename(targz.to_s)}"
|
658
|
-
# puts "copying #{targz.to_s} to #{destination_file}"
|
659
|
-
FileUtils.cp(targz.to_s, destination_file)
|
660
|
-
end
|
661
|
-
|
662
|
-
# gather all the .tar.gz files into a single tar.gz
|
663
|
-
(1..chunk_cnt).each do |cnt|
|
664
|
-
currentdir = Dir.pwd
|
665
|
-
|
666
|
-
paths = []
|
667
|
-
Pathname.glob("./gather/#{cnt}/*.tar.gz").each do |pt|
|
668
|
-
paths << File.basename(pt.to_s)
|
669
|
-
end
|
670
|
-
|
671
|
-
Dir.chdir("./gather/#{cnt}")
|
672
|
-
destination = "#{@dest_filename}_#{cnt}.#{@dest_file_ext}"
|
673
|
-
puts "tarring batch #{cnt} of #{chunk_cnt} to #{@dest_filename}_#{cnt}.#{@dest_file_ext}"
|
674
|
-
BCL.tarball(destination, paths)
|
675
|
-
Dir.chdir(currentdir)
|
676
|
-
|
677
|
-
# move the tarball back a directory
|
678
|
-
FileUtils.move("./gather/#{cnt}/#{destination}", "./gather/#{destination}")
|
679
|
-
end
|
680
|
-
|
681
|
-
Dir.chdir(current_dir)
|
682
|
-
end
|
683
319
|
end
|
data/lib/bcl/core_ext.rb
CHANGED
@@ -1,21 +1,7 @@
|
|
1
|
-
|
2
|
-
#
|
3
|
-
#
|
4
|
-
#
|
5
|
-
# This library is free software; you can redistribute it and/or
|
6
|
-
# modify it under the terms of the GNU Lesser General Public
|
7
|
-
# License as published by the Free Software Foundation; either
|
8
|
-
# version 2.1 of the License, or (at your option) any later version.
|
9
|
-
#
|
10
|
-
# This library is distributed in the hope that it will be useful,
|
11
|
-
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
13
|
-
# Lesser General Public License for more details.
|
14
|
-
#
|
15
|
-
# You should have received a copy of the GNU Lesser General Public
|
16
|
-
# License along with this library; if not, write to the Free Software
|
17
|
-
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
18
|
-
######################################################################
|
1
|
+
# *******************************************************************************
|
2
|
+
# OpenStudio(R), Copyright (c) Alliance for Sustainable Energy, LLC.
|
3
|
+
# See also https://openstudio.net/license
|
4
|
+
# *******************************************************************************
|
19
5
|
|
20
6
|
class String
|
21
7
|
def to_underscore
|
data/lib/bcl/tar_ball.rb
CHANGED
@@ -1,65 +1,17 @@
|
|
1
|
-
|
2
|
-
#
|
3
|
-
#
|
4
|
-
#
|
5
|
-
# This library is free software; you can redistribute it and/or
|
6
|
-
# modify it under the terms of the GNU Lesser General Public
|
7
|
-
# License as published by the Free Software Foundation; either
|
8
|
-
# version 2.1 of the License, or (at your option) any later version.
|
9
|
-
#
|
10
|
-
# This library is distributed in the hope that it will be useful,
|
11
|
-
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
13
|
-
# Lesser General Public License for more details.
|
14
|
-
#
|
15
|
-
# You should have received a copy of the GNU Lesser General Public
|
16
|
-
# License along with this library; if not, write to the Free Software
|
17
|
-
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
18
|
-
######################################################################
|
1
|
+
# *******************************************************************************
|
2
|
+
# OpenStudio(R), Copyright (c) Alliance for Sustainable Energy, LLC.
|
3
|
+
# See also https://openstudio.net/license
|
4
|
+
# *******************************************************************************
|
19
5
|
|
20
6
|
module BCL
|
21
7
|
module_function
|
22
8
|
|
23
|
-
# tarball multiple paths recursively to destination
|
24
|
-
def tarball(destination, paths)
|
25
|
-
# check for filepath length limit
|
26
|
-
full_destination = File.expand_path(destination)
|
27
|
-
if full_destination.length > 259 # 256 chars max; "C:\" doesn't count
|
28
|
-
puts "[TarBall] ERROR cannot generate #{destination} because path exceeds 256 char limit. shorten component name by at least by #{full_destination.length - 259} chars"
|
29
|
-
return
|
30
|
-
end
|
31
|
-
|
32
|
-
Zlib::GzipWriter.open(destination) do |gzip|
|
33
|
-
out = Archive::Tar::Minitar::Output.new(gzip)
|
34
|
-
|
35
|
-
paths.each do |fi|
|
36
|
-
if File.exist?(fi)
|
37
|
-
Archive::Tar::Minitar.pack_file(fi, out)
|
38
|
-
else
|
39
|
-
puts "[TarBall] ERROR Could not file file: #{fi}"
|
40
|
-
end
|
41
|
-
end
|
42
|
-
out.close
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
9
|
def extract_tarball(filename, destination)
|
47
10
|
Zlib::GzipReader.open(filename) do |gz|
|
48
11
|
Archive::Tar::Minitar.unpack(gz, destination)
|
49
12
|
end
|
50
13
|
end
|
51
14
|
|
52
|
-
def create_zip(_destination, paths)
|
53
|
-
Zip::File.open(zipfile_name, Zip::File::CREATE) do |zipfile|
|
54
|
-
paths.each do |fi|
|
55
|
-
# Two arguments:
|
56
|
-
# - The name of the file as it will appear in the archive
|
57
|
-
# - The original file, including the path to find it
|
58
|
-
zipfile.add(fi.basename, fi)
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
15
|
def extract_zip(filename, destination, delete_zip = false)
|
64
16
|
Zip::File.open(filename) do |zip_file|
|
65
17
|
zip_file.each do |f|
|