Difference between "command" or specific module execution in Ansible - module

I'm starting with Ansible, and I found that there is a module called command which lets me execute any command in a remote node.
I saw a couple of example where initial setups are solved by using command instead of specific modules. For example, as far as I know, both of these do the same task:
- name: Install git using apt module
apt:
name: git
state: present
- name: Install git using command
command: apt-get install git
So, my question is: is there any difference or any reason to use a module instead of command?

The difference in short is that using a specific module will give you playbook's idempotence and provide better portability and readability.
What I mean by idempotence? When you run:
- name: Install git using apt module
apt:
name: git
state: present
It will install git package only if it is not yet installed on the target system and after playbook run this task will be reported in green colour (OK) if git had been already installed.
2nd approach with the command module:
- name: Install git using command
command: apt-get install git
Above command will always report status as changed (yellow colour) when in fact nothing changed (assuming git package had been already installed). There are ways to make tasks that use the command module idempotent as well but it costs you some more work.
Best practice is to always use a specific module before command in playbooks.
Ansible is all about describing and managing system state. When you run a playbook on a certain target system it can be very misleading to see a task reporting a changed state while in fact nothing has been changed.
Think declaratively about describing desired state, not about low level commands needed to get a system to this state.
Below article will also provide some explanation around differences and consequences of using command vs specific module:
Ansible Best Practices: The Essentials

There are probably numerous reasons but here are a few:
Intrinsic idempotence (does not execute task every time without extra effort)
Superior readability (much clearer what you are trying to do)
More concise tasks (much fewer words to describe the task)
Platform-agnostic execution (works on all OS instead of just one without extra effort)

Related

How to run Odoo with OCA repositories' modules in Odoo.sh?

I am testing Odoo.sh, trying to run an Odoo 15 Enterprise. I read all the documentation and see several webinars about it, but I am not able to run an instance with any OCA module.
To do that, I followed these steps:
In the Odoo.sh interface, I created a new branch in the Development category, forking from main branch (the one in the Production category). Note: the main branch is the one created by default by Odoo.sh, I didn't make any modification on it and in fact it works OK, I can connect to it.
Also in the Odoo.sh interface, I clicked on the button Submodule and then on Run on Odoo.sh. In the opened pop-up, I added the OCA repository l10n-spain, (version 15.0 of course). The repository works perfectly in a local server. In fact you can try with other OCA repository, the result is going to be the same.
After doing that, Odoo.sh adds the repo to the project with a new [ADD] commit, and tries to make a build of it. However, the tests always fail.
If I go to the log, first, in the install.log section, I can see errors with Pip libraries, so I open a shell and try to fix them, with pip3 check and then adjusting the versions of the libraries it complains of.
After that, when I try to connect to the new build, the odoo.log starts being filled but also with errors, particularly this one:
WARNING xxx odoo.addons.base.models.ir_cron: Tried to poll an undefined table on database xxx.
ERROR xxx odoo.sql_db: bad query:
SELECT latest_version
FROM ir_module_module
WHERE name='base'
ERROR: relation "ir_module_module" does not exist
LINE 3: FROM ir_module_module
^
This error uses to appear when you do a wrong installation of Odoo, but the installation is done by Odoo.sh, so... how can I fix this?
Does anyone experienced the same? Any ideas? May be the Python libraries are the problem?
One problem can be that the requirements file brokest the installation. odoo.sh tries to install it automatically, and because odoo.sh is using outdated python modules, the installation usually breaks.
https://github.com/OCA/l10n-spain/blob/15.0/requirements.txt
You can try to copy the required modules directly to your repository.
Well, in the end I managed to connect to the build after open a shell and writing these commands:
odoosh-restart http
odoo-update all
Still didn't check which of them did the trick.

WSL can't detect VS code

