我想在多台服务器上的多个 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
答案1
“当您在循环中使用寄存器时,放置在变量中的数据结构将包含一个结果属性,该属性是来自模块的所有响应的列表。”
因此对于这个:
register: sql_procedures
loop: "{{ sql_instances.stdout_lines }}"
将会sql_procedures
是一个字典数组,其中包含每个元素的结果sql_procedures.results[*].stdout_lines
更复杂的循环可能会有所帮助。看看这个例子迭代嵌套列表这实际上就是您想要实现的(每个服务器都有程序)