While trying to deploy a Django project with CodeDeploy for the first time, I keep getting the following error in the AfterInstall phase:
Error Code: ScriptFailed
Script Name: /setup.sh
Message: Script at specified location: /setup.sh failed with exit code 2
Log Tail: LifecycleEvent - AfterInstall
Script - /setup.sh
[stderr]python: can't open file 'setup_start.py': [Errno 2] No such file or directory
This is probably because I'm misunderstanding the files section of the AppSpec. Below is a snippet of what I'm doing for that section:
files:
- source: ./BlackBoxes
destination: project/BlackBoxes
- source: ./Documentation
destination: project/Documentation
- source: ./manage.py
destination: project
- source: ./setup_start.py
destination: project
...
I did make the project folder manually on the S3 bucket but none of the subfolders.
And the AfterInstall section:
hooks:
...
AfterInstall:
- location: /setup.sh
timeout: 180
What I originally thought source was supposed to mean was the relative path of the file/directory with respect to the root of the project directory on my local development machine. I also assumed that any folder needed that didn't exist on the S3 bucket would be created automatically. Clearly, I am misunderstanding something about CodeDeploy, most likely pertaining to the AppSpec file. What exactly am I doing wrong with the deployment and what am I supposed to be doing instead?
You're going wrong in the files section. This section is where you tell Code Deploy: "place this directory/file from my repo to this location on my EC2 instance". You only need to do this for stuff your deploying, you don't need to do this for deployment hook scripts. Refer to the docs for the fine details on this section.
In a hook, the location is the relative path to your hook script from the root of your repo. So /setup.sh isn't correct -> you need to give it the relative path. Again, the docs is the place to read more on this.
What I usually do is in the root of my repo, I create a folder called eg. scripts and I store the hook scripts there.
Say my repo directory structure looks like this:
application_code/
scripts/
appspec.yml
I can then set up my appspec.yml like this:
version: 0.0
os: linux
files:
- source: application_code
destination: /desired/code/location #path to where the code should be put on the instance
hooks:
ApplicationStop:
- location: scripts/some_script.sh
timeout: 300
runas: root
Code Deploy is simple to use once you've read the documentation comprehensively. Until then, you're going to keep encountering problems like this.
Best of luck! :)
Related
I am trying to deploy an application onto EC2 instances with AWS CodeDeploy. I am getting up to the point where CodeDeploy errors out at the BeforeInstall hook. The error message I am getting is related to a ScriptMissing. The exact error is:
Script does not exist at specified location: /opt/codedeploy-agent/deployment-root/1bfe51a8-151a-4366-8a3f-c061adb4bb90/d-X8N0B5IOE/deployment-archive/scripts\codedeploy\install_dependencies.sh
The odd thing is the file exists in my version control repository. So far I have tried changing the permissions of the script, and have also tried different method in the appspec.yml file in order to get CodeDeploy to recognize this file. All methods have failed. I tried the other solutions posted relating to this scenario but they do not seem to help me.
Do these script files int he appspec.yml also need to part of the zip file that CodeDeploy uses? Any advice would be appreciated. Below is the appspec.yml file.
Appspec
version: 0.0
os: linux
files:
- source: /
destination: /var/www/html
overwrite: true
hooks:
BeforeInstall:
- location: scripts/codedeploy/install_dependencies.sh
timeout: 300
runas: root
AfterInstall:
- location: scripts/codedeploy/install_composer_dependencies.sh
timeout: 300
runas: root
- location: scripts/codedeploy/start_server.sh
timeout: 30
runas: root
ApplicationStop:
- location: scripts/codedeploy/stop_server.sh
timeout: 30
runas: root
I had a similar problem. My paths was scripts/file-name.sh. I just removed 'scripts/' from location path and leave only .sh file names and it works for me.
My files are properly copied to an EC2 instance for deployments, but they are not copied to the destination. I've got at appspec.yml file like this:
ubuntu#ip:~$ cat /opt/coded*/deployment-root/*/*/de*/appspec.yml
version: 0.0
os: linux
# I also tried with source: /
files:
- source: .
destination: /home/ubuntu/
file_exists_behavior: OVERWRITE
# notes
# ------------------------------------------------------------------------------------
# To learn more about hooks, visit the docs here:
# https://docs.aws.amazon.com/codedeploy/latest/userguide/reference-appspec-file-structure-hooks.html#appspec-hooks-server
hooks:
BeforeInstall:
- location: scripts/install_dependencies
timeout: 300
runas: root
ApplicationStart:
- location: scripts/start_server
timeout: 300
runas: root
ApplicationStop:
- location: scripts/stop_server
timeout: 300
runas: root
I've also tried setting source to source: / with the same result; nothing's copied
And I see my files are all in that /opt/coded* etc. path. But why isn't the CodeDeploy agent copying my files to the destination? The Download bundle hook is good, and the only error I get is in the ApplicationStart hook when I need to actually access my files.
Note: I'm using GitHub as my revision storage, not S3, if that helps
Edit: something that might be useful to know is in my install_dependencies script, I run something along the lines of:
cd /home/ubuntu/
pip install -r requirements.txt
where the pip installation is the line where it can't find the files
Reasoning: https://docs.aws.amazon.com/codedeploy/latest/userguide/reference-appspec-file-example.html#appspec-file-example-server
The order of the hooks. The files are copied before the AfterInstall hook.
i am trying to deploy the python application through code-deploy to the ec2 instances
but during deployment i am facing this error
The deployment failed because a specified file already exists at this
location: /home/ubuntu/yello/manage.py
attaching my appsecfile also tried with overwrite but no luck
version: 0.0
os: linux
files:
- source: /
destination: /home/ubuntu/yello
overwrite: true
hooks:
AfterInstall:
- location: script/services.sh
timeout: 300
runas: ubuntu
can anyone help ?
This is a very common error so AWS public docs has a section for the same.
https://docs.aws.amazon.com/codedeploy/latest/userguide/troubleshooting-deployments.html#troubleshooting-same-files-different-app-name
Basically when creating the deployment, you need to select Overwrite the content option so the deployment does not fail (default behaviour). Details here:
https://docs.aws.amazon.com/codedeploy/latest/userguide/deployments-rollback-and-redeploy.html#deployments-rollback-and-redeploy-content-options
The default behaviour prevents two Deployments from two different CodeDeploy "Applications" writing the same file and possibly causing some sort of conflict.
cd /var/www/your-directory/public/funnel_webhooks/test/
sudo rm -rf clickfunnel.txt
After removing this file please release the change in the code pipeline.
Now you can specify file_exists_behavior in your appspec file. Allowed values are DISALLOW, OVERWRITE, or RETAIN.
version: 0.0
os: linux
files:
- source: /
destination: /home/ubuntu/yello
file_exists_behavior: OVERWRITE
I have two instances in AWS. One for production and one for homologation. I deploy automatically with CodeDeploy. I have two branches on BitBucket, the master and homolog. When I commit in the homolog deploy must go to the instance of homologation, and if I make a merge in the master deploy must be in the production stage.
To do the automatic deploy of Bitbucket to AWS there is a series of files that configure the deploy details. One of these files is the appspec.yml. According to AWS it is only possible to have an appspec.yml file.
This basic form file has the following structure:
version: 0.0
os: linux
files:
- source: /
destination: /var/www/html
hooks:
AfterInstall:
- location: deploy-scripts/install_dependencies.py
timeout: 300
runas: root
The problem is that for each instance I have a destination folder.
If I do the deploy on the homolog instance the destination folder should be var/www/html and for the production instance it should be var/www/html/test/
I tried to do it as below:
version: 0.0
os: linux
files:
- source: /
destination: deploy-scripts/destination.py
hooks:
AfterInstall:
- location: deploy-scripts/install_dependencies.py
timeout: 300
runas: root
That's the destination.py:
if os.environ['APPLICATION_NAME'] == 'ahimsa-store-homolog':
return '/var/www/html/'
elif os.environ['APPLICATION_NAME'] == 'ahimsa-store':
return '/var/www/html/teste/'
The above option does not work. How can I do this?
The files section of appspec.yml doesn't run scripts.
Move the required files to a temporary folder using the files section
Create a script that will move these files from the temporary location to the required destination depending on your requirements. As you suggested, using os.environ['APPLICATION_NAME'] for example.
Make sure your script sets correct file permissions after moving the files.
Include that script in the AfterInstall section, so the script can find the new files "installed" in the temporary location you choose. Also make sure it is before installing the dependencies!
Another option is to have a different appspec in each branch. It would make merging more difficult, but it could help.
I have the following defined in the appspec file -
hooks:
AfterInstall:
- location: afterInstall.sh
Following is the content of afterInstall.sh (I am trying to invoke a php file from the sh file) -
php afterInstall.php
Both the files afterInstall.sh and afterInstall.php are at the same level (outermost level) in the zip archive that I am uploading to S3 -
appspec.yml
afterInstall.sh
afterInstall.php
I am getting the following error -
Error Code ScriptFailed
Script Name afterInstall.sh
Message Script at specified location: afterInstall.sh failed with exit code 1
Log Tail LifecycleEvent - AfterInstall
Script - afterInstall.sh
[stderr]Could not open input file: afterInstall.php
I also tried by adding the following to the permissions section of the apppsec file -
permissions:
- object: .
pattern: "**"
owner: sandeepan
group: sandeepan
mode: 777
type:
- file
Note - I have the login credentials of the deployment instances using the sandeepan user.
I am a bit confused with what exactly the permissions section does. From http://docs.aws.amazon.com/codedeploy/latest/userguide/app-spec-ref-permissions.html,
The permissions section specifies how special permissions, if any,
should be applied to the files and directories/folders in the files
section after they are copied to the instance.
I also tried by specifying owner/group as root/root and runas: root against the afterInstall hook, but still getting the same error.
Update
I also tried by specifying the afterInstall.php file in the files section, and ensuring its permission and ownerships are correct -
- source: afterInstall.php
destination: /var/cake_1.2.0.6311-beta
At /var/cake_1.2.0.6311-beta -
-rwxrwxr-x 1 sandeepan sandeepan 26 Aug 1 08:55 afterInstall.php
I have no other clue what else should be done to fix this.
Note - I am able to deploy successfully if I do not call a php file from the afterInstall.sh
The root cause of the error is that the php file reference is incorrect. Your script assumes that the current working directory is the the destination folder, or the deployment archive folder.
This is a reasonable assumption, however neither of these is correct. On my Ubuntu server, the current working directory of the CodeDeploy shell invocation is actually /opt/codedeploy-agent. This explains why you get the "Could not open input file" error.
Since you are in the afterInstall lifecycle hook, all your files already exist in the final destination. To solve the problem, use the path specified in the destination: directive in your afterInstall.sh:
#!/bin/bash
php /var/cake_1.2.0.6311-beta/afterInstall.php
This will allow php to locate the correct file, and you deployment will run successfully.
Update:
If you want to run a file in the beforeInstall hook, the file must already exist on the system, and be referenced by a fixed path such as /tools.
This can be accomplished by one of the following:
Use a user-data script to download the script at instance launch time, or
'Baking' the script into the AMI image itself, and launching from that image.
In either case, the beforeInstall hook can then call the script from its fixed path, eg php /tools/beforeInstall.php.
I prefer option 1 in these cases. We maintain an S3 bucket with these type of assets, which are then maintained on S3, and downloaded to each instance at launch time. Any updates are pushed to S3, and are called for each new instance launch.
The object entry can be an directory or file, current setting "." matches to the CodeDeploy deployment archive directory not the destination where the scripts were copied to. So probably you can try to use the file destination directory as the object.
And since the CodeDeploy deployment archive directory contains all the files from customer's bundle. I'm not quite sure about your file directory, but if all the objects inside the deployment archive directory are directories, probably the type filed can be changed to directory.
The file section looks like the following structure, and this section specifies the names of files that should be copied to the instance during the deployment's Install event.
files:
- source: source-file-location
destination: destination-file-location
While the hook section looks like the following structure, The hooks section of the AppSpec file contains mappings that link deployment lifecycle event hooks to one or more scripts. If an event hook is not present, then no operation is executed for that event. This section is required only if you will be running scripts as part of the deployment.
hooks:
deployment-lifecycle-event-name
- location: script-location
timeout: timeout-in-seconds
runas: user-name