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

xRemoteFile: Key should be URI rather than remote destination? #745

Open
uw-dc opened this issue Apr 4, 2022 · 4 comments
Open

xRemoteFile: Key should be URI rather than remote destination? #745

uw-dc opened this issue Apr 4, 2022 · 4 comments
Labels
discussion The issue is a discussion. enhancement The issue is an enhancement request.

Comments

@uw-dc
Copy link

uw-dc commented Apr 4, 2022

Problem description

The use case of downloading multiple remote files into the same destination path, where the destination path is a directory, seems like it would be a common one.

With that in mind, the xRemoteFile resource should perhaps be keyed on uri instead of destination?

Verbose logs

Test-ConflictingResources : A conflict was detected between resources '[xRemoteFile]PrinterDriver0
(D:\DscService\Build\Modules\someCompositeModule\0.1.0.42\someCompositeModule.psm1::784::9::xRemoteFile)' and
'[xRemoteFile]PrinterDriver1
(D:\DscService\Build\Modules\someCompositeModule\0.1.0.42\someCompositeModule.psm1::784::9::xRemoteFile)' in
node 'someserver.somedomain.sometld'. Resources have identical key properties but there are differences in the following
non-key properties: 'Uri'. Values 'https://anotherserver.somedomain.sometld:8083/PrinterDrivers/HP Color LaserJet M554-M555
PCL-6.zip' don't match values 'https://anotherserver.somedomain.sometld:8083/PrinterDrivers/PaperCut Global PostScript.zip'.

DSC configuration

