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 +4 -4
- data/README.md +107 -107
- data/kitchen-dsc.gemspec +41 -41
- data/lib/kitchen-dsc/version.rb +7 -7
- data/lib/kitchen/provisioner/dsc.rb +362 -368
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0043ea70755d3de429c6744f3103a484c9841cec
|
|
4
|
+
data.tar.gz: 005604228f4f2424e72fb41dc9e5a09c1ca9d42e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 65587a52d7f8d0a40d014cc5f28b8c18a32a69512bd22cf1776a545878c638526559f4ccdabe07db6b95ffc33c92e0a90d75b1d3fa376cf29f5dc19a1e49f1e0
|
|
7
|
+
data.tar.gz: 8fb1f84cb6d84cfa0b949e45e2b4bf0aba3dcfd653dcf4ce688f685e1ab501f7e8c1f20d35dda377017199b5417cc947deb70f537e61e0931dfe81727c7aa5d2
|
data/README.md
CHANGED
|
@@ -1,108 +1,108 @@
|
|
|
1
|
-
[](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
|
+
[](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
|
data/lib/kitchen-dsc/version.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
# encoding: utf-8
|
|
2
|
-
|
|
3
|
-
module Kitchen
|
|
4
|
-
module Dsc
|
|
5
|
-
VERSION = '0.9.
|
|
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
|
-
|
|
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
|
-
|
|
198
|
-
end
|
|
199
|
-
|
|
200
|
-
def create_sandbox
|
|
201
|
-
super
|
|
202
|
-
info('Staging DSC Resource Modules for copy to the SUT')
|
|
203
|
-
if
|
|
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
|
-
|
|
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
|
-
$
|
|
260
|
-
$job
|
|
261
|
-
$
|
|
262
|
-
$verbose_output
|
|
263
|
-
$verbose_output
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
$dsc_errors
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
File.
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
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.
|
|
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-
|
|
11
|
+
date: 2016-06-20 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: test-kitchen
|