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

Allow end-tasks, which will run when a workspace stops (timeout) #3966

Open
shaal opened this issue Apr 16, 2021 · 36 comments
Open

Allow end-tasks, which will run when a workspace stops (timeout) #3966

shaal opened this issue Apr 16, 2021 · 36 comments
Labels
aspect: product integration For any 3rd party integration requests feature: tasks meta: never-stale This issue can never become stale team: IDE team: webapp Issue belongs to the WebApp team type: feature request New feature or request

Comments

@shaal
Copy link
Contributor

shaal commented Apr 16, 2021

Similar to start-tasks I propose adding end-tasks.
End-tasks will get triggered and run when a workspace gets stopped (timeout)

Why it's necessary:

  • In a "regular" (non-gitpod) setup on a local machine, working on projects that store content and changes in a database is fairly straight forward. I can pull the database once, switch between different branches, make changes in the database, and continue working on the project for many days.
  • In a Gitpod setup, I can pull the database once, and any changes I make in the database will persist through timeout and a restart of a workspace. The next day (or minute) I want to work on a different branch so I start a NEW workspace, and poof! the database is gone.

How it works / Why it's a good idea:

  • Once end-tasks are available, I can make sure that a machine that is about to be stopped, can run a command that will store the important information / database / docker-image in a safe place. And in the next time I open a new workspace, I can choose fetching that database I saved.
  • I am sure there are many more scenarios possible that will be helpful for people once end-tasks feature is available.
@shaal
Copy link
Contributor Author

shaal commented May 30, 2021

Related issue: #4055
Technical details: #1961

@svenefftinge
Copy link
Member

hey @shaal, the feature makes absolute sense, trying to understand your particular use case better.
It sounds like you try to do two things

  1. persist in-memory state to disk before stop, so when I restart a workspace it has the same state again.
  2. keep state across multiple workspaces.

I have no questions regarding 2). I wonder what the scope of that state is is that per user per project? Or is it per project? (in which case I wonder if it should not be part of the init tasks or checked into git).

I would like to understand how you intend to surface to users why they have the state they are in and how they can control it. What would a user do if they want a clean slate for some reason or have a different DB schema, because they are working on some branch that has migrations.

These issues are generally the reason why I'd recommend creating fresh workspaces per branch and don't share such data across different project states. Within a workspace, I want to keep the state, of course. So when I stop it and later start it again it definitely should have the same DB state without question.

@chlbri
Copy link

chlbri commented Jul 13, 2021

I think for commit, because if you delete accidentally a workspace, you cannot react your changes. So I want a default commit and push with timestamps or slug to save in a new branch.

@shaal
Copy link
Contributor Author

shaal commented Jul 13, 2021

I created an example of end-task that I want to use:
shaal/DrupalPod#18

When a workspace shuts down - .gitpod/aws-backup.sh is called (creates a binary mysql backup and stores it in AWS)
When I open a new workspace where I want to use the previous' workspace's database - I'll run .gitpod/aws-restore.sh which will restore the latest backup for this branch.
Alternatively, I can run .gitpod/aws-restore [name_of_backup] to restore a specific named backup I created on a separate workspace.

@orellabac
Copy link

This will great. It will allow me to do some simple telemetry or housekeeping tasks!

@stale
Copy link

stale bot commented Oct 18, 2021

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the meta: stale This issue/PR is stale and will be closed soon label Oct 18, 2021
@shaal
Copy link
Contributor Author

shaal commented Oct 18, 2021

Can we please add the label meta: never-stale to this issue?

@stale stale bot removed the meta: stale This issue/PR is stale and will be closed soon label Oct 18, 2021
@gtsiolis gtsiolis added the meta: never-stale This issue can never become stale label Oct 19, 2021
@chlbri
Copy link

chlbri commented Oct 20, 2021 via email

@john-french
Copy link

I'm looking for this feature too and ended up here. My use case is as follows:

I'd like to use Gitpod in teaching an introductory programming course. These beginner students have enough on their plates trying to learn to code without having to learn Git (for now), so I'd forsee providing a shell script in the workspace which does git add/commit/push for them without blowing their minds. If I could run this from end-tasks it would be wonderful, their code would always get pushed to Github automatically, where I could trigger unit tests etc, without having to even mention the words "staging area" to my students.

@joepurdy
Copy link

This would unblock me on a number of different issues I've worked around in my own ways.

For starters we currently network a set of dependent workspaces together via Tailscale as Ephemeral Nodes. The issue lies in the fact that despite being "ephemeral" Tailscale doesn't perform housekeeping until as long as 48 hours later. This leads to long forgotten/deleted Gitpod instances lingering and causing duplicate hostnames.

Tailscale's official recommendation when you need a consistent hostname is to instead remove the node via an API call:

If you're using hostnames to refer to things, and need to have the node deleted as part of your workflow, then you can make an API call from your automation system.

Here is the API spec for that

Other than that, the cleanup of ephemeral nodes is a bit lazy, but they shouldn't linger more than a day or two.

With an end task in Gitpod we could automate that API call to clean-up the tailscale node before shutting down.


On a different note our developers often are working with persistent data in MySQL and even though it does persist through workspace restarts thanks to storing the data under the /workspace/mysql path there are times where one developer wishes they could share the latest DB dump with someone else. We've crudely solved this by a script to dump the database to cloud storage and another script to restore from a named DB dump. Sometimes we have team members forget to run this though and they lose the latest copy of their data.

