Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add array_element #23

Merged
merged 1 commit into from
Sep 11, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 19 additions & 4 deletions README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,10 @@ hocon_setting { 'sample map setting':
* `value`: The value of the HOCON file setting to be defined.

* `type`: The type of the value passed into the `value` parameter. This value should be a string, with valid values being
`'number'`, `'boolean'`, `'string'`, `'hash'`, `'array'`, and `'text'`.
`'number'`, `'boolean'`, `'string'`, `'hash'`, `'array'`, `'array_element'`, and `'text'`.

This parameter will not be need to be set most of the time, as the module
is generally smart enough to figure this out on its own. There are only two cases in which this parameter is required.
is generally smart enough to figure this out on its own. There are only three cases in which this parameter is required.

The first is the case in which the `value` type is a single-element array. In that case, the `type` parameter will need to be set to
`'array'`. So, for example, to add a single-element array, you would add the following to your manifest
Expand All @@ -112,7 +112,22 @@ hocon_setting { 'sample map setting':
type => 'array',
}
```


If you are trying to manage single entries in an array (for example, adding to an array from a define) you will need to set the `'type'` parameter to
`'array_element'`. For example, to add to an existing array in the 'foo' setting, you can add the following to your manifest

```
hocon_setting { 'add to array':
ensure => present,
path => '/tmp/foo.conf',
setting => 'foo',
value => 2,
type => 'array_element',
}
```

Note: When adding an item via 'array_element', the array must already exist in the HOCON file.

Since this type represents a setting in a configuration file, you can pass a string containing the exact text of the value as you want it to appear
in the file (this is useful, for example, if you want to set a parameter to a map or an array but want comments or specific indentation on elements in the map/array).
In this case, `value` must be a string with no leading or trailing whitespace, newlines, or comments that contains a valid HOCON value, and the
Expand Down Expand Up @@ -165,7 +180,7 @@ hocon_setting { 'sample map setting':
}
```

Aside from these two cases, the `type` parameter does not need to be set.
Aside from these three cases, the `type` parameter does not need to be set.

##Development

Expand Down
46 changes: 43 additions & 3 deletions lib/puppet/provider/hocon_setting/ruby.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,16 @@ def self.namevar(section_name, setting)
end

def exists?
conf_file.has_value?(setting)
if resource[:type] == 'array_element'
Array(@resource[:value]).each do |v|
if value.flatten.include?(v)
return true
end
end
return false
else
conf_file.has_value?(setting)
end
end

def create
Expand All @@ -21,7 +30,7 @@ def create
end

def destroy
conf_file_modified = conf_file.remove_value(setting)
conf_file_modified = remove_value(resource[:value])
write_conf(conf_file_modified)
@conf_file = nil
end
Expand Down Expand Up @@ -82,8 +91,39 @@ def conf_object
Hocon::ConfigFactory.parse_file(file_path)
end

def remove_value(value_to_remove)
if resource[:type] == 'array_element'
new_value_tmp = []
val = value
Array(val).each do |v|
new_value_tmp << v
end
Array(value_to_remove).each do |v|
new_value_tmp.delete(v)
end
new_value = Hocon::ConfigValueFactory.from_any_ref(new_value_tmp, nil)
conf_file_modified = conf_file.set_config_value(setting, new_value)
else
conf_file_modified = conf_file.remove_value(setting)
end
conf_file_modified
end

def set_value(value_to_set)
if resource[:type] == 'array' || (value_to_set.is_a?(String) && resource[:type] != 'text') || (value_to_set.is_a?(Array) && value_to_set.size > 1)
if resource[:type] == 'array_element'
tmp_val = []
val = value
Array(val).each do |v|
tmp_val << v
end
Array(value_to_set).each do |v|
unless tmp_val.include?(v)
tmp_val << v
end
end

new_value = Hocon::ConfigValueFactory.from_any_ref(tmp_val, nil)
elsif resource[:type] == 'array' || (value_to_set.is_a?(String) && resource[:type] != 'text') || (value_to_set.is_a?(Array) && value_to_set.size > 1)
new_value = Hocon::ConfigValueFactory.from_any_ref(value_to_set, nil)
elsif resource[:type] == 'text'
new_value = value_to_set[0]
Expand Down
29 changes: 28 additions & 1 deletion lib/puppet/type/hocon_setting.rb
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
unless value.is_a?(Hash)
raise "Type specified as 'hash' but was #{value.class}"
end
when nil
when 'array_element', nil
# Do nothing, we'll figure it out on our own
else
raise "Type was specified as #{@resource[:type]}, but should have been one of 'boolean', 'string', 'text', 'number', 'array', or 'hash'"
Expand All @@ -75,6 +75,33 @@
end
value
end

def insync?(is)
if @resource[:type] == 'array_element'
# make sure all passed values are in the file
Array(@resource[:value]).each do |v|
if not provider.value.flatten.include?(v)
return false
end
end
return true
else
super
end
end

def change_to_s(current, new)
if @resource[:type] == 'array_element'
real_new = []
real_new << current
real_new << new
real_new.flatten!
real_new.uniq!
"value changed [#{Array(current).flatten.join(", ")}] to [#{real_new.join(", ")}]"
else
super
end
end
end

validate do
Expand Down
84 changes: 84 additions & 0 deletions spec/unit/puppet/provider/conf_setting/ruby_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,90 @@ def validate_file(expected_content,tmpfile = tmpfile)
end
end

context "array_element" do
let(:orig_content) {
<<-EOS
test_key_1: [
{
foo: foovalue
bar: barvalue
master: true
}
,
{
foo: foovalue2
baz: bazvalue
url: "http://192.168.1.1:8080"
}
,
{
foo: foovalue3
}
]
EOS
}

it "should add a new element to the array" do
resource = Puppet::Type::Hocon_setting.new(common_params.merge(
:setting => 'test_key_1', :value => [{ 'foo' => 'foovalue3' }, { 'bar' => 'barvalue3' }], :type => 'array_element'))
provider = described_class.new(resource)
expect(provider.exists?).to be true
provider.create
validate_file(
<<-EOS
test_key_1: [
{
"bar" : "barvalue",
"foo" : "foovalue",
"master" : true
}
,
{
"baz" : "bazvalue",
"foo" : "foovalue2",
"url" : "http://192.168.1.1:8080"
}
,
{
"foo" : "foovalue3"
}
,
{
"bar" : "barvalue3"
}

]
EOS
)
end

it "should remove elements from the array" do
resource = Puppet::Type::Hocon_setting.new(common_params.merge(
:setting => 'test_key_1', :ensure => 'absent', :value => { 'foo' => 'foovalue3' }, :type => 'array_element'))
provider = described_class.new(resource)
expect(provider.exists?).to be true
provider.destroy
validate_file(
<<-EOS
test_key_1: [
{
"bar" : "barvalue",
"foo" : "foovalue",
"master" : true
}
,
{
"baz" : "bazvalue",
"foo" : "foovalue2",
"url" : "http://192.168.1.1:8080"
}

]
EOS
)
end
end

context "when ensuring that a setting is present" do
let(:orig_content) {
<<-EOS
Expand Down
1 change: 1 addition & 0 deletions spec/unit/puppet/type/hocon_setting_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
'text',
'number',
'array',
'array_element',
'hash'
]

Expand Down