puppet 2.6.8 → 2.6.9
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of puppet might be problematic. Click here for more details.
- data/CHANGELOG +41 -0
- data/{README.rst → README.md} +17 -10
- data/conf/redhat/puppet.spec +93 -22
- data/ext/vim/README +2 -1
- data/ext/vim/ftplugin/puppet.vim +94 -0
- data/ext/vim/indent/puppet.vim +76 -0
- data/lib/puppet.rb +2 -3
- data/lib/puppet/application/agent.rb +3 -3
- data/lib/puppet/application/apply.rb +16 -5
- data/lib/puppet/configurer.rb +60 -56
- data/lib/puppet/configurer/fact_handler.rb +6 -1
- data/lib/puppet/defaults.rb +19 -0
- data/lib/puppet/file_serving/fileset.rb +1 -1
- data/lib/puppet/indirector/exec.rb +3 -3
- data/lib/puppet/indirector/queue.rb +1 -1
- data/lib/puppet/metatype/manager.rb +7 -20
- data/lib/puppet/parser/compiler.rb +17 -16
- data/lib/puppet/parser/resource.rb +18 -1
- data/lib/puppet/parser/scope.rb +2 -2
- data/lib/puppet/provider/mount/parsed.rb +1 -1
- data/lib/puppet/provider/naginator.rb +9 -1
- data/lib/puppet/provider/nameservice/directoryservice.rb +11 -8
- data/lib/puppet/provider/package/aptitude.rb +1 -0
- data/lib/puppet/rails/host.rb +7 -0
- data/lib/puppet/resource/catalog.rb +9 -3
- data/lib/puppet/transaction.rb +15 -26
- data/lib/puppet/transaction/report.rb +3 -3
- data/lib/puppet/type.rb +13 -24
- data/lib/puppet/util/queue.rb +1 -1
- data/lib/puppet/util/queue/stomp.rb +2 -2
- data/lib/puppet/util/settings/file_setting.rb +1 -0
- data/spec/integration/defaults_spec.rb +22 -0
- data/spec/integration/indirector/catalog/queue_spec.rb +2 -2
- data/spec/integration/type_spec.rb +11 -0
- data/spec/unit/application/agent_spec.rb +2 -2
- data/spec/unit/application/apply_spec.rb +62 -50
- data/spec/unit/configurer/fact_handler_spec.rb +43 -37
- data/spec/unit/configurer_spec.rb +404 -327
- data/spec/unit/file_serving/fileset_spec.rb +7 -0
- data/spec/unit/indirector/exec_spec.rb +4 -4
- data/spec/unit/indirector/node/exec_spec.rb +1 -1
- data/spec/unit/indirector/queue_spec.rb +4 -4
- data/spec/unit/node_spec.rb +1 -0
- data/spec/unit/parser/compiler_spec.rb +8 -46
- data/spec/unit/parser/resource_spec.rb +61 -3
- data/spec/unit/parser/scope_spec.rb +9 -3
- data/spec/unit/provider/nameservice/directoryservice_spec.rb +60 -0
- data/spec/unit/rails/host_spec.rb +8 -0
- data/spec/unit/resource/catalog_spec.rb +1 -1
- data/spec/unit/transaction/report_spec.rb +3 -3
- data/spec/unit/transaction_spec.rb +8 -2
- data/spec/unit/type_spec.rb +66 -0
- data/spec/unit/util/queue/stomp_spec.rb +10 -10
- data/spec/unit/util/settings/file_setting_spec.rb +4 -0
- metadata +1229 -1232
- data/README +0 -31
- data/lib/puppet/provider/nameservice/#directoryservice.rb# +0 -519
- data/lib/puppet/reference/#providers.rb# +0 -123
- data/spec/unit/indirector/certificate_status/#file_spec.rb# +0 -188
- data/spec/unit/resource/#type_collection_spec.rb# +0 -463
@@ -1,123 +0,0 @@
|
|
1
|
-
# This doesn't get stored in trac, since it changes every time.
|
2
|
-
providers = Puppet::Util::Reference.newreference :providers, :title => "Provider Suitability Report", :depth => 1, :dynamic => true, :doc => "Which providers are valid for this machine" do
|
3
|
-
types = []
|
4
|
-
newPuppet::Type.loadall
|
5
|
-
Puppet::Type.eachtype do |klass|
|
6
|
-
next unless klass.providers.length > 0
|
7
|
-
types << klass
|
8
|
-
end
|
9
|
-
types.sort! { |a,b| a.name.to_s <=> b.name.to_s }
|
10
|
-
|
11
|
-
command_line = Puppet::Util::CommandLine.new
|
12
|
-
types.reject! { |type| ! command_line.args.include?(type.name.to_s) } unless command_line.args.empty?
|
13
|
-
|
14
|
-
ret = "Details about this host:\n\n"
|
15
|
-
|
16
|
-
# Throw some facts in there, so we know where the report is from.
|
17
|
-
["Ruby Version", "Puppet Version", "Operating System", "Operating System Release"].each do |label|
|
18
|
-
name = label.gsub(/\s+/, '')
|
19
|
-
value = Facter.value(name)
|
20
|
-
ret += option(label, value)
|
21
|
-
end
|
22
|
-
ret += "\n"
|
23
|
-
|
24
|
-
count = 1
|
25
|
-
|
26
|
-
# Produce output for each type.
|
27
|
-
types.each do |type|
|
28
|
-
features = type.features
|
29
|
-
ret += "\n" # add a trailing newline
|
30
|
-
|
31
|
-
# Now build up a table of provider suitability.
|
32
|
-
headers = %w{Provider Suitable?} + features.collect { |f| f.to_s }.sort
|
33
|
-
|
34
|
-
table_data = {}
|
35
|
-
|
36
|
-
functional = false
|
37
|
-
notes = []
|
38
|
-
begin
|
39
|
-
default = type.defaultprovider.name
|
40
|
-
rescue Puppet::DevError
|
41
|
-
default = "none"
|
42
|
-
end
|
43
|
-
type.providers.sort { |a,b| a.to_s <=> b.to_s }.each do |pname|
|
44
|
-
data = []
|
45
|
-
table_data[pname] = data
|
46
|
-
provider = type.provider(pname)
|
47
|
-
|
48
|
-
# Add the suitability note
|
49
|
-
if missing = provider.suitable?(false) and missing.empty?
|
50
|
-
data << "*X*"
|
51
|
-
suit = true
|
52
|
-
functional = true
|
53
|
-
else
|
54
|
-
data << "[#{count}]_" # A pointer to the appropriate footnote
|
55
|
-
suit = false
|
56
|
-
end
|
57
|
-
|
58
|
-
# Add a footnote with the details about why this provider is unsuitable, if that's the case
|
59
|
-
unless suit
|
60
|
-
details = ".. [#{count}]\n"
|
61
|
-
missing.each do |test, values|
|
62
|
-
case test
|
63
|
-
when :exists
|
64
|
-
details += " - Missing files #{values.join(", ")}\n"
|
65
|
-
when :variable
|
66
|
-
values.each do |name, facts|
|
67
|
-
if Puppet.settings.valid?(name)
|
68
|
-
details += " - Setting #{name} (currently #{Puppet.settings.value(name).inspect}) not in list #{facts.join(", ")}\n"
|
69
|
-
else
|
70
|
-
details += " - Fact #{name} (currently #{Facter.value(name).inspect}) not in list #{facts.join(", ")}\n"
|
71
|
-
end
|
72
|
-
end
|
73
|
-
when :true
|
74
|
-
details += " - Got #{values} true tests that should have been false\n"
|
75
|
-
when :false
|
76
|
-
details += " - Got #{values} false tests that should have been true\n"
|
77
|
-
when :feature
|
78
|
-
details += " - Missing features #{values.collect { |f| f.to_s }.join(",")}\n"
|
79
|
-
end
|
80
|
-
end
|
81
|
-
notes << details
|
82
|
-
|
83
|
-
count += 1
|
84
|
-
end
|
85
|
-
|
86
|
-
# Add a note for every feature
|
87
|
-
features.each do |feature|
|
88
|
-
if provider.features.include?(feature)
|
89
|
-
data << "*X*"
|
90
|
-
else
|
91
|
-
data << ""
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
ret += h(type.name.to_s + "_", 2)
|
97
|
-
|
98
|
-
ret += "[#{type.name}](#{"http://docs.puppetlabs.com/references/stable/type.html##{type.name}"})\n\n"
|
99
|
-
ret += option("Default provider", default)
|
100
|
-
ret += doctable(headers, table_data)
|
101
|
-
|
102
|
-
notes.each do |note|
|
103
|
-
ret += note + "\n"
|
104
|
-
end
|
105
|
-
|
106
|
-
ret += "\n"
|
107
|
-
end
|
108
|
-
|
109
|
-
ret += "\n"
|
110
|
-
|
111
|
-
ret
|
112
|
-
end
|
113
|
-
providers.header = "
|
114
|
-
Puppet resource types are usually backed by multiple implementations called `providers`,
|
115
|
-
which handle variance between platforms and tools.
|
116
|
-
|
117
|
-
Different providers are suitable or unsuitable on different platforms based on things
|
118
|
-
like the presence of a given tool.
|
119
|
-
|
120
|
-
Here are all of the provider-backed types and their different providers. Any unmentioned
|
121
|
-
types do not use providers yet.
|
122
|
-
|
123
|
-
"
|
@@ -1,188 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require File.expand_path(File.dirname(__FILE__) + '/../../../spec_helper.rb')
|
4
|
-
require 'puppet/ssl/host'
|
5
|
-
require 'puppet/indirector/certificate_status'
|
6
|
-
require 'tempfile'
|
7
|
-
|
8
|
-
describe "Puppet::Indirector::CertificateStatus::File" do
|
9
|
-
include PuppetSpec::Files
|
10
|
-
|
11
|
-
before do
|
12
|
-
Puppet::SSL::CertificateAuthority.stubs(:ca?).returns true
|
13
|
-
@terminus = Puppet::SSL::Host.indirection.terminus(:file)
|
14
|
-
|
15
|
-
@tmpdir = tmpdir("certificate_status_ca_testing")
|
16
|
-
Puppet[:confdir] = @tmpdir
|
17
|
-
Puppet[:vardir] = @tmpdir
|
18
|
-
|
19
|
-
# localcacert is where each client stores the CA certificate
|
20
|
-
# cacert is where the master stores the CA certificate
|
21
|
-
# Since we need to play the role of both for testing we need them to be the same and exist
|
22
|
-
Puppet[:cacert] = Puppet[:localcacert]
|
23
|
-
end
|
24
|
-
|
25
|
-
def generate_csr(host)
|
26
|
-
host.generate_key
|
27
|
-
csr = Puppet::SSL::CertificateRequest.new(host.name)
|
28
|
-
csr.generate(host.key.content)
|
29
|
-
Puppet::SSL::CertificateRequest.indirection.save(csr)
|
30
|
-
end
|
31
|
-
|
32
|
-
def sign_csr(host)
|
33
|
-
host.desired_state = "signed"
|
34
|
-
@terminus.save(Puppet::Indirector::Request.new(:certificate_status, :save, host.name, host))
|
35
|
-
end
|
36
|
-
|
37
|
-
def generate_signed_cert(host)
|
38
|
-
generate_csr(host)
|
39
|
-
sign_csr(host)
|
40
|
-
|
41
|
-
@terminus.find(Puppet::Indirector::Request.new(:certificate_status, :find, host.name, host))
|
42
|
-
end
|
43
|
-
|
44
|
-
def generate_revoked_cert(host)
|
45
|
-
generate_signed_cert(host)
|
46
|
-
|
47
|
-
host.desired_state = "revoked"
|
48
|
-
|
49
|
-
@terminus.save(Puppet::Indirector::Request.new(:certificate_status, :save, host.name, host))
|
50
|
-
end
|
51
|
-
|
52
|
-
it "should be a terminus on SSL::Host" do
|
53
|
-
@terminus.should be_instance_of(Puppet::Indirector::CertificateStatus::File)
|
54
|
-
end
|
55
|
-
|
56
|
-
it "should create a CA instance if none is present" do
|
57
|
-
@terminus.ca.should be_instance_of(Puppet::SSL::CertificateAuthority)
|
58
|
-
end
|
59
|
-
|
60
|
-
describe "when creating the CA" do
|
61
|
-
it "should fail if it is not a valid CA" do
|
62
|
-
Puppet::SSL::CertificateAuthority.expects(:ca?).returns false
|
63
|
-
lambda { @terminus.ca }.should raise_error(ArgumentError, "This process is not configured as a certificate authority")
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
it "should be indirected with the name 'certificate_status'" do
|
68
|
-
Puppet::SSL::Host.indirection.name.should == :certificate_status
|
69
|
-
end
|
70
|
-
|
71
|
-
describe "when finding" do
|
72
|
-
before do
|
73
|
-
@host = Puppet::SSL::Host.new("foo")
|
74
|
-
Puppet.settings.use(:main)
|
75
|
-
end
|
76
|
-
|
77
|
-
it "should return the Puppet::SSL::Host when a CSR exists for the host" do
|
78
|
-
generate_csr(@host)
|
79
|
-
request = Puppet::Indirector::Request.new(:certificate_status, :find, "foo", @host)
|
80
|
-
|
81
|
-
retrieved_host = @terminus.find(request)
|
82
|
-
|
83
|
-
retrieved_host.name.should == @host.name
|
84
|
-
retrieved_host.certificate_request.content.to_s.chomp.should == @host.certificate_request.content.to_s.chomp
|
85
|
-
end
|
86
|
-
|
87
|
-
it "should return the Puppet::SSL::Host when a public key exist for the host" do
|
88
|
-
generate_signed_cert(@host)
|
89
|
-
request = Puppet::Indirector::Request.new(:certificate_status, :find, "foo", @host)
|
90
|
-
|
91
|
-
retrieved_host = @terminus.find(request)
|
92
|
-
|
93
|
-
retrieved_host.name.should == @host.name
|
94
|
-
retrieved_host.certificate.content.to_s.chomp.should == @host.certificate.content.to_s.chomp
|
95
|
-
end
|
96
|
-
|
97
|
-
it "should return nil when neither a CSR nor public key exist for the host" do
|
98
|
-
request = Puppet::Indirector::Request.new(:certificate_status, :find, "foo", @host)
|
99
|
-
@terminus.find(request).should == nil
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
describe "when saving" do
|
104
|
-
before do
|
105
|
-
@host = Puppet::SSL::Host.new("foobar")
|
106
|
-
Puppet.settings.use(:main)
|
107
|
-
end
|
108
|
-
|
109
|
-
describe "when signing a cert" do
|
110
|
-
before do
|
111
|
-
@host.desired_state = "signed"
|
112
|
-
@request = Puppet::Indirector::Request.new(:certificate_status, :save, "foobar", @host)
|
113
|
-
end
|
114
|
-
|
115
|
-
it "should fail if no CSR is on disk" do
|
116
|
-
lambda { @terminus.save(@request) }.should raise_error(Puppet::Error, /certificate request/)
|
117
|
-
end
|
118
|
-
|
119
|
-
it "should sign the on-disk CSR when it is present" do
|
120
|
-
signed_host = generate_signed_cert(@host)
|
121
|
-
|
122
|
-
signed_host.state.should == "signed"
|
123
|
-
Puppet::SSL::Certificate.indirection.find("foobar").should be_instance_of(Puppet::SSL::Certificate)
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
describe "when revoking a cert" do
|
128
|
-
before do
|
129
|
-
@request = Puppet::Indirector::Request.new(:certificate_status, :save, "foobar", @host)
|
130
|
-
end
|
131
|
-
|
132
|
-
it "should fail if no certificate is on disk" do
|
133
|
-
@host.desired_state = "revoked"
|
134
|
-
lambda { @terminus.save(@request) }.should raise_error(Puppet::Error, /Cannot revoke/)
|
135
|
-
end
|
136
|
-
|
137
|
-
it "should revoke the certificate when it is present" do
|
138
|
-
generate_revoked_cert(@host)
|
139
|
-
|
140
|
-
@host.state.should == 'revoked'
|
141
|
-
end
|
142
|
-
end
|
143
|
-
end
|
144
|
-
|
145
|
-
describe "when deleting" do
|
146
|
-
before do
|
147
|
-
Puppet.settings.use(:main)
|
148
|
-
end
|
149
|
-
|
150
|
-
it "should not delete anything if no certificate, request, or key is on disk" do
|
151
|
-
host = Puppet::SSL::Host.new("clean_me")
|
152
|
-
request = Puppet::Indirector::Request.new(:certificate_status, :delete, "clean_me", host)
|
153
|
-
@terminus.destroy(request).should == "Nothing was deleted"
|
154
|
-
end
|
155
|
-
|
156
|
-
it "should clean certs, cert requests, keys" do
|
157
|
-
signed_host = Puppet::SSL::Host.new("clean_signed_cert")
|
158
|
-
generate_signed_cert(signed_host)
|
159
|
-
signed_request = Puppet::Indirector::Request.new(:certificate_status, :delete, "clean_signed_cert", signed_host)
|
160
|
-
@terminus.destroy(signed_request).should == "Deleted for host clean_signed_cert: Puppet::SSL::Certificate, Puppet::SSL::Key"
|
161
|
-
|
162
|
-
requested_host = Puppet::SSL::Host.new("clean_csr")
|
163
|
-
generate_csr(requested_host)
|
164
|
-
csr_request = Puppet::Indirector::Request.new(:certificate_status, :delete, "clean_csr", requested_host)
|
165
|
-
@terminus.destroy(csr_request).should == "Deleted for 'host clean_signed_cert': Puppet::SSL::CertificateRequest, Puppet::SSL::Key"
|
166
|
-
end
|
167
|
-
end
|
168
|
-
|
169
|
-
describe "when searching" do
|
170
|
-
it "should return a list of all hosts with certificate requests, signed certs, or revoked certs" do
|
171
|
-
Puppet.settings.use(:main)
|
172
|
-
|
173
|
-
signed_host = Puppet::SSL::Host.new("signed_host")
|
174
|
-
generate_signed_cert(signed_host)
|
175
|
-
|
176
|
-
requested_host = Puppet::SSL::Host.new("requested_host")
|
177
|
-
generate_csr(requested_host)
|
178
|
-
|
179
|
-
revoked_host = Puppet::SSL::Host.new("revoked_host")
|
180
|
-
generate_revoked_cert(revoked_host)
|
181
|
-
|
182
|
-
retrieved_hosts = @terminus.search(Puppet::Indirector::Request.new(:certificate_status, :search, "all", signed_host))
|
183
|
-
|
184
|
-
results = retrieved_hosts.map {|h| [h.name, h.state]}.sort{ |h,i| h[0] <=> i[0] }
|
185
|
-
results.should == [["ca","signed"],["requested_host","requested"],["revoked_host","revoked"],["signed_host","signed"]]
|
186
|
-
end
|
187
|
-
end
|
188
|
-
end
|
@@ -1,463 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require File.dirname(__FILE__) + '/../../spec_helper'
|
4
|
-
|
5
|
-
require 'puppet/resource/type_collection'
|
6
|
-
require 'puppet/resource/type'
|
7
|
-
|
8
|
-
describe Puppet::Resource::TypeCollection do
|
9
|
-
include PuppetSpec::Files
|
10
|
-
before do
|
11
|
-
@instance = Puppet::Resource::Type.new(:hostclass, "foo")
|
12
|
-
@code = Puppet::Resource::TypeCollection.new("env")
|
13
|
-
end
|
14
|
-
|
15
|
-
it "should require an environment at initialization" do
|
16
|
-
env = Puppet::Node::Environment.new("testing")
|
17
|
-
Puppet::Resource::TypeCollection.new(env).environment.should equal(env)
|
18
|
-
end
|
19
|
-
|
20
|
-
it "should convert the environment into an environment instance if a string is provided" do
|
21
|
-
env = Puppet::Node::Environment.new("testing")
|
22
|
-
Puppet::Resource::TypeCollection.new("testing").environment.should equal(env)
|
23
|
-
end
|
24
|
-
|
25
|
-
it "should create a 'loader' at initialization" do
|
26
|
-
Puppet::Resource::TypeCollection.new("testing").loader.should be_instance_of(Puppet::Parser::TypeLoader)
|
27
|
-
end
|
28
|
-
|
29
|
-
it "should be able to add a resource type" do
|
30
|
-
Puppet::Resource::TypeCollection.new("env").should respond_to(:add)
|
31
|
-
end
|
32
|
-
|
33
|
-
it "should consider '<<' to be an alias to 'add' but should return self" do
|
34
|
-
loader = Puppet::Resource::TypeCollection.new("env")
|
35
|
-
loader.expects(:add).with "foo"
|
36
|
-
loader.expects(:add).with "bar"
|
37
|
-
loader << "foo" << "bar"
|
38
|
-
end
|
39
|
-
|
40
|
-
it "should set itself as the code collection for added resource types" do
|
41
|
-
loader = Puppet::Resource::TypeCollection.new("env")
|
42
|
-
|
43
|
-
node = Puppet::Resource::Type.new(:node, "foo")
|
44
|
-
|
45
|
-
@code.add(node)
|
46
|
-
@code.node("foo").should equal(node)
|
47
|
-
|
48
|
-
node.resource_type_collection.should equal(@code)
|
49
|
-
end
|
50
|
-
|
51
|
-
it "should store node resource types as nodes" do
|
52
|
-
node = Puppet::Resource::Type.new(:node, "foo")
|
53
|
-
|
54
|
-
@code.add(node)
|
55
|
-
@code.node("foo").should equal(node)
|
56
|
-
end
|
57
|
-
|
58
|
-
it "should store hostclasses as hostclasses" do
|
59
|
-
klass = Puppet::Resource::Type.new(:hostclass, "foo")
|
60
|
-
|
61
|
-
@code.add(klass)
|
62
|
-
@code.hostclass("foo").should equal(klass)
|
63
|
-
end
|
64
|
-
|
65
|
-
it "should store definitions as definitions" do
|
66
|
-
define = Puppet::Resource::Type.new(:definition, "foo")
|
67
|
-
|
68
|
-
@code.add(define)
|
69
|
-
@code.definition("foo").should equal(define)
|
70
|
-
end
|
71
|
-
|
72
|
-
it "should merge new classes with existing classes of the same name" do
|
73
|
-
loader = Puppet::Resource::TypeCollection.new("env")
|
74
|
-
first = Puppet::Resource::Type.new(:hostclass, "foo")
|
75
|
-
second = Puppet::Resource::Type.new(:hostclass, "foo")
|
76
|
-
loader.add first
|
77
|
-
first.expects(:merge).with(second)
|
78
|
-
loader.add(second)
|
79
|
-
end
|
80
|
-
|
81
|
-
it "should remove all nodes, classes, and definitions when cleared" do
|
82
|
-
loader = Puppet::Resource::TypeCollection.new("env")
|
83
|
-
loader.add Puppet::Resource::Type.new(:hostclass, "class")
|
84
|
-
loader.add Puppet::Resource::Type.new(:definition, "define")
|
85
|
-
loader.add Puppet::Resource::Type.new(:node, "node")
|
86
|
-
|
87
|
-
loader.clear
|
88
|
-
loader.hostclass("class").should be_nil
|
89
|
-
loader.definition("define").should be_nil
|
90
|
-
loader.node("node").should be_nil
|
91
|
-
end
|
92
|
-
|
93
|
-
describe "when looking up names" do
|
94
|
-
before do
|
95
|
-
@type = Puppet::Resource::Type.new(:hostclass, "ns::klass")
|
96
|
-
end
|
97
|
-
|
98
|
-
it "should support looking up with multiple namespaces" do
|
99
|
-
@code.add @type
|
100
|
-
@code.find_hostclass(%w{boo baz ns}, "klass").should equal(@type)
|
101
|
-
end
|
102
|
-
|
103
|
-
it "should not attempt to import anything when the type is already defined" do
|
104
|
-
@code.add @type
|
105
|
-
@code.loader.expects(:import).never
|
106
|
-
@code.find_hostclass(%w{ns}, "klass").should equal(@type)
|
107
|
-
end
|
108
|
-
|
109
|
-
describe "that need to be loaded" do
|
110
|
-
it "should use the loader to load the files" do
|
111
|
-
@code.loader.expects(:load_until).with(["ns"], "klass")
|
112
|
-
@code.find_or_load(["ns"], "klass", :hostclass)
|
113
|
-
end
|
114
|
-
|
115
|
-
it "should downcase the name and downcase and array-fy the namespaces before passing to the loader" do
|
116
|
-
@code.loader.expects(:load_until).with(["ns"], "klass")
|
117
|
-
@code.find_or_load("Ns", "Klass", :hostclass)
|
118
|
-
end
|
119
|
-
|
120
|
-
it "should attempt to find the type when the loader yields" do
|
121
|
-
@code.loader.expects(:load_until).yields
|
122
|
-
@code.expects(:find).with(["ns"], "klass", :hostclass).times(2).returns(false).then.returns(true)
|
123
|
-
@code.find_or_load("ns", "klass", :hostclass)
|
124
|
-
end
|
125
|
-
|
126
|
-
it "should return the result of 'load_until'" do
|
127
|
-
@code.loader.expects(:load_until).returns "foo"
|
128
|
-
@code.find_or_load("Ns", "Klass", :hostclass).should == "foo"
|
129
|
-
end
|
130
|
-
|
131
|
-
it "should return nil if the name isn't found" do
|
132
|
-
@code.stubs(:load_until).returns(nil)
|
133
|
-
@code.find_or_load("Ns", "Klass", :hostclass).should be_nil
|
134
|
-
end
|
135
|
-
end
|
136
|
-
end
|
137
|
-
|
138
|
-
%w{hostclass node definition}.each do |data|
|
139
|
-
before do
|
140
|
-
@instance = Puppet::Resource::Type.new(data, "foo")
|
141
|
-
end
|
142
|
-
|
143
|
-
it "should have a method for adding a #{data}" do
|
144
|
-
Puppet::Resource::TypeCollection.new("env").should respond_to("add_#{data}")
|
145
|
-
end
|
146
|
-
|
147
|
-
it "should use the name of the instance to add it" do
|
148
|
-
loader = Puppet::Resource::TypeCollection.new("env")
|
149
|
-
loader.send("add_#{data}", @instance)
|
150
|
-
loader.send(data, @instance.name).should equal(@instance)
|
151
|
-
end
|
152
|
-
|
153
|
-
unless data == "hostclass"
|
154
|
-
it "should fail to add a #{data} when one already exists" do
|
155
|
-
loader = Puppet::Resource::TypeCollection.new("env")
|
156
|
-
loader.add @instance
|
157
|
-
lambda { loader.add(@instance) }.should raise_error(Puppet::ParseError)
|
158
|
-
end
|
159
|
-
end
|
160
|
-
|
161
|
-
it "should return the added #{data}" do
|
162
|
-
loader = Puppet::Resource::TypeCollection.new("env")
|
163
|
-
|
164
|
-
loader.add(@instance).should equal(@instance)
|
165
|
-
end
|
166
|
-
|
167
|
-
it "should be able to retrieve #{data} by name" do
|
168
|
-
loader = Puppet::Resource::TypeCollection.new("env")
|
169
|
-
instance = Puppet::Resource::Type.new(data, "bar")
|
170
|
-
loader.add instance
|
171
|
-
loader.send(data, "bar").should equal(instance)
|
172
|
-
end
|
173
|
-
|
174
|
-
it "should retrieve #{data} insensitive to case" do
|
175
|
-
loader = Puppet::Resource::TypeCollection.new("env")
|
176
|
-
instance = Puppet::Resource::Type.new(data, "Bar")
|
177
|
-
loader.add instance
|
178
|
-
loader.send(data, "bAr").should equal(instance)
|
179
|
-
end
|
180
|
-
|
181
|
-
it "should return nil when asked for a #{data} that has not been added" do
|
182
|
-
Puppet::Resource::TypeCollection.new("env").send(data, "foo").should be_nil
|
183
|
-
end
|
184
|
-
|
185
|
-
it "should be able to retrieve all #{data}s" do
|
186
|
-
plurals = { "hostclass" => "hostclasses", "node" => "nodes", "definition" => "definitions" }
|
187
|
-
loader = Puppet::Resource::TypeCollection.new("env")
|
188
|
-
instance = Puppet::Resource::Type.new(data, "foo")
|
189
|
-
loader.add instance
|
190
|
-
loader.send(plurals[data]).should == { "foo" => instance }
|
191
|
-
end
|
192
|
-
end
|
193
|
-
|
194
|
-
describe "when finding a qualified instance" do
|
195
|
-
it "should return any found instance if the instance name is fully qualified" do
|
196
|
-
loader = Puppet::Resource::TypeCollection.new("env")
|
197
|
-
instance = Puppet::Resource::Type.new(:hostclass, "foo::bar")
|
198
|
-
loader.add instance
|
199
|
-
loader.find("namespace", "::foo::bar", :hostclass).should equal(instance)
|
200
|
-
end
|
201
|
-
|
202
|
-
it "should return nil if the instance name is fully qualified and no such instance exists" do
|
203
|
-
loader = Puppet::Resource::TypeCollection.new("env")
|
204
|
-
loader.find("namespace", "::foo::bar", :hostclass).should be_nil
|
205
|
-
end
|
206
|
-
|
207
|
-
it "should be able to find classes in the base namespace" do
|
208
|
-
loader = Puppet::Resource::TypeCollection.new("env")
|
209
|
-
instance = Puppet::Resource::Type.new(:hostclass, "foo")
|
210
|
-
loader.add instance
|
211
|
-
loader.find("", "foo", :hostclass).should equal(instance)
|
212
|
-
end
|
213
|
-
|
214
|
-
it "should return the partially qualified object if it exists in a provided namespace" do
|
215
|
-
loader = Puppet::Resource::TypeCollection.new("env")
|
216
|
-
instance = Puppet::Resource::Type.new(:hostclass, "foo::bar::baz")
|
217
|
-
loader.add instance
|
218
|
-
loader.find("foo", "bar::baz", :hostclass).should equal(instance)
|
219
|
-
end
|
220
|
-
|
221
|
-
it "should be able to find partially qualified objects in any of the provided namespaces" do
|
222
|
-
loader = Puppet::Resource::TypeCollection.new("env")
|
223
|
-
instance = Puppet::Resource::Type.new(:hostclass, "foo::bar::baz")
|
224
|
-
loader.add instance
|
225
|
-
loader.find(["nons", "foo", "otherns"], "bar::baz", :hostclass).should equal(instance)
|
226
|
-
end
|
227
|
-
|
228
|
-
it "should return the unqualified object if it exists in a provided namespace" do
|
229
|
-
loader = Puppet::Resource::TypeCollection.new("env")
|
230
|
-
instance = Puppet::Resource::Type.new(:hostclass, "foo::bar")
|
231
|
-
loader.add instance
|
232
|
-
loader.find("foo", "bar", :hostclass).should equal(instance)
|
233
|
-
end
|
234
|
-
|
235
|
-
it "should return the unqualified object if it exists in the parent namespace" do
|
236
|
-
loader = Puppet::Resource::TypeCollection.new("env")
|
237
|
-
instance = Puppet::Resource::Type.new(:hostclass, "foo::bar")
|
238
|
-
loader.add instance
|
239
|
-
loader.find("foo::bar::baz", "bar", :hostclass).should equal(instance)
|
240
|
-
end
|
241
|
-
|
242
|
-
it "should should return the partially qualified object if it exists in the parent namespace" do
|
243
|
-
loader = Puppet::Resource::TypeCollection.new("env")
|
244
|
-
instance = Puppet::Resource::Type.new(:hostclass, "foo::bar::baz")
|
245
|
-
loader.add instance
|
246
|
-
loader.find("foo::bar", "bar::baz", :hostclass).should equal(instance)
|
247
|
-
end
|
248
|
-
|
249
|
-
it "should return the qualified object if it exists in the root namespace" do
|
250
|
-
loader = Puppet::Resource::TypeCollection.new("env")
|
251
|
-
instance = Puppet::Resource::Type.new(:hostclass, "foo::bar::baz")
|
252
|
-
loader.add instance
|
253
|
-
loader.find("foo::bar", "foo::bar::baz", :hostclass).should equal(instance)
|
254
|
-
end
|
255
|
-
|
256
|
-
it "should return nil if the object cannot be found" do
|
257
|
-
loader = Puppet::Resource::TypeCollection.new("env")
|
258
|
-
instance = Puppet::Resource::Type.new(:hostclass, "foo::bar::baz")
|
259
|
-
loader.add instance
|
260
|
-
loader.find("foo::bar", "eh", :hostclass).should be_nil
|
261
|
-
end
|
262
|
-
|
263
|
-
describe "when topscope has a class that has the same name as a local class" do
|
264
|
-
before do
|
265
|
-
@loader = Puppet::Resource::TypeCollection.new("env")
|
266
|
-
[ "foo::bar", "bar" ].each do |name|
|
267
|
-
@loader.add Puppet::Resource::Type.new(:hostclass, name)
|
268
|
-
end
|
269
|
-
end
|
270
|
-
|
271
|
-
it "should favor the local class, if the name is unqualified" do
|
272
|
-
@loader.find("foo", "bar", :hostclass).name.should == 'foo::bar'
|
273
|
-
end
|
274
|
-
|
275
|
-
it "should only look in the topclass, if the name is qualified" do
|
276
|
-
@loader.find("foo", "::bar", :hostclass).name.should == 'bar'
|
277
|
-
end
|
278
|
-
|
279
|
-
end
|
280
|
-
|
281
|
-
it "should not look in the local scope for classes when the name is qualified" do
|
282
|
-
@loader = Puppet::Resource::TypeCollection.new("env")
|
283
|
-
@loader.add Puppet::Resource::Type.new(:hostclass, "foo::bar")
|
284
|
-
|
285
|
-
@loader.find("foo", "::bar", :hostclass).should == nil
|
286
|
-
end
|
287
|
-
|
288
|
-
end
|
289
|
-
|
290
|
-
it "should use the generic 'find' method with an empty namespace to find nodes" do
|
291
|
-
loader = Puppet::Resource::TypeCollection.new("env")
|
292
|
-
loader.expects(:find).with("", "bar", :node)
|
293
|
-
loader.find_node(stub("ignored"), "bar")
|
294
|
-
end
|
295
|
-
|
296
|
-
it "should use the 'find_or_load' method to find hostclasses" do
|
297
|
-
loader = Puppet::Resource::TypeCollection.new("env")
|
298
|
-
loader.expects(:find_or_load).with("foo", "bar", :hostclass)
|
299
|
-
loader.find_hostclass("foo", "bar")
|
300
|
-
end
|
301
|
-
|
302
|
-
it "should use the 'find_or_load' method to find definitions" do
|
303
|
-
loader = Puppet::Resource::TypeCollection.new("env")
|
304
|
-
loader.expects(:find_or_load).with("foo", "bar", :definition)
|
305
|
-
loader.find_definition("foo", "bar")
|
306
|
-
end
|
307
|
-
|
308
|
-
it "should indicate whether any nodes are defined" do
|
309
|
-
loader = Puppet::Resource::TypeCollection.new("env")
|
310
|
-
loader.add_node(Puppet::Resource::Type.new(:node, "foo"))
|
311
|
-
loader.should be_nodes
|
312
|
-
end
|
313
|
-
|
314
|
-
it "should indicate whether no nodes are defined" do
|
315
|
-
Puppet::Resource::TypeCollection.new("env").should_not be_nodes
|
316
|
-
end
|
317
|
-
|
318
|
-
describe "when finding nodes" do
|
319
|
-
before :each do
|
320
|
-
@loader = Puppet::Resource::TypeCollection.new("env")
|
321
|
-
end
|
322
|
-
|
323
|
-
it "should return any node whose name exactly matches the provided node name" do
|
324
|
-
node = Puppet::Resource::Type.new(:node, "foo")
|
325
|
-
@loader << node
|
326
|
-
|
327
|
-
@loader.node("foo").should equal(node)
|
328
|
-
end
|
329
|
-
|
330
|
-
it "should return the first regex node whose regex matches the provided node name" do
|
331
|
-
node1 = Puppet::Resource::Type.new(:node, /\w/)
|
332
|
-
node2 = Puppet::Resource::Type.new(:node, /\d/)
|
333
|
-
@loader << node1 << node2
|
334
|
-
|
335
|
-
@loader.node("foo10").should equal(node1)
|
336
|
-
end
|
337
|
-
|
338
|
-
it "should preferentially return a node whose name is string-equal over returning a node whose regex matches a provided name" do
|
339
|
-
node1 = Puppet::Resource::Type.new(:node, /\w/)
|
340
|
-
node2 = Puppet::Resource::Type.new(:node, "foo")
|
341
|
-
@loader << node1 << node2
|
342
|
-
|
343
|
-
@loader.node("foo").should equal(node2)
|
344
|
-
end
|
345
|
-
end
|
346
|
-
|
347
|
-
describe "when managing files" do
|
348
|
-
before do
|
349
|
-
@loader = Puppet::Resource::TypeCollection.new("env")
|
350
|
-
Puppet::Util::LoadedFile.stubs(:new).returns stub("watched_file")
|
351
|
-
end
|
352
|
-
|
353
|
-
it "should have a method for specifying a file should be watched" do
|
354
|
-
@loader.should respond_to(:watch_file)
|
355
|
-
end
|
356
|
-
|
357
|
-
it "should have a method for determining if a file is being watched" do
|
358
|
-
@loader.watch_file("/foo/bar")
|
359
|
-
@loader.should be_watching_file("/foo/bar")
|
360
|
-
end
|
361
|
-
|
362
|
-
it "should use LoadedFile to watch files" do
|
363
|
-
Puppet::Util::LoadedFile.expects(:new).with("/foo/bar").returns stub("watched_file")
|
364
|
-
@loader.watch_file("/foo/bar")
|
365
|
-
end
|
366
|
-
|
367
|
-
it "should be considered stale if any files have changed" do
|
368
|
-
file1 = stub 'file1', :changed? => false
|
369
|
-
file2 = stub 'file2', :changed? => true
|
370
|
-
Puppet::Util::LoadedFile.expects(:new).times(2).returns(file1).then.returns(file2)
|
371
|
-
@loader.watch_file("/foo/bar")
|
372
|
-
@loader.watch_file("/other/bar")
|
373
|
-
|
374
|
-
@loader.should be_stale
|
375
|
-
end
|
376
|
-
|
377
|
-
it "should not be considered stable if no files have changed" do
|
378
|
-
file1 = stub 'file1', :changed? => false
|
379
|
-
file2 = stub 'file2', :changed? => false
|
380
|
-
Puppet::Util::LoadedFile.expects(:new).times(2).returns(file1).then.returns(file2)
|
381
|
-
@loader.watch_file("/foo/bar")
|
382
|
-
@loader.watch_file("/other/bar")
|
383
|
-
|
384
|
-
@loader.should_not be_stale
|
385
|
-
end
|
386
|
-
end
|
387
|
-
|
388
|
-
describe "when performing initial import" do
|
389
|
-
before do
|
390
|
-
@parser = Puppet::Parser::Parser.new("test")
|
391
|
-
Puppet::Parser::Parser.stubs(:new).returns @parser
|
392
|
-
@code = Puppet::Resource::TypeCollection.new("env")
|
393
|
-
end
|
394
|
-
|
395
|
-
it "should set the parser's string to the 'code' setting and parse if code is available" do
|
396
|
-
Puppet.settings[:code] = "my code"
|
397
|
-
@parser.expects(:string=).with "my code"
|
398
|
-
@parser.expects(:parse)
|
399
|
-
@code.perform_initial_import
|
400
|
-
end
|
401
|
-
|
402
|
-
it "should set the parser's file to the 'manifest' setting and parse if no code is available and the manifest is available" do
|
403
|
-
filename = tmpfile('myfile')
|
404
|
-
File.open(filename, 'w'){|f| }
|
405
|
-
Puppet.settings[:manifest] = filename
|
406
|
-
@parser.expects(:file=).with filename
|
407
|
-
@parser.expects(:parse)
|
408
|
-
@code.perform_initial_import
|
409
|
-
end
|
410
|
-
|
411
|
-
it "should pass the manifest file to the parser even if it does not exist on disk" do
|
412
|
-
filename = tmpfile('myfile')
|
413
|
-
Puppet.settings[:code] = ""
|
414
|
-
Puppet.settings[:manifest] = filename
|
415
|
-
@parser.expects(:file=).with(filename).once
|
416
|
-
@parser.expects(:parse).once
|
417
|
-
@code.perform_initial_import
|
418
|
-
end
|
419
|
-
|
420
|
-
it "should fail helpfully if there is an error importing" do
|
421
|
-
File.stubs(:exist?).returns true
|
422
|
-
@parser.expects(:parse).raises ArgumentError
|
423
|
-
@parser.stubs(:file=)
|
424
|
-
lambda { @code.perform_initial_import }.should raise_error(Puppet::Error)
|
425
|
-
end
|
426
|
-
|
427
|
-
it "should mark the type collection as needing a reparse when there is an error parsing" do
|
428
|
-
@parser.expects(:parse).raises Puppet::ParseError.new("Syntax error at ...")
|
429
|
-
|
430
|
-
lambda { @code.perform_initial_import }.should raise_error(Puppet::Error, /Syntax error at .../)
|
431
|
-
@code.require_reparse?.should be_true
|
432
|
-
end
|
433
|
-
end
|
434
|
-
|
435
|
-
describe "when determining the configuration version" do
|
436
|
-
before do
|
437
|
-
@code = Puppet::Resource::TypeCollection.new("env")
|
438
|
-
end
|
439
|
-
|
440
|
-
it "should default to the current time" do
|
441
|
-
time = Time.now
|
442
|
-
|
443
|
-
Time.stubs(:now).returns time
|
444
|
-
@code.version.should == time.to_i
|
445
|
-
end
|
446
|
-
|
447
|
-
it "should use the output of the environment's config_version setting if one is provided" do
|
448
|
-
@code.environment.stubs(:[]).with(:config_version).returns("/my/foo")
|
449
|
-
|
450
|
-
Puppet::Util.expects(:execute).with(["/my/foo"]).returns "output\n"
|
451
|
-
@code.version.should == "output"
|
452
|
-
end
|
453
|
-
|
454
|
-
it "should raise a puppet parser error if executing config_version fails" do
|
455
|
-
@code.environment.stubs(:[]).with(:config_version).returns("test")
|
456
|
-
Puppet::Util.expects(:execute).raises(Puppet::ExecutionFailure.new("msg"))
|
457
|
-
|
458
|
-
lambda { @code.version }.should raise_error(Puppet::ParseError)
|
459
|
-
end
|
460
|
-
|
461
|
-
end
|
462
|
-
|
463
|
-
end
|