puppet 5.3.5 → 5.3.6

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.

Files changed (71) hide show
  1. data/lib/puppet/application/cert.rb +3 -1
  2. data/lib/puppet/application/device.rb +99 -12
  3. data/lib/puppet/application/lookup.rb +11 -1
  4. data/lib/puppet/context.rb +1 -1
  5. data/lib/puppet/functions/map.rb +1 -1
  6. data/lib/puppet/indirector/request.rb +6 -10
  7. data/lib/puppet/indirector/rest.rb +9 -9
  8. data/lib/puppet/network/http/connection.rb +8 -0
  9. data/lib/puppet/parser/compiler.rb +7 -0
  10. data/lib/puppet/parser/functions/new.rb +31 -46
  11. data/lib/puppet/parser/functions/return.rb +22 -1
  12. data/lib/puppet/provider/group/windows_adsi.rb +4 -7
  13. data/lib/puppet/provider/service/systemd.rb +1 -1
  14. data/lib/puppet/provider/user/aix.rb +1 -1
  15. data/lib/puppet/provider/user/windows_adsi.rb +1 -1
  16. data/lib/puppet/reference/configuration.rb +2 -0
  17. data/lib/puppet/resource/catalog.rb +1 -1
  18. data/lib/puppet/type/user.rb +34 -3
  19. data/lib/puppet/util/plist.rb +1 -1
  20. data/lib/puppet/util/reference.rb +1 -8
  21. data/lib/puppet/util/windows/adsi.rb +15 -18
  22. data/lib/puppet/util/windows/principal.rb +7 -6
  23. data/lib/puppet/util/windows/sid.rb +60 -7
  24. data/lib/puppet/version.rb +1 -1
  25. data/locales/ja/puppet.po +163 -140
  26. data/locales/puppet.pot +94 -76
  27. data/man/man5/puppet.conf.5 +91 -16
  28. data/man/man8/puppet-agent.8 +6 -2
  29. data/man/man8/puppet-apply.8 +2 -2
  30. data/man/man8/puppet-ca.8 +1 -1
  31. data/man/man8/puppet-catalog.8 +1 -1
  32. data/man/man8/puppet-cert.8 +1 -1
  33. data/man/man8/puppet-certificate.8 +1 -1
  34. data/man/man8/puppet-certificate_request.8 +1 -1
  35. data/man/man8/puppet-certificate_revocation_list.8 +1 -1
  36. data/man/man8/puppet-config.8 +1 -1
  37. data/man/man8/puppet-describe.8 +1 -1
  38. data/man/man8/puppet-device.8 +33 -11
  39. data/man/man8/puppet-doc.8 +1 -1
  40. data/man/man8/puppet-epp.8 +1 -1
  41. data/man/man8/puppet-facts.8 +1 -1
  42. data/man/man8/puppet-filebucket.8 +22 -4
  43. data/man/man8/puppet-generate.8 +1 -1
  44. data/man/man8/puppet-help.8 +1 -1
  45. data/man/man8/puppet-key.8 +1 -1
  46. data/man/man8/puppet-lookup.8 +1 -1
  47. data/man/man8/puppet-man.8 +1 -1
  48. data/man/man8/puppet-master.8 +1 -1
  49. data/man/man8/puppet-module.8 +11 -2
  50. data/man/man8/puppet-node.8 +1 -1
  51. data/man/man8/puppet-parser.8 +1 -1
  52. data/man/man8/puppet-plugin.8 +1 -1
  53. data/man/man8/puppet-report.8 +1 -1
  54. data/man/man8/puppet-resource.8 +1 -1
  55. data/man/man8/puppet-status.8 +1 -1
  56. data/man/man8/puppet.8 +2 -2
  57. data/spec/integration/application/lookup_spec.rb +21 -0
  58. data/spec/integration/util/windows/adsi_spec.rb +86 -1
  59. data/spec/integration/util/windows/principal_spec.rb +10 -1
  60. data/spec/unit/application/cert_spec.rb +17 -5
  61. data/spec/unit/application/device_spec.rb +96 -2
  62. data/spec/unit/indirector/rest_spec.rb +43 -0
  63. data/spec/unit/parser/compiler_spec.rb +8 -0
  64. data/spec/unit/provider/group/windows_adsi_spec.rb +79 -22
  65. data/spec/unit/provider/service/systemd_spec.rb +1 -1
  66. data/spec/unit/provider/user/windows_adsi_spec.rb +4 -4
  67. data/spec/unit/util/plist_spec.rb +3 -3
  68. data/spec/unit/util/windows/adsi_spec.rb +31 -27
  69. data/spec/unit/util/windows/sid_spec.rb +86 -15
  70. data/tasks/manpages.rake +1 -1
  71. metadata +3415 -3415
