Creando tu primer módulo de Ansible

En este blog, te mostraré cómo crear tu primer módulo de Ansible.













Por supuesto, hay documentación disponible en Ansible.com, pero es difícil averiguarlo. Comenzar mi primer módulo sobre la base de esta introducción me resultó con gran dificultad. Por eso creé este tutorial. Los nuevos usuarios merecen un mejor punto de partida.







Este blog cubre los siguientes temas:







  • ¿Qué es el módulo Ansible?
  • Configurando nuestro entorno de construcción
  • API del servidor
  • Desarrollo del propio módulo


¿Qué es el módulo Ansible?



Si está familiarizado con Ansible, probablemente sepa que cada tarea que realiza en Ansible es un módulo de Ansible. Si no, ahora lo sabes.







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









¡Felicidades! Ahora tiene un módulo Ansible funcional. ¿Ha intentado agregar una función de cambio de usuario? También considere agregar el manejo de errores a este módulo como si lo estuviera haciendo en un módulo real para solucionar los errores y devolverlos correctamente a Ansible.







No es tan difícil, ¿verdad? Esto no es verdad. El código Python simple es esencial.

Si desea ver el resultado final completo, eche un vistazo al blog de resultados de la rama.














All Articles