Browse code

LCOW: pull goes to correct stores

Signed-off-by: John Howard <jhoward@microsoft.com>

John Howard authored on 2017/05/18 05:33:33
Showing 7 changed files
... ...
@@ -40,7 +40,7 @@ type importExportBackend interface {
40 40
 }
41 41
 
42 42
 type registryBackend interface {
43
-	PullImage(ctx context.Context, image, tag string, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error
43
+	PullImage(ctx context.Context, image, tag, platform string, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error
44 44
 	PushImage(ctx context.Context, image, tag string, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error
45 45
 	SearchRegistryForImages(ctx context.Context, filtersArgs string, term string, limit int, authConfig *types.AuthConfig, metaHeaders map[string][]string) (*registry.SearchResults, error)
46 46
 }
... ...
@@ -6,6 +6,7 @@ import (
6 6
 	"fmt"
7 7
 	"io"
8 8
 	"net/http"
9
+	"runtime"
9 10
 	"strconv"
10 11
 	"strings"
11 12
 
... ...
@@ -17,6 +18,7 @@ import (
17 17
 	"github.com/docker/docker/api/types/versions"
18 18
 	"github.com/docker/docker/pkg/ioutils"
19 19
 	"github.com/docker/docker/pkg/streamformatter"
20
+	"github.com/docker/docker/pkg/system"
20 21
 	"github.com/docker/docker/registry"
21 22
 	"golang.org/x/net/context"
22 23
 )
... ...
@@ -85,6 +87,41 @@ func (s *imageRouter) postImagesCreate(ctx context.Context, w http.ResponseWrite
85 85
 	)
86 86
 	defer output.Close()
87 87
 
88
+	// TODO @jhowardmsft LCOW Support: Eventually we will need an API change
89
+	// so that platform comes from (for example) r.Form.Get("platform"). For
90
+	// the initial implementation, we assume that the platform is the
91
+	// runtime OS of the host. It will also need a validation function such
92
+	// as below which should be called after getting it from the API.
93
+	//
94
+	// Ensures the requested platform is valid and normalized
95
+	//func validatePlatform(req string) (string, error) {
96
+	//	req = strings.ToLower(req)
97
+	//	if req == "" {
98
+	//		req = runtime.GOOS // default to host platform
99
+	//	}
100
+	//	valid := []string{runtime.GOOS}
101
+	//
102
+	//	if runtime.GOOS == "windows" && system.LCOWSupported() {
103
+	//		valid = append(valid, "linux")
104
+	//	}
105
+	//
106
+	//	for _, item := range valid {
107
+	//		if req == item {
108
+	//			return req, nil
109
+	//		}
110
+	//	}
111
+	//	return "", fmt.Errorf("invalid platform requested: %s", req)
112
+	//}
113
+	//
114
+	// And in the call-site:
115
+	//	if platform, err = validatePlatform(platform); err != nil {
116
+	//		return err
117
+	//	}
118
+	platform := runtime.GOOS
119
+	if platform == "windows" && system.LCOWSupported() {
120
+		platform = "linux"
121
+	}
122
+
88 123
 	w.Header().Set("Content-Type", "application/json")
89 124
 
90 125
 	if image != "" { //pull
... ...
@@ -106,12 +143,13 @@ func (s *imageRouter) postImagesCreate(ctx context.Context, w http.ResponseWrite
106 106
 			}
107 107
 		}
108 108
 
109
-		err = s.backend.PullImage(ctx, image, tag, metaHeaders, authConfig, output)
109
+		err = s.backend.PullImage(ctx, image, tag, platform, metaHeaders, authConfig, output)
110 110
 	} else { //import
111 111
 		src := r.Form.Get("fromSrc")
112 112
 		// 'err' MUST NOT be defined within this block, we need any error
113 113
 		// generated from the download to be available to the output
114 114
 		// stream processing below
115
+		// TODO @jhowardmsft LCOW Support: This will need extending for the platform too.
115 116
 		err = s.backend.ImportImage(src, repo, tag, message, r.Body, output, r.Form["changes"])
116 117
 	}
117 118
 	if err != nil {
... ...
@@ -129,7 +129,12 @@ func (daemon *Daemon) pullForBuilder(ctx context.Context, name string, authConfi
129 129
 		pullRegistryAuth = &resolvedConfig
130 130
 	}
131 131
 
132
-	if err := daemon.pullImageWithReference(ctx, ref, nil, pullRegistryAuth, output); err != nil {
132
+	// TODO @jhowardmsft LCOW Support: For now, use the runtime operating system of the host.
133
+	// When it gets to the builder part, this will need revisiting. There would have to be
134
+	// some indication from the user either through CLI flag to build, or through an explicit
135
+	// mechanism in a dockerfile such as a parser directive extension or an addition to
136
+	// the FROM statement syntax.
137
+	if err := daemon.pullImageWithReference(ctx, ref, runtime.GOOS, nil, pullRegistryAuth, output); err != nil {
133 138
 		return nil, err
134 139
 	}
135 140
 	return daemon.GetImage(name)
... ...
@@ -30,7 +30,7 @@ type Backend interface {
30 30
 	FindNetwork(idName string) (libnetwork.Network, error)
31 31
 	SetupIngress(clustertypes.NetworkCreateRequest, string) (<-chan struct{}, error)
32 32
 	ReleaseIngress() (<-chan struct{}, error)
33
-	PullImage(ctx context.Context, image, tag string, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error
33
+	PullImage(ctx context.Context, image, tag, platform string, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error
34 34
 	CreateManagedContainer(config types.ContainerCreateConfig) (container.ContainerCreateCreatedBody, error)
35 35
 	ContainerStart(name string, hostConfig *container.HostConfig, checkpoint string, checkpointDir string) error
36 36
 	ContainerStop(name string, seconds *int) error
... ...
@@ -7,6 +7,7 @@ import (
7 7
 	"fmt"
8 8
 	"io"
9 9
 	"os"
10
+	"runtime"
10 11
 	"strings"
11 12
 	"syscall"
12 13
 	"time"
... ...
@@ -20,6 +21,7 @@ import (
20 20
 	containerpkg "github.com/docker/docker/container"
21 21
 	"github.com/docker/docker/daemon/cluster/convert"
22 22
 	executorpkg "github.com/docker/docker/daemon/cluster/executor"
23
+	"github.com/docker/docker/pkg/system"
23 24
 	"github.com/docker/libnetwork"
24 25
 	"github.com/docker/swarmkit/agent/exec"
25 26
 	"github.com/docker/swarmkit/api"
... ...
@@ -88,7 +90,13 @@ func (c *containerAdapter) pullImage(ctx context.Context) error {
88 88
 	pr, pw := io.Pipe()
89 89
 	metaHeaders := map[string][]string{}
90 90
 	go func() {
91
-		err := c.backend.PullImage(ctx, c.container.image(), "", metaHeaders, authConfig, pw)
91
+		// TODO @jhowardmsft LCOW Support: This will need revisiting as
92
+		// the stack is built up to include LCOW support for swarm.
93
+		platform := runtime.GOOS
94
+		if platform == "windows" && system.LCOWSupported() {
95
+			platform = "linux"
96
+		}
97
+		err := c.backend.PullImage(ctx, c.container.image(), "", platform, metaHeaders, authConfig, pw)
92 98
 		pw.CloseWithError(err)
93 99
 	}()
94 100
 
... ...
@@ -18,7 +18,7 @@ import (
18 18
 
19 19
 // PullImage initiates a pull operation. image is the repository name to pull, and
20 20
 // tag may be either empty, or indicate a specific tag to pull.
21
-func (daemon *Daemon) PullImage(ctx context.Context, image, tag string, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error {
21
+func (daemon *Daemon) PullImage(ctx context.Context, image, tag, platform string, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error {
22 22
 	// Special case: "pull -a" may send an image name with a
23 23
 	// trailing :. This is ugly, but let's not break API
24 24
 	// compatibility.
... ...
@@ -43,10 +43,10 @@ func (daemon *Daemon) PullImage(ctx context.Context, image, tag string, metaHead
43 43
 		}
44 44
 	}
45 45
 
46
-	return daemon.pullImageWithReference(ctx, ref, metaHeaders, authConfig, outStream)
46
+	return daemon.pullImageWithReference(ctx, ref, platform, metaHeaders, authConfig, outStream)
47 47
 }
48 48
 
49
-func (daemon *Daemon) pullImageWithReference(ctx context.Context, ref reference.Named, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error {
49
+func (daemon *Daemon) pullImageWithReference(ctx context.Context, ref reference.Named, platform string, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error {
50 50
 	// Include a buffer so that slow client connections don't affect
51 51
 	// transfer performance.
52 52
 	progressChan := make(chan progress.Progress, 100)
... ...
@@ -60,11 +60,10 @@ func (daemon *Daemon) pullImageWithReference(ctx context.Context, ref reference.
60 60
 		close(writesDone)
61 61
 	}()
62 62
 
63
-	// ------------------------------------------------------------------------------
64
-	// TODO @jhowardmsft LCOW. For now, use just the store for the host OS. This will
65
-	// need some work to complete - we won't know the platform until after metadata
66
-	// is pulled from the repository. This affects plugin as well to complete.
67
-	// ------------------------------------------------------------------------------
63
+	// Default to the host OS platform in case it hasn't been populated with an explicit value.
64
+	if platform == "" {
65
+		platform = runtime.GOOS
66
+	}
68 67
 
69 68
 	imagePullConfig := &distribution.ImagePullConfig{
70 69
 		Config: distribution.Config{
... ...
@@ -73,12 +72,13 @@ func (daemon *Daemon) pullImageWithReference(ctx context.Context, ref reference.
73 73
 			ProgressOutput:   progress.ChanOutput(progressChan),
74 74
 			RegistryService:  daemon.RegistryService,
75 75
 			ImageEventLogger: daemon.LogImageEvent,
76
-			MetadataStore:    daemon.stores[runtime.GOOS].distributionMetadataStore,
77
-			ImageStore:       distribution.NewImageConfigStoreFromStore(daemon.stores[runtime.GOOS].imageStore),
78
-			ReferenceStore:   daemon.stores[runtime.GOOS].referenceStore,
76
+			MetadataStore:    daemon.stores[platform].distributionMetadataStore,
77
+			ImageStore:       distribution.NewImageConfigStoreFromStore(daemon.stores[platform].imageStore),
78
+			ReferenceStore:   daemon.stores[platform].referenceStore,
79 79
 		},
80 80
 		DownloadManager: daemon.downloadManager,
81 81
 		Schema2Types:    distribution.ImageTypes,
82
+		Platform:        platform,
82 83
 	}
83 84
 
84 85
 	err := distribution.Pull(ctx, ref, imagePullConfig)
... ...
@@ -59,6 +59,9 @@ type ImagePullConfig struct {
59 59
 	// Schema2Types is the valid schema2 configuration types allowed
60 60
 	// by the pull operation.
61 61
 	Schema2Types []string
62
+	// Platform is the requested platform of the image being pulled to ensure it can be validated
63
+	// when the host platform supports multiple image operating systems.
64
+	Platform string
62 65
 }
63 66
 
64 67
 // ImagePushConfig stores push configuration.