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

Lifecycle events proposal #3413

132 changes: 132 additions & 0 deletions docs/proposals/lifecycle_events.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
# Support execution of the commands based on lifecycle events.

## Abstract
Add support for the lifecycle events which can be defined in 2.0 devfiles.

Our proposed solution is to perform the postStart event as a part of the **odo push** command, and the preStop event as a part of the **odo delete** command.

Lifecycle bindings for specific events - https://github.com/devfile/kubernetes-api/issues/32


## Motivation
Devfiles support commands that can be triggered based on dev lifecycle events. Odo will need to support/execute these commands at appropriate times within the flow.

With the implementation of lifecycle events, stack creators will be able to leverage all the capabilities of devfiles when building the correct experience/features for their stacks.

## User Stories
Each lifecycle event would be suited to individual user stories. We propose that at least one issue is made for each of them for tracking and implementation purposes.

An issue has already been created for postStart: [container initiliazation support](https://github.com/openshift/odo/issues/2936)

## Design overview

The lifecycle events that have been implemented in Devfile 2.0 are generic. So their effect/meaning might be slightly different when applying them to a workspace (Che) or a single project (odo). However, this proposal will aim to provide a similar user experience within the scope of a single project.

Our proposal is that the postStart event will run as a part of **odo push**, and that the preStop event will run as a part of **odo delete**.


### The flow for **odo push** including the *postStart* lifecycle event will be as follows:
- Start the container(s) (as done today)
- postStart - Exec the specified command(s) in the container - one time only
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a note as this replaces the existing devInit in the devfile 1.0 support.

- Rest of the command execution (as we do today - exec commands for build/run/test/debug)


**Starting the container(s)**
- The containers specified in the Devfile are initialised and created if the component doesn’t already exist.

**postStart**
Copy link

@elsony elsony Jun 25, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Consider to add some implementation details on this design, e.g. before starting a given container in odo, we scan for all the events postStart events defined in the devfile and find out all the commands that uses the same container. This is the logic to identify the list of postStart event that is needed to run for a given container.
  2. Add error handling. What if the postStart command failed to execute, how do we handle it and how do we surface that error to the user.
  3. The type of container (i.e. the command group that links to a given container) may affect the behaviour, e.g. the postStart only gets executed in the first odo push in most cases for build containers (containers used by the build command) since build containers will stay up and running after the first push. However, for run containers, the container may or may not get restarted depending on the restart flag. So the postStart may gets executed again for run containers. What about containers used by debug and test group of commands? We may want to clarify the behaviour in this proposal.

Copy link

@elsony elsony Jun 29, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think point#1 and point#3 of #3413 (comment) have not been addressed yet.

Copy link
Contributor Author

@upLukeWeston upLukeWeston Jun 30, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand the premise of your point, but I have been struggling to think of any specific use cases where this would be a driving factor.
We (@EnriqueL8, @neeraj-laad, and I) have discussed the potential to be more granular in the solution by identifying which container specifically we are initialising, and whether or not there is a postStart command associated with it. This way we could better utilise the postStart commands and use it in cases where only some of the containers are being initialised.

A potential flow could be to check for postStart commands associated with a specific container when inititialising it, storing those commands in an Object(?) and then executing only those postStart commands when the containers have all finished initialising, in the order that they are defined in within the devfile. However, this isn't necessary for the basic implementation of the postStart event.
There could be room for such a feature though, and a case could be presented to argue the validity of changing the flow of odo push in order to accommodate such cases in a future implementation.

I will update the proposal to reflect this though, as it was definitely something we hadn't considered.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could we add yaml definitions of events here, as how it would refer components and commands.

- If the component is newly created, the postStart events are executed sequentially within the containers given in the Devfile.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you mean by sequentially? Do you mean if there are mutliple postStart events defined for a given container? If it is, do we executed sequentially based on the order of postStart event defined in a devfile?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. For example with the following devfile content:

...
commands:
  - exec:
      id: firstPostStartCmd
      commandLine: echo I am the first PostStart
      component: tools
      workingDir: ${CHE_PROJECTS_ROOT}/
      group:
        kind: init
commands:
  - exec:
      id: secondPostStartCmd
      commandLine: echo I am the second PostStart
      component: tools
      workingDir: ${CHE_PROJECTS_ROOT}/
      group:
        kind: init
...
events:
  postStart:
   - "firstPostStartCmd"
   - "secondPostStartCmd"

We would execute them in that order - first, then second. Presumably waiting for the previous one to complete before executing the next.

- If any of the *postStart* commands do fail, then we would exit the **odo push** and report the error that had occurred. If it had failed to execute one of the postStart commands, the **odo push** might behave differently to what the stack creator had intended, so we would bail out early.
- This functionality would also act as a replacement for `devInit` in devfile v1.0.

**Command Execution**
- After postStart, we’d run the usual build/run/test/debug commands (depending on what sort of odo push parameters the user has provided) as usual.


### The flow for **odo delete** including the *preStop* lifecycle event will be as follows:
- preStop - Exec the specified command(s) in the container
- Clean up the pod and deployment etc. (as done today)

**preStop**
- Exec the specified command(s) in their respective containers before deleting the deployment and any clean up begins.
- If any of the *preStop* commands do fail, then we would exit the **odo delete** and report the error that had occurred. If it had failed to execute one of the preStop commands, the **odo delete** might behave differently to what the stack creator had intended, so we would bail out early.


### Flow with example devfile:
```
schemaVersion: "2.0.0"
metadata:
name: test-devfile
projects:
- name: nodejs-web-app
git:
location: "https://github.com/che-samples/web-nodejs-sample.git"
components:
- container:
id: tools
image: quay.io/eclipse/che-nodejs10-ubi:nightly
name: "tools"
- container:
id: runtime
image: quay.io/eclipse/che-nodejs10-ubi:nightly
name: "runtime"
commands:
- exec:
id: download dependencies
commandLine: "npm install"
component: tools
workingDir: ${CHE_PROJECTS_ROOT}/nodejs-web-app/app
group:
kind: build
- exec:
id: run the app
commandLine: "nodemon app.js"
component: runtime
workingDir: ${CHE_PROJECTS_ROOT}/nodejs-web-app/app
group:
kind: run
- exec:
id: firstPostStartCmd
commandLine: echo I am the first PostStart
component: tools
workingDir: ${CHE_PROJECTS_ROOT}/
- exec:
id: secondPostStartCmd
commandLine: echo I am the second PostStart
component: tools
workingDir: ${CHE_PROJECTS_ROOT}/
- exec:
id: disconnectDatabase
commandLine: echo disconnecting from the database
component: tools
workingDir: ${CHE_PROJECTS_ROOT}/
events:
postStart:
- "firstPostStartCmd"
- "secondPostStartCmd"
preStop:
- "disconnectDatabase"

```

The example flow for **odo push** in this case would be:
- create the containers
- execute firstPostStartCmd within the tools container
- execute secondPostStartCmd within the tools container
- execute build command
- execute run command

The example flow for **odo delete** in this case would be:
- execute disconnectDatabase
- clean up the pod and deployment etc. (as done today)


### Conclusions:
- We think that the most important events are the postStart, and the preStop because they have clear, reasonable use case within odo’s flow.
- We aren’t fully conclusive on the necessity of preStart and postStop. They do not currently have a useful case within odo.

## Future Evolution

- *preStop* and *postStop* events are supported in Devfile 2.0, but aren't currently applicable to odo. In the future, a reason could arise where would benefit from these events.