Création de votre premier module Ansible

Dans ce blog, je vais vous montrer comment créer votre premier module Ansible.













Bien sûr, il existe une documentation disponible sur Ansible.com, mais il est difficile de la comprendre. Commencer mon premier module sur la base de cette introduction m'a été donné avec beaucoup de difficulté. C'est pourquoi j'ai créé cette procédure pas à pas. Les nouveaux utilisateurs méritent un meilleur point de départ.







Ce blog couvre les sujets suivants:







  • Qu'est-ce que le module Ansible
  • Configuration de notre environnement de construction
  • API serveur
  • Développement du module lui-même


Qu'est-ce que le module Ansible



Si vous connaissez Ansible, vous savez probablement que chaque tâche que vous effectuez dans Ansible est un module Ansible. Sinon, maintenant vous le savez.







, 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 , .









Toutes nos félicitations! Vous disposez désormais d'un module Ansible fonctionnel. Avez-vous essayé d'ajouter une fonctionnalité de changement d'utilisateur? Pensez également à ajouter la gestion des erreurs à ce module comme si vous le faisiez dans un vrai module pour prendre en charge les erreurs et les renvoyer correctement à Ansible.







Pas si difficile, non? Ce n'est pas vrai. Un code Python simple est essentiel.

Si vous voulez voir le résultat final complet, jetez un œil au blog des résultats de la branche.














All Articles