1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
|
Puppet::Face.define(:node, '0.0.1') do
action(:clean) do
option "--[no-]unexport" do
summary "Unexport exported resources"
end
summary "Clean up everything a puppetmaster knows about a node"
arguments "<host1> [<host2> ...]"
description <<-EOT
This includes
* Signed certificates ($vardir/ssl/ca/signed/node.domain.pem)
* Cached facts ($vardir/yaml/facts/node.domain.yaml)
* Cached node stuff ($vardir/yaml/node/node.domain.yaml)
* Reports ($vardir/reports/node.domain)
* Stored configs: it can either remove all data from an host in your
storedconfig database, or with --unexport turn every exported resource
supporting ensure to absent so that any other host checking out their
config can remove those exported configurations.
This will unexport exported resources of a
host, so that consumers of these resources can remove the exported
resources and we will safely remove the node from our
infrastructure.
EOT
when_invoked do |*args|
nodes = args[0..-2]
options = args.last
raise "At least one node should be passed" if nodes.empty? || nodes == options
# TODO: this is a hack and should be removed if faces provide the proper
# infrastructure to set the run mode.
require 'puppet/util/run_mode'
$puppet_application_mode = Puppet::Util::RunMode[:master]
if Puppet::SSL::CertificateAuthority.ca?
Puppet::SSL::Host.ca_location = :local
else
Puppet::SSL::Host.ca_location = :none
end
Puppet::Node::Facts.indirection.terminus_class = :yaml
Puppet::Node::Facts.indirection.cache_class = :yaml
Puppet::Node.indirection.terminus_class = :yaml
Puppet::Node.indirection.cache_class = :yaml
nodes.each { |node| cleanup(node.downcase, options[:unexport]) }
end
end
def cleanup(node, unexport)
clean_cert(node)
clean_cached_facts(node)
clean_cached_node(node)
clean_reports(node)
# This is roughly functional, but seems to introduce order-dependent test
# failures; this can be re-added when those issues are resolved.
# clean_storeconfigs(node, unexport)
end
# clean signed cert for +host+
def clean_cert(node)
if Puppet::SSL::CertificateAuthority.ca?
Puppet::Face[:ca, :current].revoke(node)
Puppet::Face[:ca, :current].destroy(node)
Puppet.info "#{node} certificates removed from ca"
else
Puppet.info "Not managing #{node} certs as this host is not a CA"
end
end
# clean facts for +host+
def clean_cached_facts(node)
Puppet::Node::Facts.indirection.destroy(node)
Puppet.info "#{node}'s facts removed"
end
# clean cached node +host+
def clean_cached_node(node)
Puppet::Node.indirection.destroy(node)
Puppet.info "#{node}'s cached node removed"
end
# clean node reports for +host+
def clean_reports(node)
Puppet::Transaction::Report.indirection.destroy(node)
Puppet.info "#{node}'s reports removed"
end
# clean storeconfig for +node+
def clean_storeconfigs(node, do_unexport=false)
return unless Puppet[:storeconfigs] && Puppet.features.rails?
require 'puppet/rails'
Puppet::Rails.connect
unless rails_node = Puppet::Rails::Host.find_by_name(node)
Puppet.notice "No entries found for #{node} in storedconfigs."
return
end
if do_unexport
unexport(rails_node)
Puppet.notice "Force #{node}'s exported resources to absent"
Puppet.warning "Please wait until all other hosts have checked out their configuration before finishing the cleanup with:"
Puppet.warning "$ puppet node clean #{node}"
else
rails_node.destroy
Puppet.notice "#{node} storeconfigs removed"
end
end
def unexport(node)
# fetch all exported resource
query = {:include => {:param_values => :param_name}}
query[:conditions] = [ "exported=? AND host_id=?", true, node.id ]
Puppet::Rails::Resource.find(:all, query).each do |resource|
if type_is_ensurable(resource)
line = 0
param_name = Puppet::Rails::ParamName.find_or_create_by_name("ensure")
if ensure_param = resource.param_values.find(
:first,
:conditions => [ 'param_name_id = ?', param_name.id ]
)
line = ensure_param.line.to_i
Puppet::Rails::ParamValue.delete(ensure_param.id);
end
# force ensure parameter to "absent"
resource.param_values.create(
:value => "absent",
:line => line,
:param_name => param_name
)
Puppet.info("#{resource.name} has been marked as \"absent\"")
end
end
end
def environment
@environment ||= Puppet::Node::Environment.new
end
def type_is_ensurable(resource)
if (type = Puppet::Type.type(resource.restype)) && type.validattr?(:ensure)
return true
else
type = environment.known_resource_types.find_definition('', resource.restype)
return true if type && type.arguments.keys.include?('ensure')
end
return false
end
end
|