Finish integration tests

This commit is contained in:
Adrien Ferrand 2020-02-13 17:02:38 +01:00
parent a37acc90eb
commit 2dbb121e35
5 changed files with 79 additions and 124 deletions

View file

@ -55,8 +55,8 @@ def github_mock(installer):
pass
class GitHubMock(BaseHTTPRequestHandler):
# def log_message(self, log_format, *args):
# pass
def log_message(self, log_format, *args):
pass
def do_GET(self):
if re.match(r'^.*/releases/latest$', self.path):
@ -95,8 +95,8 @@ def github_mock(installer):
server.server_close()
@pytest.fixture(autouse=True)
def registry_config(signing_cert, github_mock):
@pytest.fixture
def upgrade_env(signing_cert, github_mock):
try:
_ps('New-Item -Path HKLM:\\Software -Name Certbot -ErrorAction SilentlyContinue | Out-Null; exit 0')
_ps('New-ItemProperty -Path HKLM:\\Software\\Certbot -Name CertbotUpgradeApiURL -Value {} '
@ -105,62 +105,76 @@ def registry_config(signing_cert, github_mock):
'([Convert]::ToBase64String((Get-PfxCertificate -FilePath {0}).GetPublicKey())) '
'| Out-Null'.format(signing_cert))
yield
yield True
finally:
_ps('Remove-ItemProperty -Path HKLM:\\Software\\Certbot -Name CertbotUpgradeApiURL')
_ps('Remove-ItemProperty -Path HKLM:\\Software\\Certbot -Name CertbotSigningPubKey')
@unittest.skipIf(os.name != 'nt', reason='Windows installer tests must be run on Windows.')
def test_it(installer):
def test_base(installer):
_assert_certbot_is_broken()
# Install certbot
subprocess.check_output([installer, '/S'])
# Assert certbot is installed and runnable
output = subprocess.check_output('certbot --version', shell=True, universal_newlines=True)
assert re.match(r'^certbot \d+\.\d+\.\d+.*$', output), 'Flag --version does not output a version.'
# Assert the renew + auto-upgrade task is installed and ready
output = _ps('(Get-ScheduledTask -TaskName "{}").State'.format(SCHEDULED_TASK_NAME), capture_stdout=True)
assert output.strip() == 'Ready'
# Trigger the renew + auto-upgrade task, expecting Certbot to check for certificate renewals.
now = time.time()
_ps('Start-ScheduledTask -TaskName "{}"'.format(SCHEDULED_TASK_NAME))
_wait_for_task_completion()
log_path = os.path.join('C:\\', 'Certbot', 'log', 'letsencrypt.log')
modification_time = os.path.getmtime(log_path)
assert now < modification_time, 'Certbot log file has not been modified by the renew task.'
with open(log_path) as file_h:
data = file_h.read()
assert 'no renewal failures' in data, 'Renew task did not execute properly.'
# NB: This test must sit after test_base, because it needs to have
# a working installation of Certbot, and test_base does that.
@unittest.skipIf(os.name != 'nt', reason='Windows installer tests must be run on Windows.')
def test_upgrade(upgrade_env):
assert upgrade_env
subprocess.check_output(['certbot', '--version'])
# Break on purpose certbot
_ps('Remove-Item "${env:ProgramFiles(x86)}\\Certbot\\bin\\certbot.exe" -Confirm:$false')
_assert_certbot_is_broken()
# Trigger the renew + auto-upgrade task, expecting Certbot to be reinstalled and functional again.
now = time.time()
_ps('Start-ScheduledTask -TaskName "{}"'.format(SCHEDULED_TASK_NAME))
_wait_for_task_completion()
subprocess.check_output(['certbot', '--version'])
def _assert_certbot_is_broken():
try:
subprocess.check_call('certbot --version', shell=True)
subprocess.check_output(['certbot', '--version'])
except (subprocess.CalledProcessError, OSError):
pass
else:
raise AssertionError('Expect certbot to not be available in the PATH.')
try:
# Install certbot
subprocess.check_call([installer, '/S'])
# Assert certbot is installed and runnable
output = subprocess.check_output('certbot --version', shell=True, universal_newlines=True)
assert re.match(r'^certbot \d+\.\d+\.\d+.*$', output), 'Flag --version does not output a version.'
# Assert renew task is installed and ready
output = _ps('(Get-ScheduledTask -TaskName "{}").State'.format(SCHEDULED_TASK_NAME), capture_stdout=True)
assert output.strip() == 'Ready'
# Assert renew task is working
now = time.time()
_ps('Start-ScheduledTask -TaskName "{}"'.format(SCHEDULED_TASK_NAME))
status = 'Running'
while status != 'Ready':
status = _ps('(Get-ScheduledTask -TaskName "{}").State'
.format(SCHEDULED_TASK_NAME), capture_stdout=True).strip()
time.sleep(1)
log_path = os.path.join('C:\\', 'Certbot', 'log', 'letsencrypt.log')
modification_time = os.path.getmtime(log_path)
assert now < modification_time, 'Certbot log file has not been modified by the renew task.'
with open(log_path) as file_h:
data = file_h.read()
assert 'no renewal failures' in data, 'Renew task did not execute properly.'
finally:
# Sadly this command cannot work in non interactive mode: uninstaller will ask explicitly permission in an UAC prompt
# print('Uninstalling Certbot ...')
# uninstall_path = _ps('(gci "HKLM:\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall"'
# ' | foreach { gp $_.PSPath }'
# ' | ? { $_ -match "Certbot" }'
# ' | select UninstallString)'
# '.UninstallString', capture_stdout=True)
# subprocess.check_call([uninstall_path, '/S'])
pass
def _wait_for_task_completion():
status = 'Running'
while status != 'Ready':
status = _ps('(Get-ScheduledTask -TaskName "{}").State'
.format(SCHEDULED_TASK_NAME), capture_stdout=True).strip()
time.sleep(1)
def _ps(powershell_str, capture_stdout=False):

