2015-07-16 01:16:24 +00:00
#!/usr/bin/python
2017-08-12 16:27:11 +00:00
# Copyright: Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import , division , print_function
__metaclass__ = type
2015-07-16 01:16:24 +00:00
2017-08-16 03:16:38 +00:00
ANSIBLE_METADATA = { ' metadata_version ' : ' 1.1 ' ,
2017-03-14 16:07:22 +00:00
' status ' : [ ' stableinterface ' ] ,
2017-08-16 03:16:38 +00:00
' supported_by ' : ' certified ' }
2017-03-14 16:07:22 +00:00
2016-12-06 10:35:25 +00:00
2015-07-16 01:16:24 +00:00
DOCUMENTATION = '''
- - -
module : s3_lifecycle
short_description : Manage s3 bucket lifecycle rules in AWS
description :
- Manage s3 bucket lifecycle rules in AWS
version_added : " 2.0 "
2015-09-05 15:55:34 +00:00
author : " Rob White (@wimnat) "
2015-07-16 01:16:24 +00:00
notes :
- If specifying expiration time as days then transition time must also be specified in days
- If specifying expiration time as a date then transition time must also be specified as a date
requirements :
- python - dateutil
options :
name :
description :
- " Name of the s3 bucket "
required : true
expiration_date :
description :
2017-03-23 01:50:28 +00:00
- >
Indicates the lifetime of the objects that are subject to the rule by the date they will expire . The value must be ISO - 8601 format , the time must
be midnight and a GMT timezone must be specified .
2015-07-16 01:16:24 +00:00
expiration_days :
description :
- " Indicates the lifetime, in days, of the objects that are subject to the rule. The value must be a non-zero positive integer. "
prefix :
description :
2015-09-05 15:55:34 +00:00
- " Prefix identifying one or more objects to which the rule applies. If no prefix is specified, the rule will apply to the whole bucket. "
2018-05-17 19:07:40 +00:00
purge_transitions :
description :
- >
" Whether to replace all the current transition(s) with the new transition(s). When false, the provided transition(s)
will be added , replacing transitions with the same storage_class . When true , existing transitions will be removed and
replaced with the new transition ( s )
default : true
type : bool
version_added : 2.6
noncurrent_version_expiration_days :
description :
- ' Delete noncurrent versions this many days after they become noncurrent '
required : false
version_added : 2.6
noncurrent_version_storage_class :
description :
- ' Transition noncurrent versions to this storage class '
default : glacier
choices : [ ' glacier ' , ' onezone_ia ' , ' standard_ia ' ]
required : false
version_added : 2.6
noncurrent_version_transition_days :
description :
- ' Transition noncurrent versions this many days after they become noncurrent '
required : false
version_added : 2.6
noncurrent_version_transitions :
description :
- >
A list of transition behaviors to be applied to noncurrent versions for the rule . Each storage class may be used only once . Each transition
behavior contains these elements
I ( transition_days )
I ( storage_class )
version_added : 2.6
2015-07-16 01:16:24 +00:00
rule_id :
description :
- " Unique identifier for the rule. The value cannot be longer than 255 characters. A unique value for the rule will be generated if no value is provided. "
state :
description :
- " Create or remove the lifecycle rule "
default : present
choices : [ ' present ' , ' absent ' ]
status :
description :
- " If ' enabled ' , the rule is currently being applied. If ' disabled ' , the rule is not currently being applied. "
default : enabled
choices : [ ' enabled ' , ' disabled ' ]
storage_class :
description :
2018-05-17 19:07:40 +00:00
- " The storage class to transition to. Currently there are two supported values - ' glacier ' , ' onezone_ia ' , or ' standard_ia ' . "
2016-05-14 08:45:05 +00:00
- " The ' standard_ia ' class is only being available from Ansible version 2.2. "
2015-07-16 01:16:24 +00:00
default : glacier
2018-05-17 19:07:40 +00:00
choices : [ ' glacier ' , ' onezone_ia ' , ' standard_ia ' ]
2015-07-16 01:16:24 +00:00
transition_date :
description :
2017-03-23 01:50:28 +00:00
- >
Indicates the lifetime of the objects that are subject to the rule by the date they will transition to a different storage class .
The value must be ISO - 8601 format , the time must be midnight and a GMT timezone must be specified . If transition_days is not specified ,
this parameter is required . "
2015-07-16 01:16:24 +00:00
transition_days :
description :
- " Indicates when, in days, an object transitions to a different storage class. If transition_date is not specified, this parameter is required. "
2018-05-17 19:07:40 +00:00
transitions :
description :
- A list of transition behaviors to be applied to the rule . Each storage class may be used only once . Each transition
behavior may contain these elements
I ( transition_days )
I ( transition_date )
I ( storage_class )
version_added : 2.6
2016-12-08 05:34:16 +00:00
extends_documentation_fragment :
- aws
- ec2
2015-07-16 01:16:24 +00:00
'''
EXAMPLES = '''
# Note: These examples do not set authentication details, see the AWS Guide for details.
# Configure a lifecycle rule on a bucket to expire (delete) items with a prefix of /logs/ after 30 days
- s3_lifecycle :
name : mybucket
expiration_days : 30
prefix : / logs /
status : enabled
state : present
2015-12-01 03:01:57 +00:00
2015-07-16 01:16:24 +00:00
# Configure a lifecycle rule to transition all items with a prefix of /logs/ to glacier after 7 days and then delete after 90 days
- s3_lifecycle :
name : mybucket
transition_days : 7
expiration_days : 90
prefix : / logs /
status : enabled
state : present
2015-12-01 03:01:57 +00:00
2017-03-23 01:50:28 +00:00
# Configure a lifecycle rule to transition all items with a prefix of /logs/ to glacier on 31 Dec 2020 and then delete on 31 Dec 2030.
# Note that midnight GMT must be specified.
2015-07-16 01:16:24 +00:00
# Be sure to quote your date strings
- s3_lifecycle :
name : mybucket
transition_date : " 2020-12-30T00:00:00.000Z "
expiration_date : " 2030-12-30T00:00:00.000Z "
prefix : / logs /
status : enabled
state : present
2015-12-01 03:01:57 +00:00
2015-07-16 01:16:24 +00:00
# Disable the rule created above
- s3_lifecycle :
name : mybucket
prefix : / logs /
status : disabled
state : present
2015-12-01 03:01:57 +00:00
2015-07-16 01:16:24 +00:00
# Delete the lifecycle rule created above
- s3_lifecycle :
name : mybucket
prefix : / logs /
state : absent
2015-12-01 03:01:57 +00:00
2016-05-14 08:45:05 +00:00
# Configure a lifecycle rule to transition all backup files older than 31 days in /backups/ to standard infrequent access class.
- s3_lifecycle :
name : mybucket
prefix : / backups /
storage_class : standard_ia
transition_days : 31
state : present
status : enabled
2018-05-17 19:07:40 +00:00
# Configure a lifecycle rule to transition files to infrequent access after 30 days and glacier after 90
- s3_lifecycle :
name : mybucket
prefix : / logs /
state : present
status : enabled
transitions :
- transition_days : 30
storage_class : standard_ia
- transition_days : 90
storage_class : glacier
2015-07-16 01:16:24 +00:00
'''
2018-05-17 19:07:40 +00:00
from copy import deepcopy
2015-07-16 01:16:24 +00:00
import datetime
try :
import dateutil . parser
HAS_DATEUTIL = True
except ImportError :
HAS_DATEUTIL = False
try :
2018-05-17 19:07:40 +00:00
from botocore . exceptions import BotoCoreError , ClientError
2015-07-16 01:16:24 +00:00
except ImportError :
2018-05-17 19:07:40 +00:00
pass # handled by AnsibleAwsModule
2015-07-16 01:16:24 +00:00
2018-05-17 19:07:40 +00:00
from ansible . module_utils . aws . core import AnsibleAWSModule
2016-10-23 20:41:03 +00:00
2017-08-12 16:27:11 +00:00
2018-05-17 19:07:40 +00:00
def create_lifecycle_rule ( client , module ) :
2015-07-16 01:16:24 +00:00
name = module . params . get ( " name " )
expiration_date = module . params . get ( " expiration_date " )
expiration_days = module . params . get ( " expiration_days " )
2018-05-17 19:07:40 +00:00
noncurrent_version_expiration_days = module . params . get ( " noncurrent_version_expiration_days " )
noncurrent_version_transition_days = module . params . get ( " noncurrent_version_transition_days " )
noncurrent_version_transitions = module . params . get ( " noncurrent_version_transitions " )
noncurrent_version_storage_class = module . params . get ( " noncurrent_version_storage_class " )
2018-09-06 19:44:26 +00:00
prefix = module . params . get ( " prefix " ) or " "
2015-07-16 01:16:24 +00:00
rule_id = module . params . get ( " rule_id " )
status = module . params . get ( " status " )
storage_class = module . params . get ( " storage_class " )
transition_date = module . params . get ( " transition_date " )
transition_days = module . params . get ( " transition_days " )
2018-05-17 19:07:40 +00:00
transitions = module . params . get ( " transitions " )
purge_transitions = module . params . get ( " purge_transitions " )
2015-07-16 01:16:24 +00:00
changed = False
# Get the bucket's current lifecycle rules
try :
2018-05-17 19:07:40 +00:00
current_lifecycle = client . get_bucket_lifecycle_configuration ( Bucket = name )
current_lifecycle_rules = current_lifecycle [ ' Rules ' ]
except ClientError as e :
if e . response [ ' Error ' ] [ ' Code ' ] == ' NoSuchLifecycleConfiguration ' :
current_lifecycle_rules = [ ]
2015-07-16 01:16:24 +00:00
else :
2018-05-17 19:07:40 +00:00
module . fail_json_aws ( e )
except BotoCoreError as e :
module . fail_json_aws ( e )
2015-07-16 01:16:24 +00:00
2018-05-17 19:07:40 +00:00
rule = dict ( Filter = dict ( Prefix = prefix ) , Status = status . title ( ) )
if rule_id is not None :
rule [ ' ID ' ] = rule_id
2015-07-16 01:16:24 +00:00
# Create expiration
if expiration_days is not None :
2018-05-17 19:07:40 +00:00
rule [ ' Expiration ' ] = dict ( Days = expiration_days )
2015-07-16 01:16:24 +00:00
elif expiration_date is not None :
2018-05-17 19:07:40 +00:00
rule [ ' Expiration ' ] = dict ( Date = expiration_date )
2015-12-01 03:01:57 +00:00
2018-05-17 19:07:40 +00:00
if noncurrent_version_expiration_days is not None :
rule [ ' NoncurrentVersionExpiration ' ] = dict ( NoncurrentDays = noncurrent_version_expiration_days )
2015-07-16 01:16:24 +00:00
2018-05-17 19:07:40 +00:00
if transition_days is not None :
rule [ ' Transitions ' ] = [ dict ( Days = transition_days , StorageClass = storage_class . upper ( ) ) , ]
2015-07-16 01:16:24 +00:00
2018-05-17 19:07:40 +00:00
elif transition_date is not None :
rule [ ' Transitions ' ] = [ dict ( Date = transition_date , StorageClass = storage_class . upper ( ) ) , ]
if transitions is not None :
if not rule . get ( ' Transitions ' ) :
rule [ ' Transitions ' ] = [ ]
for transition in transitions :
t_out = dict ( )
if transition . get ( ' transition_date ' ) :
t_out [ ' Date ' ] = transition [ ' transition_date ' ]
elif transition . get ( ' transition_days ' ) :
t_out [ ' Days ' ] = transition [ ' transition_days ' ]
if transition . get ( ' storage_class ' ) :
t_out [ ' StorageClass ' ] = transition [ ' storage_class ' ] . upper ( )
rule [ ' Transitions ' ] . append ( t_out )
if noncurrent_version_transition_days is not None :
rule [ ' NoncurrentVersionTransitions ' ] = [ dict ( NoncurrentDays = noncurrent_version_transition_days ,
StorageClass = noncurrent_version_storage_class . upper ( ) ) , ]
if noncurrent_version_transitions is not None :
if not rule . get ( ' NoncurrentVersionTransitions ' ) :
rule [ ' NoncurrentVersionTransitions ' ] = [ ]
for noncurrent_version_transition in noncurrent_version_transitions :
t_out = dict ( )
t_out [ ' NoncurrentDays ' ] = noncurrent_version_transition [ ' transition_days ' ]
if noncurrent_version_transition . get ( ' storage_class ' ) :
t_out [ ' StorageClass ' ] = noncurrent_version_transition [ ' storage_class ' ] . upper ( )
rule [ ' NoncurrentVersionTransitions ' ] . append ( t_out )
lifecycle_configuration = dict ( Rules = [ ] )
2015-07-16 01:16:24 +00:00
appended = False
# If current_lifecycle_obj is not None then we have rules to compare, otherwise just add the rule
2018-05-17 19:07:40 +00:00
if current_lifecycle_rules :
2015-07-16 01:16:24 +00:00
# If rule ID exists, use that for comparison otherwise compare based on prefix
2018-05-17 19:07:40 +00:00
for existing_rule in current_lifecycle_rules :
2018-09-06 19:44:26 +00:00
if rule . get ( ' ID ' ) == existing_rule . get ( ' ID ' ) and rule [ ' Filter ' ] [ ' Prefix ' ] != existing_rule . get ( ' Filter ' , { } ) . get ( ' Prefix ' , ' ' ) :
existing_rule . pop ( ' ID ' )
elif rule_id is None and rule [ ' Filter ' ] [ ' Prefix ' ] == existing_rule . get ( ' Filter ' , { } ) . get ( ' Prefix ' , ' ' ) :
2018-05-17 19:07:40 +00:00
existing_rule . pop ( ' ID ' )
if rule . get ( ' ID ' ) == existing_rule . get ( ' ID ' ) :
changed_ , appended_ = update_or_append_rule ( rule , existing_rule , purge_transitions , lifecycle_configuration )
changed = changed_ or changed
appended = appended_ or appended
2015-12-04 01:50:38 +00:00
else :
2018-05-17 19:07:40 +00:00
lifecycle_configuration [ ' Rules ' ] . append ( existing_rule )
2015-07-16 01:16:24 +00:00
# If nothing appended then append now as the rule must not exist
if not appended :
2018-05-17 19:07:40 +00:00
lifecycle_configuration [ ' Rules ' ] . append ( rule )
2015-07-16 01:16:24 +00:00
changed = True
else :
2018-05-17 19:07:40 +00:00
lifecycle_configuration [ ' Rules ' ] . append ( rule )
2015-07-16 01:16:24 +00:00
changed = True
# Write lifecycle to bucket
try :
2018-05-17 19:07:40 +00:00
client . put_bucket_lifecycle_configuration ( Bucket = name , LifecycleConfiguration = lifecycle_configuration )
except ( BotoCoreError , ClientError ) as e :
module . fail_json_aws ( e )
2015-12-01 03:01:57 +00:00
2015-07-16 01:16:24 +00:00
module . exit_json ( changed = changed )
2017-12-07 16:27:06 +00:00
2018-05-17 19:07:40 +00:00
def update_or_append_rule ( new_rule , existing_rule , purge_transitions , lifecycle_obj ) :
changed = False
if existing_rule [ ' Status ' ] != new_rule [ ' Status ' ] :
if not new_rule . get ( ' Transitions ' ) and existing_rule . get ( ' Transitions ' ) :
new_rule [ ' Transitions ' ] = existing_rule [ ' Transitions ' ]
if not new_rule . get ( ' Expiration ' ) and existing_rule . get ( ' Expiration ' ) :
new_rule [ ' Expiration ' ] = existing_rule [ ' Expiration ' ]
if not new_rule . get ( ' NoncurrentVersionExpiration ' ) and existing_rule . get ( ' NoncurrentVersionExpiration ' ) :
new_rule [ ' NoncurrentVersionExpiration ' ] = existing_rule [ ' NoncurrentVersionExpiration ' ]
lifecycle_obj [ ' Rules ' ] . append ( new_rule )
changed = True
appended = True
else :
if not purge_transitions :
merge_transitions ( new_rule , existing_rule )
if compare_rule ( new_rule , existing_rule , purge_transitions ) :
lifecycle_obj [ ' Rules ' ] . append ( new_rule )
appended = True
else :
lifecycle_obj [ ' Rules ' ] . append ( new_rule )
changed = True
appended = True
return changed , appended
2015-07-16 01:16:24 +00:00
2018-05-17 19:07:40 +00:00
def compare_rule ( rule_a , rule_b , purge_transitions ) :
2015-07-16 01:16:24 +00:00
2018-05-17 19:07:40 +00:00
# Copy objects
rule1 = deepcopy ( rule_a )
rule2 = deepcopy ( rule_b )
if purge_transitions :
return rule1 == rule2
2015-07-16 01:16:24 +00:00
else :
2018-05-17 19:07:40 +00:00
transitions1 = rule1 . pop ( ' Transitions ' , [ ] )
transitions2 = rule2 . pop ( ' Transitions ' , [ ] )
noncurrent_transtions1 = rule1 . pop ( ' NoncurrentVersionTransitions ' , [ ] )
noncurrent_transtions2 = rule2 . pop ( ' NoncurrentVersionTransitions ' , [ ] )
if rule1 != rule2 :
return False
for transition in transitions1 :
if transition not in transitions2 :
return False
for transition in noncurrent_transtions1 :
if transition not in noncurrent_transtions2 :
return False
return True
2015-07-16 01:16:24 +00:00
2018-05-17 19:07:40 +00:00
def merge_transitions ( updated_rule , updating_rule ) :
# because of the legal s3 transitions, we know only one can exist for each storage class.
# So, our strategy is build some dicts, keyed on storage class and add the storage class transitions that are only
# in updating_rule to updated_rule
updated_transitions = { }
updating_transitions = { }
2018-09-06 19:44:26 +00:00
for transition in updated_rule . get ( ' Transitions ' , [ ] ) :
2018-05-17 19:07:40 +00:00
updated_transitions [ transition [ ' StorageClass ' ] ] = transition
2018-09-06 19:44:26 +00:00
for transition in updating_rule . get ( ' Transitions ' , [ ] ) :
2018-05-17 19:07:40 +00:00
updating_transitions [ transition [ ' StorageClass ' ] ] = transition
for storage_class , transition in updating_transitions . items ( ) :
if updated_transitions . get ( storage_class ) is None :
updated_rule [ ' Transitions ' ] . append ( transition )
2015-07-16 01:16:24 +00:00
2018-05-17 19:07:40 +00:00
def destroy_lifecycle_rule ( client , module ) :
2015-07-16 01:16:24 +00:00
name = module . params . get ( " name " )
prefix = module . params . get ( " prefix " )
rule_id = module . params . get ( " rule_id " )
changed = False
if prefix is None :
prefix = " "
# Get the bucket's current lifecycle rules
try :
2018-05-17 19:07:40 +00:00
current_lifecycle_rules = client . get_bucket_lifecycle_configuration ( Bucket = name ) [ ' Rules ' ]
except ClientError as e :
if e . response [ ' Error ' ] [ ' Code ' ] == ' NoSuchLifecycleConfiguration ' :
current_lifecycle_rules = [ ]
2015-07-16 01:16:24 +00:00
else :
2018-05-17 19:07:40 +00:00
module . fail_json_aws ( e )
except BotoCoreError as e :
module . fail_json_aws ( e )
2015-07-16 01:16:24 +00:00
# Create lifecycle
2018-05-17 19:07:40 +00:00
lifecycle_obj = dict ( Rules = [ ] )
2015-12-01 03:01:57 +00:00
2015-07-16 01:16:24 +00:00
# Check if rule exists
# If an ID exists, use that otherwise compare based on prefix
if rule_id is not None :
2018-05-17 19:07:40 +00:00
for existing_rule in current_lifecycle_rules :
if rule_id == existing_rule [ ' ID ' ] :
2015-07-16 01:16:24 +00:00
# We're not keeping the rule (i.e. deleting) so mark as changed
changed = True
else :
2018-05-17 19:07:40 +00:00
lifecycle_obj [ ' Rules ' ] . append ( existing_rule )
2015-07-16 01:16:24 +00:00
else :
2018-05-17 19:07:40 +00:00
for existing_rule in current_lifecycle_rules :
if prefix == existing_rule [ ' Filter ' ] [ ' Prefix ' ] :
2015-07-16 01:16:24 +00:00
# We're not keeping the rule (i.e. deleting) so mark as changed
changed = True
else :
2018-05-17 19:07:40 +00:00
lifecycle_obj [ ' Rules ' ] . append ( existing_rule )
2015-12-01 03:01:57 +00:00
2015-07-16 01:16:24 +00:00
# Write lifecycle to bucket or, if there no rules left, delete lifecycle configuration
try :
2018-05-17 19:07:40 +00:00
if lifecycle_obj [ ' Rules ' ] :
client . put_bucket_lifecycle_configuration ( Bucket = name , LifecycleConfiguration = lifecycle_obj )
2018-07-18 17:13:33 +00:00
elif current_lifecycle_rules :
changed = True
client . delete_bucket_lifecycle ( Bucket = name )
2018-05-17 19:07:40 +00:00
except ( ClientError , BotoCoreError ) as e :
module . fail_json_aws ( e )
2015-07-16 01:16:24 +00:00
module . exit_json ( changed = changed )
2015-12-01 03:01:57 +00:00
2015-07-16 01:16:24 +00:00
def main ( ) :
2018-05-17 19:07:40 +00:00
argument_spec = dict (
name = dict ( required = True , type = ' str ' ) ,
expiration_days = dict ( type = ' int ' ) ,
expiration_date = dict ( ) ,
noncurrent_version_expiration_days = dict ( type = ' int ' ) ,
noncurrent_version_storage_class = dict ( default = ' glacier ' , type = ' str ' , choices = [ ' glacier ' , ' onezone_ia ' , ' standard_ia ' ] ) ,
noncurrent_version_transition_days = dict ( type = ' int ' ) ,
noncurrent_version_transitions = dict ( type = ' list ' ) ,
prefix = dict ( ) ,
requester_pays = dict ( default = ' no ' , type = ' bool ' ) ,
rule_id = dict ( ) ,
state = dict ( default = ' present ' , choices = [ ' present ' , ' absent ' ] ) ,
status = dict ( default = ' enabled ' , choices = [ ' enabled ' , ' disabled ' ] ) ,
storage_class = dict ( default = ' glacier ' , type = ' str ' , choices = [ ' glacier ' , ' onezone_ia ' , ' standard_ia ' ] ) ,
transition_days = dict ( type = ' int ' ) ,
transition_date = dict ( ) ,
transitions = dict ( type = ' list ' ) ,
purge_transitions = dict ( default = ' yes ' , type = ' bool ' )
2015-07-16 01:16:24 +00:00
)
2018-05-17 19:07:40 +00:00
module = AnsibleAWSModule ( argument_spec = argument_spec ,
mutually_exclusive = [
[ ' expiration_days ' , ' expiration_date ' ] ,
[ ' expiration_days ' , ' transition_date ' ] ,
[ ' transition_days ' , ' transition_date ' ] ,
[ ' transition_days ' , ' expiration_date ' ] ,
[ ' transition_days ' , ' transitions ' ] ,
[ ' transition_date ' , ' transitions ' ] ,
[ ' noncurrent_version_transition_days ' , ' noncurrent_version_transitions ' ] ,
] , )
2015-12-01 03:01:57 +00:00
2015-07-16 01:16:24 +00:00
if not HAS_DATEUTIL :
2015-12-01 03:01:57 +00:00
module . fail_json ( msg = ' dateutil required for this module ' )
2015-07-16 01:16:24 +00:00
2018-05-17 19:07:40 +00:00
client = module . client ( ' s3 ' )
2015-07-16 01:16:24 +00:00
expiration_date = module . params . get ( " expiration_date " )
transition_date = module . params . get ( " transition_date " )
state = module . params . get ( " state " )
2018-05-17 19:07:40 +00:00
if state == ' present ' and module . params [ " status " ] == " enabled " : # allow deleting/disabling a rule by id/prefix
required_when_present = ( ' expiration_date ' , ' expiration_days ' , ' transition_date ' ,
' transition_days ' , ' transitions ' , ' noncurrent_version_expiration_days ' ,
' noncurrent_version_transition_days ' ,
' noncurrent_version_transitions ' )
for param in required_when_present :
if module . params . get ( param ) :
break
else :
msg = " one of the following is required when ' state ' is ' present ' : %s " % ' , ' . join ( required_when_present )
module . fail_json ( msg = msg )
2015-07-16 01:16:24 +00:00
# If expiration_date set, check string is valid
if expiration_date is not None :
try :
datetime . datetime . strptime ( expiration_date , " % Y- % m- %d T % H: % M: % S.000Z " )
2016-10-23 20:41:03 +00:00
except ValueError as e :
2015-07-16 01:16:24 +00:00
module . fail_json ( msg = " expiration_date is not a valid ISO-8601 format. The time must be midnight and a timezone of GMT must be included " )
2015-12-01 03:01:57 +00:00
2015-07-16 01:16:24 +00:00
if transition_date is not None :
try :
datetime . datetime . strptime ( transition_date , " % Y- % m- %d T % H: % M: % S.000Z " )
2016-10-23 20:41:03 +00:00
except ValueError as e :
2015-07-16 01:16:24 +00:00
module . fail_json ( msg = " expiration_date is not a valid ISO-8601 format. The time must be midnight and a timezone of GMT must be included " )
2015-12-01 03:01:57 +00:00
2015-07-16 01:16:24 +00:00
if state == ' present ' :
2018-05-17 19:07:40 +00:00
create_lifecycle_rule ( client , module )
2015-07-16 01:16:24 +00:00
elif state == ' absent ' :
2018-05-17 19:07:40 +00:00
destroy_lifecycle_rule ( client , module )
2015-07-16 01:16:24 +00:00
if __name__ == ' __main__ ' :
main ( )