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

BREAKING CHANGE: FTP #425

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open

Conversation

t3mi
Copy link

@t3mi t3mi commented May 20, 2019

Pull Request (PR) description

This is continued work from PR#202 started by @nzspambot. All the latest changes were integrated, tests and some function logic were optimized and fixed. Please review.

This Pull Request (PR) fixes the following issues

Adds new resource FTP for managing FTP sites. Fixes #81
BREAKING CHANGES: For xWebsite and xWebApplication if AuthenticationInformation was not specified Default (all $false) is assumed.

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

James Baker and others added 5 commits May 20, 2019 10:49
… README, moved shared resources to helper.psm1 from xWebsite,xWebApplication and xFTP, Updated unit tests for said resources to reflect that movement
@msftclas
Copy link

msftclas commented May 20, 2019

CLA assistant check
All CLA requirements met.

@gaelcolas
Copy link
Member

gaelcolas commented May 20, 2019

Thanks a lot for this contribution.

I don't know if you've noticed but some tests aren't passing. Any chance you could try fixing them?
https://ci.appveyor.com/project/PowerShell/xwebadministration/builds/24663455?fullLog=true#L826

@regedit32
Copy link
Member

Also, before we get too far in the review, we don't need to keep the 'x' prefix in the name. Similar to the latest resource added to this module, WebApplicationHandler, we can start naming resources without any prefixes, so perhaps just FTP. At some point we will rename older resources and bring them up to HQRM standards in the process, but this will make it easier if we follow this practice with all new resources moving forward.

@t3mi
Copy link
Author

t3mi commented May 20, 2019

@gaelcolas thanks. I'm using clear text password in Get function to construct credential object. Is switching to every property check the only route or suppressing failed rule using [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingConvertToSecureStringWithPlainText", "")] could be considered as well?

@regedit32 ok.

@t3mi t3mi changed the title xFTP FTP May 20, 2019
@codecov-io
Copy link

codecov-io commented May 20, 2019

Codecov Report

Merging #425 into dev will increase coverage by 1.15%.
The diff coverage is 96.86%.

Impacted file tree graph

@@            Coverage Diff             @@
##              dev     #425      +/-   ##
==========================================
+ Coverage   90.77%   91.92%   +1.15%     
==========================================
  Files          17       18       +1     
  Lines        2438     2835     +397     
==========================================
+ Hits         2213     2606     +393     
- Misses        225      229       +4
Impacted Files Coverage Δ
DSCResources/MSFT_xWebsite/MSFT_xWebsite.psm1 96.39% <100%> (-0.73%) ⬇️
...ces/MSFT_xWebApplication/MSFT_xWebApplication.psm1 97.87% <94.73%> (+7.12%) ⬆️
DSCResources/MSFT_FTP/MSFT_FTP.psm1 95.71% <95.71%> (ø)
DSCResources/Helper.psm1 97.2% <98.22%> (+7.2%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 3ed63bc...f501470. Read the comment docs.

@t3mi t3mi force-pushed the changes-from-PR#202 branch from 5c7572d to b46a62d Compare May 20, 2019 21:30
@regedit32
Copy link
Member

Hi @t3mi , nice work on this! Can we separate the changes into two PRs? One for the new FTP resource and another for the changes to xWebsite and xWebApplication? They are both big changes in their own right and would be good to have a separate issue opened for the changes to xWebsite and xWebApplication and describe what we're addressing there. It's a large PR and will be easier to review if we can keep the changes scoped a bit more.

@t3mi
Copy link
Author

t3mi commented May 21, 2019

@regedit32 thanks. I would prefer to not split as all the changes to xWebsite and xWebApplication are from shared functions which were moved to Helper module. The only piece which could be submitted as different PR for is change to default values for AuthenticationInformation but its very small.

@regedit32
Copy link
Member

Oh I see, you consolidated reusable functions for this new resource. Thanks for that! Can you describe the breaking change a little more? If we're going to include a breaking change, I want to make sure we're clear on the where/why for tracking purposes.

@regedit32 regedit32 changed the title FTP BREAKING CHANGE: FTP May 22, 2019
@t3mi
Copy link
Author

t3mi commented May 22, 2019

Sure. If AuthenticationInfo parameter was not specified for resources xWebsite or xWebApplication current values will be compared with default values (all available authentication options set to $false). So if any authentication option was enabled outside of DSC it will be reverted to $false unless AuthenticationInfo was set. The purpose for such change is that both resources had initial check and set of AuthenticationInfo to default values if none was provided but it wasn't working because condition had $PSBoundParameters.ContainsKey() as one of the checks.

@danielboth
Copy link
Member

Nice work @t3mi, had a quick glance at the code, can't wait for this to be merged in! @regedit32 / @kwirkykat can we get this one in for the next DSC resource kit release please?!

@regedit32
Copy link
Member

Hopefully I will get back to this over the weekend to provide feedback. Anyone is welcome to help review in the meantime.

@regedit32 regedit32 added breaking change When used on an issue, the issue has been determined to be a breaking change. needs review The pull request needs a code review. labels Jun 17, 2019
Copy link
Member

@danielboth danielboth left a comment

Choose a reason for hiding this comment

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

Reviewed 4 of 14 files at r2, 11 of 11 files at r3.
Reviewable status: all files reviewed, 46 unresolved discussions (waiting on @t3mi)


DSCResources/Helper.psm1, line 374 at r3 (raw file):

    $cimNamespace = 'root/microsoft/Windows/DesiredStateConfiguration'
    switch($IisType)

Can you put a space between switch and the open parentheses?


DSCResources/Helper.psm1, line 449 at r3 (raw file):

    )

    $Location = "${Site}"

