Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Code deploy agent runs the wrong files in case of multiple deployments having same file path and name #80

Closed
MojoJojo opened this issue Sep 22, 2016 · 9 comments

Comments

@MojoJojo
Copy link

Hi
I've noticed this several times - consider a scenario where two deployments/revisions have a same file in the same path:

  1. In the first revision, the the file is scripts/ApplicationStop/application-stop.sh
  2. In the second revision (For a different application), if you have similar file in the same location (but different) content, code deploy will execute the previous file (file from the previous deployment).
  3. You deploy another revision, and this time code deploy will pick up the previous file (from revision 2).

we have a standard script/directory structure that we follow across deployments and this really causes code deploy agent to either run the wrong scripts or mess up data in some cases.

@MojoJojo
Copy link
Author

Here's excerpts from my log files:

[2016-09-22 18:44:43.242] [d-IJBVSF6XH]LifecycleEvent - ApplicationStop
[2016-09-22 18:44:43.242] [d-IJBVSF6XH]Script - scripts/ApplicationStop/application-stop.sh
[2016-09-22 18:44:43.276] [d-IJBVSF6XH][stdout]xxxxxxxxxxxxxx stop/waiting
[2016-09-22 18:44:51.539] [d-IJBVSF6XH]LifecycleEvent - BeforeInstall
[2016-09-22 18:44:51.541] [d-IJBVSF6XH]Script - scripts/BeforeInstall/api-before-install.sh
[2016-09-22 18:44:52.933] [d-IJBVSF6XH][stdout]Try deleting system user and group [xxxxxxxx:xxxxxxxxxx]
[2016-09-22 18:44:52.935] [d-IJBVSF6XH][stdout]Deleting system user: xxxxxxxxxx
[2016-09-22 18:45:00.625] [d-IJBVSF6XH]LifecycleEvent - AfterInstall
[2016-09-22 18:45:00.625] [d-IJBVSF6XH]Script - scripts/AfterInstall/api-after-install.sh
[2016-09-22 18:45:00.691] [d-IJBVSF6XH][stdout]Preparing...                          ########################################
[2016-09-22 18:45:00.702] [d-IJBVSF6XH][stdout]Creating system group: xxxxxxxxxxx
[2016-09-22 18:45:00.728] [d-IJBVSF6XH][stdout]Creating system user: xxxxxxx in xxxxxxxx with xxxxxxxxxxxx user-daemon and shell /bin/false
[2016-09-22 18:45:00.750] [d-IJBVSF6XH][stdout]Updating / installing...
[2016-09-22 18:45:04.148] [d-IJBVSF6XH][stdout]xxxxxxxxxx-1-1               ########################################
[2016-09-22 18:45:05.572] [d-IJBVSF6XH]LifecycleEvent - ApplicationStart
[2016-09-22 18:45:05.572] [d-IJBVSF6XH]Script - scripts/ApplicationStart/api-application-start.sh
[2016-09-22 18:45:05.632] [d-IJBVSF6XH][stdout]Starting xxxxxxxxxxxxx: [  OK  ]
[2016-09-22 18:45:07.115] [d-IJBVSF6XH]LifecycleEvent - ValidateService
[2016-09-22 18:45:07.115] [d-IJBVSF6XH]Script - scripts/ValidateService/api-validate-service.sh
[2016-09-22 18:45:07.427] [d-IJBVSF6XH][stdout]xxxxxxxxxxxxx (pid  32452) is running...```

Notice the second line where it says scripts/ApplicationStop/application-stop.sh. The actual appspec taken from the same deployment (by ssh'ing into the instance):

version: 0.0
os: linux
hooks:
  AfterInstall:
    - location: scripts/AfterInstall/api-after-install.sh
      timeout: 300
      runas: root
  ApplicationStart:
    - location: scripts/ApplicationStart/api-application-start.sh
      timeout: 300
      runas: root
  ApplicationStop:
    - location: scripts/ApplicationStop/api-application-stop.sh
      timeout: 300
      runas: root
  BeforeInstall:
    - location: scripts/BeforeInstall/api-before-install.sh
      timeout: 300
      runas: root
  ValidateService:
    - location: scripts/ValidateService/api-validate-service.sh
      timeout: 300
      runas: root
files:
  - source: content/xxxxxxxx-1-1.noarch.rpm
    destination: /home/ec2-user
permissions:```

