Properly handle embedded newlines in csv

When parsing the response from the OpenStack client values (like
keystone tenant descriptions) can have embedded newline. To avoid this
issue, we drop lines that don't start with a double quoted value until
the first one we find.

Change-Id: Ie952161b503d2c46637e6a6e1c83b2dfce1c03a7
This commit is contained in:
Clayton O'Neill 2015-03-16 22:35:04 -04:00 committed by Gael Chamoulaud
parent ed58789665
commit efa9181201
2 changed files with 40 additions and 4 deletions

View File

@ -51,10 +51,7 @@ class Puppet::Provider::Openstack < Puppet::Provider
begin
if(action == 'list')
response = openstack(service, action, '--quiet', '--format', 'csv', args)
# Ignore warnings - assume legitimate output starts with a double quote
# Errors will be caught and raised prior to this
response = response.split("\n").select { |line| line =~ /^\".*\",\".*\"/ }.join("\n")
response = CSV.parse(response.to_s)
response = parse_csv(response)
keys = response.delete_at(0) # ID,Name,Description,Enabled
rv = response.collect do |line|
hash = {}
@ -180,4 +177,11 @@ class Puppet::Provider::Openstack < Puppet::Provider
self.class.get_credentials_from_env
end
def self.parse_csv(text)
# Ignore warnings - assume legitimate output starts with a double quoted
# string. Errors will be caught and raised prior to this
text = text.split("\n").drop_while { |line| line !~ /^\".*\"/ }.join("\n")
return CSV.parse(text + "\n")
end
end

View File

@ -225,4 +225,36 @@ Enabled="True"
end
describe 'parse_csv' do
context 'with mixed stderr' do
text = "ERROR: Testing\n\"field\",\"test\",1,2,3\n"
csv = Puppet::Provider::Openstack.parse_csv(text)
it 'should ignore non-CSV text at the beginning of the input' do
expect(csv).to be_kind_of(Array)
expect(csv[0]).to match_array(['field', 'test', '1', '2', '3'])
expect(csv.size).to eq(1)
end
end
context 'with \r\n line endings' do
text = "ERROR: Testing\r\n\"field\",\"test\",1,2,3\r\n"
csv = Puppet::Provider::Openstack.parse_csv(text)
it 'ignore the carriage returns' do
expect(csv).to be_kind_of(Array)
expect(csv[0]).to match_array(['field', 'test', '1', '2', '3'])
expect(csv.size).to eq(1)
end
end
context 'with embedded newlines' do
text = "ERROR: Testing\n\"field\",\"te\nst\",1,2,3\n"
csv = Puppet::Provider::Openstack.parse_csv(text)
it 'should parse correctly' do
expect(csv).to be_kind_of(Array)
expect(csv[0]).to match_array(['field', "te\nst", '1', '2', '3'])
expect(csv.size).to eq(1)
end
end
end
end