@@ -1,7 +1,7 @@
1
1
  .\" generated with Ronn/v0.7.3
2
2
  .\" http://github.com/rtomayko/ronn/tree/0.7.3
3
3
  .
4
- .TH "PUPPET\-STATUS" "8" "June 2017" "Puppet Labs, LLC" "Puppet manual"
4
+ .TH "PUPPET\-STATUS" "8" "April 2018" "Puppet, Inc." "Puppet manual"
5
5
  .
6
6
  .SH "NAME"
7
7
  \fBpuppet\-status\fR \- View puppet server status\.
@@ -1,7 +1,7 @@
1
1
  .\" generated with Ronn/v0.7.3
2
2
  .\" http://github.com/rtomayko/ronn/tree/0.7.3
3
3
  .
4
- .TH "PUPPET" "8" "June 2017" "Puppet Labs, LLC" "Puppet manual"
4
+ .TH "PUPPET" "8" "April 2018" "Puppet, Inc." "Puppet manual"
5
5
  .
6
6
  .SH "NAME"
7
7
  \fBpuppet\fR
@@ -16,4 +16,4 @@ Available subcommands:
16
16
  agent The puppet agent daemon apply Apply Puppet manifests locally ca Local Puppet Certificate Authority management\. (Deprecated) catalog Compile, save, view, and convert catalogs\. cert Manage certificates and requests certificate Provide access to the CA for certificate management\. certificate_request Manage certificate requests\. (Deprecated) certificate_revocation_list Manage the list of revoked certificates\. (Deprecated) config Interact with Puppet\'s settings\. describe Display help about resource types device Manage remote network devices doc Generate Puppet references epp Interact directly with the EPP template parser/renderer\. facts Retrieve and store facts\. filebucket Store and retrieve files in a filebucket generate Generates Puppet code from Ruby definitions\. help Display Puppet help\. key Create, save, and remove certificate keys\. (Deprecated) lookup Interactive Hiera lookup man Display Puppet manual pages\. master The puppet master daemon module Creates, installs and searches for modules on the Puppet Forge\. node View and manage node definitions\. parser Interact directly with the parser\. plugin Interact with the Puppet plugin system\. report Create, display, and submit reports\. resource The resource abstraction layer shell status View puppet server status\. (Deprecated)
17
17
  .
18
18
  .P
19
- See \'puppet help \fIsubcommand\fR \fIaction\fR\' for help on a specific subcommand action\. See \'puppet help \fIsubcommand\fR\' for help on a specific subcommand\. Puppet v5\.0\.0
19
+ See \'puppet help \fIsubcommand\fR \fIaction\fR\' for help on a specific subcommand action\. See \'puppet help \fIsubcommand\fR\' for help on a specific subcommand\. Puppet v5\.3\.6
@@ -90,6 +90,27 @@ describe 'lookup' do
90
90
  expect(lookup('a')).to eql('value a')
91
91
  end
92
92
 
