├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── dsc.html.md ├── examples ├── README.md ├── Vagrantfile ├── amz.userdata ├── manifests │ ├── Beanstalk.ps1 │ ├── BeanstalkConfig.psd1 │ └── manifests │ │ ├── Beanstalk.ps1 │ │ └── BeanstalkConfig.psd1 ├── modules │ └── BaseBeanstalkApp │ │ ├── BaseBeanstalkApp.psd1 │ │ └── DSCResources │ │ └── BeanstalkWebsite │ │ ├── BeanstalkWebsite.psd1 │ │ └── BeanstalkWebsite.schema.psm1 ├── packer.aws.json ├── packer.ovf.json ├── resources │ └── cSelfSignedCert │ │ ├── DSCResources │ │ └── cSelfSignedCert │ │ │ ├── cSelfSignedCert.psm1 │ │ │ └── cSelfSignedCert.schema.mof │ │ └── cSelfSignedCert.psd1 └── scripts │ ├── BundleConfig.ps1 │ ├── EC2Config.ps1 │ └── run-dsc.ps1 ├── go.mod ├── go.sum ├── plugin └── provisioner-dsc │ └── main.go ├── provisioner └── dsc │ ├── config.go │ ├── config.hcl2spec.go │ ├── config_test.go │ ├── provisioner.go │ └── provisioner_test.go ├── scripts ├── build.sh ├── packer-provisioner-dsc.rb └── test.sh ├── vendor.yml └── wercker.yml /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | *.test 24 | *.prof 25 | pkg 26 | bin 27 | *.cov 28 | *.log 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Matt Fellows 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | TEST?=./... 2 | 3 | default: test 4 | 5 | bin: 6 | @sh -c "$(CURDIR)/scripts/build.sh" 7 | 8 | dev: 9 | @TF_DEV=1 sh -c "$(CURDIR)/scripts/build.sh" 10 | 11 | test: 12 | @sh -c "$(CURDIR)/scripts/test.sh" 13 | 14 | testrace: 15 | go test -race $(TEST) $(TESTARGS) 16 | 17 | updatedeps: 18 | go get -d -v -p 2 ./... 19 | 20 | .PHONY: bin default dev test updatedeps 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Packer DSC Provisioner 2 | 3 | A [Desired State Configuration](http://technet.microsoft.com/en-au/library/dn249912.aspx) provisioner for [Packer.io](http://packer.io), the machine image automation tool, allowing you to automate the generation of your Windows machine images in a repeatable, reliable way. 4 | 5 | Works nicely when combined with a Vagrant development workflow, possibly leveraging the [Vagrant DSC](https://github.com/mefellows/vagrant-dsc) plugin. 6 | 7 | Features: 8 | * Automatically run DSC on a remote machine, from local DSC Configurations. 9 | * Automatically configure PowerShell Package Management (specify `install_package_management` as `true`) 10 | * Install DSC Resources from local or remote sources, including the PowerShell Gallery (see `resource_paths` and `install_modules`) 11 | * Ability to use pre-generated MOF files, if required 12 | 13 | [![Coverage Status](https://coveralls.io/repos/github/mefellows/packer-dsc/badge.svg?branch=HEAD)](https://coveralls.io/github/mefellows/packer-dsc?branch=HEAD) 14 | [![wercker status](https://app.wercker.com/status/ef7336f65a3636531141a653e775d58f/s "wercker status")](https://app.wercker.com/project/bykey/ef7336f65a3636531141a653e775d58f) 15 | 16 | ### Getting Started 17 | 18 | The plugin can be used by downloading the pre-built binary, or by building the project locally and ensuring the binary is installed in the correct location. 19 | 20 | ### On Mac OSX using Homebrew 21 | 22 | If you are using [Homebrew](http://brew.sh) you can follow these steps to install the plugins: 23 | 24 | ``` 25 | brew install https://raw.githubusercontent.com/mefellows/packer-dsc/master/scripts/packer-provisioner-dsc.rb 26 | ``` 27 | 28 | ### Using pre-built binaries 29 | 30 | 1. Install Packer 31 | 1. Download the latest [release](https://github.com/mefellows/packer-dsc/releases) for your host environment 32 | 1. Unzip the plugin binaries to [a location where Packer will detect them at run-time](https://packer.io/docs/extend/plugins.html), such as any of the following: 33 | - The directory where the packer binary is. 34 | - `~/.packer.d/plugins` on Unix systems or `%APPDATA%/packer.d/plugins` on Windows. 35 | - The current working directory. 36 | 1. Change to a directory where you have packer templates, and run as usual. 37 | 38 | ### Using a local build 39 | 40 | With [Go 1.2+](http://golang.org) installed, follow these steps to use these community plugins for Windows: 41 | 42 | 1. Install packer 43 | 1. Clone this repo 44 | 1. Run `make dev` 45 | 1. Copy the plugin binaries located in `./bin` to [a location where Packer will detect them at run-time](https://packer.io/docs/extend/plugins.html), such as any of the following: 46 | - The directory where the packer binary is. If you've built Packer locally, then Packer and the new plugins are already in `$GOPATH/bin` together. 47 | - `~/.packer.d/plugins` on Unix systems or `%APPDATA%/packer.d/plugins` on Windows. 48 | - The current working directory. 49 | 1. Change to a directory where you have packer templates, and run as usual. 50 | 51 | # Introduction 52 | 53 | Type: `dsc` 54 | 55 | DSC Packer provisioner configures DSC to run on the 56 | machines by Packer from local modules and manifest files. Modules and manifests 57 | can be uploaded from your local machine to the remote machine. 58 | 59 | -> **Note:** DSC will *not* be installed automatically by this 60 | provisioner. This provisioner expects that DSC is already [installed](https://www.penflip.com/powershellorg/the-dsc-book/blob/master/dsc-overview-and-requirements.txt) on the 61 | machine. It is common practice to use the [powershell 62 | provisioner](/docs/provisioners/powershell.html) before the DSC provisioner to install WMF4.0+, any 63 | required DSC Resources or connection to a DSC Pull server. 64 | 65 | ## Basic Example 66 | 67 | The example below is fully functional and expects the configured manifest file 68 | to exist relative to your working directory: 69 | 70 | ``` {.javascript} 71 | { 72 | "type": "dsc", 73 | "manifest_file": "manifests/Beanstalk.ps1", 74 | "configuration_file": "manifests/BeanstalkConfig.psd1", 75 | "configuration_params": { 76 | "-WebAppPath": "c:\\tmp", 77 | "-MachineName": "localhost" 78 | } 79 | } 80 | ``` 81 | 82 | ## Configuration Reference 83 | 84 | The reference of available configuration options is listed below. 85 | 86 | Required parameters: 87 | 88 | - `manifest_file` (string) - The main DSC manifest file to apply to kick off the entire thing. 89 | 90 | Optional parameters: 91 | 92 | - `configuration_name` (string) - The name of the Configuration module. Defaults to the base 93 | name of the `manifest_file`. e.g. `Default.ps1` would result in `Default`. 94 | 95 | - `mof_path` (string) - Relative path to a folder, containing the pre-generated MOF file. 96 | 97 | - `configuration_file` (string) - Relative path to the DSC Configuration Data file. 98 | Configuration data is used to parameterise the configuration_file. 99 | 100 | - `configuration_params` (object of key/value strings) - Set of Parameters to pass to the DSC 101 | Configuration. 102 | 103 | - `module_paths` (array of strings) - Set of relative module paths. 104 | These paths are added to the DSC Configuration running environment to enable _local_ modules to be addressed. 105 | 106 | - `resource_paths` (array of strings) - Set of DSC Resources to upload for system-wide use. 107 | These paths are uploaded into `${env:programfiles}\WindowsPowershell\Modules` to be used system-wide, unlike 108 | `module_paths` which is scoped to the current Configuration. 109 | 110 | - `install_modules` (array of strings) - Set of PowerShell modules to be installed 111 | with the `Install-Module` command. See `install_package_management` if you would 112 | like the DSC Provisioner to install this command for you. 113 | 114 | - `install_package_management` (bool) - Automatically installs the 115 | [Package Management](https://github.com/OneGet/oneget) package manager 116 | (formerly OneGet) on the server. 117 | 118 | - `staging_dir` (string) - The directory where files will be uploaded. 119 | Packer requires write permissions in this directory. 120 | 121 | - `clean_staging_dir` (bool) - If true, staging directory is removed after executing DSC. 122 | 123 | - `working_dir` (string) - The directory from which the command will be executed. 124 | Packer requires the directory to exist when running DSC. 125 | 126 | - `ignore_exit_codes` (boolean) - If true, Packer will never consider the 127 | DSC provisioning process a failure. 128 | 129 | - `execute_command` (string) - The command used to execute DSC. This has 130 | various [configuration template 131 | variables](/docs/templates/configuration-templates.html) available. See 132 | below for more information. 133 | 134 | ## Execute Command 135 | 136 | By default, Packer uses the following command to execute DSC: 137 | 138 | ``` 139 | {{if ne .ModulePath ""}} 140 | $absoluteModulePaths = [string]::Join(";", ("{{.ModulePath}}".Split(";") | ForEach-Object { $_ | Resolve-Path })) 141 | echo "Adding to path: $absoluteModulePaths" 142 | $env:PSModulePath="$absoluteModulePaths;${env:PSModulePath}" 143 | ("{{.ModulePath}}".Split(";") | ForEach-Object { gci -Recurse $_ | ForEach-Object { Unblock-File $_.FullName} }) 144 | {{end}} 145 | 146 | $script = $("{{.ManifestFile}}" | Resolve-Path) 147 | echo "PSModulePath Configured: ${env:PSModulePath}" 148 | echo "Running Configuration file: ${script}" 149 | 150 | {{if eq .MofPath ""}} 151 | # Generate the MOF file, only if a MOF path not already provided. 152 | # Import the Manifest 153 | . $script 154 | 155 | cd "{{.WorkingDir}}" 156 | $StagingPath = $(Join-Path "{{.WorkingDir}}" "staging") 157 | {{if ne .ConfigurationFilePath ""}} 158 | $Config = $(iex (Get-Content ("{{.WorkingDir}}" "{{.ConfigurationFilePath}}" | Resolve-Path) | Out-String)) 159 | {{end}} 160 | {{.ConfigurationName}} -OutputPath $StagingPath {{.ConfigurationParams}}{{if ne .ConfigurationFilePath ""}} -ConfigurationData $Config{{end}} 161 | {{else}} 162 | $StagingPath = "{{.MofPath}}" 163 | {{end}} 164 | 165 | # Start a DSC Configuration run 166 | Start-DscConfiguration -Force -Wait -Verbose -Path $StagingPath` 167 | ``` 168 | 169 | This command can be customized using the `execute_command` configuration. As you 170 | can see from the default value above, the value of this configuration can 171 | contain various template variables, defined below: 172 | 173 | - `WorkingDir` - The path from which DSC will be executed. 174 | - `ConfigurationParams` - Arguments to the DSC Configuration in k/v pairs. 175 | - `ConfigurationFilePath` - The path to a DSC Configuration File, if any. 176 | - `ConfigurationName` - The name of the DSC Configuration to run. 177 | - `ManifestFile` - The path on the remote machine to the manifest file for 178 | DSC to use. 179 | - `ModulePath` - The path to a directory on the remote machine containing the manifest files. 180 | - `MofPath` - The path to a directory containing any existing MOF file(s) to use. 181 | 182 | ## Examples 183 | 184 | See the [Examples](examples) directory. 185 | -------------------------------------------------------------------------------- /dsc.html.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: | 3 | DSC (local) Packer provisioner configures DSC to run on the 4 | machines by Packer from local modules and manifest files. Modules and manifests 5 | can be uploaded from your local machine to the remote machine. 6 | layout: docs 7 | page_title: 'DSC (Local) Provisioner' 8 | ... 9 | 10 | # DSC Provisioner 11 | 12 | Type: `dsc` 13 | 14 | DSC Packer provisioner configures DSC to run on the 15 | machines by Packer from local modules and manifest files. Modules and manifests 16 | can be uploaded from your local machine to the remote machine. 17 | 18 | -> **Note:** DSC will *not* be installed automatically by this 19 | provisioner. This provisioner expects that DSC is already [installed](https://www.penflip.com/powershellorg/the-dsc-book/blob/master/dsc-overview-and-requirements.txt) on the 20 | machine. It is common practice to use the [powershell 21 | provisioner](/docs/provisioners/powershell.html) before the DSC provisioner to install WMF4.0+, any 22 | required DSC Resources or connection to a DSC Pull server. 23 | 24 | ## Basic Example 25 | 26 | The example below is fully functional and expects the configured manifest file 27 | to exist relative to your working directory: 28 | 29 | ``` {.javascript} 30 | { 31 | "type": "dsc", 32 | "manifest_file": "manifests/Beanstalk.ps1", 33 | "configuration_file": "manifests/BeanstalkConfig.psd1", 34 | "configuration_params": { 35 | "-WebAppPath": "c:\\tmp", 36 | "-MachineName": "localhost" 37 | } 38 | } 39 | ``` 40 | 41 | ## Configuration Reference 42 | 43 | The reference of available configuration options is listed below. 44 | 45 | Required parameters: 46 | 47 | - `manifest_file` (string) - The main DSC manifest file to apply to kick off the entire thing. 48 | 49 | Optional parameters: 50 | 51 | - `configuration_name` (string) - The name of the Configuration module. Defaults to the base name of 52 | the `manifest_file`. e.g. `Default.ps1` would result in `Default`. 53 | 54 | - `mof_path` (string) - Relative path to a folder, containing the pre-generated MOF file. 55 | 56 | - `configuration_file` (string) - Relative path to the DSC Configuration Data file. 57 | Configuration data is used to parameterise the configuration_file. 58 | 59 | - `configuration_params` (object of key/value strings) - Set of Parameters to pass to the DSC Configuration. 60 | 61 | - `module_paths` (array of strings) - Set of relative module paths. 62 | These paths are added to the DSC Configuration running environment to enable local modules to be addressed. 63 | 64 | 65 | - `resource_paths` (array of strings) - Set of DSC Resources to upload for system-wide use. 66 | These paths are uploaded into `%SystemDrive%\WindowsPowershell\Modules` to be used system-wide, unlike 67 | `module_paths` which is scoped to the current Configuration. 68 | 69 | `install_modules` (array of strings) - Set of PowerShell modules to be installed 70 | with the `Install-Module` command. See `install_package_management` if you would 71 | like the DSC Provisioner to install this command for you. 72 | 73 | `install_package_management` (bool) - Automatically installs the 74 | [Package Management](https://github.com/OneGet/oneget) package manager 75 | (formerly OneGet) on the server. 76 | 77 | - `staging_dir` (string) - The directory where files will be uploaded. 78 | Packer requires write permissions in this directory. 79 | 80 | - `clean_staging_dir` (bool) - If true, staging directory is removed after executing DSC. 81 | 82 | - `working_dir` (string) - The directory from which the command will be executed. 83 | Packer requires the directory to exist when running DSC. 84 | 85 | - `ignore_exit_codes` (boolean) - If true, Packer will never consider the 86 | DSC provisioning a failure. 87 | 88 | - `execute_command` (string) - The command used to execute DSC. This has 89 | various [configuration template 90 | variables](/docs/templates/configuration-templates.html) available. See 91 | below for more information. 92 | 93 | ## Execute Command 94 | 95 | By default, Packer uses the following command to execute DSC: 96 | 97 | ``` 98 | {{if ne .ModulePath ""}} 99 | $absoluteModulePaths = [string]::Join(";", ("{{.ModulePath}}".Split(";") | ForEach-Object { $_ | Resolve-Path })) 100 | echo "Adding to path: $absoluteModulePaths" 101 | $env:PSModulePath="$absoluteModulePaths;${env:PSModulePath}" 102 | ("{{.ModulePath}}".Split(";") | ForEach-Object { gci -Recurse $_ | ForEach-Object { Unblock-File $_.FullName} }) 103 | {{end}} 104 | 105 | $script = $("{{.ManifestFile}}" | Resolve-Path) 106 | echo "PSModulePath Configured: ${env:PSModulePath}" 107 | echo "Running Configuration file: ${script}" 108 | 109 | {{if eq .MofPath ""}} 110 | # Generate the MOF file, only if a MOF path not already provided. 111 | # Import the Manifest 112 | . $script 113 | 114 | cd "{{.WorkingDir}}" 115 | $StagingPath = $(Join-Path "{{.WorkingDir}}" "staging") 116 | {{if ne .ConfigurationFilePath ""}} 117 | $Config = $(iex (Get-Content ("{{.WorkingDir}}" "{{.ConfigurationFilePath}}" | Resolve-Path) | Out-String)) 118 | {{end}} 119 | {{.ConfigurationName}} -OutputPath $StagingPath {{.ConfigurationParams}}{{if ne .ConfigurationFilePath ""}} -ConfigurationData $Config{{end}} 120 | {{else}} 121 | $StagingPath = "{{.MofPath}}" 122 | {{end}} 123 | 124 | # Start a DSC Configuration run 125 | Start-DscConfiguration -Force -Wait -Verbose -Path $StagingPath` 126 | ``` 127 | 128 | This command can be customized using the `execute_command` configuration. As you 129 | can see from the default value above, the value of this configuration can 130 | contain various template variables, defined below: 131 | 132 | - `WorkingDir` - The path from which DSC will be executed. 133 | - `ConfigurationParams` - Arguments to the DSC Configuration in k/v pairs. 134 | - `ConfigurationFilePath` - The path to a DSC Configuration File, if any. 135 | - `ConfigurationName` - The name of the DSC Configuration to run. 136 | - `ManifestFile` - The path on the remote machine to the manifest file for 137 | DSC to use. 138 | - `ModulePath` - The path to a directory on the remote machine containing the manifest files. 139 | - `MofPath` - The path to a directory containing any existing MOF file(s) to use. 140 | - 141 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | # Packer DSC Provisioner Examples 2 | 3 | ## AWS AMI 4 | 5 | Update the vars as required: 6 | 7 | ``` 8 | cd examples 9 | PACKER_LOG=1 PACKER_LOG_PATH=packer.log packer build \ 10 | -var source_ami=ami-75ebe61f \ 11 | -var subnet_id=subnet-7ed32427 \ 12 | -var vpc_id=vpc-89388dec \ 13 | -var region=us-east-1 \ 14 | ./packer.aws.json 15 | ``` 16 | 17 | ## Virtualbox OVF 18 | Update the path below to an existing OVF file: 19 | 20 | ``` 21 | cd examples 22 | PACKER_LOG=1 PACKER_LOG_PATH=packer.log packer build \ 23 | -debug \ 24 | -var ovf_source_path=/Users/mfellows/Downloads/output-virtualbox-iso/packer-virtualbox-iso-1417096689.ovf \ 25 | ./packer.json 26 | ``` 27 | -------------------------------------------------------------------------------- /examples/Vagrantfile: -------------------------------------------------------------------------------- 1 | # -*- mode: ruby -*- 2 | # vi: set ft=ruby : 3 | 4 | # Vagrantfile API/syntax version. Don't touch unless you know what you're doing! 5 | VAGRANTFILE_API_VERSION = "2" 6 | 7 | Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| 8 | # All Vagrant configuration is done here. The most common configuration 9 | # options are documented and commented below. For a complete reference, 10 | # please see the online documentation at vagrantup.com. 11 | 12 | # Every Vagrant virtual environment requires a box to build off of. 13 | config.vm.box = "mfellows/windows2012r2" 14 | hostname = "beanstalk.dev" 15 | ip_address = "10.0.0.30" 16 | 17 | host_port = 5895 18 | config.winrm.host = "localhost" 19 | config.winrm.port = host_port 20 | config.winrm.guest_port = host_port 21 | config.vm.guest = :windows 22 | config.vm.communicator = "winrm" 23 | config.vm.network :forwarded_port, guest: 3389, host: 3399, id: "rdp", auto_correct: false 24 | config.vm.network :forwarded_port, guest: 5985, host: host_port, id: "winrm", auto_correct: false 25 | config.vm.network :forwarded_port, guest: 80, host: 8000, id: "web" # Port forward for IIS 26 | config.vm.network :forwarded_port, guest: 443, host: 8443, id: "ssl" # Port forward for SSL IIS 27 | config.vm.network "private_network", ip: ip_address 28 | 29 | config.vm.provider "virtualbox" do |v| 30 | v.gui = true 31 | end 32 | 33 | if Vagrant.has_plugin?("vagrant-multi-hostsupdater") 34 | config.multihostsupdater.aliases = {ip_address => [hostname]} 35 | end 36 | 37 | # Install prerequisites 38 | config.vm.provision "shell", path: "./scripts/provision.ps1" 39 | 40 | # Run DSC 41 | config.vm.provision "dsc", run: "always" do |dsc| 42 | 43 | # Set of module paths relative to the Vagrantfile dir. 44 | # 45 | # These paths are added to the DSC Configuration running 46 | # environment to enable local modules to be addressed. 47 | # 48 | # @return [Array] Set of relative module paths. 49 | dsc.module_path = ["modules"] 50 | 51 | # The path relative to `dsc.manifests_path` pointing to the Configuration file 52 | dsc.configuration_file = "Beanstalk.ps1" 53 | 54 | # The path relative to Vagrantfile pointing to the Configuration Data file 55 | dsc.configuration_data_file = "manifests/BeanstalkConfig.psd1" 56 | 57 | # The Configuration Command to run. Assumed to be the same as the `dsc.configuration_file` 58 | # (sans extension) if not provided. 59 | dsc.configuration_name = "Beanstalk" 60 | 61 | # Relative path to a pre-generated MOF file. 62 | # 63 | # Path is relative to the folder containing the Vagrantfile. 64 | # dsc.mof_path = "mof" 65 | 66 | # Relative path to the folder containing the root Configuration manifest file. 67 | # Defaults to 'manifests'. 68 | # 69 | # Path is relative to the folder containing the Vagrantfile. 70 | dsc.manifests_path = "manifests" 71 | 72 | # Commandline arguments to the Configuration run 73 | # 74 | # Set of Parameters to pass to the DSC Configuration. 75 | dsc.configuration_params = {"-MachineName" => "localhost", "-WebAppPath" => "c:\\tmp", "-HostName" => hostname} 76 | 77 | # The type of synced folders to use when sharing the data 78 | # required for the provisioner to work properly. 79 | # 80 | # By default this will use the default synced folder type. 81 | # For example, you can set this to "nfs" to use NFS synced folders. 82 | # dsc.synced_folder_type = "" 83 | 84 | # Temporary working directory on the guest machine. 85 | # dsc.temp_dir = "c:/tmp/vagrant-dsc" 86 | end 87 | end 88 | -------------------------------------------------------------------------------- /examples/amz.userdata: -------------------------------------------------------------------------------- 1 | 2 | write-output "Running User Data Script" 3 | write-host "(host) Running User Data Script" 4 | 5 | # Set TZ 6 | write-output "Setting TZ" 7 | cmd.exe /c tzutil /s \"Pacific Standard Time\" 8 | 9 | Set-ExecutionPolicy Unrestricted 10 | 11 | # RDP 12 | write-output "Setting up RDP" 13 | 14 | cmd.exe /c netsh advfirewall firewall add rule name="Open Port 3389" dir=in action=allow protocol=TCP localport=3389 15 | cmd.exe /c reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server" /v fDenyTSConnections /t REG_DWORD /d 0 /f 16 | 17 | # WinRM 18 | write-output "Setting up WinRM" 19 | 20 | &winrm quickconfig `-q 21 | &winrm set winrm/config '@{MaxTimeoutms="1800000"}' 22 | &winrm set winrm/config/winrs '@{MaxMemoryPerShellMB="1024"}' 23 | &winrm set winrm/config/client/auth '@{Basic="true"}' 24 | &winrm set winrm/config/service/auth '@{Basic="true"}' 25 | &winrm set winrm/config/client '@{AllowUnencrypted="true"}' 26 | &winrm set winrm/config/service '@{AllowUnencrypted="true"}' 27 | 28 | # Firewall 29 | write-output "Setting up Firewall" 30 | 31 | cmd.exe /c netsh advfirewall firewall set rule group="remote administration" new enable=yes 32 | cmd.exe /c netsh firewall add portopening TCP 5985 "Port 5985" 33 | 34 | write-output "Finished setting up AMI" 35 | 36 | -------------------------------------------------------------------------------- /examples/manifests/Beanstalk.ps1: -------------------------------------------------------------------------------- 1 | Configuration Beanstalk 2 | { 3 | param ( 4 | [string] $MachineName, 5 | [string] $WebAppPath = "%SystemDrive%\inetpub\wwwroot", 6 | [string] $HostName = "localhost" 7 | ) 8 | 9 | Import-DscResource -Module BaseBeanstalkApp 10 | 11 | Node $MachineName 12 | { 13 | WindowsFeature IIS 14 | { 15 | Ensure = "Present" 16 | Name = "Web-Server" 17 | } 18 | 19 | WindowsFeature IISManagerFeature 20 | { 21 | Ensure = "Present" 22 | Name = "Web-Mgmt-Tools" 23 | } 24 | 25 | WindowsFeature WebApp 26 | { 27 | Ensure = "Present" 28 | Name = "Web-App-Dev" 29 | IncludeAllSubFeature = $True 30 | } 31 | 32 | BeanstalkWebsite sWebsite 33 | { 34 | WebAppPath = $WebAppPath 35 | Hostname = $HostName 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /examples/manifests/BeanstalkConfig.psd1: -------------------------------------------------------------------------------- 1 | @{ 2 | AllNodes = 3 | @( 4 | @{ 5 | NodeName = "localhost"; 6 | PSDscAllowPlainTextPassword = $true; 7 | RebootIfNeeded = $True; 8 | } 9 | ) 10 | } 11 | -------------------------------------------------------------------------------- /examples/manifests/manifests/Beanstalk.ps1: -------------------------------------------------------------------------------- 1 | Configuration Beanstalk 2 | { 3 | param ( 4 | [string] $MachineName, 5 | [string] $WebAppPath = "%SystemDrive%\inetpub\wwwroot", 6 | [string] $HostName = "localhost" 7 | ) 8 | 9 | Import-DscResource -Module BaseBeanstalkApp 10 | 11 | Node $MachineName 12 | { 13 | WindowsFeature IIS 14 | { 15 | Ensure = "Present" 16 | Name = "Web-Server" 17 | } 18 | 19 | WindowsFeature IISManagerFeature 20 | { 21 | Ensure = "Present" 22 | Name = "Web-Mgmt-Tools" 23 | } 24 | 25 | WindowsFeature WebApp 26 | { 27 | Ensure = "Present" 28 | Name = "Web-App-Dev" 29 | IncludeAllSubFeature = $True 30 | } 31 | 32 | BeanstalkWebsite sWebsite 33 | { 34 | WebAppPath = $WebAppPath 35 | Hostname = $HostName 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /examples/manifests/manifests/BeanstalkConfig.psd1: -------------------------------------------------------------------------------- 1 | @{ 2 | AllNodes = 3 | @( 4 | @{ 5 | NodeName = "localhost"; 6 | PSDscAllowPlainTextPassword = $true; 7 | RebootIfNeeded = $True; 8 | } 9 | ) 10 | } 11 | -------------------------------------------------------------------------------- /examples/modules/BaseBeanstalkApp/BaseBeanstalkApp.psd1: -------------------------------------------------------------------------------- 1 | # 2 | 3 | # Generated by: mfellows 4 | 5 | # 6 | 7 | # Generated on: 04/12/2014 8 | 9 | # 10 | 11 | 12 | 13 | @{ 14 | 15 | 16 | 17 | # Script module or binary module file associated with this manifest. 18 | 19 | # RootModule = '' 20 | 21 | 22 | 23 | # Version number of this module. 24 | 25 | ModuleVersion = '1.0' 26 | 27 | 28 | 29 | # ID used to uniquely identify this module 30 | 31 | GUID = 'f2225892-f19a-4e7b-a137-074e18948d9c' 32 | 33 | 34 | 35 | # Author of this module 36 | 37 | Author = 'mfellows' 38 | 39 | 40 | 41 | # Company or vendor of this module 42 | 43 | CompanyName = 'Unknown' 44 | 45 | 46 | 47 | # Copyright statement for this module 48 | 49 | Copyright = '(c) 2014 mfellows. All rights reserved.' 50 | 51 | 52 | 53 | # Description of the functionality provided by this module 54 | 55 | # Description = '' 56 | 57 | 58 | 59 | # Minimum version of the Windows PowerShell engine required by this module 60 | 61 | # PowerShellVersion = '' 62 | 63 | 64 | 65 | # Name of the Windows PowerShell host required by this module 66 | 67 | # PowerShellHostName = '' 68 | 69 | 70 | 71 | # Minimum version of the Windows PowerShell host required by this module 72 | 73 | # PowerShellHostVersion = '' 74 | 75 | 76 | 77 | # Minimum version of Microsoft .NET Framework required by this module 78 | 79 | # DotNetFrameworkVersion = '' 80 | 81 | 82 | 83 | # Minimum version of the common language runtime (CLR) required by this module 84 | 85 | # CLRVersion = '' 86 | 87 | 88 | 89 | # Processor architecture (None, X86, Amd64) required by this module 90 | 91 | # ProcessorArchitecture = '' 92 | 93 | 94 | 95 | # Modules that must be imported into the global environment prior to importing this module 96 | 97 | # RequiredModules = @() 98 | 99 | 100 | 101 | # Assemblies that must be loaded prior to importing this module 102 | 103 | # RequiredAssemblies = @() 104 | 105 | 106 | 107 | # Script files (.ps1) that are run in the caller's environment prior to importing this module. 108 | 109 | # ScriptsToProcess = @() 110 | 111 | 112 | 113 | # Type files (.ps1xml) to be loaded when importing this module 114 | 115 | # TypesToProcess = @() 116 | 117 | 118 | 119 | # Format files (.ps1xml) to be loaded when importing this module 120 | 121 | # FormatsToProcess = @() 122 | 123 | 124 | 125 | # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess 126 | 127 | # NestedModules = @() 128 | 129 | 130 | 131 | # Functions to export from this module 132 | 133 | FunctionsToExport = '*' 134 | 135 | 136 | 137 | # Cmdlets to export from this module 138 | 139 | CmdletsToExport = '*' 140 | 141 | 142 | 143 | # Variables to export from this module 144 | 145 | VariablesToExport = '*' 146 | 147 | 148 | 149 | # Aliases to export from this module 150 | 151 | AliasesToExport = '*' 152 | 153 | 154 | 155 | # List of all modules packaged with this module 156 | 157 | # ModuleList = @() 158 | 159 | 160 | 161 | # List of all files packaged with this module 162 | 163 | # FileList = @() 164 | 165 | 166 | 167 | # Private data to pass to the module specified in RootModule/ModuleToProcess 168 | 169 | # PrivateData = '' 170 | 171 | 172 | 173 | # HelpInfo URI of this module 174 | 175 | # HelpInfoURI = '' 176 | 177 | 178 | 179 | # Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. 180 | 181 | # DefaultCommandPrefix = '' 182 | 183 | 184 | 185 | } 186 | -------------------------------------------------------------------------------- /examples/modules/BaseBeanstalkApp/DSCResources/BeanstalkWebsite/BeanstalkWebsite.psd1: -------------------------------------------------------------------------------- 1 | # 2 | # Module manifest 3 | # 4 | # Generated by: Matt Fellows 5 | # 6 | # Generated on: 11/04/2016 7 | # 8 | 9 | @{ 10 | # Script module or binary module file associated with this manifest. 11 | RootModule = 'BeanstalkWebsite.schema.psm1' 12 | 13 | # Version number of this module. 14 | ModuleVersion = '1.0' 15 | 16 | # ID used to uniquely identify this module 17 | GUID = 'c8706c05-52b7-498b-a3e2-7475084eef71' 18 | 19 | # Author of this module 20 | Author = ' Matt Fellows' 21 | 22 | # Company or vendor of this module 23 | CompanyName = 'nib' 24 | 25 | # Copyright statement for this module 26 | Copyright = '(c) 2016 nib.com.au. All rights reserved.' 27 | 28 | # Description of the functionality provided by this module 29 | Description = 'IIS configuration with SSL bindings for a Beanstalk application' 30 | 31 | # Minimum version of the Windows PowerShell engine required by this module 32 | # PowerShellVersion = '' 33 | 34 | # Name of the Windows PowerShell host required by this module 35 | # PowerShellHostName = '' 36 | 37 | # Minimum version of the Windows PowerShell host required by this module 38 | # PowerShellHostVersion = '' 39 | 40 | # Minimum version of Microsoft .NET Framework required by this module 41 | # DotNetFrameworkVersion = '' 42 | # Minimum version of the common language runtime (CLR) required by this module 43 | 44 | # CLRVersion = '' 45 | # Processor architecture (None, X86, Amd64) required by this module 46 | 47 | # ProcessorArchitecture = '' 48 | # Modules that must be imported into the global environment prior to importing this module 49 | 50 | # RequiredModules = @() 51 | # Assemblies that must be loaded prior to importing this module 52 | 53 | # RequiredAssemblies = @() 54 | # Script files (.ps1) that are run in the caller's environment prior to importing this module. 55 | 56 | # ScriptsToProcess = @() 57 | # Type files (.ps1xml) to be loaded when importing this module 58 | 59 | # TypesToProcess = @() 60 | # Format files (.ps1xml) to be loaded when importing this module 61 | 62 | # FormatsToProcess = @() 63 | # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess 64 | 65 | # NestedModules = @() 66 | # Functions to export from this module 67 | 68 | FunctionsToExport = '*' 69 | # Cmdlets to export from this module 70 | 71 | CmdletsToExport = '*' 72 | # Variables to export from this module 73 | 74 | VariablesToExport = '*'# Aliases to export from this module 75 | 76 | AliasesToExport = '*'# List of all modules packaged with this module 77 | 78 | # ModuleList = @()# List of all files packaged with this module 79 | 80 | # FileList = @()# Private data to pass to the module specified in RootModule/ModuleToProcess 81 | # PrivateData = '' 82 | 83 | # HelpInfo URI of this module 84 | # HelpInfoURI = '' 85 | 86 | # Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. 87 | # DefaultCommandPrefix = '' 88 | 89 | } 90 | -------------------------------------------------------------------------------- /examples/modules/BaseBeanstalkApp/DSCResources/BeanstalkWebsite/BeanstalkWebsite.schema.psm1: -------------------------------------------------------------------------------- 1 | Configuration BeanstalkWebsite 2 | { 3 | param 4 | ( 5 | [String]$WebAppPath = "%SystemDrive%\inetpub\wwwroot", 6 | [String]$WebSiteName = "Default Web Site", 7 | [String]$HostNameSuffix = "dev", 8 | [String]$HostName = "beanstalk.${HostNameSuffix}", 9 | [String]$ApiAppPoolName = "beanstalk-API", 10 | [HashTable]$AuthenticationInfo = @{Anonymous = "true"; Basic = "false"; Digest = "false"; Windows = "false"} 11 | ) 12 | 13 | Import-DscResource -Module xWebAdministration 14 | 15 | # Copy the website content 16 | # This is only for vagrant testing purposes 17 | File WebContent 18 | { 19 | Ensure = "Present" 20 | Contents = "

Hello from Vagrant

" 21 | DestinationPath = "c:\tmp\index.html" 22 | Type = "File" 23 | } 24 | 25 | # Stop the default website (beanstalk need this?) 26 | # Create the new Website with HTTPS 27 | xWebsite DefaultSite 28 | { 29 | Ensure = "Present" 30 | Name = $WebSiteName 31 | State = "Started" 32 | PhysicalPath = $WebAppPath 33 | BindingInfo = @( 34 | MSFT_xWebBindingInformation 35 | { 36 | Protocol = "HTTP" 37 | Port = 80 38 | } 39 | ) 40 | DependsOn = "[File]WebContent" 41 | } 42 | } 43 | 44 | # Get a certificate thumbprint given a subject 45 | # e.g. CN=www.foo.com 46 | function getCertificateThumbprint($subject) { 47 | (Get-ChildItem -Path Cert:\LocalMachine\My | Where-Object {$_.Subject -match $subject}).Thumbprint; 48 | } 49 | -------------------------------------------------------------------------------- /examples/packer.aws.json: -------------------------------------------------------------------------------- 1 | { 2 | "variables": { 3 | "vpc_id": "", 4 | "subnet_id": "", 5 | "source_ami": "", 6 | "major_version": "1.0.", 7 | "region": "ap-southeast-2", 8 | "build_number": "{{env `BUILD_NUMBER`}}" 9 | }, 10 | "builders": [ 11 | { 12 | "type": "amazon-ebs", 13 | "winrm_username": "Administrator", 14 | "winrm_port": 5985, 15 | "user_data_file": "amz.userdata", 16 | "communicator": "winrm", 17 | "associate_public_ip_address": "true", 18 | "ssh_private_ip": "false", 19 | "region": "{{user `region`}}", 20 | "source_ami": "{{user `source_ami`}}", 21 | "vpc_id": "{{user `vpc_id`}}", 22 | "subnet_id": "{{user `subnet_id`}}", 23 | "instance_type": "t2.medium", 24 | "ami_name": "beanstalk-iis-{{user `major_version`}}.{{user `build_number`}}", 25 | "ami_description": "Beanstalk IIS" 26 | } 27 | ], 28 | "provisioners": [ 29 | { 30 | "type": "dsc", 31 | "configuration_name": "Beanstalk", 32 | "configuration_file": "manifests/BeanstalkConfig.psd1", 33 | "manifest_file": "manifests/Beanstalk.ps1", 34 | "module_paths": [ 35 | "modules" 36 | ], 37 | "install_package_management": true, 38 | "install_modules": { 39 | "xWebAdministration": "1.10.0.0" 40 | }, 41 | "module_paths": [ 42 | "modules" 43 | ], 44 | "configuration_params": { 45 | "-WebAppPath": "c:\\tmp", 46 | "-MachineName": "localhost" 47 | } 48 | } 49 | ] 50 | } 51 | -------------------------------------------------------------------------------- /examples/packer.ovf.json: -------------------------------------------------------------------------------- 1 | { 2 | "variables": { 3 | "vpc_id": "", 4 | "subnet_id": "", 5 | "source_ami": "", 6 | "major_version": "1.0.", 7 | "region": "ap-southeast-2", 8 | "ovf_source_path": "", 9 | "build_number": "{{env `BUILD_NUMBER`}}" 10 | }, 11 | "builders": [ 12 | { 13 | "type": "virtualbox-ovf", 14 | "name": "devbox-vbox", 15 | "communicator": "winrm", 16 | "source_path": "{{user `ovf_source_path`}}", 17 | "headless": false, 18 | "guest_additions_mode": "disable", 19 | "boot_wait": "30s", 20 | "winrm_username": "vagrant", 21 | "winrm_password": "FooBar@123", 22 | "winrm_timeout": "5m", 23 | "winrm_port":5985, 24 | "winrm_host":"localhost", 25 | "shutdown_command": "shutdown /s /t 10 /f /d p:4:1 /c \"Packer Shutdown\"", 26 | "shutdown_timeout": "10m", 27 | "vboxmanage": [ 28 | [ 29 | "modifyvm", 30 | "{{.Name}}", 31 | "--memory", 32 | "2048" 33 | ], 34 | [ 35 | "modifyvm", 36 | "{{.Name}}", 37 | "--vram", 38 | "64" 39 | ], 40 | [ 41 | "modifyvm", 42 | "{{.Name}}", 43 | "--cpus", 44 | "2" 45 | ] 46 | ] 47 | } 48 | ], 49 | "provisioners": [ 50 | { 51 | "type": "dsc", 52 | "configuration_name": "Beanstalk", 53 | "configuration_file": "manifests/BeanstalkConfig.psd1", 54 | "manifest_file": "manifests/Beanstalk.ps1", 55 | "install_package_management": true, 56 | "install_modules": { 57 | "xWebAdministration": "1.10.0.0" 58 | }, 59 | "module_paths": [ 60 | "modules" 61 | ], 62 | "resource_paths": [ 63 | "resources/cSelfSignedCert" 64 | ], 65 | "configuration_params": { 66 | "-WebAppPath": "c:\\tmp", 67 | "-MachineName": "localhost" 68 | } 69 | } 70 | ] 71 | } 72 | -------------------------------------------------------------------------------- /examples/resources/cSelfSignedCert/DSCResources/cSelfSignedCert/cSelfSignedCert.psm1: -------------------------------------------------------------------------------- 1 | function Get-TargetResource { 2 | 3 | [CmdletBinding()] 4 | [OutputType([Hashtable])] 5 | param ( 6 | [parameter(Mandatory)] 7 | [String]$Subject, 8 | 9 | [parameter(Mandatory)] 10 | [ValidateSet('CurrentUser','LocalMachine')] 11 | [String]$StoreLocation, 12 | 13 | [parameter(Mandatory)] 14 | [ValidateSet('TrustedPublisher','ClientAuthIssuer','Root','CA','AuthRoot','TrustedPeople','My','SmartCardRoot','Trust','Disallowed')] 15 | [String]$StoreName 16 | ) 17 | 18 | $certInfo = Get-ChildItem -Path "Cert:\$StoreLocation\$StoreName" | Where-Object Subject -eq $Subject 19 | 20 | if ($certInfo) { 21 | Write-Verbose -Message "The certificate with subject: $Subject exists." 22 | $ensureResult = 'Present' 23 | } else { 24 | Write-Verbose -Message "The certificate with subject: $Subject does not exist." 25 | $ensureResult = 'Absent' 26 | } 27 | 28 | $returnValue = @{ 29 | Subject = $certInfo.Subject 30 | Ensure = $ensureResult 31 | } 32 | 33 | $returnValue 34 | } 35 | 36 | function Set-TargetResource { 37 | [CmdletBinding()] 38 | param ( 39 | [parameter(Mandatory)] 40 | [String]$Subject, 41 | 42 | [parameter(Mandatory)] 43 | [ValidateSet('CurrentUser','LocalMachine')] 44 | [String]$StoreLocation, 45 | 46 | [parameter(Mandatory)] 47 | [ValidateSet('TrustedPublisher','ClientAuthIssuer','Root','CA','AuthRoot','TrustedPeople','My','SmartCardRoot','Trust','Disallowed')] 48 | [String]$StoreName, 49 | 50 | [parameter(Mandatory)] 51 | [ValidateSet('Absent','Present')] 52 | [String]$Ensure 53 | 54 | ) 55 | 56 | if ($Ensure -eq 'Present') { 57 | 58 | # TODO: Vendor binary to avoid any runtime issues if that file disappears 59 | if (-not(Get-Module -Name MrCertificate -ListAvailable)) { 60 | $Uri = 'https://gallery.technet.microsoft.com/scriptcenter/Self-signed-certificate-5920a7c6/file/101251/1/New-SelfSignedCertificateEx.zip' 61 | $ModulePath = "$env:ProgramFiles\WindowsPowerShell\Modules\MrCertificate" 62 | $OutFile = "$env:ProgramFiles\WindowsPowerShell\Modules\MrCertificate\New-SelfSignedCertificateEx.zip" 63 | Write-Verbose -Message 'Required module MrCertificate does not exist and will now be installed.' 64 | New-Item -Path $ModulePath -ItemType Directory 65 | Write-Verbose -Message 'Downloading the New-SelfSignedCertificateEx.zip file from the TechNet script repository.' 66 | Invoke-WebRequest -Uri $Uri -OutFile $OutFile 67 | Unblock-File -Path $OutFile 68 | Write-Verbose -Message 'Extracting the New-SelfSignedCertificateEx.zip file to the MrCertificate module folder.' 69 | Add-Type -AssemblyName System.IO.Compression.FileSystem 70 | [System.IO.Compression.ZipFile]::ExtractToDirectory($OutFile, $ModulePath) 71 | Write-Verbose -Message 'Creating the mrcertificate.psm1 file and adding the necessary content to it.' 72 | New-Item -Path $ModulePath -Name mrcertificate.psm1 -ItemType File | 73 | Add-Content -Value '. "$env:ProgramFiles\WindowsPowerShell\Modules\MrCertificate\New-SelfSignedCertificateEx.ps1"' 74 | Remove-Item -Path $OutFile -Force 75 | } 76 | 77 | Import-Module -Name MrCertificate 78 | Write-Verbose -Message "Creating certificate with subject: $Subject" 79 | New-SelfSignedCertificateEx -Subject $Subject -StoreLocation $StoreLocation -StoreName $StoreName 80 | } elseif ($Ensure -eq 'Absent') { 81 | Write-Verbose -Message "Removing the certificate with subject $Subject." 82 | Get-ChildItem -Path "Cert:\$StoreLocation\$StoreName" | 83 | Where-Object Subject -eq $Subject | 84 | Remove-Item -Force 85 | } 86 | } 87 | 88 | function Test-TargetResource { 89 | [CmdletBinding()] 90 | [OutputType([Boolean])] 91 | param ( 92 | [parameter(Mandatory)] 93 | [String]$Subject, 94 | 95 | [parameter(Mandatory)] 96 | [ValidateSet('CurrentUser','LocalMachine')] 97 | [String]$StoreLocation, 98 | 99 | [parameter(Mandatory)] 100 | [ValidateSet('TrustedPublisher','ClientAuthIssuer','Root','CA','AuthRoot','TrustedPeople','My','SmartCardRoot','Trust','Disallowed')] 101 | [String]$StoreName, 102 | 103 | [parameter(Mandatory)] 104 | [ValidateSet('Absent','Present')] 105 | [String]$Ensure 106 | ) 107 | 108 | $certInfo = Get-ChildItem -Path "Cert:\$StoreLocation\$StoreName" | 109 | Where-Object Subject -eq $Subject 110 | switch ($Ensure) { 111 | 'Absent' {$DesiredSetting = $false} 112 | 'Present' {$DesiredSetting = $true} 113 | } 114 | 115 | if (($certInfo -and $DesiredSetting) -or (-not($certInfo) -and -not($DesiredSetting))) { 116 | Write-Verbose -Message 'The certificate matches the desired state.' 117 | [Boolean]$result = $true 118 | } else { 119 | Write-Verbose -Message 'The certificate does not match the desired state.' 120 | [Boolean]$result = $false 121 | } 122 | 123 | $result 124 | } 125 | 126 | Export-ModuleMember -Function *-TargetResource 127 | -------------------------------------------------------------------------------- /examples/resources/cSelfSignedCert/DSCResources/cSelfSignedCert/cSelfSignedCert.schema.mof: -------------------------------------------------------------------------------- 1 | [ClassVersion("1.0.0.0"), FriendlyName("cSelfSignedCert")] class cSelfSignedCert : OMI_BaseResource { [Key] String Subject; [Write, ValueMap{"CurrentUser","LocalMachine"}, Values{"CurrentUser","LocalMachine"}] String StoreLocation; [Write, ValueMap{"TrustedPublisher","ClientAuthIssuer","Root","CA","AuthRoot","TrustedPeople","My","SmartCardRoot","Trust","Disallowed"}, Values{"TrustedPublisher","ClientAuthIssuer","Root","CA","AuthRoot","TrustedPeople","My","SmartCardRoot","Trust","Disallowed"}] String StoreName; [Write, ValueMap{"Absent","Present"}, Values{"Absent","Present"}] String Ensure; }; -------------------------------------------------------------------------------- /examples/resources/cSelfSignedCert/cSelfSignedCert.psd1: -------------------------------------------------------------------------------- 1 | # # Module manifest for module 'cSelfSignedCert' # # Generated by: Matt Fellows # # Generated on: 11/04/2016 # @{ # Script module or binary module file associated with this manifest. RootModule = 'cSelfSignedCert' # Version number of this module. ModuleVersion = '1.0' # ID used to uniquely identify this module GUID = 'ccacfc64-2c35-4817-b2fa-61b1c4fa82a1' # Author of this module Author = 'Matt Fellows' # Company or vendor of this module CompanyName = 'nib' # Copyright statement for this module Copyright = '(c) 2016 nib.com.au. All rights reserved.' # Description of the functionality provided by this module Description = 'Module to Create Self Signed Certificates' # Minimum version of the Windows PowerShell engine required by this module PowerShellVersion = '4.0' # Name of the Windows PowerShell host required by this module # PowerShellHostName = '' # Minimum version of the Windows PowerShell host required by this module # PowerShellHostVersion = '' # Minimum version of Microsoft .NET Framework required by this module # DotNetFrameworkVersion = '' # Minimum version of the common language runtime (CLR) required by this module # CLRVersion = '' # Processor architecture (None, X86, Amd64) required by this module # ProcessorArchitecture = '' # Modules that must be imported into the global environment prior to importing this module # RequiredModules = @() # Assemblies that must be loaded prior to importing this module # RequiredAssemblies = @() # Script files (.ps1) that are run in the caller's environment prior to importing this module. # ScriptsToProcess = @() # Type files (.ps1xml) to be loaded when importing this module # TypesToProcess = @() # Format files (.ps1xml) to be loaded when importing this module # FormatsToProcess = @() # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess # NestedModules = @() # Functions to export from this module FunctionsToExport = '*.TargetResource' # Cmdlets to export from this module CmdletsToExport = '*' # Variables to export from this module VariablesToExport = '*' # Aliases to export from this module AliasesToExport = '*' # List of all modules packaged with this module # ModuleList = @() # List of all files packaged with this module # FileList = @() # Private data to pass to the module specified in RootModule/ModuleToProcess # PrivateData = '' # HelpInfo URI of this module # HelpInfoURI = ''# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. # DefaultCommandPrefix = ''} -------------------------------------------------------------------------------- /examples/scripts/BundleConfig.ps1: -------------------------------------------------------------------------------- 1 | $EC2SettingsFile="C:\\Program Files\\Amazon\\Ec2ConfigService\\Settings\\BundleConfig.xml" 2 | $xml = [xml](get-content $EC2SettingsFile) 3 | $xmlElement = $xml.get_DocumentElement() 4 | 5 | foreach ($element in $xmlElement.Property) 6 | { 7 | if ($element.Name -eq "AutoSysprep") 8 | { 9 | $element.Value="Yes" 10 | } 11 | } 12 | $xml.Save($EC2SettingsFile) 13 | -------------------------------------------------------------------------------- /examples/scripts/EC2Config.ps1: -------------------------------------------------------------------------------- 1 | $EC2SettingsFile="C:\\Program Files\\Amazon\\Ec2ConfigService\\Settings\\Config.xml" 2 | $xml = [xml](get-content $EC2SettingsFile) 3 | $xmlElement = $xml.get_DocumentElement() 4 | $xmlElementToModify = $xmlElement.Plugins 5 | 6 | foreach ($element in $xmlElementToModify.Plugin) 7 | { 8 | if ($element.name -eq "Ec2SetPassword") 9 | { 10 | $element.State="Enabled" 11 | } 12 | elseif ($element.name -eq "Ec2SetComputerName") 13 | { 14 | $element.State="Enabled" 15 | } 16 | elseif ($element.name -eq "Ec2HandleUserData") 17 | { 18 | $element.State="Enabled" 19 | } 20 | } 21 | $xml.Save($EC2SettingsFile) 22 | -------------------------------------------------------------------------------- /examples/scripts/run-dsc.ps1: -------------------------------------------------------------------------------- 1 | # 2 | # DSC Runner. 3 | # 4 | # Bootstraps the DSC environment, sets up configuration data 5 | # and runs the DSC Configuration. 6 | # 7 | # TODO: Add parameters...? 8 | 9 | # Set the local PowerShell Module environment path 10 | $absoluteModulePaths = [string]::Join(";", ("c:\vagrant\modules".Split(";") | ForEach-Object { $_ | Resolve-Path })) 11 | 12 | echo "Adding to path: $absoluteModulePaths" 13 | $env:PSModulePath="$absoluteModulePaths;${env:PSModulePath}" 14 | ("c:\vagrant\modules".Split(";") | ForEach-Object { gci -Recurse $_ | ForEach-Object { Unblock-File $_.FullName} }) 15 | 16 | $script = $(Join-Path "c:\vagrant" "manifests/Beanstalk.ps1" -Resolve) 17 | echo "PSModulePath Configured: ${env:PSModulePath}" 18 | echo "Running Configuration file: ${script}" 19 | 20 | # Generate the MOF file, only if a MOF path not already provided. 21 | # Import the Manifest 22 | . $script 23 | 24 | cd "c:\vagrant" 25 | $StagingPath = $(Join-Path "c:\vagrant" "staging") 26 | $Config = $(iex (Get-Content (Join-Path "c:\vagrant" "manifests/BeanstalkConfig.psd1" -Resolve) | Out-String)) 27 | Beanstalk -OutputPath $StagingPath -MachineName "localhost" -WebAppPath "%SystemDrive%\inetpub\wwwroot" -HostName "beanstalk.dev" -ConfigurationData $Config 28 | 29 | # Start a DSC Configuration run 30 | Start-DscConfiguration -Force -Wait -Verbose -Path $StagingPath 31 | del $StagingPath\*.mof 32 | 33 | # TODO: Cleanup 34 | #rmdir c:\vagrant 35 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/mefellows/packer-dsc 2 | 3 | go 1.13 4 | 5 | require ( 6 | github.com/hashicorp/errwrap v1.0.0 7 | github.com/hashicorp/go-checkpoint v0.0.0-20171009173528-1545e56e46de 8 | github.com/hashicorp/go-cleanhttp v0.5.0 9 | github.com/hashicorp/go-multierror v1.0.0 10 | github.com/hashicorp/go-uuid v1.0.1 11 | github.com/hashicorp/go-version v1.2.0 12 | github.com/hashicorp/hcl/v2 v2.0.0 13 | github.com/hashicorp/packer v1.5.1 14 | github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d 15 | github.com/mitchellh/go-fs v0.0.0-20180402234041-7b48fa161ea7 16 | github.com/mitchellh/iochan v1.0.0 17 | github.com/mitchellh/mapstructure v0.0.0-20180111000720-b4575eea38cc 18 | github.com/mitchellh/multistep v0.0.0-20170316185339-391576a156a5 19 | github.com/mitchellh/reflectwalk v1.0.0 20 | github.com/ugorji/go v0.0.0-20170620104852-5efa3251c7f7 21 | github.com/zclconf/go-cty v1.1.2-0.20191126233707-f0f7fd24c4af 22 | ) 23 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 3 | cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= 4 | cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= 5 | cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= 6 | cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= 7 | cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= 8 | cloud.google.com/go v0.49.0 h1:CH+lkubJzcPYB1Ggupcq0+k8Ni2ILdG2lYjDIgavDBQ= 9 | cloud.google.com/go v0.49.0/go.mod h1:hGvAdzcWNbyuxS3nWhD7H2cIJxjRRTRLQVB0bdputVY= 10 | cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= 11 | cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= 12 | cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= 13 | cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= 14 | cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= 15 | cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= 16 | cloud.google.com/go/storage v1.4.0 h1:KDdqY5VTXBTqpSbctVTt0mVvfanP6JZzNzLE0qNY100= 17 | cloud.google.com/go/storage v1.4.0/go.mod h1:ZusYJWlOshgSBGbt6K3GnB3MT3H1xs2id9+TCl4fDBA= 18 | contrib.go.opencensus.io/exporter/ocagent v0.5.0/go.mod h1:ImxhfLRpxoYiSq891pBrLVhN+qmP8BTVvdH2YLs7Gl0= 19 | dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= 20 | dmitri.shuralyov.com/gpu/mtl v0.0.0-20191203043605-d42048ed14fd/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= 21 | github.com/1and1/oneandone-cloudserver-sdk-go v1.0.1/go.mod h1:61apmbkVJH4kg+38ftT+/l0XxdUCVnHggqcOTqZRSEE= 22 | github.com/Azure/azure-sdk-for-go v30.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= 23 | github.com/Azure/go-autorest v12.0.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= 24 | github.com/Azure/go-ntlmssp v0.0.0-20191115201650-bad6df29494a h1:3FwiePtHk5YJrooV799oo5jIfsgRdES25VdngJM03dU= 25 | github.com/Azure/go-ntlmssp v0.0.0-20191115201650-bad6df29494a/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU= 26 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 27 | github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= 28 | github.com/ChrisTrenkamp/goxpath v0.0.0-20170625215350-4fe035839290 h1:K9I21XUHNbYD3GNMmJBN0UKJCpdP+glftwNZ7Bo8kqY= 29 | github.com/ChrisTrenkamp/goxpath v0.0.0-20170625215350-4fe035839290/go.mod h1:nuWgzSkT5PnyOd+272uUmV0dnAnAn42Mk7PiQC5VzN4= 30 | github.com/NaverCloudPlatform/ncloud-sdk-go v0.0.0-20180110055012-c2e73f942591/go.mod h1:EHGzQGbwozJBj/4qj3WGrTJ0FqjgOTOxLQ0VNWvPn08= 31 | github.com/PuerkitoBio/goquery v1.5.0/go.mod h1:qD2PgZ9lccMbQlc7eEOjaeRlFQON7xY8kdmcsrnKqMg= 32 | github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= 33 | github.com/Telmate/proxmox-api-go v0.0.0-20191015171801-b0c2796b9fcf/go.mod h1:OGWyIMJ87/k/GCz8CGiWB2HOXsOVDM6Lpe/nFPkC4IQ= 34 | github.com/abdullin/seq v0.0.0-20160510034733-d5467c17e7af/go.mod h1:5Jv4cbFiHJMsVxt52+i0Ha45fjshj6wxYr1r19tB9bw= 35 | github.com/agext/levenshtein v1.2.1 h1:QmvMAjj2aEICytGiWzmxoE0x2KZvE0fvmqMOfy2tjT8= 36 | github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= 37 | github.com/aliyun/alibaba-cloud-sdk-go v0.0.0-20190418113227-25233c783f4e/go.mod h1:T9M45xf79ahXVelWoOBmH0y4aC1t5kXO5BxwyakgIGA= 38 | github.com/aliyun/aliyun-oss-go-sdk v0.0.0-20170113022742-e6dbea820a9f/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= 39 | github.com/andybalholm/cascadia v1.0.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y= 40 | github.com/antchfx/htmlquery v1.0.0/go.mod h1:MS9yksVSQXls00iXkiMqXr0J+umL/AmxXKuP28SUJM8= 41 | github.com/antchfx/xmlquery v1.0.0/go.mod h1:/+CnyD/DzHRnv2eRxrVbieRU/FIF6N0C+7oTtyUtCKk= 42 | github.com/antchfx/xpath v0.0.0-20170728053731-b5c552e1acbd/go.mod h1:Yee4kTMuNiPYJ7nSNorELQMr1J33uOpXDMByNYhvtNk= 43 | github.com/antchfx/xquery v0.0.0-20170730121040-eb8c3c172607/go.mod h1:LzD22aAzDP8/dyiCKFp31He4m2GPjl0AFyzDtZzUu9M= 44 | github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= 45 | github.com/apparentlymart/go-dump v0.0.0-20180507223929-23540a00eaa3/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM= 46 | github.com/apparentlymart/go-textseg v1.0.0 h1:rRmlIsPEEhUTIKQb7T++Nz/A5Q6C9IuX2wFoYVvnCs0= 47 | github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk= 48 | github.com/approvals/go-approval-tests v0.0.0-20160714161514-ad96e53bea43/go.mod h1:S6puKjZ9ZeqUPBv2hEBnMZGcM2J6mOsDRQcmxkMAND0= 49 | github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= 50 | github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da h1:8GUt8eRujhVEGZFFEjBj46YV4rDjvGrNxb0KMWYkL2I= 51 | github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= 52 | github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= 53 | github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= 54 | github.com/aws/aws-sdk-go v1.15.78/go.mod h1:E3/ieXAlvM0XWO57iftYVDLLvQ824smPP3ATZkfNZeM= 55 | github.com/aws/aws-sdk-go v1.16.22/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= 56 | github.com/aws/aws-sdk-go v1.24.1 h1:B2NRyTV1/+h+Dg8Bh7vnuvW6QZz/NBL+uzgC2uILDMI= 57 | github.com/aws/aws-sdk-go v1.24.1/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= 58 | github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas= 59 | github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4= 60 | github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= 61 | github.com/biogo/hts v0.0.0-20160420073057-50da7d4131a3/go.mod h1:YOY5xnRf7Jz2SZCLSKgVfyqNzbRgyTznM3HyDqQMxcU= 62 | github.com/bsm/go-vlq v0.0.0-20150828105119-ec6e8d4f5f4e/go.mod h1:N+BjUcTjSxc2mtRGSCPsat1kze3CUtvJN3/jTXlp29k= 63 | github.com/c2h5oh/datasize v0.0.0-20171227191756-4eba002a5eae/go.mod h1:S/7n9copUssQ56c7aAgHqftWO4LTf4xY6CGWt8Bc+3M= 64 | github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= 65 | github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= 66 | github.com/cheggaaa/pb v1.0.27 h1:wIkZHkNfC7R6GI5w7l/PdAdzXzlrbcI3p8OAlnkTsnc= 67 | github.com/cheggaaa/pb v1.0.27/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s= 68 | github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= 69 | github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= 70 | github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= 71 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 72 | github.com/creack/goselect v0.1.0/go.mod h1:gHrIcH/9UZDn2qgeTUeW5K9eZsVYCH6/60J/FHysWyE= 73 | github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= 74 | github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 75 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 76 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 77 | github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= 78 | github.com/digitalocean/go-libvirt v0.0.0-20190626172931-4d226dd6c437/go.mod h1:PRcPVAAma6zcLpFd4GZrjR/MRpood3TamjKI2m/z/Uw= 79 | github.com/digitalocean/go-qemu v0.0.0-20181112162955-dd7bb9c771b8/go.mod h1:/YnlngP1PARC0SKAZx6kaAEMOp8bNTQGqS+Ka3MctNI= 80 | github.com/digitalocean/godo v1.11.1/go.mod h1:h6faOIcZ8lWIwNQ+DN7b3CgX4Kwby5T+nbpNqkUIozU= 81 | github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8= 82 | github.com/dnaeon/go-vcr v1.0.0/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= 83 | github.com/docker/docker v0.0.0-20180422163414-57142e89befe/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= 84 | github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= 85 | github.com/dylanmei/iso8601 v0.1.0 h1:812NGQDBcqquTfH5Yeo7lwR0nzx/cKdsmf3qMjPURUI= 86 | github.com/dylanmei/iso8601 v0.1.0/go.mod h1:w9KhXSgIyROl1DefbMYIE7UVSIvELTbMrCfx+QkYnoQ= 87 | github.com/dylanmei/winrmtest v0.0.0-20170819153634-c2fbb09e6c08/go.mod h1:VBVDFSBXCIW8JaHQpI8lldSKfYaLMzP9oyq6IJ4fhzY= 88 | github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 89 | github.com/envoyproxy/go-control-plane v0.9.1/go.mod h1:G1fbsNGAFpC1aaERrShZQVdUV2ZuZuv6FCl2v9JNSxQ= 90 | github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= 91 | github.com/exoscale/egoscale v0.18.1/go.mod h1:Z7OOdzzTOz1Q1PjQXumlz9Wn/CddH0zSYdCF3rnBKXE= 92 | github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= 93 | github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= 94 | github.com/fatih/structtag v1.0.0/go.mod h1:IKitwq45uXL/yqi5mYghiD3w9H6eTOvI9vnk8tXMphA= 95 | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= 96 | github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= 97 | github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= 98 | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= 99 | github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= 100 | github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM= 101 | github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= 102 | github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= 103 | github.com/gocolly/colly v1.2.0/go.mod h1:Hof5T3ZswNVsOHYmba1u03W65HDWgpV5HifSuueE0EA= 104 | github.com/gofrs/flock v0.7.1 h1:DP+LD/t0njgoPBvT5MJLeliUIVQR03hiKR6vezdwHlc= 105 | github.com/gofrs/flock v0.7.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= 106 | github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= 107 | github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= 108 | github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3/go.mod h1:nPpo7qLxd6XL3hWJG/O60sR8ZKfMCiIoNap5GvD12KU= 109 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 110 | github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 111 | github.com/golang/groupcache v0.0.0-20191027212112-611e8accdfc9 h1:uHTyIjqVhYRhLbJ8nIiOJHkEZZ+5YoOsAbD3sk82NiE= 112 | github.com/golang/groupcache v0.0.0-20191027212112-611e8accdfc9/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 113 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 114 | github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 115 | github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= 116 | github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 117 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 118 | github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 119 | github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= 120 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 121 | github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w= 122 | github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= 123 | github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 124 | github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 125 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 126 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 127 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 128 | github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= 129 | github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= 130 | github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= 131 | github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= 132 | github.com/google/pprof v0.0.0-20191105193234-27840fff0d09/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= 133 | github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= 134 | github.com/google/shlex v0.0.0-20150127133951-6f45313302b9/go.mod h1:RpwtwJQFrIEPstU94h88MWPXP2ektJZ8cZ0YntAmXiE= 135 | github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 136 | github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= 137 | github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM= 138 | github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= 139 | github.com/gophercloud/gophercloud v0.2.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= 140 | github.com/gophercloud/utils v0.0.0-20190124192022-a5c25e7a53a6/go.mod h1:wjDF8z83zTeg5eMLml5EBSlAhbF7G8DobyI1YsMuyzw= 141 | github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= 142 | github.com/gorilla/websocket v0.0.0-20170319172727-a91eba7f9777/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= 143 | github.com/grpc-ecosystem/go-grpc-middleware v1.1.0/go.mod h1:f5nM7jw/oeRSadq3xCzHAvxcr8HZnzsqU6ILg/0NiiE= 144 | github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= 145 | github.com/hashicorp/consul v1.4.0 h1:PQTW4xCuAExEiSbhrsFsikzbW5gVBoi74BjUvYFyKHw= 146 | github.com/hashicorp/consul v1.4.0/go.mod h1:mFrjN1mfidgJfYP1xrJCF+AfRhr6Eaqhb2+sfyn/OOI= 147 | github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= 148 | github.com/hashicorp/errwrap v0.0.0-20180715044906-d6c0cd880357/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= 149 | github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= 150 | github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= 151 | github.com/hashicorp/go-checkpoint v0.0.0-20170624023457-a8d0786e7fa8/go.mod h1:xIwEieBHERyEvaeKF/TcHh1Hu+lxPM+n2vT1+g9I4m4= 152 | github.com/hashicorp/go-checkpoint v0.0.0-20171009173528-1545e56e46de h1:XDCSythtg8aWSRSO29uwhgh7b127fWr+m5SemqjSUL8= 153 | github.com/hashicorp/go-checkpoint v0.0.0-20171009173528-1545e56e46de/go.mod h1:xIwEieBHERyEvaeKF/TcHh1Hu+lxPM+n2vT1+g9I4m4= 154 | github.com/hashicorp/go-cleanhttp v0.0.0-20170211013415-3573b8b52aa7/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= 155 | github.com/hashicorp/go-cleanhttp v0.5.0 h1:wvCrVc9TjDls6+YGAF2hAifE1E5U1+b4tH6KdvN3Gig= 156 | github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= 157 | github.com/hashicorp/go-getter v1.3.1-0.20190906090232-a0f878cb75da h1:HAasZmyRrb7/paYuww5RfVwY3wkFpsbMNYwBxOSZquY= 158 | github.com/hashicorp/go-getter v1.3.1-0.20190906090232-a0f878cb75da/go.mod h1:7qxyCd8rBfcShwsvxgIguu4KbS3l8bUCwg2Umn7RjeY= 159 | github.com/hashicorp/go-immutable-radix v1.0.0 h1:AKDB1HM5PWEA7i4nhcpwOrO2byshxBjXVn/J/3+z5/0= 160 | github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= 161 | github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= 162 | github.com/hashicorp/go-multierror v0.0.0-20170622060955-83588e72410a/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I= 163 | github.com/hashicorp/go-multierror v0.0.0-20180717150148-3d5d8f294aa0/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I= 164 | github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o= 165 | github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= 166 | github.com/hashicorp/go-oracle-terraform v0.0.0-20181016190316-007121241b79/go.mod h1:09jT3Y/OIsjTjQ2+3bkVNPDKqWcGIYYvjB2BEKVUdvc= 167 | github.com/hashicorp/go-retryablehttp v0.5.2 h1:AoISa4P4IsW0/m4T6St8Yw38gTl5GtBAgfkhYh1xAz4= 168 | github.com/hashicorp/go-retryablehttp v0.5.2/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= 169 | github.com/hashicorp/go-rootcerts v0.0.0-20160503143440-6bb64b370b90 h1:VBj0QYQ0u2MCJzBfeYXGexnAl17GsH1yidnoxCqqD9E= 170 | github.com/hashicorp/go-rootcerts v0.0.0-20160503143440-6bb64b370b90/go.mod h1:o4zcYY1e0GEZI6eSEr+43QDYmuGglw1qSO6qdHUHCgg= 171 | github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo= 172 | github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I= 173 | github.com/hashicorp/go-sockaddr v1.0.0 h1:GeH6tui99pF4NJgfnhp+L6+FfobzVW3Ah46sLo0ICXs= 174 | github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= 175 | github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= 176 | github.com/hashicorp/go-uuid v0.0.0-20160717022140-64130c7a86d7/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= 177 | github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= 178 | github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE= 179 | github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= 180 | github.com/hashicorp/go-version v0.0.0-20170202080759-03c5bf6be031/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= 181 | github.com/hashicorp/go-version v1.0.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= 182 | github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= 183 | github.com/hashicorp/go-version v1.2.0 h1:3vNe/fWF5CBgRIguda1meWhsZHy3m8gCJ5wx+dIzX/E= 184 | github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= 185 | github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= 186 | github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= 187 | github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= 188 | github.com/hashicorp/golang-lru v0.5.3 h1:YPkqC67at8FYaadspW/6uE0COsBxS2656RLEr8Bppgk= 189 | github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= 190 | github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= 191 | github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= 192 | github.com/hashicorp/hcl/v2 v2.0.0 h1:efQznTz+ydmQXq3BOnRa3AXzvCeTq1P4dKj/z5GLlY8= 193 | github.com/hashicorp/hcl/v2 v2.0.0/go.mod h1:oVVDG71tEinNGYCxinCYadcmKU9bglqW9pV3txagJ90= 194 | github.com/hashicorp/hcl2 v0.0.0-20191002203319-fb75b3253c80/go.mod h1:Cxv+IJLuBiEhQ7pBYGEuORa0nr4U994pE8mYLuFd7v0= 195 | github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= 196 | github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= 197 | github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= 198 | github.com/hashicorp/packer v1.5.1 h1:tBKwT5W66pS47DJaS5ec25zsETwwLm09udNbk9m3bss= 199 | github.com/hashicorp/packer v1.5.1/go.mod h1:71E644RfMJwBdvgF1M8HFDh0SoyzKpcsZOKjoCpfrxY= 200 | github.com/hashicorp/serf v0.8.2 h1:YZ7UKsJv+hKjqGVUUbtE3HNj79Eln2oQ75tniF6iPt0= 201 | github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= 202 | github.com/hashicorp/vault v1.1.0 h1:v79NUgO5xCZnXVzUkIqFOXtP8YhpnHAi1fk3eo9cuOE= 203 | github.com/hashicorp/vault v1.1.0/go.mod h1:KfSyffbKxoVyspOdlaGVjIuwLobi07qD1bAbosPMpP0= 204 | github.com/hashicorp/yamux v0.0.0-20160720233140-d1caa6c97c9f/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= 205 | github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d h1:kJCB4vdITiW1eC1vq2e6IsrXKrZit1bv/TDYFGMp4BQ= 206 | github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= 207 | github.com/hetznercloud/hcloud-go v1.15.1/go.mod h1:8lR3yHBHZWy2uGcUi9Ibt4UOoop2wrVdERJgCtxsF3Q= 208 | github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= 209 | github.com/hyperonecom/h1-client-go v0.0.0-20191203060043-b46280e4c4a4/go.mod h1:yNUVHSleURKSaYUKq4Wx0i/vjCen2aq7CvPyHd/Vj2Q= 210 | github.com/jdcloud-api/jdcloud-sdk-go v1.9.1-0.20190605102154-3d81a50ca961/go.mod h1:UrKjuULIWLjHFlG6aSPunArE5QX57LftMmStAZJBEX8= 211 | github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869 h1:IPJ3dvxmJ4uczJe5YQdrYB16oTJlGSC/OyZDqUk9xX4= 212 | github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869/go.mod h1:cJ6Cj7dQo+O6GJNiMx+Pa94qKj+TG8ONdKHgMNIyyag= 213 | github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= 214 | github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= 215 | github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM= 216 | github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= 217 | github.com/joyent/triton-go v0.0.0-20180116165742-545edbe0d564/go.mod h1:U+RSyWxWd04xTqnuOQxnai7XGS2PrPY2cfGoDKtMHjA= 218 | github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= 219 | github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= 220 | github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= 221 | github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= 222 | github.com/kardianos/osext v0.0.0-20170510131534-ae77be60afb1/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8= 223 | github.com/kennygrant/sanitize v1.2.4/go.mod h1:LGsjYYtgxbetdg5owWB2mpgUL6e2nfw2eObZ0u0qvak= 224 | github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= 225 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 226 | github.com/klauspost/compress v0.0.0-20160131094358-f86d2e6d8a77/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= 227 | github.com/klauspost/cpuid v0.0.0-20160106104451-349c67577817/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= 228 | github.com/klauspost/crc32 v0.0.0-20160114101742-999f3125931f/go.mod h1:+ZoRqAPRLkC4NPOvfYeR5KNOrY6TD+/sAC3HXPZgDYg= 229 | github.com/klauspost/pgzip v0.0.0-20151221113845-47f36e165cec/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= 230 | github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 231 | github.com/kr/fs v0.0.0-20131111012553-2788f0dbd169 h1:YUrU1/jxRqnt0PSrKj1Uj/wEjk/fjnE80QFfi2Zlj7Q= 232 | github.com/kr/fs v0.0.0-20131111012553-2788f0dbd169/go.mod h1:glhvuHOU9Hy7/8PwwdtnarXqLagOX0b/TbZx2zLMqEg= 233 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 234 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 235 | github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= 236 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 237 | github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= 238 | github.com/linode/linodego v0.7.1/go.mod h1:ga11n3ivecUrPCHN0rANxKmfWBJVkOXfLMZinAbj2sY= 239 | github.com/masterzen/azure-sdk-for-go v0.0.0-20161014135628-ee4f0065d00c h1:FMUOnVGy8nWk1cvlMCAoftRItQGMxI0vzJ3dQjeZTCE= 240 | github.com/masterzen/azure-sdk-for-go v0.0.0-20161014135628-ee4f0065d00c/go.mod h1:mf8fjOu33zCqxUjuiU3I8S1lJMyEAlH+0F2+M5xl3hE= 241 | github.com/masterzen/simplexml v0.0.0-20190410153822-31eea3082786 h1:2ZKn+w/BJeL43sCxI2jhPLRv73oVVOjEKZjKkflyqxg= 242 | github.com/masterzen/simplexml v0.0.0-20190410153822-31eea3082786/go.mod h1:kCEbxUJlNDEBNbdQMkPSp6yaKcRXVI6f4ddk8Riv4bc= 243 | github.com/masterzen/winrm v0.0.0-20180224160350-7e40f93ae939 h1:cRFHA33ER97Xy5jmjS519OXCS/yE3AT3zdbQAg0Z53g= 244 | github.com/masterzen/winrm v0.0.0-20180224160350-7e40f93ae939/go.mod h1:CfZSN7zwz5gJiFhZJz49Uzk7mEBHIceWmbFmYx7Hf7E= 245 | github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= 246 | github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= 247 | github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= 248 | github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= 249 | github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y= 250 | github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= 251 | github.com/mattn/go-tty v0.0.0-20191112051231-74040eebce08/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE= 252 | github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= 253 | github.com/miekg/dns v1.1.1/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= 254 | github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= 255 | github.com/mitchellh/go-fs v0.0.0-20161108191123-7bae45d9a684/go.mod h1:g7SZj7ABpStq3tM4zqHiVEG5un/DZ1+qJJKO7qx1EvU= 256 | github.com/mitchellh/go-fs v0.0.0-20180402234041-7b48fa161ea7 h1:PXPMDtfqV+rZJshQHOiwUFqlqErXaAcuWy+/ZmyRfNc= 257 | github.com/mitchellh/go-fs v0.0.0-20180402234041-7b48fa161ea7/go.mod h1:g7SZj7ABpStq3tM4zqHiVEG5un/DZ1+qJJKO7qx1EvU= 258 | github.com/mitchellh/go-homedir v1.0.0 h1:vKb8ShqSby24Yrqr/yDYkuFz8d0WUjys40rvnGC8aR0= 259 | github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= 260 | github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0= 261 | github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= 262 | github.com/mitchellh/go-vnc v0.0.0-20150629162542-723ed9867aed/go.mod h1:3rdaFaCv4AyBgu5ALFM0+tSuHrBh6v692nyQe3ikrq0= 263 | github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 h1:DpOJ2HYzCv8LZP15IdmG+YdwD2luVPHITV96TkirNBM= 264 | github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= 265 | github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= 266 | github.com/mitchellh/gox v1.0.1/go.mod h1:ED6BioOGXMswlXa2zxfh/xdd5QhwYliBFn9V18Ap4z4= 267 | github.com/mitchellh/iochan v0.0.0-20150529224432-87b45ffd0e95/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= 268 | github.com/mitchellh/iochan v1.0.0 h1:C+X3KsSTLFVBr/tK1eYN/vs4rJcvsiLU338UhYPJWeY= 269 | github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= 270 | github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= 271 | github.com/mitchellh/mapstructure v0.0.0-20170523030023-d0303fe80992/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= 272 | github.com/mitchellh/mapstructure v0.0.0-20180111000720-b4575eea38cc h1:5T6hzGUO5OrL6MdYXYoLQtRWJDDgjdlOVBn9mIqGY1g= 273 | github.com/mitchellh/mapstructure v0.0.0-20180111000720-b4575eea38cc/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= 274 | github.com/mitchellh/multistep v0.0.0-20170316185339-391576a156a5/go.mod h1:tZVWRY9V2OVYseuyNEjh0rb7qkeCMl+kRSGLqUEhFNg= 275 | github.com/mitchellh/panicwrap v0.0.0-20170106182340-fce601fe5557/go.mod h1:QuAqW7/z+iv6aWFJdrA8kCbsF0OOJVKCICqTcYBexuY= 276 | github.com/mitchellh/prefixedio v0.0.0-20151214002211-6e6954073784/go.mod h1:kB1naBgV9ORnkiTVeyJOI1DavaJkG4oNIq0Af6ZVKUo= 277 | github.com/mitchellh/reflectwalk v0.0.0-20170508173806-8d802ff4ae93/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= 278 | github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY= 279 | github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= 280 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 281 | github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 282 | github.com/moul/anonuuid v0.0.0-20160222162117-609b752a95ef/go.mod h1:LgKrp0Iss/BVwquptq4eIe6HPr0s3t1WHT5x0qOh14U= 283 | github.com/moul/gotty-client v0.0.0-20180327180212-b26a57ebc215/go.mod h1:CxM/JGtpRrEPve5H04IhxJrGhxgwxMc6jSP2T4YD60w= 284 | github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms= 285 | github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d h1:VhgPp6v9qf9Agr/56bj7Y/xa04UccTW04VP0Qed4vnQ= 286 | github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d/go.mod h1:YUTz3bUH2ZwIWBy3CJBeOBEugqcmXREj14T+iG/4k4U= 287 | github.com/olekukonko/tablewriter v0.0.0-20180105111133-96aac992fc8b/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= 288 | github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 289 | github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 290 | github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= 291 | github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= 292 | github.com/oracle/oci-go-sdk v1.8.0/go.mod h1:VQb79nF8Z2cwLkLS35ukwStZIg5F66tcBccjip/j888= 293 | github.com/outscale/osc-go v0.0.1/go.mod h1:hJLmXzqU/t07qQYh90I0TqZzu9s85Zs6FMrxk3ukiFM= 294 | github.com/packer-community/winrmcp v0.0.0-20180921204643-0fd363d6159a h1:A3QMuteviunoaY/8ex+RKFqwhcZJ/Cf3fCW3IwL2wx4= 295 | github.com/packer-community/winrmcp v0.0.0-20180921204643-0fd363d6159a/go.mod h1:f6Izs6JvFTdnRbziASagjZ2vmf55NSIkC/weStxCHqk= 296 | github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= 297 | github.com/pierrec/lz4 v2.0.5+incompatible h1:2xWsjqPFWcplujydGg4WmhC/6fZqK42wMM8aXeqhl0I= 298 | github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= 299 | github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 300 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 301 | github.com/pkg/sftp v0.0.0-20160118190721-e84cc8c755ca h1:k8gsErq3rkcbAyCnpOycQsbw88NjCHk7L3KfBZKhQDQ= 302 | github.com/pkg/sftp v0.0.0-20160118190721-e84cc8c755ca/go.mod h1:NxmoDg/QLVWluQDUYG7XBZTLUpKeFa8e3aMf1BfjyHk= 303 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 304 | github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= 305 | github.com/profitbricks/profitbricks-sdk-go v4.0.2+incompatible/go.mod h1:T3/WrziK7fYH3C8ilAFAHe99R452/IzIG3YYkqaOFeQ= 306 | github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 307 | github.com/prometheus/client_model v0.0.0-20191202183732-d1d2010b5bee/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 308 | github.com/renstrom/fuzzysearch v0.0.0-20160331204855-2d205ac6ec17/go.mod h1:SAEjPB4voP88qmWJXI7mA5m15uNlEnuHLx4Eu2mPGpQ= 309 | github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= 310 | github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= 311 | github.com/rogpeppe/go-internal v1.5.0/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= 312 | github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= 313 | github.com/ryanuber/go-glob v0.0.0-20170128012129-256dc444b735 h1:7YvPJVmEeFHR1Tj9sZEYsmarJEQfMVYpd/Vyy/A8dqE= 314 | github.com/ryanuber/go-glob v0.0.0-20170128012129-256dc444b735/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= 315 | github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca/go.mod h1:uugorj2VCxiV1x+LzaIdVa9b4S4qGAcH6cbhh4qVxOU= 316 | github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= 317 | github.com/scaleway/scaleway-cli v0.0.0-20180921094345-7b12c9699d70/go.mod h1:XjlXWPd6VONhsRSEuzGkV8mzRpH7ou1cdLV7IKJk96s= 318 | github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= 319 | github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= 320 | github.com/shirou/gopsutil v2.18.12+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= 321 | github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc= 322 | github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= 323 | github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= 324 | github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= 325 | github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s= 326 | github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= 327 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 328 | github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 329 | github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= 330 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 331 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 332 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 333 | github.com/temoto/robotstxt v1.1.1/go.mod h1:+1AmkuG3IYkh1kv0d2qEB9Le88ehNO0zwOr3ujewlOo= 334 | github.com/tencentcloud/tencentcloud-sdk-go v3.0.97+incompatible/go.mod h1:0PfYow01SHPMhKY31xa+EFz2RStxIqj6JFAJS+IkCi4= 335 | github.com/ucloud/ucloud-sdk-go v0.12.0/go.mod h1:lM6fpI8y6iwACtlbHUav823/uKPdXsNBlnBpRF2fj3c= 336 | github.com/ufilesdk-dev/ufile-gosdk v0.0.0-20190830075812-b4dbc4ef43a6/go.mod h1:R5FMQxkQ+QK/9Vz+jfnJP4rZIktYrRcWmuAnbOSkROI= 337 | github.com/ugorji/go v0.0.0-20151218193438-646ae4a518c1/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ= 338 | github.com/ugorji/go v0.0.0-20170620104852-5efa3251c7f7 h1:VtqNxrWGmleRhhDwCE2E98hD6Qn47lM06TOq4NTF9h0= 339 | github.com/ugorji/go v0.0.0-20170620104852-5efa3251c7f7/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ= 340 | github.com/ulikunitz/xz v0.5.5 h1:pFrO0lVpTBXLpYw+pnLj6TbvHuyjXMfjGeCwSqCVwok= 341 | github.com/ulikunitz/xz v0.5.5/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8= 342 | github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= 343 | github.com/vmware/govmomi v0.0.0-20170707011325-c2105a174311/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU= 344 | github.com/xanzy/go-cloudstack v0.0.0-20190526095453-42f262b63ed0/go.mod h1:sBh287mCRwCz6zyXHMmw7sSZGPohVpnx+o+OY4M+i3A= 345 | github.com/yandex-cloud/go-genproto v0.0.0-20190916101622-7617782d381e/go.mod h1:HEUYX/p8966tMUHHT+TsS0hF/Ca/NYwqprC5WXSDMfE= 346 | github.com/yandex-cloud/go-sdk v0.0.0-20190916101744-c781afa45829/go.mod h1:Eml0jFLU4VVHgIN8zPHMuNwZXVzUMILyO6lQZSfz854= 347 | github.com/zclconf/go-cty v1.0.0/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s= 348 | github.com/zclconf/go-cty v1.1.0/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s= 349 | github.com/zclconf/go-cty v1.1.2-0.20191126233707-f0f7fd24c4af h1:4arg31xOP/qIUV1YVbCWJtChPGzwGzgmlucVbddUq+Y= 350 | github.com/zclconf/go-cty v1.1.2-0.20191126233707-f0f7fd24c4af/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s= 351 | go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= 352 | go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= 353 | go.opencensus.io v0.22.2 h1:75k/FF0Q2YM8QYo07VPddOLBslDt1MZOdEslOHvmzAs= 354 | go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= 355 | go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= 356 | go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= 357 | go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= 358 | golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 359 | golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 360 | golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 361 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 362 | golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 363 | golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 364 | golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 365 | golang.org/x/crypto v0.0.0-20191202143827-86a70503ff7e h1:egKlR8l7Nu9vHGWbcUV8lqR4987UfUbBd7GbhqGzNYU= 366 | golang.org/x/crypto v0.0.0-20191202143827-86a70503ff7e/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 367 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 368 | golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 369 | golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= 370 | golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4= 371 | golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= 372 | golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= 373 | golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= 374 | golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= 375 | golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= 376 | golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= 377 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 378 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= 379 | golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 380 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 381 | golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 382 | golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 383 | golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 384 | golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= 385 | golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= 386 | golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= 387 | golang.org/x/mobile v0.0.0-20191130191448-5c0e7e404af8/go.mod h1:p895TfNkDgPEmEQrNiOtIl3j98d/tGU95djDj7NfyjQ= 388 | golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= 389 | golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= 390 | golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 391 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 392 | golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 393 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 394 | golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 395 | golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 396 | golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 397 | golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 398 | golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 399 | golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 400 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 401 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 402 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 403 | golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 404 | golang.org/x/net v0.0.0-20190502183928-7f726cade0ab/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 405 | golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 406 | golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= 407 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 408 | golang.org/x/net v0.0.0-20191126235420-ef20fe5d7933 h1:e6HwijUxhDe+hPNjZQQn9bA5PW3vNmnN64U2ZW759Lk= 409 | golang.org/x/net v0.0.0-20191126235420-ef20fe5d7933/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 410 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 411 | golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 412 | golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 413 | golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6 h1:pE8b58s1HRDMi8RDc79m0HISf9D4TzseP40cEA6IGfs= 414 | golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 415 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 416 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 417 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 418 | golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 419 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 420 | golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 421 | golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 422 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 423 | golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 424 | golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 425 | golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 426 | golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 427 | golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 428 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 429 | golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 430 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 431 | golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 432 | golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 433 | golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 434 | golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 435 | golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 436 | golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 437 | golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 438 | golang.org/x/sys v0.0.0-20191128015809-6d18c012aee9 h1:ZBzSG/7F4eNKz2L3GE9o300RX0Az1Bw5HF7PDraD+qU= 439 | golang.org/x/sys v0.0.0-20191128015809-6d18c012aee9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 440 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 441 | golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 442 | golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= 443 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 444 | golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 445 | golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 446 | golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs= 447 | golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 448 | golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 449 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 450 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 451 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= 452 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 453 | golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 454 | golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 455 | golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 456 | golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 457 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 458 | golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 459 | golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 460 | golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 461 | golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 462 | golang.org/x/tools v0.0.0-20190909214602-067311248421/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 463 | golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 464 | golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 465 | golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 466 | golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 467 | golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 468 | golang.org/x/tools v0.0.0-20191203051722-db047d72ee39/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 469 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 470 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 471 | google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= 472 | google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= 473 | google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= 474 | google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= 475 | google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= 476 | google.golang.org/api v0.14.0 h1:uMf5uLi4eQMRrMKhCplNik4U4H8Z6C1br3zOtAa/aDE= 477 | google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= 478 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 479 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 480 | google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 481 | google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= 482 | google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= 483 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 484 | google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 485 | google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 486 | google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 487 | google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 488 | google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 489 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 490 | google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= 491 | google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 492 | google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 493 | google.golang.org/genproto v0.0.0-20191115221424-83cc0476cb11 h1:51D++eCgOHufw5VfDE9Uzqyyc+OyQIjb9hkYy9LN5Fk= 494 | google.golang.org/genproto v0.0.0-20191115221424-83cc0476cb11/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 495 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 496 | google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= 497 | google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= 498 | google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 499 | google.golang.org/grpc v1.25.1 h1:wdKvqQk7IttEw92GoRyKG2IDrUIpgpj6H6m81yfeMW0= 500 | google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= 501 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 502 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 503 | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 504 | gopkg.in/cheggaaa/pb.v1 v1.0.27/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= 505 | gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= 506 | gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= 507 | gopkg.in/h2non/gock.v1 v1.0.12/go.mod h1:KHI4Z1sxDW6P4N3DfTWSEza07YpkQP7KJBfglRMEjKY= 508 | gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= 509 | gopkg.in/jarcoal/httpmock.v1 v1.0.0-20181117152235-275e9df93516/go.mod h1:d3R+NllX3X5e0zlG1Rful3uLvsGC/Q3OHut5464DEQw= 510 | gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= 511 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= 512 | gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= 513 | gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 514 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 515 | gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 516 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 517 | honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 518 | honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 519 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 520 | honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= 521 | howett.net/plist v0.0.0-20181124034731-591f970eefbb/go.mod h1:vMygbs4qMhSZSc4lCUl2OEE+rDiIIJAIdR4m7MiMcm0= 522 | rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= 523 | -------------------------------------------------------------------------------- /plugin/provisioner-dsc/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/mefellows/packer-dsc/provisioner/dsc" 5 | "github.com/hashicorp/packer/packer/plugin" 6 | ) 7 | 8 | func main() { 9 | 10 | server, err := plugin.Server() 11 | if err != nil { 12 | panic(err) 13 | } 14 | server.RegisterProvisioner(new(dsc.Provisioner)) 15 | server.Serve() 16 | } 17 | -------------------------------------------------------------------------------- /provisioner/dsc/config.go: -------------------------------------------------------------------------------- 1 | package dsc 2 | 3 | import ( 4 | "github.com/hashicorp/packer/common" 5 | "github.com/hashicorp/packer/template/interpolate" 6 | ) 7 | 8 | type Config struct { 9 | common.PackerConfig `mapstructure:",squash"` 10 | ctx interpolate.Context 11 | 12 | // The command used to execute DSC. 13 | ExecuteCommand string `mapstructure:"execute_command"` 14 | 15 | // The file containing the command to execute DSC 16 | ExecuteCommandFilePath string `mapstructure:"execute_command_file"` 17 | 18 | // Set of Parameters to pass to the DSC Configuration. 19 | ConfigurationParams map[string]string `mapstructure:"configuration_params"` 20 | 21 | // Relative path to a folder, containing the pre-generated MOF file. 22 | // 23 | // Path is relative to the folder containing the Packer json. 24 | MofPath string `mapstructure:"mof_path"` 25 | 26 | // Relative path to the DSC Configuration Data file. 27 | // 28 | // Configuration data is used to parameterise the configuration_file. 29 | // 30 | // Path is relative to the folder containing the Packer json. 31 | ConfigurationFilePath string `mapstructure:"configuration_file"` 32 | 33 | // Relative path to the folder containing the root Configuration manifest file. 34 | // Defaults to 'manifests'. 35 | // 36 | // Path is relative to the folder containing the Packer json. 37 | ManifestDir string `mapstructure:"manifest_dir"` 38 | 39 | // The main DSC manifest file to apply to kick off the entire thing. 40 | // 41 | // Path is relative to the folder containing the Packer json. 42 | ManifestFile string `mapstructure:"manifest_file"` 43 | 44 | // The name of the Configuration module 45 | // 46 | // Defaults to the basename of the "configuration_file" 47 | // e.g. "Foo.ps1" becomes "Foo" 48 | ConfigurationName string `mapstructure:"configuration_name"` 49 | 50 | // Set of module paths relative to the Packer json dir. 51 | // 52 | // These paths are added to the DSC Configuration running 53 | // environment to enable local modules to be addressed. 54 | ModulePaths []string `mapstructure:"module_paths"` 55 | 56 | // Set of DSC resources to upload for system-wide use. 57 | // 58 | // These paths are uploaded into %SystemDrive%\WindowsPowershell\Modules 59 | // to be used system-wide. 60 | ResourcePaths []string `mapstructure:"resource_paths"` 61 | 62 | // Install the latest Windows PackageManagement software? 63 | InstallPackageManagement bool `mapstructure:"install_package_management"` 64 | 65 | // Modules to install, using the latest PackageManagement tooling 66 | // e.g. { "xWebAdministration": "1.0.0.0" } 67 | // 68 | // See InstallPackageManagement if 69 | InstallModules map[string]string `mapstructure:"install_modules"` 70 | 71 | // The directory where files will be uploaded. Packer requires write 72 | // permissions in this directory. 73 | StagingDir string `mapstructure:"staging_dir"` 74 | 75 | // If true, staging directory is removed after executing dsc. 76 | CleanStagingDir bool `mapstructure:"clean_staging_dir"` 77 | 78 | // The directory from which the command will be executed. 79 | // Packer requires the directory to exist when running dsc. 80 | WorkingDir string `mapstructure:"working_dir"` 81 | 82 | // If true, packer will ignore all exit-codes from a dsc run 83 | IgnoreExitCodes bool `mapstructure:"ignore_exit_codes"` 84 | 85 | // Specify remote DSC resources to be installed prior to the DSC execution 86 | // InstallResources map[string]string `mapstructure:"install_resources"` 87 | } 88 | -------------------------------------------------------------------------------- /provisioner/dsc/config.hcl2spec.go: -------------------------------------------------------------------------------- 1 | // Code generated by "mapstructure-to-hcl2 -type Config"; DO NOT EDIT. 2 | package dsc 3 | 4 | import ( 5 | "github.com/hashicorp/hcl/v2/hcldec" 6 | "github.com/zclconf/go-cty/cty" 7 | ) 8 | 9 | // FlatConfig is an auto-generated flat version of Config. 10 | // Where the contents of a field with a `mapstructure:,squash` tag are bubbled up. 11 | type FlatConfig struct { 12 | PackerBuildName *string `mapstructure:"packer_build_name" cty:"packer_build_name"` 13 | PackerBuilderType *string `mapstructure:"packer_builder_type" cty:"packer_builder_type"` 14 | PackerDebug *bool `mapstructure:"packer_debug" cty:"packer_debug"` 15 | PackerForce *bool `mapstructure:"packer_force" cty:"packer_force"` 16 | PackerOnError *string `mapstructure:"packer_on_error" cty:"packer_on_error"` 17 | PackerUserVars map[string]string `mapstructure:"packer_user_variables" cty:"packer_user_variables"` 18 | PackerSensitiveVars []string `mapstructure:"packer_sensitive_variables" cty:"packer_sensitive_variables"` 19 | ExecuteCommand *string `mapstructure:"execute_command" cty:"execute_command"` 20 | ExecuteCommandFilePath *string `mapstructure:"execute_command_file" cty:"execute_command_file"` 21 | ConfigurationParams map[string]string `mapstructure:"configuration_params" cty:"configuration_params"` 22 | MofPath *string `mapstructure:"mof_path" cty:"mof_path"` 23 | ConfigurationFilePath *string `mapstructure:"configuration_file" cty:"configuration_file"` 24 | ManifestDir *string `mapstructure:"manifest_dir" cty:"manifest_dir"` 25 | ManifestFile *string `mapstructure:"manifest_file" cty:"manifest_file"` 26 | ConfigurationName *string `mapstructure:"configuration_name" cty:"configuration_name"` 27 | ModulePaths []string `mapstructure:"module_paths" cty:"module_paths"` 28 | ResourcePaths []string `mapstructure:"resource_paths" cty:"resource_paths"` 29 | InstallPackageManagement *bool `mapstructure:"install_package_management" cty:"install_package_management"` 30 | InstallModules map[string]string `mapstructure:"install_modules" cty:"install_modules"` 31 | StagingDir *string `mapstructure:"staging_dir" cty:"staging_dir"` 32 | CleanStagingDir *bool `mapstructure:"clean_staging_dir" cty:"clean_staging_dir"` 33 | WorkingDir *string `mapstructure:"working_dir" cty:"working_dir"` 34 | IgnoreExitCodes *bool `mapstructure:"ignore_exit_codes" cty:"ignore_exit_codes"` 35 | } 36 | 37 | // FlatMapstructure returns a new FlatConfig. 38 | // FlatConfig is an auto-generated flat version of Config. 39 | // Where the contents a fields with a `mapstructure:,squash` tag are bubbled up. 40 | func (*Config) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } { 41 | return new(FlatConfig) 42 | } 43 | 44 | // HCL2Spec returns the hcl spec of a Config. 45 | // This spec is used by HCL to read the fields of Config. 46 | // The decoded values from this spec will then be applied to a FlatConfig. 47 | func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec { 48 | s := map[string]hcldec.Spec{ 49 | "packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false}, 50 | "packer_builder_type": &hcldec.AttrSpec{Name: "packer_builder_type", Type: cty.String, Required: false}, 51 | "packer_debug": &hcldec.AttrSpec{Name: "packer_debug", Type: cty.Bool, Required: false}, 52 | "packer_force": &hcldec.AttrSpec{Name: "packer_force", Type: cty.Bool, Required: false}, 53 | "packer_on_error": &hcldec.AttrSpec{Name: "packer_on_error", Type: cty.String, Required: false}, 54 | "packer_user_variables": &hcldec.BlockAttrsSpec{TypeName: "packer_user_variables", ElementType: cty.String, Required: false}, 55 | "packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false}, 56 | "execute_command": &hcldec.AttrSpec{Name: "execute_command", Type: cty.String, Required: false}, 57 | "execute_command_file": &hcldec.AttrSpec{Name: "execute_command_file", Type: cty.String, Required: false}, 58 | "configuration_params": &hcldec.BlockAttrsSpec{TypeName: "configuration_params", ElementType: cty.String, Required: false}, 59 | "mof_path": &hcldec.AttrSpec{Name: "mof_path", Type: cty.String, Required: false}, 60 | "configuration_file": &hcldec.AttrSpec{Name: "configuration_file", Type: cty.String, Required: false}, 61 | "manifest_dir": &hcldec.AttrSpec{Name: "manifest_dir", Type: cty.String, Required: false}, 62 | "manifest_file": &hcldec.AttrSpec{Name: "manifest_file", Type: cty.String, Required: false}, 63 | "configuration_name": &hcldec.AttrSpec{Name: "configuration_name", Type: cty.String, Required: false}, 64 | "module_paths": &hcldec.AttrSpec{Name: "module_paths", Type: cty.List(cty.String), Required: false}, 65 | "resource_paths": &hcldec.AttrSpec{Name: "resource_paths", Type: cty.List(cty.String), Required: false}, 66 | "install_package_management": &hcldec.AttrSpec{Name: "install_package_management", Type: cty.Bool, Required: false}, 67 | "install_modules": &hcldec.BlockAttrsSpec{TypeName: "install_modules", ElementType: cty.String, Required: false}, 68 | "staging_dir": &hcldec.AttrSpec{Name: "staging_dir", Type: cty.String, Required: false}, 69 | "clean_staging_dir": &hcldec.AttrSpec{Name: "clean_staging_dir", Type: cty.Bool, Required: false}, 70 | "working_dir": &hcldec.AttrSpec{Name: "working_dir", Type: cty.String, Required: false}, 71 | "ignore_exit_codes": &hcldec.AttrSpec{Name: "ignore_exit_codes", Type: cty.Bool, Required: false}, 72 | } 73 | return s 74 | } 75 | -------------------------------------------------------------------------------- /provisioner/dsc/config_test.go: -------------------------------------------------------------------------------- 1 | package dsc 2 | -------------------------------------------------------------------------------- /provisioner/dsc/provisioner.go: -------------------------------------------------------------------------------- 1 | // Package dsc implements a provisioner for Packer that executes 2 | // DSC on the remote machine, configured to apply a local manifest 3 | // versus connecting to a DSC push server. 4 | // 5 | // NOTE: This has only been tested on Windows environments 6 | package dsc 7 | 8 | import ( 9 | "fmt" 10 | "io/ioutil" 11 | "context" 12 | "os" 13 | "path/filepath" 14 | "strings" 15 | 16 | "github.com/hashicorp/packer/helper/config" 17 | "github.com/hashicorp/packer/packer" 18 | "github.com/hashicorp/packer/template/interpolate" 19 | "github.com/hashicorp/hcl/v2/hcldec" 20 | ) 21 | 22 | // Provisioner DSC 23 | type Provisioner struct { 24 | config Config 25 | communicator packer.Communicator 26 | generatedData map[string]interface{} 27 | } 28 | 29 | // ExecuteTemplate contains the template variables interpolated 30 | // into the running DSC script 31 | type ExecuteTemplate struct { 32 | WorkingDir string 33 | ConfigurationParams string 34 | ConfigurationFilePath string 35 | ConfigurationName string 36 | ModulePath string 37 | ManifestFile string 38 | ManifestDir string 39 | MofPath string 40 | } 41 | 42 | var powershellTemplate = `powershell "& { %s; exit $LastExitCode}"` 43 | 44 | // Prepare sets up the DSC configuration 45 | func (p *Provisioner) Prepare(raws ...interface{}) error { 46 | err := config.Decode(&p.config, &config.DecodeOpts{ 47 | Interpolate: true, 48 | InterpolateContext: &p.config.ctx, 49 | InterpolateFilter: &interpolate.RenderFilter{ 50 | Exclude: []string{ 51 | "execute_command", 52 | }, 53 | }, 54 | }, raws...) 55 | if err != nil { 56 | return err 57 | } 58 | 59 | var errs *packer.MultiError 60 | 61 | // Set some defaults 62 | if p.config.ExecuteCommand == "" { 63 | if p.config.ExecuteCommandFilePath == "" { 64 | p.config.ExecuteCommand = ` 65 | # 66 | # DSC Runner. 67 | # 68 | # Bootstraps the DSC environment, sets up configuration data 69 | # and runs the DSC Configuration. 70 | # 71 | # 72 | # Set the local PowerShell Module environment path 73 | {{if ne .ModulePath ""}} 74 | $absoluteModulePaths = [string]::Join(";", ("{{.ModulePath}}".Split(";") | ForEach-Object { $_ | Resolve-Path })) 75 | echo "Adding to path: $absoluteModulePaths" 76 | $env:PSModulePath="$absoluteModulePaths;${env:PSModulePath}" 77 | ("{{.ModulePath}}".Split(";") | ForEach-Object { gci -Recurse $_ | ForEach-Object { Unblock-File $_.FullName} }) 78 | {{end}} 79 | 80 | $script = $("{{.ManifestFile}}" | Resolve-Path) 81 | echo "PSModulePath Configured: ${env:PSModulePath}" 82 | echo "Running Configuration file: ${script}" 83 | 84 | {{if eq .MofPath ""}} 85 | # Generate the MOF file, only if a MOF path not already provided. 86 | # Import the Manifest 87 | . $script 88 | 89 | cd "{{.WorkingDir}}" 90 | $StagingPath = $(Join-Path "{{.WorkingDir}}" "staging") 91 | {{if ne .ConfigurationFilePath ""}} 92 | $Config = $(iex (Get-Content ("{{.ConfigurationFilePath}}" | Resolve-Path) | Out-String)) 93 | {{end}} 94 | {{.ConfigurationName}} -OutputPath $StagingPath {{.ConfigurationParams}}{{if ne .ConfigurationFilePath ""}} -ConfigurationData $Config{{end}} 95 | {{else}} 96 | $StagingPath = "{{.MofPath}}" 97 | {{end}} 98 | 99 | # Start a DSC Configuration run 100 | Start-DscConfiguration -Force -Wait -Verbose -Path $StagingPath` 101 | } else { 102 | info, err := os.Stat(p.config.ExecuteCommandFilePath) 103 | if err != nil { 104 | errs = packer.MultiErrorAppend(errs, 105 | fmt.Errorf("execute_command_file is invalid: %s", err)) 106 | } else if info.IsDir() { 107 | errs = packer.MultiErrorAppend(errs, 108 | fmt.Errorf("execute_command_file must point to a file")) 109 | } 110 | dat, errs := ioutil.ReadFile(p.config.ExecuteCommandFilePath) 111 | if err != nil { 112 | errs = packer.MultiErrorAppend(errs, 113 | fmt.Errorf("execute_command_file is invalid: %s", err)) 114 | } 115 | p.config.ExecuteCommand = string(dat) 116 | } 117 | } 118 | 119 | if p.config.StagingDir == "" { 120 | p.config.StagingDir = fmt.Sprintf("%s/packer-dsc-pull", os.TempDir()) 121 | } 122 | 123 | if p.config.WorkingDir == "" { 124 | p.config.WorkingDir = p.config.StagingDir 125 | } 126 | 127 | if p.config.ConfigurationParams == nil { 128 | p.config.ConfigurationParams = make(map[string]string) 129 | } 130 | 131 | // Validation 132 | if p.config.ConfigurationFilePath != "" { 133 | info, err := os.Stat(p.config.ConfigurationFilePath) 134 | if err != nil { 135 | errs = packer.MultiErrorAppend(errs, 136 | fmt.Errorf("configuration_file is invalid: %s", err)) 137 | } else if info.IsDir() { 138 | errs = packer.MultiErrorAppend(errs, 139 | fmt.Errorf("configuration_file must point to a file")) 140 | } 141 | } 142 | 143 | if p.config.ManifestDir != "" { 144 | info, err := os.Stat(p.config.ManifestDir) 145 | if err != nil { 146 | errs = packer.MultiErrorAppend(errs, 147 | fmt.Errorf("manifest_dir is invalid: %s", err)) 148 | } else if !info.IsDir() { 149 | errs = packer.MultiErrorAppend(errs, 150 | fmt.Errorf("manifest_dir must point to a directory")) 151 | } 152 | } 153 | 154 | if p.config.ManifestFile == "" { 155 | errs = packer.MultiErrorAppend(errs, 156 | fmt.Errorf("A manifest_file must be specified.")) 157 | } else { 158 | _, err := os.Stat(p.config.ManifestFile) 159 | if err != nil { 160 | errs = packer.MultiErrorAppend(errs, 161 | fmt.Errorf("manifest_file is invalid: %s", err)) 162 | } 163 | } 164 | 165 | if p.config.ConfigurationName == "" { 166 | p.config.ConfigurationName = strings.Split(filepath.Base(p.config.ManifestFile), ".")[0] 167 | } 168 | 169 | for i, path := range p.config.ModulePaths { 170 | info, err := os.Stat(path) 171 | if err != nil { 172 | errs = packer.MultiErrorAppend(errs, 173 | fmt.Errorf("module_path[%d] is invalid: %s", i, err)) 174 | } else if !info.IsDir() { 175 | errs = packer.MultiErrorAppend(errs, 176 | fmt.Errorf("module_path[%d] must point to a directory", i)) 177 | } 178 | } 179 | 180 | for i, path := range p.config.ResourcePaths { 181 | info, err := os.Stat(path) 182 | if err != nil { 183 | errs = packer.MultiErrorAppend(errs, 184 | fmt.Errorf("resource_path[%d] is invalid: %s", i, err)) 185 | } else if !info.IsDir() { 186 | errs = packer.MultiErrorAppend(errs, 187 | fmt.Errorf("resource_path[%d] must point to a directory", i)) 188 | } 189 | } 190 | 191 | if errs != nil && len(errs.Errors) > 0 { 192 | return errs 193 | } 194 | 195 | return nil 196 | } 197 | 198 | // Provision the remote machine with DSC 199 | func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator, generatedData map[string]interface{}) error { 200 | ui.Say("Provisioning with DSC...") 201 | ui.Message("Creating DSC staging directory...") 202 | if err := p.createDir(ctx, ui, comm, p.config.StagingDir); err != nil { 203 | return fmt.Errorf("Error creating staging directory: %s", err) 204 | } 205 | 206 | // Install PackageManagement 207 | if p.config.InstallPackageManagement { 208 | if err := p.installPackageManagement(ctx, ui, comm); err != nil { 209 | return fmt.Errorf("Error installing Package Management: %s", err) 210 | } 211 | } 212 | 213 | // Upload configuration_params config if set 214 | remoteConfigurationFilePath := "" 215 | if p.config.ConfigurationFilePath != "" { 216 | var err error 217 | remoteConfigurationFilePath, err = p.uploadConfigurationFile(ui, comm) 218 | if err != nil { 219 | return fmt.Errorf("Error uploading configuration_params config: %s", err) 220 | } 221 | } 222 | 223 | // Upload manifest dir if set 224 | remoteManifestDir := "" 225 | if p.config.ManifestDir != "" { 226 | ui.Message(fmt.Sprintf( 227 | "Uploading manifest directory from: %s", p.config.ManifestDir)) 228 | remoteManifestDir = fmt.Sprintf("%s/manifest", p.config.StagingDir) 229 | err := p.uploadDirectory(ctx, ui, comm, remoteManifestDir, p.config.ManifestDir) 230 | if err != nil { 231 | return fmt.Errorf("Error uploading manifest dir: %s", err) 232 | } 233 | } 234 | 235 | // Install any remote PowerShell modules 236 | for k, v := range p.config.InstallModules { 237 | err := p.installPackage(ctx, ui, comm, k, v) 238 | if err != nil { 239 | return err 240 | } 241 | } 242 | 243 | // Upload all modules 244 | modulePaths := make([]string, 0, len(p.config.ModulePaths)) 245 | for i, path := range p.config.ModulePaths { 246 | ui.Message(fmt.Sprintf("Uploading local modules from: %s", path)) 247 | targetPath := fmt.Sprintf("%s/module-%d", p.config.StagingDir, i) 248 | if err := p.uploadDirectory(ctx, ui, comm, targetPath, path); err != nil { 249 | return fmt.Errorf("Error uploading modules: %s", err) 250 | } 251 | 252 | modulePaths = append(modulePaths, targetPath) 253 | } 254 | 255 | // Upload all system-wide resources 256 | for _, path := range p.config.ResourcePaths { 257 | ui.Message(fmt.Sprintf("Uploading global DSC Resources from: %s", path)) 258 | targetPath := fmt.Sprintf(`%s\%s`, `${env:programfiles}\WindowsPowershell\Modules`, filepath.Base(path)) 259 | if err := p.uploadDirectory(ctx, ui, comm, targetPath, path); err != nil { 260 | return fmt.Errorf("Error uploading global DSC Resource: %s", err) 261 | } 262 | } 263 | 264 | // Upload pre-generated MOF 265 | remoteMofPath := "" 266 | if p.config.MofPath != "" { 267 | ui.Message(fmt.Sprintf("Uploading local MOF path from: %s", p.config.MofPath)) 268 | remoteMofPath = fmt.Sprintf("%s/mof", p.config.StagingDir) 269 | if err := p.uploadDirectory(ctx, ui, comm, remoteMofPath, p.config.MofPath); err != nil { 270 | return fmt.Errorf("Error uploading MOF: %s", err) 271 | } 272 | } 273 | 274 | // Upload manifest 275 | remoteManifestFile, err := p.uploadManifest(ctx, ui, comm) 276 | if err != nil { 277 | return fmt.Errorf("Error uploading manifest: %s", err) 278 | } 279 | 280 | // Compile the configuration variables 281 | configurationVars := make([]string, 0, len(p.config.ConfigurationParams)) 282 | for k, v := range p.config.ConfigurationParams { 283 | if v == "" { 284 | configurationVars = append(configurationVars, fmt.Sprintf(`%s `, k)) 285 | } else { 286 | configurationVars = append(configurationVars, fmt.Sprintf(`%s "%s"`, k, v)) 287 | } 288 | } 289 | 290 | // Execute DSC script template 291 | tmpl := &ExecuteTemplate{ 292 | ConfigurationParams: strings.Join(configurationVars, " "), 293 | ConfigurationFilePath: remoteConfigurationFilePath, 294 | ManifestDir: remoteManifestDir, 295 | ManifestFile: remoteManifestFile, 296 | ModulePath: strings.Join(modulePaths, ";"), 297 | WorkingDir: p.config.WorkingDir, 298 | ConfigurationName: p.config.ConfigurationName, 299 | MofPath: remoteMofPath, 300 | } 301 | 302 | p.config.ctx.Data = tmpl 303 | 304 | // Create the DSC script 305 | runner, err := p.createDscScript(*tmpl) 306 | if err != nil { 307 | return fmt.Errorf("Error creating DSC runner: %s", err) 308 | } 309 | 310 | // Upload runner to temporary remote path 311 | remoteScriptPath, err := p.uploadDscRunner(ui, comm, runner) 312 | 313 | if err != nil { 314 | return fmt.Errorf("Error uploading DSC runner: %s", err) 315 | } 316 | 317 | defer os.Remove(remoteScriptPath) 318 | 319 | // Return command to run the DSC Runner 320 | command := fmt.Sprintf(powershellTemplate, remoteScriptPath) 321 | cmd := &packer.RemoteCmd{ 322 | Command: command, 323 | } 324 | 325 | ui.Message(fmt.Sprintf("Running DSC: %s", command)) 326 | if err := cmd.RunWithUi(ctx, comm, ui); err != nil { 327 | return err 328 | } 329 | 330 | if cmd.ExitStatus() != 0 && cmd.ExitStatus() != 2 && !p.config.IgnoreExitCodes { 331 | return fmt.Errorf("DSC exited with a non-zero exit status: %d", cmd.ExitStatus()) 332 | } 333 | 334 | if p.config.CleanStagingDir { 335 | if err := p.removeDir(ctx, ui, comm, p.config.StagingDir); err != nil { 336 | return fmt.Errorf("Error removing staging directory: %s", err) 337 | } 338 | } 339 | return nil 340 | } 341 | 342 | func (p *Provisioner) createDscScript(tpml ExecuteTemplate) (string, error) { 343 | command, err := interpolate.Render(p.config.ExecuteCommand, &p.config.ctx) 344 | 345 | if err != nil { 346 | return "", err 347 | } 348 | 349 | file, err := ioutil.TempFile("", "packer-dsc-runner") 350 | if err != nil { 351 | return "", err 352 | } 353 | 354 | err = ioutil.WriteFile(file.Name(), []byte(command), 0655) 355 | 356 | return file.Name(), err 357 | } 358 | 359 | // Cancel a running DSC session. This is a no-op 360 | func (p *Provisioner) Cancel() { 361 | // Just hard quit. It isn't a big deal if what we're doing keeps 362 | // running on the other side. 363 | os.Exit(0) 364 | } 365 | 366 | func (p *Provisioner) uploadConfigurationFile(ui packer.Ui, comm packer.Communicator) (string, error) { 367 | ui.Message("Uploading configuration parameters...") 368 | f, err := os.Open(p.config.ConfigurationFilePath) 369 | if err != nil { 370 | return "", err 371 | } 372 | defer f.Close() 373 | 374 | path := fmt.Sprintf("%s/%s", p.config.StagingDir, p.config.ConfigurationFilePath) 375 | if err := comm.Upload(path, f, nil); err != nil { 376 | return "", err 377 | } 378 | 379 | return path, nil 380 | } 381 | 382 | func (p *Provisioner) uploadManifest(ctx context.Context, ui packer.Ui, comm packer.Communicator) (string, error) { 383 | // Create the remote manifest directory... 384 | ui.Message("Uploading manifest...") 385 | remoteManifestDir := fmt.Sprintf("%s/manifest", p.config.StagingDir) 386 | if err := p.createDir(ctx, ui, comm, remoteManifestDir); err != nil { 387 | return "", fmt.Errorf("Error creating manifest directory: %s", err) 388 | } 389 | 390 | ui.Message(fmt.Sprintf("Uploading manifest file from: %s", p.config.ManifestFile)) 391 | 392 | f, err := os.Open(p.config.ManifestFile) 393 | if err != nil { 394 | return "", err 395 | } 396 | defer f.Close() 397 | 398 | manifestFilename := filepath.Base(p.config.ManifestFile) 399 | remoteManifestFile := fmt.Sprintf("%s/%s", remoteManifestDir, manifestFilename) 400 | if err := comm.Upload(remoteManifestFile, f, nil); err != nil { 401 | return "", err 402 | } 403 | return remoteManifestFile, nil 404 | } 405 | 406 | func (p *Provisioner) uploadDscRunner(ui packer.Ui, comm packer.Communicator, file string) (string, error) { 407 | ui.Message(fmt.Sprintf("Uploading DSC runner from: %s", file)) 408 | 409 | f, err := os.Open(file) 410 | if err != nil { 411 | return "", err 412 | } 413 | defer f.Close() 414 | 415 | remoteDscFile := fmt.Sprintf("%s/%s.ps1", p.config.WorkingDir, filepath.Base(file)) 416 | if err := comm.Upload(remoteDscFile, f, nil); err != nil { 417 | return "", err 418 | } 419 | return remoteDscFile, nil 420 | } 421 | 422 | func (p *Provisioner) createDir(ctx context.Context, ui packer.Ui, comm packer.Communicator, dir string) error { 423 | cmd := &packer.RemoteCmd{ 424 | Command: fmt.Sprintf("powershell.exe -Command \"New-Item -ItemType directory -Force -ErrorAction SilentlyContinue -Path %s\"", dir), 425 | } 426 | 427 | if err := cmd.RunWithUi(ctx, comm, ui); err != nil { 428 | return err 429 | } 430 | 431 | if cmd.ExitStatus() != 0 { 432 | return fmt.Errorf("non-zero exit status") 433 | } 434 | 435 | return nil 436 | } 437 | 438 | func (p *Provisioner) removeDir(ctx context.Context, ui packer.Ui, comm packer.Communicator, dir string) error { 439 | cmd := &packer.RemoteCmd{ 440 | Command: fmt.Sprintf("powershell.exe -Command \"Remove-Item '%s' -Recurse -Force\"", dir), 441 | } 442 | 443 | if err := cmd.RunWithUi(ctx, comm, ui); err != nil { 444 | return err 445 | } 446 | 447 | if cmd.ExitStatus() != 0 { 448 | return fmt.Errorf("non-zero exit status") 449 | } 450 | 451 | return nil 452 | } 453 | 454 | // Template to upload as a script and provision Package Management 455 | var installTemplate = ` 456 | Write-Verbose 'Install PackageManagement' 457 | (New-Object System.Net.WebClient).DownloadFile('https://download.microsoft.com/download/C/4/1/C41378D4-7F41-4BBE-9D0D-0E4F98585C61/PackageManagement_x64.msi','c:\PackageManagement_x64.msi') 458 | Start-Process -FilePath "msiexec.exe" -ArgumentList "/qb /i C:\PackageManagement_x64.msi" -Wait -Passthru 459 | Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force 460 | Get-DSCResource 461 | ` 462 | 463 | // Install a package on the remote host 464 | func (p *Provisioner) installPackageManagement(ctx context.Context, ui packer.Ui, comm packer.Communicator) error { 465 | ui.Message("Installing PowerShell Package Management") 466 | 467 | // Inject template variables 468 | script, err := interpolate.Render(installTemplate, &p.config.ctx) 469 | if err != nil { 470 | return err 471 | } 472 | 473 | // Upload script 474 | file, err := ioutil.TempFile("", "packer-dsc-packagemanagement") 475 | if err != nil { 476 | return err 477 | } 478 | 479 | defer os.Remove(file.Name()) 480 | 481 | err = ioutil.WriteFile(file.Name(), []byte(script), 0655) 482 | 483 | remoteScriptFile := fmt.Sprintf("%s/%s.ps1", p.config.WorkingDir, filepath.Base(file.Name())) 484 | if err := comm.Upload(remoteScriptFile, file, nil); err != nil { 485 | return err 486 | } 487 | 488 | // Run script 489 | cmd := &packer.RemoteCmd{ 490 | Command: fmt.Sprintf(`powershell "& { %s; exit $LastExitCode}"`, remoteScriptFile), 491 | } 492 | 493 | if err := cmd.RunWithUi(ctx, comm, ui); err != nil { 494 | return err 495 | } 496 | 497 | if cmd.ExitStatus() != 0 { 498 | return fmt.Errorf("Install Package Management return a non-zero exit status: %d", cmd.ExitStatus()) 499 | } 500 | 501 | return nil 502 | } 503 | 504 | // Install a package on the remote host 505 | func (p *Provisioner) installPackage(ctx context.Context, ui packer.Ui, comm packer.Communicator, pkg string, version string) error { 506 | ui.Message(fmt.Sprintf("Installing PowerShell package '%s'", pkg)) 507 | 508 | cmd := &packer.RemoteCmd{ 509 | Command: fmt.Sprintf(powershellTemplate, fmt.Sprintf("Install-Module -Name %s -RequiredVersion %s -Force -AllowClobber", pkg, version)), 510 | } 511 | 512 | if err := cmd.RunWithUi(ctx, comm, ui); err != nil { 513 | return err 514 | } 515 | 516 | if cmd.ExitStatus() != 0 { 517 | return fmt.Errorf("PowerShell module install exited with a non-zero exit status: %d", cmd.ExitStatus()) 518 | } 519 | 520 | return nil 521 | } 522 | 523 | func (p *Provisioner) uploadDirectory(ctx context.Context, ui packer.Ui, comm packer.Communicator, dst string, src string) error { 524 | if err := p.createDir(ctx, ui, comm, dst); err != nil { 525 | return err 526 | } 527 | 528 | // Make sure there is a trailing "/" so that the directory isn't 529 | // created on the other side. 530 | if src[len(src)-1] != '/' { 531 | src = src + "/" 532 | } 533 | 534 | return comm.UploadDir(dst, src, nil) 535 | } 536 | 537 | func (p *Provisioner) ConfigSpec() hcldec.ObjectSpec { 538 | return p.config.FlatMapstructure().HCL2Spec() 539 | } 540 | -------------------------------------------------------------------------------- /provisioner/dsc/provisioner_test.go: -------------------------------------------------------------------------------- 1 | package dsc 2 | 3 | import ( 4 | "io/ioutil" 5 | "os" 6 | "regexp" 7 | "strings" 8 | "testing" 9 | 10 | "github.com/hashicorp/packer/packer" 11 | ) 12 | 13 | func testConfig() map[string]interface{} { 14 | filename := "/tmp/packer-dsc-pull-manifest" 15 | if _, err := os.Stat(filename); err != nil { 16 | tf, err := ioutil.TempFile("", "packer") 17 | os.Rename(tf.Name(), "/tmp/packer-dsc-pull-manifest") 18 | 19 | if err != nil { 20 | panic(err) 21 | } 22 | } 23 | 24 | return map[string]interface{}{ 25 | "manifest_file": filename, 26 | "manifest_dir": ".", 27 | "configuration_file": "./provisioner_test.go", 28 | "configuration_params": map[string]string{ 29 | "-Foo": "bar", 30 | }, 31 | "resource_paths": []string{ 32 | ".", 33 | }, 34 | "install_package_management": true, 35 | "install_modules": map[string]string{ 36 | "SomeModule1": "1.0.0", 37 | "SomeModule2": "2.0.0", 38 | }, 39 | } 40 | } 41 | 42 | func TestProvisioner_Impl(t *testing.T) { 43 | var raw interface{} 44 | raw = &Provisioner{} 45 | if _, ok := raw.(packer.Provisioner); !ok { 46 | t.Fatalf("must be a Provisioner") 47 | } 48 | } 49 | 50 | func TestProvisionerPrepare_configurationFileDataPath(t *testing.T) { 51 | config := testConfig() 52 | 53 | delete(config, "configuration_file") 54 | p := new(Provisioner) 55 | err := p.Prepare(config) 56 | if err != nil { 57 | t.Fatalf("err: %s", err) 58 | } 59 | 60 | // Test one that doesn't exist 61 | config["configuration_file"] = "does/not.exist" 62 | p = new(Provisioner) 63 | err = p.Prepare(config) 64 | if err == nil { 65 | t.Fatalf("Expected error but got none") 66 | } 67 | 68 | // And one that is a dir 69 | config["configuration_file"] = "." 70 | p = new(Provisioner) 71 | err = p.Prepare(config) 72 | if err == nil { 73 | t.Fatalf("Expected error but got none") 74 | } 75 | 76 | // Test with a good one 77 | tf, err := ioutil.TempFile("", "packer") 78 | if err != nil { 79 | t.Fatalf("error tempfile: %s", err) 80 | } 81 | defer os.Remove(tf.Name()) 82 | 83 | config["configuration_file"] = tf.Name() 84 | p = new(Provisioner) 85 | err = p.Prepare(config) 86 | if err != nil { 87 | t.Fatalf("err: %s", err) 88 | } 89 | } 90 | 91 | func TestProvisionerPrepare_manifestFile(t *testing.T) { 92 | config := testConfig() 93 | 94 | delete(config, "manifest_file") 95 | p := new(Provisioner) 96 | err := p.Prepare(config) 97 | if err == nil { 98 | t.Fatal("should be an error") 99 | } 100 | 101 | // Test one that doesn't exist 102 | config["manifest_file"] = "this/file/doesnt.exist" 103 | p = new(Provisioner) 104 | err = p.Prepare(config) 105 | if err == nil { 106 | t.Fatalf("Expected error but got none") 107 | } 108 | 109 | // Test with a good one 110 | tf, err := ioutil.TempFile("", "packer") 111 | if err != nil { 112 | t.Fatalf("error tempfile: %s", err) 113 | } 114 | defer os.Remove(tf.Name()) 115 | 116 | config["manifest_file"] = tf.Name() 117 | p = new(Provisioner) 118 | err = p.Prepare(config) 119 | if err != nil { 120 | t.Fatalf("err: %s", err) 121 | } 122 | 123 | } 124 | 125 | func TestProvisionerPrepare_manifestDir(t *testing.T) { 126 | config := testConfig() 127 | 128 | delete(config, "manifestdir") 129 | p := new(Provisioner) 130 | err := p.Prepare(config) 131 | if err != nil { 132 | t.Fatalf("err: %s", err) 133 | } 134 | 135 | // File is not a dir! 136 | delete(config, "manifestdir") 137 | config["manifest_dir"] = "./provisioner_test.go" 138 | p = new(Provisioner) 139 | err = p.Prepare(config) 140 | if err == nil { 141 | t.Fatalf("Expected error but got none") 142 | } 143 | 144 | // Dir not exist 145 | delete(config, "manifestdir") 146 | config["manifest_dir"] = "i/do/not/exist" 147 | p = new(Provisioner) 148 | err = p.Prepare(config) 149 | if err == nil { 150 | t.Fatalf("Expected error but got none") 151 | } 152 | 153 | // Test with a good one 154 | td, err := ioutil.TempDir("", "packer") 155 | if err != nil { 156 | t.Fatalf("error: %s", err) 157 | } 158 | defer os.RemoveAll(td) 159 | 160 | config["manifest_dir"] = td 161 | p = new(Provisioner) 162 | err = p.Prepare(config) 163 | if err != nil { 164 | t.Fatalf("err: %s", err) 165 | } 166 | } 167 | 168 | func TestProvisionerPrepare_modulePaths(t *testing.T) { 169 | config := testConfig() 170 | 171 | delete(config, "module_paths") 172 | p := new(Provisioner) 173 | err := p.Prepare(config) 174 | if err != nil { 175 | t.Fatalf("err: %s", err) 176 | } 177 | 178 | // File is not a dir 179 | config["module_paths"] = []string{"provisioner_test.go"} 180 | p = new(Provisioner) 181 | err = p.Prepare(config) 182 | if err == nil { 183 | t.Fatal("should be an error") 184 | } 185 | 186 | // Test with bad paths 187 | config["module_paths"] = []string{"i-should-not-exist"} 188 | p = new(Provisioner) 189 | err = p.Prepare(config) 190 | if err == nil { 191 | t.Fatal("should be an error") 192 | } 193 | 194 | // Test with a good one 195 | td, err := ioutil.TempDir("", "packer") 196 | if err != nil { 197 | t.Fatalf("error: %s", err) 198 | } 199 | defer os.RemoveAll(td) 200 | 201 | config["module_paths"] = []string{td} 202 | p = new(Provisioner) 203 | err = p.Prepare(config) 204 | if err != nil { 205 | t.Fatalf("err: %s", err) 206 | } 207 | } 208 | func TestProvisionerPrepare_resourcePaths(t *testing.T) { 209 | config := testConfig() 210 | 211 | delete(config, "resource_paths") 212 | p := new(Provisioner) 213 | err := p.Prepare(config) 214 | if err != nil { 215 | t.Fatalf("err: %s", err) 216 | } 217 | 218 | // File is not a dir 219 | config["resource_paths"] = []string{"provisioner_test.go"} 220 | p = new(Provisioner) 221 | err = p.Prepare(config) 222 | if err == nil { 223 | t.Fatal("should be an error") 224 | } 225 | 226 | // Test with bad paths 227 | config["resource_paths"] = []string{"i-should-not-exist"} 228 | p = new(Provisioner) 229 | err = p.Prepare(config) 230 | if err == nil { 231 | t.Fatal("should be an error") 232 | } 233 | 234 | // Test with a good one 235 | td, err := ioutil.TempDir("", "packer") 236 | if err != nil { 237 | t.Fatalf("error: %s", err) 238 | } 239 | defer os.RemoveAll(td) 240 | 241 | config["resource_paths"] = []string{td} 242 | p = new(Provisioner) 243 | err = p.Prepare(config) 244 | if err != nil { 245 | t.Fatalf("err: %s", err) 246 | } 247 | } 248 | 249 | func TestProvisionerPrepare_configurationParams(t *testing.T) { 250 | config := testConfig() 251 | 252 | delete(config, "configuration_params") 253 | p := new(Provisioner) 254 | err := p.Prepare(config) 255 | if err != nil { 256 | t.Fatalf("err: %s", err) 257 | } 258 | 259 | // Test with malformed fact 260 | config["configuration_params"] = "fact=stringified" 261 | p = new(Provisioner) 262 | err = p.Prepare(config) 263 | if err == nil { 264 | t.Fatal("should be an error") 265 | } 266 | 267 | // Test with a good one 268 | td, err := ioutil.TempDir("", "packer") 269 | if err != nil { 270 | t.Fatalf("error: %s", err) 271 | } 272 | defer os.RemoveAll(td) 273 | 274 | facts := make(map[string]string) 275 | facts["fact_name"] = "fact_value" 276 | config["configuration_params"] = facts 277 | 278 | p = new(Provisioner) 279 | err = p.Prepare(config) 280 | if err != nil { 281 | t.Fatalf("err: %s", err) 282 | } 283 | 284 | // Make sure the default facts are present 285 | delete(config, "configuration_params") 286 | p = new(Provisioner) 287 | err = p.Prepare(config) 288 | if p.config.ConfigurationParams == nil { 289 | t.Fatalf("err: Default facts are not set in the Puppet provisioner!") 290 | } 291 | } 292 | 293 | func TestProvisionerPrepare_installPackage(t *testing.T) { 294 | config := testConfig() 295 | config["install_modules"] = map[string]string{ 296 | "SomeModuleName": "1.0.0", 297 | "SomeModuleName2": "2.0.0", 298 | } 299 | p := new(Provisioner) 300 | err := p.Prepare(config) 301 | if err != nil { 302 | t.Fatalf("err: %s", err) 303 | } 304 | } 305 | 306 | func TestProvisioner_installPackage(t *testing.T) { 307 | config := testConfig() 308 | ui := &packer.MachineReadableUi{ 309 | Writer: ioutil.Discard, 310 | } 311 | comm := new(packer.MockCommunicator) 312 | config["install_modules"] = map[string]string{ 313 | "SomeModuleName": "1.0.0", 314 | "SomeModuleName2": "2.0.0", 315 | } 316 | p := new(Provisioner) 317 | err := p.Prepare(config) 318 | if err != nil { 319 | t.Fatalf("err: %s", err) 320 | } 321 | err = p.installPackage(ui, comm, "SomeModuleName", "1.0.0") 322 | if err != nil { 323 | t.Fatalf("err: %s", err) 324 | } 325 | 326 | expectedCommand := `powershell "& { Install-Module -Name SomeModuleName -RequiredVersion 1.0.0 -Force; exit $LastExitCode}"` 327 | if comm.StartCmd.Command != expectedCommand { 328 | t.Fatalf("Expected command '%s' but got '%s'", expectedCommand, comm.StartCmd.Command) 329 | } 330 | if !comm.StartCalled { 331 | t.Fatalf("Expected '%s' to be called, but no remote call was made", expectedCommand) 332 | } 333 | } 334 | 335 | func TestProvisioner_installPackageNonZeroExitCode(t *testing.T) { 336 | config := testConfig() 337 | ui := &packer.MachineReadableUi{ 338 | Writer: ioutil.Discard, 339 | } 340 | comm := new(packer.MockCommunicator) 341 | comm.StartExitStatus = 2 342 | config["install_modules"] = map[string]string{ 343 | "SomeModuleName": "1.0.0", 344 | "SomeModuleName2": "2.0.0", 345 | } 346 | p := new(Provisioner) 347 | err := p.Prepare(config) 348 | if err != nil { 349 | t.Fatalf("err: %s", err) 350 | } 351 | err = p.installPackage(ui, comm, "SomeModuleName", "1.0.0") 352 | if err == nil { 353 | t.Fatalf("Expected error but got none") 354 | } 355 | } 356 | 357 | func TestProvisionerPrepare_installPackageManagement(t *testing.T) { 358 | config := testConfig() 359 | config["install_package_management"] = true 360 | p := new(Provisioner) 361 | err := p.Prepare(config) 362 | if err != nil { 363 | t.Fatalf("err: %s", err) 364 | } 365 | } 366 | 367 | func TestProvisioner_installPackageManagement(t *testing.T) { 368 | config := testConfig() 369 | config["install_package_management"] = true 370 | p := new(Provisioner) 371 | err := p.Prepare(config) 372 | if err != nil { 373 | t.Fatalf("err: %s", err) 374 | } 375 | ui := &packer.MachineReadableUi{ 376 | Writer: ioutil.Discard, 377 | } 378 | comm := new(packer.MockCommunicator) 379 | err = p.installPackageManagement(ui, comm) 380 | if err != nil { 381 | t.Fatalf("Err: %s", err) 382 | } 383 | } 384 | 385 | func TestProvisioner_installPackageManagementFail(t *testing.T) { 386 | config := testConfig() 387 | config["install_package_management"] = true 388 | p := new(Provisioner) 389 | err := p.Prepare(config) 390 | if err != nil { 391 | t.Fatalf("err: %s", err) 392 | } 393 | ui := &packer.MachineReadableUi{ 394 | Writer: ioutil.Discard, 395 | } 396 | comm := new(packer.MockCommunicator) 397 | comm.StartExitStatus = 2 398 | err = p.installPackageManagement(ui, comm) 399 | if err == nil { 400 | t.Fatalf("Expected error but got none") 401 | } 402 | } 403 | 404 | func TestProvisionerProvision_mofFile(t *testing.T) { 405 | config := testConfig() 406 | ui := &packer.MachineReadableUi{ 407 | Writer: ioutil.Discard, 408 | } 409 | comm := new(packer.MockCommunicator) 410 | mofPath, _ := ioutil.TempDir("/tmp", "packer") 411 | defer os.Remove(mofPath) 412 | 413 | config["configuration_name"] = "SomeProjectName" 414 | config["mof_path"] = mofPath 415 | config["module_paths"] = []string{"."} 416 | 417 | // Test with valid values 418 | p := new(Provisioner) 419 | err := p.Prepare(config) 420 | if err != nil { 421 | t.Fatalf("err: %s", err) 422 | } 423 | 424 | err = p.Provision(ui, comm) 425 | if err != nil { 426 | t.Fatalf("err: %s", err) 427 | } 428 | 429 | s := comm.StartCmd.Command 430 | re := regexp.MustCompile(`powershell \"\& \{ ([a-zA-Z0-9-\/]+).*`) 431 | command := re.FindStringSubmatch(s)[1] 432 | 433 | bytes, err := ioutil.ReadFile(command) 434 | if err != nil { 435 | t.Fatalf(err.Error()) 436 | } 437 | scriptContents := strings.TrimSpace(string(bytes)) 438 | 439 | expectedCommand := ` 440 | # 441 | # DSC Runner. 442 | # 443 | # Bootstraps the DSC environment, sets up configuration data 444 | # and runs the DSC Configuration. 445 | # 446 | # 447 | # Set the local PowerShell Module environment path 448 | 449 | $absoluteModulePaths = [string]::Join(";", ("/tmp/packer-dsc-pull/module-0".Split(";") | ForEach-Object { $_ | Resolve-Path })) 450 | echo "Adding to path: $absoluteModulePaths" 451 | $env:PSModulePath="$absoluteModulePaths;${env:PSModulePath}" 452 | ("/tmp/packer-dsc-pull/module-0".Split(";") | ForEach-Object { gci -Recurse $_ | ForEach-Object { Unblock-File $_.FullName} }) 453 | 454 | 455 | $script = $("/tmp/packer-dsc-pull/manifest/packer-dsc-pull-manifest" | Resolve-Path) 456 | echo "PSModulePath Configured: ${env:PSModulePath}" 457 | echo "Running Configuration file: ${script}" 458 | 459 | 460 | $StagingPath = "/tmp/packer-dsc-pull/mof" 461 | 462 | 463 | # Start a DSC Configuration run 464 | Start-DscConfiguration -Force -Wait -Verbose -Path $StagingPath` 465 | 466 | if scriptContents != strings.TrimSpace(expectedCommand) { 467 | t.Fatalf("Expected:\n\n%s\n\nbut got: \n\n%s", strings.TrimSpace(expectedCommand), scriptContents) 468 | } 469 | } 470 | 471 | func TestProvisionerProvision_noConfigurationParams(t *testing.T) { 472 | config := testConfig() 473 | ui := &packer.MachineReadableUi{ 474 | Writer: ioutil.Discard, 475 | } 476 | comm := new(packer.MockCommunicator) 477 | config["configuration_name"] = "SomeProjectName" 478 | config["module_paths"] = []string{"."} 479 | delete(config, "configuration_file") 480 | delete(config, "configuration_params") 481 | 482 | // Test with valid values 483 | p := new(Provisioner) 484 | err := p.Prepare(config) 485 | if err != nil { 486 | t.Fatalf("err: %s", err) 487 | } 488 | 489 | err = p.Provision(ui, comm) 490 | if err != nil { 491 | t.Fatalf("err: %s", err) 492 | } 493 | 494 | s := comm.StartCmd.Command 495 | re := regexp.MustCompile(`powershell \"\& \{ ([a-zA-Z0-9-\/]+).*`) 496 | command := re.FindStringSubmatch(s)[1] 497 | 498 | bytes, err := ioutil.ReadFile(command) 499 | if err != nil { 500 | t.Fatalf(err.Error()) 501 | } 502 | scriptContents := strings.TrimSpace(string(bytes)) 503 | 504 | expectedCommand := ` 505 | # 506 | # DSC Runner. 507 | # 508 | # Bootstraps the DSC environment, sets up configuration data 509 | # and runs the DSC Configuration. 510 | # 511 | # 512 | # Set the local PowerShell Module environment path 513 | 514 | $absoluteModulePaths = [string]::Join(";", ("/tmp/packer-dsc-pull/module-0".Split(";") | ForEach-Object { $_ | Resolve-Path })) 515 | echo "Adding to path: $absoluteModulePaths" 516 | $env:PSModulePath="$absoluteModulePaths;${env:PSModulePath}" 517 | ("/tmp/packer-dsc-pull/module-0".Split(";") | ForEach-Object { gci -Recurse $_ | ForEach-Object { Unblock-File $_.FullName} }) 518 | 519 | 520 | $script = $("/tmp/packer-dsc-pull/manifest/packer-dsc-pull-manifest" | Resolve-Path) 521 | echo "PSModulePath Configured: ${env:PSModulePath}" 522 | echo "Running Configuration file: ${script}" 523 | 524 | 525 | # Generate the MOF file, only if a MOF path not already provided. 526 | # Import the Manifest 527 | . $script 528 | 529 | cd "/tmp/packer-dsc-pull" 530 | $StagingPath = $(Join-Path "/tmp/packer-dsc-pull" "staging") 531 | 532 | SomeProjectName -OutputPath $StagingPath 533 | 534 | 535 | # Start a DSC Configuration run 536 | Start-DscConfiguration -Force -Wait -Verbose -Path $StagingPath` 537 | 538 | if scriptContents != strings.TrimSpace(expectedCommand) { 539 | t.Fatalf("Expected:\n\n%s\n\nbut got: \n\n%s", strings.TrimSpace(expectedCommand), scriptContents) 540 | } 541 | } 542 | 543 | func TestProvisionerProvision_configurationParams(t *testing.T) { 544 | config := testConfig() 545 | ui := &packer.MachineReadableUi{ 546 | Writer: ioutil.Discard, 547 | } 548 | comm := new(packer.MockCommunicator) 549 | configurationParams := map[string]string{ 550 | "-Website": "Beanstalk", 551 | } 552 | config["configuration_name"] = "SomeProjectName" 553 | delete(config, "configuration_file") 554 | config["configuration_params"] = configurationParams 555 | config["module_paths"] = []string{"."} 556 | 557 | // Test with valid values 558 | p := new(Provisioner) 559 | err := p.Prepare(config) 560 | if err != nil { 561 | t.Fatalf("err: %s", err) 562 | } 563 | 564 | err = p.Provision(ui, comm) 565 | if err != nil { 566 | t.Fatalf("err: %s", err) 567 | } 568 | 569 | s := comm.StartCmd.Command 570 | re := regexp.MustCompile(`powershell \"\& \{ ([a-zA-Z0-9-\/]+).*`) 571 | command := re.FindStringSubmatch(s)[1] 572 | 573 | bytes, err := ioutil.ReadFile(command) 574 | if err != nil { 575 | t.Fatalf(err.Error()) 576 | } 577 | scriptContents := strings.TrimSpace(string(bytes)) 578 | 579 | expectedCommand := ` 580 | # 581 | # DSC Runner. 582 | # 583 | # Bootstraps the DSC environment, sets up configuration data 584 | # and runs the DSC Configuration. 585 | # 586 | # 587 | # Set the local PowerShell Module environment path 588 | 589 | $absoluteModulePaths = [string]::Join(";", ("/tmp/packer-dsc-pull/module-0".Split(";") | ForEach-Object { $_ | Resolve-Path })) 590 | echo "Adding to path: $absoluteModulePaths" 591 | $env:PSModulePath="$absoluteModulePaths;${env:PSModulePath}" 592 | ("/tmp/packer-dsc-pull/module-0".Split(";") | ForEach-Object { gci -Recurse $_ | ForEach-Object { Unblock-File $_.FullName} }) 593 | 594 | 595 | $script = $("/tmp/packer-dsc-pull/manifest/packer-dsc-pull-manifest" | Resolve-Path) 596 | echo "PSModulePath Configured: ${env:PSModulePath}" 597 | echo "Running Configuration file: ${script}" 598 | 599 | 600 | # Generate the MOF file, only if a MOF path not already provided. 601 | # Import the Manifest 602 | . $script 603 | 604 | cd "/tmp/packer-dsc-pull" 605 | $StagingPath = $(Join-Path "/tmp/packer-dsc-pull" "staging") 606 | 607 | SomeProjectName -OutputPath $StagingPath -Website "Beanstalk" 608 | 609 | 610 | # Start a DSC Configuration run 611 | Start-DscConfiguration -Force -Wait -Verbose -Path $StagingPath` 612 | 613 | if scriptContents != strings.TrimSpace(expectedCommand) { 614 | t.Fatalf("Expected:\n\n%s\n\nbut got: \n\n%s", strings.TrimSpace(expectedCommand), scriptContents) 615 | } 616 | } 617 | 618 | func TestProvisioner_removeDir(t *testing.T) { 619 | config := testConfig() 620 | p := new(Provisioner) 621 | err := p.Prepare(config) 622 | if err != nil { 623 | t.Fatalf("err: %s", err) 624 | } 625 | ui := &packer.MachineReadableUi{ 626 | Writer: ioutil.Discard, 627 | } 628 | comm := new(packer.MockCommunicator) 629 | err = p.removeDir(ui, comm, "somedir") 630 | if err != nil { 631 | t.Fatalf("err: %s", err) 632 | } 633 | 634 | comm.StartExitStatus = 1 635 | err = p.removeDir(ui, comm, "somedir") 636 | if err == nil { 637 | t.Fatalf("Expected error but got none") 638 | } 639 | 640 | } 641 | -------------------------------------------------------------------------------- /scripts/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # This script builds the application from source for multiple platforms. 4 | set -e 5 | 6 | # Get the parent directory of where this script is. 7 | SOURCE="${BASH_SOURCE[0]}" 8 | while [ -h "$SOURCE" ] ; do SOURCE="$(readlink "$SOURCE")"; done 9 | DIR="$( cd -P "$( dirname "$SOURCE" )/.." && pwd )" 10 | 11 | # Change into that directory 12 | cd $DIR 13 | 14 | # Get the git commit 15 | GIT_COMMIT=$(git rev-parse HEAD) 16 | GIT_DIRTY=$(test -n "`git status --porcelain`" && echo "+CHANGES" || true) 17 | 18 | # If its dev mode, only build for ourself 19 | if [ "${TF_DEV}x" != "x" ]; then 20 | XC_OS=${XC_OS:-$(go env GOOS)} 21 | XC_ARCH="386 amd64" 22 | fi 23 | 24 | # Determine the arch/os combos we're building for 25 | XC_ARCH=${XC_ARCH:-"386 amd64 arm"} 26 | XC_OS=${XC_OS:-linux darwin windows freebsd openbsd} 27 | 28 | # Delete the old dir 29 | echo "==> Removing old directory..." 30 | rm -f bin/* 31 | rm -rf pkg/* 32 | mkdir -p bin/ 33 | 34 | # Build! 35 | echo "==> Building..." 36 | set +e 37 | gox \ 38 | -os="${XC_OS}" \ 39 | -arch="${XC_ARCH}" \ 40 | -output "pkg/{{.OS}}_{{.Arch}}/packer-{{.Dir}}" \ 41 | ./plugin/provisioner-dsc 42 | set -e 43 | 44 | # Move all the compiled things to the $GOPATH/bin 45 | GOPATH=${GOPATH:-$(go env GOPATH)} 46 | case $(uname) in 47 | CYGWIN*|MSYS_NT*|MINGW64*) 48 | GOPATH="$(cygpath $GOPATH)" 49 | ;; 50 | esac 51 | OLDIFS=$IFS 52 | IFS=: MAIN_GOPATH=($GOPATH) 53 | IFS=$OLDIFS 54 | 55 | # Copy our OS/Arch to the bin/ directory 56 | echo "==> Copying binaries for this platform..." 57 | DEV_PLATFORM="./pkg/$(go env GOOS)_$(go env GOARCH)" 58 | for F in $(find ${DEV_PLATFORM} -mindepth 1 -maxdepth 1 -type f); do 59 | cp ${F} bin/ 60 | cp ${F} ${MAIN_GOPATH}/bin/ 61 | done 62 | 63 | # If its dev mode, update the shasums in parity.rb 64 | if [ "${TF_DEV}x" != "x" ]; then 65 | # Update parity.rb 66 | echo "==> Updating ./scripts/parity.rb with latest SHASUMS" 67 | case $(uname) in 68 | CYGWIN*|MSYS_NT*|MINGW64*) 69 | HASH32=$(sha256sum pkg/windows_386/packer-provisioner-dsc | cut -d" " -f 1) 70 | HASH64=$(sha256sum pkg/windows_amd64/packer-provisioner-dsc | cut -d" " -f 1) 71 | ;; 72 | * ) 73 | HASH32=$(shasum -a 1 pkg/darwin_386/packer-provisioner-dsc | cut -d" " -f 1) 74 | HASH64=$(shasum -a 1 pkg/darwin_amd64/packer-provisioner-dsc | cut -d" " -f 1) 75 | ;; 76 | esac 77 | sed -i "9s/sha1 '\(.*\)'/sha1 '${HASH32}'/g" scripts/packer-provisioner-dsc.rb 78 | sed -i "12s/sha1 '\(.*\)'/sha1 '${HASH64}'/g" scripts/packer-provisioner-dsc.rb 79 | fi 80 | 81 | # Done! 82 | echo 83 | echo "==> Results:" 84 | ls -hl bin/ 85 | -------------------------------------------------------------------------------- /scripts/packer-provisioner-dsc.rb: -------------------------------------------------------------------------------- 1 | require 'formula' 2 | 3 | class PackerProvisionerDsc < Formula 4 | homepage "https://github.com/mefellows/packer-dsc/" 5 | version "0.0.5-pre-release" 6 | 7 | if Hardware::CPU.is_64_bit? 8 | url "https://github.com/mefellows/packer-dsc/releases/download/#{version}/darwin_amd64.zip" 9 | sha1 'a9e619b230cdf5b8ff1bb65d56d652d14eaa80e7f83a4fc6bc48fe9c524c89a3' 10 | else 11 | url "https://github.com/mefellows/packer-dsc/releases/download/#{version}/darwin_386.zip" 12 | sha1 '4436241b87377e389d23ed697928dab5e14013294258ff1d22e02d6075ca4e4b' 13 | end 14 | 15 | depends_on :arch => :intel 16 | 17 | def install 18 | pluginpath = Pathname.new("/Users/#{ENV['USER']}/.packer.d/plugins") 19 | 20 | unless File.directory?(pluginpath) 21 | mkdir_p(pluginpath) 22 | end 23 | 24 | cp_r Dir["*"], pluginpath 25 | bin.install Dir['*'] 26 | end 27 | 28 | test do 29 | minimal = testpath/"minimal.json" 30 | minimal.write <<-EOS.undent 31 | { 32 | "builders": [ 33 | { 34 | "type": "null", 35 | "ssh_host": "foo", 36 | "ssh_username": "bar", 37 | "ssh_password": "baz" 38 | } 39 | ], 40 | "provisioners": [ 41 | { 42 | "type": "dsc", 43 | "configuration_name": "Beanstalk", 44 | "configuration_file": "manifests/BeanstalkConfig.psd1", 45 | "manifest_file": "manifests/Beanstalk.ps1", 46 | "module_paths": [ 47 | "modules" 48 | ], 49 | "configuration_params": { 50 | "-WebAppPath": "c:\\tmp", 51 | "-MachineName": "localhost" 52 | } 53 | } 54 | ] 55 | } 56 | EOS 57 | system "packer", "validate", minimal 58 | end 59 | end 60 | -------------------------------------------------------------------------------- /scripts/test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | 3 | # Get Test dependencies 4 | go get github.com/axw/gocov/gocov 5 | go get github.com/mattn/goveralls 6 | go get golang.org/x/tools/cmd/cover 7 | # go get code.google.com/p/go.tools/cmd/cover 8 | go get github.com/modocache/gover 9 | 10 | # Run test coverage on each subdirectories and merge the coverage profile. 11 | 12 | echo "mode: count" > profile.cov 13 | 14 | # Standard go tooling behavior is to ignore dirs with leading underscors 15 | for dir in $(find . -maxdepth 10 -not -path './.git*' -not -path './vendor*' -not -path './examples/*' -not -path './pkg' -not -path './bin' -not -path './scripts' -not -path '*/_*' -type d); do 16 | if ls $dir/*.go &> /dev/null; then 17 | go test -covermode=count -coverprofile=$dir/profile.tmp $dir 18 | if [ $? = 1 ]; then 19 | echo "Test failure, exiting" 20 | exit 1 21 | fi 22 | 23 | if [ -f $dir/profile.tmp ]; then 24 | cat $dir/profile.tmp | tail -n +2 >> profile.cov 25 | rm $dir/profile.tmp 26 | fi 27 | fi 28 | done 29 | 30 | go tool cover -func profile.cov -------------------------------------------------------------------------------- /vendor.yml: -------------------------------------------------------------------------------- 1 | vendors: 2 | - path: github.com/hashicorp/errwrap 3 | rev: 7554cd9344cec97297fa6649b055a8c98c2a1e55 4 | - path: github.com/hashicorp/go-checkpoint 5 | rev: a8d0786e7fa88adb6b3bcaa341a99af7f9740671 6 | - path: github.com/hashicorp/go-cleanhttp 7 | rev: 3573b8b52aa7b37b9358d966a898feb387f62437 8 | - path: github.com/hashicorp/go-multierror 9 | rev: 83588e72410abfbe4df460eeb6f30841ae47d4c4 10 | - path: github.com/hashicorp/go-uuid 11 | rev: 64130c7a86d732268a38cb04cfbaf0cc987fda98 12 | - path: github.com/hashicorp/go-version 13 | rev: 03c5bf6be031b6dd45afec16b1cf94fc8938bc77 14 | - path: github.com/hashicorp/packer 15 | rev: 324581ac9ce8d1e0558b33eea9d4f9d6d5a16002 16 | - path: github.com/hashicorp/yamux 17 | rev: d1caa6c97c9fc1cc9e83bbe34d0603f9ff0ce8bd 18 | - path: github.com/mitchellh/go-fs 19 | rev: 7bae45d9a684750e82b97ff320c82556614e621b 20 | - path: github.com/mitchellh/iochan 21 | rev: 87b45ffd0e9581375c491fef3d32130bb15c5bd7 22 | - path: github.com/mitchellh/mapstructure 23 | rev: d0303fe809921458f417bcf828397a65db30a7e4 24 | - path: github.com/mitchellh/multistep 25 | rev: 391576a156a54cfbb4cf5d5eda40cf6ffa3e3a4d 26 | - path: github.com/mitchellh/reflectwalk 27 | rev: 8d802ff4ae93611b807597f639c19f76074df5c6 28 | - path: github.com/ugorji/go 29 | rev: 5efa3251c7f7d05e5d9704a69a984ec9f1386a40 30 | - path: github.com/hashicorp/hcl/v2 -------------------------------------------------------------------------------- /wercker.yml: -------------------------------------------------------------------------------- 1 | box: tcnksm/gox:1.7 2 | build: 3 | steps: 4 | - setup-go-workspace 5 | # - golint: 6 | # exclude: "vendor" 7 | - script: 8 | name: go get 9 | code: | 10 | make updatedeps 11 | - script: 12 | name: go test 13 | code: | 14 | make test 15 | - script: 16 | name: Publish Coveralls 17 | code: goveralls -service="wercker.com" -coverprofile=profile.cov -repotoken $COVERALLS_TOKEN 18 | - script: 19 | name: gox build 20 | code: | 21 | XC_OS="linux darwin windows" XC_ARCH="386 amd64" make bin 22 | - tcnksm/zip: 23 | input: pkg 24 | output: $WERCKER_OUTPUT_DIR/dist 25 | 26 | deploy: 27 | steps: 28 | - tcnksm/ghr: 29 | token: $GITHUB_TOKEN 30 | version: $RELEASE_VERSION 31 | input: dist 32 | replace: $RELEASE_IS_DRAFT 33 | pre-release: $RELEASE_IS_DRAFT 34 | --------------------------------------------------------------------------------