Files
tiny-forge/internal/workload/plugin/container.go
T
alexei.dolgolyov c8e71a0c34 refactor(plugin): centralize workload conversion + container cleanup
Three packages (api, reconciler, webhook) each carried a private 30-line
toPluginWorkload() copy that had drifted — only the api version logged
malformed public_faces JSON; the others swallowed it. Hoist the single
implementation to plugin.WorkloadFromStore() (convert.go); store is
already a plugin dependency so no new import edge or cycle forms.

Likewise the dockerfile and static sources each had a private
removeContainerByName() that disagreed (remove-all vs stop-at-first).
Docker enforces unique container names, so the two were equivalent for
every reachable state; converge on plugin.RemoveContainerByName()
(container.go, stop-at-first) with a note on why remove-all was moot.

Callers migrated; old copies removed. Adds convert_test.go pinning the
field-by-field contract and JSON edge cases.
2026-06-19 16:21:54 +03:00

36 lines
1.4 KiB
Go

package plugin
import "context"
// RemoveContainerByName is a best-effort cleanup of a name conflict before a
// CreateContainer retry: enumerate the managed containers and stop+remove the
// one whose name matches. Docker enforces unique container names per daemon,
// so at most one managed container can match — the loop returns after the
// first hit.
//
// Shared by the source plugins (dockerfile, static) that previously each kept
// their own copy. Those copies had diverged: the dockerfile copy removed every
// match (defending against a since-debunked "a partial deploy can leave more
// than one matching artifact" case), while the static copy stopped at the
// first. We deliberately converge on stop-at-first: ManagedContainer.Name is
// the primary Docker name (Names[0]), which the daemon keeps globally unique
// across every container state, so the remove-all loop could never actually
// match more than one container — the two behaviours are equivalent for every
// reachable state.
//
// Failures are intentionally swallowed: the caller treats this as opportunistic
// and re-attempts CreateContainer regardless.
func RemoveContainerByName(ctx context.Context, deps Deps, name string) {
containers, err := deps.Docker.ListContainers(ctx, nil)
if err != nil {
return
}
for _, c := range containers {
if c.Name == name {
deps.Docker.StopContainer(ctx, c.ID, 10)
deps.Docker.RemoveContainer(ctx, c.ID, true)
return
}
}
}