我想跨多个服务器上的多个 MSSQL 实例部署一些存储过程。在我的剧本中,我有一个任务收集服务器上的所有实例,我在以下任务中使用它来循环任何实例上的所有内容。我在我的许多剧本中都使用了这种方法,但在这个剧本中,我还需要能够when
在循环任务时在条件中使用先前收集的变量。
这些是我的剧本的相关部分:
#################### GATHER INSTANCES ####################
- name: list instances
win_shell: (Find-DbaInstance -ComputerName localhost | Where Availability -eq 'Available').instancename
changed_when: False
register: sql_instances
#################### GATHER PROCEDURES ####################
- name: list procedures
win_shell: (Get-DbaDbStoredProcedure -SqlInstance localhost\{{ item }} -Database master -Schema dbo).Name
changed_when: False
register: sql_procedures
loop: "{{ sql_instances.stdout_lines }}"
#################### INSTALL CUSTOM PROCEDURES ####################
- name: my_procedure
ansible.windows.win_powershell:
script: |
$batch_install_prodecure = @'
--My Stored Procedure
'@
Invoke-DbaQuery -SqlInstance localhost\{{ item }} -Query $batch_install_prodecure
when: sql_procedures.stdout_lines.find('my_procedure') != 0
register: my_procedure
loop: "{{ sql_instances.stdout_lines }}"
这是输出:
#################### GATHER INSTANCES ####################
"stdout_lines": [
"MSSQLSERVER2",
"MSSQLSERVER"
]
#################### GATHER PROCEDURES ####################
"stdout_lines": [
"sp_Something",
"sp_Somethingelse"
],
"stderr_lines": [],
"_ansible_no_log": false,
"item": "MSSQLSERVER2",
"ansible_loop_var": "item",
"_ansible_item_label": "MSSQLSERVER2"
}
############################
"stdout_lines": [
"sp_Something",
"sp_Somethingelse"
],
"stderr_lines": [],
"_ansible_no_log": false,
"item": "MSSQLSERVER",
"ansible_loop_var": "item",
"_ansible_item_label": "MSSQLSERVER"
}
#################### INSTALL CUSTOM PROCEDURES ####################
The conditional check 'sql_procedures.stdout_lines.find('custProc_Backupcheck') != 0' failed. The error was: error while evaluating conditional (sql_procedures.stdout_lines.find('custProc_Backupcheck') != 0): 'dict object' has no attribute 'stdout_lines'
我有点明白为什么它不起作用。我必须以某种方式描述找到变量的项,因为它是在循环中生成的。我只是不知道该怎么做。
到目前为止,我所做的最远的是尝试实现与本文中所做的类似的事情,但我想这种方法不适用于我的情况
我知道我可以直接在 PowerShell 中轻松完成所有这些工作,但最终我的目标是安装多个程序(每个任务一个),并且还能够轻松删除旧程序,以便在我的 MSSQL 实例上保持相同的程序清单。
有人可以告诉我如何设置when
条件来实现我的目标吗?
编辑:
请参阅接受的答案,了解为什么它不起作用。
我现在更改为在 PowerShell 中检查是否已安装该程序:
#################### INSTALL CUSTOM PROCEDURES ####################
- name: my_procedure
ansible.windows.win_powershell:
script: |
$name_procedure = 'my_procedure'
$install_prodecure = @'
--My Stored Procedure
'@
if ((Get-DbaDbStoredProcedure -SqlInstance localhost\{{ item }} -Database master -Schema dbo).Name -contains $name_procedure) {
write-host "OK: SP $name_procedure is already installed"
} else {
write-host "SET: SP $name_procedure needs to be installed"
Invoke-DbaQuery -SqlInstance localhost\{{ item }} -Query $install_prodecure
if ((Get-DbaDbStoredProcedure -SqlInstance localhost\{{ item }} -Database master -Schema dbo).Name -contains $name_procedure) {
write-host "OK: SP $name_procedure sucessfully installed"
} else {
write-host "ERROR: Was not able to install $name_procedure"
}
}
register: my_procedure
loop: "{{ sql_instances.stdout_lines }}"
failed_when: my_procedure.host_out.find('ERROR:') != -1
changed_when: my_procedure.host_out.find('SET:') != -1
“当您使用带有循环的寄存器时,放置在变量中的数据结构将包含一个结果属性,该属性是来自模块的所有响应的列表。”
https://docs.ansible.com/ansible/latest/user_guide/playbooks_loops.html#registering-variables-with-a-loop
所以为此:
这
sql_procedures
将是一个字典数组,其中包含每个元素中的结果sql_procedures.results[*].stdout_lines
一个更复杂的循环可能会有所帮助。看一下迭代嵌套列表的示例,这实际上是您想要实现的(程序是每个服务器)