Skip to content
This repository has been archived by the owner on Jun 5, 2020. It is now read-only.

Commit

Permalink
Ability to set lifecycle and encryption configuration for buckets.
Browse files Browse the repository at this point in the history
Signed-off-by: Andrey Voronkov <avoronkov@enapter.com>
  • Loading branch information
Antiarchitect committed Jan 24, 2020
1 parent c9a1cc8 commit 347e157
Show file tree
Hide file tree
Showing 4 changed files with 155 additions and 5 deletions.
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2743,6 +2743,16 @@ The name of the bucket to managed.
A JSON parsable string of the policy to apply to the bucket.
##### `lifecycle_configuration`
A JSON parsable string of the lifecycle configuration to apply to the bucket.
More https://docs.amazonaws.cn/sdk-for-ruby/v3/api/Aws/S3/Client.html#put_bucket_lifecycle_configuration-instance_method
##### `encryption_configuration`
A JSON parsable string of the encryption configuration to apply to the bucket.
More https://docs.amazonaws.cn/sdk-for-ruby/v3/api/Aws/S3/Client.html#put_bucket_encryption-instance_method
#### Type: sqs_queue
##### `name`
Expand Down
70 changes: 70 additions & 0 deletions lib/puppet/provider/s3_bucket/v2.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,20 @@ def self.instances
Puppet.debug("An error occurred reading the policy on S3 bucket #{s3_bucket.name}: " + e.message)
end

begin
results = s3_client.get_bucket_lifecycle_configuration({bucket: s3_bucket.name})
data[:lifecycle_configuration] = JSON.pretty_generate(camelize_stringify_keys(results.to_h))
rescue Exception => e
Puppet.debug("An error occurred reading the lifecycle configuration on S3 bucket #{s3_bucket.name}: " + e.message)
end

begin
results = s3_client.get_bucket_encryption({bucket: s3_bucket.name})
data[:encryption_configuration] = JSON.pretty_generate(camelize_stringify_keys(results.server_side_encryption_configuration.to_h))
rescue Exception => e
Puppet.debug("An error occurred reading the encryption configuration on S3 bucket #{s3_bucket.name}: " + e.message)
end

new(data)
end
bucket_list.reject {|b| b.nil? }
Expand Down Expand Up @@ -61,4 +75,60 @@ def policy=(value)
})
end

def lifecycle_configuration=(value)
Puppet.debug('Replacing bucket lifecycle configuration')
s3_client.put_bucket_lifecycle_configuration({
bucket: @property_hash[:name],
lifecycle_configuration: underscore_symbolarize_keys(JSON.parse(value))
})
end

def encryption_configuration=(value)
Puppet.debug('Replacing bucket encryption configuration')
s3_client.put_bucket_encryption({
bucket: @property_hash[:name],
server_side_encryption_configuration: underscore_symbolarize_keys(JSON.parse(value))
})
end

end

private

def underscore_symbolarize_keys(obj)
return obj.reduce({}) do |acc, (k, v)|
acc.tap { |m| m[underscore(k).to_sym] = underscore_symbolarize_keys(v) }
end if obj.is_a? Hash

return obj.reduce([]) do |acc, v|
acc << underscore_symbolarize_keys(v); acc
end if obj.is_a? Array

obj
end

def camelize_stringify_keys(obj)
return obj.reduce({}) do |acc, (k, v)|
acc.tap { |m| m[camelize(k.to_s)] = camelize_stringify_keys(v) }
end if obj.is_a? Hash

return obj.reduce([]) do |acc, v|
acc << camelize_stringify_keys(v); acc
end if obj.is_a? Array

obj
end

def underscore(str)
str.gsub(/::/, '/').
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
gsub(/([a-z\d])([A-Z])/,'\1_\2').
tr("-", "_").
downcase
end

def camelize(str)
return "ID" if str == "id"
return "SSEAlgorithm" if str == "sse_algorithm"
str.split(/_/).map(&:capitalize).join
end
43 changes: 40 additions & 3 deletions lib/puppet/type/s3_bucket.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,55 @@
newproperty(:policy) do
desc 'The policy document JSON string to apply'
validate do |value|
fail Puppet::Error, 'Policy documents must be JSON strings' unless value.is_a? String
fail Puppet::Error, 'Policy documents must be JSON strings' unless is_valid_json?(value)
end

munge do |value|
begin
data = JSON.parse(value)
JSON.pretty_generate(data)
JSON.pretty_generate(JSON.parse(value))
rescue
fail('Policy string is not valid JSON')
end
end
end

newproperty(:lifecycle_configuration) do
desc 'The lifecycle configuration document JSON string to apply'
validate do |value|
fail Puppet::Error, 'Lifecycle configuration documents must be JSON strings' unless is_valid_json?(value)
end

munge do |value|
begin
JSON.pretty_generate(JSON.parse(value))
rescue
fail('Lifecycle configuration string is not valid JSON')
end
end
end

newproperty(:encryption_configuration) do
desc 'The bucket encryption document JSON string to apply'
validate do |value|
fail Puppet::Error, 'Bucket encryption documents must be JSON strings' unless is_valid_json?(value)
end

munge do |value|
begin
JSON.pretty_generate(JSON.parse(value))
rescue
fail('Bucket encryption string is not valid JSON')
end
end
end

end

private

def is_valid_json?(string)
!!JSON.parse(string)
rescue JSON::ParserError => _e
false
end

37 changes: 35 additions & 2 deletions spec/unit/type/s3_bucket_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,19 @@
:ensure,
:creation_date,
:policy,
:lifecycle_configuration,
]
end

let :valid_attributes do
{
name: 'name',
policy: '{}',
encryption_configuration: '{}',
lifecycle_configuration: '{}'
}
end

it 'should have expected properties' do
properties.each do |property|
expect(type_class.properties.map(&:name)).to be_include(property)
Expand All @@ -42,9 +52,32 @@
}.to raise_error(Puppet::Error, /Empty bucket names are not allowed/)
end

context 'with a valid name' do
context 'with a valid parameters' do
it 'should create a valid instance' do
type_class.new({ name: 'name' })
type_class.new(valid_attributes)
end

[:policy, :encryption_configuration, :lifecycle_configuration].each do |param|
it "should create a valid instance without optional :#{param}" do
type_class.new(valid_attributes.reject! { |k, _v| k == param })
end

it "should require non-blank #{param}" do
expect {
type_class.new(valid_attributes.merge({ param => '' }))
}.to raise_error(Puppet::Error)
end

it "should fail if string is not a valid JSON #{param}" do
expect {
type_class.new(valid_attributes.merge({ param => '<xml>Hi</xml>' }))
}.to raise_error(Puppet::Error)
end

it "should accept any valid JSON #{param}" do
type_class.new(valid_attributes.merge({ param => '{ "hello": "world!" }' }))
end

end
end

Expand Down

0 comments on commit 347e157

Please sign in to comment.