93
+ context 'uses node_terminus' do
94
+ require 'puppet/indirector/node/exec'
95
+ require 'puppet/indirector/node/plain'
96
+
97
+ let(:node) { Puppet::Node.new('testnode', :environment => env) }
98
+
99
+ it ':plain without --compile' do
100
+ Puppet.settings[:node_terminus] = 'exec'
101
+ Puppet::Node::Plain.any_instance.expects(:find).returns(node)
102
+ Puppet::Node::Exec.any_instance.expects(:find).never
103
+ expect(lookup('a')).to eql('value a')
104
+ end
105
+
106
+ it 'configured in Puppet settings with --compile' do
107
+ Puppet.settings[:node_terminus] = 'exec'
108
+ Puppet::Node::Plain.any_instance.expects(:find).never
109
+ Puppet::Node::Exec.any_instance.expects(:find).returns(node)
110
+ expect(lookup('a', :compile => true)).to eql('value a')
111
+ end
112
+ end
113
+
93
114
  context 'configured with the wrong environment' do
94
115
  let(:env) { Puppet::Node::Environment.create(env_name.to_sym, [File.join(populated_env_dir, env_name, 'modules')]) }
95
116
  it 'does not find data in non-existing environment' do
@@ -81,6 +81,91 @@ describe Puppet::Util::Windows::ADSI::Group,
81
81
  end
82
82
 
83
83
  describe '.members' do
84
+ it 'should return a list of members resolvable with Puppet::Util::Windows::ADSI::Group.name_sid_hash' do
85
+ temp_groupname = "g#{SecureRandom.uuid}"
86
+ temp_username = "u#{SecureRandom.uuid}"[0..12]
87
+
88
+ # select a virtual account that requires an authority to be able to resolve to SID
89
+ # the Dhcp service is chosen for no particular reason aside from it's a service available on all Windows versions
90
+ dhcp_virtualaccount = Puppet::Util::Windows::SID.name_to_principal('NT SERVICE\Dhcp')
91
+
92
+ # adding :SidTypeGroup as a group member will cause error in IAdsUser::Add
93
+ # adding :SidTypeDomain (such as S-1-5-80 / NT SERVICE or computer name) won't error
94
+ # but also won't be returned as a group member
95
+ # uncertain how to obtain :SidTypeComputer (perhaps AD? the local machine is :SidTypeDomain)
96
+ users = [
97
+ # Use sid_to_name to get localized names of SIDs - BUILTIN, SYSTEM, NT AUTHORITY, Everyone are all localized
98
+ # :SidTypeWellKnownGroup
99
+ # SYSTEM is prefixed with the NT Authority authority, resolveable with or without authority
100
+ { :sid => 'S-1-5-18', :name => Puppet::Util::Windows::SID.sid_to_name('S-1-5-18') },
101
+ # Everyone is not prefixed with an authority, resolveable with or without NT AUTHORITY authority
102
+ { :sid => 'S-1-1-0', :name => Puppet::Util::Windows::SID.sid_to_name('S-1-1-0') },
103
+ # Dhcp service account is prefixed with NT SERVICE authority, requires authority to resolve SID
104
+ # behavior is similar to IIS APPPOOL\DefaultAppPool
105
+ { :sid => dhcp_virtualaccount.sid, :name => dhcp_virtualaccount.domain_account },
106
+
107
+ # :SidTypeAlias with authority component
108
+ # Administrators group is prefixed with BUILTIN authority, can be resolved with or without authority
109
+ { :sid => 'S-1-5-32-544', :name => Puppet::Util::Windows::SID.sid_to_name('S-1-5-32-544') },
110
+ ]
111
+
112
+ begin
113
+ # :SidTypeUser as user on localhost, can be resolved with or without authority prefix
114
+ user = Puppet::Util::Windows::ADSI::User.create(temp_username)
115
+ user.commit()
116
+ users.push({ :sid => user.sid.sid, :name => Puppet::Util::Windows::ADSI.computer_name + '\\' + temp_username })
117
+
118
+ # create a test group and add above 5 members by SID
119
+ group = described_class.create(temp_groupname)
120
+ group.commit()
121
+ group.set_members(users.map { |u| u[:sid]} )
122
+
123
+ # most importantly make sure that all name are convertible to SIDs
124
+ expect { described_class.name_sid_hash(group.members) }.to_not raise_error
125
+
126
+ # also verify the names returned are as expected
127
+ expected_usernames = users.map { |u| u[:name] }
128
+ expect(group.members.map(&:domain_account)).to eq(expected_usernames)
129
+ ensure
130
+ described_class.delete(temp_groupname) if described_class.exists?(temp_groupname)
131
+ Puppet::Util::Windows::ADSI::User.delete(temp_username) if Puppet::Util::Windows::ADSI::User.exists?(temp_username)
132
+ end
133
+ end
134
+
135
+ it 'should return a list of Principal objects even with unresolvable SIDs' do
136
+ members = [
137
+ # NULL SID is not localized
138
+ stub('WIN32OLE', {
139
+ :objectSID => [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
140
+ :Name => 'NULL SID',
141
+ :ole_respond_to? => true,
142
+ }),
143
+ # unresolvable SID is a different story altogether
144
+ stub('WIN32OLE', {
145
+ # completely valid SID, but Name is just a stringified version
146
+ :objectSID => [1, 5, 0, 0, 0, 0, 0, 5, 21, 0, 0, 0, 5, 113, 65, 218, 15, 127, 9, 57, 219, 4, 84, 126, 88, 4, 0, 0],
147
+ :Name => 'S-1-5-21-3661721861-956923663-2119435483-1112',
148
+ :ole_respond_to? => true,
149
+ })
150
+ ]
151
+
152
+ admins_name = Puppet::Util::Windows::SID.sid_to_name('S-1-5-32-544')
153
+ admins = Puppet::Util::Windows::ADSI::Group.new(admins_name)
154
+
155
+ # touch the native_group member to have it lazily loaded, so COM objects can be stubbed
156
+ admins.native_group
157
+ admins.native_group.stubs(:Members).returns(members)
158
+
159
+ # well-known NULL SID
160
+ expect(admins.members[0].sid).to eq('S-1-0-0')
161
+ expect(admins.members[0].account_type).to eq(:SidTypeWellKnownGroup)
162
+
163
+ # unresolvable SID
164
+ expect(admins.members[1].sid).to eq('S-1-5-21-3661721861-956923663-2119435483-1112')
165
+ expect(admins.members[1].account).to eq('S-1-5-21-3661721861-956923663-2119435483-1112 (unresolvable)')
166
+ expect(admins.members[1].account_type).to eq(:SidTypeUnknown)
167
+ end
168
+
84
169
  it 'should return a list of members with UTF-8 names' do
85
170
  begin
86
171
  original_codepage = Encoding.default_external
@@ -88,7 +173,7 @@ describe Puppet::Util::Windows::ADSI::Group,
88
173
 
89
174
  # lookup by English name Administrators is not OK on localized Windows
90
175
  admins = Puppet::Util::Windows::ADSI::Group.new(administrators_principal.account)
91
- admins.members.each do |name|
176
+ admins.members.map(&:domain_account).each do |name|
92
177
  expect(name.encoding).to be(Encoding::UTF_8)
93
178
  end
94
179
  ensure
@@ -8,7 +8,7 @@ describe Puppet::Util::Windows::SID::Principal, :if => Puppet.features.microsoft
8
8
  let (:system_bytes) { [1, 1, 0, 0, 0, 0, 0, 5, 18, 0, 0, 0] }
9
9
  let (:null_sid_bytes) { bytes = [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] }
10
10
  let (:administrator_bytes) { [1, 2, 0, 0, 0, 0, 0, 5, 32, 0, 0, 0, 32, 2, 0, 0] }
11
- let (:computer_sid) { Puppet::Util::Windows::SID.name_to_sid_object(Puppet::Util::Windows::ADSI.computer_name) }
11
+ let (:computer_sid) { Puppet::Util::Windows::SID.name_to_principal(Puppet::Util::Windows::ADSI.computer_name) }
12
12
  # BUILTIN is localized on German Windows, but not French
13
13
  # looking this up like this dilutes the values of the tests as we're comparing two mechanisms
14
14
  # for returning the same values, rather than to a known good
@@ -23,6 +23,7 @@ describe Puppet::Util::Windows::SID::Principal, :if => Puppet.features.microsoft
23
23
  expect(principal.domain).to eq('')
24
24
  expect(principal.domain_account).to eq('NULL SID')
25
25
  expect(principal.account_type).to eq(:SidTypeWellKnownGroup)
26
+ expect(principal.to_s).to eq('NULL SID')
26
27
  end
27
28
 
28
29
  it "should create an instance from a well-known account prefixed with NT AUTHORITY" do
@@ -39,6 +40,7 @@ describe Puppet::Util::Windows::SID::Principal, :if => Puppet.features.microsoft
39
40
  expect(principal.account).to eq('SYSTEM')
40
41
  expect(principal.domain).to eq('NT AUTHORITY')
41
42
  expect(principal.domain_account).to eq('NT AUTHORITY\\SYSTEM')
43
+ expect(principal.to_s).to eq('NT AUTHORITY\\SYSTEM')
42
44
  end
43
45
 
44
46
  # Windows API LookupAccountSid behaves differently if current user is SYSTEM
@@ -87,6 +89,7 @@ describe Puppet::Util::Windows::SID::Principal, :if => Puppet.features.microsoft
87
89
  expect(principal.domain).to eq(domain)
88
90
  expect(principal.domain_account).to eq(qualified_name)
89
91
  expect(principal.account_type).to eq(:SidTypeAlias)
92
+ expect(principal.to_s).to eq(qualified_name)
90
93
  end
91
94
 
92
95
  it "should raise an error when trying to lookup an account that doesn't exist" do
@@ -106,6 +109,7 @@ describe Puppet::Util::Windows::SID::Principal, :if => Puppet.features.microsoft
106
109
  expect(principal.account).to eq(builtin_localized)
107
110
  expect(principal.domain).to eq(builtin_localized)
108
111
  expect(principal.domain_account).to eq(builtin_localized)
112
+ expect(principal.to_s).to eq(builtin_localized)
109
113
  end
110
114
 
111
115
  it "should return a BUILTIN domain principal for BUILTIN account names" do
@@ -115,6 +119,7 @@ describe Puppet::Util::Windows::SID::Principal, :if => Puppet.features.microsoft
115
119
  expect(principal.account).to eq(builtin_localized)
116
120
  expect(principal.domain).to eq(builtin_localized)
117
121
  expect(principal.domain_account).to eq(builtin_localized)
122
+ expect(principal.to_s).to eq(builtin_localized)
118
123
  end
119
124
 
120
125
  end
@@ -135,6 +140,7 @@ describe Puppet::Util::Windows::SID::Principal, :if => Puppet.features.microsoft
135
140
  expect(principal.domain).to eq(computer_sid.domain)
136
141
  expect(principal.domain_account).to eq(guest_name)
137
142
  expect(principal.account_type).to eq(:SidTypeUser)
143
+ expect(principal.to_s).to eq(guest_name)
138
144
  end
139
145
 
140
146
  it "should create an instance from a well-known group SID" do
@@ -145,6 +151,7 @@ describe Puppet::Util::Windows::SID::Principal, :if => Puppet.features.microsoft
145
151
  expect(principal.domain).to eq('')
146
152
  expect(principal.domain_account).to eq('NULL SID')
147
153
  expect(principal.account_type).to eq(:SidTypeWellKnownGroup)
154
+ expect(principal.to_s).to eq('NULL SID')
148
155
  end
149
156
 
150
157
  it "should create an instance from a well-known BUILTIN Alias SID" do
@@ -160,6 +167,7 @@ describe Puppet::Util::Windows::SID::Principal, :if => Puppet.features.microsoft
160
167
  expect(principal.domain).to eq(domain)
161
168
  expect(principal.domain_account).to eq(qualified_name)
162
169
  expect(principal.account_type).to eq(:SidTypeAlias)
170
+ expect(principal.to_s).to eq(qualified_name)
163
171
  end
164
172
 
165
173
  it "should raise an error when trying to lookup nil" do
@@ -214,6 +222,7 @@ describe Puppet::Util::Windows::SID::Principal, :if => Puppet.features.microsoft
214
222
  expect(principal.account).to eq(builtin_localized)
215
223
  expect(principal.domain).to eq(builtin_localized)
216
224
  expect(principal.domain_account).to eq(builtin_localized)
225
+ expect(principal.to_s).to eq(builtin_localized)
217
226
  end
218
227
  end
219
228
 
@@ -191,9 +191,9 @@ describe Puppet::Application::Cert => true do
191
191
  @cert_app.subcommand = :destroy
192
192
  @cert_app.command_line.stubs(:args).returns(["unsigned-node"])
193
193
 
194
- Puppet::SSL::CertificateAuthority::Interface.expects(:new).returns(@iface).with { |cert_mode,to| cert_mode == :destroy
195
- to[:to] == ["unsigned-node"]
196
- }
194
+ Puppet::SSL::CertificateAuthority::Interface.unstub(:new)
195
+ Puppet::SSL::CertificateAuthority::Interface.expects(:new).with(:revoke, anything).never
196
+ Puppet::SSL::CertificateAuthority::Interface.expects(:new).with(:destroy, {:to => ['unsigned-node'], :digest => nil}).returns(@iface)
197
197
 
198
198
  @cert_app.main
199
199
  end
@@ -203,16 +203,28 @@ describe Puppet::Application::Cert => true do
203
203
  @cert_app.command_line.stubs(:args).returns(["host","unsigned-node"])
204
204
 
205
205
  Puppet::SSL::CertificateAuthority::Interface.expects(:new).returns(@iface).with { |cert_mode,to|
206
- cert_mode == :revoke
206
+ cert_mode == :revoke &&
207
207
  to[:to] == ["host"]
208
208
  }
209
209
  Puppet::SSL::CertificateAuthority::Interface.expects(:new).returns(@iface).with { |cert_mode,to|
210
- cert_mode == :destroy
210
+ cert_mode == :destroy &&
211
211
  to[:to] == ["host","unsigned-node"]
212
212
  }
213
213
 
214
214
  @cert_app.main
215
215
  end
216
+
217
+ it "should refuse to destroy all certificates" do
218
+ @cert_app.subcommand = :destroy
219
+ @cert_app.all = true
220
+
221
+ Puppet::SSL::CertificateAuthority::Interface.unstub(:new)
222
+ Puppet::SSL::CertificateAuthority::Interface.expects(:new).never
223
+
224
+ Puppet.expects(:log_exception).with {|e| e.message == "Refusing to destroy all certs, provide an explicit list of certs to destroy"}
225
+
226
+ expect { @cert_app.main }.to exit_with(24)
227
+ end
216
228
  end
217
229
 
218
230
  describe "when identifying subcommands" do
@@ -5,6 +5,7 @@ require 'puppet/application/device'
5
5
  require 'puppet/util/network_device/config'
6
6
  require 'ostruct'
7
7
  require 'puppet/configurer'
8
+ require 'puppet/application/apply'
8
9
 
9
10
  describe Puppet::Application::Device do
10
11
  include PuppetSpec::Files
@@ -127,6 +128,18 @@ describe Puppet::Application::Device do
127
128
  expect(@device.args[:Port]).to eq("42")
128
129
  end
129
130
 
131
+ it "should store the target options with --target" do
132
+ @device.options.expects(:[]=).with(:target,'test123')
133
+
134
+ @device.handle_target('test123')
135
+ end
136
+
137
+ it "should store the resource options with --resource" do
138
+ @device.options.expects(:[]=).with(:resource,true)
139
+
140
+ @device.handle_resource(true)
141
+ end
142
+
130
143
  end
131
144
 
132
145
  describe "during setup" do
@@ -277,7 +290,11 @@ describe Puppet::Application::Device do
277
290
  Puppet.stubs(:notice)
278
291
  @device.options.stubs(:[]).with(:detailed_exitcodes).returns(false)
279
292
  @device.options.stubs(:[]).with(:target).returns(nil)
293
+ @device.options.stubs(:[]).with(:apply).returns(nil)
294
+ @device.options.stubs(:[]).with(:resource).returns(false)
295
+ @device.options.stubs(:[]).with(:to_yaml).returns(false)
280
296
  @device.options.stubs(:[]).with(:client)
297
+ @device.command_line.stubs(:args).returns([])
281
298
  Puppet::Util::NetworkDevice::Config.stubs(:devices).returns({})
282
299
  end
283
300
 
@@ -286,6 +303,12 @@ describe Puppet::Application::Device do
286
303
  @device.run_command
287
304
  end
288
305
 
306
+ it "should exit if resource is requested without target" do
307
+ @device.options.stubs(:[]).with(:resource).returns(true)
308
+ Puppet.expects(:err).with "resource command requires target"
309
+ expect { @device.main }.to exit_with 1
310
+ end
311
+
289
312
  it "should get the device list" do
290
313
  device_hash = stub_everything 'device hash'
291
314
  Puppet::Util::NetworkDevice::Config.expects(:devices).returns(device_hash)
@@ -301,8 +324,8 @@ describe Puppet::Application::Device do
301
324
  }
302
325
 
303
326
  Puppet::Util::NetworkDevice::Config.expects(:devices).returns(device_hash)
304
- Puppet.expects(:info).with("starting applying configuration to device1 at ssh://testhost")
305
- Puppet.expects(:info).with("starting applying configuration to device2 at https://testhost:443/some/path").never
327
+ URI.expects(:parse).with("ssh://user:pass@testhost")
328
+ URI.expects(:parse).with("https://user:pass@testhost/some/path").never
306
329
  expect { @device.main }.to exit_with 1
307
330
  end
308
331
 
@@ -318,6 +341,32 @@ describe Puppet::Application::Device do
318
341
  expect { @device.main }.to exit_with 1
319
342
  end
320
343
 
344
+ it "should error if target is passed and the apply path is incorrect" do
345
+ @device.options.stubs(:[]).with(:apply).returns('file.pp')
346
+ @device.options.stubs(:[]).with(:target).returns('device1')
347
+
348
+ File.expects(:file?).returns(false)
349
+ Puppet.expects(:err).with(regexp_matches(/does not exist, cannot apply/))
350
+ expect { @device.main }.to exit_with 1
351
+ end
352
+
353
+ it "should run an apply" do
354
+ @device.options.stubs(:[]).with(:apply).returns('file.pp')
355
+ @device.options.stubs(:[]).with(:target).returns('device1')
356
+ device_hash = {
357
+ "device1" => OpenStruct.new(:name => "device1", :url => "ssh://user:pass@testhost", :provider => "cisco"),
358
+ }
359
+ Puppet::Util::NetworkDevice::Config.expects(:devices).returns(device_hash)
360
+ Puppet::Util::NetworkDevice.stubs(:init)
361
+ File.expects(:file?).returns(true)
362
+
363
+ Puppet::Util::CommandLine.expects(:new).once
364
+ Puppet::Application::Apply.expects(:new).once
365
+
366
+ Puppet::Configurer.expects(:new).never
367
+ expect { @device.main }.to exit_with 1
368
+ end
369
+
321
370
  it "should exit if the device list is empty" do
322
371
  expect { @device.main }.to exit_with 1
323
372
  end
@@ -356,6 +405,51 @@ describe Puppet::Application::Device do
356
405
  expect { @device.main }.to exit_with 1
357
406
  end
358
407
 
408
+ it "should raise an error if no type is given" do
409
+ @device.options.stubs(:[]).with(:resource).returns(true)
410
+ @device.options.stubs(:[]).with(:target).returns('device1')
411
+ @device.command_line.stubs(:args).returns([])
412
+ Puppet.expects(:log_exception).with {|e| e.message == "You must specify the type to display"}
413
+ expect { @device.main }.to exit_with 1
414
+ end
415
+
416
+ it "should raise an error if the type is not found" do
417
+ @device.options.stubs(:[]).with(:resource).returns(true)
418
+ @device.options.stubs(:[]).with(:target).returns('device1')
419
+ @device.command_line.stubs(:args).returns(['nope'])
420
+ Puppet.expects(:log_exception).with {|e| e.message == "Could not find type nope"}
421
+ expect { @device.main }.to exit_with 1
422
+ end
423
+
424
+ it "should retrieve all resources of a type" do
425
+ @device.options.stubs(:[]).with(:resource).returns(true)
426
+ @device.options.stubs(:[]).with(:target).returns('device1')
427
+ @device.command_line.stubs(:args).returns(['user'])
428
+ Puppet::Resource.indirection.expects(:search).with('user/', {}).returns([])
429
+ expect { @device.main }.to exit_with 1
430
+ end
431
+
432
+ it "should retrieve named resources of a type" do
433
+ @device.options.stubs(:[]).with(:resource).returns(true)
434
+ @device.options.stubs(:[]).with(:target).returns('device1')
435
+ @device.command_line.stubs(:args).returns(['user', 'title'])
436
+ Puppet::Resource.indirection.expects(:find).with('user/title')
437
+ expect { @device.main }.to exit_with 1
438
+ end
439
+
440
+ it "should output resources as YAML" do
441
+ resources = [
442
+ Puppet::Type.type(:user).new(:name => "title").to_resource,
443
+ ]
444
+ @device.options.stubs(:[]).with(:resource).returns(true)
445
+ @device.options.stubs(:[]).with(:target).returns('device1')
446
+ @device.options.stubs(:[]).with(:to_yaml).returns(true)
447
+ @device.command_line.stubs(:args).returns(['user'])
448
+ Puppet::Resource.indirection.expects(:search).with('user/', {}).returns(resources)
449
+ @device.expects(:puts).with("user:\n title:\n")
450
+ expect { @device.main }.to exit_with 1
451
+ end
452
+
359
453
  it "should make sure all the required folders and files are created" do