Notice the name of the application stop script.

@feverLu
Copy link
Contributor

feverLu commented Sep 23, 2016

Hi,

This is actually expected behavior. ApplicationStop lifecycle event is supposed to run the script from last successful revision, cause the lifecycle event is trying to stop the application revision installed last time. All other lifecycle events run scripts from the current revision. A more detailed explanation is here: http://docs.aws.amazon.com/codedeploy/latest/userguide/app-spec-ref-hooks.html

This ApplicationStop lifecycle event occurs even before the application revision is downloaded. You can use this event if you want to gracefully stop the application or remove currently installed packages in preparation of a deployment. The AppSpec file and scripts used for this deployment lifecycle event are from the last successfully deployed application revision.

Thanks,
Binbin

@ghost
Copy link

ghost commented Oct 6, 2016

But how to deal with it? For example, I have a wrong script set in ApplicationStop section. Now, everytime I deploy (or rollback), it call the wrong script. Then, the new deployment is stopped ....

I have delete this wrong script from my EC2 instance. But nothing changes.

How can I really stop this wrong script from running?

@ghost
Copy link

ghost commented Oct 6, 2016

I found the answer:

Call the create-deployment command, set the --ignore-application-stop-failures option, and deploy the application revision again.

http://docs.aws.amazon.com/zh_cn/codedeploy/latest/userguide/troubleshooting-deployments.html#troubleshooting-deployments-applicationstop

@MojoJojo
Copy link
Author

MojoJojo commented Oct 6, 2016

Alternatively, you can delete all the files/directories located at /opt/codedeploy-agent/deployment-root and restart the code deploy agent.

@MojoJojo
Copy link
Author

MojoJojo commented Oct 6, 2016

Just for record, I resolved my issue by creating two different applications -one for backend, one for frontend. Both the applications get downloaded to different folders on each machine (different folders under /opt/codedeploy-agent/deployment-rootand now the scripts don't interfere.

Think I'm gonna close this issue.

@MojoJojo MojoJojo closed this as completed Oct 6, 2016
@ghost
Copy link

ghost commented Oct 6, 2016

Thanks

@cristina0botez
Copy link

I'm quite baffled as to why this is expected behaviour... Let's say I have revisionA that uses Apache and MySQL so revisionA.ApplicationStop will stop these applications. Then you replace MySQL with Postgres for revisionB so when you want to install revisionB, you'll want to stop Postgres not MySQL (which you might have already uninstalled)... or, perhaps you'd want to automate this even more so you'd want to uninstall MySQL and install Postgres in revisionB.ApplicationStop.
It's interesting that others have not pointed this out...

@huribeir
Copy link

huribeir commented Nov 7, 2018

@cristina0botez the key element here is to take into consideration that CodeDeploy has been designed to automate your deployments end-to-end. To that point and using your example:

  • revisionA has been deployed and left MySQL/Apache running
  • revisionA.ApplicationStop has instructions on how to stop those 2 components

When revisionB deployment starts, in theory MySQL/Apache are still running, so those are the ones that need stopping. That's why revisionA.ApplicationStop will be run. In your first example, you have implicitly assumed that the activities to replace MySQL with Postgres have been manually done outside of CodeDeploy. A revisionB deployment could look like this:

  • revisionA.ApplicationStop stops MySQL/Apache
  • revisonB.BeforeInstall removes MySQL and install/configures Postgres
  • revisionB.ApplicationStart starts Postgres/Apache
  • revisionB.ApplicationStop has instructions on how to stop Postgres/Apache, but will only be used in the next deployment.

I agree this can be slightly confusing at first, but from a development perspective it's probably easier to have your revision package designed as a single self-contained unit (i.e. with instructions that comprise the full lifecycle of the application) rather than having to figure out later how to properly stop something that's been already running. I hope this makes sense!! :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants