From 5388d8bba944276f2bb4dd71dbbe399e765be793 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robin=20Laur=C3=A9n?= Date: Wed, 22 Jun 2016 17:21:34 +0300 Subject: [PATCH 1/3] My re-write of the two existing OS X Defaults modules --- .gitignore | 3 +- Modulefile | 6 -- README.md | 145 ++++++++++++++++++++++++++++++++++++---------- examples/init.pp | 12 ++++ manifests/init.pp | 103 +++++++++++++++++++++++++++++++- metadata.json | 14 +++++ 6 files changed, 244 insertions(+), 39 deletions(-) delete mode 100644 Modulefile create mode 100644 examples/init.pp create mode 100644 metadata.json diff --git a/.gitignore b/.gitignore index 0c6117d..c06a73d 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -pkg \ No newline at end of file +pkg +.DS_Store diff --git a/Modulefile b/Modulefile deleted file mode 100644 index 9f666ce..0000000 --- a/Modulefile +++ /dev/null @@ -1,6 +0,0 @@ -name 'grahamgilbert-macdefaults' -version '0.0.1' -summary 'Manage defaults on an OS X system' -author 'Graham Gilbert' -source 'https://github.com/pebbleit/puppet-macdefaults.git' -license 'Apache 2.0' diff --git a/README.md b/README.md index 164e750..33e638c 100644 --- a/README.md +++ b/README.md @@ -1,30 +1,115 @@ -OS X Defaults module for Puppet -================== - -This module manages defaults on OS X. I didn't write 90% of this, but I can't for the life of me remember where I found it. I'm putting it on here for posterity. - -#Usage - -Possible valuse for ``type`` are: - -* string -* data -* int -* float -* bool -* data -* array -* array-add -* dict -* dict-add - -Example Puppet Code: - - include macdefaults - - mac-defaults { "set-a4": - domain => '/Library/Preferences/com.apple.print.PrintingPrefs', - key => 'DefaultPaperID', - type => 'string', - value => "iso-a4", - } \ No newline at end of file +# OS X Defaults module for Puppet + +## Note of potential disaster + +This module has not been tested. It was rolled straight into production and +let to its own devices. It will probably blow up your whole server park unless +you are careful. If it does, i'd appreciate a patch, so that it won't blow up +any other server park. + +#### Table of Contents + +1. [Description](#description) +1. [Setup - The basics of getting started with macdefaults](#setup) + * [What macdefaults affects](#what-macdefaults-affects) + * [Setup requirements](#setup-requirements) + * [Beginning with macdefaults](#beginning-with-macdefaults) +1. [Usage - Configuration options and additional functionality](#usage) +1. [Reference - An under-the-hood peek at what the module is doing and how](#reference) +1. [Limitations - OS compatibility, etc.](#limitations) +1. [Development - Guide for contributing to the module](#development) + +## Description + +Set or remove your OS X Defaults with macdefaults. + +This module is a re-write of the two modules i found floating around the +interwebs for just this, namely: + +* https://github.com/wfarr/puppet-osx_defaults by Will Farrington, and +* https://github.com/pebbleit/puppet-macdefaults by Graham Gilbert + +Neither of these have been updated for years, and one of the files contained +some kind of incompatibility with Puppet 4. So here's my mash-up of these two +modules. + + +## Setup + +### What macdefaults affects + +You can set or remove any OS X Defaults with this module, but you need to know +the correct domain. For many fun and useful things to muck around with, have a +look at https://github.com/boxen/puppet-osx. + +### Setup Requirements + +None that i can think of. You'll need a Mac (or more specifically, a macOS +computer) to run this on. + +### Beginning with macdefaults + +Use carefully. + +## Usage + +In a manifest dealing with an OS X node (you know, a Mac), include something +along the lines of + +``` +macdefaults { "AppleUpdatesThroughMunki": + ensure => present, + domain => "/Library/Preferences/ManagedInstalls", + key => "InstallAppleSoftwareUpdates", + type => 'bool', + value => True, +} +``` +The code above would ensure that Macs use Munki for Apple system udates. + +Possible values for `type` are those of OS X Defaults; ie. `string`, `data`, +`int`, `float`, `bool`, `array`, `array-add`, `dict` and `dict-add`. That said, +i've never tested any other values than `int`; i just copied this from Graham's +macdefaults README.md, so don't take my word for it. Read the source. Understand +what you do. And send me a patch if you find a bug. + +The code includes some rather ingenious checking for indepotency (lifted from +Gilbert's and Farrington's code). The type attribute isn't checked for +correctness; this is left as an excercise for the reader :) + +I removed the quotes inside some of the code, which might break stuff up. +Please use quotes around any strange string values. + +Yet untested, but according to the puppet [language reference on case matching +](https://docs.puppet.com/puppet/latest/reference/lang_conditional.html#case-matching-1), +the values for the `bool` type _should_ be case-insensitive. + +## Reference + +* https://github.com/wfarr/puppet-osx_defaults by Will Farrington, and +* https://github.com/pebbleit/puppet-macdefaults by Graham Gilbert +* https://github.com/boxen/puppet-osx by Boxen + +## Limitations + +Me, mostly. + +## Development + +Merge/pull requests welcome. + +## Release Notes/Contributors/Etc. + +First version. Works on my machine. Only tested with the `Int` type. Your +mileage will most certainly vary. Handle with care and have mercy. + +If you think there are a lot of comments in the manifest file, it's just because +that's how Puppet does it when you create a new module with `puppet module +generate macdefaults`. + +## Bug warning + +This module was originally called osx_defaults (from Will Farrington's code) but +i chose to go with the name macdefaults, as OS X will soon be known as macOS +rather than OS X. I hope i managed to find-replace all relevant instances of the +old name in the code! diff --git a/examples/init.pp b/examples/init.pp new file mode 100644 index 0000000..5b2d09a --- /dev/null +++ b/examples/init.pp @@ -0,0 +1,12 @@ +# The baseline for module testing used by Puppet Labs is that each manifest +# should have a corresponding test manifest that declares that class or defined +# type. +# +# Tests are then run by using puppet apply --noop (to check for compilation +# errors and view a log of events) or by fully applying the test in a virtual +# environment (to compare the resulting system state to the desired state). +# +# Learn more about module testing here: +# https://docs.puppet.com/guides/tests_smoke.html +# +include ::osx_defaults diff --git a/manifests/init.pp b/manifests/init.pp index 9a8d946..1813b9b 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -1,3 +1,102 @@ +# Class: macdefaults +# =========================== +# +# Handle OS X Defaults from Puppet +# +# Parameters +# ---------- +# +# * `ensure` - present or absent +# * `domain` +# * `key` +# * `type` +# * `value` +# +# Examples +# -------- +# +# @example +# macdefaults { "AppleUpdatesThroughMunki": +# ensure => present, +# domain => "/Library/Preferences/ManagedInstalls", +# key => "InstallAppleSoftwareUpdates", +# type => 'bool', +# value => True, +# } +# +# Authors +# ------- +# +# Robin Laurén +# +# Based on the works of +# * Will Farrington https://github.com/wfarr/puppet-osx_defaults +# * Graham Gilbert https://github.com/pebbleit/puppet-macdefaults +# +# Copyright +# --------- +# +# Copyright 2016 Robin Laurén / Reaktor +# + +define macdefaults( + $ensure = 'present', + $domain = undef, + $key = undef, + $value = undef, + $type = "string", +) { + + case $operatingsystem { + + "Darwin": { + $defaults_cmd = "/usr/bin/defaults" + + case $ensure { + + 'present': { + if ($domain != undef) and ($key != undef) and ($value != undef) { + exec { "defaults write $domain $key -$type $value": + command => "${defaults_cmd} write ${domain} ${key} -${type} ${value}", + unless => $type ? { + 'bool' => $value ? { + 'True' => "${defaults_cmd} read ${domain} ${key} -${type} | grep -qx 1", + 'False' => "${defaults_cmd} read ${domain} ${key} -${type} | grep -qx 0", + }, + default => "${defaults_cmd} read ${domain} ${key} -${type} | grep -qx ${value}", + } + } + } else { + warn ("macdefaults cannot ensure present without domain, key and value attributes") + } + } + + 'absent': { + if ($domain != undef) and ($key != undef) { + exec { "defaults delete $domain $key": + command => "${defaults_cmd} delete ${domain} ${key}", + onlyif => "${defaults_cmd} read ${domain} | egrep '^${key}$''", + } + } else { + warn ("macdefaults cannot ensure absent without domain and key attributes") + } + } + + default: { + warn ("macdefaults ensure => [present | absent] domain key type value") + } + } + } + default: { + warn ("macdefaults only work on OS X") + } + } +} + + + + + # Note that type can be one of: # string, data, int, float, bool, data, array, array-add, dict, dict-add define mac-defaults($domain, $key, $value = false, $type = "string", $action = "write") { @@ -11,8 +110,8 @@ 'bool' => $value ? { 'TRUE' => "defaults read $domain $key | grep -qx 1", 'FALSE' => "defaults read $domain $key | grep -qx 0" - }, - default => "defaults read $domain $key | grep -qx $value | sed -e 's/ (.*)/\1/'" + }, + default => "defaults read $domain $key | grep -qx $value | sed -e 's/ (.*)/\1/'" } } } diff --git a/metadata.json b/metadata.json new file mode 100644 index 0000000..6b6347b --- /dev/null +++ b/metadata.json @@ -0,0 +1,14 @@ +{ + "name": "llauren-osx_defaults", + "version": "0.1.0", + "author": "llauren", + "summary": "Handle OS X Defaults", + "license": "Apache-2.0", + "source": "https://github.com/llauren/puppet-macdefaults", + "project_page": "https://github.com/llauren/puppet-macdefaults", + "issues_url": "https://github.com/llauren/puppet-macdefaults/issues", + "dependencies": [ + {"name":"puppetlabs-stdlib","version_requirement":">= 1.0.0"} + ], + "data_provider": null +} From 9c33a749b958b9146a240ff7ea75664886972873 Mon Sep 17 00:00:00 2001 From: Asennus Date: Thu, 7 Dec 2017 17:11:33 +0200 Subject: [PATCH 2/3] Fairly extensive re-write of everything (STILL UNTESTED!!!) * Expanded the clever boolean `unless` code to make it more boring and readable * Added checks for the parameters * Updated requirement for stdlib to version 4, which provides `assert_type` * Added a license (BSD Simplified/2-clause; licenses are boring) * Removed bugs --- LICENSE | 21 ++++++++ README.md | 51 ++++++++++--------- examples/init.pp | 2 +- manifests/init.pp | 124 +++++++++++++++------------------------------- metadata.json | 10 ++-- 5 files changed, 95 insertions(+), 113 deletions(-) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..88d8f02 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +License: BSD 2-Clause License + +Copyright (c) Robin Laurén / Reaktor (c) 2017, All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. Redistributions in binary form must +reproducethe above copyright notice, this list of conditions and the following +disclaimer in the documentation and/or other materials provided with the +distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md index 33e638c..23e8f79 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,6 @@ any other server park. 1. [Setup - The basics of getting started with macdefaults](#setup) * [What macdefaults affects](#what-macdefaults-affects) * [Setup requirements](#setup-requirements) - * [Beginning with macdefaults](#beginning-with-macdefaults) 1. [Usage - Configuration options and additional functionality](#usage) 1. [Reference - An under-the-hood peek at what the module is doing and how](#reference) 1. [Limitations - OS compatibility, etc.](#limitations) @@ -21,7 +20,7 @@ any other server park. ## Description -Set or remove your OS X Defaults with macdefaults. +Set or remove your macOS `defaults` with macdefaults. This module is a re-write of the two modules i found floating around the interwebs for just this, namely: @@ -33,27 +32,28 @@ Neither of these have been updated for years, and one of the files contained some kind of incompatibility with Puppet 4. So here's my mash-up of these two modules. +The module includes some rudimentary error checking for missing and ill-formed +values. ## Setup +Clone or download this module to live nicely among your other puppet modules. +Cross your fingers. Breathe normally. + ### What macdefaults affects -You can set or remove any OS X Defaults with this module, but you need to know -the correct domain. For many fun and useful things to muck around with, have a -look at https://github.com/boxen/puppet-osx. +You can set or remove any macOS `defaults` with this module, but you need to +know the correct domain. For many fun and useful things to muck around with, +have a look at https://github.com/boxen/puppet-osx. ### Setup Requirements -None that i can think of. You'll need a Mac (or more specifically, a macOS -computer) to run this on. - -### Beginning with macdefaults - -Use carefully. +Requires `puppetlabs-stdlib` version 4.0.0 or higher, and a Mac to run the +module on. ## Usage -In a manifest dealing with an OS X node (you know, a Mac), include something +In a manifest dealing with a macOS node (you know, a Mac), include something along the lines of ``` @@ -65,17 +65,19 @@ macdefaults { "AppleUpdatesThroughMunki": value => True, } ``` -The code above would ensure that Macs use Munki for Apple system udates. +The example code above would ensure that Macs use Munki for Apple system udates. Possible values for `type` are those of OS X Defaults; ie. `string`, `data`, -`int`, `float`, `bool`, `array`, `array-add`, `dict` and `dict-add`. That said, -i've never tested any other values than `int`; i just copied this from Graham's -macdefaults README.md, so don't take my word for it. Read the source. Understand -what you do. And send me a patch if you find a bug. +`int` (or `integer`), `float`, `bool` (or `boolean`), `array`, `array-add`, +`dict` and `dict-add`. That said, i've never tested any other values than `int`; +i just copied this from Graham's macdefaults README.md, so don't take my word +for it. Read the source. Understand what you do. And send me a patch if you find +a bug. -The code includes some rather ingenious checking for indepotency (lifted from -Gilbert's and Farrington's code). The type attribute isn't checked for -correctness; this is left as an excercise for the reader :) +The code includes some checking for idempotency. It used to be wicked clever, +but rather opaque, so i expanded the code for readability. You can still find +the original and quote ingenious checking code for boolean values in Gilbert's +and Farrington's code. I removed the quotes inside some of the code, which might break stuff up. Please use quotes around any strange string values. @@ -86,6 +88,7 @@ the values for the `bool` type _should_ be case-insensitive. ## Reference +* `man defaults` on your Mac * https://github.com/wfarr/puppet-osx_defaults by Will Farrington, and * https://github.com/pebbleit/puppet-macdefaults by Graham Gilbert * https://github.com/boxen/puppet-osx by Boxen @@ -100,7 +103,7 @@ Merge/pull requests welcome. ## Release Notes/Contributors/Etc. -First version. Works on my machine. Only tested with the `Int` type. Your +Second major rewrite. Works on my machine. Only tested with the `Int` type. Your mileage will most certainly vary. Handle with care and have mercy. If you think there are a lot of comments in the manifest file, it's just because @@ -110,6 +113,6 @@ generate macdefaults`. ## Bug warning This module was originally called osx_defaults (from Will Farrington's code) but -i chose to go with the name macdefaults, as OS X will soon be known as macOS -rather than OS X. I hope i managed to find-replace all relevant instances of the -old name in the code! +i chose to go with the name macdefaults, as OS X is now known as macOS rather +than OS X. I hope i managed to find-replace all relevant instances of the old +name in the code! diff --git a/examples/init.pp b/examples/init.pp index 5b2d09a..fbd0e73 100644 --- a/examples/init.pp +++ b/examples/init.pp @@ -9,4 +9,4 @@ # Learn more about module testing here: # https://docs.puppet.com/guides/tests_smoke.html # -include ::osx_defaults +include ::macdefaults diff --git a/manifests/init.pp b/manifests/init.pp index 1813b9b..f34dace 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -1,7 +1,7 @@ # Class: macdefaults # =========================== # -# Handle OS X Defaults from Puppet +# Handle macOS `defaults` from Puppet # # Parameters # ---------- @@ -27,7 +27,7 @@ # Authors # ------- # -# Robin Laurén +# @author Robin Laurén # # Based on the works of # * Will Farrington https://github.com/wfarr/puppet-osx_defaults @@ -36,99 +36,57 @@ # Copyright # --------- # -# Copyright 2016 Robin Laurén / Reaktor -# - -define macdefaults( - $ensure = 'present', - $domain = undef, - $key = undef, - $value = undef, - $type = "string", +# Copyright (c) Robin Laurén / Reaktor (c) 2017, All rights reserved. +# License: BSD 2-Clause License (see LICENSE) + +class macdefaults ( + String $ensure = 'present', + String $domain = undef, + String $key = undef, + $value = undef, + String $type = 'string', ) { - case $operatingsystem { - - "Darwin": { - $defaults_cmd = "/usr/bin/defaults" - - case $ensure { - - 'present': { - if ($domain != undef) and ($key != undef) and ($value != undef) { - exec { "defaults write $domain $key -$type $value": - command => "${defaults_cmd} write ${domain} ${key} -${type} ${value}", - unless => $type ? { - 'bool' => $value ? { - 'True' => "${defaults_cmd} read ${domain} ${key} -${type} | grep -qx 1", - 'False' => "${defaults_cmd} read ${domain} ${key} -${type} | grep -qx 0", - }, - default => "${defaults_cmd} read ${domain} ${key} -${type} | grep -qx ${value}", - } - } - } else { - warn ("macdefaults cannot ensure present without domain, key and value attributes") - } - } - - 'absent': { - if ($domain != undef) and ($key != undef) { - exec { "defaults delete $domain $key": - command => "${defaults_cmd} delete ${domain} ${key}", - onlyif => "${defaults_cmd} read ${domain} | egrep '^${key}$''", - } - } else { - warn ("macdefaults cannot ensure absent without domain and key attributes") - } - } + assert_type(Enum['present', 'absent'], $ensure) + assert_type(Enum['string', 'data', 'int', 'integer', 'float', 'bool', 'boolean', 'date', 'array', 'array-add', 'dict', 'dict-add'], $type) + assert_type(String, $domain) + assert_type(String, $key) - default: { - warn ("macdefaults ensure => [present | absent] domain key type value") - } - } - } - default: { - warn ("macdefaults only work on OS X") - } + if ($facts['operatingsystem'] != 'Darwin') { + fail('macdefaults only works on macOS') } -} + $defaults_cmd = '/usr/bin/defaults' + case $ensure { + 'present': { + if ($value == undef) { + fail ('`value` is missing') + } + if ($type =~ /^bool(ean)?$/) { + $bvalue = assert_type(Boolean, $value) + $nvalue = bool2num($bvalue) + $value = bool2str($bvalue) + $check = "${defaults_cmd} read ${domain} ${key} -${type} ${value} | grep -qx ${nvalue}" + } else { + $check = "${defaults_cmd} read ${domain} ${key} -${type} | grep -qx ${value}" + } -# Note that type can be one of: -# string, data, int, float, bool, data, array, array-add, dict, dict-add -define mac-defaults($domain, $key, $value = false, $type = "string", $action = "write") { -case $operatingsystem { - Darwin:{ - case $action { - "write": { - exec {"defaults write $domain $key -$type '$value'": - path => "/bin:/usr/bin", - unless => $type ? { - 'bool' => $value ? { - 'TRUE' => "defaults read $domain $key | grep -qx 1", - 'FALSE' => "defaults read $domain $key | grep -qx 0" - }, - default => "defaults read $domain $key | grep -qx $value | sed -e 's/ (.*)/\1/'" - } + exec { "${defaults_cmd} write ${domain} ${key} -${type} ${value}": + unless => $check, } } - "delete": { - exec {"defaults delete $domain $key": - path => "/bin:/usr/bin", - logoutput => false, - onlyif => "defaults read $domain | grep -q '$key'" + + 'absent': { + exec { "${defaults_cmd} delete ${domain} ${key}": + onlyif => "${defaults_cmd} read ${domain} | egrep '^${key}$''", } } - } - } -} - - -} - -class macdefaults{ + default: { + fail ('macdefaults ensure => [present | absent] domain key type value') + } + } } diff --git a/metadata.json b/metadata.json index 6b6347b..fc34319 100644 --- a/metadata.json +++ b/metadata.json @@ -1,14 +1,14 @@ { - "name": "llauren-osx_defaults", - "version": "0.1.0", + "name": "llauren-macdefaults", + "version": "0.2.0", "author": "llauren", - "summary": "Handle OS X Defaults", - "license": "Apache-2.0", + "summary": "Handle MacOS Defaults", + "license": "FreeBSD", "source": "https://github.com/llauren/puppet-macdefaults", "project_page": "https://github.com/llauren/puppet-macdefaults", "issues_url": "https://github.com/llauren/puppet-macdefaults/issues", "dependencies": [ - {"name":"puppetlabs-stdlib","version_requirement":">= 1.0.0"} + {"name":"puppetlabs-stdlib","version_requirement":">= 4.0.0"} ], "data_provider": null } From 4032e682ade67cc549be0c3ff48359feb28df79c Mon Sep 17 00:00:00 2001 From: Asennus Date: Thu, 7 Dec 2017 17:18:30 +0200 Subject: [PATCH 3/3] Rename `OS X` to `macOS` :) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 23e8f79..44eb796 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# OS X Defaults module for Puppet +# macOS Defaults module for Puppet ## Note of potential disaster