我在名为 tomcat 的角色中有以下任务:
- name: copy tomcat file settings
copy:
src: "{{ item.src }}"
dest: "{{ item.dest }}"
owner: tomcat
group: tomcat
mode: "{{ item.mode }}"
with_items:
- { src: logrotate-tomcat7, dest: /etc/logrotate.d/tomcat7, mode: 0644 }
- { src: keystore.pks, dest: /var/lib/tomcat7/webapps, mode: 0644 }
- { src: jmxremote.access, dest: /etc/tomcat7, mode: 0644 }
- { src: jmxremote.password, dest: /etc/tomcat7, mode: 0600 }
当我运行调用 tomcat 角色的剧本时,我看到以下输出:
TASK [devops-server : copy tomcat file settings] *********************************
changed: [10.71.10.11] => (item={u'dest': u'/etc/logrotate.d/tomcat7', u'src': u'logrotate-tomcat7', u'mode': 420})
changed: [10.71.10.11] => (item={u'dest': u'/var/lib/tomcat7/webapps', u'src': u'keystore.pks', u'mode': 420})
changed: [10.71.10.11] => (item={u'dest': u'/etc/tomcat7', u'src': u'jmxremote.access', u'mode': 420})
failed: [10.71.10.11] (item={u'dest': u'/etc/tomcat7', u'src': u'jmxremote.password', u'mode': 384}) => {"checksum": "2203ad1530a3bc06732043ba67d129b5364505ce", "details": "bad symbolic permission for mode: 384", "failed": true, "gid": 91, "group": "tomcat", "item": {"dest": "/etc/tomcat7", "mode": 384, "src": "jmxremote.password"}, "mode": "0644", "msg": "mode must be in octal or symbolic form", "owner": "tomcat", "path": "/etc/tomcat7/jmxremote.password", "size": 52, "state": "file", "uid": 91}
...ignoring
显然,模式 0600 在我的 EC2 实例的命令行上运行:
ec2-user@devops-01 ~]$ sudo chmod 0600 /etc/tomcat7/jmxremote.password
ec2-user@devops-01 ~]$ ls -l /etc/tomcat7/jmxremote.password
-rw------- 1 tomcat tomcat 52 Oct 28 16:18 /etc/tomcat7/jmxremote.password
那么发生了什么?这是 Ansible 错误还是我遗漏了什么?
答案1
这显然是 Ansible 的一个错误。对我来说,代码似乎没问题。根据这个GitHub 问题octal
可以通过将for设置mode
为来解决此错误string
。如下所示:0644
"0644"
因此我会尝试这个:
with_items:
- { src: logrotate-tomcat7, dest: /etc/logrotate.d/tomcat7, mode: "0644" }
答案2
Ansible 更改。在 ansible ansible-2.5.0-2.el6 和 2.9.27-1.el7ae 中,此插件代码足以从任务中正确读取模式:
module_args = dict(
dest=dict(type='str', required=True),
src=dict(type='str', required=True),
owner=dict(type='str', required=False, default='root'),
group=dict(type='str', required=False, default='root'),
mode=dict(type='str', required=False, default='0600'),
setype=dict(type='str', required=False),
seuser=dict(type='str', required=False),
selevel=dict(type='str', required=False)
)
# the AnsibleModule object will be our abstraction working with Ansible
# this includes instantiation, a couple of common attr would be the
# args/params passed to the execution, as well as if the module
# supports check mode
module = AnsibleModule(
argument_spec=module_args,
supports_check_mode=True
)
. . .
file_args = module.load_file_common_arguments(module.params)
result['changed'] |= module.set_fs_attributes_if_different(file_args, result['changed'], expand=False)
使用 ansible-2.9.25-1.el7 时,我必须从 java_keystore.py 模块中抄袭此代码:
class ArgumentSpec(object):
def __init__(self):
self.supports_check_mode = True
self.add_file_common_args = True
# define available arguments/parameters a user can pass to the module
argument_spec = dict(
dest=dict(type='str', required=True),
src=dict(type='str', required=True),
)
self.argument_spec = argument_spec
spec = ArgumentSpec()
# the AnsibleModule object will be our abstraction working with Ansible
# this includes instantiation, a couple of common attr would be the
# args/params passed to the execution, as well as if the module
# supports check mode
module = AnsibleModule(
argument_spec=spec.argument_spec,
add_file_common_args=spec.add_file_common_args,
supports_check_mode=spec.supports_check_mode
)
. . .
file_args = module.load_file_common_arguments(module.params)
result['changed'] |= module.set_fs_attributes_if_different(file_args, result['changed'], expand=False)