-
Notifications
You must be signed in to change notification settings - Fork 56
Create apt package management resource. #434
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
Changes from all commits
d93ef7e
e36cdb8
77e8624
7a3c6b8
eabdb98
b8722fb
cec4cf9
b980f1b
25b67db
2fb63af
46b981b
e064410
b0e2a81
0ad3805
9b69247
e28061b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,74 @@ | ||
| { | ||
| "$schema": "https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2024/04/bundled/resource/manifest.json", | ||
| "type": "DSC.PackageManagement/Apt", | ||
| "description": "Manage packages with the advanced package tool (APT)", | ||
| "tags": [ | ||
| "Linux", | ||
| "apt", | ||
| "PackageManagement" | ||
| ], | ||
| "version": "0.1.0", | ||
| "get": { | ||
| "executable": "apt.dsc.resource.sh", | ||
| "args": [ | ||
| "get" | ||
| ], | ||
| "input": "env" | ||
| }, | ||
| "set": { | ||
| "executable": "apt.dsc.resource.sh", | ||
| "args": [ | ||
| "set" | ||
| ], | ||
| "input": "env", | ||
| "implementsPretest": true, | ||
| "handlesExist": true | ||
| }, | ||
| "export": { | ||
| "executable": "apt.dsc.resource.sh", | ||
| "args": [ | ||
| "export" | ||
| ], | ||
| "input": "env" | ||
| }, | ||
| "exitCodes": { | ||
| "0": "Success", | ||
| "1": "Invalid parameter" | ||
| }, | ||
| "schema": { | ||
| "embedded": { | ||
| "$schema": "http://json-schema.org/draft-07/schema#", | ||
| "$id": "https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/resources/DSC/PackageManagement/apt/v0.1.0/schema.json", | ||
| "title": "Apt", | ||
| "description": "Managed packages using apt", | ||
| "type": "object", | ||
| "required": [ | ||
| "packageName" | ||
| ], | ||
| "additionalProperties": false, | ||
| "properties": { | ||
| "packageName": { | ||
| "type": "string", | ||
| "title": "Package Name", | ||
| "description": "Defines the name of the package to query or install" | ||
| }, | ||
| "version": { | ||
| "type": "string", | ||
| "title": "Version", | ||
| "description": "Defines the version of the package to install" | ||
| }, | ||
| "source": { | ||
| "type": "string", | ||
| "title": "Source", | ||
| "description": "Indicates the source of the package", | ||
| "readOnly": true | ||
| }, | ||
| "_exist": { | ||
JamesWTruher marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| "type": "boolean", | ||
| "title": "Exist", | ||
| "description": "Defines if the package should exist or not" | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| #!/bin/bash | ||
|
|
||
| # Copyright (c) Microsoft Corporation. | ||
| # Licensed under the MIT License. | ||
|
|
||
| export exist=true | ||
| export NONINTERACTIVE=1 | ||
|
|
||
| # $packageName and $_exist are sent as env vars by dsc converting the JSON input to name/value pairs | ||
|
|
||
| check_args() { | ||
| if [[ -z $packageName ]]; then | ||
| echo "packageName not set" | ||
| exit 1 | ||
| fi | ||
| } | ||
|
|
||
| get_apt() { | ||
| pkgname=$1 | ||
| InstalledSection=0 | ||
| apt list --installed $pkgname 2>&1 | while read line; do | ||
SteveL-MSFT marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| if [[ $line == Listing* ]]; then | ||
| InstalledSection=1 | ||
| elif [[ $InstalledSection = 1 ]]; then | ||
| echo $line | awk '{ | ||
| split($0, a, " "); | ||
| split(a[1], pn, "/"); | ||
| printf("{ \"_exist\": \"%s\", \"packageName\": \"%s\", \"version\": \"%s\", \"source\": \"%s\" }\n", ENVIRON["exist"], pn[1], a[2], pn[2]); | ||
| }' | ||
| fi | ||
| done | ||
| } | ||
|
|
||
| if [[ "$#" -eq "0" ]]; then | ||
| echo "Command not provided, valid commands: get, set, export" | ||
| exit 1 | ||
| elif [[ "$1" == "get" ]]; then | ||
| check_args | ||
| output="$(get_apt $packageName)" | ||
| if [[ -z $output ]]; then | ||
| printf '{"_exist":"false","packageName":"%s","version":"","source":""}\n' $packageName | ||
| else | ||
| echo $output | ||
| fi | ||
| elif [[ "$1" == "set" ]]; then | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need to check if the resource is invoked as root? If I recall correctly, install and remove fail as normal users.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @michaeltlombardi perhaps we should have a general issue opened to add in the resource manifest when specific operations require elevated and DSC can fail fast |
||
| check_args | ||
| if [[ -z $_exist ]]; then | ||
| # if $_exist is not defined in the input, it defaults to `true` | ||
| _exist=true | ||
| fi | ||
| if [[ $_exist = true ]]; then | ||
| apt install -y "${packageName}" | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this handle installing a specific version, since we have the
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this resource should support specifying the version, but limit it to apt syntax
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can add this later |
||
| else | ||
| apt remove -y "${packageName}" | ||
| fi | ||
| elif [[ "$1" == "export" ]]; then | ||
| get_apt | ||
| else | ||
| echo "Invalid command, valid commands: get, set, export" | ||
| exit 1 | ||
| fi | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| apt.dsc.resource.sh |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,80 @@ | ||
| # Copyright (c) Microsoft Corporation. | ||
| # Licensed under the MIT License. | ||
|
|
||
| Describe 'Apt resource tests' { | ||
| BeforeAll { | ||
| $aptExists = ($null -ne (Get-Command apt -CommandType Application -ErrorAction Ignore)) | ||
| } | ||
|
|
||
| Context "export" { | ||
| It "should have more than 20 resources" -Skip:$(! $IsLinux) { | ||
| if (-not $aptExists) { | ||
| Set-ItResult -Skip -Because "Apt not found" | ||
| } | ||
|
|
||
| $result = dsc resource export --resource DSC.PackageManagement/Apt | ConvertFrom-Json | ||
| $result.resources.Count | Should -BeGreaterThan 20 | ||
| } | ||
| } | ||
|
|
||
| Context "wget tests" { | ||
| BeforeAll { | ||
| $pkgName = "wget" | ||
| $yamlPath = "$PSScriptRoot/assets/apt_${pkgName}.dsc.yaml" | ||
| } | ||
|
|
||
| It 'Config get works' -Skip:$(! $IsLinux) { | ||
| if (-not $aptExists) { | ||
| Set-ItResult -Skip -Because "Apt not found" | ||
| } | ||
| $out = dsc config get -p $yamlPath | ConvertFrom-Json -Depth 10 | ||
| $LASTEXITCODE | Should -Be 0 | ||
| $exists = $null -ne (Get-Command $pkgName -CommandType Application -ErrorAction Ignore) | ||
| $observed = $out.results[1].result.actualState._exist | ||
| $observed | Should -Be $exists | ||
| } | ||
|
|
||
| It 'Config test works' -Skip:$(! $IsLinux) { | ||
| if (-not $aptExists) { | ||
| Set-ItResult -Skip -Because "Apt not found" | ||
| } | ||
|
|
||
| $out = dsc config test -p $yamlPath| ConvertFrom-Json -Depth 10 | ||
| $LASTEXITCODE | Should -Be 0 | ||
| $exists = $null -ne (Get-Command pkgName -CommandType Application -ErrorAction Ignore) | ||
| $out.results[1].result.inDesiredState | Should -Be $exists | ||
| } | ||
| } | ||
|
|
||
| Context "install/uninstall rolldice tests" { | ||
| BeforeAll { | ||
| $pkgName = "rolldice" | ||
| $yamlInstallPath = "$PSScriptRoot/assets/apt_install_${pkgName}.dsc.yaml" | ||
| $yamlUnInstallPath = "$PSScriptRoot/assets/apt_uninstall_${pkgName}.dsc.yaml" | ||
| } | ||
|
|
||
| It 'Can install a package' -Skip:$(! $IsLinux) { | ||
| Set-ItResult -Skip -Because "Apt requires sudo" | ||
|
|
||
| if (apt list $pkgname 2>&1 | Select-String installed ) { | ||
| apt remove -y $pkgname | ||
| } | ||
|
|
||
| $result = dsc config set -p $yamlInstallPath | ConvertFrom-Json | ||
| $result.results[1].result.beforestate._exist | Should -Be false | ||
| $result.results[1].result.afterstate._exist | Should -Be true | ||
| } | ||
|
|
||
| It 'Can uninstall a package' -Skip:$(! $IsLinux) { | ||
| Set-ItResult -Skip -Because "Apt requires sudo" | ||
|
|
||
| if ($null -eq (apt list $pkgName 2>&1 | Select-String installed)) { | ||
| apt install -y $pkgname | ||
| } | ||
|
|
||
| $result = dsc config set -p $yamlUnInstallPath | ConvertFrom-Json | ||
| $result.results[1].result.beforestate._exist | Should -Be true | ||
| $result.results[1].result.afterstate._exist | Should -Be false | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| # Example to see if PowerShell 7 is installed, install it, or get all installed packages | ||
| $schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2024/04/config/document.json | ||
| resources: | ||
| - name: assertions | ||
| type: Microsoft.DSC/Assertion | ||
| properties: | ||
| $schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2024/04/config/document.json | ||
| resources: | ||
| - name: os_check | ||
| type: Microsoft/OSInfo | ||
| properties: | ||
| family: Linux | ||
| - name: apt_rolldice | ||
| type: DSC.PackageManagement/Apt | ||
| properties: | ||
| packageName: rolldice | ||
| _exist: true | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be better if this value was defined as a parameter so instead of having two similar config, you could just pass in
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm happy to leave that as an exercise for the reader |
||
| dependsOn: | ||
| - "[resourceId('Microsoft.DSC/Assertion','assertions')]" | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| # Example to see if PowerShell 7 is installed, install it, or get all installed packages | ||
| $schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2024/04/config/document.json | ||
| resources: | ||
| - name: assertions | ||
| type: Microsoft.DSC/Assertion | ||
| properties: | ||
| $schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2024/04/config/document.json | ||
| resources: | ||
| - name: os_check | ||
| type: Microsoft/OSInfo | ||
| properties: | ||
| family: Linux | ||
| - name: apt_rolldice | ||
| type: DSC.PackageManagement/Apt | ||
| properties: | ||
| packageName: rolldice | ||
| _exist: false | ||
| dependsOn: | ||
| - "[resourceId('Microsoft.DSC/Assertion','assertions')]" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| # Example to see if PowerShell 7 is installed, install it, or get all installed packages | ||
| $schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2024/04/config/document.json | ||
| resources: | ||
| - name: assertions | ||
| type: Microsoft.DSC/Assertion | ||
| properties: | ||
| $schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2024/04/config/document.json | ||
| resources: | ||
| - name: os_check | ||
| type: Microsoft/OSInfo | ||
| properties: | ||
| family: Linux | ||
| - name: apt_wget | ||
| type: DSC.PackageManagement/Apt | ||
| properties: | ||
| packageName: wget | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| _exist: true | ||
| dependsOn: | ||
| - "[resourceId('Microsoft.DSC/Assertion','assertions')]" | ||
Uh oh!
There was an error while loading. Please reload this page.