in agent/plugins/configurecontainers/windowscontainerutil/windowscontainerutil.go [43:307]
func RunInstallCommands(context context.T, orchestrationDirectory string, out iohandler.IOHandler) {
var err error
var command string
var platformVersion string
var parameters []string
var requireReboot bool
var isNanoServer bool
var output string
log := context.Log()
platformVersion, err = dep.PlatformVersion(log)
if err != nil {
log.Error("Error detecting platform version", err)
out.MarkAsFailed(fmt.Errorf("Error detecting platform version: %v", err))
return
}
log.Debug("Platform Version:", platformVersion)
if !strings.HasPrefix(platformVersion, "10") {
out.MarkAsFailed(errors.New("ConfigureDocker is only supported on Microsoft Windows Server 2016 and above."))
return
}
isNanoServer, err = dep.IsPlatformNanoServer(log)
if err != nil {
log.Error("Error detecting if Nano Server", err)
out.MarkAsFailed(fmt.Errorf("Error detecting if Nano Server: %v", err))
return
}
if isNanoServer {
command = "(Get-PackageProvider -ListAvailable).Name"
parameters = make([]string, 0)
output, err = dep.UpdateUtilExeCommandOutput(context, 120, log, command, parameters, "", "", "", "", true)
if err != nil {
log.Error("Error getting package providers", err)
out.MarkAsFailed(fmt.Errorf("Error getting package providers: %v", err))
return
}
log.Debug("Get-PackageProvider output:", output)
packageInstalled := strings.Contains(output, "NanoServerPackage")
if !packageInstalled {
out.AppendInfo("Installing Nano Server package provider.")
command = `Install-PackageProvider -Name Nuget -MinimumVersion 2.8.5.201 -Force`
parameters = make([]string, 0)
output, err = dep.UpdateUtilExeCommandOutput(context, 60, log, command, parameters, "", "", "", "", true)
if err != nil {
log.Error("Error installing Nuget package provider", err)
out.MarkAsFailed(fmt.Errorf("Error installing Nuget package provider: %v", err))
return
}
log.Debug("Install Package provider output:", output)
command = `Save-Module -Path "$env:programfiles\WindowsPowerShell\Modules\" -Name NanoServerPackage -minimumVersion 1.0.1.0`
parameters = make([]string, 0)
output, err = dep.UpdateUtilExeCommandOutput(context, 60, log, command, parameters, "", "", "", "", true)
if err != nil {
log.Error("Error saving module", err)
out.MarkAsFailed(fmt.Errorf("Error saving Nano server package: %v", err))
return
}
log.Debug("Save-Module output:", output)
command = `Import-PackageProvider NanoServerPackage`
parameters = make([]string, 0)
output, err = dep.UpdateUtilExeCommandOutput(context, 30, log, command, parameters, "", "", "", "", true)
if err != nil {
log.Error("Error importing package", err)
out.MarkAsFailed(fmt.Errorf("Error importing package: %v", err))
return
}
log.Debug("Import-PackageProvider output:", output)
}
//Install containers package
command = "(Get-Package -providername NanoServerPackage).Name"
parameters = make([]string, 0)
output, err = dep.UpdateUtilExeCommandOutput(context, 30, log, command, parameters, "", "", "", "", true)
if err != nil {
log.Error("Error getting microsoft-nanoserver-containers-package", err)
out.MarkAsFailed(fmt.Errorf("Error getting microsoft-nanoserver-containers-package: %v", err))
return
}
log.Debug("Get-Package output:", output)
packageInstalled = strings.Contains(output, "Microsoft-NanoServer-Containers-Package")
if !packageInstalled {
out.AppendInfo("Installing containers package.")
command = "Install-NanoServerPackage microsoft-nanoserver-containers-package"
parameters = make([]string, 0)
output, err = dep.UpdateUtilExeCommandOutput(context, 30, log, command, parameters, "", "", "", "", true)
if err != nil {
log.Error("Error installing microsoft-nanoserver-containers-package", err)
out.MarkAsFailed(fmt.Errorf("Error installing microsoft-nanoserver-containers-package: %v", err))
return
}
log.Debug("Install-NanoServerPackage output:", output)
requireReboot = true
}
} else {
//install windows containers feature
command = "(Get-WindowsFeature -Name containers).Installed"
parameters = make([]string, 0)
output, err = dep.UpdateUtilExeCommandOutput(context, 30, log, command, parameters, "", "", "", "", true)
if err != nil {
log.Error("Error getting containers feature", err)
out.MarkAsFailed(fmt.Errorf("Error getting containers feature: %v", err))
return
}
log.Debug("Get-WindowsFeature output:", output)
packageInstalled := strings.Contains(output, "True")
if !packageInstalled {
out.AppendInfo("Installing Windows containers feature.")
command = "(Install-WindowsFeature -Name containers).RestartNeeded"
parameters = make([]string, 0)
output, err = dep.UpdateUtilExeCommandOutput(context, 30, log, command, parameters, "", "", "", "", true)
if err != nil {
log.Error("Error installing Windows containers feature", err)
out.MarkAsFailed(fmt.Errorf("Error installing Windows containers feature: %v", err))
return
}
log.Debug("Install-WindowsFeature output:", output)
requireReboot = strings.Contains(output, "Yes")
}
}
//Create docker config if it does not exist
daemonConfigPath := PROGRAM_DATA_DIRECTORY + "\\docker\\config\\daemon.json"
daemonConfigContent := `{}`
if err := dep.SetDaemonConfig(daemonConfigPath, daemonConfigContent); err != nil {
log.Error("Error writing Docker daemon config file", err)
out.MarkAsFailed(fmt.Errorf("Error writing Docker daemon config file: %v", err))
return
}
//Download docker
var downloadOutput artifact.DownloadOutput
downloadOutput, err = dep.ArtifactDownload(context, artifact.DownloadInput{SourceURL: DOCKER_DOWNLOAD_URL, DestinationDirectory: appconfig.DownloadRoot})
if err != nil {
log.Errorf("Failed to download Docker Engine file from %v: %v", DOCKER_DOWNLOAD_URL, err)
out.MarkAsFailed(fmt.Errorf("Failed to download Docker Engine file from %v: %v", DOCKER_DOWNLOAD_URL, err))
return
}
log.Debugf("Zip file downloaded to %v", downloadOutput.LocalFilePath)
_, installedErr := os.Stat(DOCKER_INSTALLED_DIRECTORY)
if downloadOutput.IsUpdated || installedErr != nil {
out.AppendInfo("Unzipping Docker to program files directory.")
//uncompress docker zip
fileutil.Uncompress(log, downloadOutput.LocalFilePath, PROGRAM_FILES_DIRECTORY)
}
// delete downloaded file, if it exists
pluginutil.CleanupFile(log, downloadOutput.LocalFilePath)
//Set this process's path environment variable to include Docker
if !strings.Contains(strings.ToLower(os.Getenv("path")), strings.ToLower(DOCKER_INSTALLED_DIRECTORY)) {
out.AppendInfo("Setting process path variable to include docker directory")
//set envvariable for this process
os.Setenv("path", DOCKER_INSTALLED_DIRECTORY+";"+os.Getenv("path"))
}
log.Debug("Path set to ", os.Getenv("path"))
//set path env variable for machine to include Docker
var currentSystemPathValue string
currentSystemPathValue, _, err = dep.LocalRegistryKeyGetStringValue(`System\CurrentControlSet\Control\Session Manager\Environment`, "Path")
if err != nil {
log.Error("Error getting current machine registry key value", err)
out.MarkAsFailed(fmt.Errorf("Error getting current machine registry key value: %v", err))
return
}
log.Debug("System Path set to ", currentSystemPathValue)
if !strings.Contains(strings.ToLower(currentSystemPathValue), strings.ToLower(DOCKER_INSTALLED_DIRECTORY)) {
out.AppendInfo("Setting machine path variable to include docker directory")
command = "setx"
parameters = []string{"-m", "path", os.Getenv("path")}
var setPathOutput string
setPathOutput, err = dep.UpdateUtilExeCommandOutput(context, 10, log, command, parameters, "", "", "", "", false)
if err != nil {
log.Error("Error setting machine path environment variable", err)
out.MarkAsFailed(fmt.Errorf("Error setting machine path environment variable: %v", err))
return
}
log.Debug("setx path output:", setPathOutput)
}
//reboot if needed
if requireReboot {
out.AppendInfo("Rebooting machine to complete install")
log.Debug("require reboot is true")
out.SetStatus(contracts.ResultStatusSuccessAndReboot)
return
}
//Check if docker daemon registered
var dockerServiceStatusOutput string
command = "(Get-Service docker).Status"
parameters = make([]string, 0)
dockerServiceStatusOutput, err = dep.UpdateUtilExeCommandOutput(context, 120, log, command, parameters, "", "", "", "", true)
if err != nil {
log.Error("Error getting Docker service status", err)
out.MarkAsFailed(fmt.Errorf("Error getting Docker service status: %v", err))
return
}
log.Debug("Get-Service output:", dockerServiceStatusOutput)
ServiceRunning := strings.HasPrefix(dockerServiceStatusOutput, "Running")
//Register Service
if len(strings.TrimSpace(dockerServiceStatusOutput)) == 0 {
out.AppendInfo("Registering dockerd.")
command = `dockerd`
log.Debug("dockerd cmd:", command)
parameters = []string{"--register-service"}
dockerServiceStatusOutput, err = dep.UpdateUtilExeCommandOutput(context, 120, log, command, parameters, DOCKER_INSTALLED_DIRECTORY, "", "", "", false)
if err != nil {
log.Error("Error registering Docker service", err)
out.MarkAsFailed(fmt.Errorf("Error registering Docker service: %v", err))
return
}
log.Debug("dockerd output:", dockerServiceStatusOutput)
//set service to delayed start
out.AppendInfo("set dockerd service configuration.")
command = "sc.exe"
parameters = []string{"config", "docker", "start=delayed-auto"}
dockerServiceStatusOutput, err = dep.UpdateUtilExeCommandOutput(context, 10, log, command, parameters, "", "", "", "", false)
if err != nil {
log.Error("Error setting delayed start for Docker service", err)
out.MarkAsFailed(fmt.Errorf("Error setting delayed start for Docker service: %v", err))
return
}
log.Debug("sc output:", dockerServiceStatusOutput)
//sleep 10 sec after registering
time.Sleep(10 * time.Second)
}
err = dep.LocalRegistryKeySetDWordValue(`SYSTEM\CurrentControlSet\services\docker`, "AutoStartDelay", 240)
if err != nil {
log.Error("Error opening registry key to set Docker delayed start", err)
out.MarkAsFailed(fmt.Errorf("Error opening registry key to set Docker delayed start: %v", err))
return
}
//Start service
if !ServiceRunning {
out.AppendInfo("Starting Docker service.")
command = "Start-Service docker"
parameters = make([]string, 0)
dockerServiceStatusOutput, err = dep.UpdateUtilExeCommandOutput(context, 300, log, command, parameters, "", "", "", "", true)
if err != nil {
log.Error("Error starting Docker service", err)
out.MarkAsFailed(fmt.Errorf("Error starting Docker service: %v", err))
return
}
log.Debug("start-service output:", dockerServiceStatusOutput)
}
out.AppendInfo("Installation complete")
log.Debug("require reboot:", requireReboot)
out.SetStatus(contracts.ResultStatusSuccess)
return
}