non-parameter Location should use camelCase


DSCResources/Helper.psm1, line 453 at r3 (raw file):

    if ($IisType -eq 'Application')
    {
        $Location = "${Site}/${Application}"

If this is just to get to the right location on the IIS drive, why a forward slash?

Maybe even better: Join-Path -Path $Site -ChildPath $Application, and then repeat that with the IIS;\Sites logic


DSCResources/Helper.psm1, line 513 at r3 (raw file):

    )

    $Properties = ($AuthenticationInfo.CimInstanceProperties | Where-Object {$null -ne $_.Value}).Name | Sort-Object

non-parameter Properties should use camelCase


DSCResources/Helper.psm1, line 567 at r3 (raw file):

    )

    $Location = "${Site}"

non-parameter Location should use camelCase


DSCResources/Helper.psm1, line 571 at r3 (raw file):

    if ($IisType -eq 'Application')
    {
        $Location = "${Site}/${Application}"

Same comment about slash direction and can be improved with Join-Path


DSCResources/Helper.psm1, line 635 at r3 (raw file):

    )

    $Properties = ($AuthenticationInfo.CimInstanceProperties | Where-Object {$null -ne $_.Value}).Name | Sort-Object

non-parameter Properties should use camelCase


DSCResources/Helper.psm1, line 691 at r3 (raw file):

    )

    $CurrentLogFlags = switch($FtpSite.IsPresent)

non-parameter CurrentLogFlags should use camelCase, same for ProposedLogFlags

Add a space after switch


