Modify a line in a scope with Ansible

2019-03-06 05:31发布

问题:

I need to modify a line in a file. Only problem, the line appears multiple times, but in different scopes. Like in this example from wso2 configuration manual :

<KeyStore>
    <Location>${carbon.home}/resources/security/wso2carbon.jks</Location>
    <Type>JKS</Type>
    <Password>wso2carbon</Password>
    <KeyAlias>wso2carbon</KeyAlias>
    <KeyPassword>wso2carbon</KeyPassword>
</KeyStore>

<TrustStore>
    <!-- trust-store file location -->
    <Location>${carbon.home}/repository/resources/security/client-truststore.jks</Location>
    <!-- trust-store type (JKS/PKCS12 etc.) -->
    <Type>JKS</Type> 
    <!-- trust-store password -->
    <Password>wso2carbon</Password>
</TrustStore>

I would need for example to modify the <Password> entry with one value in the <Keystore> scope, and with a second different value in the <TrustStore> scope in order to have different passwords. Can the lineinfile module do that ? Or is there any other way ?

PS. Using a template is not the solution I am looking for, as I would like to use this to modify preexisting servers and not lose any local modification.

回答1:

You can't do this with lineinfile, because it handles every line of the file separately – so there's no context from other lines possible.
Regex in lineinfile is not multiline.

You can use replace – it uses multiline regex.
For example:

- replace:
    backup: yes
    dest: config.xml
    regexp: '(<{{ item.scope }}>[\S\s]*<Password>)(?!{{ item.password }}<).*(</Password>[\S\s]*</{{ item.scope }}>)'
    replace: '\1{{ item.password }}\2'
  with_items:
    - scope: KeyStore
      password: foo
    - scope: TrustStore
      password: bar

Keep in mind that this solution is not bulletproof – scope names and password shouldn't have any XML special characters or regular expression sequences. Also I can't say for sure how it handles nested XML blocks with the same scope name.
But for general cases it should be fine.
There's even a try to be idempotent – it will not match a block if the password is the same.



回答2:

Ansible lineinfile regex parameter can match multiple lines. There is no problem in that beside that the regex would be long and hard to understand and maintain.

As you are trying to manipulate XML ansible-xml module might be a good option to solve this problem.



标签: scope ansible