Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

xDscWebService: Implemented fix for issue 191 #462

Merged
merged 9 commits into from
Jan 26, 2019
Merged

xDscWebService: Implemented fix for issue 191 #462

merged 9 commits into from
Jan 26, 2019

Conversation

tmeckel
Copy link
Contributor

@tmeckel tmeckel commented Nov 13, 2018

Pull Request (PR) description

This Pull Request (PR) implements a fix for issue #191. Although this issue has been closed, I wasn't able to deploy a DSC Pull Server on a server where IIS and IIS Express are installed in parallel. The following errors are shown in while applying the configuration to the computer

VERBOSE: [UIDEFFMIMD54SPS]:                            [[xDSCWebService]PSDSCPullServer] Add Firewall Rule for port 8080
Exception calling "GetSection" with "2" argument(s): "Filename: redirection.config
Error: Cannot read configuration file
"
    + CategoryInfo          : NotSpecified: (:) [], CimException
    + FullyQualifiedErrorId : FileNotFoundException
    + PSComputerName        : localhost
 
The property 'OverrideMode' cannot be found on this object. Verify that the property exists and can be set.
    + CategoryInfo          : InvalidOperation: (:) [], CimException
    + FullyQualifiedErrorId : PropertyNotFound
    + PSComputerName        : localhost
 
Exception calling "GetSection" with "2" argument(s): "Filename: redirection.config
Error: Cannot read configuration file
"
    + CategoryInfo          : NotSpecified: (:) [], CimException
    + FullyQualifiedErrorId : FileNotFoundException
    + PSComputerName        : localhost
 
The property 'OverrideMode' cannot be found on this object. Verify that the property exists and can be set.
    + CategoryInfo          : InvalidOperation: (:) [], CimException
    + FullyQualifiedErrorId : PropertyNotFound
    + PSComputerName        : localhost
 
Exception calling "GetSection" with "2" argument(s): "Filename: redirection.config
Error: Cannot read configuration file
"
    + CategoryInfo          : NotSpecified: (:) [], CimException
    + FullyQualifiedErrorId : FileNotFoundException
    + PSComputerName        : localhost
 
The property 'OverrideMode' cannot be found on this object. Verify that the property exists and can be set.
    + CategoryInfo          : InvalidOperation: (:) [], CimException
    + FullyQualifiedErrorId : PropertyNotFound
    + PSComputerName        : localhost
 
VERBOSE: [UIDEFFMIMD54SPS]:                            [[xDSCWebService]PSDSCPullServer] Set values into the web.config that define the repository for BLUE OS

The operating system the target node is running

OsName               : Microsoft Windows Server 2012 R2 Standard
OsOperatingSystemSKU : StandardServerEdition
OsArchitecture       : 64-bit
WindowsBuildLabEx    : 9600.19125.amd64fre.winblue_ltsb.180812-0703
OsLanguage           : en-US
OsMuiLanguages       : {en-US}

Version and build of PowerShell the target node is running

Name                           Value
----                           -----
PSVersion                      5.1.14409.1012
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.14409.1012
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1

Version of the DSC module that was used ('dev' if using current dev branch)

ResourceType  : MSFT_xDSCWebService
Name          : xDSCWebService
FriendlyName  : xDSCWebService
Module        : xPSDesiredStateConfiguration
ModuleName    : xPSDesiredStateConfiguration
Version       : 8.4.0.0
Path          : C:\Program Files\WindowsPowerShell\Modules\xPSDesiredStateConfiguration\8.4.0.0\DSCResources\MSFT_xDSCWebService\MSFT_xDSCWebService.psm1
ParentPath    : C:\Program Files\WindowsPowerShell\Modules\xPSDesiredStateConfiguration\8.4.0.0\DSCResources\MSFT_xDSCWebService
ImplementedAs : PowerShell
CompanyName   : Microsoft Corporation

This Pull Request (PR) fixes the following issues

Fixes #191

Task list

  • Added an entry under the Unreleased section of the change log in the README.md.
    Entry should say what was changed, and how that affects users (if applicable).
  • Resource documentation added/updated in README.md.
  • Resource parameter descriptions added/updated in README.md, schema.mof
    and comment-based help.
  • Comment-based help added/updated.
  • Localization strings added/updated in all localization files as appropriate.
  • Examples appropriately added/updated.
  • Unit tests added/updated. See DSC Resource Testing Guidelines.
  • Integration tests added/updated (where possible). See DSC Resource Testing Guidelines.
  • New/changed code adheres to DSC Resource Style Guidelines and Best Practices.

This change is Reviewable

Copy link
Contributor

@mhendric mhendric left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: 0 of 2 files reviewed, 5 unresolved discussions (waiting on @tmeckel)

a discussion (no related file):
Need to add a new entry under the Unreleased section of README.md



DSCResources/MSFT_xDSCWebService/MSFT_xDSCWebService.psm1, line 978 at r1 (raw file):

