feat(pre-deploy): add support for pre-deploy hook containers in service management, sync *all* containers to store

This commit is contained in:
Pasha Sviderski
2026-04-08 19:16:28 +10:00
parent cef047221c
commit 1c8b77054a
11 changed files with 508 additions and 298 deletions
+3
View File
@@ -21,6 +21,9 @@ type ContainerClient interface {
CreateContainer(
ctx context.Context, serviceID string, spec ServiceSpec, machineID string,
) (container.CreateResponse, error)
CreatePreDeployHookContainer(
ctx context.Context, serviceID string, spec ServiceSpec, machineID string,
) (container.CreateResponse, error)
ExecContainer(ctx context.Context, serviceNameOrID, containerNameOrID string, config ExecOptions) (int, error)
InspectContainer(ctx context.Context, serviceNameOrID, containerNameOrID string) (MachineServiceContainer, error)
StartContainer(ctx context.Context, serviceNameOrID, containerNameOrID string) error
+13 -1
View File
@@ -18,11 +18,16 @@ const (
// DockerNetworkName is the name of the Docker network used by uncloud. Keep the value in sync with NetworkName
// in internal/machine/docker/manager.go.
DockerNetworkName = "uncloud"
LabelManaged = "uncloud.managed"
LabelServiceID = "uncloud.service.id"
LabelServiceName = "uncloud.service.name"
LabelServiceMode = "uncloud.service.mode"
LabelServicePorts = "uncloud.service.ports"
// LabelHook marks a container as a deployment hook. The value indicates the hook type (e.g. LabelHookPreDeploy).
LabelHook = "uncloud.service.hook"
// LabelHookPreDeploy indicates that the container is a pre-deploy hook that runs before deploying the service.
LabelHookPreDeploy = "pre-deploy"
)
type Container struct {
@@ -181,10 +186,17 @@ func (c *ServiceContainer) ServiceName() string {
// ServiceMode returns the replication mode of the service this container belongs to.
func (c *ServiceContainer) ServiceMode() string {
return c.Config.Labels[LabelServiceMode]
return c.ServiceSpec.Mode
}
// IsHook returns true if the container is a deployment hook (e.g. pre-deploy).
func (c *ServiceContainer) IsHook() bool {
_, ok := c.Config.Labels[LabelHook]
return ok
}
// ServicePorts returns the ports this container publishes as part of its service.
// TODO: return ports from ServiceSpec to allow updating ingress ports without recreating containers.
func (c *ServiceContainer) ServicePorts() ([]PortSpec, error) {
encoded, ok := c.Config.Labels[LabelServicePorts]
if !ok {
+8 -5
View File
@@ -454,8 +454,8 @@ type PreDeployHook struct {
Command []string
// Env defines additional environment variables for the container, merged with the service's environment variables.
Env EnvVars `json:",omitempty"`
// Privileged gives extended privileges to the container.
Privileged bool `json:",omitempty"`
// Privileged overrides the container's privileged mode. nil means inherit from the service.
Privileged *bool `json:",omitempty"`
// Timeout is the maximum duration to wait for the command to complete. On timeout, the container is stopped
// and the deployment fails. If nil, a default timeout is used.
Timeout *time.Duration `json:",omitempty"`
@@ -505,10 +505,13 @@ type RunServiceResponse struct {
}
type Service struct {
ID string
Name string
Mode string
ID string
Name string
Mode string
// Containers is the regular long-running service containers.
Containers []MachineServiceContainer
// HookContainers are one-shot containers for deployment hooks (e.g. pre-deploy).
HookContainers []MachineServiceContainer
}
type MachineServiceContainer struct {