agent/config/os_family_windows.go (72 lines of code) (raw):
//go:build windows
// +build windows
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may
// not use this file except in compliance with the License. A copy of the
// License is located at
//
// http://aws.amazon.com/apache2.0/
//
// or in the "license" file accompanying this file. This file is distributed
// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.
package config
import (
"fmt"
"github.com/aws/amazon-ecs-agent/agent/statemanager/dependencies"
"github.com/cihub/seelog"
"github.com/pkg/errors"
"golang.org/x/sys/windows"
"golang.org/x/sys/windows/registry"
)
const (
// The os-family for windows is of the format "WINDOWS_SERVER_<Release>_<FULL or CORE>"
osFamilyFormat = "WINDOWS_SERVER_%s_%s"
windowsServerCore = "CORE"
windowsServerFull = "FULL"
unsupportedWindowsOSFamily = "windows"
installationTypeServerCore = "Server Core"
installationTypeServer = "Server"
ecsWinRegistryRootKey = registry.LOCAL_MACHINE
ecsWinRegistryRootPath = `SOFTWARE\Microsoft\Windows NT\CurrentVersion`
)
var (
winRegistry dependencies.WindowsRegistry
// osReleaseFromBuildNumber is the mapping from build number to the Windows release.
// Reference- https://docs.microsoft.com/en-us/windows-server/get-started/windows-server-release-info
osReleaseFromBuildNumber = map[int]string{
14393: "2016",
17763: "2019",
19041: "2004",
19042: "20H2",
20348: "2022",
26100: "2025",
}
// windowsGetVersionFunc is the method used to obtain information about current Windows version.
windowsGetVersionFunc = windows.RtlGetVersion
)
func init() {
winRegistry = dependencies.StdRegistry{}
}
// getInstallationType returns the installation type as either CORE or FULL.
func getInstallationType(installationType string) (string, error) {
switch installationType {
case installationTypeServer:
return windowsServerFull, nil
case installationTypeServerCore:
return windowsServerCore, nil
default:
return "", errors.Errorf("unsupported installation type: %s", installationType)
}
}
// GetOSFamily returns the operating system family string.
// On Windows, it would be of the format "WINDOWS_SERVER_<Release>_<FULL or CORE>"
// In case of any exception this method just returns "windows" as operating system family.
func GetOSFamily() string {
// Find the build number of the os on which agent is running.
versionInfo := windowsGetVersionFunc()
buildNumber := int(versionInfo.BuildNumber)
osRelease, ok := osReleaseFromBuildNumber[buildNumber]
if !ok {
seelog.Errorf("windows release with build number [%d] is unsupported", buildNumber)
return unsupportedWindowsOSFamily
}
// Find the installation type from the Windows registry.
key, err := winRegistry.OpenKey(ecsWinRegistryRootKey, ecsWinRegistryRootPath, registry.QUERY_VALUE)
if err != nil {
seelog.Errorf("unable to open Windows registry key to determine Windows installation type: %v", err)
return unsupportedWindowsOSFamily
}
defer key.Close()
installationType, _, err := key.GetStringValue("InstallationType")
if err != nil {
seelog.Errorf("unable to read registry key, InstallationType: %v", err)
return unsupportedWindowsOSFamily
}
iType, err := getInstallationType(installationType)
if err != nil {
seelog.Errorf("invalid Installation type found: %v", err)
return unsupportedWindowsOSFamily
}
// Construct the OSFamily attribute from the OS release and installation type.
osFamily := fmt.Sprintf(osFamilyFormat, osRelease, iType)
seelog.Debugf("operating system family is: %s", osFamily)
return osFamily
}