At first, I tried to fix my problem of npm instruction
so I added
[interop]
appendWindowsPath = false
to /etc/wsl.conf
It works, but another problem happen.
When I type code .
Command 'code' not found, did you mean:
command 'node' from deb nodejs (12.22.9~dfsg-1ubuntu3)
command 'cdde' from deb cdde (0.3.1-1build1)
command 'ode' from deb plotutils (2.6-11)
command 'tcode' from deb emboss (6.6.0+dfsg-11ubuntu1)
command 'cde' from deb cde (0.1+git9-g551e54d-1.2)
Try: sudo apt install <deb name>
The above Error message appear.
I tried the following instruction
export PATH=$PATH:"/mnt/c/Users/%USERNAME%/AppData/Local/Programs/Microsoft VS Code/bin"
It also works properly.
Whenever I restarted WSL, npm instruction still worked well, but code instruction lost its function again.
What should I do to fix the problem?
Thanks in advance!
My main suggestion would be to not use appendWindowsPath = false to fix your NPM problem. That's like using a sledgehammer as a flyswatter. As I said in this answer:
Please do not follow the recommendations (like this answer) to completely remove all Windows paths from WSL, as that will severely limit your ability to run Windows applications in WSL (one of its great features).
You'll also lose access to the ability to run PowerShell scripts and commands in WSL easily. You won't have direct access to wsl.exe itself from inside WSL (which comes in handy).
You can type the full paths to these commands, of course, but most instructions and other answers you find here are going to assume that you've left the Windows path intact.
Instead, figure out where npm is installed in your WSL distribution and then determine why it is further toward the end of the PATH than your Windows directories. Windows paths are added at the end of the Linux PATH for a reason. If something in your startup files is adding to the path, it should put it at the beginning, so it has precedence. E.g.:
export PATH="newdir:$PATH"
Note that I'm not saying that you should change your export statement above since, as mentioned, that Windows path would normally come at the end anyway. It's really not going to matter unless you put another code executable somewhere else in your path.
Whenever I restarted WSL, npm instruction still worked well, but code instruction lost its function again.
If you do want the "quick and dirty" (not recommended) solution, then you can simply add that export command that "makes it work" to your ~/.bashrc. That file is processed each time the Bash shell starts interactively.

How can I install matplotlib for my AWS Elastic Beanstalk application?

