├── .gitignore ├── Xcode ├── screenshots │ ├── xcode_beta.png │ └── xcode_more.png ├── XcodeBuildNumberEmitter.py ├── XcodeXIPUnpacker.py ├── XcodeVersionEmitter.py ├── AppleDataGatherer.py ├── Xcode.extract.recipe ├── XcodeVersioner.py ├── XcodeFileNamer.py ├── Xcode.download.recipe ├── AppleCookieDownloader.py ├── Xcode.munki.recipe └── XcodeVersionedName.munki.recipe ├── LegacyRecipes ├── GoogleEarthPro │ ├── GoogleEarthPro_Scripts │ │ └── postinstall │ ├── GoogleEarthPro.download.recipe │ ├── com.github.autopkg.nmcspadden-recipes.googleearthpro.mobileconfig │ ├── GoogleEarthPro.pkg.recipe │ ├── GoogleEarthProProfile.pkg.recipe │ └── GoogleEarthPro.munki.recipe ├── Minecraft │ ├── minecraft.download.recipe │ ├── minecraft.pkg.recipe │ └── minecraft.munki.recipe ├── DragonDictate3 │ ├── DragonDictate3.download.recipe │ └── DragonDictate3.munki.recipe ├── MinecraftEdu │ ├── MinecraftEdu.pkg.recipe │ ├── MinecraftEdu.download.recipe │ └── MinecraftEdu.munki.recipe └── CreateUserPkgMunki │ └── createuserpkg.munki.recipe ├── PostProcessors ├── SharedPostProcessors.recipe ├── README.md └── Yo.py ├── Chef_Processors ├── ChefProcessors.recipe ├── ChefAttributeList.py ├── ChefAttributeHash.py └── ChefArray.py ├── Shared_Processors ├── SharedProcessors.recipe ├── FileAppender.py ├── PackageInfoVersioner.py ├── SHAChecksum.py ├── Rsync.py ├── InstallsArrayFineTuning.py ├── DirectoryList.py ├── SubDirectoryList.py └── README.md ├── DbVisualizer ├── DbVisualizer.install.recipe ├── DbVisualizer.download.recipe ├── DbVisualizer.dmg.recipe ├── DbVisualizer.munki.recipe └── DbVisualizer.pkg.recipe ├── ChefDK ├── ChefDK.install.recipe ├── ChefDK.munki.recipe └── ChefDK.download.recipe ├── ChefClient ├── Chef.install.recipe ├── Chef.munki.recipe └── Chef.download.recipe ├── UnityWebPlayer ├── unitywebplayer.download.recipe └── unitywebplayer.munki.recipe ├── AppStoreApp ├── AppStoreApp.pkg.recipe └── AppStoreApp.munki.recipe ├── android_ndk ├── android_ndk.download.recipe ├── AndroidNDKVersioner.py ├── android_ndk.dmg.recipe └── android_ndk.munki.recipe ├── EclipseTemurin ├── EclipseTemurin.download.recipe.yaml └── EclipseTemurin.munki.recipe.yaml ├── AdoptOpenJDK ├── AdoptOpenJDK11.munki.recipe ├── AdoptOpenJDK11.download.recipe └── AdoptOpenJDKURLProvider.py ├── README.md ├── android_sdk ├── android_sdk.minimal.munki.recipe ├── AndroidSDKVersioner.py ├── PropertiesWriter.py └── AndroidXMLParser.py ├── Acrolinx ├── AcrolinxURLProvider.py ├── Acrolinx.munki.recipe └── Acrolinx.download.recipe ├── SQLDeveloper ├── SQLDeveloper.dmg.recipe ├── SQLDeveloperVersioner.py └── SQLDeveloper.munki.recipe ├── VMwareFusionDeploy ├── VMwareFusionDeploy.munki.recipe └── VMwareFusionDeploy.pkg.recipe └── Oracle └── OracleJava8JDK.munki.recipe /.gitignore: -------------------------------------------------------------------------------- 1 | .pyc 2 | pyc 3 | *.pyc 4 | 5 | .DS_Store 6 | -------------------------------------------------------------------------------- /Xcode/screenshots/xcode_beta.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/autopkg/nmcspadden-recipes/HEAD/Xcode/screenshots/xcode_beta.png -------------------------------------------------------------------------------- /Xcode/screenshots/xcode_more.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/autopkg/nmcspadden-recipes/HEAD/Xcode/screenshots/xcode_more.png -------------------------------------------------------------------------------- /LegacyRecipes/GoogleEarthPro/GoogleEarthPro_Scripts/postinstall: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [[ -f /Library/Profiles/com.github.nmcspadden-recipes.googleearthpro.mobileconfig ]]; then 4 | /usr/bin/profiles -I -F /Library/Profiles/com.github.nmcspadden-recipes.googleearthpro.mobileconfig 5 | fi -------------------------------------------------------------------------------- /PostProcessors/SharedPostProcessors.recipe: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Description 6 | Recipe stub for any Shared Processors in this directory. 7 | 8 | Identifier 9 | com.github.nmcspadden.shared.postprocessors 10 | Input 11 | 12 | MinimumVersion 13 | 0.4.0 14 | Process 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /Chef_Processors/ChefProcessors.recipe: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Copyright 6 | Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved 7 | Description 8 | Recipe stub for any Shared Processors in this directory. 9 | Identifier 10 | com.github.nmcspadden.shared.chef 11 | Input 12 | 13 | MinimumVersion 14 | 0.4.0 15 | Process 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /Shared_Processors/SharedProcessors.recipe: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Copyright 6 | Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved 7 | Description 8 | Recipe stub for any Shared Processors in this directory. 9 | 10 | Identifier 11 | com.github.nmcspadden.shared 12 | Input 13 | 14 | MinimumVersion 15 | 0.4.0 16 | Process 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /DbVisualizer/DbVisualizer.install.recipe: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Copyright 6 | Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved 7 | Description 8 | Downloads the current release version of DbVisualizer, builds an installer package and installs it. 9 | Identifier 10 | com.github.nmcspadden.install.dbvisualizer 11 | Input 12 | 13 | NAME 14 | DbVisualizer 15 | 16 | MinimumVersion 17 | 0.4.0 18 | ParentRecipe 19 | com.github.nmcspadden.pkg.dbvisualizer 20 | Process 21 | 22 | 23 | Processor 24 | Installer 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /LegacyRecipes/Minecraft/minecraft.download.recipe: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Description 6 | Downloads latest version of Minecraft. 7 | Identifier 8 | com.github.nmcspadden.download.minecraft 9 | Input 10 | 11 | NAME 12 | Minecraft 13 | 14 | MinimumVersion 15 | 0.2.0 16 | Process 17 | 18 | 19 | Processor 20 | DeprecationWarning 21 | Arguments 22 | 23 | warning_message 24 | This recipe is no longer supported. Please remove it from your recipe list. 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /LegacyRecipes/DragonDictate3/DragonDictate3.download.recipe: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Description 6 | Downloads the latest Dragon Dictate For Mac 3 version. 7 | Identifier 8 | com.github.download.DragonDictate3 9 | Input 10 | 11 | NAME 12 | DragonDictate3 13 | 14 | MinimumVersion 15 | 1.1 16 | Process 17 | 18 | 19 | Processor 20 | DeprecationWarning 21 | Arguments 22 | 23 | warning_message 24 | This recipe is no longer supported. Please remove it from your recipe list. 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /ChefDK/ChefDK.install.recipe: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Description 6 | Downloads ChefDK installer and installs it from DMG. 7 | Identifier 8 | com.bk.install.chefdk 9 | Input 10 | 11 | NAME 12 | ChefDK 13 | DESTINATION_PATH 14 | /Applications/ 15 | 16 | MinimumVersion 17 | 0.2.9 18 | ParentRecipe 19 | ChefDK.download.recipe 20 | Process 21 | 22 | 23 | Processor 24 | Installer 25 | Arguments 26 | 27 | pkg_path 28 | %input_path% 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /ChefClient/Chef.install.recipe: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Description 6 | Downloads ChefClient installer and installs it. 7 | Identifier 8 | com.bk.install.chefclient 9 | Input 10 | 11 | NAME 12 | ChefClient 13 | DESTINATION_PATH 14 | /Applications/ 15 | 16 | MinimumVersion 17 | 0.2.9 18 | ParentRecipe 19 | Chef.download.recipe 20 | Process 21 | 22 | 23 | Processor 24 | Installer 25 | Arguments 26 | 27 | pkg_path 28 | %input_path% 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /LegacyRecipes/Minecraft/minecraft.pkg.recipe: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Description 6 | Packages up Minecraft for deployment. THIS RECIPE REQUIRES JAVA TO BE INSTALLED IN ORDER TO RUN. 7 | Identifier 8 | com.github.nmcspadden.pkg.minecraft 9 | Input 10 | 11 | NAME 12 | Minecraft 13 | 14 | MinimumVersion 15 | 0.2.0 16 | ParentRecipe 17 | com.github.nmcspadden.download.minecraft 18 | Process 19 | 20 | 21 | Processor 22 | DeprecationWarning 23 | Arguments 24 | 25 | warning_message 26 | This recipe is no longer supported. Please remove it from your recipe list. 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /LegacyRecipes/MinecraftEdu/MinecraftEdu.pkg.recipe: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Description 6 | Takes a downloaded "minecraftedu.jar" from the Caches folder and turns it into a package. 7 | Identifier 8 | com.github.nmcspadden.pkg.MinecraftEdu 9 | Input 10 | 11 | NAME 12 | MinecraftEdu 13 | 14 | MinimumVersion 15 | 0.2.0 16 | ParentRecipe 17 | com.github.nmcspadden.download.MinecraftEdu 18 | Process 19 | 20 | 21 | Processor 22 | DeprecationWarning 23 | Arguments 24 | 25 | warning_message 26 | This recipe is no longer supported. Please remove it from your recipe list. 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /PostProcessors/README.md: -------------------------------------------------------------------------------- 1 | #Yo Postprocessor 2 | 3 | This is based on Shea Craig's Yo utility, which generates notifications via the Terminal. 4 | 5 | This is a shared AutoPkg postprocessor, and will generate a notification anytime an item is imported into the Munki repo. 6 | 7 | See the documentation for details on [shared AutoPkg processors](https://github.com/autopkg/autopkg/wiki/Processor-Locations#shared-recipe-processors). 8 | 9 | It can be called on your autopkg runs with the `--post` or `--postprocessor` switch: 10 | 11 | ``` 12 | autopkg run VLC.munki --post=com.github.nmcspadden.shared/Yo 13 | ``` 14 | 15 | If will trigger after each recipe. It will *only* generate notifications with .munki recipes (i.e. recipes that call MunkiImporter as the last processor). Other recipes will not cause the Yo postprocessor to generate notifications. 16 | 17 | By default, yo.app is placed into /Applications/Utilities, but you can override this default and place yo.app anywhere by using the `-k` or `--key` switch with the `yo_path` key: 18 | 19 | ``` 20 | autopkg run VLC.munki --post=com.github.nmcspadden.shared/Yo -k yo_path="/Users/nick/Desktop/yo.app" 21 | ``` 22 | 23 | Yes, I know, this is kind of useless, but who cares, I was bored on a plane with no WiFi. -------------------------------------------------------------------------------- /UnityWebPlayer/unitywebplayer.download.recipe: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Description 6 | Downloads latest version of Unity Web Player. 7 | Identifier 8 | com.github.nmcspadden.download.UnityWebPlayer 9 | Input 10 | 11 | NAME 12 | UnityWebPlayer 13 | 14 | MinimumVersion 15 | 0.2.0 16 | Process 17 | 18 | 19 | Arguments 20 | 21 | url 22 | https://webplayer.unity3d.com/download_webplayer-3.x/webplayer-mini.dmg 23 | filename 24 | %NAME%.dmg 25 | 26 | Processor 27 | URLDownloader 28 | 29 | 30 | Processor 31 | EndOfCheckPhase 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /AppStoreApp/AppStoreApp.pkg.recipe: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Description 6 | Creates a package installer out of a MAS app if a newer version is available locally. 7 | Identifier 8 | com.github.nmcspadden.pkg.appstore 9 | Input 10 | 11 | NAME 12 | AppStoreApp 13 | PATH 14 | /Applications/%NAME%.app 15 | 16 | MinimumVersion 17 | 1.0.0 18 | Process 19 | 20 | 21 | Processor 22 | Versioner 23 | Arguments 24 | 25 | input_plist_path 26 | %PATH%/Contents/Info.plist 27 | 28 | 29 | 30 | Processor 31 | AppPkgCreator 32 | Arguments 33 | 34 | app_path 35 | %PATH% 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /LegacyRecipes/CreateUserPkgMunki/createuserpkg.munki.recipe: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Description 6 | Takes an existing CreateUserPkg .pkg file and adds Munki-specific features. You should override the NAME and PKG_PATH variables. 7 | Identifier 8 | com.github.nmcspadden.munki.CreateUserPkg 9 | Input 10 | 11 | MUNKI_REPO_SUBDIR 12 | users 13 | NAME 14 | CreateUser 15 | PKG_PATH 16 | /path/to/user_package.pkg 17 | pkginfo 18 | 19 | catalogs 20 | 21 | testing 22 | 23 | minimum_os_version 24 | 10.7.0 25 | name 26 | %NAME% 27 | unattended_install 28 | 29 | 30 | 31 | Process 32 | 33 | 34 | Processor 35 | DeprecationWarning 36 | Arguments 37 | 38 | warning_message 39 | This recipe is no longer supported. Please remove it from your recipe list. 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /DbVisualizer/DbVisualizer.download.recipe: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Copyright 6 | Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved 7 | Description 8 | Downloads the latest version of DbVisualizer. 9 | Identifier 10 | com.github.nmcspadden.download.dbvisualizer 11 | Input 12 | 13 | NAME 14 | DbVisualizer 15 | VERSION 16 | 11 17 | 18 | MinimumVersion 19 | 0.5.0 20 | Process 21 | 22 | 23 | Arguments 24 | 25 | re_pattern 26 | \/.*.tgz(?=") 27 | url 28 | https://www.dbvis.com/download/%VERSION%.0 29 | 30 | Processor 31 | URLTextSearcher 32 | 33 | 34 | Arguments 35 | 36 | url 37 | https:%match% 38 | 39 | Processor 40 | URLDownloader 41 | 42 | 43 | Processor 44 | EndOfCheckPhase 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /Shared_Processors/FileAppender.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) Facebook, Inc. and its affiliates. 5 | # 6 | # This source code is licensed under the BSD-style license found in the 7 | # LICENSE file in the root directory of this source tree.# 8 | """Processor that creates a file.""" 9 | 10 | from __future__ import absolute_import 11 | 12 | from autopkglib import Processor, ProcessorError 13 | 14 | __all__ = ["FileAppender"] 15 | 16 | 17 | class FileAppender(Processor): 18 | """Append contents to the end of a file.""" 19 | 20 | description = __doc__ 21 | input_variables = { 22 | "file_path": {"required": True, "description": "Path to a file to append to."}, 23 | "file_content": {"required": True, "description": "Contents to add to a file."}, 24 | } 25 | output_variables = {} 26 | 27 | def main(self): 28 | try: 29 | with open(self.env["file_path"], "a") as fileref: 30 | fileref.write(self.env["file_content"]) 31 | self.output("Appened to file at %s" % self.env["file_path"]) 32 | except BaseException as err: 33 | raise ProcessorError( 34 | "Can't append to file at %s: %s" % (self.env["file_path"], err) 35 | ) 36 | # clean the variable up afterwards to not poison future runs 37 | self.env["file_content"] = "" 38 | self.env["file_path"] = "" 39 | 40 | 41 | if __name__ == "__main__": 42 | PROCESSOR = FileAppender() 43 | PROCESSOR.execute_shell() 44 | -------------------------------------------------------------------------------- /android_ndk/android_ndk.download.recipe: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Copyright 6 | Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved 7 | Description 8 | Downloads latest release of Android NDK. 9 | Identifier 10 | com.github.nmcspadden.download.android_ndk 11 | Input 12 | 13 | NAME 14 | android_ndk 15 | RELEASE 16 | r.* 17 | 18 | MinimumVersion 19 | 0.5.0 20 | Process 21 | 22 | 23 | Arguments 24 | 25 | re_pattern 26 | "(https:\/\/dl\.google\.com\/android\/repository\/android-ndk-%RELEASE%-darwin-x86_64.zip)" 27 | url 28 | https://github.com/android-ndk/ndk/wiki 29 | 30 | Processor 31 | URLTextSearcher 32 | 33 | 34 | Arguments 35 | 36 | url 37 | %match% 38 | 39 | Processor 40 | URLDownloader 41 | 42 | 43 | Processor 44 | EndOfCheckPhase 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /LegacyRecipes/MinecraftEdu/MinecraftEdu.download.recipe: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Description 6 | Downloads latest version of MinecraftEdu. Be sure to replace your username and password. If you do not want to put your password in plaintext, you can use a hash of it generated here: http://minecraftedu.com/api/api.php?action=gethash&username=yourusername&password=yourpassword 7 | Identifier 8 | com.github.nmcspadden.download.MinecraftEdu 9 | Input 10 | 11 | NAME 12 | minecraft 13 | USERNAME 14 | username 15 | PASSWORD 16 | password 17 | HASHED 18 | true 19 | TYPE 20 | stable 21 | 22 | MinimumVersion 23 | 0.2.0 24 | Process 25 | 26 | 27 | Processor 28 | DeprecationWarning 29 | Arguments 30 | 31 | warning_message 32 | This recipe is no longer supported. Please remove it from your recipe list. 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /LegacyRecipes/DragonDictate3/DragonDictate3.munki.recipe: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Description 6 | Downloads the latest Dragon Dictate For Mac 3 version and imports into Munki. Does not include licensing, nor bypassing Accessibility requirements. 7 | Identifier 8 | com.github.munki.DragonDictate3 9 | Input 10 | 11 | NAME 12 | DragonDictate3 13 | MUNKI_REPO_SUBDIR 14 | apps/%NAME% 15 | pkginfo 16 | 17 | catalogs 18 | 19 | testing 20 | 21 | display_name 22 | DragonDictate 23 | name 24 | %NAME% 25 | unattended_install 26 | 27 | 28 | 29 | MinimumVersion 30 | 0.2.0 31 | ParentRecipe 32 | com.github.download.DragonDictate3 33 | Process 34 | 35 | 36 | Processor 37 | DeprecationWarning 38 | Arguments 39 | 40 | warning_message 41 | This recipe is no longer supported. Please remove it from your recipe list. 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /DbVisualizer/DbVisualizer.dmg.recipe: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Copyright 6 | Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved 7 | Description 8 | Downloads and makes a DMG of the latest version of DbVisualizer. 9 | Identifier 10 | com.github.nmcspadden.dmg.dbvisualizer 11 | Input 12 | 13 | NAME 14 | DbVisualizer 15 | 16 | MinimumVersion 17 | 0.5.0 18 | ParentRecipe 19 | com.github.nmcspadden.download.dbvisualizer 20 | Process 21 | 22 | 23 | Arguments 24 | 25 | purge_destination 26 | 27 | 28 | Processor 29 | Unarchiver 30 | 31 | 32 | Arguments 33 | 34 | pattern 35 | %RECIPE_CACHE_DIR%/%NAME%/*.app 36 | 37 | Processor 38 | FileFinder 39 | 40 | 41 | Arguments 42 | 43 | info_path 44 | %found_filename% 45 | 46 | Processor 47 | PlistReader 48 | 49 | 50 | Arguments 51 | 52 | dmg_path 53 | %RECIPE_CACHE_DIR%/%NAME%-%version%.dmg 54 | dmg_root 55 | %RECIPE_CACHE_DIR%/%NAME% 56 | 57 | Processor 58 | DmgCreator 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /LegacyRecipes/Minecraft/minecraft.munki.recipe: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Description 6 | Packages the latest Minecraft release, and imports it into Munki. THIS RECIPE REQUIRES JAVA TO SUCCESSFULLY RUN. 7 | Identifier 8 | com.github.nmcspadden.munki.minecraft 9 | Input 10 | 11 | MUNKI_REPO_SUBDIR 12 | apps 13 | NAME 14 | Minecraft 15 | pkginfo 16 | 17 | catalogs 18 | 19 | testing 20 | 21 | description 22 | Minecraft with LaunchAgent to install into user's home directories. 23 | display_name 24 | Minecraft 25 | minimum_os_version 26 | 10.7.0 27 | name 28 | %NAME% 29 | requires 30 | 31 | Java6_Apple 32 | 33 | unattended_install 34 | 35 | 36 | 37 | ParentRecipe 38 | com.github.nmcspadden.pkg.minecraft 39 | Process 40 | 41 | 42 | Processor 43 | DeprecationWarning 44 | Arguments 45 | 46 | warning_message 47 | This recipe is no longer supported. Please remove it from your recipe list. 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /ChefDK/ChefDK.munki.recipe: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Description 6 | Downloads the latest Chef DK for Mac version and imports into Munki. 7 | Identifier 8 | com.github.nmcspadden.munki.chefdk 9 | Input 10 | 11 | NAME 12 | ChefDK 13 | OS 14 | 10.12 15 | MUNKI_REPO_SUBDIR 16 | apps/%NAME% 17 | pkginfo 18 | 19 | catalogs 20 | 21 | testing 22 | 23 | category 24 | Admin Tool 25 | developer 26 | Opscode 27 | display_name 28 | Chef Development Kit 29 | name 30 | %NAME% 31 | unattended_install 32 | 33 | minimum_os_version 34 | 10.7.0 35 | 36 | 37 | MinimumVersion 38 | 0.2.0 39 | ParentRecipe 40 | com.github.nmcspadden.download.chefdk 41 | Process 42 | 43 | 44 | Arguments 45 | 46 | pkg_path 47 | %RECIPE_CACHE_DIR%/downloads/%NAME%.dmg 48 | repo_subdirectory 49 | %MUNKI_REPO_SUBDIR% 50 | 51 | Processor 52 | MunkiImporter 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /ChefClient/Chef.munki.recipe: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Description 6 | Downloads the latest Chef Client for Mac version and imports into Munki. 7 | Identifier 8 | com.github.nmcspadden.munki.ChefClient 9 | Input 10 | 11 | NAME 12 | Chef 13 | OS 14 | 10.12 15 | MUNKI_REPO_SUBDIR 16 | apps/%NAME% 17 | pkginfo 18 | 19 | catalogs 20 | 21 | testing 22 | 23 | category 24 | Admin Tool 25 | developer 26 | Opscode 27 | display_name 28 | Chef Client 29 | name 30 | %NAME% 31 | unattended_install 32 | 33 | minimum_os_version 34 | 10.7.0 35 | 36 | 37 | MinimumVersion 38 | 0.2.0 39 | ParentRecipe 40 | com.github.nmcspadden.download.ChefClient 41 | Process 42 | 43 | 44 | Arguments 45 | 46 | pkg_path 47 | %RECIPE_CACHE_DIR%/downloads/%NAME%.dmg 48 | repo_subdirectory 49 | %MUNKI_REPO_SUBDIR% 50 | 51 | Processor 52 | MunkiImporter 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /Shared_Processors/PackageInfoVersioner.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) Facebook, Inc. and its affiliates. 5 | # 6 | # This source code is licensed under the BSD-style license found in the 7 | # LICENSE file in the root directory of this source tree.# 8 | """See docstring for PackageInfoVersioner class.""" 9 | 10 | # Disabling warnings for env members and imports that only affect recipe- 11 | # specific processors. 12 | # pylint: disable=e1101,f0401 13 | 14 | from __future__ import absolute_import 15 | 16 | from xml.dom import minidom 17 | 18 | from autopkglib import Processor, ProcessorError 19 | 20 | __all__ = ["PackageInfoVersioner"] 21 | 22 | 23 | class PackageInfoVersioner(Processor): 24 | """Get version from a PackageInfo file in a distribution/bundle package.""" 25 | 26 | description = __doc__ 27 | input_variables = { 28 | "package_info_path": { 29 | "required": True, 30 | "description": ( 31 | "Path to PackageInfo file inside a distribution", 32 | "/bundle package.", 33 | ), 34 | } 35 | } 36 | output_variables = { 37 | "pkg_id": { 38 | "description": "Package identifier returned from pkg-info field in PackageInfo." 39 | }, 40 | "version": { 41 | "description": "Version returned from pkg-info field in PackageInfo." 42 | } 43 | } 44 | 45 | __doc__ = description 46 | 47 | def main(self): 48 | try: 49 | dom = minidom.parse(self.env["package_info_path"]) 50 | except IOError as err: 51 | raise ProcessorError(err) 52 | pkgrefs = dom.getElementsByTagName("pkg-info") 53 | self.env["pkg_id"] = pkgrefs[0].attributes["identifier"].value 54 | self.output("Found pkg_id %s" % self.env["pkg_id"]) 55 | self.env["version"] = pkgrefs[0].attributes["version"].value 56 | self.output("Found version %s" % self.env["version"]) 57 | 58 | 59 | if __name__ == "__main__": 60 | PROCESSOR = PackageInfoVersioner() 61 | PROCESSOR.execute_shell() 62 | -------------------------------------------------------------------------------- /ChefDK/ChefDK.download.recipe: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Description 6 | Downloads the latest Chef DK for Mac version. 7 | Identifier 8 | com.github.nmcspadden.download.chefdk 9 | Input 10 | 11 | NAME 12 | Chef 13 | OS 14 | 10.12 15 | CHEF_VERSION 16 | latest 17 | URL 18 | https://omnitruck.chef.io/stable/chefdk/download?p=mac_os_x&pv=%OS%&m=x86_64&v=%CHEF_VERSION% 19 | 20 | MinimumVersion 21 | 0.2.0 22 | Process 23 | 24 | 25 | Processor 26 | URLDownloader 27 | Arguments 28 | 29 | filename 30 | %NAME%.dmg 31 | url 32 | %URL% 33 | 34 | 35 | 36 | Processor 37 | CodeSignatureVerifier 38 | Arguments 39 | 40 | input_path 41 | %pathname%/chef*.pkg 42 | expected_authority_names 43 | 44 | Developer ID Installer: Chef Software, Inc. (EU3VF8YLX2) 45 | Developer ID Certification Authority 46 | Apple Root CA 47 | 48 | 49 | 50 | 51 | Processor 52 | EndOfCheckPhase 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /ChefClient/Chef.download.recipe: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Description 6 | Downloads the latest Chef Client for Mac version. 7 | Identifier 8 | com.github.nmcspadden.download.ChefClient 9 | Input 10 | 11 | NAME 12 | Chef 13 | OS 14 | 10.12 15 | CHEF_VERSION 16 | latest 17 | URL 18 | https://omnitruck.chef.io/stable/chef/download?p=mac_os_x&pv=10.12&m=x86_64&v=%CHEF_VERSION% 19 | 20 | MinimumVersion 21 | 0.2.0 22 | Process 23 | 24 | 25 | Processor 26 | URLDownloader 27 | Arguments 28 | 29 | filename 30 | %NAME%.dmg 31 | url 32 | %URL% 33 | 34 | 35 | 36 | Processor 37 | CodeSignatureVerifier 38 | Arguments 39 | 40 | input_path 41 | %pathname%/chef*.pkg 42 | expected_authority_names 43 | 44 | Developer ID Installer: Chef Software, Inc. (EU3VF8YLX2) 45 | Developer ID Certification Authority 46 | Apple Root CA 47 | 48 | 49 | 50 | 51 | Processor 52 | EndOfCheckPhase 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /Shared_Processors/SHAChecksum.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # 3 | # Copyright (c) 2015, Facebook, Inc. 4 | # All rights reserved. 5 | # 6 | # This source code is licensed under the BSD-style license found in the 7 | # LICENSE file in the root directory of this source tree. An additional grant 8 | # of patent rights can be found in the PATENTS file in the same directory. 9 | """See docstring for SHAChecksum class""" 10 | 11 | # Disabling warnings for env members and imports that only affect recipe- 12 | # specific processors. 13 | # pylint: disable=e1101,f0401 14 | 15 | import subprocess 16 | 17 | from autopkglib import Processor, ProcessorError 18 | 19 | 20 | __all__ = ["SHAChecksum"] 21 | 22 | 23 | class SHAChecksum(Processor): 24 | """Calculate checksum for a file""" 25 | 26 | description = __doc__ 27 | input_variables = { 28 | "source_file": { 29 | "required": True, 30 | "description": ("Path to file to calculate checksum on."), 31 | }, 32 | "checksum_type": { 33 | "required": False, 34 | "description": ( 35 | "Checksum type, will be passed directly to ", 36 | "shasum -a. See manpage for available options. " 37 | "Defaults to SHA1.", 38 | ), 39 | }, 40 | } 41 | output_variables = { 42 | "checksum": { 43 | "description": "Version returned from pkg-info field in PackageInfo." 44 | } 45 | } 46 | 47 | __doc__ = description 48 | 49 | def main(self): 50 | sha_args = self.env.get("checksum_type", None) 51 | cmd = ["/usr/bin/shasum"] 52 | if sha_args: 53 | cmd.append("-a") 54 | cmd.append(sha_args) 55 | cmd.append(self.env["source_file"]) 56 | proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 57 | (shaout, shaerr) = proc.communicate() 58 | if shaerr: 59 | raise ProcessorError(shaerr) 60 | self.output(shaout) 61 | self.env["checksum"] = shaout.split()[0].decode("utf-8") 62 | 63 | 64 | if __name__ == "__main__": 65 | PROCESSOR = SHAChecksum() 66 | PROCESSOR.execute_shell() 67 | -------------------------------------------------------------------------------- /Shared_Processors/Rsync.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) 2015, Facebook, Inc. 5 | # All rights reserved. 6 | # 7 | # This source code is licensed under the BSD-style license found in the 8 | # LICENSE file in the root directory of this source tree. An additional grant 9 | # of patent rights can be found in the PATENTS file in the same directory. 10 | """See docstring for Rsync class.""" 11 | 12 | from __future__ import absolute_import 13 | 14 | import subprocess 15 | 16 | from autopkglib import Processor, ProcessorError 17 | 18 | __all__ = ["Rsync"] 19 | 20 | 21 | class Rsync(Processor): 22 | """Rsyncs a path to another path.""" 23 | 24 | description = __doc__ 25 | input_variables = { 26 | "source_path": { 27 | "required": True, 28 | "description": ("Path to file or directory to copy from."), 29 | }, 30 | "destination_path": { 31 | "required": True, 32 | "description": ("Path to file or directory to copy to."), 33 | }, 34 | "rsync_arguments": { 35 | "required": False, 36 | "description": ("List of arguments passed to rsync directly."), 37 | }, 38 | "rsync_path": { 39 | "required": False, 40 | "description": ("Custom path to rsync. Defaults to /usr/bin/rsync."), 41 | }, 42 | } 43 | output_variables = {} 44 | 45 | __doc__ = description 46 | 47 | def main(self): 48 | rsync_location = self.env.get("rsync_path", "/usr/bin/rsync") 49 | rsync_args = self.env.get("rsync_arguments", []) 50 | if isinstance(rsync_args, basestring): 51 | raise ProcessorError("rsync_args must be a list!") 52 | cmd = [rsync_location] 53 | if rsync_args: 54 | cmd.extend(rsync_args) 55 | cmd.extend([self.env["source_path"], self.env["destination_path"]]) 56 | proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 57 | (rout, rerr) = proc.communicate() 58 | if rerr: 59 | raise ProcessorError(rerr) 60 | self.output(rout) 61 | 62 | 63 | if __name__ == "__main__": 64 | PROCESSOR = Rsync() 65 | PROCESSOR.execute_shell() 66 | -------------------------------------------------------------------------------- /Shared_Processors/InstallsArrayFineTuning.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) Facebook, Inc. and its affiliates. 5 | # 6 | # This source code is licensed under the BSD-style license found in the 7 | # LICENSE file in the root directory of this source tree.# 8 | """See docstring for PackageInfoVersioner class.""" 9 | 10 | 11 | from __future__ import absolute_import 12 | 13 | from autopkglib import Processor, ProcessorError 14 | 15 | __all__ = ["InstallsArrayFineTuning"] 16 | 17 | 18 | class InstallsArrayFineTuning(Processor): 19 | """Change an installs array to allow fine-tuning of a type.""" 20 | 21 | description = __doc__ 22 | input_variables = { 23 | "additional_pkginfo": { 24 | "required": True, 25 | "description": ("Dictionary containing an installs array."), 26 | }, 27 | "changes": { 28 | "required": True, 29 | "description": ( 30 | "List of dictionaries containing replacement values " 31 | "for installs types. Each dictionary must contain a " 32 | "path and the new type." 33 | ), 34 | }, 35 | } 36 | 37 | output_variables = { 38 | "changed_pkginfo": {"description": "Fine tuned additional_pkginfo dictionary."} 39 | } 40 | 41 | __doc__ = description 42 | 43 | def main(self): 44 | """Magic.""" 45 | current = self.env["additional_pkginfo"]["installs"] 46 | changes = self.env["changes"] 47 | for change in changes: 48 | path = change.get("path", None) 49 | if not path: 50 | raise ProcessorError("No path found in change!") 51 | newtype = change.get("type", None) 52 | if not newtype: 53 | raise ProcessorError("No type found in change!") 54 | # Replace the installs 55 | for install in current: 56 | if install["path"] == path: 57 | install["type"] = newtype 58 | self.output("Replacing type for %s to %s" % (path, newtype)) 59 | self.env["changed_pkginfo"] = current 60 | 61 | 62 | if __name__ == "__main__": 63 | PROCESSOR = InstallsArrayFineTuning() 64 | PROCESSOR.execute_shell() 65 | -------------------------------------------------------------------------------- /PostProcessors/Yo.py: -------------------------------------------------------------------------------- 1 | #!/usr/local/autopkg/python 2 | # 3 | # Copyright 2015 Nick McSpadden 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | from __future__ import absolute_import 18 | 19 | import os.path 20 | import subprocess 21 | 22 | from autopkglib import Processor, ProcessorError 23 | 24 | __all__ = ["Yo"] 25 | 26 | class Yo(Processor): 27 | description = "Provides a Yo notification if anything was imported." 28 | input_variables = { 29 | "munki_info": { 30 | "required": False, 31 | "description": ("Munki info dictionary to use to display info.") 32 | }, 33 | "munki_repo_changed": { 34 | "required": False, 35 | "description": ("Whether or not item was imported.") 36 | }, 37 | "yo_path": { 38 | "required": False, 39 | "description": ("Path to yo.app. Defaults to /Applications " 40 | "/Utilities/yo.app.") 41 | } 42 | } 43 | output_variables = { 44 | } 45 | 46 | __doc__ = description 47 | 48 | def main(self): 49 | was_imported = self.env.get("munki_repo_changed") 50 | munkiInfo = self.env.get("munki_info") 51 | yo_path = self.env.get("yo_path") or "/Applications/Utilities/yo.app" 52 | yo = os.path.join(yo_path, 'Contents/MacOS/yo') 53 | if was_imported: 54 | subtext = "%s was imported" % munkiInfo["name"] 55 | cmd = [yo, "-t", "Autopkg", "-s", subtext ] 56 | proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 57 | (cmd_out, cmd_err) = proc.communicate() 58 | 59 | 60 | if __name__ == "__main__": 61 | processor = Yo() 62 | processor.execute_shell() 63 | -------------------------------------------------------------------------------- /android_ndk/AndroidNDKVersioner.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | """Return version for Android NDK.""" 4 | # 5 | # Copyright (c) Facebook, Inc. and its affiliates. 6 | # 7 | # Licensed under the Apache License, Version 2.0 (the "License"); 8 | # you may not use this file except in compliance with the License. 9 | # You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | 19 | from __future__ import absolute_import 20 | 21 | import os 22 | import shlex 23 | 24 | from autopkglib import Processor, ProcessorError 25 | 26 | __all__ = ["AndroidNDKVersioner"] 27 | 28 | 29 | class AndroidNDKVersioner(Processor): 30 | """Return version for Android NDK.""" 31 | 32 | description = ( 33 | "Detect version of downloaded Android NDK based on source.properties." 34 | ) 35 | input_variables = { 36 | "properties_path": { 37 | "required": True, 38 | "description": "File to parse for version info.", 39 | } 40 | } 41 | output_variables = { 42 | "release_num": {"description": "Release of download."}, 43 | "version": {"description": "Version of download."}, 44 | } 45 | 46 | def main(self): 47 | """Main.""" 48 | path = self.env.get("properties_path") 49 | if not os.path.isfile(path): 50 | raise ProcessorError("%s doesn't exist!" % path) 51 | with open(path, "rb") as f: 52 | data = f.read() 53 | split_data = shlex.split(data) 54 | # Version is defined in the files 55 | version = split_data[split_data.index("Pkg.Revision") + 2] 56 | self.env["version"] = version.split()[-1] 57 | # Release is just based on filename 58 | self.env["release_num"] = os.path.basename(os.path.dirname(path)).split("-")[-1] 59 | 60 | 61 | if __name__ == "__main__": 62 | PROCESSOR = AndroidNDKVersioner() 63 | PROCESSOR.execute_shell() 64 | -------------------------------------------------------------------------------- /EclipseTemurin/EclipseTemurin.download.recipe.yaml: -------------------------------------------------------------------------------- 1 | Description: | 2 | This is a slight rewrite of grahampugh-recipes/EclipseTemurin recipes. 3 | Downloads the current release version of Eclipse Temurin 8. This is based from the tar version rather than the signed pkg version, so that the true version number can be obtained. 4 | 5 | FEATURE_VERSION may be any valid whole number, e.g. 8, 11, 16, 17. See https://api.adoptium.net/v3/info/available_releases for available feature versions. 6 | 7 | RELEASE_TYPE can be 'ga' (general availablility) or 'ea' (early access). 8 | 9 | OS may be 'mac' or others. 10 | 11 | DOWNLOAD_ARCH may be 'x64' or 'aarch64' for macOS-specific builds. Note that if you change this, you MUST also change the supported_architectures in the pkginfo dictionary to match what Munki expects: https://github.com/munki/munki/wiki/Pkginfo-Files#supported_architectures 12 | 13 | IMAGE_TYPE may be 'jdk', 'jre', 'testimage', 'debugimage' or 'staticlibs'. 14 | 15 | JVM_IMPLEMENTATION may be "hotspot", "openj9" or "dragonwell". 16 | 17 | HEAP_SIZE may be 'normal' or 'large'. 18 | 19 | VENDOR may be 'adoptopenjdk', 'openjdk', 'adoptium', 'alibaba', 'ibm'. 20 | 21 | Note that not all options are available for all vendors, and not all listed vendors may be currently available. 22 | Identifier: com.github.nmcspadden.recipes.download.EclipseTemurin 23 | MinimumVersion: "2.3" 24 | 25 | Input: 26 | NAME: EclipseTemurin 27 | FEATURE_VERSION: "11" 28 | OS: mac 29 | RELEASE_TYPE: ga 30 | DOWNLOAD_ARCH: x64 31 | IMAGE_TYPE: jdk 32 | JVM_IMPLEMENTATION: hotspot 33 | HEAP_SIZE: normal 34 | VENDOR: adoptium 35 | 36 | Process: 37 | - Processor: URLDownloader 38 | Arguments: 39 | url: "https://api.adoptium.net/v3/installer/latest/%FEATURE_VERSION%/%RELEASE_TYPE%/%OS%/%DOWNLOAD_ARCH%/%IMAGE_TYPE%/%JVM_IMPLEMENTATION%/%HEAP_SIZE%/%VENDOR%" 40 | filename: "%VENDOR%-%FEATURE_VERSION%_%IMAGE_TYPE%_%OS%_%DOWNLOAD_ARCH%_%JVM_IMPLEMENTATION%.pkg" 41 | 42 | - Processor: EndOfCheckPhase 43 | 44 | - Processor: CodeSignatureVerifier 45 | Arguments: 46 | expected_authority_names: 47 | - "Developer ID Installer: Eclipse Foundation, Inc. (JCDTMS22B4)" 48 | - Developer ID Certification Authority 49 | - Apple Root CA 50 | input_path: "%pathname%" 51 | -------------------------------------------------------------------------------- /LegacyRecipes/GoogleEarthPro/GoogleEarthPro.download.recipe: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Description 6 | Downloads latest Google Earth Pro disk image. 7 | Identifier 8 | com.github.nmcspadden-recipes.download.google-earth-pro 9 | Input 10 | 11 | NAME 12 | GoogleEarthPro 13 | DOWNLOAD_URL 14 | https://dl.google.com/earth/client/advanced/current/GoogleEarthProMac-Intel.dmg 15 | 16 | MinimumVersion 17 | 1.1 18 | Process 19 | 20 | 21 | Processor 22 | DeprecationWarning 23 | Arguments 24 | 25 | warning_message 26 | This recipe is no longer supported. Please remove it from your recipe list. 27 | 28 | 29 | 30 | Processor 31 | URLDownloader 32 | Arguments 33 | 34 | url 35 | %DOWNLOAD_URL% 36 | filename 37 | %NAME%.dmg 38 | 39 | 40 | 41 | Processor 42 | EndOfCheckPhase 43 | 44 | 45 | Processor 46 | CodeSignatureVerifier 47 | Arguments 48 | 49 | input_path 50 | %pathname%/*.pkg 51 | expected_authority_names 52 | 53 | Developer ID Installer: Google LLC (EQHXZ8M8AV) 54 | Developer ID Certification Authority 55 | Apple Root CA 56 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /LegacyRecipes/GoogleEarthPro/com.github.autopkg.nmcspadden-recipes.googleearthpro.mobileconfig: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PayloadContent 6 | 7 | 8 | PayloadContent 9 | 10 | com.google.GoogleEarthPro 11 | 12 | Set-Once 13 | 14 | 15 | mcx_data_timestamp 16 | 2015-02-06T21:16:14Z 17 | mcx_preference_settings 18 | 19 | ActivationInfo 20 | AAAAAAABABAAAAABAAAAARAAAAEAAAABAAAAAQAEACQAUgiAUQRsBLWQKntBcRgf4V9stsf7PCyVR+koFwIOaK/jaTlf1y/w 21 | Passport 22 | GEPFREE 23 | Username 24 | username 25 | osName 26 | Mac OS X 27 | 28 | 29 | 30 | 31 | 32 | PayloadEnabled 33 | 34 | PayloadIdentifier 35 | MCXToProfile.87da2811-c40f-4447-9255-a636fb3995ac.alacarte.customsettings.7c18e942-b0ea-417d-9d82-135b4b8e4db1 36 | PayloadType 37 | com.apple.ManagedClient.preferences 38 | PayloadUUID 39 | 7c18e942-b0ea-417d-9d82-135b4b8e4db1 40 | PayloadVersion 41 | 1 42 | 43 | 44 | PayloadDescription 45 | Included custom settings: 46 | com.google.GoogleEarthPro 47 | 48 | Git revision: 1d30395cd4 49 | PayloadDisplayName 50 | Google Earth Pro 51 | PayloadIdentifier 52 | com.github.nmcspadden-recipes.googleearthpro 53 | PayloadOrganization 54 | 55 | PayloadRemovalDisallowed 56 | 57 | PayloadScope 58 | System 59 | PayloadType 60 | Configuration 61 | PayloadUUID 62 | 87da2811-c40f-4447-9255-a636fb3995ac 63 | PayloadVersion 64 | 1 65 | 66 | 67 | -------------------------------------------------------------------------------- /AdoptOpenJDK/AdoptOpenJDK11.munki.recipe: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Copyright 6 | Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved 7 | Description 8 | Downloads the current release version of AdoptOpenJDK 11 and imports into Munki. 9 | Identifier 10 | com.github.facebook.munki.AdoptOpenJDK11 11 | Input 12 | 13 | NAME 14 | AdoptOpenJDK11 15 | MUNKI_REPO_SUBDIR 16 | apps/openjdk 17 | pkginfo 18 | 19 | catalogs 20 | 21 | testing 22 | 23 | category 24 | Developer Tools 25 | description 26 | Adopt Open JDK 11 27 | developer 28 | AdoptOpenJDK 29 | display_name 30 | Adopt OpenJDK 11 31 | name 32 | %NAME% 33 | unattended_install 34 | 35 | 36 | 37 | MinimumVersion 38 | 1.4.1 39 | ParentRecipe 40 | com.github.nmcspadden.download.AdoptOpenJDK11 41 | Process 42 | 43 | 44 | Arguments 45 | 46 | pkg_path 47 | %pathname% 48 | repo_subdirectory 49 | %MUNKI_REPO_SUBDIR% 50 | 51 | Processor 52 | MunkiImporter 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # recipes 2 | 3 | My own collection of recipes for Autopkg. 4 | 5 | **NOTE: Several recipes are deprecated are left purely for historical reasons.** 6 | 7 | ## AppStoreApp Recipe 8 | 9 | This recipe is designed to include an App Store app in Autopkg checks. It optionally 10 | checks your local downloaded copy for updates against the App Store, and 11 | then either directly imports into Munki or packages it up (which can then be imported into Munki or any other package-based deployment system). 12 | 13 | **You must override this recipe for each App Store app you want to include. This set of recipes does nothing useful by itself!** 14 | 15 | How to use it with Keynote, as an example: 16 | 17 | 1. `autopkg make-override AppStoreApp.munki -n MAS-Keynote.munki` 18 | 19 | 2. Edit the MAS-Keynote.munki recipe. Replace the NAME variable with 20 | "Keynote". It will automatically assume that your app is in 21 | /Applications, and set the PATH to be /Applications/Keynote.app. The 22 | NAME should always correspond to whatever comes before the ".app" in 23 | the app name. This should always point to a locally downloaded copy 24 | of the App Store App. 25 | 26 | 3. `autopkg run -vvvv MAS-Keynote.munki` 27 | 28 | What actually happens when you run the Munki recipe: 29 | 30 | 1. Copy the app from /Applications into the cache directory. 31 | 32 | 2. Create a DMG for Munki. 33 | 34 | 3. Create the Munki pkginfo. 35 | 36 | 4. Import into Munki if the local app is newer. 37 | 38 | 5. Delete the copy of the app from the cache directory. 39 | 40 | The .pkg recipe functions similarly: 41 | 42 | 1. Determine the version of the local app. 43 | 44 | 2. Build a pkg from the local app if there is not one already built for that version. 45 | 46 | To check multiple apps, create one new override for each app you want to 47 | check: 48 | `autopkg make-override AppStoreApp.munki -n MAS-iPhoto.munki autopkg make-override AppStoreApp.munki -n MAS-GarageBand.munki autopkg make-override AppStoreApp.munki -n MAS-iMovie.munki` 49 | 50 | **Important Note:** This recipe does *not* download updates for AppStore 51 | apps. It only checks to see if your copy is up to date or not, and then 52 | notifies you via standard output. The admin is still responsible for 53 | downloading the update from the App Store, either automatically (via the 54 | System Preferences option) or manually (via the App Store). 55 | -------------------------------------------------------------------------------- /AdoptOpenJDK/AdoptOpenJDK11.download.recipe: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Copyright 6 | Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved 7 | Description 8 | Downloads the current release version of AdoptOpenJDK 11. JVM defaults to "hotspot", or you can use "openj9". JDK_VERSION is which JDK OpenJDK version you wish to use, defaults to 11. 9 | Identifier 10 | com.github.nmcspadden.download.AdoptOpenJDK11 11 | Input 12 | 13 | NAME 14 | AdoptOpenJDK11 15 | JVM_TYPE 16 | hotspot 17 | JDK_TYPE 18 | jdk 19 | JDK_VERSION 20 | 11 21 | BINARY_TYPE 22 | pkg 23 | RELEASE 24 | latest 25 | 26 | MinimumVersion 27 | 1.4.1 28 | Process 29 | 30 | 31 | Arguments 32 | 33 | jdk_version 34 | %JDK_VERSION% 35 | jvm_type 36 | %JVM_TYPE% 37 | jdk_type 38 | %JDK_TYPE% 39 | binary_type 40 | %BINARY_TYPE% 41 | release 42 | %RELEASE% 43 | 44 | Processor 45 | AdoptOpenJDKURLProvider 46 | 47 | 48 | Processor 49 | URLDownloader 50 | 51 | 52 | Processor 53 | EndOfCheckPhase 54 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /Xcode/XcodeBuildNumberEmitter.py: -------------------------------------------------------------------------------- 1 | #!/usr/local/autopkg/python 2 | # 3 | # Copyright (c) Facebook, Inc. and its affiliates. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | """ Emit Xcode Build Number to disk """ 18 | 19 | import os.path 20 | 21 | from autopkglib import Processor 22 | 23 | 24 | __all__ = ["XcodeBuildNumberEmitter"] 25 | 26 | 27 | class XcodeBuildNumberEmitter(Processor): 28 | """Emit file containing Xcode Build Number""" 29 | 30 | description = __doc__ 31 | input_variables = { 32 | "dont_skip": { 33 | "description": ( 34 | "If this evaluates as truthy, do not skip this step." 35 | ), 36 | "default": False, 37 | "required": False 38 | }, 39 | "build_version": { 40 | "description": "The build version number for this Xcode Release", 41 | "required": True 42 | }, 43 | "output_filepath": { 44 | "description": "Path to which xcode build number is emitted.", 45 | "required": True 46 | } 47 | } 48 | output_variables = { 49 | "derived_filename": { 50 | "description": "The derived filename to emit." 51 | } 52 | } 53 | 54 | 55 | def main(self): 56 | """Main.""" 57 | if not self.env["dont_skip"]: 58 | self.output("dont_skip is false, so skipping this Processor.") 59 | return 60 | 61 | build_number = self.env["build_version"] 62 | destination = os.path.expandvars(self.env["output_filepath"]) 63 | 64 | with open(destination, "w") as f: 65 | f.write(build_number) 66 | self.output( 67 | f"Xcode build number ({build_number}) written to disk at {destination}" 68 | ) 69 | 70 | 71 | if __name__ == "__main__": 72 | PROCESSOR = XcodeBuildNumberEmitter() 73 | PROCESSOR.execute_shell() 74 | -------------------------------------------------------------------------------- /DbVisualizer/DbVisualizer.munki.recipe: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Copyright 6 | Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved 7 | Description 8 | Downloads and makes a DMG of the latest version of DbVisualizer, and imports into Munki. 9 | Identifier 10 | com.github.nmcspadden.munki.dbvisualizer 11 | Input 12 | 13 | MUNKI_REPO_SUBDIR 14 | apps/DbVis 15 | NAME 16 | DbVisualizer 17 | VERSION 18 | 11 19 | pkginfo 20 | 21 | catalogs 22 | 23 | testing 24 | 25 | category 26 | Database Tools 27 | description 28 | DbVisualizer is the universal database tool for developers, DBAs and analysts. It is the perfect solution since the same tool can be used on all major operating systems accessing a wide range of databases. 29 | developer 30 | DbVis Software 31 | display_name 32 | DbVisualizer 33 | requires 34 | 35 | OracleJava7 36 | 37 | unattended_install 38 | 39 | 40 | 41 | MinimumVersion 42 | 0.5.0 43 | ParentRecipe 44 | com.github.nmcspadden.dmg.dbvisualizer 45 | Process 46 | 47 | 48 | Arguments 49 | 50 | additional_pkginfo 51 | 52 | version 53 | %version% 54 | 55 | 56 | Processor 57 | MunkiPkginfoMerger 58 | 59 | 60 | Arguments 61 | 62 | pkg_path 63 | %RECIPE_CACHE_DIR%/%NAME%-%version%.dmg 64 | repo_subdirectory 65 | %MUNKI_REPO_SUBDIR% 66 | 67 | Processor 68 | MunkiImporter 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /Xcode/XcodeXIPUnpacker.py: -------------------------------------------------------------------------------- 1 | #!/usr/local/autopkg/python 2 | # 3 | # Copyright (c) Facebook, Inc. and its affiliates. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | """Unpack an Xcode XIP.""" 18 | 19 | import os 20 | import subprocess 21 | 22 | from autopkglib import Processor, ProcessorError 23 | 24 | 25 | __all__ = ["XcodeXIPUnpacker"] 26 | 27 | 28 | class XcodeXIPUnpacker(Processor): 29 | """Unpack a XIP file from Apple.""" 30 | 31 | description = __doc__ 32 | input_variables = { 33 | "PKG": { 34 | "description": "Path to an Xcode .xip file.", 35 | "required": True 36 | }, 37 | "output_path": { 38 | "description": ( 39 | "Path to unpack the contents. Defaults to " 40 | "%RECIPE_CACHE_DIR%/Xcode_unpack." 41 | ), 42 | "required": False 43 | } 44 | } 45 | output_variables = {} 46 | 47 | 48 | def main(self): 49 | """Main.""" 50 | xip_path = self.env["PKG"] 51 | if self.env.get("output_path"): 52 | output = self.env["output_path"] 53 | else: 54 | output = os.path.join( 55 | self.env["RECIPE_CACHE_DIR"], "Xcode_unpack" 56 | ) 57 | if not os.path.isdir(output): 58 | os.makedirs(output) 59 | 60 | self.output( 61 | "Extracting xip archive, please be patient, this could take a long time..." 62 | ) 63 | os.chdir(output) 64 | cmd = ["/usr/bin/xip", "--expand", xip_path] 65 | proc = subprocess.Popen( 66 | cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE 67 | ) 68 | (out, err) = proc.communicate() 69 | if err: 70 | raise ProcessorError(err) 71 | self.output("Finished xip unpack.") 72 | 73 | 74 | if __name__ == "__main__": 75 | PROCESSOR = XcodeXIPUnpacker() 76 | PROCESSOR.execute_shell() 77 | -------------------------------------------------------------------------------- /LegacyRecipes/MinecraftEdu/MinecraftEdu.munki.recipe: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Description 6 | Packages the latest MinecraftEdu release, and imports it into Munki. You MUST override the username and password variables or the recipe will fail. If you do not want to put your password in plaintext, you can use a hash of it generated here: http://minecraftedu.com/api/api.php?action=gethash&username=yourusername&password=yourpassword 7 | Identifier 8 | com.github.nmcspadden.munki.MinecraftEdu 9 | Input 10 | 11 | MUNKI_REPO_SUBDIR 12 | apps 13 | NAME 14 | MinecraftEDUInstaller 15 | pkginfo 16 | 17 | catalogs 18 | 19 | testing 20 | 21 | description 22 | MinecraftEDU with ServerTool installed. 23 | display_name 24 | Minecraft EDU 25 | minimum_os_version 26 | 10.6.8 27 | name 28 | %NAME% 29 | requires 30 | 31 | Java6_Apple 32 | 33 | preinstall_script 34 | #!/bin/bash 35 | 36 | mcpath="/Library/Application Support/minecraftedu" 37 | 38 | if [[ -e "$mcpath" ]] 39 | then 40 | /bin/rm -rf "$mcpath" 41 | fi 42 | 43 | unattended_install 44 | 45 | 46 | 47 | ParentRecipe 48 | com.github.nmcspadden.pkg.MinecraftEdu 49 | Process 50 | 51 | 52 | Processor 53 | DeprecationWarning 54 | Arguments 55 | 56 | warning_message 57 | This recipe is no longer supported. Please remove it from your recipe list. 58 | 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /android_sdk/android_sdk.minimal.munki.recipe: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Copyright 6 | Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved 7 | Description 8 | Downloads a minimal set of Android SDK tools, creates a PKG out of it, and imports into Munki. 9 | Identifier 10 | com.github.nmcspadden.munki.android_sdk.minimal 11 | Input 12 | 13 | DESTINATION_PATH 14 | /opt/android_sdk 15 | MUNKI_REPO_SUBDIR 16 | apps/%NAME% 17 | NAME 18 | android_sdk 19 | pkginfo 20 | 21 | catalogs 22 | 23 | testing 24 | 25 | category 26 | Developer Tools 27 | description 28 | Android SDK. 29 | developer 30 | Google 31 | display_name 32 | Android SDK 33 | unattended_install 34 | 35 | 36 | 37 | MinimumVersion 38 | 0.2.0 39 | ParentRecipe 40 | com.github.nmcspadden.pkg.android_sdk.minimal 41 | Process 42 | 43 | 44 | Processor 45 | DeprecationWarning 46 | Arguments 47 | 48 | warning_message 49 | This recipe will soon be removed. Please remove it from your list of recipes. 50 | 51 | 52 | 53 | Arguments 54 | 55 | additional_pkginfo 56 | 57 | name 58 | %NAME% 59 | version 60 | %version% 61 | 62 | 63 | Processor 64 | MunkiPkginfoMerger 65 | 66 | 67 | Arguments 68 | 69 | pkg_path 70 | %pkg_path% 71 | repo_subdirectory 72 | %MUNKI_REPO_SUBDIR% 73 | 74 | Processor 75 | MunkiImporter 76 | 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /Chef_Processors/ChefAttributeList.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) Facebook, Inc. and its affiliates. 5 | # 6 | # This source code is licensed under the BSD-style license found in the 7 | # LICENSE file in the root directory of this source tree.# 8 | """See docstring for ChefAttributeList class.""" 9 | 10 | from __future__ import absolute_import 11 | 12 | import os.path 13 | 14 | from autopkglib import Processor 15 | 16 | __all__ = ["ChefAttributeList"] 17 | 18 | 19 | class ChefAttributeList(Processor): 20 | """Class for Attribute List.""" 21 | 22 | description = ( 23 | "Produces a Chef attribute variable for a list of items. " 24 | "The attribute prefixes correspond to node settings - i.e. " 25 | "default[category][prefix][attribute]." 26 | ) 27 | input_variables = { 28 | "attribute_version": { 29 | "required": True, 30 | "description": "Version of Munki this applies to.", 31 | }, 32 | "attribute": {"required": True, "description": "Name of attribute."}, 33 | "value": { 34 | "required": True, 35 | "description": ( 36 | "Single string containing list of items, separated by commas." 37 | ), 38 | }, 39 | "path_prefix": { 40 | "required": False, 41 | "description": "Path to prepend to each found item.", 42 | "default": "", 43 | }, 44 | } 45 | output_variables = { 46 | "chef_block": {"description": "Chef attribute block."}, 47 | "attribute_variable": {"description": "Full name of variable."}, 48 | } 49 | 50 | __doc__ = description 51 | 52 | def main(self): 53 | """Main.""" 54 | att_prefix = "munki['%s']['%s']" % ( 55 | self.env["attribute_version"], 56 | self.env["attribute"], 57 | ) 58 | self.env["chef_block"] = att_prefix + " = [\n" 59 | for value in self.env["value"].split(","): 60 | # attribute = '%s = [\n' 61 | # print "Value: %s" % value 62 | self.env["chef_block"] += " '%s',\n" % str( 63 | os.path.join(self.env["path_prefix"], value) 64 | ) 65 | self.env["chef_block"] += "]\n" 66 | self.output("Chef block: %s" % self.env["chef_block"]) 67 | self.env["attribute_variable"] = att_prefix.replace("default", "node") 68 | 69 | 70 | if __name__ == "__main__": 71 | PROCESSOR = ChefAttributeList() 72 | PROCESSOR.execute_shell() 73 | -------------------------------------------------------------------------------- /android_ndk/android_ndk.dmg.recipe: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Copyright 6 | Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved 7 | Description 8 | Creates a disk image containing the Android NDK. 9 | Identifier 10 | com.github.nmcspadden.dmg.android_ndk 11 | Input 12 | 13 | NAME 14 | android_ndk 15 | 16 | MinimumVersion 17 | 0.2.0 18 | ParentRecipe 19 | com.github.nmcspadden.download.android_ndk 20 | Process 21 | 22 | 23 | Arguments 24 | 25 | pkgdirs 26 | 27 | opt 28 | 0755 29 | opt/android_ndk 30 | 0755 31 | 32 | pkgroot 33 | %RECIPE_CACHE_DIR%/%NAME% 34 | 35 | Processor 36 | PkgRootCreator 37 | 38 | 39 | Arguments 40 | 41 | destination_path 42 | %pkgroot%/opt/%NAME% 43 | purge_destination 44 | 45 | 46 | Processor 47 | Unarchiver 48 | 49 | 50 | Arguments 51 | 52 | pattern 53 | %pkgroot%/opt/%NAME%/android-ndk-*/source.properties 54 | 55 | Processor 56 | FileFinder 57 | 58 | 59 | Arguments 60 | 61 | properties_path 62 | %found_filename% 63 | 64 | Processor 65 | AndroidNDKVersioner 66 | 67 | 68 | Arguments 69 | 70 | dmg_path 71 | %RECIPE_CACHE_DIR%/%NAME%-%release_num%.dmg 72 | dmg_root 73 | %pkgroot% 74 | dmg_zlib_level 75 | 9 76 | 77 | Processor 78 | DmgCreator 79 | 80 | 81 | Arguments 82 | 83 | path_list 84 | 85 | %RECIPE_CACHE_DIR%/%NAME% 86 | 87 | 88 | Processor 89 | PathDeleter 90 | 91 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /Acrolinx/AcrolinxURLProvider.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # Copyright (c) Facebook, Inc. and its affiliates. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | """See docstring for AcrolinxURLProvider class""" 17 | 18 | from __future__ import absolute_import, division, print_function, unicode_literals 19 | 20 | from autopkglib import ProcessorError 21 | from autopkglib.URLGetter import URLGetter 22 | 23 | 24 | __all__ = ["AcrolinxURLProvider"] 25 | 26 | URL = "https://{}:{}@download.acrolinx.com:1443/api/deliverablePackages/575b1d0d401ae30b00e90f40/download/latest?preserve_credentials=true&proxy=true" 27 | 28 | 29 | class AcrolinxURLProvider(URLGetter): 30 | """Provides a download URL for Acrolinx.""" 31 | 32 | description = __doc__ 33 | input_variables = { 34 | "username": {"required": True, "description": "Username for authentication."}, 35 | "password": {"required": True, "description": "Password for authentication"}, 36 | } 37 | output_variables = {"url": {"description": "Download URL for Acrolinx."}} 38 | 39 | def main(self): 40 | """Find the download URL""" 41 | username = self.env["username"] 42 | password = self.env["password"] 43 | url = URL.format(username, password) 44 | # Fetch the API data 45 | curl_cmd = self.prepare_curl_cmd() 46 | curl_cmd.extend(["--head", url]) 47 | raw_headers = self.download_with_curl(curl_cmd) 48 | header = self.parse_headers(raw_headers) 49 | # Use semantic versioning for the version string, although historically this 50 | # hasn't been anything particularly problematic 51 | acrolinx_url = header.get("http_redirected") 52 | if not acrolinx_url: 53 | self.output(f"Header: {header}") 54 | raise ProcessorError( 55 | "Header did not contain an 'http_redirected' " 56 | "value containing the expected Acrolinx URL. Check your " 57 | "username and password." 58 | ) 59 | self.output(f"Found URL: {acrolinx_url}") 60 | self.env["url"] = acrolinx_url 61 | 62 | 63 | if __name__ == "__main__": 64 | PROCESSOR = AcrolinxURLProvider() 65 | PROCESSOR.execute_shell() 66 | -------------------------------------------------------------------------------- /SQLDeveloper/SQLDeveloper.dmg.recipe: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Copyright 6 | Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved 7 | Description 8 | Creates a DMG for SQLDeveloper. You must provide your own .zip download using the -p argument. 9 | Identifier 10 | com.github.nmcspadden.dmg.sqldeveloper 11 | Input 12 | 13 | NAME 14 | SQLDeveloper 15 | 16 | MinimumVersion 17 | 0.5.1 18 | Process 19 | 20 | 21 | Comment 22 | Requires manually providing SQLDeveloper .zip download. 23 | Processor 24 | PackageRequired 25 | 26 | 27 | Arguments 28 | 29 | pkgdirs 30 | 31 | pkgroot 32 | %RECIPE_CACHE_DIR%/%NAME% 33 | 34 | Processor 35 | PkgRootCreator 36 | 37 | 38 | Arguments 39 | 40 | archive_path 41 | %PKG% 42 | destination_path 43 | %pkgroot% 44 | purge_destination 45 | 46 | 47 | Processor 48 | Unarchiver 49 | 50 | 51 | Arguments 52 | 53 | input_path 54 | %pkgroot%/SQLDeveloper.app 55 | requirement 56 | identifier "com.oracle.SQLDeveloper" and anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = VB5E2TV963 57 | 58 | Processor 59 | CodeSignatureVerifier 60 | 61 | 62 | Arguments 63 | 64 | app_path 65 | %pkgroot%/SQLDeveloper.app 66 | 67 | Processor 68 | SQLDeveloperVersioner 69 | 70 | 71 | Arguments 72 | 73 | dmg_path 74 | %RECIPE_CACHE_DIR%/%NAME%-%version%.dmg 75 | dmg_root 76 | %pkgroot% 77 | 78 | Processor 79 | DmgCreator 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /Chef_Processors/ChefAttributeHash.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) Facebook, Inc. and its affiliates. 5 | # 6 | # This source code is licensed under the BSD-style license found in the 7 | # LICENSE file in the root directory of this source tree. 8 | # 9 | """See docstring for ChefAttributeHash class.""" 10 | 11 | from __future__ import absolute_import 12 | 13 | from autopkglib import Processor 14 | 15 | __all__ = ["ChefAttributeHash"] 16 | 17 | 18 | class ChefAttributeHash(Processor): 19 | description = ( 20 | "Produces a Chef attribute variable for a hash of items. " 21 | "The attribute prefixes correspond to node settings - i.e. " 22 | "default[category][prefix][attribute]." 23 | ) 24 | input_variables = { 25 | "attribute_category": { 26 | "required": True, 27 | "description": "Leading category for each attribute.", 28 | }, 29 | "attribute_prefix": { 30 | "required": True, 31 | "description": "Prefix to each attribute.", 32 | }, 33 | "attribute": {"required": True, "description": "Name of attribute."}, 34 | "value": {"required": True, "description": ("Dictionary of keys and values.")}, 35 | "in_array": { 36 | "required": False, 37 | "description": ( 38 | "Is this hash inside an array? If yes, a comma is added to the end" 39 | ), 40 | }, 41 | } 42 | output_variables = { 43 | "chef_block": {"description": "Chef attribute block."}, 44 | "attribute_variable": {"description": "Full name of variable."}, 45 | } 46 | 47 | __doc__ = description 48 | 49 | def main(self): 50 | att_prefix = "default['%s']['%s']['%s']" % ( 51 | self.env["attribute_category"], 52 | self.env["attribute_prefix"], 53 | self.env["attribute"], 54 | ) 55 | self.env["chef_block"] = att_prefix + " = {\n" 56 | for value in sorted(self.env["value"].keys()): 57 | self.env["chef_block"] += "\t%s => %s,\n" % ( 58 | value, 59 | self.env["value"][value], 60 | ) 61 | self.env["chef_block"] += "}" 62 | # Remove the trailing comma on the last item 63 | self.env["chef_block"] = self.env["chef_block"].replace(",\n}", "\n}") 64 | if self.env.get("in_array"): 65 | # if this hash is in a list of hashes, add a comma at the end 66 | self.env["chef_block"] += "," 67 | self.env["chef_block"] += "\n" 68 | self.output("Chef block: %s" % self.env["chef_block"]) 69 | self.env["attribute_variable"] = att_prefix.replace("default", "node") 70 | 71 | 72 | if __name__ == "__main__": 73 | PROCESSOR = ChefAttributeHash() 74 | PROCESSOR.execute_shell() 75 | -------------------------------------------------------------------------------- /DbVisualizer/DbVisualizer.pkg.recipe: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Copyright 6 | Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved 7 | Description 8 | Downloads the current release version of DbVisualizer and builds a package. 9 | Identifier 10 | com.github.nmcspadden.pkg.dbvisualizer 11 | Input 12 | 13 | NAME 14 | DbVisualizer 15 | 16 | MinimumVersion 17 | 0.2.0 18 | ParentRecipe 19 | com.github.nmcspadden.download.dbvisualizer 20 | Process 21 | 22 | 23 | Arguments 24 | 25 | pkgdirs 26 | 27 | Applications 28 | 0775 29 | 30 | pkgroot 31 | %RECIPE_CACHE_DIR%/%NAME% 32 | 33 | Processor 34 | PkgRootCreator 35 | 36 | 37 | Arguments 38 | 39 | archive_path 40 | %pathname% 41 | destination_path 42 | %pkgroot%/Applications 43 | purge_destination 44 | 45 | 46 | Processor 47 | Unarchiver 48 | 49 | 50 | Arguments 51 | 52 | input_plist_path 53 | %pkgroot%/Applications/DbVisualizer.app/Contents/Info.plist 54 | plist_version_key 55 | CFBundleShortVersionString 56 | 57 | Comment 58 | Get version from the app 59 | Processor 60 | Versioner 61 | 62 | 63 | Arguments 64 | 65 | pkg_request 66 | 67 | chown 68 | 69 | 70 | group 71 | admin 72 | path 73 | Applications 74 | user 75 | root 76 | 77 | 78 | id 79 | com.dbvis.DbVisualizer 80 | options 81 | purge_ds_store 82 | pkgname 83 | %NAME%-%version% 84 | version 85 | %version% 86 | 87 | 88 | Processor 89 | PkgCreator 90 | 91 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /android_sdk/AndroidSDKVersioner.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) Facebook, Inc. and its affiliates. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | 18 | """See docstring for AndroidSDKVersioner class.""" 19 | 20 | # Disabling warnings for env members and imports that only affect recipe- 21 | # specific processors. 22 | # pylint: disable=e1101,f0401 23 | 24 | from __future__ import absolute_import 25 | 26 | import urllib2 27 | import xml.etree.cElementTree as ET 28 | 29 | from autopkglib import Processor, ProcessorError 30 | 31 | __all__ = ["AndroidSDKVersioner"] 32 | 33 | 34 | class AndroidSDKVersioner(Processor): 35 | # pylint: disable=missing-docstring 36 | description = "Parse the XML file for the latest version of the SDK tools." 37 | input_variables = { 38 | "xml_file": {"required": True, "description": "Path or URL to XML file."} 39 | } 40 | output_variables = { 41 | "version": {"description": "Combined version of the SDK tools."} 42 | } 43 | 44 | __doc__ = description 45 | 46 | def main(self): 47 | if "http" in self.env["xml_file"]: 48 | try: 49 | tree = ET.ElementTree(file=urllib2.urlopen(self.env["xml_file"])) 50 | except urllib2.URLError as err: 51 | raise ProcessorError(err) 52 | else: 53 | try: 54 | tree = ET.ElementTree(file=self.env["xml_file"]) 55 | except IOError as err: 56 | raise ProcessorError(err) 57 | root = tree.getroot() 58 | schema = root.tag.split("}")[0] + "}" 59 | match = root.findall("%s%s" % (schema, "tool")) 60 | revision = "%srevision" % schema 61 | result = "" 62 | try: 63 | major = match[-1].find(revision).find("%smajor" % schema).text 64 | minor = match[-1].find(revision).find("%sminor" % schema).text 65 | micro = match[-1].find(revision).find("%smicro" % schema).text 66 | except IndexError: 67 | raise ProcessorError("Version not found!") 68 | result = "%s.%s.%s" % (major, minor, micro) 69 | self.env["version"] = result 70 | self.output("Version: %s" % self.env["version"]) 71 | 72 | 73 | if __name__ == "__main__": 74 | PROCESSOR = AndroidSDKVersioner() 75 | PROCESSOR.execute_shell() 76 | -------------------------------------------------------------------------------- /Xcode/XcodeVersionEmitter.py: -------------------------------------------------------------------------------- 1 | #!/usr/local/autopkg/python 2 | # 3 | # Copyright (c) Facebook, Inc. and its affiliates. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | """Get all Version information from Xcode.""" 18 | 19 | from os.path import basename, expandvars, splitext 20 | 21 | from urllib.parse import urlsplit 22 | 23 | from autopkglib import Processor 24 | 25 | 26 | __all__ = ["XcodeVersionEmitter"] 27 | 28 | 29 | class XcodeVersionEmitter(Processor): 30 | """Output a version number based on the URL. Skipped by default.""" 31 | 32 | description = __doc__ 33 | input_variables = { 34 | "dont_skip": { 35 | "description": ( 36 | "If this evaluates as truthy, do not skip this step." 37 | ), 38 | "default": False, 39 | "required": False 40 | }, 41 | "url": { 42 | "description": "URL to parse the version from.", 43 | "required": True 44 | }, 45 | "output_filepath": { 46 | "description": "Path to which xcode version tag is emitted.", 47 | "required": True 48 | } 49 | } 50 | output_variables = { 51 | "derived_filename": { 52 | "description": "The derived filename to emit." 53 | } 54 | } 55 | 56 | 57 | def main(self): 58 | """Main.""" 59 | if not self.env["dont_skip"]: 60 | self.output("dont_skip is false, so skipping this Processor.") 61 | return 62 | url = self.env["url"] 63 | url_split_object = urlsplit(url) 64 | # "https://download.developer.apple.com/Developer_Tools/Xcode_10.2.1/Xcode_10.2.1.xip" # noqa 65 | # "https://developer.apple.com//services-account/download?path=/Developer_Tools/Xcode_11_Beta_2/Xcode_11_Beta_2.xip" # noqa 66 | filename = splitext(basename(url_split_object.path))[0].lower() 67 | self.output(f"Derived filename: {filename}") 68 | self.env["derived_filename"] = filename 69 | 70 | destination = expandvars(self.env["output_filepath"]) 71 | with open(destination, "w") as f: 72 | f.write(filename) 73 | self.output( 74 | f"Derived filename ({filename}) written to disk at {destination}") 75 | 76 | 77 | if __name__ == "__main__": 78 | PROCESSOR = XcodeVersionEmitter() 79 | PROCESSOR.execute_shell() 80 | -------------------------------------------------------------------------------- /SQLDeveloper/SQLDeveloperVersioner.py: -------------------------------------------------------------------------------- 1 | #!/usr/local/autopkg/python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) Facebook, Inc. and its affiliates. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | 18 | """See docstring for SQLDeveloperVersioner class.""" 19 | 20 | from __future__ import absolute_import 21 | 22 | import configparser 23 | import os.path 24 | 25 | from autopkglib import Processor, ProcessorError 26 | 27 | __all__ = ["SQLDeveloperVersioner"] 28 | 29 | 30 | class SQLDeveloperVersioner(Processor): 31 | # pylint: disable=missing-docstring 32 | description = "Read the version.properties file inside the SQLDeveloper.app." 33 | input_variables = { 34 | "app_path": { 35 | "required": True, 36 | "description": "Path to app to find the version.properties file in.", 37 | } 38 | } 39 | output_variables = {"version": {"description": "Actual version of app."}} 40 | 41 | __doc__ = description 42 | 43 | def main(self): 44 | # Unsurprisingly, SQLDeveloper fails to include a useful version in 45 | # the app's Info.plist. Instead, the actual version is buried deep 46 | # inside in a file called "version.properties". Thanks, Oracle. 47 | # You know, I was a having a pretty good day up until now... 48 | 49 | # this code stolen from Oscar de Groot's answer at: 50 | # https://stackoverflow.com/questions/2819696/parsing-properties-file-in-python 51 | def add_section_header(properties_file, header_name): 52 | yield '[{}]\n'.format(header_name) 53 | for line in properties_file: 54 | yield line 55 | 56 | relative_path = ( 57 | "Contents/Resources/sqldeveloper/sqldeveloper/bin/version.properties" 58 | ) 59 | file_path = os.path.join(self.env["app_path"], relative_path) 60 | file = open(file_path, encoding="utf_8") 61 | cp = configparser.ConfigParser() 62 | try: 63 | cp.read_file(add_section_header(file, 'properties'), source=file_path) 64 | except IOError as err: 65 | raise ProcessorError(err) 66 | self.env["version"] = cp["properties"]["ver_full"] 67 | self.output("Version: %s" % self.env["version"]) 68 | 69 | 70 | if __name__ == "__main__": 71 | PROCESSOR = SQLDeveloperVersioner() 72 | PROCESSOR.execute_shell() 73 | -------------------------------------------------------------------------------- /android_ndk/android_ndk.munki.recipe: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Copyright 6 | Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved 7 | Description 8 | Takes the EXTRACTED DMG and imports into Munki. 9 | Identifier 10 | com.github.nmcspadden.munki.android_ndk 11 | Input 12 | 13 | DESTINATION_PATH 14 | /opt/android_ndk 15 | MUNKI_REPO_SUBDIR 16 | apps/%NAME% 17 | NAME 18 | android_ndk 19 | pkginfo 20 | 21 | catalogs 22 | 23 | testing 24 | 25 | category 26 | Developer Tools 27 | description 28 | Android NDK. Be sure to set your ENV variable for ANDROID_NDK_REPOSITORY to /opt/android_ndk/. 29 | developer 30 | Google 31 | display_name 32 | Android NDK 33 | unattended_install 34 | 35 | 36 | 37 | MinimumVersion 38 | 0.2.0 39 | ParentRecipe 40 | com.github.nmcspadden.dmg.android_ndk 41 | Process 42 | 43 | 44 | Arguments 45 | 46 | additional_pkginfo 47 | 48 | name 49 | %NAME%_%release_num% 50 | version 51 | %version% 52 | 53 | 54 | Processor 55 | MunkiPkginfoMerger 56 | 57 | 58 | Arguments 59 | 60 | installs_item_paths 61 | 62 | /opt/android_ndk/%NAME%_%release_num%/ 63 | 64 | 65 | Processor 66 | MunkiInstallsItemsCreator 67 | 68 | 69 | Arguments 70 | 71 | additional_makepkginfo_options 72 | 73 | --itemname=opt/android_ndk/android-ndk-%release_num% 74 | --destinationpath=%DESTINATION_PATH% 75 | --owner=root 76 | --group=wheel 77 | --mode=u+rwx,go+rwx 78 | 79 | pkg_path 80 | %dmg_path% 81 | repo_subdirectory 82 | %MUNKI_REPO_SUBDIR% 83 | 84 | Processor 85 | MunkiImporter 86 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /Acrolinx/Acrolinx.munki.recipe: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Copyright 6 | Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved 7 | Description 8 | Downloads the latest version of Acrolinx and imports it into Munki. 9 | Identifier 10 | com.github.nmcspadden.munki.Acrolinx 11 | Input 12 | 13 | MUNKI_REPO_SUBDIR 14 | apps/acrolinx 15 | NAME 16 | Acrolinx 17 | pkginfo 18 | 19 | catalogs 20 | 21 | testing 22 | 23 | category 24 | Productivity 25 | description 26 | Acrolinx helps you create more readable, findable, and engaging content. 27 | developer 28 | Acrolinx 29 | display_name 30 | Acrolinx 31 | name 32 | %NAME% 33 | unattended_install 34 | 35 | 36 | 37 | MinimumVersion 38 | 2.0 39 | ParentRecipe 40 | com.github.nmcspadden.download.Acrolinx 41 | Process 42 | 43 | 44 | Arguments 45 | 46 | input_plist_path 47 | %pathname%/%dmg_found_filename%/Contents/Info.plist 48 | plist_version_key 49 | CFBundleShortVersionString 50 | 51 | Processor 52 | Versioner 53 | 54 | 55 | Arguments 56 | 57 | pkg_path 58 | %pathname% 59 | repo_subdirectory 60 | %MUNKI_REPO_SUBDIR% 61 | 62 | Processor 63 | MunkiImporter 64 | 65 | 66 | Arguments 67 | 68 | warning_message 69 | This recipe is deprecated. Use https://github.com/autopkg/discentem-recipes/Acrolinx/Acrolinx.munki.recipe.yaml instead. 70 | 71 | Processor 72 | DeprecationWarning 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /Acrolinx/Acrolinx.download.recipe: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Copyright 6 | Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved 7 | Description 8 | Downloads the latest version of Acrolinx and imports it into Munki. 9 | Identifier 10 | com.github.nmcspadden.download.Acrolinx 11 | Input 12 | 13 | NAME 14 | Acrolinx 15 | AC_USERNAME 16 | username 17 | AC_PASSWORD 18 | password 19 | 20 | MinimumVersion 21 | 2.0 22 | Process 23 | 24 | 25 | Arguments 26 | 27 | username 28 | %AC_USERNAME% 29 | password 30 | %AC_PASSWORD% 31 | 32 | Processor 33 | AcrolinxURLProvider 34 | 35 | 36 | Arguments 37 | 38 | filename 39 | Acrolinx.dmg 40 | 41 | Processor 42 | URLDownloader 43 | 44 | 45 | Arguments 46 | 47 | pattern 48 | %pathname%/*.app 49 | 50 | Processor 51 | FileFinder 52 | 53 | 54 | Processor 55 | CodeSignatureVerifier 56 | Arguments 57 | 58 | input_path 59 | %pathname%/%dmg_found_filename% 60 | requirement 61 | identifier "com.acrolinx.Acrolinx" and anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = TH2ET36H76 62 | 63 | 64 | 65 | Arguments 66 | 67 | warning_message 68 | This recipe is deprecated. Use https://github.com/autopkg/discentem-recipes/Acrolinx/Acrolinx.download.recipe.yaml instead. 69 | 70 | Processor 71 | DeprecationWarning 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /android_sdk/PropertiesWriter.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) Facebook, Inc. and its affiliates. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | """See docstring for PropertiesWriter class.""" 19 | 20 | # Disabling warnings for env members and imports that only affect recipe- 21 | # specific processors. 22 | # pylint: disable=e1101,f0401 23 | 24 | from __future__ import absolute_import 25 | 26 | import ConfigParser 27 | from collections import OrderedDict 28 | 29 | from autopkglib import Processor, ProcessorError 30 | 31 | __all__ = ["PropertiesWriter"] 32 | 33 | 34 | # this code stolen from http://stackoverflow.com/a/25084055 35 | class EqualsSpaceRemover: 36 | output_file = None 37 | 38 | def __init__(self, new_output_file): 39 | self.output_file = new_output_file 40 | 41 | def write(self, what): 42 | self.output_file.write(what.replace(" = ", "=")) 43 | 44 | 45 | class PropertiesWriter(Processor): 46 | # pylint: disable=missing-docstring 47 | description = "Read the version.properties file inside the SQLDeveloper.app." 48 | input_variables = { 49 | "file_path": { 50 | "required": True, 51 | "description": "Path to source.properties file to create.", 52 | }, 53 | "properties": { 54 | "required": True, 55 | "description": "Dictionary of keys/values to write to file.", 56 | }, 57 | } 58 | output_variables = {} 59 | 60 | __doc__ = description 61 | 62 | def main(self): 63 | cp = ConfigParser.SafeConfigParser() 64 | cp.optionxform = str 65 | 66 | sort = sorted(self.env["properties"].items(), key=lambda t: t[0]) 67 | properties = OrderedDict(sort) 68 | 69 | for key, value in properties.iteritems(): 70 | cp.set("", str(key), value) 71 | # Write the file out 72 | with open(self.env["file_path"], "wb") as f: 73 | try: 74 | cp.write(EqualsSpaceRemover(f)) 75 | except IOError as err: 76 | raise ProcessorError(err) 77 | # Now delete the first line, the section header 78 | with open(self.env["file_path"], "rb") as old: 79 | lines = old.readlines() 80 | lines[0] = "# Generated by AutoPkg\n" 81 | with open(self.env["file_path"], "wb") as new: 82 | for line in lines: 83 | new.write(line) 84 | 85 | 86 | if __name__ == "__main__": 87 | PROCESSOR = PropertiesWriter() 88 | PROCESSOR.execute_shell() 89 | -------------------------------------------------------------------------------- /Shared_Processors/DirectoryList.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) Facebook, Inc. and its affiliates. 5 | # 6 | # This source code is licensed under the BSD-style license found in the 7 | # LICENSE file in the root directory of this source tree.# 8 | """See docstring for DirectoryList class.""" 9 | 10 | 11 | from __future__ import absolute_import 12 | 13 | import os 14 | from glob import glob 15 | 16 | from autopkglib import Processor, ProcessorError 17 | 18 | __all__ = ["DirectoryList"] 19 | 20 | 21 | class DirectoryList(Processor): 22 | """Returns a list of items in a subdirectory as a string, separated by 23 | commas. 24 | 25 | Does not recurse into subdirectories. 26 | """ 27 | 28 | input_variables = { 29 | "pattern": { 30 | "description": "Shell glob pattern to match files by", 31 | "required": True, 32 | }, 33 | "find_method": { 34 | "description": ( 35 | "Type of pattern to match. Currently only " 36 | 'supported type is "glob" (also the default)' 37 | ), 38 | "default": "glob", 39 | "required": False, 40 | }, 41 | "remove_extension": { 42 | "description": ("Remove the extension at the end. Default to False."), 43 | "default": False, 44 | "required": False, 45 | }, 46 | "suffix_string": { 47 | "description": ( 48 | "String to append to each found item name in dir. Defaults to ','" 49 | ), 50 | "default": ",", 51 | "required": False, 52 | }, 53 | } 54 | output_variables = {"found_filenames": {"description": "Found filename"}} 55 | 56 | description = __doc__ 57 | 58 | def globfind(self, pattern): 59 | """Returns multiple files matching a glob.""" 60 | # pylint: disable=no-self-use 61 | 62 | glob_matches = glob(pattern) 63 | 64 | if len(glob_matches) < 1: 65 | raise ProcessorError("No matching filename found") 66 | 67 | glob_matches.sort() 68 | 69 | # return glob_matches 70 | new_glob = [] 71 | for glob_item in glob_matches: 72 | new_string = os.path.basename(glob_item) 73 | if self.env["remove_extension"]: 74 | new_string = os.path.splitext(new_string)[0] 75 | new_glob.append(new_string) 76 | return new_glob 77 | 78 | def main(self): 79 | pattern = self.env.get("pattern") 80 | method = self.env.get("find_method") 81 | 82 | format_string = "%s" % self.env["suffix_string"] 83 | search_string = "{0}" 84 | if method == "glob": 85 | self.env["found_filenames"] = search_string.format( 86 | format_string.join(self.globfind(pattern)) 87 | ).strip() 88 | else: 89 | raise ProcessorError("Unsupported find_method: %s" % method) 90 | self.output("Found matches: %s" % self.env["found_filenames"]) 91 | 92 | 93 | if __name__ == "__main__": 94 | PROCESSOR = DirectoryList() 95 | PROCESSOR.execute_shell() 96 | -------------------------------------------------------------------------------- /EclipseTemurin/EclipseTemurin.munki.recipe.yaml: -------------------------------------------------------------------------------- 1 | Description: | 2 | Downloads the current release version of Eclipse Temurin and imports into Munki. This is the signed pkg version rather than the tar version, for those that require a signed package rather than accurate version number. 3 | 4 | FEATURE_VERSION may be any valid whole number, e.g. 8, 11, 16, 17. See https://api.adoptium.net/v3/info/available_releases for available feature versions. 5 | 6 | RELEASE_TYPE can be 'ga' (general availablility) or 'ea' (early access). 7 | 8 | OS may be 'mac' or others. 9 | 10 | DOWNLOAD_ARCH may be 'x64' or 'aarch64' for macOS-specific builds. Note that if you change this, you MUST also change MUNKI_ARCH to match what Munki expects: https://github.com/munki/munki/wiki/Pkginfo-Files#supported_architectures 11 | 12 | IMAGE_TYPE may be 'jdk', 'jre', 'testimage', 'debugimage' or 'staticlibs'. 13 | 14 | JVM_IMPLEMENTATION may be "hotspot", "openj9" or "dragonwell". 15 | 16 | HEAP_SIZE may be 'normal' or 'large'. 17 | 18 | VENDOR may be 'adoptopenjdk', 'openjdk', 'adoptium', 'alibaba', 'ibm'. 19 | 20 | Note that not all options are available for all vendors, and not all listed vendors may be currently available. 21 | Identifier: com.github.nmcspadden.munki.EclipseTemurin 22 | Input: 23 | MUNKI_REPO_SUBDIR: apps/%NAME% 24 | FEATURE_VERSION: "11" 25 | NAME: EclipseTemurin%FEATURE_VERSION% 26 | OS: mac 27 | RELEASE_TYPE: ga 28 | DOWNLOAD_ARCH: x64 29 | MUNKI_ARCH: x86_64 30 | IMAGE_TYPE: jdk 31 | JVM_IMPLEMENTATION: hotspot 32 | HEAP_SIZE: normal 33 | VENDOR: adoptium 34 | pkginfo: 35 | catalogs: 36 | - testing 37 | description: Eclipse Temurin JDK %FEATURE_VERSION% 38 | developer: Adoptium 39 | display_name: Eclipse Temurin JDK %FEATURE_VERSION% 40 | name: '%NAME%' 41 | supported_architectures: 42 | - '%MUNKI_ARCH%' 43 | unattended_install: true 44 | MinimumVersion: '2.3' 45 | ParentRecipe: com.github.nmcspadden.recipes.download.EclipseTemurin 46 | Process: 47 | - Processor: FlatPkgUnpacker 48 | Arguments: 49 | flat_pkg_path: "%pathname%" 50 | destination_path: "%RECIPE_CACHE_DIR%/unpack" 51 | purge_destination: True 52 | 53 | - Processor: PkgPayloadUnpacker 54 | Arguments: 55 | pkg_payload_path: "%RECIPE_CACHE_DIR%/unpack/net.temurin.%FEATURE_VERSION%.jdk.pkg/Payload" 56 | destination_path: "%RECIPE_CACHE_DIR%/payload" 57 | purge_destination: False 58 | 59 | - Processor: PlistReader 60 | Arguments: 61 | info_path: "%RECIPE_CACHE_DIR%/payload/Library/Java/JavaVirtualMachines/temurin-%FEATURE_VERSION%.jdk/Contents/Info.plist" 62 | plist_keys: 63 | CFBundleShortVersionString: major_version 64 | CFBundleVersion: minor_version 65 | 66 | - Processor: PathDeleter 67 | Arguments: 68 | path_list: 69 | - "%RECIPE_CACHE_DIR%/unpack" 70 | - "%RECIPE_CACHE_DIR%/payload" 71 | 72 | - Processor: MunkiPkginfoMerger 73 | Arguments: 74 | additional_pkginfo: 75 | version: '%major_version%+%minor_version%' 76 | 77 | - Processor: MunkiImporter 78 | Arguments: 79 | pkg_path: '%pathname%' 80 | repo_subdirectory: '%MUNKI_REPO_SUBDIR%' 81 | -------------------------------------------------------------------------------- /VMwareFusionDeploy/VMwareFusionDeploy.munki.recipe: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Copyright 6 | Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved 7 | Description 8 | Imports the VMwareFusion mass deployment package into Munki. Requires justinrummel-recipes to download. You can substitute your own deploy.ini file in an override by placing the content in the DEPLOY_INI_FILE input variable. At a minimum, you'll need to put your license key in (replace the XXXXXs), or the postflight will fail. 9 | Identifier 10 | com.github.nmcspadden.munki.deploy.VMwareFusion 11 | Input 12 | 13 | MUNKI_REPO_SUBDIR 14 | apps/VMware 15 | NAME 16 | VMwareFusion 17 | pkginfo 18 | 19 | blocking_applications 20 | 21 | VMware Fusion.app 22 | 23 | catalogs 24 | 25 | testing 26 | 27 | category 28 | Productivity 29 | description 30 | 31 | developer 32 | VMware 33 | display_name 34 | VMWare Fusion Pro 35 | minimum_os_version 36 | 10.13 37 | name 38 | %NAME% 39 | uninstall_method 40 | uninstall_script 41 | uninstall_script 42 | #!/bin/sh 43 | /bin/rm -rf /Applications/VMware\ Fusion.app 44 | /bin/rm -f /Library/Preferences/VMware Fusion/config 45 | 46 | 47 | 48 | MinimumVersion 49 | 0.2.5 50 | ParentRecipe 51 | com.github.nmcspadden.pkg.deploy.VMwareFusion 52 | Process 53 | 54 | 55 | Arguments 56 | 57 | dmg_path 58 | %RECIPE_CACHE_DIR%/DeployVMwareFusion.dmg 59 | dmg_root 60 | %pkgroot% 61 | 62 | Processor 63 | DmgCreator 64 | 65 | 66 | Arguments 67 | 68 | additional_pkginfo 69 | 70 | minimum_os_version 71 | %ls_minimum_system_version% 72 | version 73 | %version% 74 | 75 | 76 | Processor 77 | MunkiPkginfoMerger 78 | 79 | 80 | Arguments 81 | 82 | pkg_path 83 | %RECIPE_CACHE_DIR%/DeployVMwareFusion.dmg 84 | repo_subdirectory 85 | %MUNKI_REPO_SUBDIR% 86 | 87 | Processor 88 | MunkiImporter 89 | 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /Chef_Processors/ChefArray.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) Facebook, Inc. and its affiliates. 5 | # 6 | # This source code is licensed under the BSD-style license found in the 7 | # LICENSE file in the root directory of this source tree. 8 | # 9 | """See docstring for ChefArray class.""" 10 | 11 | from __future__ import absolute_import 12 | 13 | from autopkglib import Processor 14 | 15 | __all__ = ["ChefArray"] 16 | 17 | 18 | class ChefArray(Processor): 19 | description = ( 20 | "Produces an array that can be used with other " 21 | " Chef blocks. See " 22 | "https://docs.chef.io/ruby.html#arrays." 23 | ) 24 | input_variables = { 25 | "item_list": { 26 | "description": ( 27 | "Array of items to be put into the array block. This " 28 | "can also be a single string." 29 | ), 30 | "required": True, 31 | }, 32 | "no_wrap_quotes": { 33 | "description": "Do not add wrapping quotation marks.", 34 | "required": False, 35 | }, 36 | "remove_version": { 37 | "description": ("Removes the version string from the variable."), 38 | "required": False, 39 | }, 40 | } 41 | output_variables = {"array_block": {"description": "Chef array block."}} 42 | 43 | __doc__ = description 44 | 45 | def main(self): 46 | beginning_bracket = "[\n" 47 | iterator = "item" 48 | end_bracket = "]" 49 | each_text = ".each do |%s|\n" % iterator 50 | quotes = "'" 51 | itemlist = list() 52 | 53 | # Are we going to use wrapping quotes? 54 | if self.env.get("no_wrap_quotes"): 55 | quotes = "" 56 | 57 | # Check to see if one item was passed as a single string 58 | if isinstance(self.env["item_list"], basestring): 59 | if self.env["remove_version"]: 60 | # Remove the ['version'] text from the string 61 | version_string = "['%s']" % self.env["remove_version"] 62 | if version_string in self.env["item_list"]: 63 | self.env["item_list"] = self.env["item_list"].replace( 64 | version_string, "" 65 | ) 66 | self.env["array_block"] = self.env["item_list"] + each_text 67 | else: 68 | itemlist = self.env["item_list"] 69 | # Begin the block 70 | self.env["array_block"] = beginning_bracket 71 | # Loop through the array of items 72 | for item in itemlist: 73 | self.output("Item: %s" % item) 74 | self.env["array_block"] += " %s%s%s,\n" % (quotes, str(item), quotes) 75 | # End the block 76 | self.env["array_block"] += end_bracket 77 | # Remove the trailing comma on the last item 78 | self.env["array_block"] = self.env["array_block"].replace(",\n]", "\n]") 79 | self.env["array_block"] += each_text 80 | self.output("Chef block: \n%s" % self.env["array_block"]) 81 | 82 | 83 | if __name__ == "__main__": 84 | PROCESSOR = ChefArray() 85 | PROCESSOR.execute_shell() 86 | -------------------------------------------------------------------------------- /AppStoreApp/AppStoreApp.munki.recipe: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Description 6 | Checks for the update of a MAS app. If the version on disk is up to date, then import into Munki directly. If out of date, abort. This recipe MUST ONLY be used with an override - do not run this recipe directly. See the documentation here: https://github.com/autopkg/nmcspadden-recipes/#appstoreapp-recipe 7 | Identifier 8 | com.github.nmcspadden.munki.appstore 9 | Input 10 | 11 | MUNKI_REPO_SUBDIR 12 | apps/apple 13 | NAME 14 | AppStoreApp 15 | PATH 16 | /Applications/%NAME%.app 17 | pkginfo 18 | 19 | catalogs 20 | 21 | release 22 | 23 | display_name 24 | %NAME% 25 | name 26 | %NAME% 27 | unattended_install 28 | 29 | 30 | 31 | Process 32 | 33 | 34 | Processor 35 | Versioner 36 | Arguments 37 | 38 | input_plist_path 39 | %PATH%/Contents/Info.plist 40 | 41 | 42 | 43 | Processor 44 | Copier 45 | Arguments 46 | 47 | source_path 48 | %PATH% 49 | destination_path 50 | %RECIPE_CACHE_DIR%/%NAME%%PATH% 51 | overwrite 52 | 53 | 54 | 55 | 56 | Processor 57 | DmgCreator 58 | Arguments 59 | 60 | dmg_root 61 | %RECIPE_CACHE_DIR%/%NAME%%PATH% 62 | dmg_path 63 | %RECIPE_CACHE_DIR%/%NAME%-%version%.dmg 64 | 65 | 66 | 67 | Processor 68 | MunkiImporter 69 | Arguments 70 | 71 | pkg_path 72 | %RECIPE_CACHE_DIR%/%NAME%-%version%.dmg 73 | repo_subdirectory 74 | %MUNKI_REPO_SUBDIR% 75 | 76 | 77 | 78 | Comment 79 | Clean up after ourselves 80 | Processor 81 | PathDeleter 82 | Arguments 83 | 84 | path_list 85 | 86 | %RECIPE_CACHE_DIR%/%NAME% 87 | 88 | 89 | 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /SQLDeveloper/SQLDeveloper.munki.recipe: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Copyright 6 | Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved 7 | Description 8 | Creates a DMG for SQLDeveloper and imports into Munki. You must provide your own .zip download using the -p argument. 9 | Identifier 10 | com.github.nmcspadden.munki.sqldeveloper 11 | Input 12 | 13 | JDK_NAME 14 | OracleJava8JDK 15 | MUNKI_REPO_SUBDIR 16 | apps/Oracle 17 | NAME 18 | SQLDeveloper 19 | pkginfo 20 | 21 | catalogs 22 | 23 | testing 24 | 25 | category 26 | Developer Tools 27 | description 28 | SQL Developer is a free integrated development environment that simplifies the development and management of Oracle Database. 29 | developer 30 | Oracle 31 | display_name 32 | SQL Developer 33 | name 34 | %NAME% 35 | 36 | 37 | MinimumVersion 38 | 0.5.1 39 | ParentRecipe 40 | com.github.nmcspadden.dmg.sqldeveloper 41 | Process 42 | 43 | 44 | Arguments 45 | 46 | faux_root 47 | %pkgroot 48 | installs_item_paths 49 | 50 | SQLDeveloper.app/Contents/Resources/sqldeveloper/sqldeveloper/bin/version.properties 51 | 52 | 53 | Processor 54 | MunkiInstallsItemsCreator 55 | 56 | 57 | Arguments 58 | 59 | additional_pkginfo 60 | 61 | installs 62 | 63 | 64 | md5checksum 65 | 2e7650fee02f3ac91838397daf5f8817 66 | path 67 | /Applications/SQLDeveloper.app/Contents/Resources/sqldeveloper/sqldeveloper/bin/version.properties 68 | type 69 | file 70 | 71 | 72 | requires 73 | 74 | %JDK_NAME% 75 | 76 | version 77 | %version% 78 | 79 | 80 | Processor 81 | MunkiPkginfoMerger 82 | 83 | 84 | Arguments 85 | 86 | pkg_path 87 | %RECIPE_CACHE_DIR%/%NAME%-%version%.dmg 88 | repo_subdirectory 89 | %MUNKI_REPO_SUBDIR% 90 | 91 | Processor 92 | MunkiImporter 93 | 94 | 95 | Arguments 96 | 97 | path_list 98 | 99 | %RECIPE_CACHE_DIR%/%NAME%-%version%.dmg 100 | 101 | 102 | Processor 103 | PathDeleter 104 | 105 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /Shared_Processors/SubDirectoryList.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) Facebook, Inc. and its affiliates. 5 | # 6 | # This source code is licensed under the BSD-style license found in the 7 | # LICENSE file in the root directory of this source tree.# 8 | """See docstring for SubDirectoryList class.""" 9 | 10 | 11 | from __future__ import absolute_import 12 | 13 | import os 14 | 15 | from autopkglib import Processor, ProcessorError 16 | 17 | __all__ = ["SubDirectoryList"] 18 | 19 | 20 | class SubDirectoryList(Processor): 21 | """Finds a filename for use in other Processors. 22 | 23 | Currently only supports glob filename patterns. 24 | """ 25 | 26 | input_variables = { 27 | "root_path": { 28 | "description": "Path to start looking for files.", 29 | "required": True, 30 | }, 31 | "suffix_string": { 32 | "description": ( 33 | "String to append to each found item name in dir. Defaults to ','" 34 | ), 35 | "default": ",", 36 | "required": False, 37 | }, 38 | } 39 | output_variables = { 40 | "found_filenames": { 41 | "description": ( 42 | "String containing a list of all files found " 43 | "relative to root_path, separated by " 44 | "suffix_string." 45 | ) 46 | }, 47 | "found_directories": { 48 | "description": ( 49 | "String containg a list of all directories " 50 | "found relative to root_path, separated by " 51 | "suffix_string." 52 | ) 53 | }, 54 | "relative_root": {"description": ("Relative root path")}, 55 | } 56 | 57 | description = __doc__ 58 | 59 | def main(self): 60 | sip_dirs = ["usr", "usr/local", "private", "private/etc", "Library"] 61 | format_string = "%s" % self.env["suffix_string"] 62 | # search_string = ' \'{0}\'' 63 | search_string = "{0}" 64 | dir_list = list() 65 | file_list = list() 66 | if not os.path.isdir(self.env["root_path"]): 67 | raise ProcessorError("Can't find root path!") 68 | for dirName, subdirList, fileList in os.walk(self.env["root_path"]): 69 | relative_path = os.path.relpath(dirName, self.env["root_path"]) 70 | # We need to remove the SIP folders so Chef doesn't try to create them 71 | if not relative_path == "." and not (relative_path in sip_dirs): 72 | dir_list.append(relative_path) 73 | # search_string.format(format_string.join(dirName)).strip() 74 | for fname in fileList: 75 | if ".DS_Store" in fname: 76 | continue 77 | # print('\t%s' % fname) 78 | relpath = os.path.relpath( 79 | os.path.join(fname, dirName), self.env["root_path"] 80 | ) 81 | self.output("Relative path: %s" % relpath) 82 | if relpath == ".": 83 | # we want to avoid prepending './' to files at root dir 84 | relpath = "" 85 | # print "Real relative path: %s" % relpath 86 | file_list.append(os.path.join(relpath, fname)) 87 | self.env["found_directories"] = search_string.format( 88 | format_string.join(dir_list) 89 | ).strip() 90 | self.env["found_filenames"] = search_string.format( 91 | format_string.join(file_list) 92 | ).strip() 93 | 94 | 95 | if __name__ == "__main__": 96 | PROCESSOR = SubDirectoryList() 97 | PROCESSOR.execute_shell() 98 | -------------------------------------------------------------------------------- /Xcode/AppleDataGatherer.py: -------------------------------------------------------------------------------- 1 | #!/usr/local/autopkg/python 2 | # 3 | # Copyright (c) Facebook, Inc. and its affiliates. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | """See docstring for AppleDataGatherer class""" 18 | 19 | 20 | # Disabling warnings for env members and imports that only affect recipe- 21 | # specific processors. 22 | # pylint: disable=e1101,f0401 23 | 24 | import os 25 | 26 | from urllib.parse import quote 27 | 28 | from autopkglib import Processor, ProcessorError 29 | 30 | 31 | __all__ = ["AppleDataGatherer"] 32 | 33 | 34 | class AppleDataGatherer(Processor): 35 | """Gather Xcode-specific curl data payloads into a file on disk.""" 36 | 37 | description = __doc__ 38 | input_variables = { 39 | "apple_id": { 40 | "description": "AppleID that can log into the Apple dev portal.", 41 | "required": True 42 | }, 43 | "password": { 44 | "description": ( 45 | "Password for AppleID that can log into Apple dev portal." 46 | ), 47 | "required": False 48 | }, 49 | "password_file": { 50 | "description": ( 51 | "A path to a file to read the password from. Using " 52 | "this will ignore the 'password' argument." 53 | ), 54 | "required": False 55 | }, 56 | "appID_key": { 57 | "description": "App ID key to log into.", 58 | "required": True 59 | } 60 | } 61 | output_variables = { 62 | "data_pathname": { 63 | "description": "Path to the data file." 64 | } 65 | } 66 | 67 | 68 | def main(self): 69 | """Store the login data file.""" 70 | password = self.env.get("password") 71 | if self.env.get("password_file"): 72 | with open(self.env["password_file"]) as f: 73 | password = f.read() 74 | if not password: 75 | raise ProcessorError( 76 | "You must provide either the 'password' or 'password_file' argument." 77 | ) 78 | appleIDstring = f"appleId={quote(self.env['apple_id'])}&" 79 | appIDKeystring = f"appIdKey={self.env['appID_key']}&" 80 | passwordstring = f"accountPassword={password}" 81 | 82 | login_data = appleIDstring + appIDKeystring + passwordstring 83 | download_dir = os.path.join(self.env["RECIPE_CACHE_DIR"], "downloads") 84 | filename = "login_data" 85 | # create download_dir if needed 86 | if not os.path.exists(download_dir): 87 | try: 88 | os.makedirs(download_dir) 89 | except OSError as err: 90 | raise ProcessorError( 91 | f"Can't create {download_dir}: {err.strerror}" 92 | ) 93 | self.output("Writing data to file") 94 | self.env["data_pathname"] = os.path.join(download_dir, filename) 95 | with open(self.env["data_pathname"], "w") as f: 96 | f.write(login_data) 97 | 98 | 99 | if __name__ == "__main__": 100 | PROCESSOR = AppleDataGatherer() 101 | PROCESSOR.execute_shell() 102 | -------------------------------------------------------------------------------- /Xcode/Xcode.extract.recipe: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Description 7 | Extract Xcode from a XIP. Requires passing in a XIP containing Xcode. 8 | Identifier 9 | com.github.nmcspadden.extract.xcode 10 | Input 11 | 12 | NAME 13 | Xcode 14 | BUILD_NUMBER_EMIT_PATH 15 | xcode_build_number 16 | 17 | MinimumVersion 18 | 1.0.4 19 | ParentRecipe 20 | com.github.nmcspadden.download.xcode 21 | Process 22 | 23 | 24 | Processor 25 | XcodeXIPUnpacker 26 | Arguments 27 | 28 | PKG 29 | %pathname% 30 | 31 | 32 | 33 | Processor 34 | FileFinder 35 | Arguments 36 | 37 | pattern 38 | %RECIPE_CACHE_DIR%/Xcode_unpack/*.app 39 | 40 | 41 | 42 | Processor 43 | CodeSignatureVerifier 44 | Arguments 45 | 46 | input_path 47 | %found_filename% 48 | requirement 49 | identifier "com.apple.dt.Xcode" and anchor apple 50 | 51 | 52 | 53 | Processor 54 | PlistReader 55 | Arguments 56 | 57 | info_path 58 | %found_filename%/Contents/version.plist 59 | plist_keys 60 | 61 | CFBundleVersion 62 | bundle_version 63 | CFBundleShortVersionString 64 | version 65 | ProductBuildVersion 66 | build_version 67 | 68 | 69 | 70 | 71 | Processor 72 | XcodeVersioner 73 | Arguments 74 | 75 | app_path 76 | %found_filename% 77 | version 78 | %version% 79 | 80 | 81 | 82 | Processor 83 | XcodeBuildNumberEmitter 84 | Arguments 85 | 86 | dont_skip 87 | %NOSKIP% 88 | output_filepath 89 | %BUILD_NUMBER_EMIT_PATH% 90 | 91 | 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /Xcode/XcodeVersioner.py: -------------------------------------------------------------------------------- 1 | #!/usr/local/autopkg/python 2 | # 3 | # Copyright (c) Facebook, Inc. and its affiliates. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | """Get all Version information from Xcode.""" 18 | 19 | from autopkglib import Processor, ProcessorError 20 | 21 | 22 | __all__ = ["XcodeVersioner"] 23 | 24 | 25 | class XcodeVersioner(Processor): 26 | """Break down a version number into its separate components.""" 27 | 28 | description = __doc__ 29 | input_variables = { 30 | "version": { 31 | "description": ( 32 | "CFBundleShortVersionString from an Xcode Info.plist. " 33 | "Produced by PlistReader." 34 | ), 35 | "required": True, 36 | }, 37 | "app_path": { 38 | "description": ( 39 | "Path to Xcode app to look up version" 40 | "information from the bundle." 41 | ), 42 | "required": True 43 | } 44 | } 45 | output_variables = { 46 | "major_version": { 47 | "description": "Major version of Xcode - i.e. Xcode 7, 8." 48 | }, 49 | "minor_version": { 50 | "description": "Minor version of Xcode - i.e. Xcode X.1, X.2." 51 | }, 52 | "patch_version": { 53 | "description": ( 54 | "Patch version of Xcode - i.e. Xcode X.Y.0, X.Y.1. " 55 | "Patch version will be normalized to 0 if missing (i.e. 8.3 " 56 | "becomes 8.3.0)." 57 | ) 58 | }, 59 | "is_beta": { 60 | "description": ( 61 | "Boolean that is true if this Xcode is a beta version." 62 | ) 63 | }, 64 | "beta_version": { 65 | "description": "The beta number - 1, 2, 3, etc." 66 | }, 67 | "build_version": { 68 | "description": "Build version of Xcode - e.g. 11B500" 69 | } 70 | } 71 | 72 | 73 | def main(self): 74 | """Main.""" 75 | main_version_string = self.env["version"] 76 | split_string = main_version_string.split(".") 77 | if len(split_string) < 2: 78 | raise ProcessorError( 79 | "Version string should be in format X.Y, unless Apple broke " 80 | "literally everything again." 81 | ) 82 | self.env["major_version"] = str(split_string[0]) 83 | self.output(f"Major version: {self.env['major_version']}") 84 | self.env["minor_version"] = str(split_string[1]) 85 | self.output(f"Minor version: {self.env['minor_version']}") 86 | try: 87 | self.env["patch_version"] = split_string[2] 88 | except IndexError: 89 | self.output("Normalizing patch to 0") 90 | self.env["patch_version"] = "0" 91 | self.output(f"Patch version: {self.env['patch_version']}") 92 | self.output(f"Build version: {self.env['build_version']}") 93 | if "beta_version" not in self.env: 94 | self.env["is_beta"] = False 95 | self.output("Not a beta version") 96 | else: 97 | self.output(f"Beta version: {self.env['beta_version']}") 98 | 99 | if __name__ == "__main__": 100 | PROCESSOR = XcodeVersioner() 101 | PROCESSOR.execute_shell() 102 | -------------------------------------------------------------------------------- /LegacyRecipes/GoogleEarthPro/GoogleEarthPro.pkg.recipe: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Description 6 | Downloads latest Google Earth disk image and makes a pkg. 7 | Identifier 8 | com.github.nmcspadden-recipes.pkg.google-earth-pro 9 | Input 10 | 11 | NAME 12 | GoogleEarthPro 13 | 14 | MinimumVersion 15 | 0.2.0 16 | ParentRecipe 17 | com.github.nmcspadden-recipes.download.google-earth-pro 18 | Process 19 | 20 | 21 | 22 | Arguments 23 | 24 | pkgroot 25 | %RECIPE_CACHE_DIR%/unpack/root 26 | pkgdirs 27 | 28 | Applications 29 | 0775 30 | 31 | 32 | Processor 33 | PkgRootCreator 34 | 35 | 36 | 37 | Processor 38 | FlatPkgUnpacker 39 | Arguments 40 | 41 | destination_path 42 | %RECIPE_CACHE_DIR%/expanded 43 | flat_pkg_path 44 | %pathname%/Install Google Earth*.pkg 45 | 46 | 47 | 48 | Processor 49 | PkgPayloadUnpacker 50 | Arguments 51 | 52 | destination_path 53 | %RECIPE_CACHE_DIR%/unpack/root/Applications 54 | pkg_payload_path 55 | %RECIPE_CACHE_DIR%/expanded/Google_Earth_Pro.pkg/Payload 56 | 57 | 58 | 59 | 60 | Processor 61 | PlistReader 62 | Arguments 63 | 64 | info_path 65 | %RECIPE_CACHE_DIR%/unpack/root/Applications/Google Earth Pro.app/Contents/Info.plist 66 | plist_keys 67 | 68 | CFBundleVersion 69 | version 70 | CFBundleIdentifier 71 | bundleid 72 | 73 | 74 | 75 | 76 | Processor 77 | PkgCreator 78 | Arguments 79 | 80 | pkgname 81 | %NAME%-%version% 82 | pkg_request 83 | 84 | pkgdir 85 | %RECIPE_CACHE_DIR%/ 86 | id 87 | %bundleid% 88 | options 89 | purge_ds_store 90 | chown 91 | 92 | 93 | path 94 | Applications 95 | user 96 | root 97 | group 98 | admin 99 | 100 | 101 | 102 | 103 | 104 | 105 | Processor 106 | PathDeleter 107 | Arguments 108 | 109 | path_list 110 | 111 | %RECIPE_CACHE_DIR%/unpack 112 | %RECIPE_CACHE_DIR%/expanded 113 | 114 | 115 | 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /Xcode/XcodeFileNamer.py: -------------------------------------------------------------------------------- 1 | #!/usr/local/autopkg/python 2 | # 3 | # Copyright (c) Facebook, Inc. and its affiliates. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | """Create a filename for Xcode based on version information.""" 18 | 19 | from autopkglib import Processor 20 | 21 | 22 | __all__ = ["XcodeFileNamer"] 23 | 24 | 25 | class XcodeFileNamer(Processor): 26 | """Create a filename for Xcode based on version information.""" 27 | 28 | description = __doc__ 29 | input_variables = { 30 | "should_produce_versioned_name": { 31 | "description": ( 32 | "Whether or not we should produce a versioned name. " 33 | "If this is non-empty, it's evaluated as true." 34 | ), 35 | "required": True 36 | }, 37 | "major_version": { 38 | "description": "Major version of Xcode - i.e. Xcode 7, 8.", 39 | "required": True 40 | }, 41 | "minor_version": { 42 | "description": "Minor version of Xcode - i.e. Xcode X.1, X.2.", 43 | "required": True 44 | }, 45 | "patch_version": { 46 | "description": ( 47 | "Patch version of Xcode - i.e. Xcode X.Y.0, X.Y.1. " 48 | "Patch version will be normalized to 0 if missing (i.e. 8.3 " 49 | "becomes 8.3.0)." 50 | ), 51 | "required": True 52 | }, 53 | "is_beta": { 54 | "description": ( 55 | "Boolean that is true if this Xcode is a beta version." 56 | ), 57 | "required": True 58 | }, 59 | "beta_version": { 60 | "description": ( 61 | "The beta number - 1, 2, 3, etc. Only used if is_beta is True. " 62 | "Assumed to be 0 if not provided." 63 | ), 64 | "required": False 65 | }, 66 | "should_lowercase": { 67 | "description": ( 68 | "If this value is non-empty, use a lower-case " 69 | "filename - xcode_X.Y.0_suffix.app." 70 | ), 71 | "required": False 72 | }, 73 | "suffix": { 74 | "description": ( 75 | "Any additional suffix string to append to " 76 | "the name prior to the .app extension." 77 | ), 78 | "required": False 79 | } 80 | } 81 | output_variables = { 82 | "xcode_filename": { 83 | "description": "Allow producing a versioned Xcode name." 84 | } 85 | } 86 | 87 | 88 | def main(self): 89 | """Main.""" 90 | if not self.env["should_produce_versioned_name"]: 91 | # Set the default name for Xcode Beta or the default name for Xcode 92 | self.env["xcode_filename"] = "Xcode-beta" if self.env["is_beta"] else "Xcode" 93 | return 94 | # end up with xcode_10.2.0_beta_4 or xcode_10.2.1 95 | prefix = "xcode" if self.env.get("should_lowercase") else "Xcode" 96 | name = "{}_{}.{}.{}".format( 97 | prefix, 98 | self.env["major_version"], 99 | self.env["minor_version"], 100 | self.env["patch_version"] 101 | ) 102 | if self.env["is_beta"]: 103 | name += f"_beta_{self.env.get('beta_version', '0')}" 104 | name += self.env.get("suffix", "") 105 | self.output(f"Xcode name: {name}") 106 | self.env["xcode_filename"] = name 107 | 108 | 109 | if __name__ == "__main__": 110 | PROCESSOR = XcodeFileNamer() 111 | PROCESSOR.execute_shell() 112 | -------------------------------------------------------------------------------- /Xcode/Xcode.download.recipe: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Description 7 | Download Xcode from the Apple dev portal. You must override the APPLE_ID and one of PASSWORD or PASSWORD_FILE. BETA must either be empty for stable releases or set to "Beta" in order to match Xcode betas. 8 | Identifier 9 | com.github.nmcspadden.download.xcode 10 | Input 11 | 12 | NAME 13 | Xcode 14 | APPLE_ID 15 | dev@domain.com 16 | PASSWORD_FILE 17 | 18 | NOSKIP 19 | 20 | PASSWORD 21 | 22 | BETA 23 | 24 | PATTERN 25 | (.*\/Xcode_.*\/Xcode.*.xip) 26 | NOSKIP 27 | 28 | VERSION_EMIT_PATH 29 | xcode_tag 30 | 31 | MinimumVersion 32 | 1.0.4 33 | Process 34 | 35 | 36 | Processor 37 | AppleDataGatherer 38 | Arguments 39 | 40 | apple_id 41 | %APPLE_ID% 42 | password_file 43 | %PASSWORD_FILE% 44 | password 45 | %PASSWORD% 46 | appID_key 47 | 891bd3417a7776362562d2197f89480a8547b108fd934911bcbea0110d07f757 48 | 49 | 50 | 51 | Processor 52 | AppleCookieDownloader 53 | Arguments 54 | 55 | login_data 56 | %RECIPE_CACHE_DIR%/downloads/login_data 57 | 58 | 59 | 60 | Processor 61 | AppleURLSearcher 62 | Arguments 63 | 64 | re_pattern 65 | %PATTERN% 66 | 67 | 68 | 69 | Processor 70 | XcodeVersionEmitter 71 | Arguments 72 | 73 | dont_skip 74 | %NOSKIP% 75 | url 76 | %match% 77 | output_filepath 78 | %VERSION_EMIT_PATH% 79 | 80 | 81 | 82 | Processor 83 | EndOfCheckPhase 84 | 85 | 86 | Processor 87 | URLDownloader 88 | Arguments 89 | 90 | url 91 | %match% 92 | curl_opts 93 | 94 | --request 95 | GET 96 | --cookie 97 | %download_cookies% 98 | 99 | 100 | 101 | 102 | Processor 103 | PathDeleter 104 | Arguments 105 | 106 | path_list 107 | 108 | %RECIPE_CACHE_DIR%/downloads/login_data 109 | 110 | 111 | 112 | 113 | 114 | 115 | -------------------------------------------------------------------------------- /UnityWebPlayer/unitywebplayer.munki.recipe: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Description 6 | Downloads the current installation package for Unity Web Player. Imports it 7 | into Munki. 8 | Identifier 9 | com.github.nmcspadden.munki.UnityWebPlayer 10 | Input 11 | 12 | MUNKI_REPO_SUBDIR 13 | utility/unity 14 | NAME 15 | UnityWebPlayer 16 | pkginfo 17 | 18 | catalogs 19 | 20 | testing 21 | 22 | description 23 | The Unity Web Player enables you to view blazing 3D content created with Unity directly in your browser, and autoupdates as necessary. 24 | display_name 25 | UnityWebPlayer 26 | minimum_os_version 27 | 10.5.8 28 | name 29 | %NAME% 30 | unattended_install 31 | 32 | 33 | 34 | ParentRecipe 35 | com.github.nmcspadden.download.UnityWebPlayer 36 | Process 37 | 38 | 39 | Arguments 40 | 41 | flat_pkg_path 42 | %pathname%/*.pkg 43 | destination_path 44 | %RECIPE_CACHE_DIR%/unpack 45 | 46 | Processor 47 | FlatPkgUnpacker 48 | 49 | 50 | Arguments 51 | 52 | pkgroot 53 | %RECIPE_CACHE_DIR%/unpack/root/Library/Internet Plug-Ins/Unity Web Player.plugin 54 | pkgdirs 55 | 56 | 57 | Processor 58 | PkgRootCreator 59 | 60 | 61 | Arguments 62 | 63 | pkg_payload_path 64 | %RECIPE_CACHE_DIR%/unpack/InstallUnityPlayer.pkg.tmp/Payload 65 | destination_path 66 | %RECIPE_CACHE_DIR%/unpack/root/Library/Internet Plug-Ins/ 67 | 68 | Processor 69 | PkgPayloadUnpacker 70 | 71 | 72 | Arguments 73 | 74 | installs_item_paths 75 | 76 | /Library/Internet Plug-Ins/Unity Web player.plugin 77 | 78 | faux_root 79 | %RECIPE_CACHE_DIR%/unpack/root/ 80 | 81 | Processor 82 | MunkiInstallsItemsCreator 83 | 84 | 85 | Processor 86 | MunkiPkginfoMerger 87 | Arguments 88 | 89 | 90 | 91 | Arguments 92 | 93 | input_plist_path 94 | %RECIPE_CACHE_DIR%/unpack/root/Library/Internet Plug-Ins/Unity Web Player.plugin/Contents/Info.plist 95 | plist_version_key 96 | CFBundleVersion 97 | 98 | Processor 99 | Versioner 100 | 101 | 102 | Processor 103 | MunkiPkginfoMerger 104 | Arguments 105 | 106 | additional_pkginfo 107 | 108 | version 109 | %version% 110 | 111 | 112 | 113 | 114 | Arguments 115 | 116 | path_list 117 | 118 | %RECIPE_CACHE_DIR%/unpack 119 | 120 | 121 | Processor 122 | PathDeleter 123 | 124 | 125 | Arguments 126 | 127 | pkg_path 128 | %pathname% 129 | repo_subdirectory 130 | %MUNKI_REPO_SUBDIR% 131 | 132 | Processor 133 | MunkiImporter 134 | 135 | 136 | 137 | 138 | -------------------------------------------------------------------------------- /LegacyRecipes/GoogleEarthPro/GoogleEarthProProfile.pkg.recipe: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Description 6 | Downloads latest Google Earth disk image and makes a pkg, including profile to suppress startup screens. 7 | Identifier 8 | com.github.nmcspadden-recipes.pkg.google-earth-pro.profile 9 | Input 10 | 11 | NAME 12 | GoogleEarthPro 13 | 14 | MinimumVersion 15 | 0.2.0 16 | ParentRecipe 17 | com.github.nmcspadden-recipes.download.google-earth-pro 18 | Process 19 | 20 | 21 | 22 | Arguments 23 | 24 | pkgroot 25 | %RECIPE_CACHE_DIR%/unpack/root 26 | pkgdirs 27 | 28 | Applications 29 | 0775 30 | Library 31 | 0775 32 | Library/Profiles 33 | 0775 34 | 35 | 36 | Processor 37 | PkgRootCreator 38 | 39 | 40 | 41 | Processor 42 | FlatPkgUnpacker 43 | Arguments 44 | 45 | destination_path 46 | %RECIPE_CACHE_DIR%/expanded 47 | flat_pkg_path 48 | %pathname%/*.pkg 49 | 50 | 51 | 52 | Processor 53 | PkgPayloadUnpacker 54 | Arguments 55 | 56 | destination_path 57 | %RECIPE_CACHE_DIR%/unpack/root/Applications 58 | pkg_payload_path 59 | %RECIPE_CACHE_DIR%/expanded/Google_Earth_Pro.pkg/Payload 60 | 61 | 62 | 63 | 64 | Processor 65 | PlistReader 66 | Arguments 67 | 68 | info_path 69 | %RECIPE_CACHE_DIR%/unpack/root/Applications/Google Earth Pro.app/Contents/Info.plist 70 | plist_keys 71 | 72 | CFBundleVersion 73 | version 74 | CFBundleIdentifier 75 | bundleid 76 | 77 | 78 | 79 | 80 | 81 | Processor 82 | Copier 83 | Arguments 84 | 85 | source_path 86 | %RECIPE_DIR%/com.github.nmcspadden-recipes.googleearthpro.mobileconfig 87 | destination_path 88 | %pkgroot%/Library/Profiles/com.github.nmcspadden-recipes.googleearthpro.mobileconfig 89 | 90 | 91 | 92 | Processor 93 | PkgCreator 94 | Arguments 95 | 96 | pkgname 97 | %NAME%-%version% 98 | pkg_request 99 | 100 | pkgdir 101 | %RECIPE_CACHE_DIR%/ 102 | id 103 | %bundleid% 104 | options 105 | purge_ds_store 106 | scripts 107 | GoogleEarthPro_Scripts 108 | chown 109 | 110 | 111 | path 112 | Applications 113 | user 114 | root 115 | group 116 | admin 117 | 118 | 119 | 120 | 121 | 122 | 123 | Processor 124 | PathDeleter 125 | Arguments 126 | 127 | path_list 128 | 129 | %RECIPE_CACHE_DIR%/unpack 130 | %RECIPE_CACHE_DIR%/expanded 131 | 132 | 133 | 134 | 135 | 136 | 137 | -------------------------------------------------------------------------------- /AdoptOpenJDK/AdoptOpenJDKURLProvider.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # 3 | # Copyright (c) Facebook, Inc. and its affiliates. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | """See docstring for AdoptOpenJDKURLProvider class""" 17 | 18 | from __future__ import absolute_import, division, print_function, unicode_literals 19 | 20 | import json 21 | 22 | from autopkglib import ProcessorError 23 | from autopkglib.URLGetter import URLGetter 24 | 25 | 26 | try: 27 | from urllib.parse import urljoin 28 | except ImportError: 29 | from urlparse import urljoin 30 | 31 | 32 | __all__ = ["AdoptOpenJDKURLProvider"] 33 | 34 | URL = "https://api.adoptopenjdk.net/v2/info/releases/" 35 | 36 | 37 | class AdoptOpenJDKURLProvider(URLGetter): 38 | """Provides a version and dmg download for the AdoptOpenJDK.""" 39 | 40 | description = __doc__ 41 | input_variables = { 42 | "jdk_version": {"required": True, "description": "Version of JDK to fetch."}, 43 | "jdk_type": { 44 | "required": False, 45 | "description": "Fetch 'jdk', or 'jre'. Defaults to 'jdk'.", 46 | }, 47 | "jvm_type": { 48 | "required": False, 49 | "description": ( 50 | "Fetch a 'hotspot' or 'openj9' JVM target. Defaults to 'hotspot'." 51 | ), 52 | }, 53 | "binary_type": { 54 | "required": False, 55 | "description": "Fetch a 'pkg' or 'tgz' download. Defaults to 'pkg'.", 56 | }, 57 | "release": { 58 | "required": False, 59 | "description": "Fetch a specific release. Defaults to 'latest'.", 60 | }, 61 | } 62 | output_variables = { 63 | "version": {"description": "Version of the product."}, 64 | "url": {"description": "Download URL."}, 65 | "checksum": {"description": "Checksum of the targeted product."}, 66 | } 67 | 68 | def get_checksum(self, checksum_url, binary_type): 69 | """Get the expected checksum for the release.""" 70 | checksum_data = self.download(checksum_url, text=True) 71 | return checksum_data.split()[0] 72 | 73 | def main(self): 74 | """Find the download URL""" 75 | jvm_type = self.env.get("jvm_type", "hotspot") 76 | if jvm_type not in ["hotspot", "openj9"]: 77 | raise ProcessorError("jvm_type can only be 'hotspot' or 'openj9'") 78 | jdk_type = self.env.get("jdk_type", "jdk") 79 | if jdk_type not in ["jdk", "jre"]: 80 | raise ProcessorError("jdk_type can only be 'jdk' or 'jre'") 81 | binary_type = self.env.get("binary_type", "pkg") 82 | if binary_type not in ["pkg", "tgz"]: 83 | raise ProcessorError("jdk_type can only be 'pkg' or 'tgz'") 84 | release = self.env.get("release", "latest") 85 | queries = "?os=mac&openjdk_impl={}&type={}&release={}".format( 86 | jvm_type, jdk_type, release 87 | ) 88 | # Fetch the API data 89 | query_suffix = urljoin("openjdk{}".format(self.env["jdk_version"]), queries) 90 | api_url = urljoin(URL, query_suffix) 91 | self.output("Query URL: {}".format(api_url)) 92 | api_data = self.download(api_url, text=True) 93 | api_results = json.loads(api_data) 94 | # Determine what we're looking for - pkg or tgz 95 | if binary_type == "pkg": 96 | checksum_url = api_results["binaries"][0]["installer_checksum_link"] 97 | url = api_results["binaries"][0]["installer_link"] 98 | else: 99 | checksum_url = api_results["binaries"][0]["checksum_link"] 100 | url = api_results["binaries"][0]["binary_link"] 101 | # Use semantic versioning for the version string, although historically this 102 | # hasn't been anything particularly problematic 103 | version = api_results["binaries"][0]["version_data"]["semver"] 104 | self.env["version"] = version 105 | self.output("Version: {}".format(version)) 106 | # Get the checksum from the internet 107 | checksum = self.get_checksum(checksum_url, binary_type) 108 | self.env["checksum"] = checksum 109 | self.output("checksum: {}".format(checksum)) 110 | # Pick the URL 111 | self.env["url"] = url 112 | self.output("Found URL {}".format(self.env["url"])) 113 | 114 | 115 | if __name__ == "__main__": 116 | PROCESSOR = AdoptOpenJDKURLProvider() 117 | PROCESSOR.execute_shell() 118 | -------------------------------------------------------------------------------- /Xcode/AppleCookieDownloader.py: -------------------------------------------------------------------------------- 1 | #!/usr/local/autopkg/python 2 | # 3 | # Copyright (c) Facebook, Inc. and its affiliates. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | """See docstring for AppleCookieDownloader class""" 18 | 19 | import json 20 | import os.path 21 | 22 | from autopkglib import ProcessorError, URLGetter 23 | 24 | 25 | __all__ = ["AppleCookieDownloader"] 26 | 27 | class DownloadCookieError(Exception): 28 | def __init__(self, message): 29 | self.message = message 30 | super().__init__(self.message) 31 | 32 | 33 | 34 | class AppleCookieDownloader(URLGetter): 35 | """Downloads a URL to the specified download_dir using curl.""" 36 | 37 | description = __doc__ 38 | input_variables = { 39 | "login_data": { 40 | "description": "Path to login data file.", 41 | "required": True 42 | } 43 | } 44 | output_variables = { 45 | "download_cookies": { 46 | "description": "Path to the download cookies." 47 | } 48 | } 49 | 50 | 51 | def main(self): 52 | download_dir = os.path.join(self.env["RECIPE_CACHE_DIR"], "downloads") 53 | login_cookies = os.path.join(download_dir, "login_cookies") 54 | download_cookies = os.path.join(download_dir, "download_cookies") 55 | # create download_dir if needed 56 | if not os.path.exists(download_dir): 57 | try: 58 | os.makedirs(download_dir) 59 | except OSError as err: 60 | raise ProcessorError( 61 | f"Can't create {download_dir}: {err.strerror}" 62 | ) 63 | # We need to POST a request to the auth page to get the 64 | # 'myacinfo' cookie 65 | self.output("Getting login cookie") 66 | # Base curl options 67 | base_curl_opts = [ 68 | "--request", 69 | "POST", 70 | "--silent", 71 | "--show-error", 72 | "--no-buffer", 73 | "--dump-header", "-", 74 | "--speed-time", "30" 75 | ] 76 | # Curl options to acquire login cookies 77 | login_curl_opts = [ 78 | "--url", 79 | "https://idmsa.apple.com/IDMSWebAuth/authenticate", 80 | "--data", 81 | f"@{self.env['login_data']}", 82 | "--cookie-jar", 83 | login_cookies, 84 | "--output", 85 | "-" 86 | ] 87 | # Initialize the curl_cmd, add base curl options, and execute curl 88 | prepped_curl_cmd = self.prepare_curl_cmd() 89 | self.download_with_curl( 90 | prepped_curl_cmd + base_curl_opts + login_curl_opts 91 | ) 92 | # Now we need to get the download cookie 93 | output = os.path.join(download_dir, "listDownloads.json") 94 | self.output("Getting download cookie") 95 | if os.path.exists(output): 96 | # Delete it first 97 | os.unlink(output) 98 | # Curl options to acquire the download list 99 | dl_curl_opts = [ 100 | "--url", 101 | "https://developer.apple.com/services-account/QH65B2/downloadws/listDownloads.action", 102 | "--cookie", 103 | login_cookies, 104 | "--cookie-jar", 105 | download_cookies, 106 | "--output", 107 | output 108 | ] 109 | headers = {"Content-length": "0"} 110 | self.add_curl_headers(dl_curl_opts, headers) 111 | self.download_with_curl( 112 | prepped_curl_cmd + base_curl_opts + dl_curl_opts 113 | ) 114 | self.env["download_cookies"] = download_cookies 115 | try: 116 | with open(output) as f: 117 | # Verify this can be successfully loaded this as JSON and that credentials were not rejected 118 | login_attempt = json.load(f) 119 | if result_string := login_attempt.get("resultString"): 120 | if "your session has expired" in result_string.lower(): 121 | raise DownloadCookieError(login_attempt) 122 | except IOError as error: 123 | raise ProcessorError( 124 | "Unable to load the listDownloads.json file.") from error 125 | except DownloadCookieError as error: 126 | raise ProcessorError(error) 127 | except Exception as error: 128 | raise ProcessorError( 129 | f"Unknown error loading the list of downloads. Error: {error}") from error 130 | self.output("Successfully acquired the download list") 131 | 132 | 133 | if __name__ == "__main__": 134 | PROCESSOR = AppleCookieDownloader() 135 | PROCESSOR.execute_shell() 136 | -------------------------------------------------------------------------------- /Xcode/Xcode.munki.recipe: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Description 7 | Download, extract, and import Xcode into Munki. You must override the APPLE_ID and one of PASSWORD or PASSWORD_FILE. 8 | Identifier 9 | com.github.nmcspadden.munki.xcode 10 | Input 11 | 12 | NAME 13 | Xcode 14 | USE_VERSIONED_FILENAME 15 | 16 | FILENAME_SUFFIX 17 | 18 | MUNKI_REPO_SUBDIR 19 | apps/apple/xcode/ 20 | ICON_NAME 21 | Xcode.png 22 | pkginfo 23 | 24 | catalogs 25 | 26 | testing 27 | 28 | description 29 | Xcode 30 | display_name 31 | %NAME% 32 | name 33 | %NAME% 34 | postinstall_script 35 | #!/bin/sh 36 | # Ensure everyone is a member of "developer" group 37 | /usr/sbin/dseditgroup -o edit -a everyone -t group _developer 38 | # Enable Developer Mode 39 | /usr/sbin/DevToolsSecurity -enable 40 | # Accept the license 41 | /Applications/%fixed_filename%/Contents/Developer/usr/bin/xcodebuild -license accept 42 | # Install embedded packages 43 | for PKG in `/bin/ls /Applications/%fixed_filename%/Contents/Resources/Packages/*.pkg` ; do 44 | /usr/sbin/installer -pkg "$PKG" -target / 45 | done 46 | 47 | unattended_install 48 | 49 | 50 | 51 | MinimumVersion 52 | 1.0.4 53 | ParentRecipe 54 | com.github.nmcspadden.extract.xcode 55 | Process 56 | 57 | 58 | Comment 59 | Generate filename based on input variables 60 | Processor 61 | XcodeFileNamer 62 | Arguments 63 | 64 | should_produce_versioned_name 65 | %USE_VERSIONED_FILENAME% 66 | suffix 67 | %FILENAME_SUFFIX% 68 | 69 | 70 | 71 | Processor 72 | FileMover 73 | Arguments 74 | 75 | source 76 | %found_filename% 77 | target 78 | %RECIPE_CACHE_DIR%/%NAME%_unpack/%xcode_filename%.app 79 | 80 | 81 | 82 | Processor 83 | DmgCreator 84 | Arguments 85 | 86 | dmg_root 87 | %RECIPE_CACHE_DIR%/%NAME%_unpack/%xcode_filename%.app 88 | dmg_path 89 | %RECIPE_CACHE_DIR%/%NAME%.dmg 90 | 91 | 92 | 93 | Processor 94 | MunkiPkginfoMerger 95 | Arguments 96 | 97 | additional_pkginfo 98 | 99 | display_name 100 | Xcode %major_version%.%minor_version%.%patch_version% (%build_version%) %BETA% 101 | icon_name 102 | %ICON_NAME% 103 | version 104 | %major_version%.%minor_version%.%patch_version%.%bundle_version% 105 | 106 | 107 | 108 | 109 | Arguments 110 | 111 | pkg_path 112 | %RECIPE_CACHE_DIR%/%NAME%.dmg 113 | repo_subdirectory 114 | %MUNKI_REPO_SUBDIR% 115 | 116 | Processor 117 | MunkiImporter 118 | 119 | 120 | 121 | 122 | -------------------------------------------------------------------------------- /Shared_Processors/README.md: -------------------------------------------------------------------------------- 1 | # Shared Processors 2 | 3 | ## FileAppender 4 | 5 | This processor will simply append a string on to the end of a file. This is useful if an AutoPkg recipe needs to add more variables or other data into a file that already exists (as part of a download, or something created from a previous FileCreator processor). 6 | 7 | ### Example Usage: 8 | ``` 9 | 10 | Processor 11 | com.github.nmcspadden.shared/FileAppender 12 | Arguments 13 | 14 | file_path 15 | %pkgroot%/attributes/default.rb 16 | file_content 17 | this_will_be_added_to_the_end 18 | 19 | 20 | ``` 21 | 22 | ## PackageInfoVersioner 23 | 24 | This processor provides a way to get a version number from the PackageInfo file inside a distribution/bundle style package. This processor specifically looks for the "pkg-info" XML tag inside the PackageInfo file and uses that as the version. This is helpful for bundle packages that provide multiple components with unique / differing version numbers, and there's no single item you can reliably use for versioning. 25 | 26 | The simplest usage is to use something like FileFinder to locate the PackageInfo file inside the bundle package you've downloaded or unarchived and then call this processor. 27 | 28 | ### Example Usage: 29 | ``` 30 | 31 | Processor 32 | com.github.nmcspadden.shared/PackageInfoVersioner 33 | Arguments 34 | 35 | package_info_path 36 | %found_filename%/PackageInfo 37 | 38 | 39 | ``` 40 | 41 | ## Rsync 42 | 43 | This processor calls out to a locally installed rsync (defaults to `/usr/bin/rsync`) to rsync between a source and destination. You can specify a path to a specific rsync binary if needed. 44 | 45 | Arguments can be passed in, and the string provided to the "rsync_arguments" processor input variable will be passed directly into the subprocess call to rsync. See the rsync man page for acceptable arguments. *NOTE: The leading hyphens before your arguments are required!* 46 | 47 | Please note that we have so far only used this for local source -> destination copying, and have not tested a very wide a variety of rsync arguments - so there may be some things that get passed in that don't behave properly in this context. If you do find some arguments that cause problems, please let us know! 48 | 49 | ### Example Usage: 50 | ``` 51 | 52 | Processor 53 | com.github.nmcspadden.shared/Rsync 54 | Arguments 55 | 56 | source_path 57 | %RECIPE_CACHE_DIR%/unpack/folder 58 | destination_path 59 | %pkgroot%/merged_folder 60 | rsync_arguments 61 | -Phav 62 | 63 | 64 | ``` 65 | 66 | ## SHAChecksum 67 | 68 | This processors calls out to `/usr/bin/shasum` to calculate a checksum on a file. You can specify the SHA type (to be passed to the `-a` argument) as an input variable. 69 | 70 | ### Example Usage: 71 | This example will calculate the SHA-256 sum: 72 | 73 | ``` 74 | 75 | Processor 76 | com.github.nmcspadden.shared/SHAChecksum 77 | Comment 78 | Calculate SHA256 checksum 79 | Arguments 80 | 81 | source_file 82 | %RECIPE_CACHE_DIR%/%NAME%-%version%.pkg 83 | checksum_type 84 | 256 85 | 86 | 87 | ``` 88 | 89 | ## SubDirectoryList 90 | This is a more complex processor with more specific usage. For a given root path, this processor will walk through and create two lists: one for all files found relative to the root path, and one for all directories found relative to the root path. 91 | 92 | Both of these lists are stored as strings, with each item separated by the contents of the "suffix_string" input variable (which defaults to "," comma). 93 | 94 | This doesn't have too much use in most AutoPkg recipes, but is the foundational key for translating packages into other management suites that require the pre-creation of subdirectories before placing files on the disk. 95 | 96 | ### Example Usage: 97 | Here's a simple example for how to get the list of contents inside an unpacked package - such as the Munki app package. 98 | 99 | ``` 100 | 101 | Processor 102 | com.github.nmcspadden.shared/SubDirectoryList 103 | Comment 104 | MUNKI ADMIN - get list of folder contents 105 | Arguments 106 | 107 | root_path 108 | %pkgroot%/files/default/munki/admin/%version%/ 109 | 110 | 111 | ``` 112 | The resulting `%found_directories%` will contain a list of all folders that are inside this root path, and the `%found_files%` will contain a list of all files that were found. 113 | 114 | This could be useful for recipes that convert packages into Puppet or Chef recipes, which may require directories to be created on disk prior to files being placed there. 115 | -------------------------------------------------------------------------------- /android_sdk/AndroidXMLParser.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) Facebook, Inc. and its affiliates. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | 18 | """See docstring for AndroidXMLParser class.""" 19 | 20 | # Disabling warnings for env members and imports that only affect recipe- 21 | # specific processors. 22 | # pylint: disable=e1101,f0401 23 | 24 | from __future__ import absolute_import 25 | 26 | import urllib2 27 | import xml.etree.cElementTree as ET 28 | 29 | from autopkglib import Processor, ProcessorError 30 | 31 | __all__ = ["AndroidXMLParser"] 32 | 33 | 34 | class AndroidXMLParser(Processor): 35 | # pylint: disable=missing-docstring 36 | description = "Parse the provided XML file for a variable match." 37 | input_variables = { 38 | "xml_file": {"required": True, "description": "Path or URL to XML file."}, 39 | "namespace": { 40 | "required": True, 41 | "description": "Namespace to search for to find a tag inside.", 42 | }, 43 | "tags": { 44 | "required": True, 45 | "description": ( 46 | "Dictionary of tags to search for, and variables to " 47 | "name them - {'vendor-display': 'VendorDisplay'" 48 | ), 49 | }, 50 | } 51 | output_variables = { 52 | "xml_output_variables": { 53 | "description": ( 54 | "Output variables per 'tags' supplied as input. Note " 55 | "that this output variable is used as both a " 56 | "placeholder for documentation and for auditing " 57 | "purposes. One should use the actual named output " 58 | "variables as given as values to 'plist_keys' to refer" 59 | "to the output of this processor." 60 | ) 61 | } 62 | } 63 | 64 | __doc__ = description 65 | 66 | def main(self): 67 | if "http" in self.env["xml_file"]: 68 | try: 69 | tree = ET.ElementTree(file=urllib2.urlopen(self.env["xml_file"])) 70 | except urllib2.URLError as err: 71 | raise ProcessorError(err) 72 | else: 73 | try: 74 | tree = ET.ElementTree(file=self.env["xml_file"]) 75 | except IOError as err: 76 | raise ProcessorError(err) 77 | root = tree.getroot() 78 | schema = root.tag.split("}")[0] + "}" 79 | match = root.findall("%s%s" % (schema, self.env["namespace"])) 80 | for key, outputVar in self.env["tags"].iteritems(): 81 | for item in match[-1]: 82 | if item.tag.replace(schema, "") == key: 83 | self.env[outputVar] = item.text 84 | self.output("Found %s as %s" % (key, self.env[outputVar])) 85 | break 86 | if key == "uses-license" and ("license" in self.env["tags"].keys()): 87 | # Special case since the license isn't a traditional key 88 | license_ref = item.attrib["ref"] 89 | self.output("Found license ref: %s" % license_ref) 90 | self.env[outputVar] = license_ref 91 | self.env[self.env["tags"]["license"]] = ( 92 | root[0].text.encode("ascii", "ignore").encode("string-escape") 93 | ) 94 | if key == "url": 95 | # It's easy to find the URL here, the structure is always the same 96 | archives = "%sarchives" % schema 97 | archive = "%sarchive" % schema 98 | url = "%surl" % schema 99 | # Look for a host os 100 | host_os = "%shost-os" % schema 101 | archive_list = match[-1].find(archives).findall(archive) 102 | for arch in archive_list: 103 | if arch.find(host_os) is not None: 104 | # If there's a "host-os" in the archive 105 | if "macosx" in arch.find(host_os).text: 106 | # Look for a Mac version 107 | self.env[outputVar] = arch.find(url).text.encode( 108 | "ascii", "ignore" 109 | ) 110 | # self.output("Found %s as %s" % (key, self.env[outputVar])) 111 | break 112 | else: 113 | # No host os was provided, so assume they're not platform specific 114 | # So we return the first item 115 | self.env[outputVar] = ( 116 | match[-1].find(archives).find(archive).find(url).text 117 | ) 118 | self.output("Found: %s" % self.env[outputVar]) 119 | 120 | 121 | if __name__ == "__main__": 122 | PROCESSOR = AndroidXMLParser() 123 | PROCESSOR.execute_shell() 124 | -------------------------------------------------------------------------------- /Xcode/XcodeVersionedName.munki.recipe: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Copyright 6 | Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved 7 | Description 8 | Download, extract, and import Xcode as a unique entry into Munki. You must override the APPLE_ID and one of PASSWORD or PASSWORD_FILE. 9 | Identifier 10 | com.github.nmcspadden.munki.xcode_versioned 11 | Input 12 | 13 | APPLE_ID 14 | dev@domain.com 15 | DESTINATION_APP_NAME 16 | Xcode.app 17 | ICON_NAME 18 | Xcode.png 19 | MUNKI_REPO_SUBDIR 20 | apps/apple/xcode/ 21 | NAME 22 | Xcode 23 | 24 | ARBITRARY_SUFFIX 25 | 26 | pkginfo 27 | 28 | catalogs 29 | 30 | testing 31 | 32 | description 33 | Xcode 34 | display_name 35 | %NAME% 36 | name 37 | %NAME% 38 | unattended_install 39 | 40 | 41 | 42 | MinimumVersion 43 | 1.0.4 44 | ParentRecipe 45 | com.github.nmcspadden.extract.xcode 46 | Process 47 | 48 | 49 | Arguments 50 | 51 | version 52 | %version% 53 | 54 | Processor 55 | XcodeVersioner 56 | 57 | 58 | Arguments 59 | 60 | source 61 | %found_filename% 62 | target 63 | %RECIPE_CACHE_DIR%/%NAME%_%major_version%.%minor_version%.%patch_version%%ARBITRARY_SUFFIX%.app 64 | 65 | Processor 66 | FileMover 67 | 68 | 69 | Arguments 70 | 71 | dmg_path 72 | %RECIPE_CACHE_DIR%/%NAME%_%major_version%.%minor_version%.%patch_version%.dmg 73 | dmg_root 74 | %RECIPE_CACHE_DIR%/%NAME%_%major_version%.%minor_version%.%patch_version%%ARBITRARY_SUFFIX%.app 75 | 76 | Processor 77 | DmgCreator 78 | 79 | 80 | Arguments 81 | 82 | additional_pkginfo 83 | 84 | display_name 85 | %NAME% %major_version%.%minor_version%.%patch_version% 86 | icon_name 87 | %ICON_NAME% 88 | name 89 | %NAME%%major_version% 90 | version 91 | %major_version%.%minor_version%.%patch_version% 92 | 93 | 94 | Processor 95 | MunkiPkginfoMerger 96 | 97 | 98 | Arguments 99 | 100 | pkg_path 101 | %RECIPE_CACHE_DIR%/%NAME%_%major_version%.%minor_version%.%patch_version%.dmg 102 | repo_subdirectory 103 | %MUNKI_REPO_SUBDIR% 104 | 105 | Processor 106 | MunkiImporter 107 | 108 | 109 | Arguments 110 | 111 | path_list 112 | 113 | %RECIPE_CACHE_DIR%/%NAME%_unpack 114 | %RECIPE_CACHE_DIR%/%NAME%_%major_version%.%minor_version%.%patch_version%%ARBITRARY_SUFFIX%.app 115 | 116 | 117 | Processor 118 | PathDeleter 119 | 120 | 121 | 122 | 123 | -------------------------------------------------------------------------------- /LegacyRecipes/GoogleEarthPro/GoogleEarthPro.munki.recipe: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Description 6 | Downloads latest Google Earth Pro disk image and imports into Munki. 7 | 8 | Set the DERIVE_MIN_OS variable to a non-empty string to set the minimum_os_version via MunkiInstallsItemsCreator. This requires a minimum AutoPkg version of 2.7 please update if you're not already running it. 9 | Identifier 10 | com.github.nmcspadden-recipes.munki.google-earth-pro 11 | Input 12 | 13 | DERIVE_MIN_OS 14 | YES 15 | NAME 16 | GoogleEarthPro 17 | MUNKI_REPO_SUBDIR 18 | apps 19 | pkginfo 20 | 21 | catalogs 22 | 23 | testing 24 | 25 | description 26 | Take a virtual journey to any location in the world. Explore 3D buildings, imagery, and terrain. Find cities, places and local businesses. 27 | display_name 28 | Google Earth Pro 29 | name 30 | %NAME% 31 | unattended_install 32 | 33 | 34 | 35 | MinimumVersion 36 | 2.7 37 | ParentRecipe 38 | com.github.nstrauss.download.GoogleEarthPro 39 | Process 40 | 41 | 42 | 43 | Arguments 44 | 45 | pkgroot 46 | %RECIPE_CACHE_DIR%/unpack/root 47 | pkgdirs 48 | 49 | Applications 50 | 0775 51 | Library 52 | 0775 53 | 54 | 55 | Processor 56 | PkgRootCreator 57 | 58 | 59 | 60 | Processor 61 | FlatPkgUnpacker 62 | Arguments 63 | 64 | destination_path 65 | %RECIPE_CACHE_DIR%/expanded 66 | flat_pkg_path 67 | %pathname%/Install Google Earth*.pkg 68 | 69 | 70 | 71 | Processor 72 | PkgPayloadUnpacker 73 | Arguments 74 | 75 | destination_path 76 | %RECIPE_CACHE_DIR%/unpack/root/Applications 77 | pkg_payload_path 78 | %RECIPE_CACHE_DIR%/expanded/Google_Earth_Pro.pkg/Payload 79 | 80 | 81 | 82 | 83 | Processor 84 | Versioner 85 | Arguments 86 | 87 | input_plist_path 88 | %RECIPE_CACHE_DIR%/unpack/root/Applications/Google Earth Pro.app/Contents/Info.plist 89 | plist_version_key 90 | CFBundleVersion 91 | 92 | 93 | 94 | Arguments 95 | 96 | additional_pkginfo 97 | 98 | version 99 | %version% 100 | 101 | 102 | Processor 103 | MunkiPkginfoMerger 104 | 105 | 106 | Processor 107 | MunkiInstallsItemsCreator 108 | Arguments 109 | 110 | faux_root 111 | %RECIPE_CACHE_DIR%/unpack/root 112 | installs_item_paths 113 | 114 | /Applications/Google Earth Pro.app 115 | 116 | version_comparison_key 117 | CFBundleVersion 118 | derive_minimum_os_version 119 | %DERIVE_MIN_OS% 120 | 121 | 122 | 123 | Processor 124 | MunkiPkginfoMerger 125 | 126 | 127 | Arguments 128 | 129 | pkg_path 130 | %pathname% 131 | repo_subdirectory 132 | %MUNKI_REPO_SUBDIR% 133 | 134 | Processor 135 | MunkiImporter 136 | 137 | 138 | Processor 139 | PathDeleter 140 | Arguments 141 | 142 | path_list 143 | 144 | %RECIPE_CACHE_DIR%/unpack 145 | %RECIPE_CACHE_DIR%/expanded 146 | 147 | 148 | 149 | 150 | 151 | 152 | -------------------------------------------------------------------------------- /VMwareFusionDeploy/VMwareFusionDeploy.pkg.recipe: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Copyright 6 | Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved 7 | Description 8 | Creates a VMwareFusion mass deployment package DMG. Requires justinrummel-recipes to download. You can substitute your own deploy.ini file in an override by placing the content in the DEPLOY_INI_FILE input variable. At a minimum, you'll need to put your license key in, or the postflight will fail. 9 | Identifier 10 | com.github.nmcspadden.pkg.deploy.VMwareFusion 11 | Input 12 | 13 | DEPLOY_INI_FILE 14 | [Volume License] 15 | key = XXXXX-XXXXX-XXXXX-XXXXX-XXXXX 16 | 17 | [UI Defaults] 18 | 19 | [Locations] 20 | 21 | [Applications] 22 | 23 | [Virtual Machines] 24 | 25 | NAME 26 | VMwareFusionDeploy 27 | 28 | MinimumVersion 29 | 0.2.5 30 | ParentRecipe 31 | com.justinrummel.download.VMwareFusion 32 | Process 33 | 34 | 35 | Arguments 36 | 37 | archive_format 38 | tar 39 | archive_path 40 | %pathname% 41 | destination_path 42 | %RECIPE_CACHE_DIR%/tar 43 | purge_destination 44 | 45 | 46 | Processor 47 | Unarchiver 48 | 49 | 50 | Arguments 51 | 52 | archive_format 53 | zip 54 | archive_path 55 | %RECIPE_CACHE_DIR%/tar/com.vmware.fusion.zip 56 | destination_path 57 | %RECIPE_CACHE_DIR%/source 58 | purge_destination 59 | 60 | 61 | Processor 62 | Unarchiver 63 | 64 | 65 | Arguments 66 | 67 | info_path 68 | %RECIPE_CACHE_DIR%/source/payload/VMware Fusion.app/Contents/Info.plist 69 | plist_keys 70 | 71 | CFBundleShortVersionString 72 | version 73 | LSMinimumSystemVersion 74 | ls_minimum_system_version 75 | 76 | 77 | Comment 78 | Extract version strings from Info.plist to use for the pkginfo. 79 | Processor 80 | PlistReader 81 | 82 | 83 | Arguments 84 | 85 | pkgdirs 86 | 87 | Applications 88 | 01775 89 | 90 | pkgroot 91 | %RECIPE_CACHE_DIR%/fauxroot 92 | purge_destination 93 | 94 | 95 | Processor 96 | PkgRootCreator 97 | 98 | 99 | Arguments 100 | 101 | source 102 | %RECIPE_CACHE_DIR%/source/payload/VMware Fusion.app 103 | target 104 | %RECIPE_CACHE_DIR%/fauxroot/Applications/VMware Fusion.app 105 | 106 | Processor 107 | FileMover 108 | 109 | 110 | Arguments 111 | 112 | pkgdirs 113 | 114 | pkgroot 115 | %RECIPE_CACHE_DIR%/Deploy VMware Fusion 116 | 117 | Processor 118 | PkgRootCreator 119 | 120 | 121 | Arguments 122 | 123 | source 124 | %RECIPE_CACHE_DIR%/fauxroot/Applications/VMware Fusion.app/Contents/Library/Deploy VMware Fusion.mpkg 125 | target 126 | %pkgroot%/Deploy VMware Fusion.mpkg 127 | 128 | Processor 129 | FileMover 130 | 131 | 132 | Arguments 133 | 134 | faux_root 135 | %RECIPE_CACHE_DIR%/fauxroot 136 | installs_item_paths 137 | 138 | /Applications/VMware Fusion.app 139 | 140 | 141 | Processor 142 | MunkiInstallsItemsCreator 143 | 144 | 145 | Processor 146 | MunkiPkginfoMerger 147 | 148 | 149 | Arguments 150 | 151 | source 152 | %RECIPE_CACHE_DIR%/fauxroot/Applications/VMware Fusion.app 153 | target 154 | %pkgroot%/Deploy VMware Fusion.mpkg/Contents/00Fusion_Deployment_Items/VMware Fusion.app 155 | 156 | Processor 157 | FileMover 158 | 159 | 160 | Arguments 161 | 162 | path_list 163 | 164 | %pkgroot%/Deploy VMware Fusion.mpkg/Contents/00Fusion_Deployment_Items/Deploy.ini 165 | 166 | 167 | Processor 168 | PathDeleter 169 | 170 | 171 | Arguments 172 | 173 | file_content 174 | %DEPLOY_INI_FILE% 175 | file_path 176 | %pkgroot%/Deploy VMware Fusion.mpkg/Contents/00Fusion_Deployment_Items/Deploy.ini 177 | 178 | Processor 179 | FileCreator 180 | 181 | 182 | Arguments 183 | 184 | source 185 | %pkgroot%/Deploy VMware Fusion.mpkg 186 | target 187 | %pkgroot%/%NAME%-%version%.mpkg 188 | 189 | Processor 190 | FileMover 191 | 192 | 193 | 194 | 195 | -------------------------------------------------------------------------------- /Oracle/OracleJava8JDK.munki.recipe: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Description 6 | Downloads latest release version of Oracle Java 8 JDK and imports into a Munki repository. 7 | Identifier 8 | com.github.nmcspadden.munki.OracleJava8JDK 9 | Input 10 | 11 | NAME 12 | OracleJava8JDK 13 | MUNKI_REPO_SUBDIR 14 | utility/Oracle 15 | pkginfo 16 | 17 | catalogs 18 | 19 | testing 20 | 21 | category 22 | Utility 23 | developer 24 | Oracle 25 | description 26 | The JDK is a development environment for building applications, applets, and components using the Java programming language. The JDK includes tools useful for developing and testing programs written in the Java programming language and running on the Java platform. 27 | display_name 28 | Oracle Java 8 development kit 29 | minimum_os_version 30 | 10.7.4 31 | name 32 | %NAME% 33 | unattended_install 34 | 35 | unattended_uninstall 36 | 37 | supported_architectures 38 | 39 | i386 40 | x86_64 41 | 42 | 43 | 44 | MinimumVersion 45 | 0.2.0 46 | ParentRecipe 47 | com.github.hansen-m.download.OracleJava8JDK 48 | Process 49 | 50 | 51 | Processor 52 | PkgRootCreator 53 | Arguments 54 | 55 | pkgroot 56 | %RECIPE_CACHE_DIR%/fauxroot 57 | pkgdirs 58 | 59 | Library 60 | 0755 61 | Library/Java 62 | 0755 63 | Library/Java/JavaVirtualMachines 64 | 0755 65 | 66 | 67 | 68 | 69 | Processor 70 | FlatPkgUnpacker 71 | Arguments 72 | 73 | flat_pkg_path 74 | %pathname%/*.pkg 75 | destination_path 76 | %RECIPE_CACHE_DIR%/unpack 77 | 78 | 79 | 80 | Processor 81 | FileFinder 82 | Arguments 83 | 84 | pattern 85 | %RECIPE_CACHE_DIR%/unpack/jdk*.pkg/Payload 86 | 87 | 88 | 89 | Processor 90 | PkgPayloadUnpacker 91 | Arguments 92 | 93 | pkg_payload_path 94 | %found_filename% 95 | destination_path 96 | %RECIPE_CACHE_DIR%/jdk 97 | purge_destination 98 | 99 | 100 | 101 | 102 | Processor 103 | PlistReader 104 | Arguments 105 | 106 | info_path 107 | %RECIPE_CACHE_DIR%/jdk/Contents/Info.plist 108 | plist_keys 109 | 110 | CFBundleVersion 111 | version 112 | 113 | 114 | 115 | 116 | Processor 117 | FileMover 118 | Arguments 119 | 120 | source 121 | %RECIPE_CACHE_DIR%/jdk 122 | target 123 | %pkgroot%/Library/Java/JavaVirtualMachines/jdk%version%.jdk 124 | 125 | 126 | 127 | Processor 128 | MunkiInstallsItemsCreator 129 | Arguments 130 | 131 | faux_root 132 | %pkgroot% 133 | installs_item_paths 134 | 135 | /Library/Java/JavaVirtualMachines/jdk%version%.jdk 136 | 137 | version_comparison_key 138 | CFBundleVersion 139 | 140 | 141 | 142 | Processor 143 | MunkiPkginfoMerger 144 | Arguments 145 | 146 | 147 | 148 | Arguments 149 | 150 | pkg_path 151 | %pathname% 152 | repo_subdirectory 153 | %MUNKI_REPO_SUBDIR% 154 | additional_makepkginfo_options 155 | 156 | --pkgvers=%version% 157 | 158 | 159 | Processor 160 | MunkiImporter 161 | 162 | 163 | 164 | 165 | --------------------------------------------------------------------------------