Oct 18 2020

Enregistrer un Slave Jenkins avec Ansible

Publié par à 1:25 sous Ansible,Jenkins

Nous avons vu précédemment comment ajouter un esclave Jenkins en appelant une API REST avec Curl. Automatisons ceci avec Ansible pour avoir un nouveau noeud disponible en quelques minutes!

Vous aurez tout d’abord besoin d’un utilisateur Jenkins et son token associé avec les bons droits. « Agent connect » et « create » devraient suffire. J’appellerai cet utilisateur « node » tout simplement. Connectez-vous sur Jenkins avec cet utilisateur et créez un nouveau token.

Slave Jenkins avec Ansible


Les détails du nouveau noeud doivent être passés à l’URL REST. Intégrons ces paramètres dans un template Jinja2 comme ceci:
 

{
   "name": "{{ jenkins_node }}",
   "nodeDescription": "slave {{ jenkins_node }}",
   "numExecutors": "{{ jenkins_numExecutors }}",
   "remoteFS": "{{ jenkins_remoteFS }}",
   "labelString": "{{ jenkins_label }}",
   "mode": "EXCLUSIVE",
   "": [
      "hudson.slaves.JNLPLauncher",
      "hudson.slaves.RetentionStrategy$Always"
   ],
   "launcher": {
      "stapler-class": "hudson.slaves.JNLPLauncher",
      "$class": "hudson.slaves.JNLPLauncher",
      "workDirSettings": {
         "disabled": true,
         "workDirPath": "",
         "internalDir": "remoting",
         "failIfWorkDirIsMissing": false
      },
      "tunnel": "",
      "vmargs": ""
   },
   "retentionStrategy": {
      "stapler-class": "hudson.slaves.RetentionStrategy$Always",
      "$class": "hudson.slaves.RetentionStrategy$Always"
   },
   "nodeProperties": {
      "stapler-class-bag": "true",
      "hudson-slaves-EnvironmentVariablesNodeProperty": {
         "env": [
            {
               "key": "JAVA_HOME",
               "value": "{{ java_home }}"
            }
         ]
      },
      "_comment:": {
         "hudson-tools-ToolLocationNodeProperty": {
           "locations": [
               {
                  "key": "hudson.model.JDK$DescriptorImpl@JAVA-8",
                  "home": "/usr/bin/java"
               }
            ]
         }
      }
   }
}

 
Adaptez le modèle selon vos besoins, si vous souhaitez un agent SSH par exemple.

Les variables qui vont être remplacées dans le template peuvent être définies dans le fichier « default » suivant:

jenkins_slave_user: jenkins-slave
jenkins_token: xxxxxxde2152xxxxxxaa339exxxxxx48d6
jenkins_user: node
jenkins_url: https://jenkins.domain.lan
jenkins_node: "{{ansible_hostname}}"
jenkins_numExecutors: 4
jenkins_remoteFS: /home/jenkins-slave
jenkins_label: "label_1 label_2 label_3"
java_home: /usr/lib/jvm/java-8-openjdk-amd64/

 
jenkins_user se connectera au master et créera le nouveau noeud, en s’authentifiant avec le jenkins_token créé précédemment.
jenkins_slave_user est l’utilisateur système qui lancera le service Jenkins sur le node.

Nous pouvons maintenant ajouter une tâche Ansible à notre rôle. Nous appelons tout d’abord l’API REST:

- name: création du noeud sur le maître Jenkins
  uri:
    url: "{{jenkins_url}}/computer/doCreateItem?name={{ jenkins_node }}&type=hudson.slaves.DumbSlave"
    method: POST
    body_format: form-urlencoded
    force_basic_auth: yes
    user: "{{ jenkins_user }}"
    password: "{{jenkins_token }}"
    body: "json={{ lookup('template', 'node.json.j2', convert_data=False) }}"
    return_content: yes
    status_code: 200, 302, 400
  register: webpage

 
J’ai ajouté le code de retour 400 au cas où le noeud existe déjà mais vous pouvez l’enlever si vous préférez que ca s’arrête dans ce cas. Je le passe en échec si l’erreur n’est pas ‘already exists’:

- name: continue au cas où l'agent existe déjà
  fail:
  when: >
          webpage.status == '400'
          and 'already exists' not in webpage.x_error

 
Le service agent Jenkins a besoin d’une clé du master pour démarrer. La clé est disponible dans la page de l’agent au format XML.

- name: récupération du contenu de la page de l'agent
  uri:
    url: "{{jenkins_url}}/computer/{{jenkins_node}}/slave-agent.jnlp"
    method: POST
    body_format: form-urlencoded
    force_basic_auth: yes
    user: "{{ jenkins_user }}"
    password: "{{ jenkins_token }}"
    return_content: yes
    status_code: 200
  register: slavepage

- name: récupération de la clé contenu dans le xml
  xml:
    xmlstring: "{{slavepage.content}}"
    xpath: /jnlp/application-desc/argument
    content: text
  register: secretxml

 
La clé sera stockée dans le fichier /etc/default/jenkins-slave de l’utilisateur système qui est chargé au démarrage du service.
En voici le template:

JENKINS_USER="jenkins-slave"
JENKINS_WORKDIR=$(eval echo "~$JENKINS_USER")
JENKINS_URL={{ jenkins_url }}
JENKINS_NODENAME=$(hostname)
JENKINS_SECRET={{ jenkins_secret }}
JAVA_ARGS="-Xmx6g"

 
Ajoutez l’init script. Nous pouvons maintenant copier ces 2 fichiers:

- name: copie du fichier de paramètres de jenkins-slave
  template:
    src: jenkins-slave-default.j2
    dest: /etc/default/jenkins-slave
    owner: jenkins-slave
    group: jenkins-slave
    mode: 0600
  vars:
    jenkins_secret: "{{secretxml.matches[0].argument}}"
  register: jenkins_config

- name: Copie de l'init script jenkins-slave
  copy:
    src: jenkins-slave-init
    dest: /etc/init.d/jenkins-slave
    owner: root
    group: root
    mode: 0755

 
Et nous nous assurons que le service est bien démarré:

- name: redémarrage et activation du service jenkins-slave si besoin
  service:
    name: jenkins-slave
    enabled: yes
    state: restarted
  when: jenkins_config.changed

- name: démarrage et activation du service jenkins-slave
  service:
    name: jenkins-slave
    enabled: yes
    state: started

 
Ces étapes sont la base mais vous pouvez faire bien plus comme ajouter la création de l’utilisateur système Jenkins, ajouter votre propre autorité de certification si vous êtes sur une IP privée, et bien plus.

Voyez aussi comment accélérer Ansible et optimiser vos temps de déploiement.


No responses yet

Comments RSS

Leave a Reply