kitchen-dsc 0.9.0 → 0.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f85b4e08d3cce5d8e8023cbfeee34b3529dca80f
4
- data.tar.gz: 17f38a13535a39115dcdbb8216096418e39a2a9f
3
+ metadata.gz: 0043ea70755d3de429c6744f3103a484c9841cec
4
+ data.tar.gz: 005604228f4f2424e72fb41dc9e5a09c1ca9d42e
5
5
  SHA512:
6
- metadata.gz: c4ecfa02f5cef6df1c1b43b4727580bee86df0986aa3a97d385d6badd38f5a3be2940d250f4e91ecd070f5a184c7a4a7e11463ae12aaf7ffb6800d7526ae0dc6
7
- data.tar.gz: 75159d184589220d0a37fee3b15b42c161a3bff167de64b885376df9f20cecddbe7ad435d9f191c86a61eab4f4048ef7987f5dc8a7c7dd5f0376611d55bea58f
6
+ metadata.gz: 65587a52d7f8d0a40d014cc5f28b8c18a32a69512bd22cf1776a545878c638526559f4ccdabe07db6b95ffc33c92e0a90d75b1d3fa376cf29f5dc19a1e49f1e0
7
+ data.tar.gz: 8fb1f84cb6d84cfa0b949e45e2b4bf0aba3dcfd653dcf4ce688f685e1ab501f7e8c1f20d35dda377017199b5417cc947deb70f537e61e0931dfe81727c7aa5d2
data/README.md CHANGED
@@ -1,108 +1,108 @@
1
- [![Gem Version](https://badge.fury.io/rb/kitchen-dsc.svg)](http://badge.fury.io/rb/kitchen-dsc)
2
-
3
- # kitchen-dsc
4
- A Test Kitchen Provisioner for PowerShell DSC
5
-
6
-
7
- ## Requirements
8
- You'll need a driver box with WMF4 or greater (ONLY WINDOWS SYSTEMS)
9
-
10
- ## Installation & Setup
11
- You'll need the test-kitchen & kitchen-dsc gems installed in your system, along with kitchen-vagrant or some ther suitable driver for test-kitchen.
12
-
13
- ### Note:
14
- You will see a delay in the return of the run details due to an difference in how the verbose stream is returned for DSC runs between WMF versions, so I return the verbose stream after the job completes. I'd love to live stream the results, but that'll take a bit more experimentation. (PR's welcome!)
15
-
16
- ## Example Configurations
17
- * [Repository Style Testing](https://github.com/smurawski/dsc-kitchen-project)
18
- * [Module Style Testing](https://github.com/powershellorg/cwebadministration/tree/smurawski/adding_tests)
19
-
20
- ## Configuration Settings
21
- * configuration_script_folder
22
- * Defaults to 'examples'.
23
- * The location of a PowerShell script(s) containing the DSC configuration command(s).
24
-
25
- * configuration_script
26
- * Defaults to 'dsc_configuration.ps1'
27
- * The name of the PowerShell script containing the DSC configuration command(s) (and possibly configuration data)
28
-
29
- * configuration_name
30
- * Name of the configuration to run, defaults to the suite name.
31
-
32
- * configuration_data
33
- * A YAML representation of what should be passed to the configuration.
34
- * Overrides any configurationdata variable assigned in the configuration script.
35
-
36
- * configuration_data_variable
37
- * Defaults to 'ConfigurationData'
38
- * Name of the variable that contains the ConfigurationData hashtable
39
- * Can be defined in the configuration script or via the `configuration_data` configuration setting.
40
-
41
- * dsc_local_configuration_manager_version
42
- * Defaults to 'wmf4'
43
- * Identifies what version of the LCM is in place
44
- * Other valid values are 'wmf4_with_update' and 'wmf5'
45
- * Currently the only difference between wmf4 and wmf4_with_update/wmf5 is the action_after_reboot and the debug_mode settings. Eventually, I'd like to add support for partial configurations, pull servers, etc..
46
- * In this context, wmf4_with_update refers to wmf4 with KB3000850 applied (to add support for WMF 5 generated configurations, plus some fixes).
47
-
48
- * dsc_local_configuration_manager
49
- * Settings for the LCM
50
- * Defaults are:
51
- * action_after_reboot = 'StopConfiguration' # wmf4_with_update or wmf5
52
- * reboot_if_needed = false
53
- * allow_module_overwrite = false
54
- * certificate_id = nil
55
- * configuration_mode = 'ApplyAndAutoCorrect'
56
- * configuration_mode_frequency_mins = 30 # 15 on wmf5
57
- * debug_mode = 'All' # wmf4_with_update
58
- * refresh_frequency_mins = 15 # 30 on wmf5
59
- * refresh_mode = 'PUSH'
60
-
61
- * modules_from_gallery
62
- * Requires WMF 5
63
- * Takes a string (for one module) or an array (for multiple) to install from the gallery
64
- * Or takes a hash with keys matching the parameters for install-module.
65
- * Name is required.
66
- * Force is automatically used and not required as part of the hash table.
67
- * Repository defaults to either PSGallery or any custom feed defined, but can be overriden here.
68
-
69
- * gallery_name
70
- * Custom PowerShell gallery name to install modules from.
71
- * If there is no package source with this name registered on the machine, then gallery_uri must be configured as well.
72
-
73
- * gallery_uri
74
- * URI for a custom PowerShell gallery feed.
75
-
76
- ### Specific to repository style testing
77
- * modules_path
78
- * Defaults to 'modules'.
79
- * Points to the location of modules containing DSC resources to upload
80
- * This path is relative to the root of the repository (the location of the .kitchen.yml).
81
-
82
- ## Example
83
-
84
- ```yaml
85
- provisioner:
86
- - name: dsc
87
- dsc_local_configuration_manager_version: wmf5
88
- dsc_local_configuration_manager:
89
- reboot_if_needed: true
90
- debug_mode: none
91
- configuration_script_folder: .
92
- configuration_script: SampleConfig.ps1
93
- gallery_uri: https://ci.appveyor.com/nuget/xWebAdministration
94
- gallery_name: xWebDevFeed
95
- modules_from_gallery:
96
- - xWebAdministration
97
- - name: xComputerManagement
98
- requiredversion: 1.4.0.0
99
- repository: PSGallery
100
-
101
- suite:
102
- - name: test
103
- provisioner:
104
- configuration_data:
105
- AllNodes:
106
- - nodename: localhost
107
- role: webserver
1
+ [![Gem Version](https://badge.fury.io/rb/kitchen-dsc.svg)](http://badge.fury.io/rb/kitchen-dsc)
2
+
3
+ # kitchen-dsc
4
+ A Test Kitchen Provisioner for PowerShell DSC
5
+
6
+
7
+ ## Requirements
8
+ You'll need a driver box with WMF4 or greater (ONLY WINDOWS SYSTEMS)
9
+
10
+ ## Installation & Setup
11
+ You'll need the test-kitchen & kitchen-dsc gems installed in your system, along with kitchen-vagrant or some ther suitable driver for test-kitchen.
12
+
13
+ ### Note:
14
+ You will see a delay in the return of the run details due to an difference in how the verbose stream is returned for DSC runs between WMF versions, so I return the verbose stream after the job completes. I'd love to live stream the results, but that'll take a bit more experimentation. (PR's welcome!)
15
+
16
+ ## Example Configurations
17
+ * [Repository Style Testing](https://github.com/smurawski/dsc-kitchen-project)
18
+ * [Module Style Testing](https://github.com/powershellorg/cwebadministration/tree/smurawski/adding_tests)
19
+
20
+ ## Configuration Settings
21
+ * configuration_script_folder
22
+ * Defaults to 'examples'.
23
+ * The location of a PowerShell script(s) containing the DSC configuration command(s).
24
+
25
+ * configuration_script
26
+ * Defaults to 'dsc_configuration.ps1'
27
+ * The name of the PowerShell script containing the DSC configuration command(s) (and possibly configuration data)
28
+
29
+ * configuration_name
30
+ * Name of the configuration to run, defaults to the suite name.
31
+
32
+ * configuration_data
33
+ * A YAML representation of what should be passed to the configuration.
34
+ * Overrides any configurationdata variable assigned in the configuration script.
35
+
36
+ * configuration_data_variable
37
+ * Defaults to 'ConfigurationData'
38
+ * Name of the variable that contains the ConfigurationData hashtable
39
+ * Can be defined in the configuration script or via the `configuration_data` configuration setting.
40
+
41
+ * dsc_local_configuration_manager_version
42
+ * Defaults to 'wmf4'
43
+ * Identifies what version of the LCM is in place
44
+ * Other valid values are 'wmf4_with_update' and 'wmf5'
45
+ * Currently the only difference between wmf4 and wmf4_with_update/wmf5 is the action_after_reboot and the debug_mode settings. Eventually, I'd like to add support for partial configurations, pull servers, etc..
46
+ * In this context, wmf4_with_update refers to wmf4 with KB3000850 applied (to add support for WMF 5 generated configurations, plus some fixes).
47
+
48
+ * dsc_local_configuration_manager
49
+ * Settings for the LCM
50
+ * Defaults are:
51
+ * action_after_reboot = 'StopConfiguration' # wmf4_with_update or wmf5
52
+ * reboot_if_needed = false
53
+ * allow_module_overwrite = false
54
+ * certificate_id = nil
55
+ * configuration_mode = 'ApplyAndAutoCorrect'
56
+ * configuration_mode_frequency_mins = 30 # 15 on wmf5
57
+ * debug_mode = 'All' # wmf4_with_update
58
+ * refresh_frequency_mins = 15 # 30 on wmf5
59
+ * refresh_mode = 'PUSH'
60
+
61
+ * modules_from_gallery
62
+ * Requires WMF 5
63
+ * Takes a string (for one module) or an array (for multiple) to install from the gallery
64
+ * Or takes a hash with keys matching the parameters for install-module.
65
+ * Name is required.
66
+ * Force is automatically used and not required as part of the hash table.
67
+ * Repository defaults to either PSGallery or any custom feed defined, but can be overriden here.
68
+
69
+ * gallery_name
70
+ * Custom PowerShell gallery name to install modules from.
71
+ * If there is no package source with this name registered on the machine, then gallery_uri must be configured as well.
72
+
73
+ * gallery_uri
74
+ * URI for a custom PowerShell gallery feed.
75
+
76
+ ### Specific to repository style testing
77
+ * modules_path
78
+ * Defaults to 'modules'.
79
+ * Points to the location of modules containing DSC resources to upload
80
+ * This path is relative to the root of the repository (the location of the .kitchen.yml).
81
+
82
+ ## Example
83
+
84
+ ```yaml
85
+ provisioner:
86
+ - name: dsc
87
+ dsc_local_configuration_manager_version: wmf5
88
+ dsc_local_configuration_manager:
89
+ reboot_if_needed: true
90
+ debug_mode: none
91
+ configuration_script_folder: .
92
+ configuration_script: SampleConfig.ps1
93
+ gallery_uri: https://ci.appveyor.com/nuget/xWebAdministration
94
+ gallery_name: xWebDevFeed
95
+ modules_from_gallery:
96
+ - xWebAdministration
97
+ - name: xComputerManagement
98
+ requiredversion: 1.4.0.0
99
+ repository: PSGallery
100
+
101
+ suite:
102
+ - name: test
103
+ provisioner:
104
+ configuration_data:
105
+ AllNodes:
106
+ - nodename: localhost
107
+ role: webserver
108
108
  ```
data/kitchen-dsc.gemspec CHANGED
@@ -1,41 +1,41 @@
1
- # encoding: utf-8
2
-
3
- $LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
4
- require 'kitchen-dsc/version'
5
-
6
- Gem::Specification.new do |s|
7
- s.name = 'kitchen-dsc'
8
- s.version = Kitchen::Dsc::VERSION
9
- s.authors = ['Steven Murawski']
10
- s.email = ['smurawski@chef.io']
11
- s.homepage = 'https://github.com/test-kitchen/kitchen-dsc'
12
- s.summary = 'PowerShell DSC provisioner for test-kitchen'
13
- candidates = Dir.glob('lib/**/*') + ['README.md', 'kitchen-dsc.gemspec']
14
- s.files = candidates.sort
15
- s.platform = Gem::Platform::RUBY
16
- s.require_paths = ['lib']
17
- s.rubyforge_project = '[none]'
18
- s.license = 'Apache 2'
19
- s.description = <<-EOF
20
- == DESCRIPTION:
21
-
22
- DSC Provisioner for Test Kitchen
23
-
24
- == FEATURES:
25
-
26
- TBD
27
-
28
- EOF
29
- s.add_dependency 'test-kitchen', '~> 1.10'
30
-
31
- s.add_development_dependency 'countloc', '~> 0.4'
32
- s.add_development_dependency 'rake'
33
- s.add_development_dependency 'rspec', '~> 3.2'
34
- s.add_development_dependency 'simplecov', '~> 0.9'
35
-
36
- # style and complexity libraries are tightly version pinned as newer releases
37
- # may introduce new and undesireable style choices which would be immediately
38
- # enforced in CI
39
- s.add_development_dependency 'finstyle', '1.4.0'
40
- s.add_development_dependency 'cane', '2.6.2'
41
- end
1
+ # encoding: utf-8
2
+
3
+ $LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
4
+ require 'kitchen-dsc/version'
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = 'kitchen-dsc'
8
+ s.version = Kitchen::Dsc::VERSION
9
+ s.authors = ['Steven Murawski']
10
+ s.email = ['smurawski@chef.io']
11
+ s.homepage = 'https://github.com/test-kitchen/kitchen-dsc'
12
+ s.summary = 'PowerShell DSC provisioner for test-kitchen'
13
+ candidates = Dir.glob('lib/**/*') + ['README.md', 'kitchen-dsc.gemspec']
14
+ s.files = candidates.sort
15
+ s.platform = Gem::Platform::RUBY
16
+ s.require_paths = ['lib']
17
+ s.rubyforge_project = '[none]'
18
+ s.license = 'Apache 2'
19
+ s.description = <<-EOF
20
+ == DESCRIPTION:
21
+
22
+ DSC Provisioner for Test Kitchen
23
+
24
+ == FEATURES:
25
+
26
+ TBD
27
+
28
+ EOF
29
+ s.add_dependency 'test-kitchen', '~> 1.10'
30
+
31
+ s.add_development_dependency 'countloc', '~> 0.4'
32
+ s.add_development_dependency 'rake'
33
+ s.add_development_dependency 'rspec', '~> 3.2'
34
+ s.add_development_dependency 'simplecov', '~> 0.9'
35
+
36
+ # style and complexity libraries are tightly version pinned as newer releases
37
+ # may introduce new and undesireable style choices which would be immediately
38
+ # enforced in CI
39
+ s.add_development_dependency 'finstyle', '1.4.0'
40
+ s.add_development_dependency 'cane', '2.6.2'
41
+ end
@@ -1,7 +1,7 @@
1
- # encoding: utf-8
2
-
3
- module Kitchen
4
- module Dsc
5
- VERSION = '0.9.0'.freeze
6
- end
7
- end
1
+ # encoding: utf-8
2
+
3
+ module Kitchen
4
+ module Dsc
5
+ VERSION = '0.9.2'.freeze
6
+ end
7
+ end
@@ -1,368 +1,362 @@
1
- # -*- encoding: utf-8 -*-
2
- #
3
- # Author:: Steven Murawski (<steven.murawski@gmail.com>)
4
- #
5
- # Copyright (C) 2014 Steven Murawski
6
- #
7
- # Licensed under the MIT License.
8
- # See LICENSE for more details
9
-
10
- require 'fileutils'
11
- require 'pathname'
12
- require 'kitchen/provisioner/base'
13
- require 'kitchen/util'
14
-
15
- module Kitchen
16
- module Provisioner
17
- class Dsc < Base
18
- kitchen_provisioner_api_version 2
19
-
20
- attr_accessor :tmp_dir
21
-
22
- default_config :modules_path, 'modules'
23
-
24
- default_config :configuration_script_folder, 'examples'
25
- default_config :configuration_script, 'dsc_configuration.ps1'
26
- default_config :configuration_name do |provisioner|
27
- provisioner.instance.suite.name
28
- end
29
-
30
- default_config :configuration_data_variable, 'ConfigurationData'
31
- default_config :configuration_data
32
-
33
- default_config :nuget_force_bootstrap, true
34
- default_config :gallery_uri
35
- default_config :gallery_name
36
- default_config :modules_from_gallery
37
-
38
- default_config :dsc_local_configuration_manager_version, 'wmf4'
39
- default_config :dsc_local_configuration_manager
40
-
41
- def override_lcm_setting?(name)
42
- if config[:dsc_local_configuration_manager].nil? ||
43
- config[:dsc_local_configuration_manager][name.to_sym].nil?
44
- false
45
- else
46
- true
47
- end
48
- end
49
-
50
- def resolve_lcm_setting(name, default_value)
51
- if override_lcm_setting? name
52
- config[:dsc_local_configuration_manager][name.to_sym]
53
- else
54
- default_value
55
- end
56
- end
57
-
58
- def lcm_settings
59
- {
60
- action_after_reboot: (resolve_lcm_setting 'action_after_reboot', 'StopConfiguration'),
61
- allow_module_overwrite: (resolve_lcm_setting 'allow_module_overwrite', false),
62
- certificate_id: (resolve_lcm_setting 'certificate_id', nil),
63
- configuration_mode: (resolve_lcm_setting 'configuration_mode', 'ApplyAndAutoCorrect'),
64
- debug_mode: (resolve_lcm_setting 'debug_mode', 'All'),
65
- reboot_if_needed: (resolve_lcm_setting 'reboot_if_needed', false),
66
- refresh_mode: (resolve_lcm_setting 'refresh_mode', 'PUSH')
67
- }
68
- end
69
-
70
- def install_command
71
- lcm_config = lcm_settings
72
- case config[:dsc_local_configuration_manager_version]
73
- when 'wmf4_legacy', 'wmf4'
74
- lcm_configuration_script = <<-LCMSETUP
75
- configuration SetupLCM
76
- {
77
- LocalConfigurationManager
78
- {
79
- AllowModuleOverwrite = [bool]::Parse('#{lcm_config[:allow_module_overwrite]}')
80
- CertificateID = '#{lcm_config[:certificate_id].nil? ? '$null' : lcm_config[:certificate_id]}'
81
- ConfigurationMode = '#{lcm_config[:configuration_mode]}'
82
- ConfigurationModeFrequencyMins = #{lcm_config[:configuration_mode_frequency_mins].nil? ? '30' : lcm_config[:configuration_mode_frequency_mins]}
83
- RebootNodeIfNeeded = [bool]::Parse('#{lcm_config[:reboot_if_needed]}')
84
- RefreshFrequencyMins = #{lcm_config[:refresh_frequency_mins].nil? ? '15' : lcm_config[:refresh_frequency_mins]}
85
- RefreshMode = '#{lcm_config[:refresh_mode]}'
86
- }
87
- }
88
- LCMSETUP
89
- when 'wmf4_with_update'
90
- lcm_configuration_script = <<-LCMSETUP
91
- configuration SetupLCM
92
- {
93
- LocalConfigurationManager
94
- {
95
- ActionAfterReboot = '#{lcm_config[:action_after_reboot]}'
96
- AllowModuleOverwrite = [bool]::Parse('#{lcm_config[:allow_module_overwrite]}')
97
- CertificateID = '#{lcm_config[:certificate_id].nil? ? '$null' : lcm_config[:certificate_id]}'
98
- ConfigurationMode = '#{lcm_config[:configuration_mode]}'
99
- ConfigurationModeFrequencyMins = #{lcm_config[:configuration_mode_frequency_mins].nil? ? '30' : lcm_config[:configuration_mode_frequency_mins]}
100
- DebugMode = '#{lcm_config[:debug_mode]}'
101
- RebootNodeIfNeeded = [bool]::Parse('#{lcm_config[:reboot_if_needed]}')
102
- RefreshFrequencyMins = #{lcm_config[:refresh_frequency_mins].nil? ? '15' : lcm_config[:refresh_frequency_mins]}
103
- RefreshMode = '#{lcm_config[:refresh_mode]}'
104
- }
105
- }
106
- LCMSETUP
107
- when 'wmf5'
108
- lcm_configuration_script = <<-LCMSETUP
109
- [DSCLocalConfigurationManager()]
110
- configuration SetupLCM
111
- {
112
- Settings
113
- {
114
- ActionAfterReboot = '#{lcm_config[:action_after_reboot]}'
115
- AllowModuleOverwrite = [bool]::Parse('#{lcm_config[:allow_module_overwrite]}')
116
- CertificateID = '#{lcm_config[:certificate_id].nil? ? '$null' : lcm_config[:certificate_id]}'
117
- ConfigurationMode = '#{lcm_config[:configuration_mode]}'
118
- ConfigurationModeFrequencyMins = #{lcm_config[:configuration_mode_frequency_mins].nil? ? '15' : lcm_config[:configuration_mode_frequency_mins]}
119
- DebugMode = '#{lcm_config[:debug_mode]}'
120
- RebootNodeIfNeeded = [bool]::Parse('#{lcm_config[:reboot_if_needed]}')
121
- RefreshFrequencyMins = #{lcm_config[:refresh_frequency_mins].nil? ? '30' : lcm_config[:refresh_frequency_mins]}
122
- RefreshMode = '#{lcm_config[:refresh_mode]}'
123
- }
124
- }
125
- LCMSETUP
126
- end
127
- full_lcm_configuration_script = <<-EOH
128
- #{lcm_configuration_script}
129
-
130
- $null = SetupLCM
131
- Set-DscLocalConfigurationManager -Path ./SetupLCM | out-null
132
- EOH
133
-
134
- wrap_shell_code(full_lcm_configuration_script)
135
- end
136
- # rubocop:enable Metrics/LineLength
137
-
138
- def setup_config_directory_script
139
- "mkdir (split-path (join-path #{config[:root_path]} #{sandboxed_configuration_script})) -force | out-null"
140
- end
141
-
142
- def powershell_modules
143
- Array(config[:modules_from_gallery]).map do |powershell_module|
144
- params = if powershell_module.is_a? Hash
145
- keys = powershell_module.keys.reject { |k| k.to_s.downcase! == 'force' }
146
- unless keys.any? { |k| k.to_s.downcase! == 'repository' }
147
- keys.push(:repository)
148
- powershell_module[:repository] = psmodule_repository_name
149
- end
150
- keys.map do |key|
151
- "-#{key} #{powershell_module[key]}"
152
- end.join(' ')
153
- else
154
- "-name '#{powershell_module}' -Repository #{psmodule_repository_name}"
155
- end
156
- "install-module #{params} -force | out-null"
157
- end
158
- end
159
-
160
- def nuget_force_bootstrap
161
- return unless config[:nuget_force_bootstrap]
162
- info('Bootstrapping the nuget package provider for PowerShell PackageManagement.')
163
- 'install-packageprovider nuget -force -forcebootstrap | out-null'
164
- end
165
-
166
- def psmodule_repository_name
167
- return 'PSGallery' if config[:gallery_name].nil? && config[:gallery_uri].nil?
168
- return 'testing' if config[:gallery_name].nil?
169
- config[:gallery_name]
170
- end
171
-
172
- def register_psmodule_repository
173
- return if config[:gallery_uri].nil?
174
- info("Registering a new PowerShellGet Repository - #{psmodule_repository_name}")
175
- "register-packagesource -providername PowerShellGet -name '#{psmodule_repository_name}' -location '#{config[:gallery_uri]}' -force -trusted"
176
- end
177
-
178
- def install_module_script
179
- return if config[:modules_from_gallery].nil?
180
- <<-EOH
181
- #{nuget_force_bootstrap}
182
- #{register_psmodule_repository}
183
- #{powershell_modules.join("\n")}
184
- EOH
185
- end
186
-
187
- def install_modules?
188
- config[:dsc_local_configuration_manager_version] == 'wmf5' &&
189
- !config[:modules_from_gallery].nil?
190
- end
191
-
192
- def init_command
193
- script = <<-EOH
194
- #{setup_config_directory_script}
195
- #{install_module_script if install_modules?}
196
- EOH
197
- wrap_shell_code(script)
198
- end
199
-
200
- def create_sandbox
201
- super
202
- info('Staging DSC Resource Modules for copy to the SUT')
203
- if resource_module? || class_resource_module?
204
- prepare_resource_style_directory
205
- else
206
- prepare_repo_style_directory
207
- end
208
- info('Staging DSC configuration script for copy to the SUT')
209
- prepare_configuration_script
210
- end
211
-
212
- def prepare_command
213
- info('Moving DSC Resources onto PSModulePath')
214
- info("Generating the MOF script for the configuration #{config[:configuration_name]}")
215
- stage_resources_and_generate_mof_script = <<-EOH
216
- if (Test-Path (join-path #{config[:root_path]} 'modules'))
217
- {
218
- dir ( join-path #{config[:root_path]} 'modules/*') -directory |
219
- copy-item -destination $env:programfiles/windowspowershell/modules/ -recurse -force
220
- }
221
- if (-not (test-path 'c:/configurations'))
222
- {
223
- mkdir 'c:/configurations' | out-null
224
- }
225
- $ConfigurationScriptPath = Join-path #{config[:root_path]} #{sandboxed_configuration_script}
226
- if (-not (test-path $ConfigurationScriptPath))
227
- {
228
- throw "Failed to find $ConfigurationScriptPath"
229
- }
230
- invoke-expression (get-content $ConfigurationScriptPath -raw)
231
- if (-not (get-command #{config[:configuration_name]}))
232
- {
233
- throw "Failed to create a configuration command #{config[:configuration_name]}"
234
- }
235
-
236
- #{configuration_data_assignment unless config[:configuration_data].nil?}
237
-
238
- $null = #{config[:configuration_name]} -outputpath c:/configurations #{'-configurationdata $' + configuration_data_variable}
239
- EOH
240
- debug("Shelling out: #{stage_resources_and_generate_mof_script}")
241
- wrap_shell_code(stage_resources_and_generate_mof_script)
242
- end
243
- # rubocop:enable Metrics/LineLength
244
-
245
- def configuration_data_variable
246
- config[:configuration_data_variable].nil? ? 'ConfigurationData' : config[:configuration_data_variable]
247
- end
248
-
249
- def configuration_data_assignment
250
- '$' + configuration_data_variable + ' = ' + ps_hash(config[:configuration_data])
251
- end
252
-
253
- def run_command
254
- config[:retry_on_exit_code] = [35] if config[:retry_on_exit_code].empty?
255
- config[:max_retries] = 3 if config[:max_retries] == 1
256
-
257
- info("Running the configuration #{config[:configuration_name]}")
258
- run_configuration_script = <<-EOH
259
- $ProgressPreference = 'SilentlyContinue'
260
- $job = start-dscconfiguration -Path c:/configurations/ -force
261
- $job | wait-job
262
- $verbose_output = $job.childjobs[0].verbose
263
- $verbose_output
264
- if ($verbose_output -match 'A reboot is required to progress further. Please reboot the system.') {
265
- "A reboot is required to continue."
266
- shutdown /r /t 15
267
- exit 35
268
- }
269
- $dsc_errors = $job.childjobs[0].Error
270
- if ($dsc_errors -ne $null) {
271
- $dsc_errors
272
- exit 1
273
- }
274
- EOH
275
-
276
- debug("Shelling out: #{run_configuration_script}")
277
- wrap_shell_code(run_configuration_script)
278
- end
279
-
280
- private
281
-
282
- def resource_module?
283
- module_metadata_file = File.join(config[:kitchen_root], "#{module_name}.psd1")
284
- module_dsc_resource_folder = File.join(config[:kitchen_root], 'DSCResources')
285
- File.exist?(module_metadata_file) &&
286
- File.exist?(module_dsc_resource_folder)
287
- end
288
-
289
- def class_resource_module?
290
- module_metadata_file = File.join(config[:kitchen_root], "#{module_name}.psd1")
291
- module_dsc_resource_folder = File.join(config[:kitchen_root], 'DSCResources')
292
- File.exist?(module_metadata_file) &&
293
- !File.exist?(module_dsc_resource_folder)
294
- end
295
-
296
- def list_files(path)
297
- base_directory_content = Dir.glob(File.join(path, '*'))
298
- nested_directory_content = Dir.glob(File.join(path, '*/**/*'))
299
- all_directory_content = [base_directory_content, nested_directory_content].flatten
300
-
301
- ignore_files = ['Gemfile', 'Gemfile.lock', 'README.md', 'LICENSE.txt']
302
- all_directory_content.reject do |f|
303
- debug("Enumerating #{f}")
304
- ignore_files.include?(File.basename(f)) || File.directory?(f)
305
- end
306
- end
307
-
308
- def module_name
309
- File.basename(config[:kitchen_root])
310
- end
311
-
312
- def prepare_resource_style_directory
313
- sandbox_base_module_path = File.join(sandbox_path, "modules/#{module_name}")
314
-
315
- base = config[:kitchen_root]
316
- list_files(base).each do |src|
317
- dest = File.join(sandbox_base_module_path, src.sub("#{base}/", ''))
318
- FileUtils.mkdir_p(File.dirname(dest))
319
- debug("Staging #{src} ")
320
- debug(" at #{dest}")
321
- FileUtils.cp(src, dest, preserve: true)
322
- end
323
- end
324
-
325
- def prepare_repo_style_directory
326
- module_path = File.join(config[:kitchen_root], config[:modules_path])
327
- sandbox_module_path = File.join(sandbox_path, 'modules')
328
-
329
- if Dir.exist?(module_path)
330
- debug("Moving #{module_path} to #{sandbox_module_path}")
331
- FileUtils.cp_r(module_path, sandbox_module_path)
332
- else
333
- debug("The modules path #{module_path} was not found. Not moving to #{sandbox_module_path}.")
334
- end
335
- end
336
-
337
- def sandboxed_configuration_script
338
- File.join('configuration', config[:configuration_script])
339
- end
340
-
341
- def pad(depth = 0)
342
- ' ' * depth
343
- end
344
-
345
- def ps_hash(obj, depth = 0)
346
- if obj.is_a?(Hash)
347
- obj.map do |k, v|
348
- %(#{pad(depth + 2)}#{ps_hash(k)} = #{ps_hash(v, depth + 2)})
349
- end.join(";\n").insert(0, "@{\n").insert(-1, "\n#{pad(depth)}}")
350
- elsif obj.is_a?(Array)
351
- array_string = obj.map { |v| ps_hash(v, depth + 4) }.join(',')
352
- "#{pad(depth)}@(\n#{array_string}\n)"
353
- else
354
- %("#{obj}")
355
- end
356
- end
357
-
358
- def prepare_configuration_script
359
- configuration_script_file = File.join(config[:configuration_script_folder], config[:configuration_script])
360
- configuration_script_path = File.join(config[:kitchen_root], configuration_script_file)
361
- sandbox_configuration_script_path = File.join(sandbox_path, sandboxed_configuration_script)
362
- FileUtils.mkdir_p(File.dirname(sandbox_configuration_script_path))
363
- debug("Moving #{configuration_script_path} to #{sandbox_configuration_script_path}")
364
- FileUtils.cp(configuration_script_path, sandbox_configuration_script_path)
365
- end
366
- end
367
- end
368
- end
1
+ # -*- encoding: utf-8 -*-
2
+ #
3
+ # Author:: Steven Murawski (<steven.murawski@gmail.com>)
4
+ #
5
+ # Copyright (C) 2014 Steven Murawski
6
+ #
7
+ # Licensed under the MIT License.
8
+ # See LICENSE for more details
9
+
10
+ require 'fileutils'
11
+ require 'pathname'
12
+ require 'kitchen/provisioner/base'
13
+ require 'kitchen/util'
14
+
15
+ module Kitchen
16
+ module Provisioner
17
+ class Dsc < Base
18
+ kitchen_provisioner_api_version 2
19
+
20
+ attr_accessor :tmp_dir
21
+
22
+ default_config :modules_path, 'modules'
23
+
24
+ default_config :configuration_script_folder, 'examples'
25
+ default_config :configuration_script, 'dsc_configuration.ps1'
26
+ default_config :configuration_name do |provisioner|
27
+ provisioner.instance.suite.name
28
+ end
29
+
30
+ default_config :configuration_data_variable, 'ConfigurationData'
31
+ default_config :configuration_data
32
+
33
+ default_config :nuget_force_bootstrap, true
34
+ default_config :gallery_uri
35
+ default_config :gallery_name
36
+ default_config :modules_from_gallery
37
+
38
+ default_config :dsc_local_configuration_manager_version, 'wmf4'
39
+ default_config :dsc_local_configuration_manager
40
+
41
+ def override_lcm_setting?(name)
42
+ if config[:dsc_local_configuration_manager].nil? ||
43
+ config[:dsc_local_configuration_manager][name.to_sym].nil?
44
+ false
45
+ else
46
+ true
47
+ end
48
+ end
49
+
50
+ def resolve_lcm_setting(name, default_value)
51
+ if override_lcm_setting? name
52
+ config[:dsc_local_configuration_manager][name.to_sym]
53
+ else
54
+ default_value
55
+ end
56
+ end
57
+
58
+ def lcm_settings
59
+ {
60
+ action_after_reboot: (resolve_lcm_setting 'action_after_reboot', 'StopConfiguration'),
61
+ allow_module_overwrite: (resolve_lcm_setting 'allow_module_overwrite', false),
62
+ certificate_id: (resolve_lcm_setting 'certificate_id', nil),
63
+ configuration_mode: (resolve_lcm_setting 'configuration_mode', 'ApplyAndAutoCorrect'),
64
+ debug_mode: (resolve_lcm_setting 'debug_mode', 'All'),
65
+ reboot_if_needed: (resolve_lcm_setting 'reboot_if_needed', false),
66
+ refresh_mode: (resolve_lcm_setting 'refresh_mode', 'PUSH')
67
+ }
68
+ end
69
+
70
+ def install_command
71
+ lcm_config = lcm_settings
72
+ case config[:dsc_local_configuration_manager_version]
73
+ when 'wmf4_legacy', 'wmf4'
74
+ lcm_configuration_script = <<-LCMSETUP
75
+ configuration SetupLCM
76
+ {
77
+ LocalConfigurationManager
78
+ {
79
+ AllowModuleOverwrite = [bool]::Parse('#{lcm_config[:allow_module_overwrite]}')
80
+ CertificateID = '#{lcm_config[:certificate_id].nil? ? '$null' : lcm_config[:certificate_id]}'
81
+ ConfigurationMode = '#{lcm_config[:configuration_mode]}'
82
+ ConfigurationModeFrequencyMins = #{lcm_config[:configuration_mode_frequency_mins].nil? ? '30' : lcm_config[:configuration_mode_frequency_mins]}
83
+ RebootNodeIfNeeded = [bool]::Parse('#{lcm_config[:reboot_if_needed]}')
84
+ RefreshFrequencyMins = #{lcm_config[:refresh_frequency_mins].nil? ? '15' : lcm_config[:refresh_frequency_mins]}
85
+ RefreshMode = '#{lcm_config[:refresh_mode]}'
86
+ }
87
+ }
88
+ LCMSETUP
89
+ when 'wmf4_with_update'
90
+ lcm_configuration_script = <<-LCMSETUP
91
+ configuration SetupLCM
92
+ {
93
+ LocalConfigurationManager
94
+ {
95
+ ActionAfterReboot = '#{lcm_config[:action_after_reboot]}'
96
+ AllowModuleOverwrite = [bool]::Parse('#{lcm_config[:allow_module_overwrite]}')
97
+ CertificateID = '#{lcm_config[:certificate_id].nil? ? '$null' : lcm_config[:certificate_id]}'
98
+ ConfigurationMode = '#{lcm_config[:configuration_mode]}'
99
+ ConfigurationModeFrequencyMins = #{lcm_config[:configuration_mode_frequency_mins].nil? ? '30' : lcm_config[:configuration_mode_frequency_mins]}
100
+ DebugMode = '#{lcm_config[:debug_mode]}'
101
+ RebootNodeIfNeeded = [bool]::Parse('#{lcm_config[:reboot_if_needed]}')
102
+ RefreshFrequencyMins = #{lcm_config[:refresh_frequency_mins].nil? ? '15' : lcm_config[:refresh_frequency_mins]}
103
+ RefreshMode = '#{lcm_config[:refresh_mode]}'
104
+ }
105
+ }
106
+ LCMSETUP
107
+ when 'wmf5'
108
+ lcm_configuration_script = <<-LCMSETUP
109
+ [DSCLocalConfigurationManager()]
110
+ configuration SetupLCM
111
+ {
112
+ Settings
113
+ {
114
+ ActionAfterReboot = '#{lcm_config[:action_after_reboot]}'
115
+ AllowModuleOverwrite = [bool]::Parse('#{lcm_config[:allow_module_overwrite]}')
116
+ CertificateID = '#{lcm_config[:certificate_id].nil? ? '$null' : lcm_config[:certificate_id]}'
117
+ ConfigurationMode = '#{lcm_config[:configuration_mode]}'
118
+ ConfigurationModeFrequencyMins = #{lcm_config[:configuration_mode_frequency_mins].nil? ? '15' : lcm_config[:configuration_mode_frequency_mins]}
119
+ DebugMode = '#{lcm_config[:debug_mode]}'
120
+ RebootNodeIfNeeded = [bool]::Parse('#{lcm_config[:reboot_if_needed]}')
121
+ RefreshFrequencyMins = #{lcm_config[:refresh_frequency_mins].nil? ? '30' : lcm_config[:refresh_frequency_mins]}
122
+ RefreshMode = '#{lcm_config[:refresh_mode]}'
123
+ }
124
+ }
125
+ LCMSETUP
126
+ end
127
+ full_lcm_configuration_script = <<-EOH
128
+ #{lcm_configuration_script}
129
+
130
+ $null = SetupLCM
131
+ Set-DscLocalConfigurationManager -Path ./SetupLCM | out-null
132
+ EOH
133
+
134
+ wrap_powershell_code(full_lcm_configuration_script)
135
+ end
136
+ # rubocop:enable Metrics/LineLength
137
+
138
+ def setup_config_directory_script
139
+ "mkdir (split-path (join-path #{config[:root_path]} #{sandboxed_configuration_script})) -force | out-null"
140
+ end
141
+
142
+ def powershell_modules
143
+ Array(config[:modules_from_gallery]).map do |powershell_module|
144
+ params = if powershell_module.is_a? Hash
145
+ keys = powershell_module.keys.reject { |k| k.to_s.downcase! == 'force' }
146
+ unless keys.any? { |k| k.to_s.downcase! == 'repository' }
147
+ keys.push(:repository)
148
+ powershell_module[:repository] = psmodule_repository_name
149
+ end
150
+ keys.map do |key|
151
+ "-#{key} #{powershell_module[key]}"
152
+ end.join(' ')
153
+ else
154
+ "-name '#{powershell_module}' -Repository #{psmodule_repository_name}"
155
+ end
156
+ "install-module #{params} -force | out-null"
157
+ end
158
+ end
159
+
160
+ def nuget_force_bootstrap
161
+ return unless config[:nuget_force_bootstrap]
162
+ info('Bootstrapping the nuget package provider for PowerShell PackageManagement.')
163
+ 'install-packageprovider nuget -force -forcebootstrap | out-null'
164
+ end
165
+
166
+ def psmodule_repository_name
167
+ return 'PSGallery' if config[:gallery_name].nil? && config[:gallery_uri].nil?
168
+ return 'testing' if config[:gallery_name].nil?
169
+ config[:gallery_name]
170
+ end
171
+
172
+ def register_psmodule_repository
173
+ return if config[:gallery_uri].nil?
174
+ info("Registering a new PowerShellGet Repository - #{psmodule_repository_name}")
175
+ "register-packagesource -providername PowerShellGet -name '#{psmodule_repository_name}' -location '#{config[:gallery_uri]}' -force -trusted"
176
+ end
177
+
178
+ def install_module_script
179
+ return if config[:modules_from_gallery].nil?
180
+ <<-EOH
181
+ #{nuget_force_bootstrap}
182
+ #{register_psmodule_repository}
183
+ #{powershell_modules.join("\n")}
184
+ EOH
185
+ end
186
+
187
+ def install_modules?
188
+ config[:dsc_local_configuration_manager_version] == 'wmf5' &&
189
+ !config[:modules_from_gallery].nil?
190
+ end
191
+
192
+ def init_command
193
+ script = <<-EOH
194
+ #{setup_config_directory_script}
195
+ #{install_module_script if install_modules?}
196
+ EOH
197
+ wrap_powershell_code(script)
198
+ end
199
+
200
+ def create_sandbox
201
+ super
202
+ info('Staging DSC Resource Modules for copy to the SUT')
203
+ if powershell_module?
204
+ prepare_resource_style_directory
205
+ else
206
+ prepare_repo_style_directory
207
+ end
208
+ info('Staging DSC configuration script for copy to the SUT')
209
+ prepare_configuration_script
210
+ end
211
+
212
+ def prepare_command
213
+ info('Moving DSC Resources onto PSModulePath')
214
+ info("Generating the MOF script for the configuration #{config[:configuration_name]}")
215
+ stage_resources_and_generate_mof_script = <<-EOH
216
+ if (Test-Path (join-path #{config[:root_path]} 'modules'))
217
+ {
218
+ dir ( join-path #{config[:root_path]} 'modules/*') -directory |
219
+ copy-item -destination $env:programfiles/windowspowershell/modules/ -recurse -force
220
+ }
221
+ if (-not (test-path 'c:/configurations'))
222
+ {
223
+ mkdir 'c:/configurations' | out-null
224
+ }
225
+ $ConfigurationScriptPath = Join-path #{config[:root_path]} #{sandboxed_configuration_script}
226
+ if (-not (test-path $ConfigurationScriptPath))
227
+ {
228
+ throw "Failed to find $ConfigurationScriptPath"
229
+ }
230
+ invoke-expression (get-content $ConfigurationScriptPath -raw)
231
+ if (-not (get-command #{config[:configuration_name]}))
232
+ {
233
+ throw "Failed to create a configuration command #{config[:configuration_name]}"
234
+ }
235
+
236
+ #{configuration_data_assignment unless config[:configuration_data].nil?}
237
+
238
+ $null = #{config[:configuration_name]} -outputpath c:/configurations #{'-configurationdata $' + configuration_data_variable}
239
+ EOH
240
+ debug("Shelling out: #{stage_resources_and_generate_mof_script}")
241
+ wrap_powershell_code(stage_resources_and_generate_mof_script)
242
+ end
243
+ # rubocop:enable Metrics/LineLength
244
+
245
+ def configuration_data_variable
246
+ config[:configuration_data_variable].nil? ? 'ConfigurationData' : config[:configuration_data_variable]
247
+ end
248
+
249
+ def configuration_data_assignment
250
+ '$' + configuration_data_variable + ' = ' + ps_hash(config[:configuration_data])
251
+ end
252
+
253
+ def run_command
254
+ config[:retry_on_exit_code] = [35] if config[:retry_on_exit_code].empty?
255
+ config[:max_retries] = 3 if config[:max_retries] == 1
256
+
257
+ info("Running the configuration #{config[:configuration_name]}")
258
+ run_configuration_script = <<-EOH
259
+ $job = start-dscconfiguration -Path c:/configurations/ -force
260
+ $job | wait-job
261
+ $verbose_output = $job.childjobs[0].verbose
262
+ $verbose_output
263
+ if ($verbose_output -match 'A reboot is required to progress further. Please reboot the system.') {
264
+ "A reboot is required to continue."
265
+ shutdown /r /t 15
266
+ exit 35
267
+ }
268
+ $dsc_errors = $job.childjobs[0].Error
269
+ if ($dsc_errors -ne $null) {
270
+ $dsc_errors
271
+ exit 1
272
+ }
273
+ EOH
274
+
275
+ debug("Shelling out: #{run_configuration_script}")
276
+ wrap_powershell_code(run_configuration_script)
277
+ end
278
+
279
+ private
280
+
281
+ def wrap_powershell_code(code)
282
+ wrap_shell_code( [ "$ProgressPreference = 'SilentlyContinue';", code ].join("\n") )
283
+ end
284
+
285
+ def powershell_module?
286
+ module_metadata_file = File.join(config[:kitchen_root], "#{module_name}.psd1")
287
+ File.exist?(module_metadata_file)
288
+ end
289
+
290
+ def list_files(path)
291
+ base_directory_content = Dir.glob(File.join(path, '*'))
292
+ nested_directory_content = Dir.glob(File.join(path, '*/**/*'))
293
+ all_directory_content = [base_directory_content, nested_directory_content].flatten
294
+
295
+ ignore_files = ['Gemfile', 'Gemfile.lock', 'README.md', 'LICENSE.txt']
296
+ all_directory_content.reject do |f|
297
+ debug("Enumerating #{f}")
298
+ ignore_files.include?(File.basename(f)) || File.directory?(f)
299
+ end
300
+ end
301
+
302
+ def module_name
303
+ File.basename(config[:kitchen_root])
304
+ end
305
+
306
+ def prepare_resource_style_directory
307
+ sandbox_base_module_path = File.join(sandbox_path, "modules/#{module_name}")
308
+
309
+ base = config[:kitchen_root]
310
+ list_files(base).each do |src|
311
+ dest = File.join(sandbox_base_module_path, src.sub("#{base}/", ''))
312
+ FileUtils.mkdir_p(File.dirname(dest))
313
+ debug("Staging #{src} ")
314
+ debug(" at #{dest}")
315
+ FileUtils.cp(src, dest, preserve: true)
316
+ end
317
+ end
318
+
319
+ def prepare_repo_style_directory
320
+ module_path = File.join(config[:kitchen_root], config[:modules_path])
321
+ sandbox_module_path = File.join(sandbox_path, 'modules')
322
+
323
+ if Dir.exist?(module_path)
324
+ debug("Moving #{module_path} to #{sandbox_module_path}")
325
+ FileUtils.cp_r(module_path, sandbox_module_path)
326
+ else
327
+ debug("The modules path #{module_path} was not found. Not moving to #{sandbox_module_path}.")
328
+ end
329
+ end
330
+
331
+ def sandboxed_configuration_script
332
+ File.join('configuration', config[:configuration_script])
333
+ end
334
+
335
+ def pad(depth = 0)
336
+ ' ' * depth
337
+ end
338
+
339
+ def ps_hash(obj, depth = 0)
340
+ if obj.is_a?(Hash)
341
+ obj.map do |k, v|
342
+ %(#{pad(depth + 2)}#{ps_hash(k)} = #{ps_hash(v, depth + 2)})
343
+ end.join(";\n").insert(0, "@{\n").insert(-1, "\n#{pad(depth)}}")
344
+ elsif obj.is_a?(Array)
345
+ array_string = obj.map { |v| ps_hash(v, depth + 4) }.join(',')
346
+ "#{pad(depth)}@(\n#{array_string}\n)"
347
+ else
348
+ %("#{obj}")
349
+ end
350
+ end
351
+
352
+ def prepare_configuration_script
353
+ configuration_script_file = File.join(config[:configuration_script_folder], config[:configuration_script])
354
+ configuration_script_path = File.join(config[:kitchen_root], configuration_script_file)
355
+ sandbox_configuration_script_path = File.join(sandbox_path, sandboxed_configuration_script)
356
+ FileUtils.mkdir_p(File.dirname(sandbox_configuration_script_path))
357
+ debug("Moving #{configuration_script_path} to #{sandbox_configuration_script_path}")
358
+ FileUtils.cp(configuration_script_path, sandbox_configuration_script_path)
359
+ end
360
+ end
361
+ end
362
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kitchen-dsc
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.9.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Steven Murawski
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-06-17 00:00:00.000000000 Z
11
+ date: 2016-06-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: test-kitchen