End tasks could help here as well by automatically calling the script to have an autosave backup just in case.

@jetdream
Copy link

Our projects heavily rely on cloud infrastructure for development.

I see this feature extremely useful for cleaning up the associated cloud infrastructure
on start tasks we create AWS services instances using Terraform/Ansible - database, event bus, storage, stream processor etc
on end tasks we would destroy those instances

@jkaye2012
Copy link

We would like this feature as well. For us, the primary benefit would be cleaning up caches that are left around the workspace. This leads to workspaces taking a very long time to come back up (or, often, never coming back up at all). If we could hook an end task, automating a clean of the workspace would be trivial.

@pawlean
Copy link
Contributor

pawlean commented Mar 20, 2022

Thank you all for your input. I noticed that this wasn't in a team inbox, @shaal so I've just put it in the WebApp team.

WebApp team - if this doesn't belong to your team, can you move it to the correct inbox? I thought this may be one of those that requires input from every eng team... Your call!

@csweichel
Copy link
Contributor

In today's workspaces, prior to a regular shutdown all processes receive SIGTERM. They then have 15 seconds time before receiving SIGKILL. That's not quite as convenient as shutdown hooks, but helps to e.g. flush a DB to disk prior to shutdown.

@jkaye2012
Copy link

Interesting, one way to simulate a generic shutdown hook then would be to implement a daemon that we run locally that sleeps until it receives the SIGTERM, then fires the shutdown logic, correct?

@geropl
Copy link
Member

geropl commented Apr 7, 2022

@akosyakov Pulling you in because this is more of supervisor territory; webapp would just provide/approve the additions to the config.

Does this seems reasonable to implement?

@geropl geropl added team: webapp Issue belongs to the WebApp team team: IDE labels Apr 7, 2022
@geropl geropl removed this from 🍎 WebApp Team Apr 7, 2022
@loujaybee
Copy link
Member

loujaybee commented Sep 23, 2022

Adding to IDE team sync next week to see if we can pick up the open PR and get it completed.

No promises on timeline, but we'll take a look!

Related internal thread.

@csweichel
Copy link
Contributor

Relevant discussion: #11287 (comment)

@loujaybee
Copy link
Member

loujaybee commented Sep 27, 2022

Removing from IDE sync, as looks like @svenefftinge is looking into this ! 🙏 🚀

@karpa
Copy link

karpa commented Oct 1, 2022

I read that some users had success by using SIGTERM. Can you post a link or some instructions on how you do it?

@axonasif
Copy link
Member

axonasif commented Oct 2, 2022

Hey @karpa, until #11287 is deployed, you can use this snippet on your .gitpod.yml:

tasks:
  - name: Shutdown daemon
    command: |
      function shutdown() {
        # Do stuff here, for example
        docker-compose stop;
      }

      trap 'shutdown; exit' SIGTERM;
      printf '\033[3J\033c\033[3J%s\n' 'Waiting for SIGTERM ...';
      exec {sfd}<> <(:);
      until read -t 3600 -u $sfd; do continue; done;

@akosyakov
Copy link
Member

@karpa here is an example of how one can set it up till we have shutdown commands: https://github.com/akosyakov/gitpodify-docker-compose/blob/docker-compose_check/.gitpod.yml

@geropl geropl removed the status in 🍎 WebApp Team Oct 14, 2022
@geropl
Copy link
Member

geropl commented Oct 14, 2022

@svenefftinge on holidays, so took it out of progress for now.

@karpa
Copy link

karpa commented Oct 17, 2022

I used the code from both of you @akosyakov and @axonasif and adapted it to solve my problems. Thanks.

@loujaybee
Copy link
Member

Bumping this one again, as it has come up again in conversations with integration partners. Having this feature would be incredibly powerful for showcasing infrastructure spin up and tear down with Gitpod, especially in the context of ephemeral cloud infra environments as a natural extension of Gitpod. Again, let's see who can pick up the draft PR and get it over the line 🙏

@loujaybee
Copy link
Member

Linking this docs effort for workspace lifecycle updates:

Opportunity to document shutdown behaviours and hooks for users to listen to.

@akosyakov
Copy link
Member

I wonder whether anyone try to use existing Linux solution instead like init.d services. Here is a setup which start docker-compose daemon in a usual way [1].

There is no need for end tasks then, and users can port existing init.d service scripts to Gitpod, the normal command tasks is used to call out to start such service:

tasks:
   - command: service docker-compose start

@faermanj
Copy link

faermanj commented Jul 3, 2023

It would be great to be able to tear down cloud resources (k8s clusters, s3 buckets, ...) when environments are deleted. Currently we have to "prune" such resources manually, which is error prone and wasteful.

@akosyakov
Copy link
Member

akosyakov commented Jul 4, 2023

@faermanj Have you already tried to create a Gitpod task which on SIGTERM does it? All processes will receive SIGTERM signal on the workspace shutdown and have 15 seconds by default to gracefully terminate. You can also use init.d to perform it [1] in the background.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
aspect: product integration For any 3rd party integration requests feature: tasks meta: never-stale This issue can never become stale team: IDE team: webapp Issue belongs to the WebApp team type: feature request New feature or request
Projects
Status: No status
Development

Successfully merging a pull request may close this issue.