summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Smith <tsmith@chef.io>2019-10-09 08:23:04 -0700
committerGitHub <noreply@github.com>2019-10-09 08:23:04 -0700
commit11311c4f7d5f867f551c597ab9495b820e6eb336 (patch)
treeed44327df6a4223b59dea0a5b066cf2202dc2c1b
parent68dfb74ac66ff8c4e78fda7d2d2d8dc1b9e5158b (diff)
parent9b54fdc5405c4764cbb509d229576a1baa99a57e (diff)
downloadchef-11311c4f7d5f867f551c597ab9495b820e6eb336.tar.gz
Merge pull request #8379 from jasonwbarnett/feature/add-leave-action-to-windows_ad_join
windows_ad_join: Add :leave action to for leaving an AD domain
-rw-r--r--lib/chef/resource/windows_ad_join.rb75
-rw-r--r--spec/unit/resource/windows_ad_join_spec.rb4
2 files changed, 76 insertions, 3 deletions
diff --git a/lib/chef/resource/windows_ad_join.rb b/lib/chef/resource/windows_ad_join.rb
index c0a84746b5..08264bb16e 100644
--- a/lib/chef/resource/windows_ad_join.rb
+++ b/lib/chef/resource/windows_ad_join.rb
@@ -57,6 +57,10 @@ class Chef
description: "Specifies a new hostname for the computer in the new domain.",
introduced: "14.5"
+ property :workgroup_name, String,
+ description: "Specifies the name of a workgroup to which the computer is added to when it is removed from the domain. The default value is WORKGROUP. This property is only applicable to the :leave action.",
+ introduced: "15.0"
+
# define this again so we can default it to true. Otherwise failures print the password
property :sensitive, [TrueClass, FalseClass],
default: true, desired_state: false
@@ -64,7 +68,7 @@ class Chef
action :join do
description "Join the Active Directory domain."
- unless on_domain?
+ unless on_desired_domain?
cmd = "$pswd = ConvertTo-SecureString \'#{new_resource.domain_password}\' -AsPlainText -Force;"
cmd << "$credential = New-Object System.Management.Automation.PSCredential (\"#{new_resource.domain_user}@#{new_resource.domain_name}\",$pswd);"
cmd << "Add-Computer -DomainName #{new_resource.domain_name} -Credential $credential"
@@ -92,12 +96,77 @@ class Chef
end
end
+ action :leave do
+ description "Leave the Active Directory domain."
+
+ if joined_to_domain?
+ cmd = ""
+ cmd << "$pswd = ConvertTo-SecureString \'#{new_resource.domain_password}\' -AsPlainText -Force;"
+ cmd << "$credential = New-Object System.Management.Automation.PSCredential (\"#{new_resource.domain_user}@#{new_resource.domain_name}\",$pswd);"
+ cmd << "Remove-Computer"
+ cmd << " -UnjoinDomainCredential $credential"
+ cmd << " -NewName \"#{new_resource.new_hostname}\"" if new_resource.new_hostname
+ cmd << " -WorkgroupName \"#{new_resource.workgroup_name}\"" if new_resource.workgroup_name
+ cmd << " -Force"
+
+ converge_by("leave Active Directory domain #{node_domain}") do
+ ps_run = powershell_out(cmd)
+ if ps_run.error?
+ if sensitive?
+ raise "Failed to leave the domain #{node_domain}: *suppressed sensitive resource output*"
+ else
+ raise "Failed to leave the domain #{node_domain}: #{ps_run.stderr}"
+ end
+ end
+
+ unless new_resource.reboot == :never
+ reboot "Reboot to leave domain #{new_resource.domain_name}" do
+ action clarify_reboot(new_resource.reboot)
+ reason "Reboot to leave domain #{new_resource.domain_name}"
+ end
+ end
+ end
+ end
+ end
+
action_class do
- def on_domain?
+ #
+ # @return [String] The domain name the node is joined to. When the node
+ # is not joined to a domain this will return the name of the
+ # workgroup the node is a member of.
+ #
+ def node_domain
node_domain = powershell_out!("(Get-WmiObject Win32_ComputerSystem).Domain")
raise "Failed to check if the system is joined to the domain #{new_resource.domain_name}: #{node_domain.stderr}}" if node_domain.error?
- node_domain.stdout.downcase.strip == new_resource.domain_name.downcase
+ node_domain.stdout.downcase.strip
+ end
+
+ #
+ # @return [String] The workgroup the node is a member of. This will
+ # return an empty string if the system is not a member of a
+ # workgroup.
+ #
+ def node_workgroup
+ node_workgroup = powershell_out!("(Get-WmiObject Win32_ComputerSystem).Workgroup")
+ raise "Failed to check if the system is currently a member of a workgroup" if node_workgroup.error?
+
+ node_workgroup.stdout.downcase.strip
+ end
+
+ #
+ # @return [true, false] Whether or not the node is joined to ANY domain
+ #
+ def joined_to_domain?
+ node_workgroup.empty? && !node_domain.empty?
+ end
+
+ #
+ # @return [true, false] Whether or not the node is joined to the domain
+ # defined by the resource :domain_name property.
+ #
+ def on_desired_domain?
+ node_domain == new_resource.domain_name.downcase
end
# This resource historically took `:immediate` and `:delayed` as arguments to the reboot property but then
diff --git a/spec/unit/resource/windows_ad_join_spec.rb b/spec/unit/resource/windows_ad_join_spec.rb
index 87dd83cd49..98f7111e69 100644
--- a/spec/unit/resource/windows_ad_join_spec.rb
+++ b/spec/unit/resource/windows_ad_join_spec.rb
@@ -36,6 +36,10 @@ describe Chef::Resource::WindowsAdJoin do
expect { resource.action :join }.not_to raise_error
end
+ it "supports :leave action" do
+ expect { resource.action :leave }.not_to raise_error
+ end
+
it "only accepts FQDNs for the domain_name property" do
expect { resource.domain_name "example" }.to raise_error(ArgumentError)
end