refactor container image resolution

This commit is contained in:
2026-08-22 16:04:32 +08:00
parent 0102fa6ce9
commit b163b48ae3
+35 -12
View File
@@ -395,13 +395,10 @@ type resolvedImage struct {
// 信息,随后从仓库摘要中解析出唯一的不可变引用。若仓库存在多个匹配摘要则报错,
// 以保证后续部署所用的引用是确定且唯一的。
func (u *Updater) pullAndResolveImage(ctx context.Context, imageReference string) (resolvedImage, error) {
named, err := reference.ParseNormalizedNamed(imageReference)
named, err := parseTaggedImageReference(imageReference)
if err != nil {
return resolvedImage{}, fmt.Errorf("parse container image reference: %w", err)
}
if _, ok := named.(reference.Tagged); !ok {
return resolvedImage{}, errors.New("--container-image requires a tag-qualified image reference")
}
if err := u.engine.Ping(ctx); err != nil {
return resolvedImage{}, err
}
@@ -412,15 +409,41 @@ func (u *Updater) pullAndResolveImage(ctx context.Context, imageReference string
if err != nil {
return resolvedImage{}, fmt.Errorf("inspect pulled backend image: %w", err)
}
if image.Platform.OS == "" || image.Platform.Architecture == "" {
return resolvedImage{}, errors.New("pulled backend image does not report an exact platform")
if err := validateImagePlatform(image.Platform); err != nil {
return resolvedImage{}, err
}
repository := reference.TrimNamed(named).Name()
immutableReference, digest, err := resolveRepositoryDigest(image.RepoDigests, repository)
if err != nil {
return resolvedImage{}, err
}
return resolvedImage{ImmutableReference: immutableReference, Digest: digest, Platform: image.Platform}, nil
}
func parseTaggedImageReference(imageReference string) (reference.Named, error) {
named, err := reference.ParseNormalizedNamed(imageReference)
if err != nil {
return nil, err
}
if _, ok := named.(reference.Tagged); !ok {
return nil, errors.New("--container-image requires a tag-qualified image reference")
}
return named, nil
}
func validateImagePlatform(platform containerengine.Platform) error {
if platform.OS == "" || platform.Architecture == "" {
return errors.New("pulled backend image does not report an exact platform")
}
return nil
}
func resolveRepositoryDigest(values []string, repository string) (string, string, error) {
matches := make(map[string]string)
for _, value := range image.RepoDigests {
for _, value := range values {
digested, err := reference.ParseNormalizedNamed(value)
if err != nil {
return resolvedImage{}, fmt.Errorf("parse pulled repository digest %q: %w", value, err)
return "", "", fmt.Errorf("parse pulled repository digest %q: %w", value, err)
}
withDigest, ok := digested.(reference.Digested)
if !ok || reference.TrimNamed(digested).Name() != repository {
@@ -429,15 +452,15 @@ func (u *Updater) pullAndResolveImage(ctx context.Context, imageReference string
matches[withDigest.Digest().String()] = value
}
if len(matches) == 0 {
return resolvedImage{}, fmt.Errorf("pulled backend image has no repository digest for %s", repository)
return "", "", fmt.Errorf("pulled backend image has no repository digest for %s", repository)
}
if len(matches) != 1 {
return resolvedImage{}, fmt.Errorf("pulled backend image has multiple repository digests for %s", repository)
return "", "", fmt.Errorf("pulled backend image has multiple repository digests for %s", repository)
}
for digest, immutableReference := range matches {
return resolvedImage{ImmutableReference: immutableReference, Digest: digest, Platform: image.Platform}, nil
return immutableReference, digest, nil
}
return resolvedImage{}, errors.New("repository digest resolution produced no result")
return "", "", errors.New("repository digest resolution produced no result")
}
// runContainerUpdate 根据事务当前状态执行容器后端更新的核心流程:启动目标容器,