fix: recreate containers only if spec changed by comparing spec hash

This commit is contained in:
Pavel Sviderski
2025-03-19 13:11:04 +10:00
parent bd8bcbd2f9
commit fb01604d21
8 changed files with 285 additions and 140 deletions
+33 -5
View File
@@ -40,17 +40,22 @@ func (cli *Client) CreateContainer(
}
containerName := fmt.Sprintf("%s-%s", spec.Name, suffix)
// TODO: calculate the spec hash and set it as a label to detect changes in the service spec.
specHash, err := spec.ImmutableHash()
if err != nil {
return resp, fmt.Errorf("calculate immutable hash for service spec: %w", err)
}
config := &container.Config{
Cmd: spec.Container.Command,
Entrypoint: spec.Container.Entrypoint,
Hostname: containerName,
Image: spec.Container.Image,
Labels: map[string]string{
api.LabelServiceID: serviceID,
api.LabelServiceName: spec.Name,
api.LabelServiceMode: spec.Mode,
api.LabelManaged: "",
api.LabelServiceID: serviceID,
api.LabelServiceName: spec.Name,
api.LabelServiceMode: spec.Mode,
api.LabelServiceSpecHash: specHash,
api.LabelManaged: "",
},
}
if spec.Mode == "" {
@@ -335,3 +340,26 @@ func (cli *Client) RemoveContainer(
return nil
}
type ContainerSpecStatus string
const ContainerUpToDate ContainerSpecStatus = "up-to-date"
const ContainerNeedsUpdate ContainerSpecStatus = "needs-update"
const ContainerNeedsRecreate ContainerSpecStatus = "needs-recreate"
func CompareContainerToSpec(ctr api.Container, spec api.ServiceSpec) (ContainerSpecStatus, error) {
specHash, err := spec.ImmutableHash()
if err != nil {
return "", fmt.Errorf("calculate immutable hash for service spec: %w", err)
}
// Is the hash label is unset, there is no easy way to compare its configuration with the spec,
// so let's recreate as well.
if ctr.Config.Labels[api.LabelServiceSpecHash] != specHash {
return ContainerNeedsRecreate, nil
}
// TODO: compare mutable properties such as memory or CPU limits when they are implemented.
return ContainerUpToDate, nil
}