Skip to content

Commit

Permalink
(chocolateyGH-20) add cChocoConfig resource
Browse files Browse the repository at this point in the history
This resource allows users to change Chocolatey Config
settings using an DSC resource.
  • Loading branch information
mkevenaar committed May 28, 2020
1 parent 03e6836 commit f8bb5f1
Show file tree
Hide file tree
Showing 4 changed files with 341 additions and 0 deletions.
188 changes: 188 additions & 0 deletions DSCResources/cChocoConfig/cChocoConfig.psm1
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
# Copyright (c) 2017 Chocolatey Software, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

<#
.Description
Returns the configuration for cChocoConfig.
.Example
Get-TargetResource -ConfigName cacheLocation -Ensure 'Present' -Value 'c:\temp\choco'
#>
function Get-TargetResource
{
[CmdletBinding()]
[OutputType([Hashtable])]
param
(
[parameter(Mandatory = $true)]
[string]
$ConfigName,

[ValidateSet('Present','Absent')]
[string]
$Ensure='Present',

[parameter(Mandatory = $false)]
[string]
$Value
)

Write-Verbose "Starting cChocoConfig Get-TargetResource - Config Name: $ConfigName, Ensure: $Ensure"

$returnValue = @{
ConfigName = $ConfigName
Ensure = $Ensure
Value = $Value
}

$returnValue

}

<#
.Description
Performs the set for the cChocoConfig resource.
.Example
Set-TargetResource -ConfigName cacheLocation -Ensure 'Present' -Value 'c:\temp\choco'
#>
function Set-TargetResource
{
[CmdletBinding(SupportsShouldProcess=$true)]
param
(
[parameter(Mandatory = $true)]
[string]
$ConfigName,

[ValidateSet('Present','Absent')]
[string]
$Ensure='Present',

[parameter(Mandatory = $false)]
[string]
$Value
)


Write-Verbose "Starting cChocoConfig Set-TargetResource - Config Name: $ConfigName, Ensure: $Ensure"

if ($pscmdlet.ShouldProcess("Choco config $ConfigName will be ensured $Ensure."))
{
if ($Ensure -eq 'Present')
{
Write-Verbose "Setting choco config $ConfigName."
choco config set --name "'$ConfigName'" --value "'$Value'"
}
else
{
Write-Verbose "Unsetting choco config $ConfigName."
choco config unset --name "'$ConfigName'"
}
}

}

<#
.Description
Performs the test for cChocoFeature.
.Example
Test-TargetResource -ConfigName cacheLocation -Ensure 'Present' -Value 'c:\temp\choco'
#>
function Test-TargetResource
{
[CmdletBinding()]
[OutputType([Boolean])]
param
(
[parameter(Mandatory = $true)]
[string]
$ConfigName,

[ValidateSet('Present','Absent')]
[string]
$Ensure='Present',

[parameter(Mandatory = $false)]
[string]
$Value
)

Write-Verbose "Starting cChocoConfig Test-TargetResource - Config Name: $ConfigName, Ensure: $Ensure."

# validate value is given when ensure present
if ($Ensure -eq 'Present' -and (-not $PSBoundParameters.ContainsKey('Value') -or [String]::IsNullOrEmpty($Value))) {
throw "Missing parameter 'Value' when ensuring config is present!"
}

if($env:ChocolateyInstall -eq "" -or $null -eq $env:ChocolateyInstall)
{
$command = Get-Command -Name choco.exe -ErrorAction SilentlyContinue

if(!$command) {
throw "Unable to find choco.exe. Please make sure Chocolatey is installed correctly."
}

$chocofolder = Split-Path $command.Source

if( $chocofolder.EndsWith("bin") )
{
$chocofolder = Split-Path $chocofolder
}
}
else
{
$chocofolder = $env:ChocolateyInstall
}

if(!(Get-Item -Path $chocofolder -ErrorAction SilentlyContinue)) {
throw "Unable to find Chocolatey installation folder. Please make sure Chocolatey is installed and configured properly."
}

$configfolder = Join-Path -Path $chocofolder -ChildPath "config"
$configfile = Get-ChildItem -Path $configfolder | Where-Object {$_.Name -match "chocolatey.config$"}

if(!(Get-Item -Path $configfile.FullName -ErrorAction SilentlyContinue)) {
throw "Unable to find Chocolatey config file. Please make sure Chocolatey is installed and configured properly."
}

# There is currently no choco command that only returns the settings in an CSV format.
# choco config list -r shows settings, sources, features and a note about API keys.
$xml = [xml](Get-Content -Path $configfile.FullName)
$settings = $xml.chocolatey.config.add
foreach($setting in $settings)
{
# If the config name matches and it should be present, check the value and
# if it matches it returns true.
if($setting.key -eq $ConfigName -and $Ensure -eq 'Present')
{
return ($setting.value -eq $Value)
}
# If the config name matches and it should be absent, check the value and
# if it is null or empty, return true
elseif($setting.key -eq $ConfigName -and $Ensure -eq 'Absent')
{
return ([String]::IsNullOrEmpty($setting.value))
}
}

# If we get this far, the configuraion item hasn't been found.
# There is currently no value, so return false if it should be present.
# True otherwise.
return !($Ensure -eq 'Present')
}