$iisInstallPath = (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\INetStp" -Name InstallPath).InstallPath

Get-ItemProperty should use Named Parameter (-Path)
Also, you should use single quotes instead of double quotes here.


DSCResources/MSFT_xDSCWebService/MSFT_xDSCWebService.psm1, line 983 at r1 (raw file):

$assyPath = Join-Path $iisInstallPath "Microsoft.Web.Administration.dll" -Resolve -ErrorAction:SilentlyContinue

Join-Path should use Named Parameters (-Path and -ChildPath)Also, you should use single quotes instead of double quotes here.


DSCResources/MSFT_xDSCWebService/MSFT_xDSCWebService.psm1, line 989 at r1 (raw file):

"Microsoft.Web.Administration.ServerManager"

Use single quotes here


DSCResources/MSFT_xDSCWebService/en-US/MSFT_xDSCWebService.psd1, line 3 at r1 (raw file):

    ThrowUseSecurityBestPractice     = Error: Cannot use best practice security settings with unencrypted traffic. Please set UseSecurityBestPractices to $false or use a certificate to encrypt pull server traffic.
    FindCertificateBySubjectMultiple = More than one certificate found with subject containing {0} and using template "{1}".

Recommend updating all of the old entries so that the equals sign aligns with the equals sign of the new entry.

@mhendric
Copy link
Contributor

mhendric commented Nov 14, 2018

Looks like this breaks the following Unit test. An update will be required for the corresponding Unit test:

  Describing MSFT_xDSCWebService\Update-LocationTagInApplicationHostConfigForAuthentication
5857
    [-] Error occurred in Describe block 298ms
5858
      FileNotFoundException: Filename: \\?\C:\windows\system32\inetsrv\config\applicationHost.config
5859
      Error: Unrecognized configuration path 'MACHINE/WEBROOT/APPHOST/PesterSite'
5860
      MethodInvocationException: Exception calling "GetSection" with "2" argument(s): "Filename: \\?\C:\windows\system32\inetsrv\config\applicationHost.config
5861
      Error: Unrecognized configuration path 'MACHINE/WEBROOT/APPHOST/PesterSite'
5862
      "
5863
      at Update-LocationTagInApplicationHostConfigForAuthentication, C:\projects\xpsdesiredstateconfiguration\DSCResources\MSFT_xDSCWebService\MSFT_xDSCWebService.psm1: line 994
5864
      at <ScriptBlock>, C:\projects\xpsdesiredstateconfiguration\Tests\Unit\MSFT_xDSCWebService.Tests.ps1: line 1111
5865
      at DescribeImpl, C:\Program Files\WindowsPowerShell\Modules\Pester\4.4.2\Functions\Describe.ps1: line 171
5866
5867
  Describing MSFT_xDSCWebService\Find-CertificateThumbprintWithSubjectAndTemplateName
5868
    [+] Should return the certificate thumbprint when the certificate is found 267ms

@tmeckel
Copy link
Contributor Author

tmeckel commented Nov 15, 2018

Hi @mhendric thanks for the review! I fully understand the remark about using single quotes and using explicit parameter names. But I'm not sure about the requirement aligning the '=' signs. Is it only about code style and is it part of the contribution guidelines for this project? And I'll try to setup a VM to reproduce the failed Pester test.

And one word about the issue about having a Pull Server configured via this resource when IIS Express is installed aside a IIS: I wasn't simply able to deploy a Pull Server on two machines where this was the case in two different customer environments. Perhaps it's a esoteric setup, because you won't face the situation in a production environment but it's highly likely in development or test enviroments where you would normally test your DSC configuartions.

@mhendric
Copy link
Contributor

But I'm not sure about the requirement aligning the '=' signs. Is it only about code style and is it part of the contribution guidelines for this project?

I don't think it's an official style guideline. I think it's more of an unspoken rule that in the absence of guidance, follow the existing style (which in this case was with aligned equals signs). You can probably choose to disregard this one, it will just make those of us with OCD cringe a little :) . @johlju , do you think this is a topic worth adding to the DSC Resource Style Guidelines?

And I'll try to setup a VM to reproduce the failed Pester test.

Just FYI, this particular Unit Test file (as with most from this module, I suspect) can be run from a non-Web Server. I just tested running the original MSFT_xDSCWebService.Tests.ps1 from a Windows 10 machine without any Web roles, and it worked just fine.

@tmeckel
Copy link
Contributor Author

tmeckel commented Nov 16, 2018

And I'll try to setup a VM to reproduce the failed Pester test.

Just FYI, this particular Unit Test file (as with most from this module, I suspect) can be run from a non-Web Server. I just tested running the original MSFT_xDSCWebService.Tests.ps1 from a Windows 10 machine without any Web roles, and it worked just fine.

When I think about it, the test is implemented incorrectly. Because of the other DSC Resources which could be applied on arbitrary computers the xDscWebService relies on an installed IIS. Not without reason there is a test function for that in the implementation.

https://github.com/PowerShell/xPSDesiredStateConfiguration/blob/9fd047b90f3d74c4a83e0ae0011da1af5b916bbd/DSCResources/MSFT_xDSCWebService/PSWSIISEndpoint.psm1#L98

Which is used here, where the actual IIS plumbing is done.

https://github.com/PowerShell/xPSDesiredStateConfiguration/blob/9fd047b90f3d74c4a83e0ae0011da1af5b916bbd/DSCResources/MSFT_xDSCWebService/PSWSIISEndpoint.psm1#L15

But that all doesn't explain why the test now fails because I only (funny I know , because every single IT system got broken at least once by a goo intention) changed the loading strategy for the correct IIS Webdministration.dll so that it won't pick the Webadminitration module of IIS Express. This is in fact the main reason for the bug that you can't deploy a pull server on a computer where IIS and IIS Express are installed side by side.

The strong name of the IIS Express Webadminstration assembly only differs in it's version number and to make it worse it's higher than the one provided by IIS itself. And because the code is using Assembly::LoadByPartcialName to not having to change the code if the IIS guys change the strong name and that LoadByPartcialName always favors the highest Version for a partially specified Assembly name, you end up with the Webadminstration module of IIS Express and IIS Express does support the concept of applicationHost.config and such.

Please also refer to #191 for the older discussion about the error.

@mhendric
Copy link
Contributor

So, Unit tests should not rely on the results of external function calls, or rely on the machine being in a certain state. Essentially you're just trying to test that the code for a specific function flows properly under expected conditions. You're not trying to test that the function and all it's external calls work. That falls under the scope of Integration tests.

The first two problems I see in the 'Update-LocationTagInApplicationHostConfigForAuthentication' tests after this change are that you are not Mock'ing the calls to Get-ItemProperty or Join-Path. Get-ItemProperty could only actually return a value on a real IIS web server, so you should Mock that function to just return a static path (valid or not).

Next, you use -Resolve in the Join-Path, so unless the path was actually valid, that will fail. So you should just Mock Join-Path to return a fake string. Here's an example for both of these:

            Mock -CommandName Get-ItemProperty -Verifiable -MockWith {
                return @{
                    InstallPath = 'C:\InstallPath'
                }
            }
            Mock -CommandName Join-Path -Verifiable -MockWith { return 'C:\InstallPath\Microsoft.Web.Administration.dll' }

Next set of problems are that the old Unit tests had verifiable Mock's for Add-Type and New-Object, but you removed those lines of code, so those verifications are going to fail when those functions aren't attempted to be called. You should remove those Mock statements entirely.

Next up, and this is the biggest challenge, I'm not sure that the following lines are Mockable via Pester. I don't think Pester can Mock static class functions. You may need to come up with an alternate way to represent those calls that can be Mock'ed. You may also consider moving those to a dedicated function, and then in Update-LocationTagInApplicationHostConfigForAuthentication you can just Mock that function. But at some point you're going to need to be able to create Unit tests for these lines.

    $assy = [System.Reflection.Assembly]::LoadFrom($assyPath)
    $webAdminSrvMgr = [System.Activator]::CreateInstance($assy.FullName, "Microsoft.Web.Administration.ServerManager").Unwrap()

For Mock'ing functions of objects (like $webAdminSrvMgr.GetApplicationHostConfiguration()), you'll want to have the base object be a custom PSObject, and then add a ScriptMethod member corresponding to the function. See line 82 of the following code for an example of how I've done this: https://github.com/PowerShell/xExchange/blob/dev/Tests/Unit/MSFT_xExchClientAccessServer.tests.ps1

Let me know if you have any questions on all of this.

@mhendric
Copy link
Contributor

I don't think Pester can Mock static class functions. You may need to come up with an alternate way to represent those calls that can be Mock'ed. You may also consider moving those to a dedicated function, and then in Update-LocationTagInApplicationHostConfigForAuthentication you can just Mock that function.

Researched this a bit further. I'm pretty sure you're going to have to move those lines to a dedicated function if we want Update-LocationTagInApplicationHostConfigForAuthentication to continue to be Unit testable. See: pester/Pester#592

@tmeckel
Copy link
Contributor Author

tmeckel commented Nov 17, 2018

So, Unit tests should not rely on the results of external function calls, or rely on the machine being in a certain state. Essentially you're just trying to test that the code for a specific function flows properly under expected conditions. You're not trying to test that the function and all it's external calls work. That falls under the scope of Integration tests.

The first two problems I see in the 'Update-LocationTagInApplicationHostConfigForAuthentication' tests after this change are that you are not Mock'ing the calls to Get-ItemProperty or Join-Path. Get-ItemProperty could only actually return a value on a real IIS web server, so you should Mock that function to just return a static path (valid or not).

Next, you use -Resolve in the Join-Path, so unless the path was actually valid, that will fail. So you should just Mock Join-Path to return a fake string. Here's an example for both of these:

            Mock -CommandName Get-ItemProperty -Verifiable -MockWith {
                return @{
                    InstallPath = 'C:\InstallPath'
                }
            }
            Mock -CommandName Join-Path -Verifiable -MockWith { return 'C:\InstallPath\Microsoft.Web.Administration.dll' }

Next set of problems are that the old Unit tests had verifiable Mock's for Add-Type and New-Object, but you removed those lines of code, so those verifications are going to fail when those functions aren't attempted to be called. You should remove those Mock statements entirely.

Thanks @mhendric for the detailed explanation how the tests are structured here! I highly appreciate that!

So and because I thought I understood something (LOL) I thought, well the test is now broken because I removed the Get-GacAssemblyVersion function https://github.com/PowerShell/xPSDesiredStateConfiguration/blob/9fd047b90f3d74c4a83e0ae0011da1af5b916bbd/DSCResources/MSFT_xDSCWebService/MSFT_xDSCWebService.psm1#L1068 and replaced it with my new code to load the WebAdministration assembly, and because the unit test relies on a mock up for that particular function. But to my own surprsie I didn't find a mock up for the function in current dev branch version. So how did the old unit test ever passed? :-O Because when I refer to what you said about the static native function been called by my code, they have to wrapped by a mock up so that the unit test will pass.

Next up, and this is the biggest challenge, I'm not sure that the following lines are Mockable via Pester. I don't think Pester can Mock static class functions. You may need to come up with an alternate way to represent those calls that can be Mock'ed. You may also consider moving those to a dedicated function, and then in Update-LocationTagInApplicationHostConfigForAuthentication you can just Mock that function. But at some point you're going to need to be able to create Unit tests for these lines.

    $assy = [System.Reflection.Assembly]::LoadFrom($assyPath)
    $webAdminSrvMgr = [System.Activator]::CreateInstance($assy.FullName, "Microsoft.Web.Administration.ServerManager").Unwrap()

For Mock'ing functions of objects (like $webAdminSrvMgr.GetApplicationHostConfiguration()), you'll want to have the base object be a custom PSObject, and then add a ScriptMethod member corresponding to the function. See line 82 of the following code for an example of how I've done this: https://github.com/PowerShell/xExchange/blob/dev/Tests/Unit/MSFT_xExchClientAccessServer.tests.ps1

Let me know if you have any questions on all of this.

So with all what you said about how to setup unit tests and what I found about how the https://github.com/PowerShell/xPSDesiredStateConfiguration/blob/9fd047b90f3d74c4a83e0ae0011da1af5b916bbd/Tests/Unit/MSFT_xDSCWebService.Tests.ps1#L1095 is setup currently, as I said earlier, I personally don't understand how the test could've ever passed sucessfully.

So from my point of view I would do two things now

  1. Introduce a new function Import-WebAdministration in which I'll wrap the code that is currentlöy used to load the correct WebAdministration assembly and call it in Update-LocationTagInApplicationHostConfigForAuthentication
  2. Change the Unit test for Update-LocationTagInApplicationHostConfigForAuthentication in the way that I add a mock up for Import-WebAdministration, including a test that the method is called at least once.

@mhendric
Copy link
Contributor

as I said earlier, I personally don't understand how the test could've ever passed sucessfully.

I haven't tried to actually debug the old code while running the Unit tests, but my guess is that since Add-Type was being Mock'ed, it didn't actually matter what result, if any, came back from Get-GacAssemblyVersion. That being said, Get-GacAssemblyVersion probably should have been Mock'ed so that Update-LocationTagInApplicationHostConfigForAuthentication wouldn't rely on external calls.

So from my point of view I would do two things now

Sounds like a good approach to me.

@codecov-io
Copy link

codecov-io commented Nov 18, 2018

Codecov Report

Merging #462 into dev will decrease coverage by <1%.
The diff coverage is 73%.

Impacted file tree graph

@@         Coverage Diff         @@
##            dev   #462   +/-   ##
===================================
- Coverage    72%    72%   -1%     
===================================
  Files        27     27           
  Lines      4024   4029    +5     
  Branches      4      4           
===================================
- Hits       2922   2919    -3     
- Misses     1098   1106    +8     
  Partials      4      4

@tmeckel
Copy link
Contributor Author

tmeckel commented Nov 18, 2018

@mhendric I changed the PR according our discussion and the rest of your findings, espcially adding a comment to README.md. The appveyor tests fail because of failed PSScriptAnalyzer rules, but as I can see they don't relate to my code.

Added -Path parameter to Get-ItemProperty in function  Get-IISServerManager
@tmeckel
Copy link
Contributor Author

tmeckel commented Nov 18, 2018

as I said earlier, I personally don't understand how the test could've ever passed sucessfully.

I haven't tried to actually debug the old code while running the Unit tests, but my guess is that since Add-Type was being Mock'ed, it didn't actually matter what result, if any, came back from Get-GacAssemblyVersion. That being said, Get-GacAssemblyVersion probably should have been Mock'ed so that Update-LocationTagInApplicationHostConfigForAuthentication wouldn't rely on external calls.

BTW I ran the unit test MSFT_xDSCWebService.Tests.ps1 on my Windows 8.1 box and surely enough the test Update-LocationTagInApplicationHostConfigForAuthentication failed as expected.

image

@mhendric
Copy link
Contributor

BTW I ran the unit test MSFT_xDSCWebService.Tests.ps1 on my Windows 8.1 box and surely enough the test Update-LocationTagInApplicationHostConfigForAuthentication failed as expected.

Hmmmm…. works just fine from my Windows 10 machine:

PS D:\GitHub\xPSDesiredStateConfiguration\tests\unit> invoke-pester .\MSFT_xDSCWebService.Tests.ps1
Executing all tests in '.\MSFT_xDSCWebService.Tests.ps1'

Executing script .\MSFT_xDSCWebService.Tests.ps1

  Describing MSFT_xDSCWebService\Get-TargetResource

    Context DSC Web Service is not installed
      [+] Should not throw 4.22s
      [+] Should return Ensure set to Absent 163ms

    Context DSC Web Service is installed without certificate
      [+] Should not throw 656ms
      [+] Should return EndpointName set to PesterTestSite 63ms
      [+] Should return Port set to 8080 14ms
      [+] Should return PhysicalPath set to TestDrive:\inetpub\PesterTestSite 11ms
      [+] Should return State set to Started 13ms
      [+] Should return DatabasePath set to C:\Program Files\WindowsPowerShell\DscService 19ms
      [+] Should return ModulePath set to C:\Program Files\WindowsPowerShell\DscService\Modules 13ms
      [+] Should return ConfigurationPath set to C:\Program Files\WindowsPowerShell\DscService\Configuration 10ms
      [+] Should return DSCServerURL set to http://mikehdell1:8080/PesterTest 12ms
      [+] Should return Ensure set to Present 10ms
      [+] Should return RegistrationKeyPath set to C:\Program Files\WindowsPowerShell\DscService 10ms
      [+] Should return AcceptSelfSignedCertificates set to $true 36ms
      [+] Should return UseSecurityBestPractices set to $false 12ms
      [+] Should return Enable32BitAppOnWin64 set to $false 11ms
      [+] Should return 'DisableSecurityBestPractices' set to $null 44ms
      [+] Should call expected mocks 153ms

    Context DSC Web Service is installed and using OleDb
      [+] Should not throw 220ms
      [+] Should return DatabasePath set to Data Source=TestDrive:\inetpub\PesterTestSite\Devices.mdb 23ms
      [+] Should call expected mocks 77ms

    Context DSC Web Service is installed with certificate using thumbprint
      [+] Should not throw 232ms
      [+] Should return CertificateThumbPrint set to AABBCCDDEEFFGGHHIIJJKKLLMMNNOOPPQQRRSSTT 21ms
      [+] Should return CertificateSubject set to PesterTestCertificate 12ms
      [+] Should return CertificateTemplateName set to WebServer 19ms
      [+] Should call expected mocks 34ms

    Context DSC Web Service is installed with certificate using subject
      [+] Should not throw 124ms
      [+] Should return CertificateThumbPrint set to AABBCCDDEEFFGGHHIIJJKKLLMMNNOOPPQQRRSSTT 16ms
      [+] Should return CertificateSubject set to PesterTestCertificate 9ms
      [+] Should return CertificateTemplateName set to WebServer 9ms
      [+] Should call expected mocks 30ms

    Context Function parameters contain invalid data
      [+] Should throw if CertificateThumbprint and CertificateSubject are not specifed 91ms
      [+] Should throw if CertificateThumbprint and CertificateSubject are both specifed 36ms

  Describing MSFT_xDSCWebService\Set-TargetResource

    Context DSC Service is not installed and Ensure is Absent
      [+] Should call expected mocks 376ms

    Context DSC Service is installed and Ensure is Absent
      [+] Should call expected mocks 127ms

    Context Ensure is Present
      [+] Should call expected mocks 472ms
      [+] Should create the DatabasePath directory 113ms
      [+] Should create the RegistrationKeyPath directory 85ms
      [+] Should create the ModulePath directory 78ms
      [+] Should create the ConfigurationPath directory 96ms

    Context Ensure is Present - isDownLevelOfBlue
      [+] Should call expected mocks 231ms

    Context Ensure is Present - isUpLevelOfBlue
      [+] Should call expected mocks 206ms

    Context Ensure is Present - Enable32BitAppOnWin64
      [+] Should call expected mocks 228ms

    Context Ensure is Present - AcceptSelfSignedCertificates is $false
      [+] Should call expected mocks 157ms

    Context Ensure is Present - UseSecurityBestPractices is $true
      [+] Should throw an error because no certificate specified 97ms

    Context Ensure is Present - CertificateSubject
      [+] Should call expected mocks 190ms

    Context Ensure is Present - CertificateThumbprint and UseSecurityBestPractices is $true
      [+] Should not throw an error 207ms
      [+] Should call expected mocks 19ms

    Context Function parameters contain invalid data
      [+] Should throw if CertificateThumbprint and CertificateSubject are not specifed 75ms

  Describing MSFT_xDSCWebService\Test-TargetResource

    Context DSC Service is not installed
      [+] Should return $true when Ensure is Absent 147ms
      [+] Should return $false when Ensure is Present 20ms

    Context DSC Web Service is installed as HTTP
      [+] Should return $false when Ensure is Absent 83ms
      [+] Should return $false if Port doesn't match 32ms
      [+] Should return $false if Certificate Thumbprint is set 30ms
      [+] Should return $false if Physical Path doesn't match 74ms
      [+] Should return $false when State is set to Stopped 50ms
      [+] Should return $false when dbProvider is not set 52ms
      [+] Should return $true when dbProvider is set to ESENT and ConnectionString does not match the value in web.confi
g 148ms
      [+] Should return $false when dbProvider is set to ESENT and ConnectionString does match the value in web.config 5
4ms
      [+] Should return $true when dbProvider is set to System.Data.OleDb and ConnectionString does not match the value
in web.config 70ms
      [+] Should return $false when dbProvider is set to System.Data.OleDb and ConnectionString does match the value in
web.config 49ms
      [+] Should return $true when ModulePath is set the same as in web.config 73ms
      [+] Should return $false when ModulePath is not set the same as in web.config 51ms
      [+] Should return $true when ConfigurationPath is set the same as in web.config 69ms
      [+] Should return $false when ConfigurationPath is not set the same as in web.config 60ms
      [+] Should return $true when RegistrationKeyPath is set the same as in web.config 99ms
      [+] Should return $false when RegistrationKeyPath is not set the same as in web.config 82ms
      [+] Should return $true when AcceptSelfSignedCertificates is set the same as in web.config 116ms
      [+] Should return $false when AcceptSelfSignedCertificates is not set the same as in web.config 103ms

    Context DSC Web Service is installed as HTTPS
      [+] Should return $false if Certificate Thumbprint is set to AllowUnencryptedTraffic 86ms
      [+] Should return $false if Certificate Subject does not match the current certificate 34ms
      [+] Should return $false when UseSecurityBestPractices and insecure protocols are enabled 110ms

    Context Function parameters contain invalid data
      [+] Should throw if CertificateThumbprint and CertificateSubject are not specifed 71ms

  Describing MSFT_xDSCWebService\Test-WebsitePath
    [+] Should return $true if Endpoint PhysicalPath doesn't match PhysicalPath 113ms
    [+] Should return $true if Endpoint PhysicalPath doesn't match PhysicalPath 21ms

  Describing MSFT_xDSCWebService\Test-WebConfigAppSetting
    [+] Should return $true when ExpectedAppSettingValue is ESENT for dbprovider. 71ms
    [+] Should return $true when ExpectedAppSettingValue is TestDrive:\DatabasePath\Devices.edb for dbconnectionstr. 10m
s
    [+] Should return $true when ExpectedAppSettingValue is TestDrive:\ModulePath for ModulePath. 12ms
    [+] Should return $false when ExpectedAppSettingValue is not ESENT for dbprovider. 19ms
    [+] Should return $false when ExpectedAppSettingValue is not TestDrive:\DatabasePath\Devices.edb for dbconnectionstr
. 10ms
    [+] Should return $false when ExpectedAppSettingValue is not TestDrive:\ModulePath for ModulePath. 18ms

  Describing MSFT_xDSCWebService\Get-WebConfigAppSetting
    [+] Should return ESENT when Key is dbprovider. 62ms
    [+] Should return TestDrive:\DatabasePath\Devices.edb when Key is dbconnectionstr. 13ms
    [+] Should return TestDrive:\ModulePath when Key is ModulePath. 11ms
    [+] Should return Null if Key is not found 19ms

  Describing MSFT_xDSCWebService\Test-WebConfigModulesSetting
    [+] Should return $true if Module is present in Web.config and expected to be installed. 70ms
    [+] Should return $false if Module is present in Web.config and not expected to be installed. 21ms
    [+] Should return $true if Module is not present in Web.config and not expected to be installed. 21ms
    [+] Should return $false if Module is not present in Web.config and expected to be installed. 21ms

  Describing MSFT_xDSCWebService\Get-WebConfigModulesSetting
    [+] Should return the Module name if it is present in Web.config. 62ms
    [+] Should return an empty string if the module is not present in Web.config. 20ms

  Describing MSFT_xDSCWebService\Get-ScriptFolder
    [+] Should return the directory that contains this script 120ms

  Describing MSFT_xDSCWebService\Update-LocationTagInApplicationHostConfigForAuthentication
    [+] Should call expected mocks 198ms

  Describing MSFT_xDSCWebService\Find-CertificateThumbprintWithSubjectAndTemplateName
    [+] Should return the certificate thumbprint when the certificate is found 132ms
    [+] Should throw an error when the certificate is not found 43ms
    [+] Should throw an error when the more than one certificate is found 35ms

  Describing MSFT_xDSCWebService\Get-OSVersion
    [+] Should return a System.Version object 100ms
Tests completed in 12.21s
Tests Passed: 97, Failed: 0, Skipped: 0, Pending: 0, Inconclusive: 0
PS D:\GitHub\xPSDesiredStateConfiguration\tests\unit>

@tmeckel
Copy link
Contributor Author

tmeckel commented Nov 19, 2018

BTW I ran the unit test MSFT_xDSCWebService.Tests.ps1 on my Windows 8.1 box and surely enough the test Update-LocationTagInApplicationHostConfigForAuthentication failed as expected.

Hmmmm…. works just fine from my Windows 10 machine:

Because I changed the implementation and the mock ups as planned I don't this we should waste any time on the old stuff ;-) As you can see in the appveyor results (https://ci.appveyor.com/project/PowerShell/xpsdesiredstateconfiguration/builds/20388250?fullLog=true#L5888) the changed implementation of the unit tests now passes although the module is now using the new strategy for loading the WebAdministration assembly.

Copy link
Contributor

@mhendric mhendric left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed 1 of 4 files at r2.
Reviewable status: 1 of 4 files reviewed, 5 unresolved discussions (waiting on @tmeckel)


DSCResources/MSFT_xDSCWebService/MSFT_xDSCWebService.psm1, line 983 at r1 (raw file):

Previously, mhendric (Mike Hendrickson) wrote…
$assyPath = Join-Path $iisInstallPath "Microsoft.Web.Administration.dll" -Resolve -ErrorAction:SilentlyContinue

Join-Path should use Named Parameters (-Path and -ChildPath)Also, you should use single quotes instead of double quotes here.

Still need Named Parameters for Join-Path.


DSCResources/MSFT_xDSCWebService/MSFT_xDSCWebService.psm1, line 987 at r3 (raw file):

 {

Open brace for function should be on new line to align with the rest of the functions in this module. Function also needs comment based help: https://github.com/PowerShell/DscResources/blob/master/StyleGuidelines.md#functions


DSCResources/MSFT_xDSCWebService/MSFT_xDSCWebService.psm1, line 991 at r3 (raw file):

Quoted 8 lines of code…
    if (-not $iisInstallPath)
    {
        throw ($LocalizedData.IISInstallationPathNotFound)
    }
    $assyPath = Join-Path $iisInstallPath 'Microsoft.Web.Administration.dll' -Resolve -ErrorAction:SilentlyContinue
    if (-not $assyPath)
    {
        throw ($LocalizedData.IISWebAdministrationAssemblyNotFound)

I think it may be best to leave these lines in the original function since they are in fact Mockable. That way the only place where we'll have UnMockable and Untestable code will be in Get-IISServerManager. Update-LocationTagInApplicationHostConfigForAuthentication will still be completely Unit testable.

If you did leave this code in here though, you should pass $LocalizedData to this function as a parameter, since it's defined outside of the function. I don't think we want to assume it will always be available in scope.


DSCResources/MSFT_xDSCWebService/MSFT_xDSCWebService.psm1, line 1003 at r3 (raw file):

}

Shouldn't this function have a return value? Assuming it should, also make sure to add the return type (at a minimum, System.Object, below [CmdletBinding()].

Thomas Meckel added 2 commits November 19, 2018 18:11
Added parameter -Path and -ChildPath to Join-Path call in Get-IISServerManager
Changed brace alignment in Get-IISServerManager
Copy link
Contributor Author

@tmeckel tmeckel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: 1 of 4 files reviewed, 5 unresolved discussions (waiting on @mhendric and @tmeckel)


DSCResources/MSFT_xDSCWebService/MSFT_xDSCWebService.psm1, line 983 at r1 (raw file):

Previously, mhendric (Mike Hendrickson) wrote…

Still need Named Parameters for Join-Path.

I added the parameters to Join-Path


DSCResources/MSFT_xDSCWebService/MSFT_xDSCWebService.psm1, line 987 at r3 (raw file):

Previously, mhendric (Mike Hendrickson) wrote…
 {

Open brace for function should be on new line to align with the rest of the functions in this module. Function also needs comment based help: https://github.com/PowerShell/DscResources/blob/master/StyleGuidelines.md#functions

Done


DSCResources/MSFT_xDSCWebService/MSFT_xDSCWebService.psm1, line 991 at r3 (raw file):

Previously, mhendric (Mike Hendrickson) wrote…
    if (-not $iisInstallPath)
    {
        throw ($LocalizedData.IISInstallationPathNotFound)
    }
    $assyPath = Join-Path $iisInstallPath 'Microsoft.Web.Administration.dll' -Resolve -ErrorAction:SilentlyContinue
    if (-not $assyPath)
    {
        throw ($LocalizedData.IISWebAdministrationAssemblyNotFound)

I think it may be best to leave these lines in the original function since they are in fact Mockable. That way the only place where we'll have UnMockable and Untestable code will be in Get-IISServerManager. Update-LocationTagInApplicationHostConfigForAuthentication will still be completely Unit testable.

If you did leave this code in here though, you should pass $LocalizedData to this function as a parameter, since it's defined outside of the function. I don't think we want to assume it will always be available in scope.

I added the output type declaration to Get-IISServerManager and I would prefer to leave the code for loading the ServerManager object in this function because it's separately mockable and monitorable that it's called by Update-LocationTagInApplicationHostConfigForAuthentication.

Furthermore I wouldn't add a parameter for the $LocalizedData now because as with Find-CertificateThumbprintWithSubjectAndTemplateName the $LocalizedData is initialized "globally" (i.e. in the scope of the PSM1 file) and is available for all functions therein.

Perhaps this isn't ideal because such supports functions should be placed in a different PS1 oder PSM1 file, but the code works right now and we should move all support functions at once and doing it like patchwork.


DSCResources/MSFT_xDSCWebService/MSFT_xDSCWebService.psm1, line 1003 at r3 (raw file):

Previously, mhendric (Mike Hendrickson) wrote…
}

Shouldn't this function have a return value? Assuming it should, also make sure to add the return type (at a minimum, System.Object, below [CmdletBinding()].

A Powershell function doesn't need an explicit return statement because all values that are put into the pipeline will be returned from the function. The return statement terminates the current scope though. So at the end of a function the return statement is redundant thus I always omit it. But I've to admit that it's more readable to have a return statement, so I added it.

Copy link
Contributor Author

@tmeckel tmeckel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: 1 of 4 files reviewed, 5 unresolved discussions (waiting on @mhendric)


DSCResources/MSFT_xDSCWebService/MSFT_xDSCWebService.psm1, line 978 at r1 (raw file):

Previously, mhendric (Mike Hendrickson) wrote…
$iisInstallPath = (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\INetStp" -Name InstallPath).InstallPath

Get-ItemProperty should use Named Parameter (-Path)
Also, you should use single quotes instead of double quotes here.

Done


DSCResources/MSFT_xDSCWebService/MSFT_xDSCWebService.psm1, line 989 at r1 (raw file):

Previously, mhendric (Mike Hendrickson) wrote…
"Microsoft.Web.Administration.ServerManager"

Use single quotes here

Done


DSCResources/MSFT_xDSCWebService/en-US/MSFT_xDSCWebService.psd1, line 3 at r1 (raw file):

Previously, mhendric (Mike Hendrickson) wrote…
    ThrowUseSecurityBestPractice     = Error: Cannot use best practice security settings with unencrypted traffic. Please set UseSecurityBestPractices to $false or use a certificate to encrypt pull server traffic.
    FindCertificateBySubjectMultiple = More than one certificate found with subject containing {0} and using template "{1}".

Recommend updating all of the old entries so that the equals sign aligns with the equals sign of the new entry.

Done.

Copy link
Contributor

@mhendric mhendric left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed 2 of 4 files at r2, 1 of 1 files at r4.
Reviewable status: :shipit: complete! all files reviewed, all discussions resolved

@mhendric
Copy link
Contributor

@tmeckel , everything looks good to me, good work! Now if we can only find a Maintainer to check this in...

In the meantime, have you tested this code for real to make sure it works on an actual IIS server?

@tmeckel
Copy link
Contributor Author

tmeckel commented Nov 20, 2018

@tmeckel , everything looks good to me, good work! Now if we can only find a Maintainer to check this in...

The situation with having PRs merged and Issues reviewed is definitely a problem with this DSC module and sadly to say with the PSDscResources module also. As you can see I submitted a PR for a nasty bug in the Group resource in PSDscResources PowerShell/PSDscResources#118 (which can be found here too #467 because the code base of these two modules are merely the same) but the PR is marked as abandoned. @johlju was kind enough to discuss how to setup the integration tests for the solution but I think he has more important things to do than reviewing an merging PRs and he's already the owner of the SQL DSC module.

I personally submitted some PRs and issues with SharePoint Powershell PNP and it's core library project and there everything worked like a charm. So with the DSC modules it's kinda disappointing. I know every developer thinks he's the hub of the world, but why e.g. was a bot used here that puts issues and PRs on stale and abandoned when there's a lack of time to work on those things? And we do have serious issues here inside the DSC modules which render them unusable in some conditions or operational scenarios.

Don't get me wrong I'm very sure that every single person here does a great job. I simply think there's too much work put on too little shoulders. So I definitely endorse your issue #466!

In the meantime, have you tested this code for real to make sure it works on an actual IIS server?

Yes I tested the new code, and all the other fixes for which I submitted PRs, in out test environment, which includes servers with IIS Express and IIS installed side by side and plain vanilla servers, because the fixes are required to have a DSC Pull Server deployed in our production environment and passing our quality tests.

@stale
Copy link

stale bot commented Dec 4, 2018

Labeling this pull request (PR) as abandoned since it has gone 14 days or more since the last update. An abandoned PR can be continued by another contributor. The abandoned label will be removed if work on this PR is taken up again.

@stale stale bot added the abandoned The pull request has been abandoned. label Dec 4, 2018
@PlagueHO
Copy link
Member

We should be able to pick this one up again once I've got all the integration tests passing again (and we've got a maintainer with merge permissions).

@mhendric
Copy link
Contributor

@tmeckel , @PlagueHO was able to fix the integration tests. Can you rebase this when you get a chance? That will trigger a new CI build, which should pass. Thanks for your patience on this!

https://github.com/PowerShell/DscResources/blob/master/GettingStartedWithGitHub.md#resolve-merge-conflicts

@mhendric mhendric removed the abandoned The pull request has been abandoned. label Jan 24, 2019
@PlagueHO
Copy link
Member

I updated the branch on this one too and the tests are now running. Fingers crossed we can just get the review done 😁

@PlagueHO PlagueHO added the needs review The pull request needs a code review. label Jan 25, 2019
Copy link
Contributor

@mhendric mhendric left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:lgtm:

Reviewed 2 of 2 files at r5.
Reviewable status: :shipit: complete! all files reviewed, all discussions resolved

@mhendric mhendric added ready for merge The pull request was approved by the community and is ready to be merged by a maintainer. and removed needs review The pull request needs a code review. labels Jan 26, 2019
@mhendric mhendric merged commit 3c1d592 into dsccommunity:dev Jan 26, 2019
@tmeckel tmeckel deleted the own-issue-191 branch January 26, 2019 09:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ready for merge The pull request was approved by the community and is ready to be merged by a maintainer.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Errors while creating new DSC pull server
4 participants