├── .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 | [](https://coveralls.io/github/mefellows/packer-dsc?branch=HEAD)
14 | [](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 |
--------------------------------------------------------------------------------