{"id":5505,"date":"2026-11-05T12:47:00","date_gmt":"2026-11-05T12:47:00","guid":{"rendered":"https:\/\/geekmungus.co.uk\/?p=5505"},"modified":"2026-11-05T12:47:00","modified_gmt":"2026-11-05T12:47:00","slug":"ansible-using-stat-and-assert","status":"publish","type":"post","link":"https:\/\/geekmungus.co.uk\/?p=5505","title":{"rendered":"Ansible &#8211; Using &#8220;stat&#8221; and &#8220;assert&#8221;"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">When building playbooks and tasks, you may find you want to check the status of a host before you attempt to perform a particular action upon it. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You wouldn&#8217;t want it to attempt to perform an action which would fail because something is missing, you&#8217;d want it to check first. Although you can use conditionals to handle the situation and perhaps continue, this is beyond the scope of this article. Instead we&#8217;re just looking at using two Ansible methods &#8220;stat&#8221; and &#8220;assert&#8221;. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">So, <strong>stat<\/strong> is used to gather information about a file directory on the managed host. It doesn&#8217;t change anything on the host and you can use it to check if a path exists, whether it is a file or directory, or check gather its permissions, owner, size, checksum etc.  <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You can then use <strong>assert <\/strong>to check if that the condition (gathered by stat) is true or false, and then if false fail with an optional message saying why. Assert is useful to validate that a host is in the state that your playbook has been coded to, before it conducts any actions.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Example<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The below example checks if the <strong>\/etc\/ssh\/sshd_config<\/strong> file exists and if it is a regular file.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>- name: Check SSH configuration file\n  ansible.builtin.stat:\n    path: \/etc\/ssh\/sshd_config\n  register: ssh_config\n\n- name: Confirm SSH configuration file is present\n  ansible.builtin.assert:\n    that:\n      - ssh_config.stat.exists\n      - ssh_config.stat.isreg\n    success_msg: \"SSH configuration file exists\"\n    fail_msg: \"SSH configuration file is missing or is not a regular file\"<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"513\" src=\"https:\/\/geekmungus.co.uk\/wp-content\/uploads\/2026\/11\/image-1024x513.png\" alt=\"\" class=\"wp-image-5506\" srcset=\"https:\/\/geekmungus.co.uk\/wp-content\/uploads\/2026\/11\/image-1024x513.png 1024w, https:\/\/geekmungus.co.uk\/wp-content\/uploads\/2026\/11\/image-300x150.png 300w, https:\/\/geekmungus.co.uk\/wp-content\/uploads\/2026\/11\/image-767x384.png 767w, https:\/\/geekmungus.co.uk\/wp-content\/uploads\/2026\/11\/image.png 1074w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">So from what we can see, <strong>stat <\/strong>has collected that file <strong>\/etc\/ssh\/sshd_config<\/strong> does indeed exist and this is held within the <strong>ssh_config <\/strong>register (variable) as <strong>ssh_config.stat.exists<\/strong> (in this case with the value &#8220;true&#8221;) and then that it is a regular file (i.e. not a directory, or symlink or the like), and that is again in <strong>ssh_config<\/strong> as <strong>ssh_config.stat.isreg<\/strong>. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Now the <strong>assert <\/strong>comes into play. It checks if these two conditions <strong>ssh_config.stat.exists<\/strong> and <strong>ssh_config.stat.isreg<\/strong> are true or false; and prints a message either way.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If we were then to change the ansible to instead look for a non-existent file called: <strong>\/etc\/ssh\/sshd_config<\/strong>, we&#8217;d get the following:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"608\" src=\"https:\/\/geekmungus.co.uk\/wp-content\/uploads\/2026\/11\/image-1-1024x608.png\" alt=\"\" class=\"wp-image-5508\" srcset=\"https:\/\/geekmungus.co.uk\/wp-content\/uploads\/2026\/11\/image-1-1024x608.png 1024w, https:\/\/geekmungus.co.uk\/wp-content\/uploads\/2026\/11\/image-1-768x456.png 768w, https:\/\/geekmungus.co.uk\/wp-content\/uploads\/2026\/11\/image-1-300x178.png 300w, https:\/\/geekmungus.co.uk\/wp-content\/uploads\/2026\/11\/image-1.png 1093w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">In which case we can assert that the host is not in the state we expect and therefore the playbook (for that host or any other host) should fail because it doesn&#8217;t match the state we would expect!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>When building playbooks and tasks, you may find you want to check the status of a host before you attempt to perform a particular action upon it. You wouldn&#8217;t want it to attempt to perform an action which would fail because something is missing, you&#8217;d want it to check first. Although you can use conditionals &#8230; <a title=\"Ansible &#8211; Using &#8220;stat&#8221; and &#8220;assert&#8221;\" class=\"read-more\" href=\"https:\/\/geekmungus.co.uk\/?p=5505\" aria-label=\"Read more about Ansible &#8211; Using &#8220;stat&#8221; and &#8220;assert&#8221;\">Read more<\/a><\/p>\n","protected":false},"author":4,"featured_media":4522,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[49],"tags":[],"class_list":["post-5505","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-ansible"],"_links":{"self":[{"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=\/wp\/v2\/posts\/5505","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=5505"}],"version-history":[{"count":2,"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=\/wp\/v2\/posts\/5505\/revisions"}],"predecessor-version":[{"id":5509,"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=\/wp\/v2\/posts\/5505\/revisions\/5509"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=\/wp\/v2\/media\/4522"}],"wp:attachment":[{"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=5505"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=5505"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=5505"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}