diff --git a/pkg/configurer/windows.go b/pkg/configurer/windows.go index f961d2a7..ff74d30c 100644 --- a/pkg/configurer/windows.go +++ b/pkg/configurer/windows.go @@ -60,7 +60,7 @@ func (c WindowsConfigurer) InstallMCRLicense(h os.Host, lic string) error { // InstallMCR install MCR on Windows. func (c WindowsConfigurer) InstallMCR(h os.Host, engineConfig commonconfig.MCRConfig) error { - version := "latest" + version := windowsInstallerVersion(engineConfig.Channel) installerPath, getInstallerErr := GetInstaller(engineConfig.InstallURLWindows) if getInstallerErr != nil { @@ -124,6 +124,25 @@ func isExitCode3010(err error) bool { return err != nil && strings.Contains(err.Error(), "non-zero exit code: 3010") } +// windowsInstallerVersion returns the version token to pass as DOCKER_VERSION +// to install.ps1. For non-FIPS channels the repo publishes only +// docker-latest.zip so "latest" is correct. For FIPS channels (suffix /fips) +// the repo publishes docker-+fips.zip but no docker-latest+fips.zip, +// so the version must be extracted from the channel string. +func windowsInstallerVersion(channel string) string { + if !strings.HasSuffix(channel, "/fips") { + return "latest" + } + ch := strings.TrimSuffix(channel, "/fips") + parts := strings.Split(ch, "-") + for i, p := range parts { + if len(p) > 0 && p[0] >= '0' && p[0] <= '9' { + return strings.Join(parts[i:], "-") + } + } + return "latest" +} + // Reboot triggers an immediate forced restart by scheduling a SYSTEM-context // one-shot task that runs 'shutdown /r /f /t 5', then immediately triggering // and deleting it within the 5-second countdown window. diff --git a/pkg/configurer/windows_test.go b/pkg/configurer/windows_test.go new file mode 100644 index 00000000..94900e93 --- /dev/null +++ b/pkg/configurer/windows_test.go @@ -0,0 +1,32 @@ +package configurer + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestWindowsInstallerVersion(t *testing.T) { + tests := []struct { + channel string + want string + }{ + // Standard channels — always "latest"; docker-latest.zip is published + {"stable-29.2", "latest"}, + {"stable-25.0", "latest"}, + {"ee-stable-29.2", "latest"}, + // FIPS channels — version extracted; only docker-+fips.zip is published + {"stable-29.2.1/fips", "29.2.1"}, + {"stable-29.4.1/fips", "29.4.1"}, + {"test-29.4.1/fips", "29.4.1"}, + // FIPS RC channel + {"test-29.4.1-rc3/fips", "29.4.1-rc3"}, + // FIPS channel with no parseable version — falls back to latest + {"stable/fips", "latest"}, + } + for _, tt := range tests { + t.Run(tt.channel, func(t *testing.T) { + require.Equal(t, tt.want, windowsInstallerVersion(tt.channel), "channel=%q", tt.channel) + }) + } +}