$dscPrinterDriverPath = 'C:\ProgramData\DSC\PrinterDriver'

    $printerDrivers = @{
        'HP Color LaserJet M554-M555 PCL-6' = @{
            SourceInf = "$dscPrinterDriverPath\HP Color LaserJet M554-M555 PCL-6\hpma08734_x64.inf"
            StoreInf = 'C:\Windows\System32\DriverStore\FileRepository\hpma08734_x64.inf_amd64_4cbc9f21081b2c3d\hpma08734_x64.inf'
        }

        'PaperCut Global PostScript' = @{
            SourceInf = "$dscPrinterDriverPath\PaperCut Global PostScript\PCGlobal.inf"
            StoreInf = 'C:\Windows\System32\DriverStore\FileRepository\pcglobal.inf_amd64_e25f98e06af28150\pcglobal.inf'
        }
    }

    File DscPrinterDriversFolder {
        DestinationPath = $dscPrinterDriverPath
        Ensure          = 'Present'
        Type            = 'Directory'
    }

    $i = 0
    foreach ($printerDriver in $printerDrivers.GetEnumerator()) {

        xRemoteFile "PrinterDriver$i" {
            Uri             = "https://$DSCPullServerSoftwareRepo/PrinterDrivers/$($printerDriver.Name).zip"
            DestinationPath = "$dscPrinterDriverPath/$($printerDriver.Name).zip"
            DependsOn       = '[File]DscPrinterDriversFolder'
        }

        File "DscPrinterDriverFolder$i" {
            DestinationPath = "$dscPrinterDriverPath\$($printerDriver.Name)"
            Ensure          = 'Present'
            Type            = 'Directory'
            DependsOn       = "[xRemoteFile]PrinterDriver$i"
        }

        xArchive "ExpandPrinterDriverArchive$i" {
            Path        = "$dscPrinterDriverPath\$($printerDriver.Name).zip"
            Destination = "$dscPrinterDriverPath\$($printerDriver.Name)"
            Ensure      = 'Present'
            DependsOn   = "[File]DscPrinterDriverFolder$i"
        }

        Script "AddPrinterDriverToDriverStore$i" {
            GetScript  = {
                return @{
                    result = Get-WindowsDriver -Online -All -ErrorAction SilentlyContinue | `
                            Where-Object {
                            $_.ClassName -eq 'Printer' -and
                            $_.OriginalFileName -eq $using:printerDriver.Value.StoreInf
                        }
                }
            }
            SetScript  = {
                $processStartInfo = [System.Diagnostics.ProcessStartInfo]::new('C:\Windows\System32\pnputil.exe', "/add-driver `"$($using:printerDriver.Value.SourceInf)`"")
                $processStartInfo.CreateNoWindow = $false
                $processStartInfo.WorkingDirectory = 'C:\Windows\system32'
                $processStartInfo.UseShellExecute = $false
                $processStartInfo.RedirectStandardError = $true
                $processStartInfo.RedirectStandardOutput = $true

                $process = New-Object -TypeName System.Diagnostics.Process
                $process.StartInfo = $processStartInfo

                Write-Verbose -Message ("Running process `'{0}`' with arguments `'{1}`'" -f $process.StartInfo.FileName, $process.StartInfo.Arguments)
                $process.Start()

                $stdout = $process.StandardOutput.ReadToEnd()
                $stderr = $process.StandardError.ReadToEnd()

                $process.WaitForExit()

                if (0 -ne $process.ExitCode) {
                    Write-Verbose -Message ('Printer driver ({0}) not successfully added to driver store. pnputil.exe returned non-zero ({1}) exit code' -f $using:printerDriver.Name, $exitCode)
                    Write-Verbose -Message ("`tStandard Output: {0}" -f $stdout)
                    Write-Verbose -Message ("`tStandard Error: {0}" -f $stderr)
                    throw [System.Configuration.ConfigurationException] 'Printer driver ({0}) not successfully added to driver store. pnputil.exe returned non-zero ({1}) exit code' -f $using:printerDriver.Name, $exitCode
                }

                if ($null -eq (Get-WindowsDriver -Online -All -ErrorAction SilentlyContinue | `
                                Where-Object {
                                $_.ClassName -eq 'Printer' -and
                                $_.OriginalFileName -eq $using:printerDriver.Value.StoreInf
                            }
                    )) {
                    Write-Verbose -Message ('Printer driver ({0}) is missing from driver store after running pnputil.exe' -f $using:printerDriver.Name)
                    throw [System.Configuration.ConfigurationException] 'Printer driver ({0}) is missing from driver store after running pnputil.exe' -f $using:printerDriver.Name
                }
            }
            TestScript = {
                return ($true -eq (Get-WindowsDriver -Online -All -ErrorAction SilentlyContinue | `
                                Where-Object {
                                $_.ClassName -eq 'Printer' -and
                                $_.OriginalFileName -eq $using:printerDriver.Value.StoreInf
                            }
                    ))
            }
            DependsOn  = "[xArchive]ExpandPrinterDriverArchive$i"
        }

        Script "InstallPrinterDriver$i" {
            GetScript  = {
                return @{
                    result = (Get-PrinterDriver -Name $using:printerDriver.Name -ErrorAction SilentlyContinue).Name
                }
            }
            SetScript  = {
                Add-PrinterDriver -Name $using:PrinterDriver.Name -InfPath $using:printerDriver.Value.StoreInf

                if ($null -eq (Get-PrinterDriver -Name $using:printerDriver.Name -ErrorAction SilentlyContinue)) {
                    Write-Verbose -Message ("Printer driver ({0}) not successfully installed with 'Add-PrinterDriver'" -f $using:printerDriver.Name)
                    throw [System.Configuration.ConfigurationException] "Printer driver ({0}) not successfully installed with 'Add-PrinterDriver'" -f $using:printerDriver.Name
                }
            }
            TestScript = {
                return ($true -eq (Get-PrinterDriver -Name $using:printerDriver.Name -ErrorAction SilentlyContinue))
            }
            DependsOn  = "[Script]AddPrinterDriverToDriverStore$i"
        }

        $i++
    }

Suggested solution

lines (16 sloc) 1.92 KB
[ClassVersion("1.0.0.1"), FriendlyName("xRemoteFile")]
class DSC_xRemoteFile : OMI_BaseResource
{
[Required, Description("Path under which downloaded or copied file should be accessible after operation.")] String DestinationPath;
[Key, Description("URI of the file which should be downloaded. It must be a HTTP, HTTPS or FILE resource.")] String Uri;
[Write, Description("User agent for the web request.")] String UserAgent;
[Write, Description("Headers of the web request."), EmbeddedInstance("MSFT_KeyValuePair")] String Headers[];
[Write, Description("Specifies credential of a user which has permissions to send the request."), EmbeddedInstance("MSFT_Credential")] String Credential;
[Write, Description("Determines whether the remote file should be re-downloaded if file in the DestinationPath was modified locally. The default value is true.")] Boolean MatchSource;
[Write, Description("Specifies the algorithm used to calculate the checksum of the file."), ValueMap{"None","SHA1","SHA256","SHA384","SHA512","MACTripleDES","MD5","RIPEMD160"}, Values{"None","SHA1","SHA256","SHA384","SHA512","MACTripleDES","MD5","RIPEMD160"}] String ChecksumType;
[Write, Description("Specifies the expected checksum value of downloaded file.")] String Checksum;
[Write, Description("Specifies how long the request can be pending before it times out.")] Uint32 TimeoutSec;
[Write, Description("Uses a proxy server for the request, rather than connecting directly to the Internet resource. Should be the URI of a network proxy server (e.g 'http://10.20.30.1').")] String Proxy;
[Write, Description("Specifies a user account that has permission to use the proxy server that is specified by the Proxy parameter."), EmbeddedInstance("MSFT_Credential")] String ProxyCredential;
[Read, Description("Returns whether the destination path exists on the machine."), ValueMap{"Present", "Absent"}, Values{"Present", "Absent"}] String Ensure;
};

Operating system the target node is running

Server 2019

PowerShell version and build the target node is running

PSVersion                      5.1.17763.2268

17763

xPSDesiredStateConfiguration version

v9.1.0
@uw-dc
Copy link
Author

uw-dc commented Apr 4, 2022

Happy to PR the change if it's agreed upon.

@PlagueHO PlagueHO added enhancement The issue is an enhancement request. discussion The issue is a discussion. labels Apr 4, 2022
@PlagueHO
Copy link
Member

PlagueHO commented Apr 4, 2022

Hi @uw-dc - thank you for submitting this.

I suspect converting Uri to be the Key would break existing DSC configs. For example, when the same file needs to be copied to multiple locations. This is an edge case but could be easily managed by having both Uri and DestinationPath as keys. That should then support your scenario without breaking existing any existing configurations. What do you reckon?

@uw-dc
Copy link
Author

uw-dc commented Apr 5, 2022

Hello @PlagueHO ,

Thanks for the quick response.
That sounds more than reasonable.

I'll go ahead and PR this change?

@PlagueHO
Copy link
Member

PlagueHO commented Apr 7, 2022

Hi @uw-dc - sure, would love the PR! If you run into any issues with the pipeline execution etc, please let me know as I've not had much time lately to work on this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
discussion The issue is a discussion. enhancement The issue is an enhancement request.
Projects
None yet
Development

No branches or pull requests

2 participants