#python #ansible #ansible-inventory
Вопрос:
Задачи Ansible повторное использование сеанса HTTP из запросов Python
Сценарий:
- Сложный процесс входа в веб-службу с несколькими перенаправлениями и очистками форм (через BeautifulSoup)
- Файл скрипта Python, использующий модуль запросов с сеансом, для хранения маркеров и файлов cookie успеха для входа в систему для последующих вызовов API веб-службы
Цель:
- Задача Ansible 1. Выполните скрипт Python для аутентификации веб-службы, верните сеанс HTTPS в Ansible
- Задача Ansible 2..n: Выполнение API веб-служб с использованием встроенного
uri
модуля Ansible, используя сеанс HTTPS из
Мысли:
- Честно говоря, я немного не понимаю, как эффективно структурировать это в Ansible. Возможно, было бы разумно рассмотреть весь скрипт Python для аутентификации в качестве модуля Ansible?
ПРИМЕР СКРИПТА АУТЕНТИФИКАЦИИ НА PYTHON (упрощенный)
def main():
import requests
# Create Session for requests, store all cookies in this object
https_session = requests.Session()
if 'page_1' not in globals():
page_1 = https_session.get(
'https://login.test.com',
allow_redirects=True
)
...
...
...
if 'redirect_8' not in globals():
redirect_8 = https_session.post(
'https://login.test.com/authenticate',
allow_redirects=True,
data = {
"token": response_7['token']
}
)
# Return the Cookie Jar
return https_session.cookies
main()
ПРИМЕР ВЫЗОВА ANSIBLE:
- name: test1
script: login.py
args:
executable: python3
environment:
username: "{{ input_user }}"
password: "{{ input_pwd }}"
ignore_errors: yes
register: login_test
- debug:
msg: "{{ login_test }}.stdout"
ПРИМЕР ВОЗВРАТА К ANSIBLE:
"
{
"results": [
{
"changed": True,
"rc": 0,
"stdout": "<RequestsCookieJar[<Cookie TOKEN=wxyz-wxyz for .home.test.com/>, <Cookie USER_ID=123456789 for .home.test.com/>\n",
"stdout_lines": [
"<RequestsCookieJar[<Cookie TOKEN=wxyz-wxyz for .home.test.com/>, <Cookie USER_ID=123456789 for .home.test.com/>, "
],
"stderr": "",
"stderr_lines": [],
"failed": False,
"ansible_loop_var": "item",
}
],
"skipped": False,
"changed": True,
"msg": "All items completed",
}
.stdout"
Комментарии:
1. Может
return json.dumps(https_session.cookies.get_dict())
быть, это правильный путь? Все еще не понимаю, в каком направлении двигаться / какие варианты доступны для этого варианта использования
Ответ №1:
Это можно было бы красиво завернуть в lookup
плагин:
lookup_plugins/session_cookie.py
:
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = """
lookup: session_cookie
author: Author
options:
username:
type: string
required: True
password:
type: string
required: True
"""
from ansible.plugins.lookup import LookupBase
from ansible.utils.display import Display
import requests
display = Display()
class LookupModule(LookupBase):
def run(self, _terms, variables=None, **kwargs):
self.set_options(var_options=variables, direct=kwargs)
url_username=self.get_option('username')
url_password=self.get_option('password')
https_session = requests.Session()
# do your custom sutff here
https_session.get(
'https://google.com',
allow_redirects=True
)
# retrieve cookies from session an return them
cookies = https_session.cookies.get_dict()
return [cookies]
И тогда его можно будет использовать в сборнике игр, как это:
playbook.yml
- name: Get session cookie
hosts: localhost
connection: local
gather_facts: false
vars:
password: secret
user: admin
cookie: "{{ lookup('session_cookie', username=user, password=password) }}"
tasks:
- debug:
msg: "{{ cookie['1P_JAR'] }}"
Запуск его вернет значение файла cookie из сеанса:
ansible-playbook -i',' playbook.yaml
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'
PLAY [Get session cookie] *****************************************************************************************************
TASK [debug] ******************************************************************************************************************
ok: [localhost] => {
"msg": "2021-09-13-10"
}
Я заметил, что
requests
иногда не очень хорошо играл с разветвлением ansible, см. Проблему ansible, поэтому мне пришлось добавить это envexport OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES
.