我的 ansible 剧本中有一个错误:
致命:[localhost]:失败! => {“msg”:“该任务包含一个带有未定义变量的选项。错误是:'dict object'没有属性'json'。'dict object'没有属性'json' 错误似乎位于 '/home/ansibleliza/ansible-router/new/liza/work4.yaml': 第 60 行,第 7 列,但可能 位于文件的其他位置,具体取决于确切的语法问题。 有问题的行似乎是: - 名称:Створити пристрій, якщо він не існує ^ 这里 “}
本质是创建一个 playbook,通过 API 在 netbox 中创建对象。
它是如何工作的:首先,它运行一个Python脚本,该脚本将解析3个配置文件,然后将输出以JSON格式保存在myresult.txt文件中。每次再次运行 playbook 时,都应更新结果文件。要创建的第一个对象是 Site,它将具有同名的 slug 和状态(活动)。接下来,创建一个 Device,它包括之前创建的站点,添加角色 id (id 2 ) 和 device_type (id_1),设备名称取自 myresult.txt,status (active) 。然后创建 VLAN,它们是使用 Vlan Id、名称、状态创建的,所有这些都取自 myresult.txt。接下来,将创建接口,其中包括之前创建的设备、名称、类型、描述、mac、id。如果描述中说该接口已关闭,则不会启用该接口,在描述中将没有描述。另外,有些接口连接到先前创建的 vlan,但有些接口有很多 vlan,有些有 1 个,有些接口根本没有 vlan,或者这些接口被 shutdown(netbox 中的 vlan 在 802.1Q 中标明)。柱子)。还有要点是,在剧本第一次启动期间,所有这些对象都是在网络盒中创建的,并且应该检查该对象是否已经存在(然后它将跳过)或该对象尚不存在并且它将被创建。每次更改配置文件时(例如,如果将新的 VLAN 添加到列表中),则在下次启动 netbox 后,应进行检查,然后在必要时创建新的 VLAN 或其他对象
这是我的剧本:
tasks:
- name: Run script.py to generate result.txt
command: python3 "{{ script_path }}"
register: script_output
ignore_errors: yes
- name: Read the content of result.txt
slurp:
src: "{{ result_file_path }}"
register: result_content
- name: Convert the read data from base64
set_fact:
result_data: "{{ result_content['content'] | b64decode | from_json }}"
- name: Check if the site exists
uri:
url: "{{ netbox_url }}/dcim/sites/?name={{ result_data['site'] }}"
method: GET
headers:
Authorization: "Token {{ netbox_token }}"
Accept: "application/json"
register: site_check_response
- name: Create the site if it doesn't exist
uri:
url: "{{ netbox_url }}/dcim/sites/"
method: POST
body_format: json
body:
name: "{{ result_data['site'] }}"
slug: "{{ result_data['site'] | lower }}"
status: "active"
headers:
Authorization: "Token {{ netbox_token }}"
Content-Type: "application/json"
status_code: 201
when: site_check_response.json.count == 0
register: site_creation_response
- name: Check if the device exists
uri:
url: "{{ netbox_url }}/dcim/devices/?name={{ result_data['name'] }}"
method: GET
headers:
Authorization: "Token {{ netbox_token }}"
Accept: "application/json"
register: device_check_response
- name: Create the device if it doesn't exist
uri:
url: "{{ netbox_url }}/dcim/devices/"
method: POST
body_format: json
body:
name: "{{ result_data['name'] }}"
role: 2 # Role ID
device_type: 1 # Device type ID
site: "{{ site_creation_response.json.id if site_creation_response is defined else site_check_response.json.results[0].id }}"
status: "active"
headers:
Authorization: "Token {{ netbox_token }}"
Content-Type: "application/json"
status_code: 201
when: device_check_response.json.count == 0
- name: Check if the VLAN exists
uri:
url: "{{ netbox_url }}/ipam/vlans/?site_id={{ (site_creation_response.json.id if (site_creation_response is defined and 'json' in site_creation_response and 'id' in site_creation_response.json) else site_check_response.json.results[0].id if (site_check_response is defined and 'json' in site_check_response and site_check_response.json.results|length > 0) else '') }}&vid={{ item.id }}"
method: GET
headers:
Authorization: "Token {{ netbox_token }}"
Accept: "application/json"
loop: "{{ result_data['vlans'] }}"
register: vlan_check_response
when: site_creation_response is defined or (site_check_response is defined and site_check_response.json.results|length > 0)
- name: Create VLANs if they don't exist
uri:
url: "{{ netbox_url }}/ipam/vlans/"
method: POST
body_format: json
body:
name: "{{ item.item.name }}"
vid: "{{ item.item.id }}"
site: "{{ site_creation_response.json.id if site_creation_response is defined else site_check_response.json.results[0].id }}"
status: "active"
headers:
Authorization: "Token {{ netbox_token }}"
Content-Type: "application/json"
status_code: 201
loop: "{{ vlan_check_response.results }}"
when: item.json.count == 0
loop_control:
loop_var: item
- name: Set Default for interfaces_list
set_fact:
interfaces_list: []
- name: Check if the device interfaces exist
uri:
url: "{{ netbox_url }}/dcim/interfaces/?device_id={{ device_creation_response.json.id if device_creation_response is defined else device_check_response.json.results[0].id }}&name={{ item.key }}"
method: GET
headers:
Authorization: "Token {{ netbox_token }}"
Accept: "application/json"
loop: "{{ result_data['interfaces'] | dict2items }}"
register: interface_check_response
when: device_creation_response is defined or (device_check_response is defined and device_check_response.json.results|length > 0)
- name: Create interfaces if they don't exist
uri:
url: "{{ netbox_url }}/dcim/interfaces/"
method: POST
body_format: json
headers:
Authorization: "Token {{ netbox_token }}"
Content-Type: "application/json"
status_code: [201, 400]
body: >
{{
{
"device": (device_creation_response.json.id if device_creation_response is defined else device_check_response.json.results[0].id),
"name": item.key,
"enabled": (false if item.value.description == "shutdown" else true),
"description": ("No description" if item.value.description == "shutdown" else item.value.description),
"type": item.value.type,
"mac_address": (item.value.mac | default('') | replace('.', ''))
} | to_json
}}
loop: "{{ result_data['interfaces'] | dict2items }}"
loop_control:
loop_var: item
第一次启动playbook时,会出现我指出的错误,但它可能出现在设备、vlan、接口阶段。有时,当我再次运行时,就没有错误了。我不知道这种行为的原因。
看起来您的剧本正在尝试使用未定义或未正确传递的变量,特别是应该具有“json”属性的变量。确保您的 python 脚本实际上以 JSON 格式输出到“myresult.txt”。另外,请仔细检查您的剧本是否正确读取“myresult.txt”。如果文件读取部分正常,则问题可能在于您访问数据的方式。确保您尝试访问的数据结构与结果文件中的 JSON 结构匹配。如果没有确切的剧本代码,这些是开始检查的最佳位置!