Fix properties in cinder_type provider for osc >= 4.0.0

Openstackclient 4.0.0 changed the way some properties are displayed
on screen.

Old:
...,"Properties"
...,"volume_backend_name='BACKEND_1'"

New:
...,"Properties"
...,"{u'volume_backend_name': u'BACKEND_1'}"
or
...,"{'volume_backend_name': 'BACKEND_1'}"

This is breaking idempotency on the cinder_type provider, since it
does not detect them correctly. This patch aims at fixing this, by
trying to detect the new format, and using JSON parsing in that case.

Change-Id: I6a68505d15473b140c85a199a09d2fee45864800
This commit is contained in:
Javier Pena 2019-09-18 17:48:56 +02:00
parent d004949ac8
commit 5821ade2cf
2 changed files with 67 additions and 2 deletions

View File

@ -80,7 +80,7 @@ Puppet::Type.type(:cinder_type).provide(
list.each do |type|
if type[:is_public] == 'False'
type_details = request('volume type', 'show', type[:id])
type[:access_project_ids] = string2array(type_details[:access_project_ids])
type[:access_project_ids] = parsestring(type_details[:access_project_ids])
type[:is_public] = false
else
type[:access_project_ids] = []
@ -93,7 +93,7 @@ Puppet::Type.type(:cinder_type).provide(
:name => type[:name],
:ensure => :present,
:id => type[:id],
:properties => string2array(type[:properties]),
:properties => parsestring(type[:properties]),
:is_public => type[:is_public],
:access_project_ids => type[:access_project_ids]
})
@ -112,4 +112,23 @@ Puppet::Type.type(:cinder_type).provide(
def self.string2array(input)
return input.delete("'").split(/,\s/)
end
def self.pythondict2array(input)
json_input = JSON.parse(input.gsub(/u'(\w*)'/, '"\1"').gsub(/'/, '"'))
output = []
json_input.each do | k, v |
output = output + ["#{k}=#{v}"]
end
return output
end
def self.parsestring(input)
if input[0] == '{'
# 4.0.0+ output, python dict
return self.pythondict2array(input)
else
# Pre-4.0.0 output, key=value
return self.string2array(input)
end
end
end

View File

@ -89,6 +89,28 @@ access_project_ids="54f4d231201b4944a5fa4587a09bda23, 54f4d231201b4944a5fa4587a0
expect(instances[0].access_project_ids).to match_array([])
expect(instances[1].access_project_ids).to match_array(['54f4d231201b4944a5fa4587a09bda23', '54f4d231201b4944a5fa4587a09bda28'])
end
it 'finds types with a Properties hash' do
provider_class.expects(:openstack)
.with('volume type', 'list', '--quiet', '--format', 'csv', '--long')
.returns('"ID","Name","Is Public","Properties"
"28b632e8-6694-4bba-bf68-67b19f619019","type-1","True","{\'key1\': \'value1\'}"
"4f992f69-14ec-4132-9313-55cc06a6f1f6","type-2","False","{\'key2\': \'value2\'}"
')
provider_class.expects(:openstack)
.with('volume type', 'show', '--format', 'shell', '4f992f69-14ec-4132-9313-55cc06a6f1f6')
.returns('
id="4f992f69-14ec-4132-9313-55cc06a6f1f6"
name="type-2"
properties="key2=\'value2\'"
is_public="False"
access_project_ids="54f4d231201b4944a5fa4587a09bda23, 54f4d231201b4944a5fa4587a09bda28"
')
instances = provider_class.instances
expect(instances.count).to eq(2)
expect(instances[0].properties).to eq(["key1=value1"])
expect(instances[1].properties).to eq(["key2=value2"])
end
end
describe '#string2array' do
@ -97,5 +119,29 @@ access_project_ids="54f4d231201b4944a5fa4587a09bda23, 54f4d231201b4944a5fa4587a0
expect(provider_class.string2array(s)).to eq(['key=value', 'key2=value2'])
end
end
describe '#pythondict2array' do
it 'should return an array with key-value when provided with a unicode python dict' do
s = "{u'key': 'value', u'key2': 'value2'}"
expect(provider_class.pythondict2array(s)).to eq(['key=value', 'key2=value2'])
end
it 'should return an array with key-value when provided with a python dict' do
s = "{'key': 'value', 'key2': 'value2'}"
expect(provider_class.pythondict2array(s)).to eq(['key=value', 'key2=value2'])
end
end
describe '#parsestring' do
it 'should call string2array when provided with a string' do
s = "key='value', key2='value2'"
expect(provider_class.parsestring(s)).to eq(['key=value', 'key2=value2'])
end
it 'should call pythondict2array when provided with a hash' do
s = "{u'key': 'value', u'key2': 'value2'}"
expect(provider_class.parsestring(s)).to eq(['key=value', 'key2=value2'])
end
end
end
end