(no such process) while deploying app via Ansible - ansible

I am trying to follow the Ansible Tutorial by Matt Wright. I have forked it and updated with latest Ansible modules here.
But I'm getting
msg: hello_flask: ERROR (no such process)
while running deploy.yml at -name: start app. I have a open issue here on github.
Why I am getting this error?

So you are seeing the error because supervisor is not finding the hello_flask application.
This is probably because you have a newer configuration for supervisor that doesn't include ini files.
If you look at one of the latest /etc/supervisor/supervisor.conf it actually includes *.conf files not *.ini files.
[include]
files = /etc/supervisor/conf.d/*.conf
Also, if you look at this Ansible task:
- name: create supervisor program config
action: template src=templates/supervisor.ini dest=/etc/supervisor/${app_name}.ini
notify:
- restart app
You can see that the configuration for hello_flash is being put under /etc/supervisor/hello_flash.ini
So make sure either that your supervisor.conf includes *.ini files. Or simply change this step to this:
- name: create supervisor program config
action: template src=templates/supervisor.ini dest=/etc/supervisor/conf.d/${app_name}.conf
notify:
- restart app
Hope it helps.

Related

How to add meta information to ansible playbook tasks

I have to display the ansible output to the user after a play is ran programatically. Currently I log the std_out to a json file using the stdout_callback=json option and then parse it. But I don't need to show all tasks from the tasks to the user but only a few.
For example, in the following tasks I only want to show the installing supervisor task, not the second one.
tasks:
-
name: 'Install Supervisor'
apt: 'pkg=supervisor state=latest update_cache=true'
-
name: 'Ensure the Supervisor service is enabled'
service: 'name=supervisor state=started enabled=yes'
Is there any way to
either omit it from the stdout, so that it never comes in the json log file.
I add some kind of meta information to the task, so that I can see that information in the log file and avoid showing that to user.

Ansible idempotency issue with unarchive and then modify extracted file

In one of the ansible roles we extract some tar.gz file and then we replace one of the extracted files with another one to fix some issue.
The problem is when we run ansible again, ansible is extracting the archive back again since the directory content is changed and naturally marking the task changed and also replaces the file again as expected.
So we have two "changes" now everytime we run the playbook...
How should I handle this issue to keep the operation idempotent?
Use exclude option to ignore certain paths, see documentation.
i.e.
- unarchive:
src: https://example.com/example.zip
dest: /usr/local/bin
remote_src: True
exclude: bad.config
creates might also suit you, unarchive step will not be run if specified path already exists on remote machine

How can I ensure that an Ansible shell command executes only once per host?

I want to be able to guarantee that after a long running shell command is executed successfully on a given host, it is not executed in subsequent playbook runs on that host.
I was happy to learn of the creates option to the Ansible shell task (see http://docs.ansible.com/ansible/shell_module.html); using this I can create a file after a shell command succeeds and not have that command execute in future runs:
- name: Install Jupiter theme
shell: wp theme install ~/downloads/jupiter-theme.zip --activate
&& touch ~/ansible-flags/install-jupiter-theme
args:
creates: ~/ansible-flags/install-jupiter-theme
As you can see, I have a directory ansible-flags for these control files in the home directory of my active user (deploy).
However, this is quite a kludge. Is there a better way to do this?
Also, the situation gets a lot more complicated when I need to run a step as a different user; in that case, I don't have access to the deploy home directory and its subdirectories. I could grant access, of course, but that's adding even more complexity. How would you recommend I deal with this?
Your playbook should be idempotent!
So either task should be safe to be executed multiple times (e.g. echo ok) or your should check whether you should execute it at all.
Your task may look like this:
- name: Install Jupiter theme
shell: wp theme is-installed jupiter || wp theme install ~/downloads/jupiter-theme.zip --activate
It will check if the jupiter theme is installed and will run wp theme install only if theme is not installed.
But this will mark the result of task as changed in any case.
To make it nice, you can do this:
- name: Install Jupiter theme
shell: wp theme is-installed jupiter && echo ThemeAlreadyInstalled || wp theme install ~/downloads/jupiter-theme.zip --activate
register: cmd_result
changed_when: cmd_result.stdout != "ThemeAlreadyInstalled"
First, it will check if the jupiter theme is already installed.
If this is the case, it will output ThemeAlreadyInstalled and exit.
Otherwise it will call wp theme install.
The task's result is registered into cmd_result.
We user changed_when parameter to state the fact that if ThemeAlreadyInstalled ansible shouldn't consider the task as changed, so it remains green in your playbook output.
If you do some preparation tasks before wp theme install (e.g. download theme), you may want to run the test as separate task to register the result and use when clauses in subsequent tasks:
- name: Check Jupiter theme is installed
shell: wp theme is-installed jupiter && echo Present || echo Absent
register: wp_theme
changed_when: false
- name: Download theme
get_url: url=...
when: wp_theme.stdout == "Absent"
- name: Install Jupiter theme
shell: wp theme install ~/downloads/jupiter-theme.zip --activate
when: wp_theme.stdout == "Absent"
Ansible itself is stateless, so whatever technique you use needs to be implement by yourself. There is no easier way like telling Ansible to only ever run a task once.
I think what you have already is pretty straight forward. Maybe use another path to check. I'm pretty sure the wp theme install will actually extract that zip to some location, which you then can use together with the creates option.
There are alternatives but nothing that makes it easier:
Create a script in any language you like, that checks for the theme and if it is not installed, install it. Instead of the shell task then you would execute the script with the script module.
Install a local fact in /etc/ansible/facts.d which checks if the theme in already installed. Then you could simply apply a condition based on that fact to the shell task.
Set up fact caching, then register the result of your shell task and store it as a fact. With fact caching enabled you can access the stored result on later playbook runs.
It only gets more complicated. The creates option is perfect for this scenario and if you use the location where the wp command extracted the zip to, it also is pretty clean.
Of course you need to grant access to that file, if you have a need to access it from another user account. Storing stuff in a users home directory with the permissions set to only be readable by the owner indeed is no ideal solution.

Amazon Web Service CodeDeploy appspec.yml problems

I have a Node.js application which is being automatically deployed to Amazon Web Service through Codeship using the CodeDeploy AWS deployment system.
During the deployment process I've set in my appspec.yml for the currently running web application to be stopped. Once the deployment is complete, I want the web application to be started up again.
os: linux
files:
- source: /
destination: /var/www/app2
hooks:
AfterInstall:
- location: bash_scripts/stop_forever.sh
runas: ec2-user
ApplicationStart:
- location: bash_scripts/start_forever.sh
runas: ec2-user
However I've not yet been able to have either of these scripts to be called successfully from the appspec.yml file during a deployment.
The current error I'm seeing in the AWS deployment agent log is
Error CodeScriptMissing
Script Name /var/scripts/stop_forever.sh
MessageScript does not exist at specified location: /var/scripts/stop_forever.sh
Log TailLifecycleEvent - ApplicationStop
This seems to refer to an older version of the appspec.yml file which was attempting to run these scripts in a different location. Even though I've changed the contents of the appspec.yml file in the deployed package, this error message remains the same on each deploy.
In addition to appspec.yml file listed above, I've also tried making the following changes:
Not listing a runas parameter for each hook
Referencing a script inside the deployed directory
Referencing a script outside the deployed directory
Having a version parameter initially set to 0.0
Unfortunately there is very little online in terms of appspec.yml troubleshooting, other than the AWS documentation.
What very obvious thing I am doing wrong?
The ApplicationStop hook is being called from the previously installed deployment before trying to run the current deployment appspec.yml file.
In order to prevent this from happening you'll have to remove any previously installed deployment from the server.
Stop the code deploy agent - sudo service codedeploy-agent stop
clear all deployments under /opt/codedeploy-agent/deployment-root
Restart the code deploy agent - sudo service codedeploy-agent start
There is another way documented in the AWS developer forums, which I think is preferable.
Use the --ignore-application-stop-failures option with the CLI tool while doing the deployment, it worked perfectly for me.
Example taken from the forum:
aws deploy create-deployment --application-name APPLICATION --deployment-group-name GROUP --ignore-application-stop-failures --s3-location bundleType=tar,bucket=BUCKET,key=KEY --description "Ignore ApplicationStop failures due to broken script"
https://forums.aws.amazon.com/thread.jspa?threadID=166904

Run PHP script after deployment on AWS Elastic Beanstalk

I've created a PHP script that generates a local.xml file for Magento with the required database settings and credentials. I need to run this after the application is deployed; however I cannot seem to figure out a way to do so. My understanding is that I need to create a .config file inside of a .ebextensions directory. Anyone have a solution?
Technically Josh is not correct. According to the documentation (http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/customize-containers-ec2.html#customize-containers-format-commands): the commands section .. "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 closest I am aware of is the "container_commands" section which "The commands in container_commands are processed in alphabetical order by name. They run after the application and web server have been set up and the application version file has been extracted, but before the application version is deployed."
I don't know of a way to truly run a script post deployment (which is why I was here looking for that answer).
Elastic Beanstalk will look files under /opt/elasticbeanstalk/hooks/appdeploy/post directory to run after deployment.
So you can make use of this and do:
commands:
create_post_dir:
command: "mkdir /opt/elasticbeanstalk/hooks/appdeploy/post"
ignoreErrors: true
files:
"/opt/elasticbeanstalk/hooks/appdeploy/post/job_after_deploy.sh":
mode: "000755"
owner: root
group: root
content: |
#!/usr/bin/env bash
/var/app/current
** run your php script here **
Yup, .ebextensions are what you are looking for. To see how to bundle the source, take a look at the sample applications. There is a PHP one you can look at as well.
For more info on .ebextensions, take a look at this page.
Here's an example of a custom command. This could go in a file called sample.config within the .ebextensions directory:
commands:
success_command:
command: echo "this will be ran after launching"
Be careful if you copy and paste YAML and double check the format. You can also use JSON which follows the similar format.

Resources