I'm having a hell of a time deploying matplotlib on AWS Elastic Beanstalk. I gather that my issue comes from some dependencies and the way that EB deploys packages installed with PIP, and have attempted to follow the instructions here on SO for resolving the issue.
I first tried incrementally deploying, as suggested in the linked answer, by adding pieces of the matplotlib package stack to my requirements.txt file in stages. But this takes forever (for each stage) and is prone to failure and timing out (which seems to leave build directories behind that stall subsequent package installations).
So the simple solution mentioned off-handedly at the end of the answer appeals to me: just eb ssh, activate the virtialenv with
source /opt/python/run/venv/bin/activate
and pip install packages manually. But I can't get this to work either. First I'm often confronted with left-beind build directories (as mentioned above)
pip can't proceed with requirement 'xxxx' due to a pre-existing build directory.
location: /opt/python/run/venv/build/xxxx
This is likely due to a previous installation that failed.
pip is being responsible and not assuming it can delete this.
Please delete it and try again.
But even after removing these, I consistently get
Exception:
Traceback (most recent call last):
File "/opt/python/run/venv/lib/python2.7/site-packages/pip/basecommand.py", line 122, in main
status = self.run(options, args)
File "/opt/python/run/venv/lib/python2.7/site-packages/pip/commands/install.py", line 278, in run
requirement_set.prepare_files(finder, force_root_egg_info=self.bundle, bundle=self.bundle)
File "/opt/python/run/venv/lib/python2.7/site-packages/pip/req.py", line 1197, in prepare_files
do_download,
File "/opt/python/run/venv/lib/python2.7/site-packages/pip/req.py", line 1375, in unpack_url
self.session,
File "/opt/python/run/venv/lib/python2.7/site-packages/pip/download.py", line 582, in unpack_http_url
unpack_file(temp_location, location, content_type, link)
File "/opt/python/run/venv/lib/python2.7/site-packages/pip/util.py", line 625, in unpack_file
untar_file(filename, location)
File "/opt/python/run/venv/lib/python2.7/site-packages/pip/util.py", line 533, in untar_file
os.makedirs(location)
File "/opt/python/run/venv/lib64/python2.7/os.py", line 157, in makedirs
mkdir(name, mode)
OSError: [Errno 13] Permission denied: '/opt/python/run/venv/build/xxxx'
in response to pip install xxxx (and sudo pip fails with sudo: pip: command not found).
What can I do to get this working on AWS-EB? In particular, what do I need to do to get the simple SSH+PIP approach working; or is there some other better — simpler! — approach I should try.
FWIW, I have a .ebextensions/software.config with
packages:
yum:
gcc-c++: []
gcc-gfortran: []
python-devel: []
atlas-sse3-devel: []
lapack-devel: []
libpng-devel: []
freetype-devel: []
zlib-devel: []
and a requirements.txt that ends with
pytz==2014.10
pyparsing==2.0.3
python-dateutil==2.4.0
nose==1.3.4
six>=1.8.0
mock==1.0.1
numpy==1.9.1
matplotlib==1.4.2
After about 4 hours, I've gotten far as numpy (as reported by pip list in the EB virtualenv).
And (in case it matters) the user who is SSHing is part in a group with the policy
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"elasticbeanstalk:*",
"ec2:*",
"elasticloadbalancing:*",
"autoscaling:*",
"cloudwatch:*",
"s3:*",
"sns:*",
"cloudformation:*",
"rds:*",
"sqs:*",
"iam:PassRole"
],
"Resource": "*"
}
]
}
I have used many approaches to build and deploy numpy/scipy/matplotlib, on Windows as well as Linux systems. I have used system-provided package managers (aptitude, rpm), 3rd-party package managers (pypm), Python package managers (easy_install, pip), source releases, used different build environments/tools (GCC, but also Intel MKL, OpenMP). While doing so, I have run into many many quite annoying situations, but have also learned a lot about the pros and cons of each approach.
I have no experience with Elastic Beanstalk (EB), but I have experience with EC2. I see that you can SSH into an instance and poke around. So, what I suggest further below is based on
above-stated experiences and on
the more or less obvious boundary conditions regarding Beanstalk and on
your application scenario, described in another question here on SO and on
the fact that you just want to get things running, quickly
My suggestion: start off with not building these things yourself. Do not use pip. If possible, try to use the package manager of the Linux distribution in place and let it handle the installation of everything required for you, with a single command (e.g. sudo apt-get install python-matplotlib).
Disadvantages:
possibly old package versions, depending on the Linux distro in use
non-optimized builds (e.g. not built against e.g. Intel MKL or not leveraging OpenMP features or not using special instruction sets)
Advantages:
it quickly downloads, because packages are most likely cached near your machine
it quickly installs (these packages are pre-built, no compilation involved)
it just works
So, I hope you can just use aptitude or rpm or whatever on these machines and inherit the great work that the distribution package maintainers do for you, behind the scenes.
Once you are confident in your application and identified some bottleneck or issue, you might have reason to use a newer version of numpy/matplotlib/... or you might have reason to have a faster version of these, by creating an optimized build.
Edit: EB-related details of outlined approach
In the meantime we have learned that EB by default runs Amazon Linux which is based on Red Hat Enterprise Linux. Likewise, it uses yum as package manager and packages are in RPM format.
Amazon provides documentation about available packages. In Amazon Linux 2014.09, these packages are available: http://aws.amazon.com/de/amazon-linux-ami/2014.09-packages/
In this list we find
numpy-1.7.2
python-matplotlib-0.99.1.2
This version of matplotlib is very old, according to the changelog it is from September 2009: "2009-09-21 Tagged for release 0.99.1".
I did not anticipate it to be so old, but still, it might be sufficient for your needs. So we proceed with our plan (but I'd understand if that's a blocker).
Now, we have learned that system Python and EB Python are isolated from each other. That does not mean that EB Python cannot access system Python site packages. We just need it to tell so. A simple and clean method is to set up a proper directory structure with the packages that should be accessible to EB Python, and to communicate this directory to EB Python via sys.path.
Clearly, we need to customize the bootstrapping phase of EB containers. The available tools are documented here: http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/customize-containers-ec2.html
Obviously, we want to make use of the packages approach, and tell EB to install the numpy and python-matplotlib packages via yum. So the corresponding config file section should contain:
packages:
yum:
numpy: []
python-matplotlib: []
Explicitly mentioning numpy might not be necessary, it likely is a dependency of python-matplotlib.
Also, we need to make use of the commands section:
You can use the commands key to execute commands on the EC2 instance.
The commands are processed in alphabetical order by name, and they run
before the application and web server are set up and the application
version file is extracted.
The following three commands create above-mentioned directory, and set up symbolic links to the numpy/mpl installation paths (these paths hopefully are available in the moment these commands become executed):
commands:
00-create-dir:
command: "mkdir -p /opt/py26-selected-site-packages"
01-link-numpy:
command: "ln -s /usr/lib64/python2.6/site-packages/numpy /opt/py26-selected-site-packages/numpy"
02-link-mpl:
command: "ln -s /usr/lib64/python2.6/site-packages/matplotlib /opt/py26-selected-site-packages/matplotlib"
Two uncertainties: the AWS docs to not clarify that packages are processed before commands are executed. You have to try. It it does not work, use container_commands. Secondly, it is just an educated guess that /usr/lib64/python2.6/site-packages/matplotlib is available after installing python-matplotlib. It should be installed to this place, but it may end up somewhere else. Needs to be tested. Numpy should end up where specified as inferred from this article.
[UPDATE FROM SEB]
AWS documentation says "The cfn-init helper script processes these configuration sections in the following order: packages, groups, users, sources, files, commands, and then services."
http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-init.html
So, your approach is safe
[/UPDATE]
The crucial step, as pointed out in the comments to this answer, is to tell your Python app where to look for packages. Direct modification of sys.path before attempting to import is a reliable method to take control of this. The following code adds our special directory to the selection of directories in which Python looks out for packages, and then attempts to import matplotlib:
sys.path.append("/opt/py26-selected-site-packages")
from matplotlib import pyplot
The order in sys.path defines priorities, so in case there is any other matplotlib or numpy package available in one of the other directories, it might be a better idea to
sys.path.insert(0, "/opt/py26-selected-site-packages")
However, this should not be necessary if our whole approach was well thought-through.
To add to Jan-Philip Answer :
AWS Elastic Beanstalk is using Amazon Linux distribution (except for .Net environments). Amazon Linux uses the yum package manager. MatPlotLib is available in Amazon's software repository.
[ec2-user#ip-1-1-1-174 ~]$ yum list | grep matplot
python-matplotlib.x86_64 0.99.1.2-1.6.amzn1 amzn-main
If this version is the one you need for your application, I would try to simply modify your .ebextensions/software.config file and to add the package to the yum section of it:
packages:
yum:
python-matplotlib: []
python-devel: []
atlas-sse3-devel: []
lapack-devel: []
libpng-devel: []
freetype-devel: []
zlib-devel: []
A last note about AWS Elastic BeansTalk and SSH.
While Amazon gives you the possibility to SSH to your Elastic Beanstalk instances, you should use this possibility only for debugging purposes, to understand why your app failed or is not installing as suggested.
Other than that, your deployment must be 100% automatic. When Elastic Beanstalk (Auto Scaling to be precise) will scale out your infrastructure (add more instances) or scale it in (terminate instances) depending on your application workload, all your manual configuration will be lost.
Best practices is to not install SSH keys on your production environment, it further reduces the surface of attacks.
I might be a bit late to this question, but as AWS and a lot of the cloud service providers are moving into Docker and taking into consideration that you haven't specified the platform . I have a fast solution to your question:
Use the generic docker platform.
I created some images with Python, Numpy, Scipy and Matplotlib preinstalled, so you can directly pull and start using them with one line of code.
Python 2.7(This one also has the versions that you were specifying for numpy and matplotlib)
sudo docker pull chuseuiti/pynuscimat2.7
Python 3.4
sudo docker pull chuseuiti/pynusci
However you can create your own image or modify existing images.
In case you want to automate your instances, you can pass a Dockerfile to AWS with the definition of your image.
Tip, in case you don't know about docker:
It is need to login before been able to pull:
sudo docker login
After pulling the image, you can generate and work in a container created from an image with the next code:
sudo docker run -i -t chuseuiti/pynuscimat2.7 bash
PS. At least with the free tier AWS is always complaining about running out of time with scipy and matplotlib, it takes too much time to install them, that is why I use this option.

Ignore packagist.org on composer install | update

I'm using composer internally for managing internal software dependencies. Our repository server is on our private network and we aren't using any other package from any other repository than ours.
Every time you run
composer.phar [install | update]
It checks on packagist.org repositories after check our own repository. Beyond unnecessary, it takes longer when packagist is slow (or even down) or our internet connection is having a bad day.
Is there any way to tell composer to ignore checking for packagist repositories?
Yes, and it is even documented on https://getcomposer.org/doc/05-repositories.md#disabling-packagist-org
You may try to use this command:
$ composer config repositories.packagist false
You probably want to have a look at Satis: http://getcomposer.org/doc/articles/handling-private-packages-with-satis.md
It will make your life easier if you deal with a bit more of local/private packages, because otherwise you'd have to mention EVERY repository that might host required code. And you can use Satis to grab a copy of the versions into a ZIP file that can be hosted locally as well. See http://www.naderman.de/slippy/src/?file=2012-11-22-You-Thought-Composer-Couldnt-Do-That.html#13 for some hints of how to do it (press cursor keys left/right to skip through the presentation)
For extra bonus points, you'd add packagist.org as a Composer repository to Satis, require some needed packages, and set { "require-dependencies": true } to grab their dependencies as well. In your own code, you'd only set your Satis repository and disable Packagist.

rvm install fails with or without rvmrc

I'm using rvmrc with the following text:
rvm_path=/local/rvm
(on Ubuntu 11.10) but trying to install gives an obscure error:
$ bash < <(curl -s https://rvm.beginrescueend.com/install/rvm)
Successfully checked out branch ''
Current branch master is up to date.
Successfully pulled (rebased) from origin
: No such file or directory
Any ideas?
You have no need at all to set $rvm_path. You're using a multi-user install. Please follow the explicit instructions for the Multi-User install at https://rvm.io and remove any existing installations, remove /etc/rvmrc, /etc/profile.d/rvm.sh, and $HOME/.rvmrc. Comment out any RVM sourcing lines in your .bash_profile, and .bashrc and log out of the machine then back in. Then reinstall correctly. Setting the rvm_path has never been a requirement of the installer UNLESS you already have a Multi-User working installation in place, and you want to attempt to use a per-user install with it. THEN you would preset the $rvm_path to $HOME/.rvm in your own $HOME/.rvmrc, log out then back in and then attempt the install again. BUT, that is not a supported installation type. Which is why 99.999% of users will not need to set rvm_path at all.
The real problem was that the git configuration for auto-converting line endings was not set correctly which prevented any installation from working. It had nothing to do with using rvmrc settings.
The fix for this is simple (and comes straight from the github help page):
$ git config --global core.autocrlf input
Line endings are important in linux and by forgetting that setting, everything the rvm-install script was pulling from github had \r\n endings. I made that change so long ago on my work machine, I didn't even remember it -- but it was not set on my home system.
I'll leave it up in case someone else has the same problem.