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

introduce service hooks #12166

Merged
merged 1 commit into from
Oct 7, 2024
Merged

introduce service hooks #12166

merged 1 commit into from
Oct 7, 2024

Conversation

ndeloof
Copy link
Contributor

@ndeloof ndeloof commented Sep 26, 2024

What I did

Added support for post_start and pre_stop lifecycle hooks to services

demo: https://asciinema.org/a/Oh1ZFu2IERd3Fo4nK6lcSAhwS

Related issue

(not mandatory) A picture of a cute animal, if possible in relation to what you did
image

@ndeloof ndeloof requested review from a team, glours and jhrotko and removed request for a team September 26, 2024 14:02
@ndeloof ndeloof marked this pull request as ready for review September 30, 2024 07:05
@ndeloof ndeloof force-pushed the service_hooks branch 4 times, most recently from b870947 to 0aacddf Compare September 30, 2024 07:30
go.mod Outdated
@@ -193,4 +193,4 @@ require (
tags.cncf.io/container-device-interface v0.8.0 // indirect
)

replace github.com/compose-spec/compose-go/v2 => github.com/compose-spec/compose-go/v2 v2.2.1-0.20240926141145-d3fd7d94aa31
replace github.com/compose-spec/compose-go/v2 => github.com/ndeloof/compose-go/v2 v2.0.1-0.20240924090029-29a100a62f5f
Copy link
Contributor

Choose a reason for hiding this comment

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

leaving this comment here not to forget to delete this after compose-spec is bumped

Comment on lines +305 to +310
for _, hook := range service.PreStop {
err := s.runHook(ctx, container, *service, hook, nil)
if err != nil {
return err
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

We are always iterating over all hooks for PreStop, PostStart, etc.
I think it would make sense to add a function that encapsulates this in hook.go.

func (s composeService) ExecuteHooks(ctx context.Context, container moby.Container, service types.ServiceConfig, listener api.ContainerEventListener, hooks []types.ServiceHook) error {
	for _, hook := range hooks {
		err := s.runHook(ctx, container, service, hook, listener)
		if err != nil {
			return err
		}
	}
	return nil
}

@@ -85,7 +85,8 @@ func (s *composeService) down(ctx context.Context, projectName string, options a

err = InReverseDependencyOrder(ctx, project, func(c context.Context, service string) error {
serviceContainers := containers.filter(isService(service))
err := s.removeContainers(ctx, serviceContainers, options.Timeout, options.Volumes)
serv := project.Services[service]
Copy link
Contributor

@jhrotko jhrotko Oct 2, 2024

Choose a reason for hiding this comment

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

We could add a validation that the service exists here. Since this is the place where we get its value becoming easier later on for debugging.

serv, ok := project.Services[service] 
if !ok {
  return fmt.Error() ....
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

as we run inside InReverseDependencyOrder service is guaranteed to exist (actually, InReverseDependencyOrder could pass a *ServiceConfig, but this could have impact on immutability)

service is passed as a pointer down to

if service != nil {
, as this same method is used to also stop orphaned container, where we don't have a defined service so need the ability to pass nil

case <-tick.C:
inspect, err := s.apiClient().ContainerExecInspect(ctx, exec.ID)
if err != nil {
return nil
Copy link
Contributor

@jhrotko jhrotko Oct 2, 2024

Choose a reason for hiding this comment

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

Might have missed something, but shouldn't we return the error in this case? I see the same is done for ContainerExecStart. But in line 84 we do not ignore these errors

@@ -309,32 +320,32 @@ func (s *composeService) stopContainer(ctx context.Context, w progress.Writer, c
return nil
}

func (s *composeService) stopContainers(ctx context.Context, w progress.Writer, containers []moby.Container, timeout *time.Duration) error {
func (s *composeService) stopContainers(ctx context.Context, w progress.Writer, serv *types.ServiceConfig, containers []moby.Container, timeout *time.Duration) error {
Copy link
Contributor

@jhrotko jhrotko Oct 2, 2024

Choose a reason for hiding this comment

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

nit: rename to serv -> service for consistency

wOut := utils.GetWriter(func(line string) {
listener(api.ContainerEvent{
Type: api.HookEventLog,
Container: getContainerNameWithoutProject(container) + " ->",
Copy link
Contributor

@jhrotko jhrotko Oct 2, 2024

Choose a reason for hiding this comment

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

I would propose to change the -> to the name of the hook + index? we could pass it as a variable. If all hooks have the same "signature" -> might be complicated to understand from which hook the log comes from

Copy link
Contributor Author

Choose a reason for hiding this comment

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

hooks have no name so far (to be debated)
I wanted here to distinguish hook output from main logs without making the prefix a looooooong line, as this will remain for the whole compose execution after hook completed

Copy link
Contributor

Choose a reason for hiding this comment

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

how about we choose an emoji for each hook? 😆

Copy link
Contributor Author

Choose a reason for hiding this comment

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

My first implementation was using 🪝 but this won't run well on a Windows terminal

@jhrotko
Copy link
Contributor

jhrotko commented Oct 2, 2024

Really cool stuff @ndeloof 😊

@ndeloof ndeloof mentioned this pull request Oct 4, 2024
3 tasks
Copy link
Contributor

@glours glours left a comment

Choose a reason for hiding this comment

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

Sounds good to me 👍
Glad we finally have the first implementation of hooks mechanism 🥳

Signed-off-by: Nicolas De Loof <[email protected]>
@ndeloof ndeloof merged commit 82b41b9 into docker:main Oct 7, 2024
28 checks passed
@ndeloof ndeloof deleted the service_hooks branch October 7, 2024 14:07
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

Successfully merging this pull request may close these issues.

3 participants