mirror of
https://github.com/saltstack/salt.git
synced 2025-04-16 01:30:20 +00:00
1900 lines
70 KiB
NSIS
1900 lines
70 KiB
NSIS
!define PRODUCT_NAME "Salt Minion"
|
|
!define PRODUCT_PUBLISHER "SaltStack, Inc"
|
|
!define PRODUCT_WEB_SITE "http://saltproject.io"
|
|
!define PRODUCT_CALL_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\salt-call.exe"
|
|
!define PRODUCT_CP_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\salt-cp.exe"
|
|
!define PRODUCT_KEY_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\salt-key.exe"
|
|
!define PRODUCT_MASTER_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\salt-master.exe"
|
|
!define PRODUCT_MINION_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\salt-minion.exe"
|
|
!define PRODUCT_RUN_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\salt-run.exe"
|
|
!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
|
|
!define PRODUCT_UNINST_ROOT_KEY "HKLM"
|
|
!define /date TIME_STAMP "%Y-%m-%d-%H-%M-%S"
|
|
|
|
# Request admin rights
|
|
RequestExecutionLevel admin
|
|
|
|
# Import Libraries
|
|
!include "FileFunc.nsh"
|
|
!include "LogicLib.nsh"
|
|
!include "MoveFileFolder.nsh"
|
|
!include "MUI2.nsh"
|
|
!include "nsDialogs.nsh"
|
|
!include "StrFunc.nsh"
|
|
!include "WinMessages.nsh"
|
|
!include "WinVer.nsh"
|
|
!include "x64.nsh"
|
|
${StrLoc}
|
|
${StrStrAdv}
|
|
|
|
# Required by MoveFileFolder.nsh
|
|
!insertmacro Locate
|
|
|
|
# Get salt version from CLI argument /DSaltVersion
|
|
!ifdef SaltVersion
|
|
!define PRODUCT_VERSION "${SaltVersion}"
|
|
!else
|
|
!define PRODUCT_VERSION "Undefined Version"
|
|
!endif
|
|
|
|
# Get architecture from CLI argument /DPythonArchitecture
|
|
# Should be x64, AMD64, or x86
|
|
!ifdef PythonArchitecture
|
|
!define PYTHON_ARCHITECTURE "${PythonArchitecture}"
|
|
!else
|
|
# Default
|
|
!define PYTHON_ARCHITECTURE "x64"
|
|
!endif
|
|
|
|
# Get Estimated Size from CLI argument /DEstimatedSize
|
|
!ifdef PythonArchitecture
|
|
!define ESTIMATED_SIZE "${EstimatedSize}"
|
|
!else
|
|
# Default
|
|
!define ESTIMATED_SIZE 0
|
|
!endif
|
|
|
|
# x64 and AMD64 are AMD64, all others are x86
|
|
!if "${PYTHON_ARCHITECTURE}" == "x64"
|
|
!define CPUARCH "AMD64"
|
|
!else if "${PYTHON_ARCHITECTURE}" == "AMD64"
|
|
!define CPUARCH "AMD64"
|
|
!else
|
|
!define CPUARCH "x86"
|
|
!endif
|
|
|
|
!define BUILD_TYPE "Python 3"
|
|
!define OUTFILE "Salt-Minion-${PRODUCT_VERSION}-Py3-${CPUARCH}-Setup.exe"
|
|
|
|
# Part of the Trim function for Strings
|
|
!define Trim "!insertmacro Trim"
|
|
!macro Trim ResultVar String
|
|
Push "${String}"
|
|
Call Trim
|
|
Pop "${ResultVar}"
|
|
!macroend
|
|
|
|
# Part of the Explode function for Strings
|
|
!define Explode "!insertmacro Explode"
|
|
!macro Explode Length Separator String
|
|
Push "${Separator}"
|
|
Push "${String}"
|
|
Call Explode
|
|
Pop "${Length}"
|
|
!macroend
|
|
|
|
# Part of the StrContains function for Strings
|
|
!define StrContains "!insertmacro StrContains"
|
|
!macro StrContains OUT NEEDLE HAYSTACK
|
|
Push "${HAYSTACK}"
|
|
Push "${NEEDLE}"
|
|
Call StrContains
|
|
Pop "${OUT}"
|
|
!macroend
|
|
|
|
|
|
###############################################################################
|
|
# Configure Pages, Ordering, and Configuration
|
|
###############################################################################
|
|
!define MUI_ABORTWARNING
|
|
!define MUI_ICON "salt.ico"
|
|
!define MUI_UNICON "salt.ico"
|
|
!define MUI_WELCOMEFINISHPAGE_BITMAP "panel.bmp"
|
|
!define MUI_UNWELCOMEFINISHPAGE_BITMAP "panel.bmp"
|
|
|
|
|
|
# Welcome page
|
|
!insertmacro MUI_PAGE_WELCOME
|
|
|
|
# License page
|
|
!insertmacro MUI_PAGE_LICENSE "LICENSE.txt"
|
|
|
|
# Install location page
|
|
!define MUI_PAGE_CUSTOMFUNCTION_SHOW pageCheckExistingInstall
|
|
!insertmacro MUI_PAGE_DIRECTORY
|
|
|
|
# Configure Minion page
|
|
Page custom pageMinionConfig pageMinionConfig_Leave
|
|
|
|
# Instfiles page
|
|
!insertmacro MUI_PAGE_INSTFILES
|
|
|
|
# Finish page (Customized)
|
|
!define MUI_PAGE_CUSTOMFUNCTION_SHOW pageFinish_Show
|
|
!define MUI_PAGE_CUSTOMFUNCTION_LEAVE pageFinish_Leave
|
|
!insertmacro MUI_PAGE_FINISH
|
|
|
|
# Uninstaller pages
|
|
!insertmacro MUI_UNPAGE_INSTFILES
|
|
|
|
# Language files
|
|
!insertmacro MUI_LANGUAGE "English"
|
|
|
|
|
|
###############################################################################
|
|
# Custom Dialog Box Variables
|
|
###############################################################################
|
|
Var Dialog
|
|
Var Label
|
|
Var MinionStart_ChkBox
|
|
Var MinionStartDelayed_ChkBox
|
|
Var MasterHost_Cfg
|
|
Var MasterHost_TxtBox
|
|
Var MasterHost
|
|
Var MinionName_Cfg
|
|
Var MinionName_TxtBox
|
|
Var MinionName
|
|
Var ExistingConfigFound
|
|
Var ConfigType_DropList
|
|
Var ConfigType
|
|
Var CustomConfig_TxtBox
|
|
Var CustomConfig_Btn
|
|
Var CustomConfig
|
|
Var CustomConfigWarning_Lbl
|
|
Var ExistingConfigWarning_Lbl
|
|
Var DefaultConfigWarning_Lbl
|
|
Var MoveExistingConfig_ChkBox
|
|
Var MoveExistingConfig
|
|
Var StartMinion
|
|
Var StartMinionDelayed
|
|
Var DeleteInstallDir
|
|
Var DeleteRootDir
|
|
Var ConfigWriteMinion
|
|
Var ConfigWriteMaster
|
|
# For new method installation
|
|
Var RegInstDir
|
|
Var RegRootDir
|
|
Var RootDir
|
|
Var SysDrive
|
|
Var ExistingInstallation
|
|
Var CustomLocation
|
|
|
|
|
|
###############################################################################
|
|
# Directory Picker Dialog Box
|
|
###############################################################################
|
|
Function pageCheckExistingInstall
|
|
# If this is an Existing Installation we want to disable the directory
|
|
# picker functionality
|
|
# https://nsis-dev.github.io/NSIS-Forums/html/t-166727.html
|
|
# Use the winspy tool (https://sourceforge.net/projects/winspyex/) to get
|
|
# the Control ID for the items you want to disable
|
|
# The Control ID is in the Details tab
|
|
# It is a Hex value that needs to be converted to an integer
|
|
${If} $ExistingInstallation == 1
|
|
# 32770 is Class name used by all NSIS dialog boxes
|
|
FindWindow $R0 "#32770" "" $HWNDPARENT
|
|
# 1019 is the Destination Folder text field (0x3FB)
|
|
GetDlgItem $R1 $R0 1019
|
|
EnableWindow $R1 0
|
|
# 1001 is the Browse button (0x3E9)
|
|
GetDlgItem $R1 $R0 1001
|
|
EnableWindow $R1 0
|
|
# Disabling the Location Picker causes the buttons to behave incorrectly
|
|
# Esc and Enter don't work. Nor can you use Alt+N and Alt+B. Setting
|
|
# the focus to the Next button seems to fix this
|
|
# Set focus on Next button (0x1)
|
|
# Next=1, cancel=2, back=3
|
|
GetDlgItem $R1 $HWNDPARENT 1
|
|
SendMessage $HWNDPARENT ${WM_NEXTDLGCTL} $R1 1
|
|
${EndIf}
|
|
FunctionEnd
|
|
|
|
|
|
###############################################################################
|
|
# Minion Settings Dialog Box
|
|
###############################################################################
|
|
Function pageMinionConfig
|
|
|
|
# Set Page Title and Description
|
|
!insertmacro MUI_HEADER_TEXT "Minion Settings" "Set the Minion Master and ID"
|
|
nsDialogs::Create 1018
|
|
Pop $Dialog
|
|
|
|
${If} $Dialog == error
|
|
Abort
|
|
${EndIf}
|
|
|
|
# Master IP or Hostname Dialog Control
|
|
${NSD_CreateLabel} 0 0 100% 9u "&Master IP or Hostname:"
|
|
Pop $Label
|
|
|
|
${NSD_CreateText} 0 10u 100% 12u $MasterHost
|
|
Pop $MasterHost_TxtBox
|
|
|
|
# Minion ID Dialog Control
|
|
${NSD_CreateLabel} 0 30u 100% 9u "Minion &Name:"
|
|
Pop $Label
|
|
|
|
${NSD_CreateText} 0 40u 100% 12u $MinionName
|
|
Pop $MinionName_TxtBox
|
|
|
|
# Config Drop List
|
|
${NSD_CreateDropList} 0 60u 25% 36u ""
|
|
Pop $ConfigType_DropList
|
|
${NSD_CB_AddString} $ConfigType_DropList "Default Config"
|
|
${NSD_CB_AddString} $ConfigType_DropList "Custom Config"
|
|
${NSD_OnChange} $ConfigType_DropList pageMinionConfig_OnChange
|
|
|
|
# Add Existing Config Warning Label
|
|
${NSD_CreateLabel} 0 75u 100% 50u \
|
|
"The values above are taken from an existing configuration found in \
|
|
`$RootDir\conf\minion`.$\n\
|
|
$\n\
|
|
Clicking `Install` will leave the existing config unchanged."
|
|
Pop $ExistingConfigWarning_Lbl
|
|
CreateFont $0 "Arial" 10 500 /ITALIC
|
|
SendMessage $ExistingConfigWarning_Lbl ${WM_SETFONT} $0 1
|
|
SetCtlColors $ExistingConfigWarning_Lbl 0xBB0000 transparent
|
|
|
|
# Add Checkbox to move root_dir
|
|
${NSD_CreateCheckBox} 0 125u 100% 10u \
|
|
"Move &existing root directory (C:\salt) to %ProgramData%\Salt."
|
|
Pop $MoveExistingConfig_ChkBox
|
|
CreateFont $0 "Arial" 10 500
|
|
SendMessage $MoveExistingConfig_ChkBox ${WM_SETFONT} $0 1
|
|
${If} $MoveExistingConfig == 1
|
|
${NSD_Check} $MoveExistingConfig_ChkBox
|
|
${EndIf}
|
|
|
|
# Add Default Config Warning Label
|
|
${NSD_CreateLabel} 0 75u 100% 60u "Clicking `Install` will backup the \
|
|
existing minion config file and minion.d directories. The values \
|
|
above will be used in the new default config.$\n\
|
|
$\n\
|
|
NOTE: If Master IP is set to `salt` and Minion Name is set to \
|
|
`hostname` no changes will be made."
|
|
Pop $DefaultConfigWarning_Lbl
|
|
CreateFont $0 "Arial" 10 500 /ITALIC
|
|
SendMessage $DefaultConfigWarning_Lbl ${WM_SETFONT} $0 1
|
|
SetCtlColors $DefaultConfigWarning_Lbl 0xBB0000 transparent
|
|
|
|
# Add Custom Config File Selector and Warning Label
|
|
${NSD_CreateText} 26% 60u 64% 12u $CustomConfig
|
|
Pop $CustomConfig_TxtBox
|
|
${NSD_CreateButton} 91% 60u 9% 12u "..."
|
|
Pop $CustomConfig_Btn
|
|
${NSD_OnClick} $CustomConfig_Btn pageCustomConfigBtn_OnClick
|
|
|
|
${If} $ExistingConfigFound == 0
|
|
${NSD_CreateLabel} 0 75u 100% 60u \
|
|
"Values entered above will be used in the custom config.$\n\
|
|
$\n\
|
|
NOTE: If Master IP is set to `salt` and Minion Name is set to \
|
|
`hostname` no changes will be made."
|
|
${Else}
|
|
${NSD_CreateLabel} 0 75u 100% 60u \
|
|
"Clicking `Install` will backup the the existing minion config \
|
|
file and minion.d directories. The values above will be used in \
|
|
the custom config.$\n\
|
|
$\n\
|
|
NOTE: If Master IP is set to `salt` and Minion Name is set to \
|
|
`hostname` no changes will be made."
|
|
${Endif}
|
|
Pop $CustomConfigWarning_Lbl
|
|
CreateFont $0 "Arial" 10 500 /ITALIC
|
|
SendMessage $CustomConfigWarning_Lbl ${WM_SETFONT} $0 1
|
|
SetCtlColors $CustomConfigWarning_Lbl 0xBB0000 transparent
|
|
|
|
# If existing config found, add the Existing Config option to the Drop List
|
|
# If not, hide the Default Warning
|
|
${If} $ExistingConfigFound == 1
|
|
${NSD_CB_AddString} $ConfigType_DropList "Existing Config"
|
|
${Else}
|
|
ShowWindow $DefaultConfigWarning_Lbl ${SW_HIDE}
|
|
${Endif}
|
|
|
|
${NSD_CB_SelectString} $ConfigType_DropList $ConfigType
|
|
${NSD_SetText} $CustomConfig_TxtBox $CustomConfig
|
|
|
|
Call pageMinionConfig_OnChange
|
|
|
|
nsDialogs::Show
|
|
|
|
FunctionEnd
|
|
|
|
|
|
Function pageMinionConfig_OnChange
|
|
|
|
# You have to pop the top handle to keep the stack clean
|
|
Pop $R0
|
|
|
|
# Assign the current checkbox state to the variable
|
|
${NSD_GetText} $ConfigType_DropList $ConfigType
|
|
|
|
# Update Dialog
|
|
${Switch} $ConfigType
|
|
${Case} "Existing Config"
|
|
# Enable Master/Minion and set values
|
|
EnableWindow $MasterHost_TxtBox 0
|
|
EnableWindow $MinionName_TxtBox 0
|
|
${NSD_SetText} $MasterHost_TxtBox $MasterHost_Cfg
|
|
${NSD_SetText} $MinionName_TxtBox $MinionName_Cfg
|
|
# Hide Custom File Picker
|
|
ShowWindow $CustomConfig_TxtBox ${SW_HIDE}
|
|
ShowWindow $CustomConfig_Btn ${SW_HIDE}
|
|
# Hide Warnings
|
|
ShowWindow $DefaultConfigWarning_Lbl ${SW_HIDE}
|
|
ShowWindow $CustomConfigWarning_Lbl ${SW_HIDE}
|
|
# Show Existing Warning
|
|
ShowWindow $ExistingConfigWarning_Lbl ${SW_SHOW}
|
|
${If} $RootDir == "C:\salt"
|
|
ShowWindow $MoveExistingConfig_ChkBox ${SW_SHOW}
|
|
${Else}
|
|
ShowWindow $MoveExistingConfig_ChkBox ${SW_HIDE}
|
|
${EndIf}
|
|
${Break}
|
|
${Case} "Custom Config"
|
|
# Enable Master/Minion and set values
|
|
EnableWindow $MasterHost_TxtBox 1
|
|
EnableWindow $MinionName_TxtBox 1
|
|
${NSD_SetText} $MasterHost_TxtBox $MasterHost
|
|
${NSD_SetText} $MinionName_TxtBox $MinionName
|
|
# Show Custom File Picker
|
|
ShowWindow $CustomConfig_TxtBox ${SW_SHOW}
|
|
ShowWindow $CustomConfig_Btn ${SW_SHOW}
|
|
# Hide Warnings
|
|
ShowWindow $DefaultConfigWarning_Lbl ${SW_HIDE}
|
|
ShowWindow $ExistingConfigWarning_Lbl ${SW_HIDE}
|
|
ShowWindow $MoveExistingConfig_ChkBox ${SW_HIDE}
|
|
# Show Custom Warning
|
|
ShowWindow $CustomConfigWarning_Lbl ${SW_SHOW}
|
|
${Break}
|
|
${Case} "Default Config"
|
|
# Enable Master/Minion and set values
|
|
EnableWindow $MasterHost_TxtBox 1
|
|
EnableWindow $MinionName_TxtBox 1
|
|
${NSD_SetText} $MasterHost_TxtBox $MasterHost
|
|
${NSD_SetText} $MinionName_TxtBox $MinionName
|
|
# Hide Custom File Picker
|
|
ShowWindow $CustomConfig_TxtBox ${SW_HIDE}
|
|
ShowWindow $CustomConfig_Btn ${SW_HIDE}
|
|
# Hide Warnings
|
|
ShowWindow $ExistingConfigWarning_Lbl ${SW_HIDE}
|
|
ShowWindow $MoveExistingConfig_ChkBox ${SW_HIDE}
|
|
ShowWindow $CustomConfigWarning_Lbl ${SW_HIDE}
|
|
# Show Default Warning, if there is an existing config
|
|
${If} $ExistingConfigFound == 1
|
|
ShowWindow $DefaultConfigWarning_Lbl ${SW_SHOW}
|
|
${Endif}
|
|
${Break}
|
|
${EndSwitch}
|
|
|
|
FunctionEnd
|
|
|
|
# File Picker Definitions
|
|
!define OFN_FILEMUSTEXIST 0x00001000
|
|
!define OFN_DONTADDTOREC 0x02000000
|
|
!define OPENFILENAME_SIZE_VERSION_400 76
|
|
!define OPENFILENAME 'i,i,i,i,i,i,i,i,i,i,i,i,i,i,&i2,&i2,i,i,i,i'
|
|
Function pageCustomConfigBtn_OnClick
|
|
|
|
Pop $0
|
|
System::Call '*(&t${NSIS_MAX_STRLEN})i.s' # Allocate OPENFILENAME.lpstrFile buffer
|
|
System::Call '*(${OPENFILENAME})i.r0' # Allocate OPENFILENAME struct
|
|
System::Call '*$0(${OPENFILENAME})(${OPENFILENAME_SIZE_VERSION_400}, \
|
|
$hwndparent, , , , , , sr1, ${NSIS_MAX_STRLEN} , , , , \
|
|
t"Select Custom Config File", \
|
|
${OFN_FILEMUSTEXIST} | ${OFN_DONTADDTOREC})'
|
|
|
|
# Populate file name field
|
|
${NSD_GetText} $CustomConfig_TxtBox $2
|
|
System::Call "*$1(&t${NSIS_MAX_STRLEN}r2)" ; Set lpstrFile to the old path (if any)
|
|
|
|
# Open the dialog
|
|
System::Call 'COMDLG32::GetOpenFileName(ir0)i.r2'
|
|
|
|
# Get file name field
|
|
${If} $2 <> 0
|
|
System::Call "*$1(&t${NSIS_MAX_STRLEN}.r2)"
|
|
${NSD_SetText} $CustomConfig_TxtBox $2
|
|
${EndIf}
|
|
|
|
# Free resources
|
|
System::Free $1
|
|
System::Free $0
|
|
|
|
FunctionEnd
|
|
|
|
|
|
Function pageMinionConfig_Leave
|
|
|
|
# Save the State
|
|
${NSD_GetText} $MasterHost_TxtBox $MasterHost
|
|
${NSD_GetText} $MinionName_TxtBox $MinionName
|
|
${NSD_GetText} $ConfigType_DropList $ConfigType
|
|
${NSD_GetText} $CustomConfig_TxtBox $CustomConfig
|
|
${NSD_GetState} $MoveExistingConfig_ChkBox $MoveExistingConfig
|
|
|
|
# Abort if config file not found
|
|
${If} $ConfigType == "Custom Config"
|
|
IfFileExists "$CustomConfig" done 0
|
|
MessageBox MB_OK|MB_ICONEXCLAMATION \
|
|
"File not found: $CustomConfig" \
|
|
/SD IDOK
|
|
Abort
|
|
${EndIf}
|
|
|
|
${If} $MoveExistingConfig == 1
|
|
|
|
# This makes the $APPDATA variable point to the ProgramData folder
|
|
# instead of the current user's roaming AppData folder
|
|
SetShellVarContext all
|
|
|
|
# Get directory status
|
|
# We don't want to overwrite data in the new location, so it needs to
|
|
# either be empty or not found. Otherwise, warn and abort
|
|
${DirState} "$APPDATA\Salt Project\Salt" $R0 # 0=Empty, 1=full, -1=Not Found
|
|
StrCmp $R0 "1" 0 done # Move files if directory empty or missing
|
|
MessageBox MB_OKCANCEL \
|
|
"The $APPDATA\Salt Project\Salt directory is not empty.$\n\
|
|
These files will need to be moved manually." \
|
|
/SD IDOK IDCANCEL cancel
|
|
# OK: We're continuing without moving existing config
|
|
StrCpy $MoveExistingConfig 0
|
|
Goto done
|
|
|
|
cancel:
|
|
# Cancel: We're unchecking the checkbox and returning the user to
|
|
# the dialog box
|
|
# Abort just returns the user back to the dialog box
|
|
${NSD_UNCHECK} $MoveExistingConfig_ChkBox
|
|
Abort
|
|
|
|
${EndIf}
|
|
|
|
done:
|
|
|
|
FunctionEnd
|
|
|
|
|
|
###############################################################################
|
|
# Custom Finish Page
|
|
###############################################################################
|
|
Function pageFinish_Show
|
|
|
|
# Imports so the checkboxes will show up
|
|
!define SWP_NOSIZE 0x0001
|
|
!define SWP_NOMOVE 0x0002
|
|
!define HWND_TOP 0x0000
|
|
|
|
# Create Start Minion Checkbox
|
|
${NSD_CreateCheckbox} 120u 90u 100% 12u "&Start salt-minion"
|
|
Pop $MinionStart_ChkBox
|
|
SetCtlColors $MinionStart_ChkBox "" "ffffff"
|
|
# This command required to bring the checkbox to the front
|
|
System::Call "User32::SetWindowPos(i, i, i, i, i, i, i) b ($MinionStart_ChkBox, ${HWND_TOP}, 0, 0, 0, 0, ${SWP_NOSIZE}|${SWP_NOMOVE})"
|
|
|
|
# Create Start Minion Delayed ComboBox
|
|
${NSD_CreateCheckbox} 130u 102u 100% 12u "&Delayed Start"
|
|
Pop $MinionStartDelayed_ChkBox
|
|
SetCtlColors $MinionStartDelayed_ChkBox "" "ffffff"
|
|
# This command required to bring the checkbox to the front
|
|
System::Call "User32::SetWindowPos(i, i, i, i, i, i, i) b ($MinionStartDelayed_ChkBox, ${HWND_TOP}, 0, 0, 0, 0, ${SWP_NOSIZE}|${SWP_NOMOVE})"
|
|
|
|
# Load current settings for Minion
|
|
${If} $StartMinion == 1
|
|
${NSD_Check} $MinionStart_ChkBox
|
|
${EndIf}
|
|
|
|
# Load current settings for Minion Delayed
|
|
${If} $StartMinionDelayed == 1
|
|
${NSD_Check} $MinionStartDelayed_ChkBox
|
|
${EndIf}
|
|
|
|
FunctionEnd
|
|
|
|
|
|
Function pageFinish_Leave
|
|
|
|
# Assign the current checkbox states
|
|
${NSD_GetState} $MinionStart_ChkBox $StartMinion
|
|
${NSD_GetState} $MinionStartDelayed_ChkBox $StartMinionDelayed
|
|
|
|
FunctionEnd
|
|
|
|
|
|
###############################################################################
|
|
# Installation Settings
|
|
###############################################################################
|
|
Name "${PRODUCT_NAME} ${PRODUCT_VERSION} (${BUILD_TYPE})"
|
|
OutFile "${OutFile}"
|
|
InstallDir "C:\Program Files\Salt Project\Salt"
|
|
InstallDirRegKey HKLM "${PRODUCT_DIR_REGKEY}" ""
|
|
ShowInstDetails show
|
|
ShowUnInstDetails show
|
|
|
|
Section "MainSection" SEC01
|
|
|
|
${If} $MoveExistingConfig == 1
|
|
# This makes the $APPDATA variable point to the ProgramData folder
|
|
# instead of the current user's roaming AppData folder
|
|
SetShellVarContext all
|
|
|
|
detailPrint "Moving existing config to $APPDATA\Salt Project\Salt"
|
|
# Make sure the target directory exists
|
|
nsExec::Exec "md $APPDATA\Salt Project\Salt"
|
|
# Take ownership of the C:\salt directory
|
|
detailPrint "Taking ownership: $RootDir"
|
|
nsExec::Exec "takeown /F $RootDir /R"
|
|
# Move the C:\salt directory to the new location
|
|
StrCpy $switch_overwrite 0
|
|
detailPrint "Moving $RootDir to $APPDATA"
|
|
IfFileExists "$RootDir\conf" 0 +2
|
|
!insertmacro MoveFolder "$RootDir\conf" "$APPDATA\Salt Project\Salt\conf" "*.*"
|
|
IfFileExists "$RootDir\srv" 0 +2
|
|
!insertmacro MoveFolder "$RootDir\srv" "$APPDATA\Salt Project\Salt\srv" "*.*"
|
|
IfFileExists "$RootDir\var" 0 +2
|
|
!insertmacro MoveFolder "$RootDir\var" "$APPDATA\Salt Project\Salt\var" "*.*"
|
|
# Make RootDir the new location
|
|
StrCpy $RootDir "$APPDATA\Salt Project\Salt"
|
|
${EndIf}
|
|
|
|
${If} $ConfigType != "Existing Config"
|
|
Call BackupExistingConfig
|
|
${EndIf}
|
|
|
|
|
|
# Install files to the Installation Directory
|
|
SetOutPath "$INSTDIR\"
|
|
SetOverwrite off
|
|
File /r "..\..\buildenv\"
|
|
|
|
# Set up Root Directory
|
|
CreateDirectory "$RootDir\conf\pki\minion"
|
|
CreateDirectory "$RootDir\conf\minion.d"
|
|
CreateDirectory "$RootDir\var\cache\salt\minion\extmods\grains"
|
|
CreateDirectory "$RootDir\var\cache\salt\minion\proc"
|
|
CreateDirectory "$RootDir\var\log\salt"
|
|
CreateDirectory "$RootDir\var\run"
|
|
nsExec::Exec 'icacls $RootDir /inheritance:r /grant:r "*S-1-5-32-544":(OI)(CI)F /grant:r "*S-1-5-18":(OI)(CI)F'
|
|
|
|
SectionEnd
|
|
|
|
|
|
Function .onInit
|
|
# This function gets executed before any other. This is where we will
|
|
# detect existing installations and config to be used by the installer
|
|
|
|
# Make sure we do not allow 32-bit Salt on 64-bit systems
|
|
# This is the system the installer is running on
|
|
${If} ${RunningX64}
|
|
# This is the Python architecture the installer was built with
|
|
${If} ${CPUARCH} == "x86"
|
|
MessageBox MB_OK|MB_ICONEXCLAMATION \
|
|
"Detected 64-bit Operating system.$\n$\n\
|
|
Please install the 64-bit version of Salt on this operating system." \
|
|
/SD IDOK
|
|
Abort
|
|
${EndIf}
|
|
${Else}
|
|
# This is the Python architecture the installer was built with
|
|
${If} ${CPUARCH} == "AMD64"
|
|
MessageBox MB_OK|MB_ICONEXCLAMATION \
|
|
"Detected 32-bit Operating system.$\n$\n\
|
|
Please install the 32-bit version of Salt on this operating system." \
|
|
/SD IDOK
|
|
Abort
|
|
${EndIf}
|
|
${EndIf}
|
|
|
|
Call parseInstallerCommandLineSwitches
|
|
|
|
# Uninstall msi-installed salt
|
|
# Source: https://nsis-dev.github.io/NSIS-Forums/html/t-303468.html
|
|
# TODO: Add a message box here confirming the uninstall of the MSI
|
|
!define upgradecode {FC6FB3A2-65DE-41A9-AD91-D10A402BD641} # Salt upgrade code
|
|
StrCpy $0 0
|
|
loop:
|
|
System::Call 'MSI::MsiEnumRelatedProducts(t "${upgradecode}",i0,i r0,t.r1)i.r2'
|
|
${If} $2 = 0
|
|
# Now $1 contains the product code
|
|
DetailPrint product:$1
|
|
push $R0
|
|
StrCpy $R0 $1
|
|
Call UninstallMSI
|
|
pop $R0
|
|
IntOp $0 $0 + 1
|
|
goto loop
|
|
${Endif}
|
|
|
|
# If a custom config is passed on the CLI, verify its existence before
|
|
# continuing so we don't uninstall an existing installation and then fail
|
|
# NOTE: This handles custom config for silent installations where the
|
|
# NOTE: custom config is passed on the CLI. The GUI has its own checking
|
|
# NOTE: when the user selects a custom config.
|
|
${If} $ConfigType == "Custom Config"
|
|
IfFileExists "$CustomConfig" checkExistingInstallation 0
|
|
Abort
|
|
${EndIf}
|
|
|
|
checkExistingInstallation:
|
|
# Check for existing installation
|
|
|
|
# The NSIS installer is a 32bit application and will use the WOW6432Node
|
|
# in the registry by default. We need to look in the 64 bit location on
|
|
# 64 bit systems
|
|
${If} ${RunningX64}
|
|
# https://nsis.sourceforge.io/Docs/Chapter4.html#setregview
|
|
SetRegView 64 # View the 64 bit portion of the registry
|
|
${EndIf}
|
|
|
|
ReadRegStr $R0 HKLM \
|
|
"Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
|
|
"UninstallString"
|
|
|
|
# Puts the nullsoft installer back to its default
|
|
SetRegView 32 # Set it back to the 32 bit portion of the registry
|
|
|
|
# If not found, look in 32 bit
|
|
${If} $R0 == ""
|
|
ReadRegStr $R0 HKLM \
|
|
"Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
|
|
"UninstallString"
|
|
${EndIf}
|
|
|
|
# If it's empty it's not installed
|
|
StrCmp $R0 "" skipUninstall
|
|
|
|
# Set InstDir to the parent directory so that we can uninstall it
|
|
${GetParent} $R0 $INSTDIR
|
|
|
|
# Found existing installation, prompt to uninstall
|
|
MessageBox MB_OKCANCEL|MB_USERICON \
|
|
"${PRODUCT_NAME} is already installed.$\n$\n\
|
|
Click `OK` to remove the existing installation." \
|
|
/SD IDOK IDOK uninst
|
|
Abort
|
|
|
|
uninst:
|
|
|
|
# Get current Silent status
|
|
StrCpy $R0 0
|
|
${If} ${Silent}
|
|
StrCpy $R0 1
|
|
${EndIf}
|
|
|
|
# Turn on Silent mode
|
|
SetSilent silent
|
|
|
|
# Don't remove all directories when upgrading (old method)
|
|
StrCpy $DeleteInstallDir 0
|
|
|
|
# Don't remove RootDir when upgrading (new method)
|
|
StrCpy $DeleteRootDir 0
|
|
|
|
# Uninstall silently
|
|
Call uninstallSalt
|
|
|
|
# Set it back to Normal mode, if that's what it was before
|
|
${If} $R0 == 0
|
|
SetSilent normal
|
|
${EndIf}
|
|
|
|
skipUninstall:
|
|
|
|
Call getExistingInstallation
|
|
|
|
Call getExistingMinionConfig
|
|
|
|
${If} $ExistingConfigFound == 0
|
|
${AndIf} $ConfigType == "Existing Config"
|
|
StrCpy $ConfigType "Default Config"
|
|
${EndIf}
|
|
|
|
FunctionEnd
|
|
|
|
|
|
Function BackupExistingConfig
|
|
|
|
${If} $ExistingConfigFound == 1 # If existing config found
|
|
${AndIfNot} $ConfigType == "Existing Config" # If not using Existing Config
|
|
|
|
# Backup the minion config
|
|
Rename "$RootDir\conf\minion" "$RootDir\conf\minion-${TIME_STAMP}.bak"
|
|
IfFileExists "$RootDir\conf\minion.d" 0 +2
|
|
Rename "$RootDir\conf\minion.d" "$RootDir\conf\minion.d-${TIME_STAMP}.bak"
|
|
|
|
${EndIf}
|
|
|
|
# By this point there should be no existing config. It was either backed up
|
|
# or wasn't there to begin with
|
|
${If} $ConfigType == "Custom Config" # If we're using Custom Config
|
|
${AndIfNot} $CustomConfig == "" # If a custom config is passed
|
|
|
|
# Check for a file name
|
|
# Named file should be in the same directory as the installer
|
|
CreateDirectory "$RootDir\conf"
|
|
IfFileExists "$EXEDIR\$CustomConfig" 0 checkFullPath
|
|
CopyFiles /SILENT /FILESONLY "$EXEDIR\$CustomConfig" "$RootDir\conf\minion"
|
|
goto finished
|
|
|
|
# Maybe it was a full path to a file
|
|
checkFullPath:
|
|
IfFileExists "$CustomConfig" 0 finished
|
|
CopyFiles /SILENT /FILESONLY "$CustomConfig" "$RootDir\conf\minion"
|
|
|
|
finished:
|
|
|
|
${EndIf}
|
|
|
|
FunctionEnd
|
|
|
|
|
|
Section -Post
|
|
|
|
WriteUninstaller "$INSTDIR\uninst.exe"
|
|
|
|
# The NSIS installer is a 32bit application and will use the WOW6432Node in
|
|
# the registry by default. We need to look in the 64 bit location on 64 bit
|
|
# systems
|
|
${If} ${RunningX64}
|
|
# https://nsis.sourceforge.io/Docs/Chapter4.html#setregview
|
|
SetRegView 64 # View 64 bit portion of the registry
|
|
${EndIf}
|
|
|
|
# Write Uninstall Registry Entries
|
|
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" \
|
|
"DisplayName" "$(^Name)"
|
|
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" \
|
|
"UninstallString" "$INSTDIR\uninst.exe"
|
|
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" \
|
|
"DisplayIcon" "$INSTDIR\salt.ico"
|
|
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" \
|
|
"DisplayVersion" "${PRODUCT_VERSION}"
|
|
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" \
|
|
"URLInfoAbout" "${PRODUCT_WEB_SITE}"
|
|
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" \
|
|
"Publisher" "${PRODUCT_PUBLISHER}"
|
|
WriteRegStr HKLM "SYSTEM\CurrentControlSet\services\salt-minion" \
|
|
"DependOnService" "nsi"
|
|
|
|
# If ESTIMATED_SIZE is not set, calculated it
|
|
${If} ${ESTIMATED_SIZE} == 0
|
|
${GetSize} "$INSTDIR" "/S=OK" $0 $1 $2
|
|
${Else}
|
|
StrCpy $0 ${ESTIMATED_SIZE}
|
|
${Endif}
|
|
IntFmt $0 "0x%08X" $0
|
|
WriteRegDWORD ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" \
|
|
"EstimatedSize" "$0"
|
|
|
|
# Write Commandline Registry Entries
|
|
WriteRegStr HKLM "${PRODUCT_CALL_REGKEY}" "" "$INSTDIR\salt-call.exe"
|
|
WriteRegStr HKLM "${PRODUCT_CALL_REGKEY}" "Path" "$INSTDIR\"
|
|
WriteRegStr HKLM "${PRODUCT_MINION_REGKEY}" "" "$INSTDIR\salt-minion.exe"
|
|
WriteRegStr HKLM "${PRODUCT_MINION_REGKEY}" "Path" "$INSTDIR\"
|
|
|
|
# Write Salt Configuration Registry Entries
|
|
# We want to write EXPAND_SZ string types to allow us to use environment
|
|
# variables. It's OK to use EXPAND_SZ even if you don't use an environment
|
|
# variable so we'll just do that whether it's new location or old.
|
|
|
|
# Check for Program Files
|
|
# Set the current setting for INSTDIR... we'll only change it if it contains
|
|
# Program Files
|
|
StrCpy $RegInstDir $INSTDIR
|
|
|
|
# Program Files
|
|
# We want to use the environment variables instead of the hardcoded path
|
|
${StrContains} $0 "Program Files" $INSTDIR
|
|
StrCmp $0 "" +2 # If it's empty, skip the next line
|
|
StrCpy $RegInstDir "%ProgramFiles%\Salt Project\Salt"
|
|
|
|
# Check for ProgramData
|
|
# Set the current setting for RootDir. we'll only change it if it contains
|
|
# ProgramData
|
|
StrCpy $RegRootDir $RootDir
|
|
|
|
# We want to use the environment variables instead of the hardcoded path
|
|
${StrContains} $0 "ProgramData" $RootDir
|
|
StrCmp $0 "" +2 # If it's empty, skip the next line
|
|
StrCpy $RegRootDir "%ProgramData%\Salt Project\Salt"
|
|
|
|
WriteRegExpandStr HKLM "SOFTWARE\Salt Project\Salt" "install_dir" "$RegInstDir"
|
|
WriteRegExpandStr HKLM "SOFTWARE\Salt Project\Salt" "root_dir" "$RegRootDir"
|
|
|
|
# Puts the nullsoft installer back to its default
|
|
SetRegView 32 # Set it back to the 32 bit portion of the registry
|
|
|
|
# Register the Salt-Minion Service
|
|
nsExec::Exec `$INSTDIR\ssm.exe install salt-minion "$INSTDIR\salt-minion.exe" -c """$RootDir\conf""" -l quiet`
|
|
nsExec::Exec "$INSTDIR\ssm.exe set salt-minion Description Salt Minion from saltstack.com"
|
|
nsExec::Exec "$INSTDIR\ssm.exe set salt-minion Start SERVICE_AUTO_START"
|
|
nsExec::Exec "$INSTDIR\ssm.exe set salt-minion AppStopMethodConsole 24000"
|
|
nsExec::Exec "$INSTDIR\ssm.exe set salt-minion AppStopMethodWindow 2000"
|
|
nsExec::Exec "$INSTDIR\ssm.exe set salt-minion AppRestartDelay 60000"
|
|
|
|
# There is a default minion config laid down in the $INSTDIR directory
|
|
${Switch} $ConfigType
|
|
${Case} "Existing Config"
|
|
# If this is an Existing Config, we don't do anything
|
|
${Break}
|
|
${Case} "Custom Config"
|
|
# If this is a Custom Config, update the custom config
|
|
Call updateMinionConfig
|
|
${Break}
|
|
${Case} "Default Config"
|
|
# If this is the Default Config, we move it and update it
|
|
StrCpy $switch_overwrite 1
|
|
|
|
!insertmacro MoveFolder "$INSTDIR\configs" "$RootDir\conf" "*.*"
|
|
Call updateMinionConfig
|
|
${Break}
|
|
${EndSwitch}
|
|
|
|
# Delete the configs directory that came with the installer
|
|
RMDir /r "$INSTDIR\configs"
|
|
|
|
# Add $INSTDIR in the Path
|
|
EnVar::SetHKLM
|
|
EnVar::AddValue Path "$INSTDIR"
|
|
|
|
SectionEnd
|
|
|
|
|
|
Function .onInstSuccess
|
|
|
|
# If StartMinionDelayed is 1, then set the service to start delayed
|
|
${If} $StartMinionDelayed == 1
|
|
nsExec::Exec "$INSTDIR\ssm.exe set salt-minion Start SERVICE_DELAYED_AUTO_START"
|
|
${EndIf}
|
|
|
|
# If start-minion is 1, then start the service
|
|
${If} $StartMinion == 1
|
|
nsExec::Exec 'net start salt-minion'
|
|
${EndIf}
|
|
|
|
FunctionEnd
|
|
|
|
|
|
Function un.onInit
|
|
|
|
Call un.parseUninstallerCommandLineSwitches
|
|
|
|
MessageBox MB_USERICON|MB_YESNO|MB_DEFBUTTON1 \
|
|
"Are you sure you want to completely remove $(^Name) and all of its \
|
|
components?" \
|
|
/SD IDYES IDYES +2
|
|
Abort
|
|
|
|
FunctionEnd
|
|
|
|
|
|
Section Uninstall
|
|
|
|
Call un.uninstallSalt
|
|
|
|
# Remove $INSTDIR from the Path
|
|
EnVar::SetHKLM
|
|
EnVar::DeleteValue Path "$INSTDIR"
|
|
|
|
SectionEnd
|
|
|
|
|
|
!macro uninstallSalt un
|
|
Function ${un}uninstallSalt
|
|
|
|
# WARNING: Any changes made here need to be reflected in the MSI uninstaller
|
|
# Make sure we're in the right directory
|
|
${If} $INSTDIR == "c:\salt\Scripts"
|
|
StrCpy $INSTDIR "C:\salt"
|
|
${EndIf}
|
|
# $ProgramFiles is different depending on the CPU Architecture
|
|
# https://nsis.sourceforge.io/Reference/$PROGRAMFILES
|
|
# x86 : C:\Program Files
|
|
# x64 : C:\Program Files (x86)
|
|
${If} $INSTDIR == "$ProgramFiles\Salt Project\Salt\Scripts"
|
|
StrCpy $INSTDIR "$ProgramFiles\Salt Project\Salt"
|
|
${EndIf}
|
|
# $ProgramFiles64 is the C:\Program Files directory
|
|
${If} $INSTDIR == "$ProgramFiles64\Salt Project\Salt\Scripts"
|
|
StrCpy $INSTDIR "$ProgramFiles64\Salt Project\Salt"
|
|
${EndIf}
|
|
|
|
# Stop and Remove salt-minion service
|
|
nsExec::Exec "net stop salt-minion"
|
|
nsExec::Exec "sc delete salt-minion"
|
|
|
|
# Stop and remove the salt-master service
|
|
nsExec::Exec "net stop salt-master"
|
|
nsExec::Exec "sc delete salt-master"
|
|
|
|
# We need to make sure the service is stopped and removed before deleting
|
|
# any files
|
|
StrCpy $0 1 # Tries
|
|
StrCpy $1 1 # Service Present
|
|
loop:
|
|
detailPrint "Verifying salt-minion deletion: try $0"
|
|
nsExec::ExecToStack 'net start | FIND /C /I "salt-minion"'
|
|
pop $2 # First on the stack is the return code
|
|
pop $1 # Next on the stack is standard out (service present)
|
|
${If} $1 == 1
|
|
${If} $0 < 5
|
|
IntOp $0 $0 + 1
|
|
Sleep 1000
|
|
goto loop
|
|
${Else}
|
|
MessageBox MB_OK|MB_ICONEXCLAMATION \
|
|
"Failed to remove salt-minion service" \
|
|
/SD IDOK
|
|
Abort
|
|
${EndIf}
|
|
${EndIf}
|
|
|
|
# Remove files
|
|
Delete "$INSTDIR\multi-minion*"
|
|
Delete "$INSTDIR\salt*"
|
|
Delete "$INSTDIR\ssm.exe"
|
|
Delete "$INSTDIR\uninst.exe"
|
|
Delete "$INSTDIR\vcredist.exe"
|
|
RMDir /r "$INSTDIR\DLLs"
|
|
RMDir /r "$INSTDIR\Include"
|
|
RMDir /r "$INSTDIR\Lib"
|
|
RMDir /r "$INSTDIR\libs"
|
|
RMDir /r "$INSTDIR\Scripts"
|
|
|
|
# Remove everything in the 64 bit registry
|
|
|
|
# The NSIS installer is a 32bit application and will use the WOW6432Node in
|
|
# the registry by default. We need to look in the 64 bit location on 64 bit
|
|
# systems
|
|
${If} ${RunningX64}
|
|
# https://nsis.sourceforge.io/Docs/Chapter4.html#setregview
|
|
SetRegView 64 # View the 64 bit portion of the registry
|
|
|
|
# Get Root Directory from the Registry (64 bit)
|
|
ReadRegStr $RootDir HKLM "SOFTWARE\Salt Project\Salt" "root_dir"
|
|
|
|
# Remove Registry entries
|
|
DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}"
|
|
|
|
# Remove Command Line Registry entries
|
|
DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_CALL_REGKEY}"
|
|
DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_CP_REGKEY}"
|
|
DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_KEY_REGKEY}"
|
|
DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_MASTER_REGKEY}"
|
|
DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_MINION_REGKEY}"
|
|
DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_RUN_REGKEY}"
|
|
DeleteRegKey HKLM "SOFTWARE\Salt Project"
|
|
${EndIf}
|
|
|
|
# Remove everything in the 32 bit registry
|
|
SetRegView 32 # Set it to 32 bit
|
|
|
|
${If} $RootDir == ""
|
|
# Get Root Directory from the Registry (32 bit)
|
|
ReadRegStr $RootDir HKLM "SOFTWARE\Salt Project\Salt" "root_dir"
|
|
${EndIf}
|
|
|
|
# Remove Registry entries
|
|
DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}"
|
|
|
|
# Remove Command Line Registry entries
|
|
DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_CALL_REGKEY}"
|
|
DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_CP_REGKEY}"
|
|
DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_KEY_REGKEY}"
|
|
DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_MASTER_REGKEY}"
|
|
DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_MINION_REGKEY}"
|
|
DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_RUN_REGKEY}"
|
|
DeleteRegKey HKLM "SOFTWARE\Salt Project"
|
|
|
|
# SystemDrive is not a built in NSIS constant, so we need to get it from
|
|
# the environment variables
|
|
ReadEnvStr $0 "SystemDrive" # Get the SystemDrive env var
|
|
StrCpy $SysDrive "$0\"
|
|
|
|
# Automatically close when finished
|
|
SetAutoClose true
|
|
|
|
# Old Method Installation
|
|
${If} $INSTDIR == "C:\salt"
|
|
|
|
# Prompt to remove the Installation Directory. This is because that
|
|
# directory is also the root_dir which includes the config and pki
|
|
# directories
|
|
${IfNot} $DeleteInstallDir == 1
|
|
MessageBox MB_YESNO|MB_DEFBUTTON2|MB_USERICON \
|
|
"Would you like to completely remove $INSTDIR and all of its contents?" \
|
|
/SD IDNO IDNO finished
|
|
${EndIf}
|
|
|
|
SetOutPath "$SysDrive" # Can't remove CWD
|
|
RMDir /r "$INSTDIR"
|
|
|
|
${Else}
|
|
|
|
# Prompt for the removal of the Installation Directory which contains
|
|
# the extras directory and the Root Directory which contains the config
|
|
# and pki directories. These directories will not be removed during
|
|
# an upgrade.
|
|
${IfNot} $DeleteRootDir == 1
|
|
MessageBox MB_YESNO|MB_DEFBUTTON2|MB_USERICON \
|
|
"Would you like to completely remove the entire Salt \
|
|
Installation? This includes the following:$\n\
|
|
- Extra Pip Packages ($INSTDIR\extras-3.##)$\n\
|
|
- Minion Config ($RootDir\conf)$\n\
|
|
- Minion PKIs ($RootDir\conf\pki)"\
|
|
/SD IDNO IDNO finished
|
|
${EndIf}
|
|
|
|
# New Method Installation
|
|
# This makes the $APPDATA variable point to the ProgramData folder instead
|
|
# of the current user's roaming AppData folder
|
|
SetShellVarContext all
|
|
|
|
# We can always remove the Installation Directory on New Method Installs
|
|
# because it only contains binary data
|
|
|
|
# Remove INSTDIR
|
|
# Make sure you're not removing important system directory such as
|
|
# Program Files, C:\Windows, or C:
|
|
${If} $INSTDIR != $ProgramFiles
|
|
${AndIf} $INSTDIR != $ProgramFiles64
|
|
${AndIf} $INSTDIR != $SysDrive
|
|
${AndIf} $INSTDIR != $WinDir
|
|
SetOutPath "$SysDrive" # Can't remove CWD
|
|
RMDir /r $INSTDIR
|
|
${EndIf}
|
|
|
|
# Remove INSTDIR (The parent)
|
|
# For example, though salt is installed in ProgramFiles\Salt Project\Salt
|
|
# We want to remove ProgramFiles\Salt Project
|
|
# Only delete Salt Project directory if it's in Program Files
|
|
# Otherwise, we can't guess where the user may have installed salt
|
|
${GetParent} $INSTDIR $0 # Get parent directory (Salt Project)
|
|
${If} $0 == "$ProgramFiles\Salt Project" # Make sure it's ProgramFiles
|
|
${OrIf} $0 == "$ProgramFiles64\Salt Project" # Make sure it's Program Files (x86)
|
|
SetOutPath "$SysDrive" # Can't remove CWD
|
|
RMDir /r $0
|
|
${EndIf}
|
|
|
|
# If RootDir is still empty, use C:\salt
|
|
${If} $RootDir == ""
|
|
StrCpy $RootDir "C:\salt"
|
|
${EndIf}
|
|
|
|
# Expand any environment variables
|
|
ExpandEnvStrings $RootDir $RootDir
|
|
|
|
# Remove the Salt Project directory in ProgramData
|
|
# The Salt Project directory will only ever be in ProgramData
|
|
# It is not user selectable
|
|
${GetParent} $RootDir $0 # Get parent directory
|
|
${If} $0 == "$APPDATA\Salt Project" # Make sure it's not ProgramData
|
|
SetOutPath "$SysDrive" # Can't remove CWD
|
|
RMDir /r $0
|
|
${EndIf}
|
|
|
|
${EndIf}
|
|
|
|
finished:
|
|
|
|
FunctionEnd
|
|
!macroend
|
|
|
|
|
|
!insertmacro uninstallSalt ""
|
|
!insertmacro uninstallSalt "un."
|
|
|
|
|
|
Function un.onUninstSuccess
|
|
HideWindow
|
|
MessageBox MB_OK|MB_USERICON \
|
|
"$(^Name) was successfully removed from your computer." \
|
|
/SD IDOK
|
|
FunctionEnd
|
|
|
|
|
|
###############################################################################
|
|
# Helper Functions
|
|
###############################################################################
|
|
|
|
#------------------------------------------------------------------------------
|
|
# Trim Function
|
|
# - Trim whitespace from the beginning and end of a string
|
|
# - Trims spaces, \r, \n, \t
|
|
#
|
|
# Usage:
|
|
# Push " some string " ; String to Trim
|
|
# Call Trim
|
|
# Pop $0 ; Trimmed String: "some string"
|
|
#
|
|
# or
|
|
#
|
|
# ${Trim} $0 $1 ; Trimmed String, String to Trim
|
|
#------------------------------------------------------------------------------
|
|
Function Trim
|
|
|
|
Exch $R1 # Original string
|
|
Push $R2
|
|
|
|
Loop:
|
|
StrCpy $R2 "$R1" 1
|
|
StrCmp "$R2" " " TrimLeft
|
|
StrCmp "$R2" "$\r" TrimLeft
|
|
StrCmp "$R2" "$\n" TrimLeft
|
|
StrCmp "$R2" "$\t" TrimLeft
|
|
GoTo Loop2
|
|
TrimLeft:
|
|
StrCpy $R1 "$R1" "" 1
|
|
Goto Loop
|
|
|
|
Loop2:
|
|
StrCpy $R2 "$R1" 1 -1
|
|
StrCmp "$R2" " " TrimRight
|
|
StrCmp "$R2" "$\r" TrimRight
|
|
StrCmp "$R2" "$\n" TrimRight
|
|
StrCmp "$R2" "$\t" TrimRight
|
|
GoTo Done
|
|
TrimRight:
|
|
StrCpy $R1 "$R1" -1
|
|
Goto Loop2
|
|
|
|
Done:
|
|
Pop $R2
|
|
Exch $R1
|
|
|
|
FunctionEnd
|
|
|
|
|
|
#------------------------------------------------------------------------------
|
|
# Explode Function
|
|
# - Splits a string based off the passed separator
|
|
# - Each item in the string is pushed to the stack
|
|
# - The last item pushed to the stack is the length of the array
|
|
#
|
|
# Usage:
|
|
# Push "," ; Separator
|
|
# Push "string,to,separate" ; String to explode
|
|
# Call Explode
|
|
# Pop $0 ; Number of items in the array
|
|
#
|
|
# or
|
|
#
|
|
# ${Explode} $0 $1 $2 ; Length, Separator, String
|
|
#------------------------------------------------------------------------------
|
|
Function Explode
|
|
# Initialize variables
|
|
Var /GLOBAL explString
|
|
Var /GLOBAL explSeparator
|
|
Var /GLOBAL explStrLen
|
|
Var /GLOBAL explSepLen
|
|
Var /GLOBAL explOffset
|
|
Var /GLOBAL explTmp
|
|
Var /GLOBAL explTmp2
|
|
Var /GLOBAL explTmp3
|
|
Var /GLOBAL explArrCount
|
|
|
|
# Get input from user
|
|
Pop $explString
|
|
Pop $explSeparator
|
|
|
|
# Calculates initial values
|
|
StrLen $explStrLen $explString
|
|
StrLen $explSepLen $explSeparator
|
|
StrCpy $explArrCount 1
|
|
|
|
${If} $explStrLen <= 1 # If we got a single character
|
|
${OrIf} $explSepLen > $explStrLen # or separator is larger than the string,
|
|
Push $explString # then we return initial string with no change
|
|
Push 1 # and set array's length to 1
|
|
Return
|
|
${EndIf}
|
|
|
|
# Set offset to the last symbol of the string
|
|
StrCpy $explOffset $explStrLen
|
|
IntOp $explOffset $explOffset - 1
|
|
|
|
# Clear temp string to exclude the possibility of appearance of occasional data
|
|
StrCpy $explTmp ""
|
|
StrCpy $explTmp2 ""
|
|
StrCpy $explTmp3 ""
|
|
|
|
# Loop until the offset becomes negative
|
|
${Do}
|
|
# If offset becomes negative, it is time to leave the function
|
|
${IfThen} $explOffset == -1 ${|} ${ExitDo} ${|}
|
|
|
|
# Remove everything before and after the searched part ("TempStr")
|
|
StrCpy $explTmp $explString $explSepLen $explOffset
|
|
|
|
${If} $explTmp == $explSeparator
|
|
# Calculating offset to start copy from
|
|
IntOp $explTmp2 $explOffset + $explSepLen # Offset equals to the current offset plus length of separator
|
|
StrCpy $explTmp3 $explString "" $explTmp2
|
|
|
|
Push $explTmp3 # Throwing array item to the stack
|
|
IntOp $explArrCount $explArrCount + 1 # Increasing array's counter
|
|
|
|
StrCpy $explString $explString $explOffset 0 # Cutting all characters beginning with the separator entry
|
|
StrLen $explStrLen $explString
|
|
${EndIf}
|
|
|
|
${If} $explOffset = 0 # If the beginning of the line met and there is no separator,
|
|
# copying the rest of the string
|
|
${If} $explSeparator == "" # Fix for the empty separator
|
|
IntOp $explArrCount $explArrCount - 1
|
|
${Else}
|
|
Push $explString
|
|
${EndIf}
|
|
${EndIf}
|
|
|
|
IntOp $explOffset $explOffset - 1
|
|
${Loop}
|
|
|
|
Push $explArrCount
|
|
FunctionEnd
|
|
|
|
|
|
#------------------------------------------------------------------------------
|
|
# StrContains
|
|
#
|
|
# This function does a case sensitive searches for an occurrence of a substring in a string.
|
|
# It returns the substring if it is found.
|
|
# Otherwise it returns null("").
|
|
# Written by kenglish_hi
|
|
# Adapted from StrReplace written by dandaman32
|
|
#------------------------------------------------------------------------------
|
|
Function StrContains
|
|
|
|
# Initialize variables
|
|
Var /GLOBAL STR_HAYSTACK
|
|
Var /GLOBAL STR_NEEDLE
|
|
Var /GLOBAL STR_CONTAINS_VAR_1
|
|
Var /GLOBAL STR_CONTAINS_VAR_2
|
|
Var /GLOBAL STR_CONTAINS_VAR_3
|
|
Var /GLOBAL STR_CONTAINS_VAR_4
|
|
Var /GLOBAL STR_RETURN_VAR
|
|
|
|
Exch $STR_NEEDLE
|
|
Exch 1
|
|
Exch $STR_HAYSTACK
|
|
# Uncomment to debug
|
|
#MessageBox MB_OK 'STR_NEEDLE = $STR_NEEDLE STR_HAYSTACK = $STR_HAYSTACK '
|
|
StrCpy $STR_RETURN_VAR ""
|
|
StrCpy $STR_CONTAINS_VAR_1 -1
|
|
StrLen $STR_CONTAINS_VAR_2 $STR_NEEDLE
|
|
StrLen $STR_CONTAINS_VAR_4 $STR_HAYSTACK
|
|
|
|
loop:
|
|
IntOp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_1 + 1
|
|
StrCpy $STR_CONTAINS_VAR_3 $STR_HAYSTACK $STR_CONTAINS_VAR_2 $STR_CONTAINS_VAR_1
|
|
StrCmp $STR_CONTAINS_VAR_3 $STR_NEEDLE found
|
|
StrCmp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_4 done
|
|
Goto loop
|
|
|
|
found:
|
|
StrCpy $STR_RETURN_VAR $STR_NEEDLE
|
|
Goto done
|
|
|
|
done:
|
|
Pop $STR_NEEDLE # Prevent "invalid opcode" errors and keep the stack clean
|
|
Exch $STR_RETURN_VAR
|
|
FunctionEnd
|
|
|
|
|
|
#------------------------------------------------------------------------------
|
|
# UninstallMSI Function
|
|
# - Uninstalls MSI by product code
|
|
#
|
|
# Usage:
|
|
# Push product code
|
|
# Call UninstallMSI
|
|
#
|
|
# Source:
|
|
# https://nsis.sourceforge.io/Uninstalling_a_previous_MSI_(Windows_installer_package)
|
|
#------------------------------------------------------------------------------
|
|
Function UninstallMSI
|
|
; $R0 === product code
|
|
MessageBox MB_OKCANCEL|MB_ICONINFORMATION \
|
|
"${PRODUCT_NAME} is already installed via MSI.$\n$\n\
|
|
Click `OK` to remove the existing installation." \
|
|
/SD IDOK IDOK UninstallMSI
|
|
Abort
|
|
|
|
UninstallMSI:
|
|
ExecWait '"msiexec.exe" /x $R0 /qb /quiet /norestart'
|
|
|
|
FunctionEnd
|
|
|
|
|
|
###############################################################################
|
|
# Specialty Functions
|
|
###############################################################################
|
|
|
|
Function getExistingInstallation
|
|
# Try to detect an existing installation. There are three possible scenarios
|
|
# 1. Existing New Method Installation
|
|
# 2. Existing Old Method Installation
|
|
# 3. New Installation
|
|
# The results of this function will determine if the user is allowed to set
|
|
# the install location in the GUI. If there is an existing installation
|
|
# present, the location picker will be grayed out
|
|
# This function also sets the RootDir and INSTDIR variables used by the
|
|
# installer.
|
|
|
|
# Reset ExistingInstallation
|
|
StrCpy $ExistingInstallation 0
|
|
|
|
# Get ProgramFiles
|
|
# Use RunningX64 here to get the Architecture for the system running the
|
|
# installer.
|
|
# There are 3 scenarios here:
|
|
${If} ${RunningX64}
|
|
StrCpy $INSTDIR "$ProgramFiles64\Salt Project\Salt"
|
|
${Else}
|
|
# 32 bit Salt on 32 bit system (C:\Program Files)
|
|
StrCpy $INSTDIR "$ProgramFiles\Salt Project\Salt"
|
|
${EndIf}
|
|
|
|
# This makes the $APPDATA variable point to the ProgramData folder instead
|
|
# of the current user's roaming AppData folder
|
|
SetShellVarContext all
|
|
|
|
# Set default location of for salt config
|
|
StrCpy $RootDir "$APPDATA\Salt Project\Salt"
|
|
|
|
# The NSIS installer is a 32bit application and will use the WOW6432Node in
|
|
# the registry by default. We need to look in the 64 bit location on 64 bit
|
|
# systems
|
|
${If} ${RunningX64}
|
|
# https://nsis.sourceforge.io/Docs/Chapter4.html#setregview
|
|
SetRegView 64 # View the 64 bit portion of the registry
|
|
${EndIf}
|
|
|
|
# Check for existing new method installation from registry
|
|
# Look for `install_dir` in HKLM\SOFTWARE\Salt Project\Salt
|
|
ReadRegStr $R0 HKLM "SOFTWARE\Salt Project\Salt" "install_dir"
|
|
StrCmp $R0 "" checkOldInstallation
|
|
StrCpy $ExistingInstallation 1
|
|
|
|
# Set INSTDIR to the location in the registry
|
|
StrCpy $INSTDIR $R0
|
|
# Expand any environment variables it contains
|
|
ExpandEnvStrings $INSTDIR $INSTDIR
|
|
|
|
# Set RootDir, if defined
|
|
ReadRegStr $R0 HKLM "SOFTWARE\Salt Project\Salt" "root_dir"
|
|
StrCmp $R0 "" finished
|
|
StrCpy $RootDir $R0
|
|
# Expand any environment variables it contains
|
|
ExpandEnvStrings $RootDir $RootDir
|
|
Goto finished
|
|
|
|
# Check for existing old method installation
|
|
# Look for `python.exe` in C:\salt\bin
|
|
checkOldInstallation:
|
|
IfFileExists "C:\salt\bin\python.exe" 0 newInstallation
|
|
StrCpy $ExistingInstallation 1
|
|
StrCpy $INSTDIR "C:\salt"
|
|
StrCpy $RootDir "C:\salt"
|
|
Goto finished
|
|
|
|
# This is a new installation
|
|
# Check if custom location was passed via command line
|
|
newInstallation:
|
|
${IfNot} $CustomLocation == ""
|
|
StrCpy $INSTDIR $CustomLocation
|
|
${EndIf}
|
|
|
|
finished:
|
|
SetRegView 32 # View the 32 bit portion of the registry
|
|
|
|
FunctionEnd
|
|
|
|
|
|
Function getExistingMinionConfig
|
|
|
|
# Set Config Found Default Value
|
|
StrCpy $ExistingConfigFound 0
|
|
|
|
# Find config, should be in $RootDir\conf\minion
|
|
# Root dir is usually ProgramData\Salt Project\Salt\conf though it may be
|
|
# C:\salt\conf if Salt was installed the old way
|
|
|
|
IfFileExists "$RootDir\conf\minion" check_owner
|
|
IfFileExists "C:\salt\conf\minion" old_location confNotFound
|
|
|
|
old_location:
|
|
StrCpy $RootDir "C:\salt"
|
|
|
|
check_owner:
|
|
# We need to verify the owner of the config directory (C:\salt\conf) to
|
|
# ensure the config has not been modified by an unknown user. The
|
|
# permissions and ownership of the directories is determined by the
|
|
# installer used to install Salt. The NullSoft installer requests Admin
|
|
# privileges so all directories are created with the Administrators
|
|
# Group (S-1-5-32-544) as the owner. The MSI installer, however, runs in
|
|
# the context of the Windows Installer service (msiserver), therefore
|
|
# all directories are created with the Local System account (S-1-5-18)
|
|
# as the owner.
|
|
#
|
|
# When Salt is launched it sets the root_dir (C:\salt) permissions as
|
|
# follows:
|
|
# - Owner: Administrators
|
|
# - Allow Perms:
|
|
# - Owner: Full Control
|
|
# - System: Full Control
|
|
# - Administrators: Full Control
|
|
#
|
|
# The conf_dir (C:\salt\conf) inherits Allow/Deny permissions from the
|
|
# parent, but NOT Ownership. The owner will be the Administrators Group
|
|
# if it was installed via NullSoft or the Local System account if it was
|
|
# installed via the MSI. Therefore valid owners for the conf_dir are
|
|
# both the Administrators group and the Local System account.
|
|
#
|
|
# An unprivileged account cannot change the owner of a directory by
|
|
# default. So, if the owner of the conf_dir is either the Administrators
|
|
# group or the Local System account, then we will trust it. Otherwise,
|
|
# we will display an option to abort the installation or to backup the
|
|
# untrusted config directory and continue with the default config. If
|
|
# running the install with the silent option (/S) it will backup the
|
|
# untrusted config directory and continue with the default config.
|
|
|
|
AccessControl::GetFileOwner /SID "$RootDir\conf"
|
|
Pop $0
|
|
|
|
# Check for valid SIDs
|
|
StrCmp $0 "S-1-5-32-544" correct_owner # Administrators Group (NullSoft)
|
|
StrCmp $0 "S-1-5-18" correct_owner # Local System (MSI)
|
|
MessageBox MB_YESNO \
|
|
"Insecure config found at $RootDir\conf. If you continue, the \
|
|
config directory will be renamed to $RootDir\conf.insecure \
|
|
and the default config will be used. Continue?" \
|
|
/SD IDYES IDYES insecure_config
|
|
Abort
|
|
|
|
insecure_config:
|
|
# Backing up insecure config
|
|
Rename "$RootDir\conf" "$RootDir\conf.insecure-${TIME_STAMP}"
|
|
Goto confNotFound
|
|
|
|
correct_owner:
|
|
StrCpy $ExistingConfigFound 1
|
|
FileOpen $0 "$RootDir\conf\minion" r
|
|
|
|
confLoop:
|
|
ClearErrors # clear Errors
|
|
FileRead $0 $1 # read the next line
|
|
IfErrors EndOfFile # error is probably EOF
|
|
${StrLoc} $2 $1 "master:" ">" # find `master:` starting at the beginning
|
|
${If} $2 == 0 # if it found it in the first position, then it is defined
|
|
${StrStrAdv} $2 $1 "master: " ">" ">" "0" "0" "0" # read everything after `master: `
|
|
${Trim} $2 $2 # trim white space
|
|
${If} $2 == "" # if it's empty, it's probably a list of masters
|
|
masterLoop:
|
|
ClearErrors # clear Errors
|
|
FileRead $0 $1 # read the next line
|
|
IfErrors EndOfFile # error is probably EOF
|
|
${StrStrAdv} $2 $1 "- " ">" ">" "0" "0" "0" # read everything after `- `
|
|
${Trim} $2 $2 # trim white space
|
|
${IfNot} $2 == "" # if the line is not empty, we found something
|
|
${If} $MasterHost_Cfg == "" # if the config setting is empty
|
|
StrCpy $MasterHost_Cfg $2 # make the first item the new entry
|
|
${Else}
|
|
StrCpy $MasterHost_Cfg "$MasterHost_Cfg,$2" # Append the new master, comma separated
|
|
${EndIf}
|
|
Goto masterLoop # check the next one
|
|
${EndIf}
|
|
${Else}
|
|
StrCpy $MasterHost_Cfg $2 # a single master entry
|
|
${EndIf}
|
|
${EndIf}
|
|
|
|
${StrLoc} $2 $1 "id:" ">"
|
|
${If} $2 == 0
|
|
${StrStrAdv} $2 $1 "id: " ">" ">" "0" "0" "0"
|
|
${Trim} $2 $2
|
|
StrCpy $MinionName_Cfg $2
|
|
${EndIf}
|
|
|
|
Goto confLoop
|
|
|
|
EndOfFile:
|
|
FileClose $0
|
|
|
|
confNotFound:
|
|
|
|
# Set Default Config Values if not found
|
|
${If} $MasterHost_Cfg == ""
|
|
StrCpy $MasterHost_Cfg "salt"
|
|
${EndIf}
|
|
${If} $MinionName_Cfg == ""
|
|
StrCpy $MinionName_Cfg "hostname"
|
|
${EndIf}
|
|
|
|
FunctionEnd
|
|
|
|
|
|
Var cfg_line
|
|
Var chk_line
|
|
Var lst_check
|
|
Function updateMinionConfig
|
|
|
|
ClearErrors
|
|
FileOpen $0 "$RootDir\conf\minion" "r" # open target file for reading
|
|
GetTempFileName $R0 # get new temp file name
|
|
FileOpen $1 $R0 "w" # open temp file for writing
|
|
|
|
StrCpy $ConfigWriteMaster 1 # write the master config value
|
|
StrCpy $ConfigWriteMinion 1 # write the minion config value
|
|
|
|
loop: # loop through each line
|
|
FileRead $0 $cfg_line # read line from target file
|
|
IfErrors done # end if errors are encountered (end of line)
|
|
|
|
loop_after_read:
|
|
StrCpy $lst_check 0 # list check not performed
|
|
|
|
${If} $MasterHost == "" # if master is empty
|
|
${OrIf} $MasterHost == "salt" # or if master is 'salt'
|
|
StrCpy $ConfigWriteMaster 0 # no need to write master config
|
|
${EndIf} # close if statement
|
|
${If} $MinionName == "" # if minion is empty
|
|
${OrIf} $MinionName == "hostname" # and if minion is not 'hostname'
|
|
StrCpy $ConfigWriteMinion 0 # no need to write minion config
|
|
${EndIf} # close if statement
|
|
|
|
${If} $ConfigWriteMaster == 1 # if we need to write master config
|
|
|
|
${StrLoc} $3 $cfg_line "master:" ">" # where is 'master:' in this line
|
|
${If} $3 == 0 # is it in the first...
|
|
${OrIf} $3 == 1 # or second position (account for comments)
|
|
|
|
${Explode} $9 "," $MasterHost # Split the hostname on commas, $9 is the number of items found
|
|
${If} $9 == 1 # 1 means only a single master was passed
|
|
StrCpy $cfg_line "master: $MasterHost$\r$\n" # write the master
|
|
${Else} # make a multi-master entry
|
|
StrCpy $cfg_line "master:" # make the first line "master:"
|
|
|
|
loop_explode: # start a loop to go through the list in the config
|
|
pop $8 # pop the next item off the stack
|
|
${Trim} $8 $8 # trim any whitespace
|
|
StrCpy $cfg_line "$cfg_line$\r$\n - $8" # add it to the master variable ($2)
|
|
IntOp $9 $9 - 1 # decrement the list count
|
|
${If} $9 >= 1 # if it's not 0
|
|
Goto loop_explode # do it again
|
|
${EndIf} # close if statement
|
|
StrCpy $cfg_line "$cfg_line$\r$\n" # Make sure there's a new line at the end
|
|
|
|
# Remove remaining items in list
|
|
${While} $lst_check == 0 # while list item found
|
|
FileRead $0 $chk_line # read line from target file
|
|
IfErrors done # end if errors are encountered (end of line)
|
|
${StrLoc} $3 $chk_line " - " ">" # where is 'master:' in this line
|
|
${If} $3 == "" # is it in the first...
|
|
StrCpy $lst_check 1 # list check performed and finished
|
|
${EndIf}
|
|
${EndWhile}
|
|
|
|
${EndIf} # close if statement
|
|
|
|
StrCpy $ConfigWriteMaster 0 # master value written to config
|
|
|
|
${EndIf} # close if statement
|
|
${EndIf} # close if statement
|
|
|
|
${If} $ConfigWriteMinion == 1 # if we need to write minion config
|
|
${StrLoc} $3 $cfg_line "id:" ">" # where is 'id:' in this line
|
|
${If} $3 == 0 # is it in the first...
|
|
${OrIf} $3 == 1 # or the second position (account for comments)
|
|
StrCpy $cfg_line "id: $MinionName$\r$\n" # write the minion config setting
|
|
StrCpy $ConfigWriteMinion 0 # minion value written to config
|
|
${EndIf} # close if statement
|
|
${EndIf} # close if statement
|
|
|
|
FileWrite $1 $cfg_line # write changed or unchanged line to temp file
|
|
|
|
${If} $lst_check == 1 # master not written to the config
|
|
StrCpy $cfg_line $chk_line
|
|
Goto loop_after_read # A loop was performed, skip the next read
|
|
${EndIf} # close if statement
|
|
|
|
Goto loop # check the next line in the config file
|
|
|
|
done:
|
|
ClearErrors
|
|
# Does master config still need to be written
|
|
${If} $ConfigWriteMaster == 1 # master not written to the config
|
|
|
|
${Explode} $9 "," $MasterHost # split the hostname on commas, $9 is the number of items found
|
|
${If} $9 == 1 # 1 means only a single master was passed
|
|
StrCpy $cfg_line "master: $MasterHost" # write the master
|
|
${Else} # make a multi-master entry
|
|
StrCpy $cfg_line "master:" # make the first line "master:"
|
|
|
|
loop_explode_2: # start a loop to go through the list in the config
|
|
pop $8 # pop the next item off the stack
|
|
${Trim} $8 $8 # trim any whitespace
|
|
StrCpy $cfg_line "$cfg_line$\r$\n - $8" # add it to the master variable ($2)
|
|
IntOp $9 $9 - 1 # decrement the list count
|
|
${If} $9 >= 1 # if it's not 0
|
|
Goto loop_explode_2 # do it again
|
|
${EndIf} # close if statement
|
|
${EndIf} # close if statement
|
|
FileWrite $1 $cfg_line # write changed or unchanged line to temp file
|
|
|
|
${EndIf} # close if statement
|
|
|
|
${If} $ConfigWriteMinion == 1 # minion ID not written to the config
|
|
StrCpy $cfg_line "$\r$\nid: $MinionName" # write the minion config setting
|
|
FileWrite $1 $cfg_line # write changed or unchanged line to temp file
|
|
${EndIf} # close if statement
|
|
|
|
FileClose $0 # close target file
|
|
FileClose $1 # close temp file
|
|
Delete "$RootDir\conf\minion" # delete target file
|
|
CopyFiles /SILENT $R0 "$RootDir\conf\minion" # copy temp file to target file
|
|
Delete $R0 # delete temp file
|
|
|
|
FunctionEnd
|
|
|
|
|
|
Function un.parseUninstallerCommandLineSwitches
|
|
|
|
# Load the parameters
|
|
${GetParameters} $R0
|
|
|
|
# Display Help
|
|
ClearErrors
|
|
${GetOptions} $R0 "/?" $R1
|
|
IfErrors display_un_help_not_found
|
|
|
|
# Using a message box here
|
|
# I couldn't get the console output to work with the uninstaller
|
|
MessageBox MB_OK \
|
|
"Help for Salt Minion Uninstallation\
|
|
$\n\
|
|
$\n==============================================\
|
|
$\n\
|
|
$\n/delete-install-dir$\tDelete the installation directory that contains the\
|
|
$\n$\t$\tconfig and pki directories. Default is to not delete\
|
|
$\n$\t$\tthe installation directory\
|
|
$\n\
|
|
$\n$\t$\tThis applies to old method installations where\
|
|
$\n$\t$\tthe root directory and the installation directory\
|
|
$\n$\t$\tare the same (C:\salt)\
|
|
$\n\
|
|
$\n/delete-root-dir$\tDelete the root directory that contains the config\
|
|
$\n$\t$\tand pki directories. Also removes the installation directory\
|
|
$\n$\t$\tincluding the extras directory. Default is to not delete\
|
|
$\n\
|
|
$\n$\t$\tThis applies to new method installations where the\
|
|
$\n$\t$\troot directory is in ProgramData and the installation\
|
|
$\n$\t$\tdirectory is user defined, usually Program Files\
|
|
$\n\
|
|
$\n/S$\t$\tUninstall Salt silently\
|
|
$\n\
|
|
$\n/?$\t$\tDisplay this help screen\
|
|
$\n\
|
|
$\n--------------------------------------------------------------------------------------------\
|
|
$\n\
|
|
$\nExamples:\
|
|
$\n\
|
|
$\n$\tuninst.exe /S\
|
|
$\n\
|
|
$\n$\tuninst.exe /S /delete-root-dir\
|
|
$\n\
|
|
$\n=============================================="
|
|
|
|
Abort
|
|
|
|
display_un_help_not_found:
|
|
|
|
# Load the parameters
|
|
${GetParameters} $R0
|
|
|
|
# Uninstaller: Remove Installation Directory
|
|
ClearErrors
|
|
${GetOptions} $R0 "/delete-install-dir" $R1
|
|
IfErrors delete_install_dir_not_found
|
|
StrCpy $DeleteInstallDir 1
|
|
delete_install_dir_not_found:
|
|
|
|
# Uninstaller: Remove Root Directory
|
|
ClearErrors
|
|
${GetOptions} $R0 "/delete-root-dir" $R1
|
|
IfErrors delete_root_dir_not_found
|
|
StrCpy $DeleteRootDir 1
|
|
delete_root_dir_not_found:
|
|
|
|
FunctionEnd
|
|
|
|
|
|
Function parseInstallerCommandLineSwitches
|
|
|
|
# Load the parameters
|
|
${GetParameters} $R0
|
|
|
|
# Display Help
|
|
ClearErrors
|
|
${GetOptions} $R0 "/?" $R1
|
|
IfErrors display_help_not_found
|
|
|
|
System::Call 'kernel32::GetStdHandle(i -11)i.r0'
|
|
System::Call 'kernel32::AttachConsole(i -1)i.r1'
|
|
${If} $0 = 0
|
|
${OrIf} $1 = 0
|
|
System::Call 'kernel32::AllocConsole()'
|
|
System::Call 'kernel32::GetStdHandle(i -11)i.r0'
|
|
${EndIf}
|
|
FileWrite $0 "$\n"
|
|
FileWrite $0 "$\n"
|
|
FileWrite $0 "Help for Salt Minion installation$\n"
|
|
FileWrite $0 "===============================================================================$\n"
|
|
FileWrite $0 "$\n"
|
|
FileWrite $0 "/minion-name=$\t$\tA string value to set the minion name. Default value is$\n"
|
|
FileWrite $0 "$\t$\t$\t'hostname'. Setting the minion name causes the installer$\n"
|
|
FileWrite $0 "$\t$\t$\tto use the default config or a custom config if defined$\n"
|
|
FileWrite $0 "$\n"
|
|
FileWrite $0 "/master=$\t$\tA string value to set the IP address or hostname of the$\n"
|
|
FileWrite $0 "$\t$\t$\tmaster. Default value is 'salt'. You may pass a single$\n"
|
|
FileWrite $0 "$\t$\t$\tmaster or a comma-separated list of masters. Setting$\n"
|
|
FileWrite $0 "$\t$\t$\tthe master will cause the installer to use the default$\n"
|
|
FileWrite $0 "$\t$\t$\tconfig or a custom config if defined$\n"
|
|
FileWrite $0 "$\n"
|
|
FileWrite $0 "/start-minion=$\t$\t1 will start the minion service, 0 will not.$\n"
|
|
FileWrite $0 "$\t$\t$\tDefault is 1$\n"
|
|
FileWrite $0 "$\n"
|
|
FileWrite $0 "/start-minion-delayed$\tSet the minion start type to 'Automatic (Delayed Start)'$\n"
|
|
FileWrite $0 "$\n"
|
|
FileWrite $0 "/default-config$\t$\tOverwrite the existing config if present with the$\n"
|
|
FileWrite $0 "$\t$\t$\tdefault config for salt. Default is to use the existing$\n"
|
|
FileWrite $0 "$\t$\t$\tconfig if present. If /master and/or /minion-name is$\n"
|
|
FileWrite $0 "$\t$\t$\tpassed, those values will be used to update the new$\n"
|
|
FileWrite $0 "$\t$\t$\tdefault config$\n"
|
|
FileWrite $0 "$\n"
|
|
FileWrite $0 "$\t$\t$\tAny existing config will be backed up by appending$\n"
|
|
FileWrite $0 "$\t$\t$\ta timestamp and a .bak extension. That includes$\n"
|
|
FileWrite $0 "$\t$\t$\tthe minion file and the minion.d directory$\n"
|
|
FileWrite $0 "$\n"
|
|
FileWrite $0 "/custom-config=$\t$\tA string value specifying the name of a custom config$\n"
|
|
FileWrite $0 "$\t$\t$\tfile in the same path as the installer or the full path$\n"
|
|
FileWrite $0 "$\t$\t$\tto a custom config file. If /master and/or /minion-name$\n"
|
|
FileWrite $0 "$\t$\t$\tis passed, those values will be used to update the new$\n"
|
|
FileWrite $0 "$\t$\t$\tcustom config$\n"
|
|
FileWrite $0 "$\n"
|
|
FileWrite $0 "$\t$\t$\tAny existing config will be backed up by appending$\n"
|
|
FileWrite $0 "$\t$\t$\ta timestamp and a .bak extension. That includes$\n"
|
|
FileWrite $0 "$\t$\t$\tthe minion file and the minion.d directory$\n"
|
|
FileWrite $0 "$\n"
|
|
FileWrite $0 "/install-dir=$\t$\tSpecify the installation location for the Salt binaries.$\n"
|
|
FileWrite $0 "$\t$\t$\tThis will be ignored for existing installations.$\n"
|
|
FileWrite $0 "$\n"
|
|
FileWrite $0 "/move-config$\t$\tIf config is found at C:\salt it will be moved to %ProgramData%$\n"
|
|
FileWrite $0 "$\n"
|
|
FileWrite $0 "/S$\t$\t$\tInstall Salt silently$\n"
|
|
FileWrite $0 "$\n"
|
|
FileWrite $0 "/?$\t$\t$\tDisplay this help screen$\n"
|
|
FileWrite $0 "$\n"
|
|
FileWrite $0 "-------------------------------------------------------------------------------$\n"
|
|
FileWrite $0 "$\n"
|
|
FileWrite $0 "Examples:$\n"
|
|
FileWrite $0 "$\n"
|
|
FileWrite $0 " $EXEFILE /S$\n"
|
|
FileWrite $0 "$\n"
|
|
FileWrite $0 " $EXEFILE /S /minion-name=myminion /master=master.mydomain.com /start-minion-delayed$\n"
|
|
FileWrite $0 "$\n"
|
|
FileWrite $0 " $EXEFILE /S /minion-name=myminion /master=master.mydomain.com /install-dir=$\"C:\Software\salt$\"$\n"
|
|
FileWrite $0 "$\n"
|
|
FileWrite $0 "===============================================================================$\n"
|
|
FileWrite $0 "$\n"
|
|
System::Free $0
|
|
System::Free $1
|
|
System::Call 'kernel32::FreeConsole()'
|
|
|
|
# Give the user back the prompt
|
|
!define VK_RETURN 0x0D ; Enter Key
|
|
!define KEYEVENTF_EXTENDEDKEY 0x0001
|
|
!define KEYEVENTF_KEYUP 0x0002
|
|
System::Call "user32::keybd_event(i${VK_RETURN}, i0x45, i${KEYEVENTF_EXTENDEDKEY}|0, i0)"
|
|
System::Call "user32::keybd_event(i${VK_RETURN}, i0x45, i${KEYEVENTF_EXTENDEDKEY}|${KEYEVENTF_KEYUP}, i0)"
|
|
Abort
|
|
|
|
display_help_not_found:
|
|
|
|
# Set default value for Use Existing Config
|
|
StrCpy $ConfigType "Existing Config"
|
|
|
|
# Check for start-minion switches
|
|
# /start-service is to be deprecated, so we must check for both
|
|
${GetOptions} $R0 "/start-service=" $R1
|
|
${GetOptions} $R0 "/start-minion=" $R2
|
|
|
|
# Service: Start Salt Minion
|
|
${IfNot} $R2 == ""
|
|
# If start-minion was passed something, then set it
|
|
StrCpy $StartMinion $R2
|
|
${ElseIfNot} $R1 == ""
|
|
# If start-service was passed something, then set StartMinion to that
|
|
StrCpy $StartMinion $R1
|
|
MessageBox MB_OK|MB_ICONINFORMATION \
|
|
"`/start-service` is being deprecated. Please use `/start-minion` \
|
|
instead." /SD IDOK
|
|
${Else}
|
|
# Otherwise default to 1
|
|
StrCpy $StartMinion 1
|
|
${EndIf}
|
|
|
|
# Service: Minion Startup Type Delayed
|
|
ClearErrors
|
|
${GetOptions} $R0 "/start-minion-delayed" $R1
|
|
IfErrors start_minion_delayed_not_found
|
|
StrCpy $StartMinionDelayed 1
|
|
start_minion_delayed_not_found:
|
|
|
|
# Minion Config: Master IP/Name
|
|
# If setting master, we don't want to use existing config
|
|
${GetOptions} $R0 "/master=" $R1
|
|
${IfNot} $R1 == ""
|
|
StrCpy $MasterHost $R1
|
|
StrCpy $ConfigType "Default Config"
|
|
${ElseIf} $MasterHost == ""
|
|
StrCpy $MasterHost "salt"
|
|
${EndIf}
|
|
|
|
# Minion Config: Minion ID
|
|
# If setting minion id, we don't want to use existing config
|
|
${GetOptions} $R0 "/minion-name=" $R1
|
|
${IfNot} $R1 == ""
|
|
StrCpy $MinionName $R1
|
|
StrCpy $ConfigType "Default Config"
|
|
${ElseIf} $MinionName == ""
|
|
StrCpy $MinionName "hostname"
|
|
${EndIf}
|
|
|
|
# Use Default Config
|
|
ClearErrors
|
|
${GetOptions} $R0 "/default-config" $R1
|
|
IfErrors default_config_not_found
|
|
StrCpy $ConfigType "Default Config"
|
|
default_config_not_found:
|
|
|
|
# Use Custom Config
|
|
# Set default value for Use Custom Config
|
|
StrCpy $CustomConfig ""
|
|
# Existing config will get a `.bak` extension
|
|
${GetOptions} $R0 "/custom-config=" $R1
|
|
${IfNot} $R1 == ""
|
|
# A Custom Config was passed, set it
|
|
StrCpy $CustomConfig $R1
|
|
StrCpy $ConfigType "Custom Config"
|
|
${EndIf}
|
|
|
|
# Set Install Location
|
|
ClearErrors
|
|
${GetOptions} $R0 "/install-dir=" $R1
|
|
${IfNot} $R1 == ""
|
|
# A Custom Location was passed, set it
|
|
StrCpy $CustomLocation $R1
|
|
${EndIf}
|
|
|
|
# Set Move Config Option
|
|
ClearErrors
|
|
${GetOptions} $R0 "/move-config" $R1
|
|
IfErrors move_config_not_found
|
|
StrCpy $MoveExistingConfig 1
|
|
move_config_not_found:
|
|
|
|
FunctionEnd
|