【问题标题】:Ansible regex_replace does not recognize the variableAnsible regex_replace 无法识别变量
【发布时间】:2019-06-24 19:40:36
【问题描述】:

我正在尝试使用 regex_replace 替换字符串,但我遇到了参数问题。

vars:
    **mongoURI**: "mongodb://shard1:27017,shard2:27017,shard3:27017/?ssl=true&authSource=admin&replicaSet=TestCluster-shard-0"

- name: Create Mongo connection string    
      set_fact:        
        **readinput**: "mongodb://{{ (userinfo_json.Users | first).username }}:{{ (userinfo_json.Users | first).password }}@" 
        readconnstring: "{{ mongoURI | regex_replace('mongodb://', '{{ readinput }}') | regex_replace('\\?ssl', 'test?ssl') + ('&retryWrites=true') }}"

以上工作正常,如果我用 URI 初始化 mongoURI 变量,我会得到所需的输出。这是输出。

mongodb://testuser:password@shard1:27017,shard1:27017,shard1:27017/?ssl=true&authSource=admin&replicaSet=TestCluster-shard-0

但是我需要从 JSON 输入中读取 mongoURI 值。当我这样做时,第一个 regex_replace 无法识别变量(readinput)。

- name: Fetch Mongo URI
      set_fact:
        mongoURI: "{{ (cluster_status_check.content | from_json).mongoURIWithOptions }}"
      when: cluster_status_check.status == 200

在这种情况下,最后两个 regex_replaces 工作正常,但第一个正被替换为变量名,如下所示。

*{{ readinput }}*shard1:27017,shard1:27017,shard1:27017/?ssl=true&authSource=admin&replicaSet=TestCluster-shard-0

我尝试使用 urlsplit('hostname') 但 'mongodb://' 未被识别为主机名。

我还尝试删除 readinput 变量周围的单引号 readconnstring: "{{ mongoURI | regex_replace('mongodb://', {{ readinput }})) 并删除变量的 {{ }} readconnstring: "{{ mongoURI | regex_replace('mongodb://', readinput))

但两者都给出语法错误。

由于 from_json 将输出转换为字典,我尝试使用 with_items 但没有成功。

- name: Create Mongo connection string    
      set_fact:        
        readinput: "mongodb://{{ (userinfo_json.Users | first).username }}:{{ (userinfo_json.Users | first).password }}@" 
        readconnstring: "{{ item | regex_replace('mongodb://', '{{ readinput }}') | regex_replace('\\?ssl', 'test?ssl') + ('&retryWrites=true') }}"
  with_items:
        - "{{ mongoURI }}"
---
- hosts: localhost
  gather_facts: no
  vars:
    mongoURI: ""

- name: Check whether cluster already exists
      uri:
        url: https://cloud.mongodb.com/api/atlas/v1.0/groups/{{ groupid }}/clusters/{{ clustername }}
        return_content: yes
        method: GET
        user: "{{ user }}"
        password: "{{ apikey }}"
        status_code: 404, 200
      register: cluster_status_check
- name: Fetch Mongo URI
      set_fact:
        mongoURI: "{{ (cluster_status_check.content | from_json).mongoURIWithOptions }}"
      when: cluster_status_check.status == 200

- name: Create Mongo connection string    
      set_fact:        
        readinput: "mongodb://{{ (userinfo_json.Users | first).username }}:{{ (userinfo_json.Users | first).password }}@" 
        readconnstring: "{{ mongoURI | regex_replace('mongodb://', '{{ readinput }}') | regex_replace('\\?ssl', 'test?ssl') + ('&retryWrites=true') }}"

不是将 mongodb:// 替换为 readinput 值,而是将其替换为 {{ readinput }}

期望的输出:

mongodb://testuser:password@shard1:27017,shard1:27017,shard1:27017/?ssl=true&authSource=admin&replicaSet=TestCluster-shard-0

实际输出:

{{ readinput }}shard1:27017,shard1:27017,shard1:27017/?ssl=true&authSource=admin&replicaSet=TestCluster-shard-0

【问题讨论】:

  • 在没有{{}} 的情况下使用 readinput 时会出现什么语法错误?见this答案
  • 致命:[本地主机]:失败! => { "msg": "({{ mongoURI | regex_replace('mongodb://', readinput) }}) 发生意外的模板类型错误:'NoneType' 类型的对象没有 len()" }
  • 在执行 regex_replace 之前,您可以尝试打印 mongoURI 的值吗?
  • 是的,我打印的是一样的。 - name: Fetch Mongo URI set_fact: mongoURI: "{{ (cluster_status_check.content | from_json).mongoURIWithOptions }}" when: cluster_status_check.status == 200 - debug: msg: "Fetched URI:{{ mongoURI }}" 这是价值。出于隐私原因稍作改动。 mongodb://testcluster-shard-00-00-azure.mongodb.net:27017,testcluster-shard-00-01-azure.mongodb.net:27017,testcluster-shard-00-02-azure.mongodb.net:27017/?ssl=true&authSource=admin&replicaSet=TestCluster-shard-0
  • 我也在 regex_replace 之前打印了,mongoURI 变量的内容与上面给出的相同。

标签: regex mongodb ansible


【解决方案1】:

我发现了问题并修复了。问题在于设置一个变量并立即在任务中使用它。

- name: initialize variables
      set_fact:                
        readinput: "mongodb://{{ (userinfo_json.Users | first).username }}:{{ (userinfo_json.Users | first).password }}@"

- name: Create Mongo connection string    
      set_fact:        
        readconnstring: "{{ mongoURI | regex_replace('mongodb://', readinput) | regex_replace('\\?ssl', 'test?ssl') + ('&retryWrites=true') }}"

根据文档,使用 set_fact 设置的变量可用于后续播放。当我将 readinput 初始化移到另一个任务时,代码就起作用了。我也不必将变量包装在 {{ }} 中。

我浪费了很多时间。不知道为什么 set_fact 有这样的限制。

【讨论】:

  • 令人惊讶的是这个问题在ansible DSL中也完全没有逻辑......谢谢!
【解决方案2】:

你不需要'{{ readinput }}'readinput就足够了。

类似的东西应该可以工作:

- name: Create Mongo connection string    
  set_fact:        
    readinput: "mongodb://{{ (userinfo_json.Users | first).username }}:{{ (userinfo_json.Users | first).password }}@" 
    readconnstring: "{{ mongoURI | regex_replace('mongodb://', readinput) | regex_replace('\\?ssl', 'test?ssl') }}&retryWrites=true"

【讨论】:

  • 我已经试过了。这是我得到的错误。 fatal: [localhost]: FAILED! => { "msg": "Unexpected templating type error occurred on ({{ mongoURI | regex_replace('mongodb://', readinput) }}): object of type 'NoneType' has no len()" }
  • 可能是mongoURI的问题,先解决一下
  • 这里是从 JSON 文件中读取的 mongoURI 的值。出于隐私原因,我必须对其进行一些更改。 mongodb://testcluster-shard-00-00-azure.mongodb.net:27017,testcluster-shard-00-01-azure.mongodb.net:27017,testcluster-shard-00-02-azure.mongodb.net:27017/?ssl=true&authSource=admin&replicaSet=TestCluster-shard-0
猜你喜欢
  • 1970-01-01
  • 2021-02-27
  • 2013-05-15
  • 2014-06-10
  • 2017-01-04
  • 2013-08-13
  • 2018-11-12
  • 2013-02-18
  • 1970-01-01
相关资源
最近更新 更多