360
454
  Puppet.settings.expects(:use).with(:main, :agent, :ssl).twice
361
455
  expect { @device.main }.to exit_with 1
@@ -723,6 +723,49 @@ describe Puppet::Indirector::REST do
723
723
  end
724
724
  end
725
725
 
726
+ describe '#handle_response' do
727
+ # There are multiple request types to choose from, this may not be the one I want for this situation
728
+ let(:response) { mock_response(200, 'body') }
729
+ let(:connection) { stub('mock http connection', :put => response, :verify_callback= => nil) }
730
+ let(:instance) { model.new('the thing', 'some contents') }
731
+ let(:request) { save_request(instance.name, instance) }
732
+
733
+ before :each do
734
+ terminus.stubs(:network).returns(connection)
735
+ end
736
+
737
+ it 'adds server_agent_version to the context if not already set' do
738
+ Puppet.expects(:push_context).with(:server_agent_version => Puppet.version)
739
+ terminus.handle_response(request, response)
740
+ end
741
+
742
+ it 'does not add server_agent_version to the context if it is already set' do
743
+ Puppet.override(:server_agent_version => "5.3.4") do
744
+ Puppet.expects(:push_context).never
745
+ terminus.handle_response(request, response)
746
+ end
747
+ end
748
+
749
+ it 'downgrades to pson and emits a warning' do
750
+ response.stubs(:[]).with(Puppet::Network::HTTP::HEADER_PUPPET_VERSION).returns('4.2.8')
751
+ Puppet[:preferred_serialization_format] = 'other'
752
+
753
+ Puppet.expects(:warning).with('Downgrading to PSON for future requests')
754
+
755
+ terminus.handle_response(request, response)
756
+
757
+ expect(Puppet[:preferred_serialization_format]).to eq('pson')
758
+ end
759
+
760
+ it 'preserves the set serialization format' do
761
+ Puppet[:preferred_serialization_format] = 'other'
762
+
763
+ expect(Puppet[:preferred_serialization_format]).to eq('other')
764
+
765
+ terminus.handle_response(request, response)
766
+ end
767
+ end
768
+
726
769
  context 'dealing with SRV settings' do
727
770
  [
728
771
  :destroy,