{"id":1010,"date":"2020-07-04T19:21:56","date_gmt":"2020-07-04T17:21:56","guid":{"rendered":"http:\/\/www.netexpertise.eu\/en\/?p=1010"},"modified":"2021-05-13T20:19:53","modified_gmt":"2021-05-13T18:19:53","slug":"register-a-jenkins-slave-with-ansible","status":"publish","type":"post","link":"http:\/\/www.netexpertise.eu\/en\/devops\/ansible\/register-a-jenkins-slave-with-ansible.html","title":{"rendered":"Register a Jenkins Slave with Ansible"},"content":{"rendered":"\n<p>We saw <a href=\"http:\/\/en\/devops\/jenkins\/jenkins-slave-auto-register-with-rest-api.html\">how to register a Jenkins slave<\/a> with a REST API. Let&#8217;s go one step further: make <a href=\"\/en\/category\/devops\/ansible\">Ansible<\/a> do that for you.<\/p>\n\n\n\n<p>You will first need a Jenkins user and associated token with the proper rights. Agent connect and create permissions should be sufficient. I&#8217;ll simply call that user &#8220;node&#8221;. Log on Jenkins with the &#8220;node&#8221; account and add a new token.<br><br><\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><a href=\"http:\/\/www.netexpertise.eu\/en\/wp-content\/uploads\/cafe-morning-coffee-drink-drinking-604600.jpg\"><img decoding=\"async\" src=\"\/uploads\/cafe-morning-coffee-drink-drinking-604600.jpg\" alt=\"Cafe Morning Coffee Drink Drinking  - 453169 \/ Pixabay\"\/><\/a><figcaption><a href=\"https:\/\/pixabay.com\/users\/453169\">453169<\/a> \/ Pixabay<\/figcaption><\/figure><\/div>\n\n\n\n<p><br>The new node details need to be passed on to the REST url. We&#8217;ll squeeze these settings into a Jinja2 template as follow:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"json\" class=\"language-json\">{\n   \"name\": \"{{ jenkins_node }}\",\n   \"nodeDescription\": \"slave {{ jenkins_node }}\",\n   \"numExecutors\": \"{{ jenkins_numExecutors }}\",\n   \"remoteFS\": \"{{ jenkins_remoteFS }}\",\n   \"labelString\": \"{{ jenkins_label }}\",\n   \"mode\": \"EXCLUSIVE\",\n   \"\": [\n      \"hudson.slaves.JNLPLauncher\",\n      \"hudson.slaves.RetentionStrategy$Always\"\n   ],\n   \"launcher\": {\n      \"stapler-class\": \"hudson.slaves.JNLPLauncher\",\n      \"$class\": \"hudson.slaves.JNLPLauncher\",\n      \"workDirSettings\": {\n         \"disabled\": true,\n         \"workDirPath\": \"\",\n         \"internalDir\": \"remoting\",\n         \"failIfWorkDirIsMissing\": false\n      },\n      \"tunnel\": \"\",\n      \"vmargs\": \"\"\n   },\n   \"retentionStrategy\": {\n      \"stapler-class\": \"hudson.slaves.RetentionStrategy$Always\",\n      \"$class\": \"hudson.slaves.RetentionStrategy$Always\"\n   },\n   \"nodeProperties\": {\n      \"stapler-class-bag\": \"true\",\n      \"hudson-slaves-EnvironmentVariablesNodeProperty\": {\n         \"env\": [\n            {\n               \"key\": \"JAVA_HOME\",\n               \"value\": \"{{ java_home }}\"\n            }\n         ]\n      },\n      \"_comment:\": {\n         \"hudson-tools-ToolLocationNodeProperty\": {\n           \"locations\": [\n               {\n                  \"key\": \"hudson.model.JDK$DescriptorImpl@JAVA-8\",\n                  \"home\": \"\/usr\/bin\/java\"\n               }\n            ]\n         }\n      }\n   }\n}<\/code><\/pre>\n\n\n\n<p><br>Adapt the template to your needs, if you&#8217;d like a SSH agent for instance.<br><br>The variables that will be replaced in the template can be defined in the following &#8220;default&#8221; file:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"yaml\" class=\"language-yaml\">jenkins_slave_user: jenkins-slave\njenkins_token: xxxxxxde2152xxxxxxaa339exxxxxx48d6\njenkins_user: node\njenkins_url: https:\/\/jenkins.domain.lan\njenkins_node: \"{{ansible_hostname}}\"\njenkins_numExecutors: 4\njenkins_remoteFS: \/home\/jenkins-slave\njenkins_label: \"label_1 label_2 label_3\"\njava_home: \/usr\/lib\/jvm\/java-8-openjdk-amd64\/<\/code><\/pre>\n\n\n\n<p><br>jenkins_user will connect to the master and create the new node, authenticating with jenkins_token created beforehand.<br>jenkins_slave_user is the system user that will launch Jenkins service on the node.<br><br>We can now add Ansible tasks to build our role. We first call the REST API:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"yaml\" class=\"language-yaml\"> name: create node on Jenkins master\n uri:\n url: \"{{jenkins_url}}\/computer\/doCreateItem?name={{ jenkins_node }}&amp;type=hudson.slaves.DumbSlave\"\n method: POST\n body_format: form-urlencoded\n force_basic_auth: yes\n user: \"{{ jenkins_user }}\"\n password: \"{{jenkins_token }}\"\n body: \"json={{ lookup('template', 'node.json.j2', convert_data=False) }}\"\n return_content: yes\n status_code: 200, 302, 400\n register: webpage<\/code><\/pre>\n\n\n\n<p><br>I added return code 400 in case the node already exists but you may remove it if you think it&#8217;s best. Then I make it fail if the error is anything else than &#8216;already exists&#8217;:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"yaml\" class=\"language-yaml\"> name: Go through if agent already exists error\n fail:\n when: &gt;\n       webpage.status == '400'\n       and 'already exists' not in webpage.x_error <\/code><\/pre>\n\n\n\n<p><br>The Jenkins agent service needs a secret from the master to get started. The secret is embedded in the agent&#8217;s page in XML format so you can easily retrieve it.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"yaml\" class=\"language-yaml\"> name: get node page content\n uri:\n url: \"{{jenkins_url}}\/computer\/{{jenkins_node}}\/slave-agent.jnlp\"\n method: POST\n body_format: form-urlencoded\n force_basic_auth: yes\n user: \"{{ jenkins_user }}\"\n password: \"{{ jenkins_token }}\"\n return_content: yes\n status_code: 200\n register: slavepage\n name: get secret from xml\n xml:\n xmlstring: \"{{slavepage.content}}\"\n xpath: \/jnlp\/application-desc\/argument\n content: text\n register: secretxml <\/code><\/pre>\n\n\n\n<p>It will be stored in the system user&#8217;s default file \/etc\/default\/jenkins-slave that is loaded by the startup script.<br><br>Here&#8217;s the template:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">JENKINS_USER=\"jenkins-slave\"\nJENKINS_WORKDIR=$(eval echo \"~$JENKINS_USER\")\nJENKINS_URL={{ jenkins_url }}\nJENKINS_NODENAME=$(hostname)\nJENKINS_SECRET={{ jenkins_secret }}\nJAVA_ARGS=\"-Xmx6g\"<\/code><\/pre>\n\n\n\n<p><br>Here comes the init script. We can now upload these two files:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"yaml\" class=\"language-yaml\"> name: Copy jenkins-slave default file template\n template:\n src: jenkins-slave-default.j2\n dest: \/etc\/default\/jenkins-slave\n owner: jenkins-slave\n group: jenkins-slave\n mode: 0600\n vars:\n jenkins_secret: \"{{secretxml.matches[0].argument}}\"\n register: jenkins_config\n name: Copy jenkins-slave init file\n copy:\n src: jenkins-slave-init\n dest: \/etc\/init.d\/jenkins-slave\n owner: root\n group: root\n mode: 0755<\/code><\/pre>\n\n\n\n<p><br>Final step, we make sure the service is started:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"yaml\" class=\"language-yaml\"> name: restart and enable jenkins-slave service if needed\n service:\n name: jenkins-slave\n enabled: yes\n state: restarted\n when: jenkins_config.changed\n name: start and enable jenkins-slave service\n service:\n name: jenkins-slave\n enabled: yes\n state: started <\/code><\/pre>\n\n\n\n<p><br>These steps were the basics but you can do a lot more like adding the Jenkins system user creation, adding your own CA certificate if you&#8217;re on a private IP, and so on<br><br>Also check how to <a href=\"\/en\/devops\/ansible\/make-ansible-6x-faster-with-these-3-tips.html\">speed up Ansible<\/a> and save a lot of time when deploying.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>We saw how to register a Jenkins slave with a REST API. Let&#8217;s go one step further: make Ansible do that for you. You will first need a Jenkins user and associated token with the proper rights. Agent connect and create permissions should be sufficient. I&#8217;ll simply call that user &#8220;node&#8221;. Log on Jenkins with [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0},"categories":[427,426],"tags":[429,428],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v21.8.1 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Netexpertise - Register a Jenkins Slave with Ansible<\/title>\n<meta name=\"description\" content=\"Steps to register a Jenkins Slave with Ansible playbooks and Jenkins REST API\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.netexpertise.eu\/en\/devops\/ansible\/register-a-jenkins-slave-with-ansible.html\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Netexpertise - Register a Jenkins Slave with Ansible\" \/>\n<meta property=\"og:description\" content=\"Steps to register a Jenkins Slave with Ansible playbooks and Jenkins REST API\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.netexpertise.eu\/en\/devops\/ansible\/register-a-jenkins-slave-with-ansible.html\" \/>\n<meta property=\"og:site_name\" content=\"Netexpertise\" \/>\n<meta property=\"article:published_time\" content=\"2020-07-04T17:21:56+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2021-05-13T18:19:53+00:00\" \/>\n<meta name=\"author\" content=\"dave\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@netexpertise\" \/>\n<meta name=\"twitter:site\" content=\"@netexpertise\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.netexpertise.eu\/en\/devops\/ansible\/register-a-jenkins-slave-with-ansible.html\",\"url\":\"https:\/\/www.netexpertise.eu\/en\/devops\/ansible\/register-a-jenkins-slave-with-ansible.html\",\"name\":\"Netexpertise - Register a Jenkins Slave with Ansible\",\"isPartOf\":{\"@id\":\"https:\/\/www.netexpertise.eu\/en\/#website\"},\"datePublished\":\"2020-07-04T17:21:56+00:00\",\"dateModified\":\"2021-05-13T18:19:53+00:00\",\"author\":{\"@id\":\"https:\/\/www.netexpertise.eu\/en\/#\/schema\/person\/cb4cd666549d22e9070ec1cfc1a496fa\"},\"description\":\"Steps to register a Jenkins Slave with Ansible playbooks and Jenkins REST API\",\"breadcrumb\":{\"@id\":\"https:\/\/www.netexpertise.eu\/en\/devops\/ansible\/register-a-jenkins-slave-with-ansible.html#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.netexpertise.eu\/en\/devops\/ansible\/register-a-jenkins-slave-with-ansible.html\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.netexpertise.eu\/en\/devops\/ansible\/register-a-jenkins-slave-with-ansible.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.netexpertise.eu\/en\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Register a Jenkins Slave with Ansible\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.netexpertise.eu\/en\/#website\",\"url\":\"https:\/\/www.netexpertise.eu\/en\/\",\"name\":\"Netexpertise\",\"description\":\"Systems \/ Networks \/ DevOps\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.netexpertise.eu\/en\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.netexpertise.eu\/en\/#\/schema\/person\/cb4cd666549d22e9070ec1cfc1a496fa\",\"name\":\"dave\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.netexpertise.eu\/en\/#\/schema\/person\/image\/\",\"url\":\"http:\/\/1.gravatar.com\/avatar\/1129916e1f4955bd632f27f836f64e55?s=96&d=mm&r=g\",\"contentUrl\":\"http:\/\/1.gravatar.com\/avatar\/1129916e1f4955bd632f27f836f64e55?s=96&d=mm&r=g\",\"caption\":\"dave\"},\"sameAs\":[\"http:\/\/www.netexpertise.eu\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Netexpertise - Register a Jenkins Slave with Ansible","description":"Steps to register a Jenkins Slave with Ansible playbooks and Jenkins REST API","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.netexpertise.eu\/en\/devops\/ansible\/register-a-jenkins-slave-with-ansible.html","og_locale":"en_US","og_type":"article","og_title":"Netexpertise - Register a Jenkins Slave with Ansible","og_description":"Steps to register a Jenkins Slave with Ansible playbooks and Jenkins REST API","og_url":"https:\/\/www.netexpertise.eu\/en\/devops\/ansible\/register-a-jenkins-slave-with-ansible.html","og_site_name":"Netexpertise","article_published_time":"2020-07-04T17:21:56+00:00","article_modified_time":"2021-05-13T18:19:53+00:00","author":"dave","twitter_card":"summary_large_image","twitter_creator":"@netexpertise","twitter_site":"@netexpertise","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.netexpertise.eu\/en\/devops\/ansible\/register-a-jenkins-slave-with-ansible.html","url":"https:\/\/www.netexpertise.eu\/en\/devops\/ansible\/register-a-jenkins-slave-with-ansible.html","name":"Netexpertise - Register a Jenkins Slave with Ansible","isPartOf":{"@id":"https:\/\/www.netexpertise.eu\/en\/#website"},"datePublished":"2020-07-04T17:21:56+00:00","dateModified":"2021-05-13T18:19:53+00:00","author":{"@id":"https:\/\/www.netexpertise.eu\/en\/#\/schema\/person\/cb4cd666549d22e9070ec1cfc1a496fa"},"description":"Steps to register a Jenkins Slave with Ansible playbooks and Jenkins REST API","breadcrumb":{"@id":"https:\/\/www.netexpertise.eu\/en\/devops\/ansible\/register-a-jenkins-slave-with-ansible.html#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.netexpertise.eu\/en\/devops\/ansible\/register-a-jenkins-slave-with-ansible.html"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.netexpertise.eu\/en\/devops\/ansible\/register-a-jenkins-slave-with-ansible.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.netexpertise.eu\/en"},{"@type":"ListItem","position":2,"name":"Register a Jenkins Slave with Ansible"}]},{"@type":"WebSite","@id":"https:\/\/www.netexpertise.eu\/en\/#website","url":"https:\/\/www.netexpertise.eu\/en\/","name":"Netexpertise","description":"Systems \/ Networks \/ DevOps","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.netexpertise.eu\/en\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/www.netexpertise.eu\/en\/#\/schema\/person\/cb4cd666549d22e9070ec1cfc1a496fa","name":"dave","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.netexpertise.eu\/en\/#\/schema\/person\/image\/","url":"http:\/\/1.gravatar.com\/avatar\/1129916e1f4955bd632f27f836f64e55?s=96&d=mm&r=g","contentUrl":"http:\/\/1.gravatar.com\/avatar\/1129916e1f4955bd632f27f836f64e55?s=96&d=mm&r=g","caption":"dave"},"sameAs":["http:\/\/www.netexpertise.eu"]}]}},"_links":{"self":[{"href":"http:\/\/www.netexpertise.eu\/en\/wp-json\/wp\/v2\/posts\/1010"}],"collection":[{"href":"http:\/\/www.netexpertise.eu\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.netexpertise.eu\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.netexpertise.eu\/en\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/www.netexpertise.eu\/en\/wp-json\/wp\/v2\/comments?post=1010"}],"version-history":[{"count":0,"href":"http:\/\/www.netexpertise.eu\/en\/wp-json\/wp\/v2\/posts\/1010\/revisions"}],"wp:attachment":[{"href":"http:\/\/www.netexpertise.eu\/en\/wp-json\/wp\/v2\/media?parent=1010"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.netexpertise.eu\/en\/wp-json\/wp\/v2\/categories?post=1010"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.netexpertise.eu\/en\/wp-json\/wp\/v2\/tags?post=1010"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}