View file

@ -112,11 +112,11 @@ Aborting auto-upgrade process.
if (Test-Path $installDir\uninstall.exe) {
# Uninstall old Certbot first
Write-Message "Running the uninstaller for old version (install dir: $installDir) ..."
Start-Process -FilePath $installDir\uninstall.exe -ArgumentList "/S _?=$installDir"
Start-Process -FilePath $installDir\uninstall.exe -ArgumentList "/S" -Wait
}
# Install new version of Certbot
Write-Message "Running the installer for new version (install dir: $installDir) ..."
Start-Process -FilePath $installerPath -ArgumentList "/S /D=$installDir"
Start-Process -FilePath $installerPath -ArgumentList "/S /D=$installDir" -Wait
Write-Message "Certbot $latestVersion is installed."
} catch {

View file

@ -11,7 +11,7 @@ $down = Join-Path (Get-ScriptDirectory) 'tasks-down.ps1'
$taskName = "Certbot Renew & Auto-Update Task"
$taskDescription = "Execute twice a day the 'certbot renew' command, to renew managed certificates if needed, and upgrade Certbot is a new version is available."
$actionRenew = New-ScheduledTaskAction -Execute 'Powershell.exe' -Argument '-NoProfile -WindowStyle Hidden -Command "certbot renew"'
$actionRenew = New-ScheduledTaskAction -Execute 'Powershell.exe' -Argument "-NoProfile -WindowStyle Hidden -Command ""& '$InstallDir\bin\certbot.exe' renew"""
$actionUpgrade = New-ScheduledTaskAction -Execute 'Powershell.exe' -Argument "-NoProfile -WindowStyle Hidden -File ""$InstallDir\auto-update.ps1"""
$delay = New-TimeSpan -Hours 12

Binary file not shown.

View file

@ -1,7 +1,12 @@
; This NSIS template is based on the built-in one in pynsist 2.3.
; Added lines are enclosed within "CERTBOT CUSTOM BEGIN/END" comments.
; If pynsist is upgraded, this template must be updated if necessary using the new built-in one.
; This NSIS template is based on the built-in one in pynsist 2.4.
; If pynsist is upgraded, this template may be updated if necessary using the new built-in one.
; Original file can be found here: https://github.com/takluyver/pynsist/blob/2.4/nsist/pyapp.nsi
; Diff file is located at .\template-nsi.patch
; Require the installer do be installed with admin privileges
RequestExecutionLevel admin
; Set default installation path (overridable with /D= flag)
InstallDir "$PROGRAMFILES\Certbot"
!define PRODUCT_NAME "[[ib.appname]]"
!define PRODUCT_VERSION "[[ib.version]]"
@ -11,31 +16,9 @@
!define ARCH_TAG "[[arch_tag]]"
!define INSTALLER_NAME "[[ib.installer_name]]"
!define PRODUCT_ICON "[[icon]]"
; Marker file to tell the uninstaller that it's a user installation
!define USER_INSTALL_MARKER _user_install_marker
SetCompressor lzma
; CERTBOT CUSTOM BEGIN
; Administrator privileges are required to insert a new task in Windows Scheduler.
; Also comment out some options to disable ability to choose AllUsers/CurrentUser install mode.
; As a result, installer run always with admin privileges (because of MULTIUSER_EXECUTIONLEVEL),
; using the AllUsers installation mode by default (because of MULTIUSER_INSTALLMODE_DEFAULT_CURRENTUSER
; not set), and this default behavior cannot be overridden (because of MULTIUSER_MUI not set).
; See https://nsis.sourceforge.io/Docs/MultiUser/Readme.html
!define MULTIUSER_EXECUTIONLEVEL Admin
;!define MULTIUSER_EXECUTIONLEVEL Highest
;!define MULTIUSER_INSTALLMODE_DEFAULT_CURRENTUSER
;!define MULTIUSER_MUI
;!define MULTIUSER_INSTALLMODE_COMMANDLINE
; CERTBOT CUSTOM END
!define MULTIUSER_INSTALLMODE_INSTDIR "[[ib.appname]]"
[% if ib.py_bitness == 64 %]
!define MULTIUSER_INSTALLMODE_FUNCTION correct_prog_files
[% endif %]
!include MultiUser.nsh
[% block modernui %]
; Modern UI installer stuff
!include "MUI2.nsh"
@ -49,10 +32,6 @@ SetCompressor lzma
[% if license_file %]
!insertmacro MUI_PAGE_LICENSE [[license_file]]
[% endif %]
; CERTBOT CUSTOM BEGIN
; Disable the installation mode page (AllUsers/CurrentUser)
;!insertmacro MULTIUSER_PAGE_INSTALLMODE
; CERTBOT CUSTOM END
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH
@ -60,10 +39,7 @@ SetCompressor lzma
!insertmacro MUI_LANGUAGE "English"
[% endblock modernui %]
; CERTBOT CUSTOM BEGIN
Name "${PRODUCT_NAME} (beta) ${PRODUCT_VERSION}"
;Name "${PRODUCT_NAME} ${PRODUCT_VERSION}"
; CERTBOT CUSTOM END
OutFile "${INSTALLER_NAME}"
ShowInstDetails show
@ -76,18 +52,13 @@ SectionEnd
Section "!${PRODUCT_NAME}" sec_app
SetRegView [[ib.py_bitness]]
SetShellVarContext all
SectionIn RO
File ${PRODUCT_ICON}
SetOutPath "$INSTDIR\pkgs"
File /r "pkgs\*.*"
SetOutPath "$INSTDIR"
; Marker file for per-user install
StrCmp $MultiUser.InstallMode CurrentUser 0 +3
FileOpen $0 "$INSTDIR\${USER_INSTALL_MARKER}" w
FileClose $0
SetFileAttributes "$INSTDIR\${USER_INSTALL_MARKER}" HIDDEN
[% block install_files %]
; Install files
[% for destination, group in grouped_files %]
@ -129,14 +100,8 @@ Section "!${PRODUCT_NAME}" sec_app
DetailPrint "Setting up command-line launchers..."
nsExec::ExecToLog '[[ python ]] -Es "$INSTDIR\_assemble_launchers.py" [[ python ]] "$INSTDIR\bin"'
StrCmp $MultiUser.InstallMode CurrentUser 0 AddSysPathSystem
; Add to PATH for current user
nsExec::ExecToLog '[[ python ]] -Es "$INSTDIR\_system_path.py" add_user "$INSTDIR\bin"'
GoTo AddedSysPath
AddSysPathSystem:
; Add to PATH for all users
nsExec::ExecToLog '[[ python ]] -Es "$INSTDIR\_system_path.py" add "$INSTDIR\bin"'
AddedSysPath:
; Add to PATH for all users
nsExec::ExecToLog '[[ python ]] -Es "$INSTDIR\_system_path.py" add "$INSTDIR\bin"'
[% endif %]
[% endblock install_commands %]
@ -164,11 +129,9 @@ Section "!${PRODUCT_NAME}" sec_app
WriteRegDWORD SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
"NoRepair" 1
; CERTBOT CUSTOM BEGIN
; Execute ps script to create the certbot renew & auto-update task
DetailPrint "Setting up certbot renew & auto-update scheduled task"
nsExec::ExecToStack 'powershell -inputformat none -ExecutionPolicy RemoteSigned -File "$INSTDIR\tasks-up.ps1" -InstallDir "$INSTDIR"'
; CERTBOT CUSTOM END
; Check if we need to reboot
IfRebootFlag 0 noreboot
@ -179,21 +142,16 @@ Section "!${PRODUCT_NAME}" sec_app
SectionEnd
Section "Uninstall"
; CERTBOT CUSTOM BEGIN
SetRegView [[ib.py_bitness]]
SetShellVarContext all
; Execute ps script to remove the certbot renew & auto-update task, then delete scripts
nsExec::ExecToStack 'powershell -inputformat none -ExecutionPolicy RemoteSigned -File "$INSTDIR\tasks-down.ps1"'
Delete "$INSTDIR\tasks-down.ps1"
Delete "$INSTDIR\tasks-up.ps1"
Delete "$INSTDIR\auto-update.ps1"
; CERTBOT CUSTOM END
SetRegView [[ib.py_bitness]]
SetShellVarContext all
IfFileExists "$INSTDIR\${USER_INSTALL_MARKER}" 0 +3
SetShellVarContext current
Delete "$INSTDIR\${USER_INSTALL_MARKER}"
Delete $INSTDIR\uninstall.exe
Delete "$INSTDIR\uninstall.exe"
Delete "$INSTDIR\${PRODUCT_ICON}"
RMDir /r "$INSTDIR\pkgs"
@ -244,20 +202,3 @@ Function .onMouseOverSection
[% endblock mouseover_messages %]
FunctionEnd
Function .onInit
!insertmacro MULTIUSER_INIT
FunctionEnd
Function un.onInit
!insertmacro MULTIUSER_UNINIT
FunctionEnd
[% if ib.py_bitness == 64 %]
Function correct_prog_files
; The multiuser machinery doesn't know about the different Program files
; folder for 64-bit applications. Override the install dir it set.
StrCmp $MultiUser.InstallMode AllUsers 0 +2
StrCpy $INSTDIR "$PROGRAMFILES64\${MULTIUSER_INSTALLMODE_INSTDIR}"
FunctionEnd
[% endif %]