DSCResources/TYConsulting_cPowerShellModuleManagement/TYConsulting_cPowerShellModuleManagement.psm1
Function Get-TargetResource { [CmdletBinding()] [OutputType([System.Array])] param( [ValidateSet('Present','Absent')] [System.String] $Ensure = 'Present', [parameter(Mandatory = $true, HelpMessage="Enter the PowerShell module name. Enter 'All' to include all modules in the repository.")] [ValidateNotNullOrEmpty()] [System.String] $PSModuleName, [parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [System.Version] $PSModuleVersion, [parameter(Mandatory = $true,HelpMessage='Enter PowerShell Repository Name')] [ValidateNotNullOrEmpty()] [System.String] $RepositoryName, [parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [ValidateRange(0,23)] [System.Int32] $MaintenanceStartHour, [parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [ValidateRange(0,59)] [System.Int32] $MaintenanceStartMinute, [parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [System.Int32] $MaintenanceLengthMinute ) $arrModules = @() $parms = @{ Repository = $RepositoryName } If ($PSModuleName -ine 'all') { $parms.Add('Name', $PSModuleName) If ($PSBoundParameters.ContainsKey('PSModuleVersion')) { $parms.Add('RequiredVersion', $PSModuleVersion) Write-Verbose ("Getting module '{0}' version '{1}' from repository '{2}'." -f $PSModuleName, $PSModuleVersion, $RepositoryName) } else { Write-Verbose ("Getting the latest version of module '{0}' from repository '{1}'." -f $PSModuleName, $RepositoryName) } } else { Write-Verbose ("Getting all modules from repository '{0}'." -f $RepositoryName) } $ModulesInRepo = PowerShellGet\Find-Module @parms -ErrorVariable ev -ErrorAction SilentlyContinue Write-Verbose "Modules found in repository: $($ModulesInRepo.Count)" Foreach ($ModuleInRepo in $ModulesInRepo) { Write-Verbose ("Checking module '{0}' version '{1}'." -f $ModuleInRepo.Name, $ModuleInRepo.Version.Tostring()) $localModule = Get-Module -Name $($ModuleInRepo.Name) -ListAvailable | Where-Object {$_.version -eq $($ModuleInRepo.Version)} $objProperties = @{ Name = $ModuleInRepo.Name Version = $ModuleInRepo.Version } If ($localModule) { Write-Verbose ("Module '{0}' version '{1}' is Present." -f $ModuleInRepo.Name, $ModuleInRepo.Version.Tostring()) $objProperties.Add('Ensure', 'Present') } else { Write-Verbose ("Module '{0}' version '{1}' is Absent." -f $ModuleInRepo.Name, $ModuleInRepo.Version.Tostring()) $objProperties.Add('Ensure', 'Absent') } $objLocalModule = new-object PSObject -Property $objProperties $arrModules +=$objLocalModule } ,$arrModules } Function Set-TargetResource { [CmdletBinding()] param( [ValidateSet('Present','Absent')] [System.String] $Ensure = 'Present', [parameter(Mandatory = $true, HelpMessage="Enter the PowerShell module name. Enter 'All' to include all modules in the repository.")] [ValidateNotNullOrEmpty()] [System.String] $PSModuleName, [parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [System.Version] $PSModuleVersion, [parameter(Mandatory = $true,HelpMessage='Add help message for user')] [ValidateNotNullOrEmpty()] [System.String] $RepositoryName, [parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [ValidateRange(0,23)] [System.Int32] $MaintenanceStartHour, [parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [ValidateRange(0,59)] [System.Int32] $MaintenanceStartMinute, [parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [System.Int32] $MaintenanceLengthMinute ) Write-Verbose "Getting Install-Module command details." $InstallModuleCmdInfo = Get-command Install-Module Write-Output ("Getting modules from repository '{0}'." -f $RepositoryName) $parms = @{ Repository = $RepositoryName } If ($PSModuleName -ine 'all') { $parms.Add('Name', $PSModuleName) If ($PSBoundParameters.ContainsKey('PSModuleVersion')) { $parms.Add('RequiredVersion', $PSModuleVersion) } } #check if Installation / Uninstallation can be actioned at this point of time If ($PSBoundParameters.ContainsKey('MaintenanceStartHour') -and $PSBoundParameters.ContainsKey('MaintenanceStartMinute') -and $PSBoundParameters.ContainsKey('MaintenanceLengthMinute')) { $bOKtoAction = Validate-MaintenanceWindow -MaintenanceStartHour $MaintenanceStartHour -MaintenanceStartMinute $MaintenanceStartMinute -MaintenanceLengthMinute $MaintenanceLengthMinute } else { #If maintenance window is not specified, set to true Write-Verbose 'Maintenance window is not specified. It will be ignored.' $bOKtoAction = $true } $ModulesInRepo = PowerShellGet\Find-Module @parms -ErrorVariable ev -ErrorAction SilentlyContinue Foreach ($ModuleInRepo in $ModulesInRepo) { $localModule = Get-Module -Name $($ModuleInRepo.Name) -ListAvailable | Where-Object {$_.version -eq $($ModuleInRepo.Version)} If ($localModule) { Write-Verbose ("Module {0} version '{1}' is already installed." -f $ModuleInRepo.Name, $ModuleInRepo.Version) If ($Ensure -ieq 'absent') { If ($PSBoundParameters.ContainsKey('PSModuleVersion')) { #Make sure uninstallation is not actioned outside of the maintenance window if ($bOKtoAction) { Write-Verbose ("Uinstalling Module {0} version '{1}'." -f $ModuleInRepo.Name, $ModuleInRepo.Version) $UninstallModule = PowerShellGet\Uninstall-Module -Name $ModuleInRepo.Name -RequiredVersion $ModuleInRepo.Version -Force -ErrorVariable ev -ErrorAction SilentlyContinue } else { Write-Verbose ("Module {0} version '{1}' will not be uninstalled at this time because it is out side of configured maintenance window." -f $ModuleInRepo.Name, $ModuleInRepo.Version) } } else { #Make sure uninstallation is not actioned outside of the maintenance window if ($bOKtoAction) { Write-Verbose ("Uinstalling all versions of Module {0}." -f $ModuleInRepo.Name) $UninstallModule = PowerShellGet\Uninstall-Module -Name $ModuleInRepo.Name -AllVersions -Force -ErrorVariable ev -ErrorAction SilentlyContinue } else { Write-Verbose ("All versions of Module {0} will not be uninstalled at this time because it is outside of configured maintenance window." -f $ModuleInRepo.Name) } } } } else { Write-Verbose ("Module {0} version '{1}' is not installed." -f $ModuleInRepo.Name, $ModuleInRepo.Version) if ($Ensure -ieq 'present') { if ($bOKtoAction) { Write-Verbose ("Installing Module {0} version '{1}' now." -f $ModuleInRepo.Name, $ModuleInRepo.Version) If ($InstallModuleCmdInfo.Parameters.containskey("AllowClobber")) { Write-Verbose "Installing the module using Install-Module cmdlet with -AllowClobber switch." $InstallModule = PowerShellGet\Install-Module -Name $($ModuleInRepo.Name) -RequiredVersion $($ModuleInRepo.Version) -Repository $RepositoryName -Force -Scope AllUsers -AllowClobber } else { Write-Verbose "Installing the module using Install-Module cmdlet without -AllowClobber switch." $InstallModule = PowerShellGet\Install-Module -Name $($ModuleInRepo.Name) -RequiredVersion $($ModuleInRepo.Version) -Repository $RepositoryName -Force -Scope AllUsers } } else { Write-Verbose ("Module {0} version '{1}' will not be installed at this time because it is outside of configured maitnenance window." -f $ModuleInRepo.Name, $ModuleInRepo.Version) } } } } If(!(Test-TargetResource @PSBoundParameters)) { throw 'Set-TargetResouce failed' } } Function Test-TargetResource { [CmdletBinding()] [OutputType([System.Boolean])] param( [ValidateSet('Present','Absent')] [System.String] $Ensure = 'Present', [parameter(Mandatory = $true, HelpMessage="Enter the PowerShell module name. Enter 'All' to include all modules in the repository.")] [ValidateNotNullOrEmpty()] [System.String] $PSModuleName, [parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [System.Version] $PSModuleVersion, [parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.String] $RepositoryName, [parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [ValidateRange(0,23)] [System.Int32] $MaintenanceStartHour, [parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [ValidateRange(0,59)] [System.Int32] $MaintenanceStartMinute, [parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [System.Int32] $MaintenanceLengthMinute ) $arrModules = Get-TargetResource @PSBoundParameters $result = $true Foreach ($item in $arrModules) { Write-Verbose "$($item.Name) is currently $($item.Ensure), desired configuration is $ensure." if ($item.Ensure -ine $Ensure) { $result = $false } } $result } Function Validate-MaintenanceWindow { [CmdletBinding()] [OutputType([System.Boolean])] Param ( [parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidateRange(0,24)] [System.Int32] $MaintenanceStartHour, [parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidateRange(0,60)] [System.Int32] $MaintenanceStartMinute, [parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.Int32] $MaintenanceLengthMinute ) $MaintenanceStartTime = Get-Date -Hour $MaintenanceStartHour -Minute $MaintenanceStartMinute $now = Get-Date $MaintenanceEndTime = $MaintenanceStartTime.AddMinutes($MaintenanceLengthMinute) Write-Verbose "Maintenance Window Start Time: $($MaintenanceStartTime.Tostring())" Write-Verbose "Maintenance Window End Time: $($MaintenanceEndTime.Tostring())" #Check if the current datetime is within the maintenance window. If ($MaintenanceStartTime -le $now -and $MaintenanceEndTime -gt $now) { $bWithinMaintWindow = $true } else { $bWithinMaintWindow = $false } $bWithinMaintWindow } Export-ModuleMember -Function *-TargetResource |