Skip to content

Commit d93ef7e

Browse files
committed
Create apt package management resource.
1 parent 2fc0525 commit d93ef7e

File tree

8 files changed

+278
-0
lines changed

8 files changed

+278
-0
lines changed

build.ps1

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ $filesForWindowsPackage = @(
4545
$filesForLinuxPackage = @(
4646
'dsc',
4747
'assertion.dsc.resource.json',
48+
'apt.dsc.resource.json',
49+
'apt.dsc.resource.sh',
4850
'group.dsc.resource.json',
4951
'powershell.dsc.resource.json',
5052
'psDscAdapter/',

resources/apt/apt.dsc.resource.json

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
{
2+
"$schema": "https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2024/04/bundled/resource/manifest.json",
3+
"type": "DSC.PackageManagement/Apt",
4+
"description": "DSC resource to manage Apt packages",
5+
"tags": [
6+
"Linux",
7+
"apt",
8+
"PackageManagement"
9+
],
10+
"version": "0.1.0",
11+
"get": {
12+
"executable": "apt.dsc.resource.sh",
13+
"args": [
14+
"get"
15+
],
16+
"input": "env"
17+
},
18+
"set": {
19+
"executable": "apt.dsc.resource.sh",
20+
"args": [
21+
"set"
22+
],
23+
"input": "env",
24+
"implementsPretest": true,
25+
"handlesExist": true
26+
},
27+
"export": {
28+
"executable": "apt.dsc.resource.sh",
29+
"args": [
30+
"export"
31+
],
32+
"input": "env"
33+
},
34+
"exitCodes": {
35+
"0": "Success",
36+
"1": "Invalid parameter"
37+
},
38+
"schema": {
39+
"embedded": {
40+
"$schema": "http://json-schema.org/draft-07/schema#",
41+
"$id": "https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/resources/DSC/PackageManagement/apt/v0.1.0/schema.json",
42+
"title": "Apt",
43+
"description": "Managed packages using apt",
44+
"type": "object",
45+
"required": [
46+
"packageName"
47+
],
48+
"additionalProperties": false,
49+
"properties": {
50+
"packageName": {
51+
"type": "string",
52+
"title": "Package Name",
53+
"description": "Defines the name of the package to query or install"
54+
},
55+
"version": {
56+
"type": "string",
57+
"title": "Version",
58+
"description": "Defines the version of the package to install"
59+
},
60+
"Source": {
61+
"type": "string",
62+
"title": "Source",
63+
"description": "Defines the source of the package"
64+
},
65+
"_exist": {
66+
"type": "boolean",
67+
"title": "Exist",
68+
"description": "Defines if the package should exist or not"
69+
}
70+
}
71+
}
72+
}
73+
}

resources/apt/apt.dsc.resource.sh

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
#!/bin/bash
2+
3+
# Copyright (c) Microsoft Corporation.
4+
# Licensed under the MIT License.
5+
6+
export exist=true
7+
export NONINTERACTIVE=1
8+
9+
# $packageName and $_exist are sent as env vars by dsc converting the JSON input to name/value pairs
10+
11+
check_args() {
12+
if [[ -z $packageName ]]; then
13+
echo "packageName not set"
14+
exit 1
15+
fi
16+
}
17+
18+
get_apt() {
19+
pkgname=$1
20+
InstalledSection=0
21+
apt list --installed $pkgname 2>&1 | while read line; do
22+
if [[ $line == Listing* ]]; then
23+
InstalledSection=1
24+
elif [[ $InstalledSection = 1 ]]; then
25+
echo $line | awk '{
26+
split($0, a, " ");
27+
split(a[1], pn, "/");
28+
printf("{ \"_exist\": \"%s\", \"packageName\": \"%s\", \"Version\": \"%s\", \"Source\": \"%s\" }\n", ENVIRON["exist"], pn[1], a[2], pn[2]);
29+
}'
30+
fi
31+
done
32+
}
33+
34+
if [[ "$#" -eq "0" ]]; then
35+
echo "Command not provided, valid commands: get, set, export"
36+
exit 1
37+
elif [[ "$1" == "get" ]]; then
38+
check_args
39+
output="$(get_apt $packageName)"
40+
if [[ -z $output ]]; then
41+
printf '{ "_exist": "false", "packageName": "%s", "Version": "", "Source": "" }\n' $packageName
42+
else
43+
echo $output
44+
fi
45+
elif [[ "$1" == "set" ]]; then
46+
check_args
47+
if [[ -z $_exist ]]; then
48+
# if $_exist is not defined in the input, it defaults to `true`
49+
_exist=true
50+
fi
51+
if [[ $_exist = true ]]; then
52+
apt install -y "${packageName}"
53+
else
54+
apt remove -y "${packageName}"
55+
fi
56+
elif [[ "$1" == "export" ]]; then
57+
get_apt
58+
else
59+
echo "Invalid command, valid commands: get, set, export"
60+
exit 1
61+
fi

resources/apt/copy_files.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
apt.dsc.resource.sh

resources/apt/test/apt.tests.ps1

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# Copyright (c) Microsoft Corporation.
2+
# Licensed under the MIT License.
3+
4+
Describe 'Apt resource tests' {
5+
BeforeAll {
6+
$aptExists = ($null -ne (Get-Command apt -CommandType Application -ErrorAction Ignore))
7+
}
8+
9+
Context "export" {
10+
It "should have more than 20 resources" {
11+
if (-not $aptExists) {
12+
Set-ItResult -Skip -Because "Apt not found"
13+
}
14+
15+
$result = dsc resource export --resource DSC.PackageManagement/Apt | ConvertFrom-Json
16+
$result.resources.Count | Should -BeGreaterThan 20
17+
}
18+
}
19+
20+
Context "wget tests" {
21+
BeforeAll {
22+
$pkgName = "wget"
23+
$yamlPath = "$PSScriptRoot/assets/apt_${pkgName}.dsc.yaml"
24+
}
25+
26+
It 'Config get works' {
27+
if (-not $aptExists) {
28+
Set-ItResult -Skip -Because "Apt not found"
29+
}
30+
$out = dsc config get -p $yamlPath | ConvertFrom-Json -Depth 10
31+
$LASTEXITCODE | Should -Be 0
32+
$exists = $null -ne (Get-Command $pkgName -CommandType Application -ErrorAction Ignore)
33+
$observed = $out.results[1].result.actualState._exist
34+
$observed | Should -Be $exists
35+
}
36+
37+
It 'Config test works' {
38+
if (-not $aptExists) {
39+
Set-ItResult -Skip -Because "Apt not found"
40+
}
41+
42+
$out = dsc config test -p $yamlPath| ConvertFrom-Json -Depth 10
43+
$LASTEXITCODE | Should -Be 0
44+
$exists = $null -ne (Get-Command pkgName -CommandType Application -ErrorAction Ignore)
45+
$out.results[1].result.inDesiredState | Should -Be $exists
46+
}
47+
}
48+
49+
Context "install/uninstall rolldice tests" {
50+
BeforeAll {
51+
$pkgName = "rolldice"
52+
$yamlInstallPath = "$PSScriptRoot/assets/apt_install_${pkgName}.dsc.yaml"
53+
$yamlUnInstallPath = "$PSScriptRoot/assets/apt_uninstall_${pkgName}.dsc.yaml"
54+
}
55+
56+
It 'Can install a package' {
57+
if (-not $aptExists) {
58+
Set-ItResult -Skip -Because "Apt not found"
59+
}
60+
61+
if (apt list $pkgname 2>&1 | Select-String installed ) {
62+
apt remove -y $pkgname
63+
}
64+
65+
$result = dsc config set -p $yamlInstallPath | ConvertFrom-Json
66+
$result.results[1].result.beforestate._exist | Should -Be false
67+
$result.results[1].result.afterstate._exist | Should -Be true
68+
}
69+
70+
It 'Can uninstall a package' {
71+
if (-not $aptExists) {
72+
Set-ItResult -Skip -Because "Apt not found"
73+
}
74+
75+
if ($null -eq (apt list $pkgName 2>&1 | Select-String installed)) {
76+
apt install -y $pkgname
77+
}
78+
79+
$result = dsc config set -p $yamlUnInstallPath | ConvertFrom-Json
80+
$result.results[1].result.beforestate._exist | Should -Be true
81+
$result.results[1].result.afterstate._exist | Should -Be false
82+
}
83+
}
84+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Example to see if PowerShell 7 is installed, install it, or get all installed packages
2+
$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2024/04/config/document.json
3+
resources:
4+
- name: assertions
5+
type: Microsoft.DSC/Assertion
6+
properties:
7+
$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2024/04/config/document.json
8+
resources:
9+
- name: os_check
10+
type: Microsoft/OSInfo
11+
properties:
12+
family: Linux
13+
- name: apt_rolldice
14+
type: DSC.PackageManagement/Apt
15+
properties:
16+
packageName: rolldice
17+
_exist: true
18+
dependsOn:
19+
- "[resourceId('Microsoft.DSC/Assertion','assertions')]"
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Example to see if PowerShell 7 is installed, install it, or get all installed packages
2+
$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2024/04/config/document.json
3+
resources:
4+
- name: assertions
5+
type: Microsoft.DSC/Assertion
6+
properties:
7+
$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2024/04/config/document.json
8+
resources:
9+
- name: os_check
10+
type: Microsoft/OSInfo
11+
properties:
12+
family: Linux
13+
- name: apt_rolldice
14+
type: DSC.PackageManagement/Apt
15+
properties:
16+
packageName: rolldice
17+
_exist: false
18+
dependsOn:
19+
- "[resourceId('Microsoft.DSC/Assertion','assertions')]"
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Example to see if PowerShell 7 is installed, install it, or get all installed packages
2+
$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2024/04/config/document.json
3+
resources:
4+
- name: assertions
5+
type: Microsoft.DSC/Assertion
6+
properties:
7+
$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2024/04/config/document.json
8+
resources:
9+
- name: os_check
10+
type: Microsoft/OSInfo
11+
properties:
12+
family: Linux
13+
- name: apt_wget
14+
type: DSC.PackageManagement/Apt
15+
properties:
16+
packageName: wget
17+
_exist: true
18+
dependsOn:
19+
- "[resourceId('Microsoft.DSC/Assertion','assertions')]"

0 commit comments

Comments
 (0)