Restore: фолбэк pull по тегу, если образ по digest удалён из реестра
Общий pull падал целиком (minio/minio удалён с Docker Hub), create не проходил. Теперь при ошибке образы тянутся по одному, для недоступных по digest закрепление снимается, а при полном отказе в todo попадает подсказка. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
97c7051021
commit
7e29fb11eb
1 file changed
+47
-2
@@ -54,6 +54,7 @@ func (r *restorer) restoreCompose(c manifest.Category) error {
|
||||
|
||||
if err := compose("pull", "--ignore-buildable", "--quiet"); err != nil {
|
||||
r.warn("%s: pull: %v", c.Name, err)
|
||||
r.pullFallback(c, compose)
|
||||
}
|
||||
if hasBuilt(info) {
|
||||
if err := compose("build"); err != nil {
|
||||
@@ -94,6 +95,46 @@ func hasBuilt(info *manifest.Compose) bool {
|
||||
|
||||
// writePinFile пишет compose.restore.yml с образами по digest. Пустая строка — закреплять нечего.
|
||||
func (r *restorer) writePinFile(c manifest.Category) (string, error) {
|
||||
return r.writePinFileSkip(c, nil)
|
||||
}
|
||||
|
||||
// pullFallback вызывается, когда общий pull не удался (например, образ по digest
|
||||
// удалён из реестра — так случилось с minio/minio на Docker Hub). Тянет сервисы
|
||||
// по одному; для тех, что не нашлись по digest, снимает закрепление и пробует
|
||||
// тег из исходного compose-файла.
|
||||
func (r *restorer) pullFallback(c manifest.Category, compose func(...string) error) {
|
||||
var failed []string
|
||||
for svc, img := range c.Compose.Images {
|
||||
if img.Built {
|
||||
continue
|
||||
}
|
||||
if err := compose("pull", "--quiet", svc); err != nil {
|
||||
failed = append(failed, svc)
|
||||
}
|
||||
}
|
||||
if len(failed) == 0 {
|
||||
return
|
||||
}
|
||||
slices.Sort(failed)
|
||||
skip := map[string]bool{}
|
||||
for _, svc := range failed {
|
||||
skip[svc] = true
|
||||
}
|
||||
if _, err := r.writePinFileSkip(c, skip); err != nil {
|
||||
r.warn("%s: не удалось переписать %s: %v", c.Name, pinFile, err)
|
||||
return
|
||||
}
|
||||
for _, svc := range failed {
|
||||
if err := compose("pull", "--quiet", svc); err != nil {
|
||||
r.warn("%s: образ сервиса %s недоступен ни по digest, ни по тегу: %v", c.Name, svc, err)
|
||||
r.todo = append(r.todo, fmt.Sprintf("%s: образ сервиса %s недоступен в реестре (возможно, удалён или переехал, напр. minio/minio → quay.io/minio/minio). Поправьте image в compose-файле и выполните `docker compose up -d`", c.Name, svc))
|
||||
continue
|
||||
}
|
||||
r.warn("%s: сервис %s: образ по digest недоступен, взят по тегу из compose-файла (версия может отличаться)", c.Name, svc)
|
||||
}
|
||||
}
|
||||
|
||||
func (r *restorer) writePinFileSkip(c manifest.Category, skip map[string]bool) (string, error) {
|
||||
var services []string
|
||||
for name := range c.Compose.Images {
|
||||
services = append(services, name)
|
||||
@@ -105,16 +146,20 @@ func (r *restorer) writePinFile(c manifest.Category) (string, error) {
|
||||
n := 0
|
||||
for _, svc := range services {
|
||||
img := c.Compose.Images[svc]
|
||||
if img.Built || img.Digest == "" {
|
||||
if img.Built || img.Digest == "" || skip[svc] {
|
||||
continue
|
||||
}
|
||||
fmt.Fprintf(&b, " %q:\n image: %q\n", svc, img.Digest)
|
||||
n++
|
||||
}
|
||||
p := filepath.Join(c.Compose.Dir, pinFile)
|
||||
if n == 0 {
|
||||
if skip != nil {
|
||||
// файл уже подключён через -f: оставляем валидный пустой
|
||||
return p, os.WriteFile(p, []byte("services: {}\n"), 0o644)
|
||||
}
|
||||
return "", nil
|
||||
}
|
||||
p := filepath.Join(c.Compose.Dir, pinFile)
|
||||
return p, os.WriteFile(p, []byte(b.String()), 0o644)
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user