vagrant-windows-domain 1.0.0
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 +7 -0
- data/.gitignore +24 -0
- data/.travis.yml +19 -0
- data/Gemfile +12 -0
- data/LICENSE.txt +22 -0
- data/README.md +87 -0
- data/Rakefile +13 -0
- data/development/Vagrantfile +64 -0
- data/lib/vagrant-windows-domain.rb +18 -0
- data/lib/vagrant-windows-domain/config.rb +121 -0
- data/lib/vagrant-windows-domain/locales/en.yml +17 -0
- data/lib/vagrant-windows-domain/plugin.rb +23 -0
- data/lib/vagrant-windows-domain/provisioner.rb +193 -0
- data/lib/vagrant-windows-domain/templates/runner.ps1.erb +9 -0
- data/lib/vagrant-windows-domain/version.rb +5 -0
- data/spec/base.rb +54 -0
- data/spec/provisioner/config_spec.rb +87 -0
- data/spec/provisioner/provisioner_spec.rb +197 -0
- data/spec/spec_helper.rb +25 -0
- data/vagrant-windows-domain.gemspec +28 -0
- metadata +208 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 32c0962897914ab1f2665b2ee83e436403d1c7d6
|
4
|
+
data.tar.gz: 6b9f71576ad54801a1325ed828d8a04b614e186b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a2a5bba2574096eb6dd50802d44f87b1a20e94caee7f9191dfa686cef067c16b86ca4953c97d40e3203373eed09d5eaec89d28b77a4df6ca6a5f2af473dec6b7
|
7
|
+
data.tar.gz: a15ef170cca8c7b9d8424d1e35d71d8447c3e49567fe9b74c36b6e69e31a99e7146f72dbcd9ac99679efc327a5dc19a824d4ec700e72f3c5ed6f24ef8d66f668
|
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: bs4ezY+1Wksy8hH3nymPJ3AL99mpXULVc/AIh16JetEYw1850QkX7r4gQukMlcyByKUhxucjDLid0Y+KDH5kGMM16QjrVQGhAnUQzMoLD2qPbAaxDCUqpCJtFEEQKYxJvFvEK8a5SQzAsTVG4sgABQ/MllsIIH0FjkWgFtH6050=
|
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-windows-domain.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-windows-domain", 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,87 @@
|
|
1
|
+
# Vagrant Windows Domain Plugin
|
2
|
+
|
3
|
+
[](https://travis-ci.org/SEEK-Jobs/vagrant-windows-domain)
|
4
|
+
[](https://coveralls.io/r/SEEK-Jobs/vagrant-windows-domain?branch=master)
|
5
|
+
[](http://badge.fury.io/rb/vagrant-windows-domain)
|
6
|
+
|
7
|
+
A Vagrant Plugin that makes connecting and disconnecting your Windows Vagrant box to a Windows Domain a cinch.
|
8
|
+
|
9
|
+
On a `vagrant up` - unless credentials are supplied - it will prompt the user for their domain credentials and add the guest to the domain, including restarting the guest without interfering with other provisioners.
|
10
|
+
|
11
|
+
On a `vagrant destroy`, it will do the same and remove itself from the Domain, keeping things neat-n-tidy.
|
12
|
+
|
13
|
+
## Installation
|
14
|
+
|
15
|
+
```vagrant plugin install vagrant-windows-domain```
|
16
|
+
|
17
|
+
## Usage
|
18
|
+
|
19
|
+
In your Vagrantfile, add the following plugin and configure to your needs:
|
20
|
+
|
21
|
+
```ruby
|
22
|
+
config.vm.provision :windows_domain do |domain|
|
23
|
+
|
24
|
+
# The Windows Domain to join.
|
25
|
+
#
|
26
|
+
# Setting this will result in an additional restart.
|
27
|
+
domain.domain = "domain.int"
|
28
|
+
|
29
|
+
# The new Computer Name to use when joining the domain.
|
30
|
+
#
|
31
|
+
# Uses the Rename-Computer PowerShell command. ORRRR -NewName flag??
|
32
|
+
# Specifies a new name for the computer in the new domain.
|
33
|
+
domain.computer_name "myfandangledname"
|
34
|
+
|
35
|
+
# The Username to use when authenticating against the Domain.
|
36
|
+
#
|
37
|
+
# Specifies a user account that has permission to join the computers to a new domain.
|
38
|
+
#
|
39
|
+
# If not supplied the plugin will prompt the user during provisioning to provide one.
|
40
|
+
domain.username = "me"
|
41
|
+
|
42
|
+
# The Password to use when authenticating against the Domain.
|
43
|
+
#
|
44
|
+
# Specifies the password of a user account that has permission to
|
45
|
+
# join the computers to a new domain.
|
46
|
+
#
|
47
|
+
# If not supplied the plugin will prompt the user during provisioning to provide one.
|
48
|
+
domain.password = "iprobablyshouldntusethisfield"
|
49
|
+
|
50
|
+
# The set of Advanced options to pass when joining the Domain.
|
51
|
+
#
|
52
|
+
# See (https://technet.microsoft.com/en-us/library/hh849798.aspx) for detail, these are generally not required.
|
53
|
+
domain.join_options = { "--JoinReadOnly" => "" }
|
54
|
+
|
55
|
+
# Organisational Unit path in AD.
|
56
|
+
#
|
57
|
+
# Specifies an organizational unit (OU) for the domain account.
|
58
|
+
# Enter the full distinguished name of the OU in quotation marks.
|
59
|
+
# The default value is the default OU for machine objects in the domain.
|
60
|
+
domain.ou_path = "OU=testOU,DC=domain,DC=Domain,DC=com"
|
61
|
+
|
62
|
+
# Performs an unsecure join to the specified domain.
|
63
|
+
#
|
64
|
+
# When this option is enabled username/password are not required and cannot be used.
|
65
|
+
domain.unsecure = false
|
66
|
+
end
|
67
|
+
```
|
68
|
+
## Example
|
69
|
+
|
70
|
+
There is a [sample](https://github.com/SEEK-Jobs/vagrant-windows-domain/tree/master/development) Vagrant setup used for development of this plugin.
|
71
|
+
This is a great real-life example to get you on your way.
|
72
|
+
|
73
|
+
### Supported Environments
|
74
|
+
|
75
|
+
Currently the plugin supports any Windows environment with Powershell 3+ installed (2008r2, 2012r2 should work nicely).
|
76
|
+
|
77
|
+
## Uninistallation
|
78
|
+
|
79
|
+
```vagrant plugin uninstall vagrant-windows-domain```
|
80
|
+
|
81
|
+
## Contributing
|
82
|
+
|
83
|
+
1. Fork it ( https://github.com/[my-github-username]/vagrant-windows-domain/fork )
|
84
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
85
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
86
|
+
4. Squash commits & push to the branch (`git push origin my-new-feature`)
|
87
|
+
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,64 @@
|
|
1
|
+
# -*- mode: ruby -*-
|
2
|
+
# vi: set ft=ruby :
|
3
|
+
|
4
|
+
$shell_script = <<SCRIPT
|
5
|
+
Write-Host "Hey, this happened after the restart!"
|
6
|
+
SCRIPT
|
7
|
+
|
8
|
+
# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
|
9
|
+
VAGRANTFILE_API_VERSION = "2"
|
10
|
+
|
11
|
+
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
|
12
|
+
|
13
|
+
config.vm.box = "mfellows/windows2012r2"
|
14
|
+
config.vm.guest = :windows
|
15
|
+
config.vm.communicator = "winrm"
|
16
|
+
config.vm.network :forwarded_port, guest: 5985, host: 5985, id: "winrm", auto_correct: true
|
17
|
+
|
18
|
+
# Run Windows Domain Provisioner
|
19
|
+
config.vm.provision :windows_domain do |domain|
|
20
|
+
|
21
|
+
# The Windows Domain to join.
|
22
|
+
#
|
23
|
+
# Setting this will result in an additional restart.
|
24
|
+
domain.domain = "domain.int"
|
25
|
+
|
26
|
+
# The new Computer Name to use when joining the domain.
|
27
|
+
#
|
28
|
+
# Uses the Rename-Computer PowerShell command. ORRRR -NewName flag??
|
29
|
+
# Specifies a new name for the computer in the new domain.
|
30
|
+
domain.computer_name "myfandangledname"
|
31
|
+
|
32
|
+
# The Username to use when authenticating against the Domain.
|
33
|
+
#
|
34
|
+
# Specifies a user account that has permission to join the computers to a new domain.
|
35
|
+
domain.username = "me"
|
36
|
+
|
37
|
+
# The Password to use when authenticating against the Domain.
|
38
|
+
#
|
39
|
+
# Specifies the password of a user account that has permission to
|
40
|
+
# join the computers to a new domain.
|
41
|
+
domain.password = "iprobablyshouldntusethisfield"
|
42
|
+
|
43
|
+
# The set of Advanced options to pass when joining the Domain.
|
44
|
+
#
|
45
|
+
# See (https://technet.microsoft.com/en-us/library/hh849798.aspx) for detail.
|
46
|
+
# NOTE: If we user :computer_name from above this needs to be merged!!
|
47
|
+
domain.join_options
|
48
|
+
|
49
|
+
# Organisational Unit path in AD.
|
50
|
+
#
|
51
|
+
# Specifies an organizational unit (OU) for the domain account.
|
52
|
+
# Enter the full distinguished name of the OU in quotation marks.
|
53
|
+
# The default value is the default OU for machine objects in the domain.
|
54
|
+
domain.ou_path
|
55
|
+
|
56
|
+
# Performs an unsecure join to the specified domain.
|
57
|
+
#
|
58
|
+
# When this option is used username/password are not required
|
59
|
+
domain.unsecure
|
60
|
+
end
|
61
|
+
|
62
|
+
# Confirm that this will run after the reload from the domain provisioner!
|
63
|
+
config.vm.provision "shell", inline: $shell_script
|
64
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require "pathname"
|
2
|
+
|
3
|
+
require "vagrant-windows-domain/plugin"
|
4
|
+
|
5
|
+
module VagrantPlugins
|
6
|
+
module WindowsDomain
|
7
|
+
lib_path = Pathname.new(File.expand_path("../vagrant-windows-domain", __FILE__))
|
8
|
+
autoload :Action, lib_path.join("action")
|
9
|
+
autoload :Errors, lib_path.join("errors")
|
10
|
+
|
11
|
+
# This returns the path to the source of this plugin.
|
12
|
+
#
|
13
|
+
# @return [Pathname]
|
14
|
+
def self.source_root
|
15
|
+
@source_root ||= Pathname.new(File.expand_path("../lib", __FILE__))
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
require "vagrant/util/counter"
|
2
|
+
require "log4r"
|
3
|
+
|
4
|
+
module VagrantPlugins
|
5
|
+
module WindowsDomain
|
6
|
+
# The "Configuration" represents a configuration of how the WindowsDomain
|
7
|
+
# provisioner should behave: authentication mechanism etc.
|
8
|
+
class Config < Vagrant.plugin("2", :config)
|
9
|
+
|
10
|
+
# The Windows Domain to join.
|
11
|
+
#
|
12
|
+
# Setting this will result in an additional restart.
|
13
|
+
attr_accessor :domain
|
14
|
+
|
15
|
+
# The new Computer Name to use when joining the domain.
|
16
|
+
#
|
17
|
+
# Uses the Rename-Computer PowerShell command. ORRRR -NewName flag??
|
18
|
+
# Specifies a new name for the computer in the new domain.
|
19
|
+
attr_accessor :computer_name
|
20
|
+
|
21
|
+
# The Username to use when authenticating against the Domain.
|
22
|
+
#
|
23
|
+
# Specifies a user account that has permission to join the computers to a new domain.
|
24
|
+
attr_accessor :username
|
25
|
+
|
26
|
+
# The Password to use when authenticating against the Domain.
|
27
|
+
#
|
28
|
+
# Specifies the password of a user account that has permission to
|
29
|
+
# join the computers to a new domain.
|
30
|
+
attr_accessor :password
|
31
|
+
|
32
|
+
# The set of Advanced options to pass when joining the Domain.
|
33
|
+
#
|
34
|
+
# See (https://technet.microsoft.com/en-us/library/hh849798.aspx) for detail.
|
35
|
+
# NOTE: If we user :computer_name from above this needs to be merged!!
|
36
|
+
attr_accessor :join_options
|
37
|
+
|
38
|
+
# Organisational Unit path in AD.
|
39
|
+
#
|
40
|
+
# Specifies an organizational unit (OU) for the domain account.
|
41
|
+
# Enter the full distinguished name of the OU in quotation marks.
|
42
|
+
# The default value is the default OU for machine objects in the domain.
|
43
|
+
attr_accessor :ou_path
|
44
|
+
|
45
|
+
# Performs an unsecure join to the specified domain.
|
46
|
+
#
|
47
|
+
# When this option is used username/password are not required
|
48
|
+
attr_accessor :unsecure
|
49
|
+
|
50
|
+
# The current Computer Name.
|
51
|
+
#
|
52
|
+
# Used to determine whether or not we need to rename the computer
|
53
|
+
# on join. This parameter should not be manually set.
|
54
|
+
attr_accessor :old_computer_name
|
55
|
+
|
56
|
+
def initialize
|
57
|
+
super
|
58
|
+
@domain = UNSET_VALUE
|
59
|
+
@computer_name = UNSET_VALUE
|
60
|
+
@username = UNSET_VALUE
|
61
|
+
@password = UNSET_VALUE
|
62
|
+
@join_options = {}
|
63
|
+
@ou_path = UNSET_VALUE
|
64
|
+
@unsecure = UNSET_VALUE
|
65
|
+
@logger = Log4r::Logger.new("vagrant::vagrant_windows_domain")
|
66
|
+
end
|
67
|
+
|
68
|
+
# Final step of the Configuration lifecyle prior to
|
69
|
+
# validation.
|
70
|
+
#
|
71
|
+
# Ensures all attributes are set to defaults if not provided.
|
72
|
+
def finalize!
|
73
|
+
super
|
74
|
+
|
75
|
+
# Null checks
|
76
|
+
@domain = nil if @domain == UNSET_VALUE || @domain == ""
|
77
|
+
@computer_name = nil if @computer_name == UNSET_VALUE || @computer_name == ""
|
78
|
+
@username = nil if @username == UNSET_VALUE || @username == ""
|
79
|
+
@password = nil if @password == UNSET_VALUE || @password == ""
|
80
|
+
@join_options = {} if @join_options == UNSET_VALUE
|
81
|
+
@ou_path = nil if @ou_path == UNSET_VALUE
|
82
|
+
@unsecure = false if @unsecure == UNSET_VALUE
|
83
|
+
end
|
84
|
+
|
85
|
+
# Validate configuration and return a hash of errors.
|
86
|
+
#
|
87
|
+
# Validation happens after finalize!.
|
88
|
+
#
|
89
|
+
# @param [Machine] The current {Machine}
|
90
|
+
# @return [Hash] Any errors or {} if no errors found
|
91
|
+
def validate(machine)
|
92
|
+
@old_computer_name = get_guest_computer_name(machine)
|
93
|
+
|
94
|
+
errors = _detected_errors
|
95
|
+
|
96
|
+
# Need to supply one of them!
|
97
|
+
if ( (@username != nil && @password != nil) && @unsecure == true)
|
98
|
+
errors << I18n.t("vagrant_windows_domain.errors.both_credentials_provided")
|
99
|
+
end
|
100
|
+
|
101
|
+
{ "windows domain provisioner" => errors }
|
102
|
+
end
|
103
|
+
|
104
|
+
# Gets the Computer Name from the guest machine
|
105
|
+
def get_guest_computer_name(machine)
|
106
|
+
computerName = ""
|
107
|
+
machine.communicate.shell.powershell("$env:COMPUTERNAME") do |type, data|
|
108
|
+
if !data.chomp.empty?
|
109
|
+
if [:stderr, :stdout].include?(type)
|
110
|
+
color = type == :stdout ? :green : :red
|
111
|
+
computerName = data.chomp
|
112
|
+
@logger.info("Detected guest computer name: #{computerName}")
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
computerName
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
en:
|
2
|
+
vagrant_windows_domain:
|
3
|
+
already_status: |-
|
4
|
+
The machine is already %{status}.
|
5
|
+
|
6
|
+
running: |-
|
7
|
+
"Running Windows Domain Provisioner"
|
8
|
+
|
9
|
+
errors:
|
10
|
+
unsupported_platform: |-
|
11
|
+
Unsupported platform detected. Vagrant Windows Domain only works on Windows guest environments.
|
12
|
+
both_credentials_provided: |-
|
13
|
+
You must not supply a "username" and "password" if "unsecure" is set to true.
|
14
|
+
binary_not_detected: |-
|
15
|
+
"The command '%{binary} required to join/remove the guest machine from the domain '%{domain}' was not found on the guest machine"
|
16
|
+
absolute_module_path: |-
|
17
|
+
"Absolute 'module_path' not allowed. Please provide a path relative to your Vagrantfile."
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require "vagrant"
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module WindowsDomain
|
5
|
+
class Plugin < Vagrant.plugin("2")
|
6
|
+
name "DSC"
|
7
|
+
description <<-DESC
|
8
|
+
Provides support for adding and removing guest Windows machines
|
9
|
+
from a Domain.
|
10
|
+
DESC
|
11
|
+
|
12
|
+
config(:windows_domain, :provisioner) do
|
13
|
+
require_relative 'config'
|
14
|
+
Config
|
15
|
+
end
|
16
|
+
|
17
|
+
provisioner(:windows_domain) do
|
18
|
+
require_relative 'provisioner'
|
19
|
+
Provisioner
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,193 @@
|
|
1
|
+
require "log4r"
|
2
|
+
require 'erb'
|
3
|
+
|
4
|
+
module VagrantPlugins
|
5
|
+
module WindowsDomain
|
6
|
+
# DSC Errors namespace, including setup of locale-based error messages.
|
7
|
+
class WindowsDomainError < Vagrant::Errors::VagrantError
|
8
|
+
error_namespace("vagrant_windows_domain.errors")
|
9
|
+
I18n.load_path << File.expand_path("locales/en.yml", File.dirname(__FILE__))
|
10
|
+
end
|
11
|
+
class DSCUnsupportedOperation < WindowsDomainError
|
12
|
+
error_key(:unsupported_operation)
|
13
|
+
end
|
14
|
+
|
15
|
+
# Windows Domain Provisioner Plugin.
|
16
|
+
#
|
17
|
+
# Connects and Removes a guest Machine from a Windows Domain.
|
18
|
+
class Provisioner < Vagrant.plugin("2", :provisioner)
|
19
|
+
|
20
|
+
# Default path for storing the transient script runner
|
21
|
+
WINDOWS_DOMAIN_GUEST_RUNNER_PATH = "c:/tmp/vagrant-windows-domain-runner.ps1"
|
22
|
+
|
23
|
+
# Constructs the Provisioner Plugin.
|
24
|
+
#
|
25
|
+
# @param [Machine] machine The guest machine that is to be provisioned.
|
26
|
+
# @param [Config] config The Configuration object used by the Provisioner.
|
27
|
+
# @returns Provisioner
|
28
|
+
def initialize(machine, config)
|
29
|
+
super
|
30
|
+
|
31
|
+
@logger = Log4r::Logger.new("vagrant::provisioners::vagrant_windows_domain")
|
32
|
+
end
|
33
|
+
|
34
|
+
# Configures the Provisioner.
|
35
|
+
#
|
36
|
+
# @param [Config] root_config The default configuration from the Vagrant hierarchy.
|
37
|
+
def configure(root_config)
|
38
|
+
raise WindowsDomainError, :unsupported_platform if !windows?
|
39
|
+
|
40
|
+
verify_guest_capability
|
41
|
+
end
|
42
|
+
|
43
|
+
# Run the Provisioner!
|
44
|
+
def provision
|
45
|
+
@machine.env.ui.say(:info, "Connecting guest machine to domain '#{config.domain}' with computer name '#{config.computer_name}'")
|
46
|
+
|
47
|
+
set_credentials
|
48
|
+
|
49
|
+
join_domain
|
50
|
+
|
51
|
+
restart_guest
|
52
|
+
end
|
53
|
+
|
54
|
+
# Join the guest machine to a Windows Domain.
|
55
|
+
#
|
56
|
+
# Generates, writes and runs a script to join a domain.
|
57
|
+
def join_domain
|
58
|
+
run_remote_command_runner(write_command_runner_script(generate_command_runner_script(true)))
|
59
|
+
end
|
60
|
+
|
61
|
+
# Removes the guest machine from a Windows Domain.
|
62
|
+
#
|
63
|
+
# Generates, writes and runs a script to leave a domain.
|
64
|
+
def leave_domain
|
65
|
+
run_remote_command_runner(write_command_runner_script(generate_command_runner_script(false)))
|
66
|
+
end
|
67
|
+
alias_method :unjoin_domain, :leave_domain
|
68
|
+
|
69
|
+
# Ensure credentials are provided.
|
70
|
+
#
|
71
|
+
# Get username/password from user if not provided
|
72
|
+
# as part of the config.
|
73
|
+
def set_credentials
|
74
|
+
if (config.username == nil)
|
75
|
+
@logger.info("==> Requesting username as none provided")
|
76
|
+
config.username = @machine.env.ui.ask("Please enter your domain username: ")
|
77
|
+
end
|
78
|
+
|
79
|
+
if (config.password == nil)
|
80
|
+
@logger.info("==> Requesting password as none provided")
|
81
|
+
config.password = @machine.env.ui.ask("Please enter your domain password (output will be hidden): ", {:echo => false})
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# Cleanup after a destroy action.
|
86
|
+
#
|
87
|
+
# This is the method called when destroying a machine that allows
|
88
|
+
# for any state related to the machine created by the provisioner
|
89
|
+
# to be cleaned up.
|
90
|
+
def cleanup
|
91
|
+
set_credentials
|
92
|
+
leave_domain
|
93
|
+
|
94
|
+
end
|
95
|
+
|
96
|
+
# Restarts the Computer and waits
|
97
|
+
def restart_guest
|
98
|
+
@machine.env.ui.say(:info, "Restarting computer for updates to take effect.")
|
99
|
+
options = {}
|
100
|
+
options[:provision_ignore_sentinel] = false
|
101
|
+
@machine.action(:reload, options)
|
102
|
+
begin
|
103
|
+
sleep 10
|
104
|
+
end until @machine.communicate.ready?
|
105
|
+
end
|
106
|
+
|
107
|
+
# Verify that we can call the remote operations.
|
108
|
+
# Required to add the computer to a Domain.
|
109
|
+
def verify_guest_capability
|
110
|
+
verify_binary("Add-Computer")
|
111
|
+
verify_binary("Remove-Computer")
|
112
|
+
end
|
113
|
+
|
114
|
+
# Verify a binary\command is executable on the guest machine.
|
115
|
+
def verify_binary(binary)
|
116
|
+
@machine.communicate.sudo(
|
117
|
+
"which #{binary}",
|
118
|
+
error_class: WindowsDomainError,
|
119
|
+
error_key: :binary_not_detected,
|
120
|
+
domain: config.domain,
|
121
|
+
binary: binary)
|
122
|
+
end
|
123
|
+
|
124
|
+
# Generates a PowerShell runner script from an ERB template
|
125
|
+
#
|
126
|
+
# @param [boolean] add_to_domain Whether or not to add or remove the computer to the domain (default: true).
|
127
|
+
# @return [String] The interpolated PowerShell script.
|
128
|
+
def generate_command_runner_script(add_to_domain=true)
|
129
|
+
path = File.expand_path("../templates/runner.ps1", __FILE__)
|
130
|
+
|
131
|
+
script = Vagrant::Util::TemplateRenderer.render(path, options: {
|
132
|
+
config: @config,
|
133
|
+
username: @config.username,
|
134
|
+
password: @config.password,
|
135
|
+
domain: @config.domain,
|
136
|
+
add_to_domain: add_to_domain
|
137
|
+
# parameters: @config.join_options.map { |k,v| "#{k}" + (!v.nil? ? " \"#{v}\"": '') }.join(" ")
|
138
|
+
})
|
139
|
+
end
|
140
|
+
|
141
|
+
# Writes the PowerShell runner script to a location on the guest.
|
142
|
+
#
|
143
|
+
# @param [String] script The PowerShell runner script.
|
144
|
+
# @return [String] the Path to the uploaded location on the guest machine.
|
145
|
+
def write_command_runner_script(script)
|
146
|
+
guest_script_path = WINDOWS_DOMAIN_GUEST_RUNNER_PATH
|
147
|
+
file = Tempfile.new(["vagrant-windows-domain-runner", "ps1"])
|
148
|
+
begin
|
149
|
+
file.write(script)
|
150
|
+
file.fsync
|
151
|
+
file.close
|
152
|
+
@machine.communicate.upload(file.path, guest_script_path)
|
153
|
+
ensure
|
154
|
+
file.close
|
155
|
+
file.unlink
|
156
|
+
end
|
157
|
+
guest_script_path
|
158
|
+
end
|
159
|
+
|
160
|
+
# Runs the PowerShell script on the guest machine.
|
161
|
+
def run_remote_command_runner(script_path)
|
162
|
+
command = ". '#{script_path}'"
|
163
|
+
|
164
|
+
@machine.ui.info(I18n.t(
|
165
|
+
"vagrant_windows_domain.running"))
|
166
|
+
|
167
|
+
opts = {
|
168
|
+
elevated: true,
|
169
|
+
error_key: :ssh_bad_exit_status_muted,
|
170
|
+
good_exit: 0,
|
171
|
+
shell: :powershell
|
172
|
+
}
|
173
|
+
|
174
|
+
@machine.communicate.sudo(command, opts) do |type, data|
|
175
|
+
if !data.chomp.empty?
|
176
|
+
if [:stderr, :stdout].include?(type)
|
177
|
+
color = type == :stdout ? :green : :red
|
178
|
+
@machine.ui.info(
|
179
|
+
data.chomp,
|
180
|
+
color: color, new_line: false, prefix: false)
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
# If on using WinRM, we can assume we are on Windows
|
187
|
+
def windows?
|
188
|
+
@machine.config.vm.communicator == :winrm
|
189
|
+
end
|
190
|
+
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
$secpasswd = ConvertTo-SecureString "<%= options[:password] %>" -AsPlainText -Force
|
2
|
+
$credentials = New-Object System.Management.Automation.PSCredential ("<%= options[:username] %>", $secpasswd)
|
3
|
+
|
4
|
+
<% if options[:add_to_domain] === true %>
|
5
|
+
echo "Add-Computer"
|
6
|
+
Add-Computer -DomainName <%= options[:domain] %> -Credential $credentials -Verbose -Force #-WhatIf
|
7
|
+
<% else %>
|
8
|
+
Remove-Computer -UnjoinDomainCredential $credentials -Verbose -Force
|
9
|
+
<% end %>
|
data/spec/base.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
shared_context "unit" do
|
2
|
+
before(:each) do
|
3
|
+
# State to store the list of registered plugins that we have to
|
4
|
+
# unregister later.
|
5
|
+
@_plugins = []
|
6
|
+
|
7
|
+
# Create a thing to store our temporary files so that they aren't
|
8
|
+
# unlinked right away.
|
9
|
+
@_temp_files = []
|
10
|
+
end
|
11
|
+
|
12
|
+
# This helper creates a temporary file and returns a Pathname
|
13
|
+
# object pointed to it.
|
14
|
+
#
|
15
|
+
# @return [Pathname]
|
16
|
+
def temporary_file(contents=nil)
|
17
|
+
f = Tempfile.new("vagrant-unit")
|
18
|
+
|
19
|
+
if contents
|
20
|
+
f.write(contents)
|
21
|
+
f.flush
|
22
|
+
end
|
23
|
+
|
24
|
+
# Store the tempfile in an instance variable so that it is not
|
25
|
+
# garbage collected, so that the tempfile is not unlinked.
|
26
|
+
@_temp_files << f
|
27
|
+
|
28
|
+
return Pathname.new(f.path)
|
29
|
+
end
|
30
|
+
|
31
|
+
# Asserts that the current (config) validation run should fail.
|
32
|
+
# Any error message is sufficient.
|
33
|
+
def assert_invalid
|
34
|
+
errors = subject.validate(machine)
|
35
|
+
if !errors.values.any? { |v| !v.empty? }
|
36
|
+
raise "No errors: #{errors.inspect}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Asserts that the current (config) validation should fail with a specific message.
|
41
|
+
def assert_error(error)
|
42
|
+
errors = subject.validate(machine)
|
43
|
+
raise "Error #{error} was not raised" if !errors["windows domain provisioner"].include? error
|
44
|
+
end
|
45
|
+
|
46
|
+
# Asserts that no failures should occur in the current (config) validation run.
|
47
|
+
def assert_valid
|
48
|
+
errors = subject.validate(machine)
|
49
|
+
if !errors.values.all? { |v| v.empty? }
|
50
|
+
raise "Errors: #{errors.inspect}"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'vagrant-windows-domain/provisioner'
|
3
|
+
require 'vagrant-windows-domain/config'
|
4
|
+
require 'base'
|
5
|
+
|
6
|
+
describe VagrantPlugins::WindowsDomain::Config do
|
7
|
+
include_context "unit"
|
8
|
+
let(:instance) { described_class.new }
|
9
|
+
let(:machine) { double("machine") }
|
10
|
+
|
11
|
+
let(:root_path) { (Pathname.new(Dir.mktmpdir)).to_s }
|
12
|
+
let(:ui) { Vagrant::UI::Silent.new }
|
13
|
+
let(:machine) { double("machine", ui: ui) }
|
14
|
+
let(:env) { double("environment", root_path: root_path, ui: ui) }
|
15
|
+
let(:vm) { double ("vm") }
|
16
|
+
let(:communicator) { double ("communicator") }
|
17
|
+
let(:shell) { double ("shell") }
|
18
|
+
let(:powershell) { double ("powershell") }
|
19
|
+
let(:guest) { double ("guest") }
|
20
|
+
let(:configuration_file) { "manifests/MyWebsite.ps1" }
|
21
|
+
let(:module_path) { ["foo/modules", "foo/modules2"] }
|
22
|
+
let(:root_config) { VagrantPlugins::DSC::Config.new }
|
23
|
+
# subject { described_class.new machine, root_config }
|
24
|
+
|
25
|
+
describe "defaults (finalize!)" do
|
26
|
+
|
27
|
+
before do
|
28
|
+
env = double("environment", root_path: "/tmp/vagrant-windows-domain-path")
|
29
|
+
config = double("config")
|
30
|
+
machine.stub(config: config, env: env)
|
31
|
+
end
|
32
|
+
|
33
|
+
before { subject.finalize! }
|
34
|
+
|
35
|
+
its("domain") { should be_nil }
|
36
|
+
its("computer_name") { should eq(nil) }
|
37
|
+
its("username") { should be_nil }
|
38
|
+
its("password") { should be_nil }
|
39
|
+
its("join_options") { should eq({}) }
|
40
|
+
its("ou_path") { should be_nil }
|
41
|
+
its("unsecure") { should eq(false) }
|
42
|
+
|
43
|
+
it "should ignore empty strings" do
|
44
|
+
subject.domain = ""
|
45
|
+
subject.username = ""
|
46
|
+
subject.password = ""
|
47
|
+
subject.computer_name = ""
|
48
|
+
|
49
|
+
subject.finalize!
|
50
|
+
|
51
|
+
expect(subject.domain).to be_nil
|
52
|
+
expect(subject.computer_name).to be_nil
|
53
|
+
expect(subject.username).to be_nil
|
54
|
+
expect(subject.password).to be_nil
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe "validate settings" do
|
59
|
+
before do
|
60
|
+
env = double("environment", root_path: "/tmp/vagrant-windows-domain-path")
|
61
|
+
config = double("config")
|
62
|
+
machine.stub(config: config, env: env)
|
63
|
+
allow(machine).to receive(:communicate).and_return(communicator)
|
64
|
+
allow(communicator).to receive(:shell).and_return(shell)
|
65
|
+
allow(shell).to receive(:powershell).and_yield(:stdout, "myoldcomputername")
|
66
|
+
end
|
67
|
+
|
68
|
+
before { subject.finalize! }
|
69
|
+
|
70
|
+
it "should be invalid if either 'username' and 'password' or 'unsecure' are both provided" do
|
71
|
+
subject.username = "myusername"
|
72
|
+
subject.password = "mypassword"
|
73
|
+
subject.unsecure = true
|
74
|
+
subject.validate(machine)
|
75
|
+
|
76
|
+
assert_invalid
|
77
|
+
assert_error("You must not supply a \"username\" and \"password\" if \"unsecure\" is set to true.")
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should detect the current computers' name" do
|
81
|
+
subject.validate(machine)
|
82
|
+
expect(subject.old_computer_name).to eq("myoldcomputername")
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
@@ -0,0 +1,197 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'vagrant-windows-domain/provisioner'
|
3
|
+
require 'vagrant-windows-domain/config'
|
4
|
+
require 'rspec/its'
|
5
|
+
|
6
|
+
describe VagrantPlugins::WindowsDomain::Provisioner do
|
7
|
+
include_context "unit"
|
8
|
+
|
9
|
+
let(:root_path) { (Pathname.new(Dir.mktmpdir)).to_s }
|
10
|
+
let(:ui) { Vagrant::UI::Silent.new }
|
11
|
+
let(:machine) { double("machine", ui: ui) }
|
12
|
+
let(:env) { double("environment", root_path: root_path, ui: ui) }
|
13
|
+
let(:vm) { double ("vm") }
|
14
|
+
let(:communicator) { double ("communicator") }
|
15
|
+
let(:shell) { double ("shell") }
|
16
|
+
let(:powershell) { double ("powershell") }
|
17
|
+
let(:guest) { double ("guest") }
|
18
|
+
let(:configuration_file) { "manifests/MyWebsite.ps1" }
|
19
|
+
let(:module_path) { ["foo/modules", "foo/modules2"] }
|
20
|
+
let(:root_config) { VagrantPlugins::WindowsDomain::Config.new }
|
21
|
+
subject { described_class.new machine, root_config }
|
22
|
+
|
23
|
+
describe "configure" do
|
24
|
+
before do
|
25
|
+
allow(machine).to receive(:root_config).and_return(root_config)
|
26
|
+
machine.stub(config: root_config, env: env)
|
27
|
+
|
28
|
+
allow(machine).to receive(:communicate).and_return(communicator)
|
29
|
+
allow(communicator).to receive(:shell).and_return(shell)
|
30
|
+
allow(shell).to receive(:powershell).with("$env:COMPUTERNAME").and_yield(:stdout, "myoldcomputername")
|
31
|
+
allow(root_config).to receive(:vm).and_return(vm)
|
32
|
+
allow(vm).to receive(:communicator).and_return(:winrm)
|
33
|
+
root_config.finalize!
|
34
|
+
root_config.validate(machine)
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should confirm if the OS is Windows" do
|
38
|
+
allow(communicator).to receive(:sudo).twice
|
39
|
+
expect(subject.windows?).to eq(true)
|
40
|
+
subject.configure(root_config)
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should error if the detected OS is not Windows" do
|
44
|
+
allow(vm).to receive(:communicator).and_return(:ssh)
|
45
|
+
expect { subject.configure(root_config) }.to raise_error("Unsupported platform detected. Vagrant Windows Domain only works on Windows guest environments.")
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should verify the guest has the required powershell cmdlets/capabilities" do
|
49
|
+
expect(communicator).to receive(:sudo).with("which Add-Computer", {:error_class=>VagrantPlugins::WindowsDomain::WindowsDomainError, :error_key=>:binary_not_detected, :domain=>nil, :binary=>"Add-Computer"})
|
50
|
+
expect(communicator).to receive(:sudo).with("which Remove-Computer", {:error_class=>VagrantPlugins::WindowsDomain::WindowsDomainError, :error_key=>:binary_not_detected, :domain=>nil, :binary=>"Remove-Computer"})
|
51
|
+
subject.configure(root_config)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe "provision" do
|
56
|
+
|
57
|
+
# before do
|
58
|
+
# # allow(root_config).to receive(:vm).and_return(vm)
|
59
|
+
# allow(machine).to receive(:root_config).and_return(root_config)
|
60
|
+
# allow(machine).to receive(:env).and_return(env)
|
61
|
+
# root_config.finalize!
|
62
|
+
# root_config.validate(machine)
|
63
|
+
# subject.configure(root_config)
|
64
|
+
# machine.stub(config: root_config, env: env, communicate: communicator, guest: guest)
|
65
|
+
# end
|
66
|
+
|
67
|
+
it "should join the domain" do
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should restart the machine on a successful domain join" do
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should not attempt to join the domain if already on it" do
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should authenticate with credentials if provided" do
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should prompt for credentials if not provided" do
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should remove any traces of credentials once provisioning has occurred" do
|
88
|
+
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
describe "cleanup" do
|
94
|
+
|
95
|
+
it "should leave domain when a `vagrant destroy` is issued" do
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
|
101
|
+
# describe "Powershell runner script" do
|
102
|
+
# before do
|
103
|
+
# # Prevent counters messing with output in tests
|
104
|
+
# Vagrant::Util::Counter.class_eval do
|
105
|
+
# def get_and_update_counter(name=nil) 1 end
|
106
|
+
# end
|
107
|
+
|
108
|
+
# allow(machine).to receive(:root_config).and_return(root_config)
|
109
|
+
# root_config.configuration_file = configuration_file
|
110
|
+
# machine.stub(config: root_config, env: env)
|
111
|
+
# root_config.module_path = module_path
|
112
|
+
# root_config.configuration_file = configuration_file
|
113
|
+
# root_config.finalize!
|
114
|
+
# root_config.validate(machine)
|
115
|
+
# subject.configure(root_config)
|
116
|
+
|
117
|
+
# end
|
118
|
+
|
119
|
+
# context "with default parameters" do
|
120
|
+
# it "should generate a valid powershell command" do
|
121
|
+
# script = subject.generate_dsc_runner_script
|
122
|
+
# expect_script = "#
|
123
|
+
# # DSC Runner.
|
124
|
+
# #
|
125
|
+
# # Bootstraps the DSC environment, sets up configuration data
|
126
|
+
# # and runs the DSC Configuration.
|
127
|
+
# #
|
128
|
+
# #
|
129
|
+
|
130
|
+
# # Set the local PowerShell Module environment path
|
131
|
+
# $absoluteModulePaths = [string]::Join(\";\", (\"/tmp/vagrant-windows-domain-1/modules-0;/tmp/vagrant-windows-domain-1/modules-1\".Split(\";\") | ForEach-Object { $_ | Resolve-Path }))
|
132
|
+
|
133
|
+
# echo \"Adding to path: $absoluteModulePaths\"
|
134
|
+
# $env:PSModulePath=\"$absoluteModulePaths;${env:PSModulePath}\"
|
135
|
+
# (\"/tmp/vagrant-windows-domain-1/modules-0;/tmp/vagrant-windows-domain-1/modules-1\".Split(\";\") | ForEach-Object { gci -Recurse $_ | ForEach-Object { Unblock-File $_.FullName} })
|
136
|
+
|
137
|
+
# $script = $(Join-Path \"/tmp/vagrant-windows-domain-1\" \"manifests/MyWebsite.ps1\" -Resolve)
|
138
|
+
# echo \"PSModulePath Configured: ${env:PSModulePath}\"
|
139
|
+
# echo \"Running Configuration file: ${script}\"
|
140
|
+
|
141
|
+
# # Generate the MOF file, only if a MOF path not already provided.
|
142
|
+
# # Import the Manifest
|
143
|
+
# . $script
|
144
|
+
|
145
|
+
# cd \"/tmp/vagrant-windows-domain-1\"
|
146
|
+
# $StagingPath = $(Join-Path \"/tmp/vagrant-windows-domain-1\" \"staging\")
|
147
|
+
# $response = MyWebsite -OutputPath $StagingPath 4>&1 5>&1 | Out-String
|
148
|
+
|
149
|
+
# # Start a DSC Configuration run
|
150
|
+
# $response += Start-DscConfiguration -Force -Wait -Verbose -Path $StagingPath 4>&1 5>&1 | Out-String
|
151
|
+
# $response"
|
152
|
+
|
153
|
+
# expect(script).to eq(expect_script)
|
154
|
+
# end
|
155
|
+
# end
|
156
|
+
|
157
|
+
# end
|
158
|
+
|
159
|
+
# describe "write DSC Runner script" do
|
160
|
+
# it "should upload the customised DSC runner to the guest" do
|
161
|
+
# script = "myscript"
|
162
|
+
# path = "/local/runner/path"
|
163
|
+
# guest_path = "c:/tmp/vagrant-windows-domain-runner.ps1"
|
164
|
+
# machine.stub(config: root_config, env: env, communicate: communicator)
|
165
|
+
# file = double("file")
|
166
|
+
# allow(file).to receive(:path).and_return(path)
|
167
|
+
# allow(Tempfile).to receive(:new) { file }
|
168
|
+
# expect(file).to receive(:write).with(script)
|
169
|
+
# expect(file).to receive(:fsync)
|
170
|
+
# expect(file).to receive(:close).exactly(2).times
|
171
|
+
# expect(file).to receive(:unlink)
|
172
|
+
# expect(communicator).to receive(:upload).with(path, guest_path)
|
173
|
+
# res = subject.write_dsc_runner_script(script)
|
174
|
+
# expect(res.to_s).to eq(guest_path)
|
175
|
+
# end
|
176
|
+
# end
|
177
|
+
|
178
|
+
# describe "Apply DSC" do
|
179
|
+
# it "should invoke the DSC Runner and notify the User of provisioning status" do
|
180
|
+
# expect(ui).to receive(:info).with(any_args).once
|
181
|
+
# expect(ui).to receive(:info).with("provisioned!", {color: :green, new_line: false, prefix: false}).once
|
182
|
+
# allow(machine).to receive(:communicate).and_return(communicator)
|
183
|
+
# expect(communicator).to receive(:sudo).with('. ' + "'c:/tmp/vagrant-windows-domain-runner.ps1'",{:elevated=>true, :error_key=>:ssh_bad_exit_status_muted, :good_exit=>0, :shell=>:powershell}).and_yield(:stdout, "provisioned!")
|
184
|
+
|
185
|
+
# subject.run_dsc_apply
|
186
|
+
# end
|
187
|
+
|
188
|
+
# it "should show error output in red" do
|
189
|
+
# expect(ui).to receive(:info).with(any_args).once
|
190
|
+
# expect(ui).to receive(:info).with("provisioned!", {color: :red, new_line: false, prefix: false}).once
|
191
|
+
# allow(machine).to receive(:communicate).and_return(communicator)
|
192
|
+
# expect(communicator).to receive(:sudo).with('. ' + "'c:/tmp/vagrant-windows-domain-runner.ps1'",{:elevated=>true, :error_key=>:ssh_bad_exit_status_muted, :good_exit=>0, :shell=>:powershell}).and_yield(:stderr, "provisioned!")
|
193
|
+
|
194
|
+
# subject.run_dsc_apply
|
195
|
+
# end
|
196
|
+
# end
|
197
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'simplecov'
|
2
|
+
require 'coveralls'
|
3
|
+
|
4
|
+
require 'vagrant-windows-domain/version'
|
5
|
+
require 'vagrant-windows-domain/plugin'
|
6
|
+
require 'rspec/its'
|
7
|
+
require 'base'
|
8
|
+
|
9
|
+
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
|
10
|
+
SimpleCov::Formatter::HTMLFormatter,
|
11
|
+
Coveralls::SimpleCov::Formatter
|
12
|
+
]
|
13
|
+
|
14
|
+
SimpleCov.start do
|
15
|
+
coverage_dir('tmp/coverage')
|
16
|
+
add_filter '/spec/'
|
17
|
+
end
|
18
|
+
|
19
|
+
RSpec.configure do |config|
|
20
|
+
config.expect_with :rspec do |c|
|
21
|
+
c.syntax = :expect
|
22
|
+
end
|
23
|
+
config.color = true
|
24
|
+
config.tty = true
|
25
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'vagrant-windows-domain/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "vagrant-windows-domain"
|
8
|
+
spec.version = Vagrant::WindowsDomain::VERSION
|
9
|
+
spec.authors = ["Matt Fellows"]
|
10
|
+
spec.email = ["matt.fellows@onegeek.com.au"]
|
11
|
+
spec.summary = "Windows Domain Provisioner for Vagrant"
|
12
|
+
spec.description = "Adds and Removes Windows Guests from a Windows Domain, as part of the standard machine lifecycle."
|
13
|
+
spec.homepage = "https://github.com/SEEK-Jobs/vagrant-windows-domain"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "rake", '~> 10.3', '>= 10.3.0'
|
22
|
+
spec.add_development_dependency "bundler", "~> 1.6", '>= 1.6.0'
|
23
|
+
spec.add_development_dependency "coveralls", "~> 0.7.1", '>= 0.7.1'
|
24
|
+
spec.add_development_dependency "rspec-core", '~> 3.1', '>= 3.1.0'
|
25
|
+
spec.add_development_dependency "rspec-expectations", '~> 3.1', '>= 3.1.0'
|
26
|
+
spec.add_development_dependency "rspec-mocks", '~> 3.1', '>= 3.1.0'
|
27
|
+
spec.add_development_dependency "rspec-its", "~> 1.0.1", '>= 1.0.0'
|
28
|
+
end
|
metadata
ADDED
@@ -0,0 +1,208 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: vagrant-windows-domain
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Matt Fellows
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-01-30 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rake
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '10.3'
|
20
|
+
- - '>='
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 10.3.0
|
23
|
+
type: :development
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '10.3'
|
30
|
+
- - '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 10.3.0
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: bundler
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ~>
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '1.6'
|
40
|
+
- - '>='
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: 1.6.0
|
43
|
+
type: :development
|
44
|
+
prerelease: false
|
45
|
+
version_requirements: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - ~>
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '1.6'
|
50
|
+
- - '>='
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: 1.6.0
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: coveralls
|
55
|
+
requirement: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - ~>
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: 0.7.1
|
60
|
+
- - '>='
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: 0.7.1
|
63
|
+
type: :development
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ~>
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 0.7.1
|
70
|
+
- - '>='
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: 0.7.1
|
73
|
+
- !ruby/object:Gem::Dependency
|
74
|
+
name: rspec-core
|
75
|
+
requirement: !ruby/object:Gem::Requirement
|
76
|
+
requirements:
|
77
|
+
- - ~>
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: '3.1'
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 3.1.0
|
83
|
+
type: :development
|
84
|
+
prerelease: false
|
85
|
+
version_requirements: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ~>
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '3.1'
|
90
|
+
- - '>='
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: 3.1.0
|
93
|
+
- !ruby/object:Gem::Dependency
|
94
|
+
name: rspec-expectations
|
95
|
+
requirement: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - ~>
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '3.1'
|
100
|
+
- - '>='
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: 3.1.0
|
103
|
+
type: :development
|
104
|
+
prerelease: false
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - ~>
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '3.1'
|
110
|
+
- - '>='
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: 3.1.0
|
113
|
+
- !ruby/object:Gem::Dependency
|
114
|
+
name: rspec-mocks
|
115
|
+
requirement: !ruby/object:Gem::Requirement
|
116
|
+
requirements:
|
117
|
+
- - ~>
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
version: '3.1'
|
120
|
+
- - '>='
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: 3.1.0
|
123
|
+
type: :development
|
124
|
+
prerelease: false
|
125
|
+
version_requirements: !ruby/object:Gem::Requirement
|
126
|
+
requirements:
|
127
|
+
- - ~>
|
128
|
+
- !ruby/object:Gem::Version
|
129
|
+
version: '3.1'
|
130
|
+
- - '>='
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: 3.1.0
|
133
|
+
- !ruby/object:Gem::Dependency
|
134
|
+
name: rspec-its
|
135
|
+
requirement: !ruby/object:Gem::Requirement
|
136
|
+
requirements:
|
137
|
+
- - ~>
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: 1.0.1
|
140
|
+
- - '>='
|
141
|
+
- !ruby/object:Gem::Version
|
142
|
+
version: 1.0.0
|
143
|
+
type: :development
|
144
|
+
prerelease: false
|
145
|
+
version_requirements: !ruby/object:Gem::Requirement
|
146
|
+
requirements:
|
147
|
+
- - ~>
|
148
|
+
- !ruby/object:Gem::Version
|
149
|
+
version: 1.0.1
|
150
|
+
- - '>='
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: 1.0.0
|
153
|
+
description: Adds and Removes Windows Guests from a Windows Domain, as part of the
|
154
|
+
standard machine lifecycle.
|
155
|
+
email:
|
156
|
+
- matt.fellows@onegeek.com.au
|
157
|
+
executables: []
|
158
|
+
extensions: []
|
159
|
+
extra_rdoc_files: []
|
160
|
+
files:
|
161
|
+
- .gitignore
|
162
|
+
- .travis.yml
|
163
|
+
- Gemfile
|
164
|
+
- LICENSE.txt
|
165
|
+
- README.md
|
166
|
+
- Rakefile
|
167
|
+
- development/Vagrantfile
|
168
|
+
- lib/vagrant-windows-domain.rb
|
169
|
+
- lib/vagrant-windows-domain/config.rb
|
170
|
+
- lib/vagrant-windows-domain/locales/en.yml
|
171
|
+
- lib/vagrant-windows-domain/plugin.rb
|
172
|
+
- lib/vagrant-windows-domain/provisioner.rb
|
173
|
+
- lib/vagrant-windows-domain/templates/runner.ps1.erb
|
174
|
+
- lib/vagrant-windows-domain/version.rb
|
175
|
+
- spec/base.rb
|
176
|
+
- spec/provisioner/config_spec.rb
|
177
|
+
- spec/provisioner/provisioner_spec.rb
|
178
|
+
- spec/spec_helper.rb
|
179
|
+
- vagrant-windows-domain.gemspec
|
180
|
+
homepage: https://github.com/SEEK-Jobs/vagrant-windows-domain
|
181
|
+
licenses:
|
182
|
+
- MIT
|
183
|
+
metadata: {}
|
184
|
+
post_install_message:
|
185
|
+
rdoc_options: []
|
186
|
+
require_paths:
|
187
|
+
- lib
|
188
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
189
|
+
requirements:
|
190
|
+
- - '>='
|
191
|
+
- !ruby/object:Gem::Version
|
192
|
+
version: '0'
|
193
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
194
|
+
requirements:
|
195
|
+
- - '>='
|
196
|
+
- !ruby/object:Gem::Version
|
197
|
+
version: '0'
|
198
|
+
requirements: []
|
199
|
+
rubyforge_project:
|
200
|
+
rubygems_version: 2.4.1
|
201
|
+
signing_key:
|
202
|
+
specification_version: 4
|
203
|
+
summary: Windows Domain Provisioner for Vagrant
|
204
|
+
test_files:
|
205
|
+
- spec/base.rb
|
206
|
+
- spec/provisioner/config_spec.rb
|
207
|
+
- spec/provisioner/provisioner_spec.rb
|
208
|
+
- spec/spec_helper.rb
|