Update logic to choose manifest from manifest list to check
for os version on Windows. Separate the logic for windows
and unix to keep unix logic the same.
Signed-off-by: Derek McGowan <derek@mcgstyle.net>
| ... | ... |
@@ -708,29 +708,20 @@ func (p *v2Puller) pullManifestList(ctx context.Context, ref reference.Named, mf |
| 708 | 708 |
} |
| 709 | 709 |
|
| 710 | 710 |
logrus.Debugf("%s resolved to a manifestList object with %d entries; looking for a os/arch match", ref, len(mfstList.Manifests))
|
| 711 |
- var manifestDigest digest.Digest |
|
| 712 |
- // TODO @jhowardmsft LCOW Support: Need to remove the hard coding in LCOW mode. |
|
| 713 |
- lookingForOS := runtime.GOOS |
|
| 714 |
- if system.LCOWSupported() {
|
|
| 715 |
- lookingForOS = "linux" |
|
| 716 |
- } |
|
| 717 |
- for _, manifestDescriptor := range mfstList.Manifests {
|
|
| 718 |
- // TODO(aaronl): The manifest list spec supports optional |
|
| 719 |
- // "features" and "variant" fields. These are not yet used. |
|
| 720 |
- // Once they are, their values should be interpreted here. |
|
| 721 |
- if manifestDescriptor.Platform.Architecture == runtime.GOARCH && manifestDescriptor.Platform.OS == lookingForOS {
|
|
| 722 |
- manifestDigest = manifestDescriptor.Digest |
|
| 723 |
- logrus.Debugf("found match for %s/%s with media type %s, digest %s", runtime.GOOS, runtime.GOARCH, manifestDescriptor.MediaType, manifestDigest.String())
|
|
| 724 |
- break |
|
| 725 |
- } |
|
| 726 |
- } |
|
| 727 | 711 |
|
| 728 |
- if manifestDigest == "" {
|
|
| 712 |
+ manifestMatches := filterManifests(mfstList.Manifests) |
|
| 713 |
+ |
|
| 714 |
+ if len(manifestMatches) == 0 {
|
|
| 729 | 715 |
errMsg := fmt.Sprintf("no matching manifest for %s/%s in the manifest list entries", runtime.GOOS, runtime.GOARCH)
|
| 730 | 716 |
logrus.Debugf(errMsg) |
| 731 | 717 |
return "", "", errors.New(errMsg) |
| 732 | 718 |
} |
| 733 | 719 |
|
| 720 |
+ if len(manifestMatches) > 1 {
|
|
| 721 |
+ logrus.Debugf("found multiple matches in manifest list, choosing best match %s", manifestMatches[0].Digest.String())
|
|
| 722 |
+ } |
|
| 723 |
+ manifestDigest := manifestMatches[0].Digest |
|
| 724 |
+ |
|
| 734 | 725 |
manSvc, err := p.repo.Manifests(ctx) |
| 735 | 726 |
if err != nil {
|
| 736 | 727 |
return "", "", err |
| ... | ... |
@@ -3,11 +3,27 @@ |
| 3 | 3 |
package distribution |
| 4 | 4 |
|
| 5 | 5 |
import ( |
| 6 |
+ "runtime" |
|
| 7 |
+ |
|
| 6 | 8 |
"github.com/docker/distribution" |
| 7 | 9 |
"github.com/docker/distribution/context" |
| 10 |
+ "github.com/docker/distribution/manifest/manifestlist" |
|
| 11 |
+ "github.com/sirupsen/logrus" |
|
| 8 | 12 |
) |
| 9 | 13 |
|
| 10 | 14 |
func (ld *v2LayerDescriptor) open(ctx context.Context) (distribution.ReadSeekCloser, error) {
|
| 11 | 15 |
blobs := ld.repo.Blobs(ctx) |
| 12 | 16 |
return blobs.Open(ctx, ld.digest) |
| 13 | 17 |
} |
| 18 |
+ |
|
| 19 |
+func filterManifests(manifests []manifestlist.ManifestDescriptor) []manifestlist.ManifestDescriptor {
|
|
| 20 |
+ var matches []manifestlist.ManifestDescriptor |
|
| 21 |
+ for _, manifestDescriptor := range manifests {
|
|
| 22 |
+ if manifestDescriptor.Platform.Architecture == runtime.GOARCH && manifestDescriptor.Platform.OS == runtime.GOOS {
|
|
| 23 |
+ matches = append(matches, manifestDescriptor) |
|
| 24 |
+ |
|
| 25 |
+ logrus.Debugf("found match for %s/%s with media type %s, digest %s", runtime.GOOS, runtime.GOARCH, manifestDescriptor.MediaType, manifestDescriptor.Digest.String())
|
|
| 26 |
+ } |
|
| 27 |
+ } |
|
| 28 |
+ return matches |
|
| 29 |
+} |
| ... | ... |
@@ -3,13 +3,19 @@ |
| 3 | 3 |
package distribution |
| 4 | 4 |
|
| 5 | 5 |
import ( |
| 6 |
+ "fmt" |
|
| 6 | 7 |
"net/http" |
| 7 | 8 |
"os" |
| 9 |
+ "runtime" |
|
| 10 |
+ "sort" |
|
| 11 |
+ "strings" |
|
| 8 | 12 |
|
| 9 | 13 |
"github.com/docker/distribution" |
| 10 | 14 |
"github.com/docker/distribution/context" |
| 15 |
+ "github.com/docker/distribution/manifest/manifestlist" |
|
| 11 | 16 |
"github.com/docker/distribution/manifest/schema2" |
| 12 | 17 |
"github.com/docker/distribution/registry/client/transport" |
| 18 |
+ "github.com/docker/docker/pkg/system" |
|
| 13 | 19 |
"github.com/sirupsen/logrus" |
| 14 | 20 |
) |
| 15 | 21 |
|
| ... | ... |
@@ -55,3 +61,57 @@ func (ld *v2LayerDescriptor) open(ctx context.Context) (distribution.ReadSeekClo |
| 55 | 55 |
} |
| 56 | 56 |
return rsc, err |
| 57 | 57 |
} |
| 58 |
+ |
|
| 59 |
+func filterManifests(manifests []manifestlist.ManifestDescriptor) []manifestlist.ManifestDescriptor {
|
|
| 60 |
+ version := system.GetOSVersion() |
|
| 61 |
+ |
|
| 62 |
+ // TODO @jhowardmsft LCOW Support: Need to remove the hard coding in LCOW mode. |
|
| 63 |
+ lookingForOS := runtime.GOOS |
|
| 64 |
+ osVersion := fmt.Sprintf("%d.%d.%d", version.MajorVersion, version.MinorVersion, version.Build)
|
|
| 65 |
+ if system.LCOWSupported() {
|
|
| 66 |
+ lookingForOS = "linux" |
|
| 67 |
+ osVersion = "" |
|
| 68 |
+ } |
|
| 69 |
+ |
|
| 70 |
+ var matches []manifestlist.ManifestDescriptor |
|
| 71 |
+ for _, manifestDescriptor := range manifests {
|
|
| 72 |
+ if manifestDescriptor.Platform.Architecture == runtime.GOARCH && manifestDescriptor.Platform.OS == lookingForOS {
|
|
| 73 |
+ if !versionMatch(manifestDescriptor.Platform.OSVersion, osVersion) {
|
|
| 74 |
+ continue |
|
| 75 |
+ } |
|
| 76 |
+ matches = append(matches, manifestDescriptor) |
|
| 77 |
+ |
|
| 78 |
+ logrus.Debugf("found match for %s/%s with media type %s, digest %s", runtime.GOOS, runtime.GOARCH, manifestDescriptor.MediaType, manifestDescriptor.Digest.String())
|
|
| 79 |
+ } |
|
| 80 |
+ } |
|
| 81 |
+ sort.Stable(manifestsByVersion(matches)) |
|
| 82 |
+ return matches |
|
| 83 |
+} |
|
| 84 |
+ |
|
| 85 |
+func versionMatch(actual, expected string) bool {
|
|
| 86 |
+ // Check whether actual and expected are equivalent, or whether |
|
| 87 |
+ // expected is a version prefix of actual. |
|
| 88 |
+ return actual == "" || expected == "" || actual == expected || strings.HasPrefix(actual, expected+".") |
|
| 89 |
+} |
|
| 90 |
+ |
|
| 91 |
+type manifestsByVersion []manifestlist.ManifestDescriptor |
|
| 92 |
+ |
|
| 93 |
+func (mbv manifestsByVersion) Less(i, j int) bool {
|
|
| 94 |
+ if mbv[i].Platform.OSVersion == "" {
|
|
| 95 |
+ return false |
|
| 96 |
+ } |
|
| 97 |
+ if mbv[j].Platform.OSVersion == "" {
|
|
| 98 |
+ return true |
|
| 99 |
+ } |
|
| 100 |
+ // TODO: Split version by parts and compare |
|
| 101 |
+ // TODO: Prefer versions which have a greater version number |
|
| 102 |
+ return false |
|
| 103 |
+} |
|
| 104 |
+ |
|
| 105 |
+func (mbv manifestsByVersion) Len() int {
|
|
| 106 |
+ return len(mbv) |
|
| 107 |
+} |
|
| 108 |
+ |
|
| 109 |
+func (mbv manifestsByVersion) Swap(i, j int) {
|
|
| 110 |
+ mbv[i], mbv[j] = mbv[j], mbv[i] |
|
| 111 |
+} |