vagrant-windows-domain 1.0.0
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 +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
|
+
[![Build Status](https://travis-ci.org/SEEK-Jobs/vagrant-windows-domain.svg)](https://travis-ci.org/SEEK-Jobs/vagrant-windows-domain)
|
4
|
+
[![Coverage Status](https://coveralls.io/repos/SEEK-Jobs/vagrant-windows-domain/badge.svg?branch=master)](https://coveralls.io/r/SEEK-Jobs/vagrant-windows-domain?branch=master)
|
5
|
+
[![Gem Version](https://badge.fury.io/rb/vagrant-windows-domain.svg)](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
|