DSCResources/Helper.psm1, line 780 at r3 (raw file):

    )

    $WebSiteASP = (Get-WebConfiguration `

non-parameter WebsiteASP should use camelCase,

Same for ExistingObject, ProposedObject and ErrorMessage


DSCResources/Helper.psm1, line 792 at r3 (raw file):

    })

    if(-not $ExistingObject)

Add space after if


DSCResources/Helper.psm1, line 797 at r3 (raw file):

    }

    if(-not (Compare-Object -ReferenceObject $ExistingObject `

Add space after if


DSCResources/Helper.psm1, line 801 at r3 (raw file):

                            -Property name))
    {
        if(Compare-Object -ReferenceObject $ExistingObject `

Add space after if


DSCResources/Helper.psm1, line 852 at r3 (raw file):

    )

    $Website = Get-Website | Where-Object -FilterScript {$_.Name -eq $Name}

non-parameter Website should use camelCase

Same for ReferenceObject, ExcludeStopeed, OtherWebsiteFilter, DifferenceObject, CompareSplat and Result


DSCResources/Helper.psm1, line 1077 at r3 (raw file):

                        }

                        $bindingInformation = $IPAddressString, `

Backticks are also not required after a comma ( , )


DSCResources/Helper.psm1, line 1201 at r3 (raw file):

            {
                <#
                    WebAdministration can throw the following exception if there are non-standard

Excellent additional information! :)


DSCResources/Helper.psm1, line 1371 at r3 (raw file):

    try
    {
        $IsValid = [UInt16]$InputString -ne 0

non-parameters should use camelCase


Examples/Sample_xFTP_NewFTPSite.ps1, line 37 at r3 (raw file):

            PhysicalPath      = $FTPSitePath
            State             = 'Started'
            AuthorizationInfo = @(

This example misses AuthenticationInfo, which would be nice to add, so it's clear that Authentication needs to be configured next to Authorization.


Tests/Unit/Helper.Tests.ps1, line 1097 at r3 (raw file):

                    It 'Should call expected mocks' {
                        Assert-MockCalled -CommandName Get-WebConfigurationProperty -Exactly ($testCase.IisType -ne 'Ftp')

($testCase.IisType -ne 'Ftp') is not returning a number here, so I had to test what this is doing. It works since $true casts to [int] 1, but that's not very clear from this code. It would already be better if you cast it to int yourself so: [int]($testCase.IisType -ne 'Ftp')

Other than that, I feel it would be even better to just write -Times 0 or -Times 1, what's the benefit of doing it like this?


Tests/Unit/Helper.Tests.ps1, line 1198 at r3 (raw file):

            )

            foreach($testCase in $testCases)

Space after foreach


Tests/Unit/Helper.Tests.ps1, line 1232 at r3 (raw file):

            }

            foreach($truthyTestCase in $truthyTestCases)

Space after foreach


Tests/Unit/Helper.Tests.ps1, line 2016 at r3 (raw file):

            Mock -CommandName Clear-WebConfiguration -Verifiable

            foreach($testCase in $testCases)

Add a space between foreach and (


Tests/Unit/Helper.Tests.ps1, line 2234 at r3 (raw file):

            )

            foreach($testCase in $testCases)

Add a space after foreach


Tests/Unit/MSFT_xWebApplication.Tests.ps1, line 4 at r3 (raw file):

$script:DSCResourceName     = 'MSFT_xWebApplication'
$script:DSCHelperModuleName = 'Helper'

Same generic comment about camelCase variable names applies for this file as well


Tests/Unit/MSFT_xWebsite.Tests.ps1, line 4 at r3 (raw file):

$script:DSCResourceName     = 'MSFT_xWebsite'
$script:DSCHelperModuleName = 'Helper'

Same generic comment about camelCase variable names applies for this file as well


DSCResources/MSFT_FTP/MSFT_FTP.psm1, line 111 at r3 (raw file):

        Specifies username for access to physical path if required.

    .PARAMETER PhysicalPathAccessPass

This password is implemented as a plaintext string. Doing that means users of this resource are encouraged to put their passwords in plaintext in the configuration. I would rather see that PhysicalPathAccessAccount and PhysicalPathAccessPass get combined in a pscredential object. That way we can at least deliver it to the LCM in a secure way.


DSCResources/MSFT_FTP/MSFT_FTP.psm1, line 353 at r3 (raw file):

                } |
                ForEach-Object -Begin {
                    $NewftpSiteSplat = @{}

non-parameter NewftpSiteSplat should use camelCase

Same for: LocalizedData


DSCResources/MSFT_FTP/MSFT_FTP.psm1, line 369 at r3 (raw file):

                # Set default port to FTP:21 else it will be HTTP:80
                if(-not(($PSBoundParameters.ContainsKey('BindingIfo'))))

BindingIfo is misspelled, should be BindingInfo
Also, please add a space between if and the open parentheses


DSCResources/MSFT_FTP/MSFT_FTP.psm1, line 374 at r3 (raw file):

                }

                if ([bool]([System.Uri]$PhysicalPath).IsUnc)

[bool] is not required here, IsUnc is a boolean by default.


DSCResources/MSFT_FTP/MSFT_FTP.psm1, line 411 at r3 (raw file):

        # Update physical path access username if required
        if ($PSBoundParameters.ContainsKey('PhysicalPathAccessAccount') -and `

A backtick behind -and is not required, code will work fine without it. I won't make this statement everywhere, but please clean it everywhere, just makes it so much more readable.

It's the same with -or as well.


DSCResources/MSFT_FTP/MSFT_FTP.psm1, line 647 at r3 (raw file):

            if ($PSBoundParameters.ContainsKey('LogTruncateSize'))
            {
                Write-Verbose -Message ($LocalizedData.WarningLogPeriod -f $Name)

In general, other resources return an error to the user when an unsupported configuration has been setup. This way of silently handling such an unsupported configuration might lead to unexpected results for the user of the resource. I would prefer to just return an error if the user specified both LogPeriod and LogTruncateSize.


DSCResources/MSFT_FTP/MSFT_FTP.psm1, line 1006 at r3 (raw file):

    Assert-Module

    $InDesiredState = $true

non-parameter InDesiredState should use camelCase

Same for: LocalizedData


DSCResources/MSFT_FTP/MSFT_FTP.psm1, line 1233 at r3 (raw file):

        if ($PSBoundParameters.ContainsKey('LoglocalTimeRollover') -and `
            ($LoglocalTimeRollover -ne `
            ([System.Convert]::ToBoolean($ftpSite.ftpServer.logFile.localTimeRollover))))

Is there some version specific thing that you need to convert it to boolean? (As my test system returns this as boolean itself, W2016).


DSCResources/MSFT_FTP/MSFT_FTP.psm1, line 1300 at r3 (raw file):

    )

    $CurrentDirectoryBrowseflags = (Get-Website -Name $Site).ftpServer.directoryBrowse.showFlags `

non-parameter CurrentDirectoryBrowseflags should use camelCase

Same for ProposedDirectoryBrowseflags


DSCResources/MSFT_FTP/MSFT_FTP.psm1, line 1362 at r3 (raw file):

    }

    $existingFtpAuthorizationInfo = $CurrentAuthorizationCollection | `

Same comment as with -and and -or, after a pipe | there is not backtick required to continue on the next line.


DSCResources/MSFT_FTP/MSFT_FTP.psm1, line 1366 at r3 (raw file):

        Select-Object accessType,users,roles,permissions

    $existingObject=$()

Can you put some spaces around the equal sign?


DSCResources/MSFT_FTP/MSFT_FTP.psm1, line 1369 at r3 (raw file):

    $existingObject += foreach($existingAuthorization in $existingFtpAuthorizationInfo)
    {
        $currentObject = New-Object -TypeName PSObject `

This is pure preference, but in general I would prefer this:

[pscustomobject]@{
accessType = $existingAuthorization.accessType
users = $existingAuthorization.users
roles = $existingAuthorization.roles
permissions = $existingAuthorization.permissions
}

Helps you with keeping the code nicely formatted and doesn't require backticks.


DSCResources/MSFT_FTP/MSFT_FTP.psm1, line 1419 at r3 (raw file):

    )

    $Store = $SslInfo.CertificateStoreName

non-parameter Store should use camelCase

Same for, Hash and Properties


DSCResources/MSFT_FTP/MSFT_FTP.psm1, line 1422 at r3 (raw file):

    $Hash  = $SslInfo.CertificateThumbprint

    if($null -ne $Hash -and -not(Test-Path -Path Cert:\LocalMachine\${Store}\${Hash}))

Add a space between if and open parentheses


DSCResources/MSFT_FTP/MSFT_FTP.psm1, line 1454 at r3 (raw file):

                              -Property $Properties

    if($null -ne $compare)

Add a space between if and open parentheses


DSCResources/MSFT_FTP/MSFT_FTP.psm1, line 1672 at r3 (raw file):

    }

    foreach ($Authorization in $AuthorizationInfo)

non-parameter Authorization should use camelCase


Tests/Integration/MSFT_FTP.config.psd1, line 15 at r3 (raw file):

            AuthenticationInfoAnonymous   = $false
            AuthenticationInfoBasic       = $true
            AuthorizationInfoAccessType1  = 'Allow'

The names of the variables are a bit cryptic here, why not just:

AuthorizationInfoAccessTypeAllow
AuthorizationInforAccessTypeDeny

(and the same for User and Permissions)

That will also make the integration tests more readable on what happens!


Tests/Unit/MSFT_FTP.tests.ps1, line 4 at r3 (raw file):

$script:DSCResourceName     = 'MSFT_FTP'
$script:DSCHelperModuleName = 'Helper'

In general, since this script does not accept parameters, all parameters should be in camelCase


Tests/Unit/MSFT_FTP.tests.ps1, line 1196 at r3 (raw file):

                Set-TargetResource @MockParameters

                It 'Should call all the mocks' {

In general, I like the way the tests for Test-TargetResource are structured way better than these tests. If this test now fails, that tells just "something failed", but we don't know what or where.

I think it's much more beneficial to future contributors to split the tests so each individual parameter is tested if it sets successfully, leaving the end-to-end test to the integration tests.

I did have a look at the other tests in this module as well, and see they follow a similar model, so I don't think this is something to decline this PR on, I do think it's valuable to get this discussion started, so would also love to hear your opinion.


Tests/Unit/MSFT_FTP.tests.ps1, line 1197 at r3 (raw file):

                It 'Should call all the mocks' {
                    Assert-MockCalled -CommandName Set-ItemProperty -Exactly 18

Use named parameters for function and cmdlet calls rather than positional parameters, so all these should read:

Assert-MockCalled -CommandName Set-ItemProperty -Exactly -Times 18

This is due to Exactly being a switch parameter.


Tests/Unit/MSFT_FTP.tests.ps1, line 1328 at r3 (raw file):

        }

        Describe "how $DSCResourceName\Compare-DirectoryBrowseFlags responds" {

Since DirectoryBrowseFlags accepts multiple flags, can you add a test that covers that scenario?


Tests/Unit/MSFT_FTP.tests.ps1, line 1763 at r3 (raw file):

                It 'Should call Get-WebConfiguration 4 times' {
                    Assert-MockCalled -CommandName Get-WebConfiguration -Exactly 1

This test does not match what the It block tells it will do

@danielboth
Copy link
Member

Hi @t3mi, @regedit32,

Ok so I went for a full review of this resource this weekend. Not only reviewing the code, but also testing it on a test system. One learning from that one that, even if the IIS server is not setup as a FTP server (missing the Web-Ftp-Server role), this resource will apply the configuration like everything should work. That would be a nice check to add.

Another discussion point is the setup of username / password as plaintext strings, I've added a comment in reviewable, so we can follow up on that one.

I have to say, awesome work on all the refactoring @t3mi. Also, the FTP resource went through all the tests I did on my test system properly as well. Feels production ready and well setup with full coverage for all the FTP properties!

On the review I did, I spent a good number of hours on this, but I went through the tests a bit less rigorous as I did through the code implementing the FTP resource. Mainly because reviewable just has a hard time perfoming properly on these large diffs, so apologies if I missed something there.

For all comments around syntax, I took most of these from https://github.com/PowerShell/DscResources/blob/master/StyleGuidelines.md, except for the backticks part where we should possible add that backticks should only be used when required. I hope we can agree on that.

@johlju
Copy link
Member

johlju commented Aug 29, 2019

@t3mi do you have time to work on this so we can get this over the finish line?

@t3mi
Copy link
Author

t3mi commented Aug 29, 2019

@johlju I'll be able to finalize all my PRs once I'm back from vacation in the mid of September.

@danielboth thanks for spending your time to review this!

@danielboth
Copy link
Member

Hi @t3mi, any updates from you on this one? Would be great to finish it.

@t3mi
Copy link
Author

t3mi commented Oct 1, 2019

@danielboth yes, I'm working on this.

Copy link
Member

@danielboth danielboth left a comment

Choose a reason for hiding this comment

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

Let me know if you need any more help @t3mi, thanks!

Reviewable status: all files reviewed, 46 unresolved discussions (waiting on @t3mi)

@danielboth
Copy link
Member

Let me check-in here as I'm wondering what progress has been made.

@johlju johlju changed the base branch from dev to master December 30, 2019 12:16
@markatdxb
Copy link

Hello, just looking at the thread, has the FTP been already implemented ?

@davetapley
Copy link
Contributor

davetapley commented Nov 4, 2020

Paging @t3mi and @danielboth, looks like both @markatdxb and myself are interested in this.

I'm fairly new to all this (I discovered it via Ansible), but I'm happy to help if I can.

@johlju
Copy link
Member

johlju commented Nov 15, 2020

@davetapley I think this PR has been abandoned since there has been no commits since the review. The best option would be to send a PR to @t3mi's working branch, but that means @t3mi need to be around to merge it thpugh. Other option is to fork the @t3mi's working branch to continue the work by sending in a new PR as per https://dsccommunity.org/guidelines/contributing/#how-to-continue-working-on-a-pull-request-pr-when-an-author-contributor-is-unable-to-complete-it.

@johlju johlju changed the base branch from master to main January 7, 2021 19:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
breaking change When used on an issue, the issue has been determined to be a breaking change. needs review The pull request needs a code review.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

MSFT_xWebsite support for FTP websites
9 participants