Export-ModuleMember -Function *-TargetResource
9 changes: 9 additions & 0 deletions DSCResources/cChocoConfig/cChocoConfig.schema.mof
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

[ClassVersion("1.0.0.0"), FriendlyName("cChocoConfig")]
class cChocoConfig : OMI_BaseResource
{
[Key] String ConfigName;
[Write,ValueMap{"Present", "Absent"},Values{"Present", "Absent"}] String Ensure;
[Write] String Value;
};

39 changes: 39 additions & 0 deletions Examples/cChocoConfigExample.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Copyright (c) 2017 Chocolatey Software, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


configuration ChocoConfig {

Import-DscResource -ModuleName cChoco

Node 'localhost' {

cChocoConfig webRequestTimeoutSeconds {
ConfigName = "webRequestTimeoutSeconds"
Ensure = 'Present'
Value = 30
}

cChocoConfig proxy {
ConfigName = "proxy"
Ensure = 'Absent'
}
}

}


$config = ChocoConfig

Start-DscConfiguration -Path $config.psparentpath -Wait -Verbose -Force
105 changes: 105 additions & 0 deletions Tests/cChocoConfig_Tests.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# Copyright (c) 2017 Chocolatey Software, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


$ResourceName = ((Split-Path $MyInvocation.MyCommand.Path -Leaf) -split '_')[0]
$ResourceFile = (Get-DscResource -Name $ResourceName).Path

$TestsPath = (split-path -path $MyInvocation.MyCommand.Path -Parent)
$ResourceFile = Get-ChildItem -Recurse $TestsPath\.. -File | Where-Object {$_.name -eq "$ResourceName.psm1"}

Import-Module -Name $ResourceFile.FullName


#---------------------------------#
# Pester tests for cChocoConfig #
#---------------------------------#
Describe "Testing cChocoConfig" {

Context "Test-TargetResource" {

mock -ModuleName cChocoConfig -CommandName Get-Content -MockWith {'<?xml version="1.0" encoding="utf-8"?>
<chocolatey xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<config>
<add key="commandExecutionTimeoutSeconds" value="1339" description="Default timeout for command execution. for infinite (starting in 0.10.4)." />
<add key="proxy" value="" description="Explicit proxy location. Available in 0.9.9.9+." />
</config>
<sources>
<source id="chocolatey" value="https://chocolatey.org/api/v2/" disabled="false" bypassProxy="false" selfService="false" adminOnly="false" priority="0" />
</sources>
</chocolatey>'
} -Verifiable

it 'Test-TargetResource returns true when Present and Configured.' {
Test-TargetResource -ConfigName 'commandExecutionTimeoutSeconds' -Ensure 'Present' -Value '1339' | Should be $true
}

it 'Test-TargetResource returns false when Present and Not configured' {
Test-TargetResource -ConfigName 'proxy' -Ensure 'Present' -Value 'http://myproxy.url' | Should be $false
}

it 'Test-TargetResource returns false when Present and Unknown' {
Test-TargetResource -ConfigName 'MyParam' -Ensure 'Present' -Value 'MyValue' | Should be $false
}

it 'Test-TargetResource throws when Present and no value' {
{ Test-TargetResource -ConfigName 'MyParam' -Ensure 'Present' } | Should -Throw "Missing parameter 'Value' when ensuring config is present!"
}

it 'Test-TargetResource throws when Present and no value' {
{ Test-TargetResource -ConfigName 'MyParam' -Ensure 'Present' -Value '' } | Should -Throw "Missing parameter 'Value' when ensuring config is present!"
}

it 'Test-TargetResource throws when Present and no value' {
{ Test-TargetResource -ConfigName 'MyParam' -Ensure 'Present' -Value $null } | Should -Throw "Missing parameter 'Value' when ensuring config is present!"
}

it 'Test-TargetResource returns false when Absent and Configured' {
Test-TargetResource -ConfigName 'commandExecutionTimeoutSeconds' -Ensure 'Absent' | Should be $false
}

it 'Test-TargetResource returns true when Absent and Not configured' {
Test-TargetResource -ConfigName 'proxy' -Ensure 'Absent' | Should be $true
}

it 'Test-TargetResource returns true when Absent and Unknown' {
Test-TargetResource -ConfigName 'MyParam' -Ensure 'Absent' | Should be $true
}

}

Context "Set-TargetResource" {

InModuleScope -ModuleName cChocoConfig -ScriptBlock {
function choco {}
mock choco {}
}

Set-TargetResource -ConfigName "TestConfig" -Ensure "Present" -Value "MyValue"

it "Present - Should have called choco, with set" {
Assert-MockCalled -CommandName choco -ModuleName cChocoConfig -ParameterFilter {
$args -contains "'MyValue'"
}
}

Set-TargetResource -ConfigName "TestConfig" -Ensure "Absent"

it "Absent - Should have called choco, with unset" {
Assert-MockCalled -CommandName choco -ModuleName cChocoConfig -ParameterFilter {
$args -contains "unset"
}
}
}
}

0 comments on commit f8bb5f1

Please sign in to comment.