Erstellen Sie Ihr erstes Ansible-Modul

In diesem Blog zeige ich Ihnen, wie Sie Ihr erstes Ansible-Modul erstellen.













Natürlich gibt es auf Ansible.com Dokumentation, aber es ist schwer herauszufinden. Das Starten meines ersten Moduls auf der Grundlage dieser Einführung war für mich sehr schwierig. Deshalb habe ich diese exemplarische Vorgehensweise erstellt. Neue Benutzer verdienen einen besseren Ausgangspunkt.







Dieser Blog behandelt die folgenden Themen:







  • Was ist das Ansible-Modul?
  • Einrichten unserer Build-Umgebung
  • Server-API
  • Entwicklung des Moduls selbst


Was ist das Ansible-Modul?



Wenn Sie mit Ansible vertraut sind, wissen Sie wahrscheinlich, dass jede Aufgabe, die Sie in Ansible ausführen, ein Ansible-Modul ist. Wenn nicht, wissen Sie es jetzt.







, Ansible:







- name:    python-requests
  yum:
    name: python-requests
    state: latest
      
      





Ansible yum



.







. .







- , . , , - Ansible Galaxy, Ansible.







Ansible, API . , , , , , , .







Ansible, .









VSCode Ansible. - , , , -.







, Ansible API, .







API . — . .







, VSCode.







git clone https://gitlab.com/techforce1/ansible-module.git -b blog-setup
      
      





, blog-setup!







3 (.devcontainer



, ansible



, api-server



). API. cmd



, api-server



docker build -t api-server



( ).







. docker run -it -d -p 5000: 5000 api-server



. API-. http://localhost:5000, -.







, , Ansible, — VSCode. .devcontainer. VSCode , devcontainer



.







devcontainer



VSCode devcontainer



.







, , devcontainer



. Ansible devcontainer



. , Ansible , VSCode.







VSCode , , Reopen in container



.













.







API



API API, . * http://localhost:5000/. - , . API, http://localhost:5000/API/users.







, « », , API . , http://localhost:5000/API/get-token. . admin



initial_password



.







, , API







API , - , , - .







API curl



. curl, :







$ curl -u admin:initial_password http:/172.17.0.1:5000/API/get-token
{
  "duration": 600, 
  "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjA1NzE0NjI5Ljk1NzU4ODd9.8yDkOzN0umO2hN_D84KLV4Q4OuWzQoNf8puXWku9F14"
}
      
      





URL . , VSCode. , , IP- , API. .







, API, curl



:







$ curl -H 'Accept: application/json' -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjA1NzE0NjI5Ljk1NzU4ODd9.8yDkOzN0umO2hN_D84KLV4Q4OuWzQoNf8puXWku9F14" http:/172.17.0.1:5000/API/users
{
  "Users": [
    {
      "admin": true, 
      "created": "Wed, 18 Nov 2020 14:41:31 GMT", 
      "email": "admin@api.local", 
      "id": 1, 
      "username": "admin"
    }
  ]
}
      
      





, API, GET



POST



:







{
  "Users": [
    {
      "username": "test",
      "email": "test@api.local", 
      "password": "password",
      "admin": true
    }
  ]
}
      
      





Ansible



. ansible/tasks/main.yml



. :







name: Add test user to API
our_api_module:
  name: test1
  state: present
  email: test1@test.local
  admin: False
      
      





our_api_module



, 4 . . , Ansible.







. , , playbook. , Ansible , .







. 44, , , Ansible . arguments_spec



, playbook. false. , Ansible.







def main():
    module = AnsibleModule(
        argument_spec=dict(
            state=dict(type='str', default='present',
                       choices=['absent', 'present']),
            name=dict(type='str', required=True),
            email=dict(type='str', required=True),
            admin=dict(type='bool', default=False),
            base_url=dict(requred=False, default=None),
            username=dict(requred=False, default=None),
            password=dict(requred=False, default=None, no_log=True),
        ),
        supports_check_mode=False,
    )
      
      





59 ApiModule



, , 23. init. API. , , getToken



37.







urls



Ansible 3 .







def getToken(self):
    url = "{baseUrl}/API/get-token".format(baseUrl=self.baseUrl)
    response = open_url(url, method="GET", url_username=self.username, url_password=self.password, validate_certs=self.verifySsl)
    return json.loads(response.read())['token']
      
      





. , . 69. , . 2 : , (state). , if



, :







if api.state == 'absent':
    if api.user_exist(api.name):
       # do something to delete user
elif api.state == 'present':
    if not api.user_exist(api.name):
       # do something to add user
      
      





. user_exist. ApiModule



:







def user_exist(self, name):
    url = "{baseUrl}/API/users".format(baseUrl=self.baseUrl)
    headers = {
        'Accept': "application/json",
        "Authorization": "Bearer {}" . format(self.token),
    }
    response = open_url(url, method="GET", headers=headers, validate_certs=self.verifySsl)
    results = json.loads(response.read())
    for user in results['Users']:
        if name == user['username']:
            return True
    return False
      
      





, , , . api endpoint /API/users , . True, False.







, , .







:







def user_add(self):
        url = "{baseUrl}/API/users".format(baseUrl=self.baseUrl)
        headers = {
            'Accept': "application/json",
            'Content-Type': "application/json",
            "Authorization": "Bearer {}" . format(self.token),
        }
        data = {
            'username': self.name,
            'email': self.email,
            'admin': self.admin,
            'password': self.password
        }
        json_data = json.dumps(data, ensure_ascii=False)
        try:
            open_url(url, method="POST", headers=headers, data=json_data, validate_certs=self.verifySsl)
            return True
        except:
            return False
      
      





. user_add . : HTTP



POST



DELETE



, , URL-.

, URL- :







url = "{baseUrl}/API/users/{username}".format(baseUrl=self.baseUrl, username=self.name)
      
      





if.







, playbook (tasks/main.yml



) :







- name: Add test2 user to API
  our_api_module:
    name: test2
    state: present
    email: test2@test.local
    admin: False
    password: "test2test2"

- name: Delete test1 user to API
  our_api_module:
    name: test1
    state: absent
    email: test1@test.local
    admin: False
    password: "test3test3"
      
      





playbook, , 2 , 1 , .









Herzliche Glückwünsche! Sie haben jetzt ein funktionierendes Ansible-Modul. Haben Sie versucht, eine Benutzeränderungsfunktion hinzuzufügen? Erwägen Sie außerdem, diesem Modul eine Fehlerbehandlung hinzuzufügen, als ob Sie dies in einem realen Modul tun würden, um Fehler zu beheben und sie korrekt an Ansible zurückzugeben.







Nicht so schwer, oder? Es ist nicht so. Einfacher Python-Code ist unerlässlich.

Wenn Sie das vollständige Endergebnis sehen möchten, schauen Sie sich den Blog mit den Zweigergebnissen an.














All Articles