refactor container image resolution
This commit is contained in:
@@ -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 根据事务当前状态执行容器后端更新的核心流程:启动目标容器,
|
||||
|
||||
Reference in New Issue
Block a user