mirror of
https://github.com/docker/compose.git
synced 2026-06-28 04:03:48 +00:00
feat: add stop lifecycle hook for external providers
Provider-backed services were silently skipped on `docker compose stop`, leaving external resources running after the user expected the stack to be paused (e.g. after Ctrl+C during `up --watch`). Compose now invokes `<provider> compose stop <service>` for providers that advertise a `stop` block in their `metadata` subcommand output. Providers that do not advertise stop (or do not implement metadata at all) are silently skipped, preserving backward compatibility with existing providers that pre-date this hook. Closes #13772 Signed-off-by: Guillaume Lours <glours@users.noreply.github.com>
This commit is contained in:
parent
8e0d5e17a7
commit
672dc14d29
7 changed files with 235 additions and 14 deletions
|
|
@ -74,8 +74,14 @@ func composeCommand() *cobra.Command {
|
|||
downCmd.Flags().String("name", "", "Name of the database to be deleted")
|
||||
_ = downCmd.MarkFlagRequired("name")
|
||||
|
||||
c.AddCommand(upCmd, downCmd)
|
||||
c.AddCommand(metadataCommand(upCmd, downCmd))
|
||||
stopCmd := &cobra.Command{
|
||||
Use: "stop",
|
||||
Run: stop,
|
||||
Args: cobra.ExactArgs(1),
|
||||
}
|
||||
|
||||
c.AddCommand(upCmd, downCmd, stopCmd)
|
||||
c.AddCommand(metadataCommand(upCmd, downCmd, stopCmd))
|
||||
return c
|
||||
}
|
||||
|
||||
|
|
@ -96,21 +102,29 @@ func down(_ *cobra.Command, _ []string) {
|
|||
fmt.Printf(`{ "type": "error", "message": "Permission error" }%s`, lineSeparator)
|
||||
}
|
||||
|
||||
func metadataCommand(upCmd, downCmd *cobra.Command) *cobra.Command {
|
||||
func stop(_ *cobra.Command, _ []string) {
|
||||
if marker := os.Getenv("PROVIDER_STOP_MARKER"); marker != "" {
|
||||
_ = os.WriteFile(marker, []byte("stopped"), 0o600)
|
||||
}
|
||||
}
|
||||
|
||||
func metadataCommand(upCmd, downCmd, stopCmd *cobra.Command) *cobra.Command {
|
||||
return &cobra.Command{
|
||||
Use: "metadata",
|
||||
Run: func(cmd *cobra.Command, _ []string) {
|
||||
metadata(upCmd, downCmd)
|
||||
metadata(upCmd, downCmd, stopCmd)
|
||||
},
|
||||
Args: cobra.NoArgs,
|
||||
}
|
||||
}
|
||||
|
||||
func metadata(upCmd, downCmd *cobra.Command) {
|
||||
func metadata(upCmd, downCmd, stopCmd *cobra.Command) {
|
||||
metadata := ProviderMetadata{}
|
||||
metadata.Description = "Manage services on AwesomeCloud"
|
||||
metadata.Up = commandParameters(upCmd)
|
||||
metadata.Down = commandParameters(downCmd)
|
||||
stopParams := commandParameters(stopCmd)
|
||||
metadata.Stop = &stopParams
|
||||
jsonMetadata, err := json.Marshal(metadata)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
|
@ -134,9 +148,10 @@ func commandParameters(cmd *cobra.Command) CommandMetadata {
|
|||
}
|
||||
|
||||
type ProviderMetadata struct {
|
||||
Description string `json:"description"`
|
||||
Up CommandMetadata `json:"up"`
|
||||
Down CommandMetadata `json:"down"`
|
||||
Description string `json:"description"`
|
||||
Up CommandMetadata `json:"up"`
|
||||
Down CommandMetadata `json:"down"`
|
||||
Stop *CommandMetadata `json:"stop,omitempty"`
|
||||
}
|
||||
|
||||
type CommandMetadata struct {
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ the resource(s) needed to run a service.
|
|||
If `provider.type` doesn't resolve into any of those, Compose will report an error and interrupt the `up` command.
|
||||
|
||||
To be a valid Compose extension, provider command *MUST* accept a `compose` command (which can be hidden)
|
||||
with subcommands `up` and `down`.
|
||||
with subcommands `up` and `down`. It *MAY* additionally implement a `stop` subcommand to support `docker compose stop`.
|
||||
|
||||
## Up lifecycle
|
||||
|
||||
|
|
@ -107,6 +107,20 @@ into its runtime environment.
|
|||
`down` lifecycle is equivalent to `up` with the `<provider> compose --project-name <NAME> down <SERVICE>` command.
|
||||
The provider is responsible for releasing all resources associated with the service.
|
||||
|
||||
## Stop lifecycle
|
||||
|
||||
When the user runs `docker compose stop`, Compose invokes `<provider> compose --project-name <NAME> stop <SERVICE>` for each
|
||||
provider-backed service in reverse dependency order. The provider should pause the resource without releasing it, so a later
|
||||
`docker compose start` or `docker compose up` can resume it. Any `setenv` JSON message returned during `stop` is ignored,
|
||||
since dependent services are also stopping.
|
||||
|
||||
The `stop` hook is opt-in: Compose invokes it only when the provider declares a `stop` block in its `metadata` subcommand
|
||||
output. Providers that do not advertise `stop` in metadata (or do not implement the `metadata` subcommand at all) are
|
||||
silently skipped during `docker compose stop`, preserving backward compatibility with providers that pre-date this hook.
|
||||
|
||||
The `--timeout` flag of `docker compose stop` applies only to container services; provider stop hooks are not subject to
|
||||
this timeout and are responsible for managing their own shutdown duration.
|
||||
|
||||
## Provide metadata about options
|
||||
|
||||
Compose extensions *MAY* optionally implement a `metadata` subcommand to provide information about the parameters accepted by the `up` and `down` commands.
|
||||
|
|
@ -153,6 +167,16 @@ The expected JSON output format is:
|
|||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"stop": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "name",
|
||||
"description": "Name of the database to be stopped",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -160,6 +184,7 @@ The top elements are:
|
|||
- `description`: Human-readable description of the provider
|
||||
- `up`: Object describing the parameters accepted by the `up` command
|
||||
- `down`: Object describing the parameters accepted by the `down` command
|
||||
- `stop`: Object describing the parameters accepted by the `stop` command (optional)
|
||||
|
||||
And for each command parameter, you should include the following properties:
|
||||
- `name`: The parameter name (without `--` prefix)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue