mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Merge pull request #29001 from darrenstahlmsft/WindowsOnLinux
Block pulling Windows images on non-Windows daemons
This commit is contained in:
commit
c31f73abfd
3 changed files with 55 additions and 30 deletions
|
@ -142,9 +142,12 @@ func (s *imageConfigStore) RootFSFromConfig(c []byte) (*image.RootFS, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// fail immediately on windows
|
// fail immediately on Windows when downloading a non-Windows image
|
||||||
|
// and vice versa
|
||||||
if runtime.GOOS == "windows" && unmarshalledConfig.OS == "linux" {
|
if runtime.GOOS == "windows" && unmarshalledConfig.OS == "linux" {
|
||||||
return nil, fmt.Errorf("image operating system %q cannot be used on this platform", unmarshalledConfig.OS)
|
return nil, fmt.Errorf("image operating system %q cannot be used on this platform", unmarshalledConfig.OS)
|
||||||
|
} else if runtime.GOOS != "windows" && unmarshalledConfig.OS == "windows" {
|
||||||
|
return nil, fmt.Errorf("image operating system %q cannot be used on this platform", unmarshalledConfig.OS)
|
||||||
}
|
}
|
||||||
|
|
||||||
return unmarshalledConfig.RootFS, nil
|
return unmarshalledConfig.RootFS, nil
|
||||||
|
|
|
@ -534,15 +534,18 @@ func (p *v2Puller) pullSchema2(ctx context.Context, ref reference.Named, mfst *s
|
||||||
}
|
}
|
||||||
|
|
||||||
configChan := make(chan []byte, 1)
|
configChan := make(chan []byte, 1)
|
||||||
errChan := make(chan error, 1)
|
configErrChan := make(chan error, 1)
|
||||||
|
layerErrChan := make(chan error, 1)
|
||||||
|
downloadsDone := make(chan struct{})
|
||||||
var cancel func()
|
var cancel func()
|
||||||
ctx, cancel = context.WithCancel(ctx)
|
ctx, cancel = context.WithCancel(ctx)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
// Pull the image config
|
// Pull the image config
|
||||||
go func() {
|
go func() {
|
||||||
configJSON, err := p.pullSchema2Config(ctx, target.Digest)
|
configJSON, err := p.pullSchema2Config(ctx, target.Digest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errChan <- ImageConfigPullError{Err: err}
|
configErrChan <- ImageConfigPullError{Err: err}
|
||||||
cancel()
|
cancel()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -553,6 +556,7 @@ func (p *v2Puller) pullSchema2(ctx context.Context, ref reference.Named, mfst *s
|
||||||
configJSON []byte // raw serialized image config
|
configJSON []byte // raw serialized image config
|
||||||
downloadedRootFS *image.RootFS // rootFS from registered layers
|
downloadedRootFS *image.RootFS // rootFS from registered layers
|
||||||
configRootFS *image.RootFS // rootFS from configuration
|
configRootFS *image.RootFS // rootFS from configuration
|
||||||
|
release func() // release resources from rootFS download
|
||||||
)
|
)
|
||||||
|
|
||||||
// https://github.com/docker/docker/issues/24766 - Err on the side of caution,
|
// https://github.com/docker/docker/issues/24766 - Err on the side of caution,
|
||||||
|
@ -564,7 +568,7 @@ func (p *v2Puller) pullSchema2(ctx context.Context, ref reference.Named, mfst *s
|
||||||
// check to block Windows images being pulled on Linux is implemented, it
|
// check to block Windows images being pulled on Linux is implemented, it
|
||||||
// may be necessary to perform the same type of serialisation.
|
// may be necessary to perform the same type of serialisation.
|
||||||
if runtime.GOOS == "windows" {
|
if runtime.GOOS == "windows" {
|
||||||
configJSON, configRootFS, err = receiveConfig(p.config.ImageStore, configChan, errChan)
|
configJSON, configRootFS, err = receiveConfig(p.config.ImageStore, configChan, configErrChan)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", err
|
return "", "", err
|
||||||
}
|
}
|
||||||
|
@ -575,41 +579,52 @@ func (p *v2Puller) pullSchema2(ctx context.Context, ref reference.Named, mfst *s
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.config.DownloadManager != nil {
|
if p.config.DownloadManager != nil {
|
||||||
|
go func() {
|
||||||
|
var (
|
||||||
|
err error
|
||||||
|
rootFS image.RootFS
|
||||||
|
)
|
||||||
downloadRootFS := *image.NewRootFS()
|
downloadRootFS := *image.NewRootFS()
|
||||||
rootFS, release, err := p.config.DownloadManager.Download(ctx, downloadRootFS, descriptors, p.config.ProgressOutput)
|
rootFS, release, err = p.config.DownloadManager.Download(ctx, downloadRootFS, descriptors, p.config.ProgressOutput)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if configJSON != nil {
|
// Intentionally do not cancel the config download here
|
||||||
// Already received the config
|
// as the error from config download (if there is one)
|
||||||
return "", "", err
|
// is more interesting than the layer download error
|
||||||
}
|
layerErrChan <- err
|
||||||
select {
|
return
|
||||||
case err = <-errChan:
|
|
||||||
return "", "", err
|
|
||||||
default:
|
|
||||||
cancel()
|
|
||||||
select {
|
|
||||||
case <-configChan:
|
|
||||||
case <-errChan:
|
|
||||||
}
|
|
||||||
return "", "", err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if release != nil {
|
|
||||||
defer release()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
downloadedRootFS = &rootFS
|
downloadedRootFS = &rootFS
|
||||||
|
close(downloadsDone)
|
||||||
|
}()
|
||||||
|
} else {
|
||||||
|
// We have nothing to download
|
||||||
|
close(downloadsDone)
|
||||||
}
|
}
|
||||||
|
|
||||||
if configJSON == nil {
|
if configJSON == nil {
|
||||||
configJSON, configRootFS, err = receiveConfig(p.config.ImageStore, configChan, errChan)
|
configJSON, configRootFS, err = receiveConfig(p.config.ImageStore, configChan, configErrChan)
|
||||||
|
if err == nil && configRootFS == nil {
|
||||||
|
err = errRootFSInvalid
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
cancel()
|
||||||
|
select {
|
||||||
|
case <-downloadsDone:
|
||||||
|
case <-layerErrChan:
|
||||||
|
}
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-downloadsDone:
|
||||||
|
case err = <-layerErrChan:
|
||||||
return "", "", err
|
return "", "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
if configRootFS == nil {
|
if release != nil {
|
||||||
return "", "", errRootFSInvalid
|
defer release()
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if downloadedRootFS != nil {
|
if downloadedRootFS != nil {
|
||||||
|
|
|
@ -272,3 +272,10 @@ func (s *DockerSuite) TestPullLinuxImageFailsOnWindows(c *check.C) {
|
||||||
_, _, err := dockerCmdWithError("pull", "ubuntu")
|
_, _, err := dockerCmdWithError("pull", "ubuntu")
|
||||||
c.Assert(err.Error(), checker.Contains, "cannot be used on this platform")
|
c.Assert(err.Error(), checker.Contains, "cannot be used on this platform")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Regression test for https://github.com/docker/docker/issues/28892
|
||||||
|
func (s *DockerSuite) TestPullWindowsImageFailsOnLinux(c *check.C) {
|
||||||
|
testRequires(c, DaemonIsLinux, Network)
|
||||||
|
_, _, err := dockerCmdWithError("pull", "microsoft/nanoserver")
|
||||||
|
c.Assert(err.Error(), checker.Contains, "cannot be used on this platform")
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue