最近在使用Ansible的s3_lifecycle module配置S3上文件的lifecycle时遇到了下面的exception
Filter element can only be used in Lifecycle V2.
这个信息不是很明确,所以Google了一下,发现了有人遇到相同的问题https://github.com/ansible/ansible/issues/53751。看了下大概原因是新的put-bucket-lifecycle-configuration API改变了参数Prefix的格式,从
{
"Rules": [
{
"Expiration": {
"Days": 365
},
"ID": "lifecycle-rule-name",
"Prefix": "/",
"Status": "Enabled",
}
]
}
变成了
{
"Rules": [
{
"Expiration": {
"Days": 365
},
"ID": "lifecycle-rule-name",
"Filter": {
"Prefix": "/"
},
"Status": "Enabled",
}
]
}
再去看s3_lifecycle module的create_lifecycle_rule方法,添加的新rule的Prefix格式是带Filter的,而对已经存在的rule的Prefix格式并没有进行必要的转换。这就导致传给put-bucket-lifecycle-configuration的rule list里既有带Filter的Prefix,又有不带Filter的Prefix,这时就会出现上面的问题。而如果传给put-bucket-lifecycle-configuration的rule list的Prefix格式一致,无论是都带Filter或是都不带Filter,都不会出现上述问题。
解决这个问题的办法可以是删除已经存在的rule,也可以对已经存在的rule的Prefix进行格式转换。为了保留原有的rule,我选择了改变s3_lifecycle module的逻辑,在添加新rule时,对已经存在的rule进行必要的格式转换。
if existing_rule.get('Prefix'):
existing_rule['Filter'] = dict(Prefix=existing_rule.pop('Prefix'))
这样就可以使得传给put-bucket-lifecycle-configuration的rule list的Prefix格式一致。当然,还有一些别的小改动,这里就不详述了。
另外有意思的一点是https://github.com/ansible/ansible/issues/53751中提到了下面这个解决方案
Comment out prefix: option in your playbook, run it (should succeed), put it back again and rerun.
为什么这样可以解决问题呢?这是由于不传入Prefix之后,下面的语句得以执行
elif rule_id is None and rule['Filter']['Prefix'] == existing_rule.get('Filter', {}).get('Prefix', ''):
existing_rule.pop('ID')
最终,existing_rule都不再保留,相当于“删除”了已经存在的所有rule。
References: