What's the advantage of mere Ansible on mere shell-scripting if one doesn't use communally-maintained...
I establish a LAMP with a few extras on a remote Debian machine with a similar shell (Bash) script:
#/bin/bash
apt update -y
apt upgrade ufw sshguard unattended-upgrades wget curl git zip unzip tree -y
ufw --force enable
ufw allow 22,25,80,443
apt upgrade lamp-server^ ssmtp
apt upgrade python-certbot-apache
apt upgrade php-{cli,curl,mbstring,mcrypt,gd} phpmyadmin
curl -sS https://getcomposer.org/installer -o composer-setup.php
php composer-setup.php --install-dir=/usr/local/bin --filename=composer
cat <<-EOF > /etc/php*/conf.d/local.ini
upload_max_filesize = 2000M
post_max_size = 2000M
EOF
a2enmod http2 deflate expires
Some sysadmins who saw a similar script told me sayings like "you better do it with Ansible because otherwise it will be a nightmare to maintain it".
Well, I can achieve basically the same with the following Ansible playbook I wrote (and have yet to test because I don't have a free machine right now but should work when deployed to all machines):
---
- hosts: all
become: yes
become_user: root
tasks:
- name: Update apt package-indexes cache
apt:
update_cache=yes
- name: Install external basics
apt: state=latest
with-items:
- ufw
- sshguard
- unattended-upgrades
- wget
- curl
- git
- zip
- unzip
- tree
- name: Setup firewall with ufw
ufw:
rule: allow
port: 22,25,80,443
- name: Establish a LAPMS (Linux, Apache, PHP, MySQL, SSMTP) server environment
apt: state=latest
with-items:
- apache2 # Web server
- python-certbot-apache
- php
- php-mysql # MySQL server
- php-cli
- php-curl
- php-mbstring
- php-mcrypt
- php-gd
- ssmtp # Email server
- phpmyadmin
- name: Install Composer
get_url:
url: https://getcomposer.org/installer
dest: /tmp/composer-setup.php
command: php /tmp/composer-setup.php --install-dir=/usr/local/bin --filename=composer
- name: Configure PHP variables
shell: |
cat <<-EOF > /etc/php*/conf.d/local.ini
upload_max_filesize = 2000M
post_max_size = 2000M
EOF
args:
executable: /bin/bash
- apache2_module:
state: present
name: http2
- apache2_module:
state: present
name: deflate
- apache2_module:
state: present
name: expires
My contemplation
I don't recognize a significant advantage of using mere Ansible over mere shell-scripting in the above trivial case as Ansible does only what we tell it to and doesn't do release_upgrades (as from Apache 2.4 to 3.4) and will basically give me the same apt upgrade -y
automation with scheduling (say with cron
) so I can't understand how it will be much of a helper (also the result is basically same but the number of lines is far greater (72 instead 20/21) unless one uses Ansible-Galaxy roles which are well organized programs containing a core of one or more Ansible playbooks.
My question
How does mere Ansible by itself (without using Ansible-Galaxy roles) more efficient than mere shell-scripting in general and Bash in particular in a trivial task such as the above?
shell-script software-installation upgrade scheduling ansible
closed as primarily opinion-based by muru, Mr Shunz, Rui F Ribeiro, sourcejedi, Jeff Schaller Dec 19 at 16:20
Many good questions generate some degree of opinion based on expert experience, but answers to this question will tend to be almost entirely based on opinions, rather than facts, references, or specific expertise. If this question can be reworded to fit the rules in the help center, please edit the question.
add a comment |
I establish a LAMP with a few extras on a remote Debian machine with a similar shell (Bash) script:
#/bin/bash
apt update -y
apt upgrade ufw sshguard unattended-upgrades wget curl git zip unzip tree -y
ufw --force enable
ufw allow 22,25,80,443
apt upgrade lamp-server^ ssmtp
apt upgrade python-certbot-apache
apt upgrade php-{cli,curl,mbstring,mcrypt,gd} phpmyadmin
curl -sS https://getcomposer.org/installer -o composer-setup.php
php composer-setup.php --install-dir=/usr/local/bin --filename=composer
cat <<-EOF > /etc/php*/conf.d/local.ini
upload_max_filesize = 2000M
post_max_size = 2000M
EOF
a2enmod http2 deflate expires
Some sysadmins who saw a similar script told me sayings like "you better do it with Ansible because otherwise it will be a nightmare to maintain it".
Well, I can achieve basically the same with the following Ansible playbook I wrote (and have yet to test because I don't have a free machine right now but should work when deployed to all machines):
---
- hosts: all
become: yes
become_user: root
tasks:
- name: Update apt package-indexes cache
apt:
update_cache=yes
- name: Install external basics
apt: state=latest
with-items:
- ufw
- sshguard
- unattended-upgrades
- wget
- curl
- git
- zip
- unzip
- tree
- name: Setup firewall with ufw
ufw:
rule: allow
port: 22,25,80,443
- name: Establish a LAPMS (Linux, Apache, PHP, MySQL, SSMTP) server environment
apt: state=latest
with-items:
- apache2 # Web server
- python-certbot-apache
- php
- php-mysql # MySQL server
- php-cli
- php-curl
- php-mbstring
- php-mcrypt
- php-gd
- ssmtp # Email server
- phpmyadmin
- name: Install Composer
get_url:
url: https://getcomposer.org/installer
dest: /tmp/composer-setup.php
command: php /tmp/composer-setup.php --install-dir=/usr/local/bin --filename=composer
- name: Configure PHP variables
shell: |
cat <<-EOF > /etc/php*/conf.d/local.ini
upload_max_filesize = 2000M
post_max_size = 2000M
EOF
args:
executable: /bin/bash
- apache2_module:
state: present
name: http2
- apache2_module:
state: present
name: deflate
- apache2_module:
state: present
name: expires
My contemplation
I don't recognize a significant advantage of using mere Ansible over mere shell-scripting in the above trivial case as Ansible does only what we tell it to and doesn't do release_upgrades (as from Apache 2.4 to 3.4) and will basically give me the same apt upgrade -y
automation with scheduling (say with cron
) so I can't understand how it will be much of a helper (also the result is basically same but the number of lines is far greater (72 instead 20/21) unless one uses Ansible-Galaxy roles which are well organized programs containing a core of one or more Ansible playbooks.
My question
How does mere Ansible by itself (without using Ansible-Galaxy roles) more efficient than mere shell-scripting in general and Bash in particular in a trivial task such as the above?
shell-script software-installation upgrade scheduling ansible
closed as primarily opinion-based by muru, Mr Shunz, Rui F Ribeiro, sourcejedi, Jeff Schaller Dec 19 at 16:20
Many good questions generate some degree of opinion based on expert experience, but answers to this question will tend to be almost entirely based on opinions, rather than facts, references, or specific expertise. If this question can be reworded to fit the rules in the help center, please edit the question.
It is utterly disappointing to me that such an important-understanding question was closed. Please migrate to wherever you see fit: DevOps SE, SuperUser SE, ServerFault, StackOverflow, or whatever. This is the most important Ansible question I ever asked in my life in my opinion. Pleople, please help me to re-open it or flag it with me to migration.
– JohnDoea
Dec 20 at 7:29
Another reason is that your bash script continues on errors, while Ansible stops on errors and reports them. It also reports which steps changed or didn't change a system.
– r3m0t
2 days ago
add a comment |
I establish a LAMP with a few extras on a remote Debian machine with a similar shell (Bash) script:
#/bin/bash
apt update -y
apt upgrade ufw sshguard unattended-upgrades wget curl git zip unzip tree -y
ufw --force enable
ufw allow 22,25,80,443
apt upgrade lamp-server^ ssmtp
apt upgrade python-certbot-apache
apt upgrade php-{cli,curl,mbstring,mcrypt,gd} phpmyadmin
curl -sS https://getcomposer.org/installer -o composer-setup.php
php composer-setup.php --install-dir=/usr/local/bin --filename=composer
cat <<-EOF > /etc/php*/conf.d/local.ini
upload_max_filesize = 2000M
post_max_size = 2000M
EOF
a2enmod http2 deflate expires
Some sysadmins who saw a similar script told me sayings like "you better do it with Ansible because otherwise it will be a nightmare to maintain it".
Well, I can achieve basically the same with the following Ansible playbook I wrote (and have yet to test because I don't have a free machine right now but should work when deployed to all machines):
---
- hosts: all
become: yes
become_user: root
tasks:
- name: Update apt package-indexes cache
apt:
update_cache=yes
- name: Install external basics
apt: state=latest
with-items:
- ufw
- sshguard
- unattended-upgrades
- wget
- curl
- git
- zip
- unzip
- tree
- name: Setup firewall with ufw
ufw:
rule: allow
port: 22,25,80,443
- name: Establish a LAPMS (Linux, Apache, PHP, MySQL, SSMTP) server environment
apt: state=latest
with-items:
- apache2 # Web server
- python-certbot-apache
- php
- php-mysql # MySQL server
- php-cli
- php-curl
- php-mbstring
- php-mcrypt
- php-gd
- ssmtp # Email server
- phpmyadmin
- name: Install Composer
get_url:
url: https://getcomposer.org/installer
dest: /tmp/composer-setup.php
command: php /tmp/composer-setup.php --install-dir=/usr/local/bin --filename=composer
- name: Configure PHP variables
shell: |
cat <<-EOF > /etc/php*/conf.d/local.ini
upload_max_filesize = 2000M
post_max_size = 2000M
EOF
args:
executable: /bin/bash
- apache2_module:
state: present
name: http2
- apache2_module:
state: present
name: deflate
- apache2_module:
state: present
name: expires
My contemplation
I don't recognize a significant advantage of using mere Ansible over mere shell-scripting in the above trivial case as Ansible does only what we tell it to and doesn't do release_upgrades (as from Apache 2.4 to 3.4) and will basically give me the same apt upgrade -y
automation with scheduling (say with cron
) so I can't understand how it will be much of a helper (also the result is basically same but the number of lines is far greater (72 instead 20/21) unless one uses Ansible-Galaxy roles which are well organized programs containing a core of one or more Ansible playbooks.
My question
How does mere Ansible by itself (without using Ansible-Galaxy roles) more efficient than mere shell-scripting in general and Bash in particular in a trivial task such as the above?
shell-script software-installation upgrade scheduling ansible
I establish a LAMP with a few extras on a remote Debian machine with a similar shell (Bash) script:
#/bin/bash
apt update -y
apt upgrade ufw sshguard unattended-upgrades wget curl git zip unzip tree -y
ufw --force enable
ufw allow 22,25,80,443
apt upgrade lamp-server^ ssmtp
apt upgrade python-certbot-apache
apt upgrade php-{cli,curl,mbstring,mcrypt,gd} phpmyadmin
curl -sS https://getcomposer.org/installer -o composer-setup.php
php composer-setup.php --install-dir=/usr/local/bin --filename=composer
cat <<-EOF > /etc/php*/conf.d/local.ini
upload_max_filesize = 2000M
post_max_size = 2000M
EOF
a2enmod http2 deflate expires
Some sysadmins who saw a similar script told me sayings like "you better do it with Ansible because otherwise it will be a nightmare to maintain it".
Well, I can achieve basically the same with the following Ansible playbook I wrote (and have yet to test because I don't have a free machine right now but should work when deployed to all machines):
---
- hosts: all
become: yes
become_user: root
tasks:
- name: Update apt package-indexes cache
apt:
update_cache=yes
- name: Install external basics
apt: state=latest
with-items:
- ufw
- sshguard
- unattended-upgrades
- wget
- curl
- git
- zip
- unzip
- tree
- name: Setup firewall with ufw
ufw:
rule: allow
port: 22,25,80,443
- name: Establish a LAPMS (Linux, Apache, PHP, MySQL, SSMTP) server environment
apt: state=latest
with-items:
- apache2 # Web server
- python-certbot-apache
- php
- php-mysql # MySQL server
- php-cli
- php-curl
- php-mbstring
- php-mcrypt
- php-gd
- ssmtp # Email server
- phpmyadmin
- name: Install Composer
get_url:
url: https://getcomposer.org/installer
dest: /tmp/composer-setup.php
command: php /tmp/composer-setup.php --install-dir=/usr/local/bin --filename=composer
- name: Configure PHP variables
shell: |
cat <<-EOF > /etc/php*/conf.d/local.ini
upload_max_filesize = 2000M
post_max_size = 2000M
EOF
args:
executable: /bin/bash
- apache2_module:
state: present
name: http2
- apache2_module:
state: present
name: deflate
- apache2_module:
state: present
name: expires
My contemplation
I don't recognize a significant advantage of using mere Ansible over mere shell-scripting in the above trivial case as Ansible does only what we tell it to and doesn't do release_upgrades (as from Apache 2.4 to 3.4) and will basically give me the same apt upgrade -y
automation with scheduling (say with cron
) so I can't understand how it will be much of a helper (also the result is basically same but the number of lines is far greater (72 instead 20/21) unless one uses Ansible-Galaxy roles which are well organized programs containing a core of one or more Ansible playbooks.
My question
How does mere Ansible by itself (without using Ansible-Galaxy roles) more efficient than mere shell-scripting in general and Bash in particular in a trivial task such as the above?
shell-script software-installation upgrade scheduling ansible
shell-script software-installation upgrade scheduling ansible
edited yesterday
asked Dec 19 at 10:39
JohnDoea
1291132
1291132
closed as primarily opinion-based by muru, Mr Shunz, Rui F Ribeiro, sourcejedi, Jeff Schaller Dec 19 at 16:20
Many good questions generate some degree of opinion based on expert experience, but answers to this question will tend to be almost entirely based on opinions, rather than facts, references, or specific expertise. If this question can be reworded to fit the rules in the help center, please edit the question.
closed as primarily opinion-based by muru, Mr Shunz, Rui F Ribeiro, sourcejedi, Jeff Schaller Dec 19 at 16:20
Many good questions generate some degree of opinion based on expert experience, but answers to this question will tend to be almost entirely based on opinions, rather than facts, references, or specific expertise. If this question can be reworded to fit the rules in the help center, please edit the question.
It is utterly disappointing to me that such an important-understanding question was closed. Please migrate to wherever you see fit: DevOps SE, SuperUser SE, ServerFault, StackOverflow, or whatever. This is the most important Ansible question I ever asked in my life in my opinion. Pleople, please help me to re-open it or flag it with me to migration.
– JohnDoea
Dec 20 at 7:29
Another reason is that your bash script continues on errors, while Ansible stops on errors and reports them. It also reports which steps changed or didn't change a system.
– r3m0t
2 days ago
add a comment |
It is utterly disappointing to me that such an important-understanding question was closed. Please migrate to wherever you see fit: DevOps SE, SuperUser SE, ServerFault, StackOverflow, or whatever. This is the most important Ansible question I ever asked in my life in my opinion. Pleople, please help me to re-open it or flag it with me to migration.
– JohnDoea
Dec 20 at 7:29
Another reason is that your bash script continues on errors, while Ansible stops on errors and reports them. It also reports which steps changed or didn't change a system.
– r3m0t
2 days ago
It is utterly disappointing to me that such an important-understanding question was closed. Please migrate to wherever you see fit: DevOps SE, SuperUser SE, ServerFault, StackOverflow, or whatever. This is the most important Ansible question I ever asked in my life in my opinion. Pleople, please help me to re-open it or flag it with me to migration.
– JohnDoea
Dec 20 at 7:29
It is utterly disappointing to me that such an important-understanding question was closed. Please migrate to wherever you see fit: DevOps SE, SuperUser SE, ServerFault, StackOverflow, or whatever. This is the most important Ansible question I ever asked in my life in my opinion. Pleople, please help me to re-open it or flag it with me to migration.
– JohnDoea
Dec 20 at 7:29
Another reason is that your bash script continues on errors, while Ansible stops on errors and reports them. It also reports which steps changed or didn't change a system.
– r3m0t
2 days ago
Another reason is that your bash script continues on errors, while Ansible stops on errors and reports them. It also reports which steps changed or didn't change a system.
– r3m0t
2 days ago
add a comment |
3 Answers
3
active
oldest
votes
I do not think there is a big problem with 20 lines, as a shell script for an individual machine or two. That is a good thing to have.
That said, your script is not idempotent. For example it uses apt-get upgrade foo
, which can perform changes even if the script has already been run on this system. I do not think it worth using apt-get upgrade foo
. That command does not guarantee to apply security or bugfix updates to your dependencies.
A carefully written Ansible playbook can double as a small system check. This relies on the playbook being idempotent (and also that it reports "changed" status accurately). Running ansible-playbook --check
will show whether the system still meets all the defined tasks, or whether it has been changed. This can both be useful later on, and also to look for inconsistencies immediately after running a playbook.
And you may set up Ansible so you can run this on several machines at once.
Configuration tools like Ansible are useful at scale. Partly due to these sorts of features. Partly due to these sorts of constraints, which it encourages you to follow.
Encouraging you to write idempotent scripts can also be useful for maintenance. Consider the temptation to write a script that adds lines to an existing file (or adds tokens inside an existing line :-( ). If you ensure idempotence, then you can re-run the modified script without adding duplicate lines.
Another constraint is if you ever want to remove things from an installed system. In many cases this is not a problem, and you could always write an uninstall script/playbook later on. But in some cases you need to be careful about this. E.g. you might want to make sure not to use Ansible lineinfile
to replace an individual line, and instead overwrite the entire file with your own version. This can be useful when you no longer want to change line A from the default, but you still want to change line B.
For my usage, I would like to address the removal problem when managing firewalls. If you stop allowing a port in your install script, you might forget to explicitly block the port everywhere. The Ansible ufw
module does not help here, because it only allows adding or removing individual rules. I am currently thinking about using an alternative to the ufw
firewall, which has proper support for working from configuration files. (E.g. firewalld
, shorewall
, ferm
...).
1
The uninstallation angle is particularly hard to get right. Ideally, you want to be able to change your configuration description to omit the part you want to uninstall (since that’s the new target state for your system), and run your configuration management tool again. Thinking in terms of uninstallation playbooks often causes maintenance issues further down the line.
– Stephen Kitt
Dec 19 at 13:31
I never understood that saying that Ansible is idempotent. It doesn't recursively operate on an operator to recursively bring the same result, it can bring different results (sorry, I didn't lean much math in the past and not sure I understand idempotent well enough to understand the answer, let alone in the Ansible context).
– JohnDoea
Dec 19 at 13:31
@JohnDoea good Ansible playbooks are idempotent because they describe a desired state, not a desired installation process. If they describe a state, running them through Ansible ensures that the system is in the desired state, not that the desired configuration changes are applied. Applying the same state multiple times results in no change, so it’s idempotent.
– Stephen Kitt
Dec 19 at 13:33
@JohnDoea HTTP DELETE method, or NFS write operations, are examples of operations which are described as idempotent. They have the same effect if you run them twice, as if you run them once. In NFS3 over UDP, this property allows write requests to be safely re-sent if the client does not receive a success response after a timeout. Even though it might be the response packet that was lost, not the write request packet.
– sourcejedi
Dec 19 at 13:38
1
There are circumstances in which you want a list of all the allowed packages ;-). But yes, I certainly agree this is hard. It also leads to the whole pets-v.-cattle debate: in a cattle situation you’d nuke your VM and create a new one (no uninstallation needed), in the pet situation you need to deal with the ongoing maintenance of your system which always ends up having to deal with clean-up.
– Stephen Kitt
Dec 19 at 13:59
|
show 7 more comments
The difference between Bash and Ansible is that Ansible, when written properly, is idempotent. There are no changes when a playbook runs repeatedly. In this respect Bash script describes a procedure while Ansible playbook rather describes a state of a system.
To address the comment
"not sure I understand idempotent well enough to understand the answer".
Idempotence means that a playbook "can be applied multiple times without changing the result beyond the initial application". Best practice is to run a playbook twice. During the first run a playbook performs all changes. During the second run no changes should be reported.
Dear Vladimir, thank you, but if so, anyone who says Ansible uses to automate upgrades is either mistaking or laying, right? I assume yes, but then we can say that Ansible-Galaxy roles are an exception for that idempotence, right?
– JohnDoea
yesterday
Dear John, to tell you the truth, my experience with "automatic upgrades" is limited to procedures provided by Vendors. Such procedures should be idempotent. But, in most cases I automatically read Release Notes, test and fix potential backward incompatibilities on my own with Ansible.
– Vladimir Botka
yesterday
Thanks Vladimir, but what are "vendors" in this context, please?
– JohnDoea
yesterday
add a comment |
One of the main selling points of Ansible is that playbooks tend to be easier to read than dense BASH one liners due to its use of YAML syntax. You can also use linters and debuggers in a more feature rich way than you can with BASH scripts, and some IDEs even have built in Ansible text completion modules to assist with writing playbooks.
Hey Timothy, is one such IDE is VSCODE? Because only with it I work and prefer to stick with it. Maybe you have a recommendation for An Ansible plugin for it?
– JohnDoea
Dec 20 at 7:26
I've never used VSCODE before, but I have used Atom IDE which has several Ansible plugins for auto completion and linting capabilities to assist with writing playbooks.
– Timothy Pulliam
yesterday
add a comment |
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
I do not think there is a big problem with 20 lines, as a shell script for an individual machine or two. That is a good thing to have.
That said, your script is not idempotent. For example it uses apt-get upgrade foo
, which can perform changes even if the script has already been run on this system. I do not think it worth using apt-get upgrade foo
. That command does not guarantee to apply security or bugfix updates to your dependencies.
A carefully written Ansible playbook can double as a small system check. This relies on the playbook being idempotent (and also that it reports "changed" status accurately). Running ansible-playbook --check
will show whether the system still meets all the defined tasks, or whether it has been changed. This can both be useful later on, and also to look for inconsistencies immediately after running a playbook.
And you may set up Ansible so you can run this on several machines at once.
Configuration tools like Ansible are useful at scale. Partly due to these sorts of features. Partly due to these sorts of constraints, which it encourages you to follow.
Encouraging you to write idempotent scripts can also be useful for maintenance. Consider the temptation to write a script that adds lines to an existing file (or adds tokens inside an existing line :-( ). If you ensure idempotence, then you can re-run the modified script without adding duplicate lines.
Another constraint is if you ever want to remove things from an installed system. In many cases this is not a problem, and you could always write an uninstall script/playbook later on. But in some cases you need to be careful about this. E.g. you might want to make sure not to use Ansible lineinfile
to replace an individual line, and instead overwrite the entire file with your own version. This can be useful when you no longer want to change line A from the default, but you still want to change line B.
For my usage, I would like to address the removal problem when managing firewalls. If you stop allowing a port in your install script, you might forget to explicitly block the port everywhere. The Ansible ufw
module does not help here, because it only allows adding or removing individual rules. I am currently thinking about using an alternative to the ufw
firewall, which has proper support for working from configuration files. (E.g. firewalld
, shorewall
, ferm
...).
1
The uninstallation angle is particularly hard to get right. Ideally, you want to be able to change your configuration description to omit the part you want to uninstall (since that’s the new target state for your system), and run your configuration management tool again. Thinking in terms of uninstallation playbooks often causes maintenance issues further down the line.
– Stephen Kitt
Dec 19 at 13:31
I never understood that saying that Ansible is idempotent. It doesn't recursively operate on an operator to recursively bring the same result, it can bring different results (sorry, I didn't lean much math in the past and not sure I understand idempotent well enough to understand the answer, let alone in the Ansible context).
– JohnDoea
Dec 19 at 13:31
@JohnDoea good Ansible playbooks are idempotent because they describe a desired state, not a desired installation process. If they describe a state, running them through Ansible ensures that the system is in the desired state, not that the desired configuration changes are applied. Applying the same state multiple times results in no change, so it’s idempotent.
– Stephen Kitt
Dec 19 at 13:33
@JohnDoea HTTP DELETE method, or NFS write operations, are examples of operations which are described as idempotent. They have the same effect if you run them twice, as if you run them once. In NFS3 over UDP, this property allows write requests to be safely re-sent if the client does not receive a success response after a timeout. Even though it might be the response packet that was lost, not the write request packet.
– sourcejedi
Dec 19 at 13:38
1
There are circumstances in which you want a list of all the allowed packages ;-). But yes, I certainly agree this is hard. It also leads to the whole pets-v.-cattle debate: in a cattle situation you’d nuke your VM and create a new one (no uninstallation needed), in the pet situation you need to deal with the ongoing maintenance of your system which always ends up having to deal with clean-up.
– Stephen Kitt
Dec 19 at 13:59
|
show 7 more comments
I do not think there is a big problem with 20 lines, as a shell script for an individual machine or two. That is a good thing to have.
That said, your script is not idempotent. For example it uses apt-get upgrade foo
, which can perform changes even if the script has already been run on this system. I do not think it worth using apt-get upgrade foo
. That command does not guarantee to apply security or bugfix updates to your dependencies.
A carefully written Ansible playbook can double as a small system check. This relies on the playbook being idempotent (and also that it reports "changed" status accurately). Running ansible-playbook --check
will show whether the system still meets all the defined tasks, or whether it has been changed. This can both be useful later on, and also to look for inconsistencies immediately after running a playbook.
And you may set up Ansible so you can run this on several machines at once.
Configuration tools like Ansible are useful at scale. Partly due to these sorts of features. Partly due to these sorts of constraints, which it encourages you to follow.
Encouraging you to write idempotent scripts can also be useful for maintenance. Consider the temptation to write a script that adds lines to an existing file (or adds tokens inside an existing line :-( ). If you ensure idempotence, then you can re-run the modified script without adding duplicate lines.
Another constraint is if you ever want to remove things from an installed system. In many cases this is not a problem, and you could always write an uninstall script/playbook later on. But in some cases you need to be careful about this. E.g. you might want to make sure not to use Ansible lineinfile
to replace an individual line, and instead overwrite the entire file with your own version. This can be useful when you no longer want to change line A from the default, but you still want to change line B.
For my usage, I would like to address the removal problem when managing firewalls. If you stop allowing a port in your install script, you might forget to explicitly block the port everywhere. The Ansible ufw
module does not help here, because it only allows adding or removing individual rules. I am currently thinking about using an alternative to the ufw
firewall, which has proper support for working from configuration files. (E.g. firewalld
, shorewall
, ferm
...).
1
The uninstallation angle is particularly hard to get right. Ideally, you want to be able to change your configuration description to omit the part you want to uninstall (since that’s the new target state for your system), and run your configuration management tool again. Thinking in terms of uninstallation playbooks often causes maintenance issues further down the line.
– Stephen Kitt
Dec 19 at 13:31
I never understood that saying that Ansible is idempotent. It doesn't recursively operate on an operator to recursively bring the same result, it can bring different results (sorry, I didn't lean much math in the past and not sure I understand idempotent well enough to understand the answer, let alone in the Ansible context).
– JohnDoea
Dec 19 at 13:31
@JohnDoea good Ansible playbooks are idempotent because they describe a desired state, not a desired installation process. If they describe a state, running them through Ansible ensures that the system is in the desired state, not that the desired configuration changes are applied. Applying the same state multiple times results in no change, so it’s idempotent.
– Stephen Kitt
Dec 19 at 13:33
@JohnDoea HTTP DELETE method, or NFS write operations, are examples of operations which are described as idempotent. They have the same effect if you run them twice, as if you run them once. In NFS3 over UDP, this property allows write requests to be safely re-sent if the client does not receive a success response after a timeout. Even though it might be the response packet that was lost, not the write request packet.
– sourcejedi
Dec 19 at 13:38
1
There are circumstances in which you want a list of all the allowed packages ;-). But yes, I certainly agree this is hard. It also leads to the whole pets-v.-cattle debate: in a cattle situation you’d nuke your VM and create a new one (no uninstallation needed), in the pet situation you need to deal with the ongoing maintenance of your system which always ends up having to deal with clean-up.
– Stephen Kitt
Dec 19 at 13:59
|
show 7 more comments
I do not think there is a big problem with 20 lines, as a shell script for an individual machine or two. That is a good thing to have.
That said, your script is not idempotent. For example it uses apt-get upgrade foo
, which can perform changes even if the script has already been run on this system. I do not think it worth using apt-get upgrade foo
. That command does not guarantee to apply security or bugfix updates to your dependencies.
A carefully written Ansible playbook can double as a small system check. This relies on the playbook being idempotent (and also that it reports "changed" status accurately). Running ansible-playbook --check
will show whether the system still meets all the defined tasks, or whether it has been changed. This can both be useful later on, and also to look for inconsistencies immediately after running a playbook.
And you may set up Ansible so you can run this on several machines at once.
Configuration tools like Ansible are useful at scale. Partly due to these sorts of features. Partly due to these sorts of constraints, which it encourages you to follow.
Encouraging you to write idempotent scripts can also be useful for maintenance. Consider the temptation to write a script that adds lines to an existing file (or adds tokens inside an existing line :-( ). If you ensure idempotence, then you can re-run the modified script without adding duplicate lines.
Another constraint is if you ever want to remove things from an installed system. In many cases this is not a problem, and you could always write an uninstall script/playbook later on. But in some cases you need to be careful about this. E.g. you might want to make sure not to use Ansible lineinfile
to replace an individual line, and instead overwrite the entire file with your own version. This can be useful when you no longer want to change line A from the default, but you still want to change line B.
For my usage, I would like to address the removal problem when managing firewalls. If you stop allowing a port in your install script, you might forget to explicitly block the port everywhere. The Ansible ufw
module does not help here, because it only allows adding or removing individual rules. I am currently thinking about using an alternative to the ufw
firewall, which has proper support for working from configuration files. (E.g. firewalld
, shorewall
, ferm
...).
I do not think there is a big problem with 20 lines, as a shell script for an individual machine or two. That is a good thing to have.
That said, your script is not idempotent. For example it uses apt-get upgrade foo
, which can perform changes even if the script has already been run on this system. I do not think it worth using apt-get upgrade foo
. That command does not guarantee to apply security or bugfix updates to your dependencies.
A carefully written Ansible playbook can double as a small system check. This relies on the playbook being idempotent (and also that it reports "changed" status accurately). Running ansible-playbook --check
will show whether the system still meets all the defined tasks, or whether it has been changed. This can both be useful later on, and also to look for inconsistencies immediately after running a playbook.
And you may set up Ansible so you can run this on several machines at once.
Configuration tools like Ansible are useful at scale. Partly due to these sorts of features. Partly due to these sorts of constraints, which it encourages you to follow.
Encouraging you to write idempotent scripts can also be useful for maintenance. Consider the temptation to write a script that adds lines to an existing file (or adds tokens inside an existing line :-( ). If you ensure idempotence, then you can re-run the modified script without adding duplicate lines.
Another constraint is if you ever want to remove things from an installed system. In many cases this is not a problem, and you could always write an uninstall script/playbook later on. But in some cases you need to be careful about this. E.g. you might want to make sure not to use Ansible lineinfile
to replace an individual line, and instead overwrite the entire file with your own version. This can be useful when you no longer want to change line A from the default, but you still want to change line B.
For my usage, I would like to address the removal problem when managing firewalls. If you stop allowing a port in your install script, you might forget to explicitly block the port everywhere. The Ansible ufw
module does not help here, because it only allows adding or removing individual rules. I am currently thinking about using an alternative to the ufw
firewall, which has proper support for working from configuration files. (E.g. firewalld
, shorewall
, ferm
...).
edited Dec 19 at 14:01
answered Dec 19 at 12:41
sourcejedi
22.7k435100
22.7k435100
1
The uninstallation angle is particularly hard to get right. Ideally, you want to be able to change your configuration description to omit the part you want to uninstall (since that’s the new target state for your system), and run your configuration management tool again. Thinking in terms of uninstallation playbooks often causes maintenance issues further down the line.
– Stephen Kitt
Dec 19 at 13:31
I never understood that saying that Ansible is idempotent. It doesn't recursively operate on an operator to recursively bring the same result, it can bring different results (sorry, I didn't lean much math in the past and not sure I understand idempotent well enough to understand the answer, let alone in the Ansible context).
– JohnDoea
Dec 19 at 13:31
@JohnDoea good Ansible playbooks are idempotent because they describe a desired state, not a desired installation process. If they describe a state, running them through Ansible ensures that the system is in the desired state, not that the desired configuration changes are applied. Applying the same state multiple times results in no change, so it’s idempotent.
– Stephen Kitt
Dec 19 at 13:33
@JohnDoea HTTP DELETE method, or NFS write operations, are examples of operations which are described as idempotent. They have the same effect if you run them twice, as if you run them once. In NFS3 over UDP, this property allows write requests to be safely re-sent if the client does not receive a success response after a timeout. Even though it might be the response packet that was lost, not the write request packet.
– sourcejedi
Dec 19 at 13:38
1
There are circumstances in which you want a list of all the allowed packages ;-). But yes, I certainly agree this is hard. It also leads to the whole pets-v.-cattle debate: in a cattle situation you’d nuke your VM and create a new one (no uninstallation needed), in the pet situation you need to deal with the ongoing maintenance of your system which always ends up having to deal with clean-up.
– Stephen Kitt
Dec 19 at 13:59
|
show 7 more comments
1
The uninstallation angle is particularly hard to get right. Ideally, you want to be able to change your configuration description to omit the part you want to uninstall (since that’s the new target state for your system), and run your configuration management tool again. Thinking in terms of uninstallation playbooks often causes maintenance issues further down the line.
– Stephen Kitt
Dec 19 at 13:31
I never understood that saying that Ansible is idempotent. It doesn't recursively operate on an operator to recursively bring the same result, it can bring different results (sorry, I didn't lean much math in the past and not sure I understand idempotent well enough to understand the answer, let alone in the Ansible context).
– JohnDoea
Dec 19 at 13:31
@JohnDoea good Ansible playbooks are idempotent because they describe a desired state, not a desired installation process. If they describe a state, running them through Ansible ensures that the system is in the desired state, not that the desired configuration changes are applied. Applying the same state multiple times results in no change, so it’s idempotent.
– Stephen Kitt
Dec 19 at 13:33
@JohnDoea HTTP DELETE method, or NFS write operations, are examples of operations which are described as idempotent. They have the same effect if you run them twice, as if you run them once. In NFS3 over UDP, this property allows write requests to be safely re-sent if the client does not receive a success response after a timeout. Even though it might be the response packet that was lost, not the write request packet.
– sourcejedi
Dec 19 at 13:38
1
There are circumstances in which you want a list of all the allowed packages ;-). But yes, I certainly agree this is hard. It also leads to the whole pets-v.-cattle debate: in a cattle situation you’d nuke your VM and create a new one (no uninstallation needed), in the pet situation you need to deal with the ongoing maintenance of your system which always ends up having to deal with clean-up.
– Stephen Kitt
Dec 19 at 13:59
1
1
The uninstallation angle is particularly hard to get right. Ideally, you want to be able to change your configuration description to omit the part you want to uninstall (since that’s the new target state for your system), and run your configuration management tool again. Thinking in terms of uninstallation playbooks often causes maintenance issues further down the line.
– Stephen Kitt
Dec 19 at 13:31
The uninstallation angle is particularly hard to get right. Ideally, you want to be able to change your configuration description to omit the part you want to uninstall (since that’s the new target state for your system), and run your configuration management tool again. Thinking in terms of uninstallation playbooks often causes maintenance issues further down the line.
– Stephen Kitt
Dec 19 at 13:31
I never understood that saying that Ansible is idempotent. It doesn't recursively operate on an operator to recursively bring the same result, it can bring different results (sorry, I didn't lean much math in the past and not sure I understand idempotent well enough to understand the answer, let alone in the Ansible context).
– JohnDoea
Dec 19 at 13:31
I never understood that saying that Ansible is idempotent. It doesn't recursively operate on an operator to recursively bring the same result, it can bring different results (sorry, I didn't lean much math in the past and not sure I understand idempotent well enough to understand the answer, let alone in the Ansible context).
– JohnDoea
Dec 19 at 13:31
@JohnDoea good Ansible playbooks are idempotent because they describe a desired state, not a desired installation process. If they describe a state, running them through Ansible ensures that the system is in the desired state, not that the desired configuration changes are applied. Applying the same state multiple times results in no change, so it’s idempotent.
– Stephen Kitt
Dec 19 at 13:33
@JohnDoea good Ansible playbooks are idempotent because they describe a desired state, not a desired installation process. If they describe a state, running them through Ansible ensures that the system is in the desired state, not that the desired configuration changes are applied. Applying the same state multiple times results in no change, so it’s idempotent.
– Stephen Kitt
Dec 19 at 13:33
@JohnDoea HTTP DELETE method, or NFS write operations, are examples of operations which are described as idempotent. They have the same effect if you run them twice, as if you run them once. In NFS3 over UDP, this property allows write requests to be safely re-sent if the client does not receive a success response after a timeout. Even though it might be the response packet that was lost, not the write request packet.
– sourcejedi
Dec 19 at 13:38
@JohnDoea HTTP DELETE method, or NFS write operations, are examples of operations which are described as idempotent. They have the same effect if you run them twice, as if you run them once. In NFS3 over UDP, this property allows write requests to be safely re-sent if the client does not receive a success response after a timeout. Even though it might be the response packet that was lost, not the write request packet.
– sourcejedi
Dec 19 at 13:38
1
1
There are circumstances in which you want a list of all the allowed packages ;-). But yes, I certainly agree this is hard. It also leads to the whole pets-v.-cattle debate: in a cattle situation you’d nuke your VM and create a new one (no uninstallation needed), in the pet situation you need to deal with the ongoing maintenance of your system which always ends up having to deal with clean-up.
– Stephen Kitt
Dec 19 at 13:59
There are circumstances in which you want a list of all the allowed packages ;-). But yes, I certainly agree this is hard. It also leads to the whole pets-v.-cattle debate: in a cattle situation you’d nuke your VM and create a new one (no uninstallation needed), in the pet situation you need to deal with the ongoing maintenance of your system which always ends up having to deal with clean-up.
– Stephen Kitt
Dec 19 at 13:59
|
show 7 more comments
The difference between Bash and Ansible is that Ansible, when written properly, is idempotent. There are no changes when a playbook runs repeatedly. In this respect Bash script describes a procedure while Ansible playbook rather describes a state of a system.
To address the comment
"not sure I understand idempotent well enough to understand the answer".
Idempotence means that a playbook "can be applied multiple times without changing the result beyond the initial application". Best practice is to run a playbook twice. During the first run a playbook performs all changes. During the second run no changes should be reported.
Dear Vladimir, thank you, but if so, anyone who says Ansible uses to automate upgrades is either mistaking or laying, right? I assume yes, but then we can say that Ansible-Galaxy roles are an exception for that idempotence, right?
– JohnDoea
yesterday
Dear John, to tell you the truth, my experience with "automatic upgrades" is limited to procedures provided by Vendors. Such procedures should be idempotent. But, in most cases I automatically read Release Notes, test and fix potential backward incompatibilities on my own with Ansible.
– Vladimir Botka
yesterday
Thanks Vladimir, but what are "vendors" in this context, please?
– JohnDoea
yesterday
add a comment |
The difference between Bash and Ansible is that Ansible, when written properly, is idempotent. There are no changes when a playbook runs repeatedly. In this respect Bash script describes a procedure while Ansible playbook rather describes a state of a system.
To address the comment
"not sure I understand idempotent well enough to understand the answer".
Idempotence means that a playbook "can be applied multiple times without changing the result beyond the initial application". Best practice is to run a playbook twice. During the first run a playbook performs all changes. During the second run no changes should be reported.
Dear Vladimir, thank you, but if so, anyone who says Ansible uses to automate upgrades is either mistaking or laying, right? I assume yes, but then we can say that Ansible-Galaxy roles are an exception for that idempotence, right?
– JohnDoea
yesterday
Dear John, to tell you the truth, my experience with "automatic upgrades" is limited to procedures provided by Vendors. Such procedures should be idempotent. But, in most cases I automatically read Release Notes, test and fix potential backward incompatibilities on my own with Ansible.
– Vladimir Botka
yesterday
Thanks Vladimir, but what are "vendors" in this context, please?
– JohnDoea
yesterday
add a comment |
The difference between Bash and Ansible is that Ansible, when written properly, is idempotent. There are no changes when a playbook runs repeatedly. In this respect Bash script describes a procedure while Ansible playbook rather describes a state of a system.
To address the comment
"not sure I understand idempotent well enough to understand the answer".
Idempotence means that a playbook "can be applied multiple times without changing the result beyond the initial application". Best practice is to run a playbook twice. During the first run a playbook performs all changes. During the second run no changes should be reported.
The difference between Bash and Ansible is that Ansible, when written properly, is idempotent. There are no changes when a playbook runs repeatedly. In this respect Bash script describes a procedure while Ansible playbook rather describes a state of a system.
To address the comment
"not sure I understand idempotent well enough to understand the answer".
Idempotence means that a playbook "can be applied multiple times without changing the result beyond the initial application". Best practice is to run a playbook twice. During the first run a playbook performs all changes. During the second run no changes should be reported.
edited Dec 19 at 14:21
answered Dec 19 at 10:54
Vladimir Botka
1815
1815
Dear Vladimir, thank you, but if so, anyone who says Ansible uses to automate upgrades is either mistaking or laying, right? I assume yes, but then we can say that Ansible-Galaxy roles are an exception for that idempotence, right?
– JohnDoea
yesterday
Dear John, to tell you the truth, my experience with "automatic upgrades" is limited to procedures provided by Vendors. Such procedures should be idempotent. But, in most cases I automatically read Release Notes, test and fix potential backward incompatibilities on my own with Ansible.
– Vladimir Botka
yesterday
Thanks Vladimir, but what are "vendors" in this context, please?
– JohnDoea
yesterday
add a comment |
Dear Vladimir, thank you, but if so, anyone who says Ansible uses to automate upgrades is either mistaking or laying, right? I assume yes, but then we can say that Ansible-Galaxy roles are an exception for that idempotence, right?
– JohnDoea
yesterday
Dear John, to tell you the truth, my experience with "automatic upgrades" is limited to procedures provided by Vendors. Such procedures should be idempotent. But, in most cases I automatically read Release Notes, test and fix potential backward incompatibilities on my own with Ansible.
– Vladimir Botka
yesterday
Thanks Vladimir, but what are "vendors" in this context, please?
– JohnDoea
yesterday
Dear Vladimir, thank you, but if so, anyone who says Ansible uses to automate upgrades is either mistaking or laying, right? I assume yes, but then we can say that Ansible-Galaxy roles are an exception for that idempotence, right?
– JohnDoea
yesterday
Dear Vladimir, thank you, but if so, anyone who says Ansible uses to automate upgrades is either mistaking or laying, right? I assume yes, but then we can say that Ansible-Galaxy roles are an exception for that idempotence, right?
– JohnDoea
yesterday
Dear John, to tell you the truth, my experience with "automatic upgrades" is limited to procedures provided by Vendors. Such procedures should be idempotent. But, in most cases I automatically read Release Notes, test and fix potential backward incompatibilities on my own with Ansible.
– Vladimir Botka
yesterday
Dear John, to tell you the truth, my experience with "automatic upgrades" is limited to procedures provided by Vendors. Such procedures should be idempotent. But, in most cases I automatically read Release Notes, test and fix potential backward incompatibilities on my own with Ansible.
– Vladimir Botka
yesterday
Thanks Vladimir, but what are "vendors" in this context, please?
– JohnDoea
yesterday
Thanks Vladimir, but what are "vendors" in this context, please?
– JohnDoea
yesterday
add a comment |
One of the main selling points of Ansible is that playbooks tend to be easier to read than dense BASH one liners due to its use of YAML syntax. You can also use linters and debuggers in a more feature rich way than you can with BASH scripts, and some IDEs even have built in Ansible text completion modules to assist with writing playbooks.
Hey Timothy, is one such IDE is VSCODE? Because only with it I work and prefer to stick with it. Maybe you have a recommendation for An Ansible plugin for it?
– JohnDoea
Dec 20 at 7:26
I've never used VSCODE before, but I have used Atom IDE which has several Ansible plugins for auto completion and linting capabilities to assist with writing playbooks.
– Timothy Pulliam
yesterday
add a comment |
One of the main selling points of Ansible is that playbooks tend to be easier to read than dense BASH one liners due to its use of YAML syntax. You can also use linters and debuggers in a more feature rich way than you can with BASH scripts, and some IDEs even have built in Ansible text completion modules to assist with writing playbooks.
Hey Timothy, is one such IDE is VSCODE? Because only with it I work and prefer to stick with it. Maybe you have a recommendation for An Ansible plugin for it?
– JohnDoea
Dec 20 at 7:26
I've never used VSCODE before, but I have used Atom IDE which has several Ansible plugins for auto completion and linting capabilities to assist with writing playbooks.
– Timothy Pulliam
yesterday
add a comment |
One of the main selling points of Ansible is that playbooks tend to be easier to read than dense BASH one liners due to its use of YAML syntax. You can also use linters and debuggers in a more feature rich way than you can with BASH scripts, and some IDEs even have built in Ansible text completion modules to assist with writing playbooks.
One of the main selling points of Ansible is that playbooks tend to be easier to read than dense BASH one liners due to its use of YAML syntax. You can also use linters and debuggers in a more feature rich way than you can with BASH scripts, and some IDEs even have built in Ansible text completion modules to assist with writing playbooks.
edited Dec 19 at 20:56
Rui F Ribeiro
38.8k1479129
38.8k1479129
answered Dec 19 at 13:44
Timothy Pulliam
1,130821
1,130821
Hey Timothy, is one such IDE is VSCODE? Because only with it I work and prefer to stick with it. Maybe you have a recommendation for An Ansible plugin for it?
– JohnDoea
Dec 20 at 7:26
I've never used VSCODE before, but I have used Atom IDE which has several Ansible plugins for auto completion and linting capabilities to assist with writing playbooks.
– Timothy Pulliam
yesterday
add a comment |
Hey Timothy, is one such IDE is VSCODE? Because only with it I work and prefer to stick with it. Maybe you have a recommendation for An Ansible plugin for it?
– JohnDoea
Dec 20 at 7:26
I've never used VSCODE before, but I have used Atom IDE which has several Ansible plugins for auto completion and linting capabilities to assist with writing playbooks.
– Timothy Pulliam
yesterday
Hey Timothy, is one such IDE is VSCODE? Because only with it I work and prefer to stick with it. Maybe you have a recommendation for An Ansible plugin for it?
– JohnDoea
Dec 20 at 7:26
Hey Timothy, is one such IDE is VSCODE? Because only with it I work and prefer to stick with it. Maybe you have a recommendation for An Ansible plugin for it?
– JohnDoea
Dec 20 at 7:26
I've never used VSCODE before, but I have used Atom IDE which has several Ansible plugins for auto completion and linting capabilities to assist with writing playbooks.
– Timothy Pulliam
yesterday
I've never used VSCODE before, but I have used Atom IDE which has several Ansible plugins for auto completion and linting capabilities to assist with writing playbooks.
– Timothy Pulliam
yesterday
add a comment |
It is utterly disappointing to me that such an important-understanding question was closed. Please migrate to wherever you see fit: DevOps SE, SuperUser SE, ServerFault, StackOverflow, or whatever. This is the most important Ansible question I ever asked in my life in my opinion. Pleople, please help me to re-open it or flag it with me to migration.
– JohnDoea
Dec 20 at 7:29
Another reason is that your bash script continues on errors, while Ansible stops on errors and reports them. It also reports which steps changed or didn't change a system.
– r3m0t
2 days ago