vagrant-dsc 0.0.1.beta
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +24 -0
- data/.travis.yml +19 -0
- data/Gemfile +12 -0
- data/LICENSE.txt +22 -0
- data/README.md +67 -0
- data/Rakefile +13 -0
- data/development/Vagrantfile +86 -0
- data/development/manifests/ContosoWebsite.ps1 +17 -0
- data/lib/vagrant-dsc/config.rb +108 -0
- data/lib/vagrant-dsc/locales/en.yml +32 -0
- data/lib/vagrant-dsc/plugin.rb +23 -0
- data/lib/vagrant-dsc/powershell/configure_dsc.ps1 +13 -0
- data/lib/vagrant-dsc/provisioner.rb +192 -0
- data/lib/vagrant-dsc/templates/runner.ps1.erb +27 -0
- data/lib/vagrant-dsc/version.rb +5 -0
- data/lib/vagrant-dsc.rb +18 -0
- data/spec/base.rb +57 -0
- data/spec/command_builder_spec.rb +105 -0
- data/spec/provisioner/base_test.rb.bak +49 -0
- data/spec/provisioner/config_spec.rb +289 -0
- data/spec/provisioner/provisioner_spec.rb +46 -0
- data/spec/spec_helper.rb +23 -0
- data/vagrant-dsc.gemspec +28 -0
- metadata +214 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: f557e67cafe5c89fb6f203f66d638247f087cce7
|
4
|
+
data.tar.gz: b56ff50eea0ab89a8445b9c062e467fd57803c7b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 0fb75aa00d69bb332d73d45b3fa8d714fcbf7bd21dda120fbf22578dd8f706fe1324343db3a94094aff47d9e9b09f5d1dd9e17575180a0552cc9ba9e0aeeab00
|
7
|
+
data.tar.gz: e87885d268d76c03ce585f0976a43ba3b382ae12847a9af8c9834e6e4050ea92f54807048dd664c393da6fab91e988047308e9cd2f6660bd38282319f565c35b
|
data/.gitignore
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
*.bundle
|
19
|
+
*.so
|
20
|
+
*.o
|
21
|
+
*.a
|
22
|
+
mkmf.log
|
23
|
+
.vagrant
|
24
|
+
.idea
|
data/.travis.yml
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
language: ruby
|
2
|
+
before_install:
|
3
|
+
- rvm @global do gem uninstall bundler --all --executables
|
4
|
+
- gem uninstall bundler --all --executables
|
5
|
+
- gem install bundler --version '< 1.7.0'
|
6
|
+
rvm:
|
7
|
+
- 2.0.0
|
8
|
+
- 2.1.0
|
9
|
+
- ruby-head
|
10
|
+
matrix:
|
11
|
+
allow_failures:
|
12
|
+
- rvm: ruby-head
|
13
|
+
fast_finish: true
|
14
|
+
env:
|
15
|
+
matrix:
|
16
|
+
- VAGRANT_VERSION=v1.6.5
|
17
|
+
global:
|
18
|
+
secure: d34dSoYsh9C9tCgAeKp3TIYdxPlrGh1j+x01Igg7Ku0rmmv0f1+NSZOcSpgbf5daXFk1i5mQrRcYjIVOclGAlCXM7IKWfDyefstmYl+2+Hjv4LGJHQNvBTz02MerfKlUef2HMAt3HJsNvwhqvIVrHetC6ZeSaFtupWqhuXWgREQ=
|
19
|
+
script: bundle exec rake test:unit
|
data/Gemfile
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
# Specify your gem's dependencies in vagrant-dsc.gemspec
|
4
|
+
gemspec
|
5
|
+
|
6
|
+
group :development do
|
7
|
+
gem "vagrant", git: "https://github.com/mitchellh/vagrant.git"
|
8
|
+
end
|
9
|
+
|
10
|
+
group :plugins do
|
11
|
+
gem "vagrant-dsc", path: "."
|
12
|
+
end
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Matt Fellows
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
# Vagrant DSC Plugin
|
2
|
+
|
3
|
+
[Desired State Configuration](http://technet.microsoft.com/en-au/library/dn249912.aspx) provisioning plugin for Vagrant, enabling you to quickly configure & bootstrap a Windows Virtual Machine in a repeatable, reliable fashion.
|
4
|
+
|
5
|
+
.NET Devs - no more excuses...
|
6
|
+
|
7
|
+
> But it works on my machine!?
|
8
|
+
|
9
|
+
...is a thing of the past
|
10
|
+
|
11
|
+
## Installation
|
12
|
+
|
13
|
+
```vagrant plugin install vagrant-dsc```
|
14
|
+
|
15
|
+
## Usage
|
16
|
+
|
17
|
+
In your Vagrantfile, add the following plugin:
|
18
|
+
|
19
|
+
```ruby
|
20
|
+
config.vm.provision "dsc" do |dsc|
|
21
|
+
# The (Vagrantfile) relative path(s) to any folder containing DSC Resources
|
22
|
+
dsc.manifests_path = ["manifests", "other_manifests"]
|
23
|
+
|
24
|
+
# The path relative to `dsc.manifests_path` pointing to the Configuration file
|
25
|
+
# Defaults to `default.ps1`
|
26
|
+
dsc.manifest_file = "MyWebsite.ps1"
|
27
|
+
|
28
|
+
# The Configuration Command to run. Assumed to be the same as the `dsc.manifest_file`
|
29
|
+
# (sans extension) if not provided. In this case it would default to 'MyWebsite'
|
30
|
+
dsc.command_name = "MyCustomCommandNameForWebsite"
|
31
|
+
|
32
|
+
#
|
33
|
+
dsc.parameters
|
34
|
+
end
|
35
|
+
```
|
36
|
+
|
37
|
+
## Features
|
38
|
+
|
39
|
+
*
|
40
|
+
|
41
|
+
### Supported Environments
|
42
|
+
|
43
|
+
Currently the plugin only supports modern Windows environments with DSC installed (Windows 8.1+, Windows Server 2012 R2+ are safe bets).
|
44
|
+
The plugin works on older platforms that have a later version of .NET (4.5) and the WMF 4.0 installed.
|
45
|
+
|
46
|
+
As a general guide, configuring your Windows Server
|
47
|
+
|
48
|
+
From the [DSC Book](https://onedrive.live.com/view.aspx?cid=7F868AA697B937FE&resid=7F868AA697B937FE!156&app=Word):
|
49
|
+
|
50
|
+
> **DSC Overview and Requirements**
|
51
|
+
> Desired State Configuration (DSC) was first introduced as part of Windows Management Framework (WMF) 4.0, which is preinstalled in Windows 8.1 and Windows Server 2012 R2, and is available for Windows 7, Windows Server 2008 R2, and Windows Server 2012. Because Windows 8.1 is a free upgrade to Windows 8, WMF 4 is not available for Windows 8.
|
52
|
+
> You must have WMF 4.0 on a computer if you plan to author configurations there. You must also have WMF 4.0 on any computer you plan to manage via DSC. Every computer involved in the entire DSC conversation must have WMF 4.0 installed. Period. Check $PSVersionTable in PowerShell if you’re not sure what version is installed on a computer.
|
53
|
+
> On Windows 8.1 and Windows Server 2012 R2, make certain that KB2883200 is installed or DSC will not work. On Windows Server 2008 R2, Windows 7, and Windows Server 2008, be sure to install the full Microsoft .NET Framework 4.5 package prior to installing WMF 4.0 or DSC may not work correctly.
|
54
|
+
|
55
|
+
We may consider automatically installing and configuring DSC in a future release of the plugin.
|
56
|
+
|
57
|
+
## Uninistallation
|
58
|
+
|
59
|
+
```vagrant plugin uninstall vagrant-dsc```
|
60
|
+
|
61
|
+
## Contributing
|
62
|
+
|
63
|
+
1. Fork it ( https://github.com/[my-github-username]/vagrant-dsc/fork )
|
64
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
65
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
66
|
+
4. Squash commits & push to the branch (`git push origin my-new-feature`)
|
67
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require 'rspec/core/rake_task'
|
3
|
+
task :default => [:test, :quality]
|
4
|
+
# Remove 'install' task as the gem is installed to Vagrant, not to system
|
5
|
+
Rake::Task[:install].clear
|
6
|
+
namespace :test do
|
7
|
+
RSpec::Core::RakeTask.new('unit') do |task|
|
8
|
+
task.pattern = 'spec/**/*_spec.rb'
|
9
|
+
end
|
10
|
+
end
|
11
|
+
desc "Run all tests"
|
12
|
+
task :test => ['test:unit']
|
13
|
+
task :spec => :test
|
@@ -0,0 +1,86 @@
|
|
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 = "win-dev"
|
14
|
+
|
15
|
+
config.vm.guest = :windows
|
16
|
+
config.vm.communicator = "winrm"
|
17
|
+
|
18
|
+
config.vm.network :forwarded_port, guest: 3389, host: 3389
|
19
|
+
config.vm.network :forwarded_port, guest: 5985, host: 5985, id: "winrm", auto_correct: true
|
20
|
+
config.vm.network :forwarded_port, guest: 80, host: 8000 # Port forward for IIS
|
21
|
+
|
22
|
+
config.vm.provider "virtualbox" do |v|
|
23
|
+
v.gui = true
|
24
|
+
end
|
25
|
+
|
26
|
+
$script = <<SCRIPT
|
27
|
+
#
|
28
|
+
# Script that gets executed on the remote machine
|
29
|
+
#
|
30
|
+
|
31
|
+
function Write-BootstrapProgress
|
32
|
+
{
|
33
|
+
param($message)
|
34
|
+
Write-Host " ${message}"
|
35
|
+
}
|
36
|
+
|
37
|
+
# Install Choco if not already installed
|
38
|
+
|
39
|
+
if ( (Get-Command "choco" -errorAction SilentlyContinue) ) {
|
40
|
+
Write-BootstrapProgress "Chocolatey already installed. Skipping."
|
41
|
+
} else {
|
42
|
+
Write-BootstrapProgress "Installing Chocolatey"
|
43
|
+
$wc=new-object net.webclient; $wp=[system.net.WebProxy]::GetDefaultProxy(); $wp.UseDefaultCredentials=$true; $wc.Proxy=$wp; iex ($wc.DownloadString('https://chocolatey.org/install.ps1'))
|
44
|
+
# Add to path
|
45
|
+
$env:Path = $env:Path + ";C:\ProgramData\chocolatey\bin"
|
46
|
+
[Environment]::SetEnvironmentVariable( "Path", $env:Path, [System.EnvironmentVariableTarget]::Machine )
|
47
|
+
}
|
48
|
+
|
49
|
+
Write-BootstrapProgress "Installing required software"
|
50
|
+
if ( -Not (Get-Command "Install-Module" -errorAction SilentlyContinue) ) {
|
51
|
+
Write-BootstrapProgress "Installing PSGet"
|
52
|
+
(new-object Net.WebClient).DownloadString("http://psget.net/GetPsGet.ps1") | iex
|
53
|
+
}
|
54
|
+
Install-Module Posh-Git
|
55
|
+
|
56
|
+
Write-BootstrapProgress "Installing required packages"
|
57
|
+
$packages = @(
|
58
|
+
"git.commandline"
|
59
|
+
"git"
|
60
|
+
"seek-dsc"
|
61
|
+
"NuGet.CommandLine"
|
62
|
+
"invokemsbuild"
|
63
|
+
)
|
64
|
+
|
65
|
+
Write-BootstrapProgress "Packages installed"
|
66
|
+
SCRIPT
|
67
|
+
|
68
|
+
# First pre-configure the machine with required software
|
69
|
+
config.vm.provision "shell", inline: $script
|
70
|
+
|
71
|
+
config.vm.provision "dsc" do |dsc|
|
72
|
+
# The (Vagrantfile) relative path(s) to any folder containing DSC Resources
|
73
|
+
dsc.module_path = ["manifests", "modules"]
|
74
|
+
|
75
|
+
# The path relative to `dsc.manifests_path` pointing to the Configuration file
|
76
|
+
dsc.manifest_file = "manifests/ContosoWebsite.ps1"
|
77
|
+
|
78
|
+
# The Configuration Command to run. Assumed to be the same as the `dsc.manifest_file`
|
79
|
+
# (sans extension) if not provided.
|
80
|
+
# dsc.command_name = "ContosoWebsite"
|
81
|
+
|
82
|
+
# Commandline arguments to the Configuration run
|
83
|
+
dsc.configuration_parameters = {}
|
84
|
+
dsc.configuration_parameters[:machineName] = "localhost"
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
Configuration ContosoWebsite
|
2
|
+
{
|
3
|
+
param ($MachineName)
|
4
|
+
|
5
|
+
Node $MachineName
|
6
|
+
{
|
7
|
+
#Install the IIS Role
|
8
|
+
File website
|
9
|
+
{
|
10
|
+
Ensure = "Present"
|
11
|
+
Type = "Directory"
|
12
|
+
DestinationPath = "c:\mywebroot"
|
13
|
+
}
|
14
|
+
}
|
15
|
+
}
|
16
|
+
|
17
|
+
Write-Output "Hello from DSC Provisioner: Config file"
|
@@ -0,0 +1,108 @@
|
|
1
|
+
require "vagrant/util/counter"
|
2
|
+
require "log4r"
|
3
|
+
|
4
|
+
module VagrantPlugins
|
5
|
+
module DSC
|
6
|
+
class Config < Vagrant.plugin("2", :config)
|
7
|
+
extend Vagrant::Util::Counter
|
8
|
+
|
9
|
+
attr_accessor :facter
|
10
|
+
attr_accessor :mof_file
|
11
|
+
attr_accessor :manifest_file
|
12
|
+
attr_accessor :manifests_path
|
13
|
+
attr_accessor :configuration_name
|
14
|
+
attr_accessor :module_path
|
15
|
+
attr_accessor :options
|
16
|
+
attr_accessor :synced_folder_type
|
17
|
+
attr_accessor :temp_dir
|
18
|
+
attr_accessor :working_directory
|
19
|
+
|
20
|
+
def initialize
|
21
|
+
super
|
22
|
+
|
23
|
+
@manifest_file = UNSET_VALUE
|
24
|
+
@manifests_path = UNSET_VALUE
|
25
|
+
@configuration_name = UNSET_VALUE
|
26
|
+
@mof_file = UNSET_VALUE
|
27
|
+
@module_path = UNSET_VALUE
|
28
|
+
@options = []
|
29
|
+
@facter = {}
|
30
|
+
@synced_folder_type = UNSET_VALUE
|
31
|
+
@temp_dir = UNSET_VALUE
|
32
|
+
@working_directory = UNSET_VALUE
|
33
|
+
|
34
|
+
@logger = Log4r::Logger.new("vagrant::vagrant_dsc")
|
35
|
+
end
|
36
|
+
|
37
|
+
def merge(other)
|
38
|
+
super.tap do |result|
|
39
|
+
result.facter = @facter.merge(other.facter)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def finalize!
|
44
|
+
super
|
45
|
+
|
46
|
+
@manifest_file = "default.ps1" if @manifest_file == UNSET_VALUE
|
47
|
+
@module_path = nil if @module_path == UNSET_VALUE
|
48
|
+
@synced_folder_type = nil if @synced_folder_type == UNSET_VALUE
|
49
|
+
@temp_dir = nil if @temp_dir == UNSET_VALUE
|
50
|
+
@mof_file = nil if @mof_file == UNSET_VALUE
|
51
|
+
@working_directory = nil if @working_directory == UNSET_VALUE
|
52
|
+
@configuration_name = File.basename(@manifest_file, File.extname(@manifest_file)) if @configuration_name == UNSET_VALUE
|
53
|
+
@manifests_path = File.dirname(@manifest_file)
|
54
|
+
|
55
|
+
# Set a default temp dir that has an increasing counter so
|
56
|
+
# that multiple DSC definitions won't overwrite each other
|
57
|
+
if !@temp_dir
|
58
|
+
counter = self.class.get_and_update_counter(:dsc_config)
|
59
|
+
@temp_dir = "/tmp/vagrant-dsc-#{counter}"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Returns the module paths as an array of paths expanded relative to the
|
64
|
+
# root path.
|
65
|
+
def expanded_module_paths(root_path)
|
66
|
+
return [] if !module_path
|
67
|
+
|
68
|
+
# Get all the paths and expand them relative to the root path, returning
|
69
|
+
# the array of expanded paths
|
70
|
+
paths = module_path
|
71
|
+
paths = [paths] if !paths.is_a?(Array)
|
72
|
+
paths.map do |path|
|
73
|
+
Pathname.new(path).expand_path(root_path)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
#
|
78
|
+
# Validate configuration
|
79
|
+
#
|
80
|
+
def validate(machine)
|
81
|
+
@logger.info("==> Configurin' DSC man!")
|
82
|
+
errors = _detected_errors
|
83
|
+
|
84
|
+
# Calculate the manifests and module paths based on env
|
85
|
+
this_expanded_module_paths = expanded_module_paths(machine.env.root_path)
|
86
|
+
|
87
|
+
# Manifest file validation
|
88
|
+
|
89
|
+
if manifests_path[0].to_sym == :host
|
90
|
+
expanded_path = Pathname.new(manifests_path[1]).
|
91
|
+
expand_path(machine.env.root_path)
|
92
|
+
if !expanded_path.directory?
|
93
|
+
errors << I18n.t("vagrant_dsc.errors.manifests_path_missing",
|
94
|
+
path: expanded_path.to_s)
|
95
|
+
else
|
96
|
+
expanded_manifest_file = expanded_path.join(manifest_file)
|
97
|
+
if !expanded_manifest_file.file? && !expanded_manifest_file.directory?
|
98
|
+
errors << I18n.t("vagrant_dsc.errors.manifest_missing",
|
99
|
+
manifest: expanded_manifest_file.to_s)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
{ "dsc provisioner" => errors }
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
en:
|
2
|
+
vagrant_dsc:
|
3
|
+
already_status: |-
|
4
|
+
The machine is already %{status}.
|
5
|
+
|
6
|
+
running_dsc: |-
|
7
|
+
"Running DSC Provisioner with %{manifest}..."
|
8
|
+
|
9
|
+
will_not_destroy: |-
|
10
|
+
The instance '%{name}' will not be destroyed, since the confirmation
|
11
|
+
was declined.
|
12
|
+
|
13
|
+
config:
|
14
|
+
access_key_id_required: |-
|
15
|
+
An access key ID must be specified via "access_key_id"
|
16
|
+
|
17
|
+
errors:
|
18
|
+
missing_shared_folders: |-
|
19
|
+
Shared folders not properly configured. This is generally resolved by a 'vagrant halt && vagrant up'
|
20
|
+
unsupported_os: |-
|
21
|
+
Vagrant DSC does not work
|
22
|
+
dsc_not_detected: |-
|
23
|
+
Unable to detect a working DSC environment. Please ensure powershell v4+
|
24
|
+
is installed, including WMF 4+.
|
25
|
+
dsc_incorrect_powershell_version: |-
|
26
|
+
Powershell version 4 or greater not installed. Please ensure powershell v4+ is installed, including WMF 4+.
|
27
|
+
module_path_missing: |-
|
28
|
+
"Path to DSC Modules does not exist: %{path}"
|
29
|
+
manifests_path_missing: |-
|
30
|
+
"Path to DSC Manifest folder does not exist: %{path}"
|
31
|
+
manifest_missing: |-
|
32
|
+
"Path to DSC Manifest does not exist: %{manifest}"
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require "vagrant"
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module DSC
|
5
|
+
class Plugin < Vagrant.plugin("2")
|
6
|
+
name "DSC"
|
7
|
+
description <<-DESC
|
8
|
+
Provides support for provisioning your virtual machines with
|
9
|
+
DSC either using a local `DSC` Configuration or a DSC server.
|
10
|
+
DESC
|
11
|
+
|
12
|
+
config(:dsc, :provisioner) do
|
13
|
+
require_relative 'config'
|
14
|
+
Config
|
15
|
+
end
|
16
|
+
|
17
|
+
provisioner(:dsc) do
|
18
|
+
require_relative 'provisioner'
|
19
|
+
Provisioner
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# Sets up DSC
|
2
|
+
echo 'Setting up DSC components'
|
3
|
+
|
4
|
+
$ChocoInstallPathOld = "$env:SystemDrive\Chocolatey\bin"
|
5
|
+
$ChocoInstallPath = "$env:SystemDrive\ProgramData\Chocolatey\bin"
|
6
|
+
|
7
|
+
# Install chocolatey
|
8
|
+
if ( !(Get-Command "choco") -and !(Test-Path $ChocoInstallPath)) {
|
9
|
+
iex ((new-object net.webclient).DownloadString('http://chocolatey.org/install.ps1'))
|
10
|
+
}
|
11
|
+
|
12
|
+
choco install DotNet4.5
|
13
|
+
choco install powershell4
|
@@ -0,0 +1,192 @@
|
|
1
|
+
require "log4r"
|
2
|
+
require 'erb'
|
3
|
+
|
4
|
+
module VagrantPlugins
|
5
|
+
module DSC
|
6
|
+
class DSCError < Vagrant::Errors::VagrantError
|
7
|
+
error_namespace("vagrant_dsc.errors")
|
8
|
+
I18n.load_path << File.expand_path("locales/en.yml", File.dirname(__FILE__))
|
9
|
+
end
|
10
|
+
|
11
|
+
class Provisioner < Vagrant.plugin("2", :provisioner)
|
12
|
+
POWERSHELL_VERSION = 5
|
13
|
+
DSC_GUEST_RUNNER_PATH = "c:/tmp/vagrant-dsc-runner.ps1"
|
14
|
+
|
15
|
+
def initialize(machine, config)
|
16
|
+
super
|
17
|
+
|
18
|
+
@logger = Log4r::Logger.new("vagrant::provisioners::dsc")
|
19
|
+
end
|
20
|
+
|
21
|
+
def configure(root_config)
|
22
|
+
@logger.info("==> Configuring DSC man!")
|
23
|
+
|
24
|
+
# Calculate the paths we're going to use based on the environment
|
25
|
+
root_path = @machine.env.root_path
|
26
|
+
@expanded_module_paths = @config.expanded_module_paths(root_path)
|
27
|
+
@manifest_file = File.join(manifests_guest_path, @config.manifest_file)
|
28
|
+
|
29
|
+
# Setup the module paths
|
30
|
+
@module_paths = []
|
31
|
+
@expanded_module_paths.each_with_index do |path, i|
|
32
|
+
@module_paths << [path, File.join(config.temp_dir, "modules-#{i}")]
|
33
|
+
end
|
34
|
+
|
35
|
+
folder_opts = {}
|
36
|
+
folder_opts[:type] = @config.synced_folder_type if @config.synced_folder_type
|
37
|
+
folder_opts[:owner] = "root" if !@config.synced_folder_type
|
38
|
+
|
39
|
+
# Share the manifests directory with the guest
|
40
|
+
@logger.info("==> Sharing manifest #{File.expand_path(@config.manifests_path, root_path)} | #{manifests_guest_path} | #{folder_opts}")
|
41
|
+
root_config.vm.synced_folder(
|
42
|
+
File.expand_path(@config.manifests_path, root_path),
|
43
|
+
manifests_guest_path, folder_opts)
|
44
|
+
|
45
|
+
# Share the module paths
|
46
|
+
@module_paths.each do |from, to|
|
47
|
+
@logger.info("==> Sharing module folders #{from} | #{to}")
|
48
|
+
root_config.vm.synced_folder(from, to, folder_opts)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def provision
|
53
|
+
@logger.info("==> Provisioning DSC man! #{Vagrant.source_root}")
|
54
|
+
|
55
|
+
# If the machine has a wait for reboot functionality, then
|
56
|
+
# do that (primarily Windows)
|
57
|
+
if @machine.guest.capability?(:wait_for_reboot)
|
58
|
+
@machine.guest.capability(:wait_for_reboot)
|
59
|
+
end
|
60
|
+
|
61
|
+
# Check that the shared folders are properly shared
|
62
|
+
check = []
|
63
|
+
check << manifests_guest_path
|
64
|
+
@module_paths.each do |host_path, guest_path|
|
65
|
+
check << guest_path
|
66
|
+
end
|
67
|
+
|
68
|
+
# Make sure the temporary directory is properly set up
|
69
|
+
@machine.communicate.tap do |comm|
|
70
|
+
comm.sudo("mkdir -p #{config.temp_dir}")
|
71
|
+
comm.sudo("chmod 0777 #{config.temp_dir}")
|
72
|
+
end
|
73
|
+
|
74
|
+
verify_shared_folders(check)
|
75
|
+
|
76
|
+
verify_dsc
|
77
|
+
|
78
|
+
generate_dsc_runner_script
|
79
|
+
|
80
|
+
run_dsc_apply
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
def manifests_guest_path
|
85
|
+
File.join(config.temp_dir, config.manifests_path)
|
86
|
+
end
|
87
|
+
|
88
|
+
def verify_dsc
|
89
|
+
verify_binary("Start-DscConfiguration")
|
90
|
+
|
91
|
+
# Confirm WMF 4.0+ in $PSVersionTable
|
92
|
+
@machine.communicate.test(
|
93
|
+
"(($PSVersionTable | ConvertTo-json | ConvertFrom-Json).PSVersion.Major) -ge #{POWERSHELL_VERSION} ",
|
94
|
+
error_class: DSCError,
|
95
|
+
error_key: :dsc_incorrect_powershell_version )
|
96
|
+
end
|
97
|
+
|
98
|
+
def verify_binary(binary)
|
99
|
+
@machine.communicate.sudo(
|
100
|
+
"which #{binary}",
|
101
|
+
error_class: DSCError,
|
102
|
+
error_key: :dsc_not_detected,
|
103
|
+
binary: binary)
|
104
|
+
end
|
105
|
+
|
106
|
+
# Install and Configure DSC where possible.
|
107
|
+
#
|
108
|
+
def install_dsc
|
109
|
+
|
110
|
+
# Ensure .NET 4.5 installed
|
111
|
+
|
112
|
+
# Ensure WMF 4.0 is installed
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
# Generates a Powershell DSC runner script from an ERB template
|
117
|
+
def generate_dsc_runner_script
|
118
|
+
path = File.expand_path("../templates/runner.ps1", __FILE__)
|
119
|
+
script = Vagrant::Util::TemplateRenderer.render(path, options: {
|
120
|
+
config: config,
|
121
|
+
module_paths: @module_paths,
|
122
|
+
manifest_file: config.manifest_file,
|
123
|
+
configuration_name: config.configuration_name,
|
124
|
+
temp_path: config.temp_dir,
|
125
|
+
parameters: config.parameters.map { |k,v|}.join,
|
126
|
+
})
|
127
|
+
guest_script_path = DSC_GUEST_RUNNER_PATH
|
128
|
+
file = Tempfile.new(["vagrant-dsc-runner", "ps1"])
|
129
|
+
begin
|
130
|
+
file.write(script)
|
131
|
+
file.fsync
|
132
|
+
file.close
|
133
|
+
@machine.communicate.upload(file.path, guest_script_path)
|
134
|
+
ensure
|
135
|
+
file.close
|
136
|
+
file.unlink
|
137
|
+
end
|
138
|
+
guest_script_path
|
139
|
+
end
|
140
|
+
|
141
|
+
def run_dsc_apply
|
142
|
+
|
143
|
+
# Set up Configuration arguments (hostname, manifest/module location, error levels ...)
|
144
|
+
|
145
|
+
# Where are the modules?
|
146
|
+
|
147
|
+
# Where is the manifest
|
148
|
+
|
149
|
+
# Setup $env:PSModulePath for execution env.
|
150
|
+
|
151
|
+
# Integrator -ConfigurationData "$SetupPath\Configuration\Development.psd1" -OutputPath $StagingPath -BasePath $AppBasePath
|
152
|
+
|
153
|
+
# TODO: Get a counter in here in case of multiple runs
|
154
|
+
|
155
|
+
# Apply configuration/parameters to DSC Runner
|
156
|
+
|
157
|
+
# Import starting point configuration into scope
|
158
|
+
|
159
|
+
command = ".\"#{DSC_GUEST_RUNNER_PATH}\""
|
160
|
+
|
161
|
+
@machine.ui.info(I18n.t(
|
162
|
+
"vagrant_dsc.running_dsc",
|
163
|
+
manifest: config.manifest_file))
|
164
|
+
|
165
|
+
opts = {
|
166
|
+
elevated: true,
|
167
|
+
error_key: :ssh_bad_exit_status_muted,
|
168
|
+
good_exit: [0,2],
|
169
|
+
}
|
170
|
+
|
171
|
+
@machine.communicate.sudo(command, opts) do |type, data|
|
172
|
+
if !data.chomp.empty?
|
173
|
+
@machine.ui.info(data.chomp)
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
def verify_shared_folders(folders)
|
179
|
+
folders.each do |folder|
|
180
|
+
@logger.info("Checking for shared folder: #{folder}")
|
181
|
+
if !@machine.communicate.test("test -d #{folder}", sudo: true)
|
182
|
+
raise DSCError, :missing_shared_folders
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
def windows?
|
188
|
+
@machine.config.vm.communicator == :winrm
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
#
|
2
|
+
# DSC Runner Script.
|
3
|
+
# Bootstraps the DSC environment, configuration and runs the DSC Configuration.
|
4
|
+
#
|
5
|
+
|
6
|
+
# Set the local PowerShell module environment path
|
7
|
+
<% options[:module_paths].each do |host, guest| %>
|
8
|
+
echo "Adding to path: <%= guest %>"
|
9
|
+
$env:PSModulePath="<%= guest %>;${env:PSModulePath}"
|
10
|
+
<% end %>
|
11
|
+
|
12
|
+
echo "PSModulePath Configured: ${env:PSModulePath}"
|
13
|
+
echo "Running Configuration file: <%= options[:manifest_file_path] %>"
|
14
|
+
|
15
|
+
# Import the Manifest
|
16
|
+
. $(Join-Path "<%= options[:temp_path] %>" "<%= options[:manifest_file] %>")
|
17
|
+
|
18
|
+
# Generate the MOF file
|
19
|
+
cd "<%= options[:temp_path] %>"
|
20
|
+
$StagingPath = $(Join-Path "<%= options[:temp_path] %>" "staging")
|
21
|
+
<%= options[:configuration_name] %> -MachineName "localhost" -OutputPath $StagingPath <%= options[:configuration_parameters] %>
|
22
|
+
|
23
|
+
# Start a DSC Configuration run
|
24
|
+
Start-DscConfiguration -Force -Wait -Verbose -Path $StagingPath
|
25
|
+
|
26
|
+
# Cleanup
|
27
|
+
del -Path $StagingPath -Recurse
|