puppet 7.16.0-universal-darwin → 7.19.0-universal-darwin
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/Gemfile.lock +76 -15
 - data/ext/systemd/puppet.service +2 -1
 - data/lib/puppet/agent.rb +47 -11
 - data/lib/puppet/application/agent.rb +3 -13
 - data/lib/puppet/application/apply.rb +2 -2
 - data/lib/puppet/configurer.rb +1 -1
 - data/lib/puppet/defaults.rb +11 -1
 - data/lib/puppet/face/help.rb +1 -1
 - data/lib/puppet/face/module/list.rb +16 -7
 - data/lib/puppet/functions/capitalize.rb +1 -1
 - data/lib/puppet/generate/type.rb +1 -1
 - data/lib/puppet/http/client.rb +22 -2
 - data/lib/puppet/info_service/task_information_service.rb +1 -1
 - data/lib/puppet/module/task.rb +5 -1
 - data/lib/puppet/parameter.rb +19 -4
 - data/lib/puppet/parser/templatewrapper.rb +1 -1
 - data/lib/puppet/pops/evaluator/deferred_resolver.rb +46 -6
 - data/lib/puppet/pops/functions/dispatcher.rb +10 -6
 - data/lib/puppet/pops/loader/ruby_legacy_function_instantiator.rb +7 -6
 - data/lib/puppet/pops/types/type_mismatch_describer.rb +22 -1
 - data/lib/puppet/provider/package/puppetserver_gem.rb +7 -16
 - data/lib/puppet/provider/package/yum.rb +8 -3
 - data/lib/puppet/provider/user/directoryservice.rb +15 -8
 - data/lib/puppet/reference/configuration.rb +2 -0
 - data/lib/puppet/ssl/ssl_provider.rb +65 -12
 - data/lib/puppet/ssl/state_machine.rb +13 -17
 - data/lib/puppet/transaction.rb +22 -0
 - data/lib/puppet/type/tidy.rb +1 -1
 - data/lib/puppet/type/user.rb +3 -0
 - data/lib/puppet/type.rb +20 -3
 - data/lib/puppet/util/json.rb +5 -2
 - data/lib/puppet/util/resource_template.rb +1 -1
 - data/lib/puppet/util/selinux.rb +1 -1
 - data/lib/puppet/util.rb +12 -1
 - data/lib/puppet/version.rb +1 -1
 - data/lib/puppet.rb +1 -14
 - data/man/man5/puppet.conf.5 +12 -4
 - data/man/man8/puppet-agent.8 +2 -2
 - data/man/man8/puppet-apply.8 +1 -1
 - data/man/man8/puppet-catalog.8 +1 -1
 - data/man/man8/puppet-config.8 +1 -1
 - data/man/man8/puppet-describe.8 +1 -1
 - data/man/man8/puppet-device.8 +1 -1
 - data/man/man8/puppet-doc.8 +1 -1
 - data/man/man8/puppet-epp.8 +1 -1
 - data/man/man8/puppet-facts.8 +1 -1
 - data/man/man8/puppet-filebucket.8 +1 -1
 - data/man/man8/puppet-generate.8 +1 -1
 - data/man/man8/puppet-help.8 +1 -1
 - data/man/man8/puppet-lookup.8 +1 -1
 - data/man/man8/puppet-module.8 +1 -1
 - data/man/man8/puppet-node.8 +1 -1
 - data/man/man8/puppet-parser.8 +1 -1
 - data/man/man8/puppet-plugin.8 +1 -1
 - data/man/man8/puppet-report.8 +1 -1
 - data/man/man8/puppet-resource.8 +1 -1
 - data/man/man8/puppet-script.8 +1 -1
 - data/man/man8/puppet-ssl.8 +1 -1
 - data/man/man8/puppet.8 +2 -2
 - data/spec/integration/application/agent_spec.rb +157 -0
 - data/spec/integration/application/apply_spec.rb +74 -0
 - data/spec/integration/http/client_spec.rb +27 -10
 - data/spec/lib/puppet_spec/https.rb +1 -1
 - data/spec/lib/puppet_spec/puppetserver.rb +39 -2
 - data/spec/unit/agent_spec.rb +28 -2
 - data/spec/unit/application/agent_spec.rb +26 -16
 - data/spec/unit/daemon_spec.rb +2 -11
 - data/spec/unit/face/module/list_spec.rb +26 -0
 - data/spec/unit/http/client_spec.rb +18 -0
 - data/spec/unit/info_service_spec.rb +11 -3
 - data/spec/unit/pops/evaluator/deferred_resolver_spec.rb +26 -0
 - data/spec/unit/pops/loaders/loaders_spec.rb +1 -1
 - data/spec/unit/pops/types/type_mismatch_describer_spec.rb +167 -1
 - data/spec/unit/provider/package/puppetserver_gem_spec.rb +2 -2
 - data/spec/unit/provider/user/directoryservice_spec.rb +1 -1
 - data/spec/unit/ssl/ssl_provider_spec.rb +75 -1
 - data/spec/unit/ssl/state_machine_spec.rb +1 -0
 - data/spec/unit/task_spec.rb +56 -13
 - data/spec/unit/util/resource_template_spec.rb +1 -1
 - data/spec/unit/util/selinux_spec.rb +5 -0
 - data/spec/unit/util_spec.rb +11 -1
 - data/tasks/generate_cert_fixtures.rake +5 -4
 - metadata +2 -2
 
| 
         @@ -77,13 +77,13 @@ describe Puppet::HTTP::Client, unless: Puppet::Util::Platform.jruby? do 
     | 
|
| 
       77 
77 
     | 
    
         
             
                  }
         
     | 
| 
       78 
78 
     | 
    
         
             
                }
         
     | 
| 
       79 
79 
     | 
    
         | 
| 
       80 
     | 
    
         
            -
                let(: 
     | 
| 
       81 
     | 
    
         
            -
                  res = tmpfile(' 
     | 
| 
      
 80 
     | 
    
         
            +
                let(:cert_file) do
         
     | 
| 
      
 81 
     | 
    
         
            +
                  res = tmpfile('cert_file')
         
     | 
| 
       82 
82 
     | 
    
         
             
                  File.write(res, https_server.ca_cert)
         
     | 
| 
       83 
83 
     | 
    
         
             
                  res
         
     | 
| 
       84 
84 
     | 
    
         
             
                end
         
     | 
| 
       85 
85 
     | 
    
         | 
| 
       86 
     | 
    
         
            -
                it "mutually authenticates the connection" do
         
     | 
| 
      
 86 
     | 
    
         
            +
                it "mutually authenticates the connection using an explicit context" do
         
     | 
| 
       87 
87 
     | 
    
         
             
                  client_context = ssl_provider.create_context(
         
     | 
| 
       88 
88 
     | 
    
         
             
                    cacerts: [https_server.ca_cert], crls: [https_server.ca_crl],
         
     | 
| 
       89 
89 
     | 
    
         
             
                    client_cert: https_server.server_cert, private_key: https_server.server_key
         
     | 
| 
         @@ -95,10 +95,27 @@ describe Puppet::HTTP::Client, unless: Puppet::Util::Platform.jruby? do 
     | 
|
| 
       95 
95 
     | 
    
         
             
                  end
         
     | 
| 
       96 
96 
     | 
    
         
             
                end
         
     | 
| 
       97 
97 
     | 
    
         | 
| 
      
 98 
     | 
    
         
            +
                it "mutually authenticates the connection when the client and server certs are issued from different CAs" do
         
     | 
| 
      
 99 
     | 
    
         
            +
                  # this is the client cert's CA, key and cert
         
     | 
| 
      
 100 
     | 
    
         
            +
                  Puppet[:localcacert] = fixtures('ssl/unknown-ca.pem')
         
     | 
| 
      
 101 
     | 
    
         
            +
                  Puppet[:hostprivkey] = fixtures('ssl/unknown-127.0.0.1-key.pem')
         
     | 
| 
      
 102 
     | 
    
         
            +
                  Puppet[:hostcert] = fixtures('ssl/unknown-127.0.0.1.pem')
         
     | 
| 
      
 103 
     | 
    
         
            +
             
     | 
| 
      
 104 
     | 
    
         
            +
                  # this is the server cert's CA that the client needs in order to authenticate the server
         
     | 
| 
      
 105 
     | 
    
         
            +
                  Puppet[:ssl_trust_store] = fixtures('ssl/ca.pem')
         
     | 
| 
      
 106 
     | 
    
         
            +
             
     | 
| 
      
 107 
     | 
    
         
            +
                  # need to pass both the client and server CAs. The former is needed so the server can authenticate our client cert
         
     | 
| 
      
 108 
     | 
    
         
            +
                  https_server = PuppetSpec::HTTPSServer.new(ca_cert: [cert_fixture('ca.pem'), cert_fixture('unknown-ca.pem')])
         
     | 
| 
      
 109 
     | 
    
         
            +
                  https_server.start_server(ctx_proc: ctx_proc) do |port|
         
     | 
| 
      
 110 
     | 
    
         
            +
                    res = client.get(URI("https://127.0.0.1:#{port}"), options: {include_system_store: true})
         
     | 
| 
      
 111 
     | 
    
         
            +
                    expect(res).to be_success
         
     | 
| 
      
 112 
     | 
    
         
            +
                  end
         
     | 
| 
      
 113 
     | 
    
         
            +
                end
         
     | 
| 
      
 114 
     | 
    
         
            +
             
     | 
| 
       98 
115 
     | 
    
         
             
                it "connects when the server's CA is in the system store and the connection is mutually authenticated using create_context" do
         
     | 
| 
       99 
     | 
    
         
            -
                  Puppet::Util.withenv("SSL_CERT_FILE" =>  
     | 
| 
      
 116 
     | 
    
         
            +
                  Puppet::Util.withenv("SSL_CERT_FILE" => cert_file) do
         
     | 
| 
       100 
117 
     | 
    
         
             
                    client_context = ssl_provider.create_context(
         
     | 
| 
       101 
     | 
    
         
            -
                      cacerts: [ 
     | 
| 
      
 118 
     | 
    
         
            +
                      cacerts: [], crls: [],
         
     | 
| 
       102 
119 
     | 
    
         
             
                      client_cert: https_server.server_cert, private_key: https_server.server_key,
         
     | 
| 
       103 
120 
     | 
    
         
             
                      revocation: false, include_system_store: true
         
     | 
| 
       104 
121 
     | 
    
         
             
                    )
         
     | 
| 
         @@ -109,8 +126,8 @@ describe Puppet::HTTP::Client, unless: Puppet::Util::Platform.jruby? do 
     | 
|
| 
       109 
126 
     | 
    
         
             
                  end
         
     | 
| 
       110 
127 
     | 
    
         
             
                end
         
     | 
| 
       111 
128 
     | 
    
         | 
| 
       112 
     | 
    
         
            -
                it "connects when the server's CA is in the system store and the connection is mutually authenticated  
     | 
| 
       113 
     | 
    
         
            -
                  Puppet::Util.withenv("SSL_CERT_FILE" =>  
     | 
| 
      
 129 
     | 
    
         
            +
                it "connects when the server's CA is in the system store and the connection is mutually authenticated using load_context" do
         
     | 
| 
      
 130 
     | 
    
         
            +
                  Puppet::Util.withenv("SSL_CERT_FILE" => cert_file) do
         
     | 
| 
       114 
131 
     | 
    
         
             
                    client_context = ssl_provider.load_context(revocation: false, include_system_store: true)
         
     | 
| 
       115 
132 
     | 
    
         
             
                    https_server.start_server(ctx_proc: ctx_proc) do |port|
         
     | 
| 
       116 
133 
     | 
    
         
             
                      res = client.get(URI("https://127.0.0.1:#{port}"), options: {ssl_context: client_context})
         
     | 
| 
         @@ -132,12 +149,12 @@ describe Puppet::HTTP::Client, unless: Puppet::Util::Platform.jruby? do 
     | 
|
| 
       132 
149 
     | 
    
         | 
| 
       133 
150 
     | 
    
         
             
                it "connects when the server's CA is in the system store" do
         
     | 
| 
       134 
151 
     | 
    
         
             
                  # create a temp cacert bundle
         
     | 
| 
       135 
     | 
    
         
            -
                   
     | 
| 
       136 
     | 
    
         
            -
                  File.write( 
     | 
| 
      
 152 
     | 
    
         
            +
                  cert_file = tmpfile('cert_file')
         
     | 
| 
      
 153 
     | 
    
         
            +
                  File.write(cert_file, https_server.ca_cert)
         
     | 
| 
       137 
154 
     | 
    
         | 
| 
       138 
155 
     | 
    
         
             
                  # override path to system cacert bundle, this must be done before
         
     | 
| 
       139 
156 
     | 
    
         
             
                  # the SSLContext is created and the call to X509::Store.set_default_paths
         
     | 
| 
       140 
     | 
    
         
            -
                  Puppet::Util.withenv("SSL_CERT_FILE" =>  
     | 
| 
      
 157 
     | 
    
         
            +
                  Puppet::Util.withenv("SSL_CERT_FILE" => cert_file) do
         
     | 
| 
       141 
158 
     | 
    
         
             
                    system_context = ssl_provider.create_system_context(cacerts: [])
         
     | 
| 
       142 
159 
     | 
    
         
             
                    https_server.start_server do |port|
         
     | 
| 
       143 
160 
     | 
    
         
             
                      res = client.get(URI("https://127.0.0.1:#{port}"), options: {ssl_context: system_context})
         
     | 
| 
         @@ -40,7 +40,7 @@ class PuppetSpec::HTTPSServer 
     | 
|
| 
       40 
40 
     | 
    
         | 
| 
       41 
41 
     | 
    
         
             
                IO.pipe {|stop_pipe_r, stop_pipe_w|
         
     | 
| 
       42 
42 
     | 
    
         
             
                  store = OpenSSL::X509::Store.new
         
     | 
| 
       43 
     | 
    
         
            -
                  store.add_cert( 
     | 
| 
      
 43 
     | 
    
         
            +
                  Array(@ca_cert).each { |c| store.add_cert(c) }
         
     | 
| 
       44 
44 
     | 
    
         
             
                  store.purpose = OpenSSL::X509::PURPOSE_SSL_CLIENT
         
     | 
| 
       45 
45 
     | 
    
         
             
                  ctx = OpenSSL::SSL::SSLContext.new
         
     | 
| 
       46 
46 
     | 
    
         
             
                  ctx.cert_store = store
         
     | 
| 
         @@ -72,6 +72,40 @@ class PuppetSpec::Puppetserver 
     | 
|
| 
       72 
72 
     | 
    
         
             
                end
         
     | 
| 
       73 
73 
     | 
    
         
             
              end
         
     | 
| 
       74 
74 
     | 
    
         | 
| 
      
 75 
     | 
    
         
            +
              class CertificateServlet < WEBrick::HTTPServlet::AbstractServlet
         
     | 
| 
      
 76 
     | 
    
         
            +
                def initialize(server, ca_cert)
         
     | 
| 
      
 77 
     | 
    
         
            +
                  super(server)
         
     | 
| 
      
 78 
     | 
    
         
            +
                  @ca_cert = ca_cert
         
     | 
| 
      
 79 
     | 
    
         
            +
                end
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                def do_GET request, response
         
     | 
| 
      
 82 
     | 
    
         
            +
                  if request.path =~ %r{/puppet-ca/v1/certificate/ca$}
         
     | 
| 
      
 83 
     | 
    
         
            +
                    response['Content-Type'] = 'text/plain'
         
     | 
| 
      
 84 
     | 
    
         
            +
                    response.body = @ca_cert.to_pem
         
     | 
| 
      
 85 
     | 
    
         
            +
                  else
         
     | 
| 
      
 86 
     | 
    
         
            +
                    response.status = 404
         
     | 
| 
      
 87 
     | 
    
         
            +
                  end
         
     | 
| 
      
 88 
     | 
    
         
            +
                end
         
     | 
| 
      
 89 
     | 
    
         
            +
              end
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
              class CertificateRevocationListServlet < WEBrick::HTTPServlet::AbstractServlet
         
     | 
| 
      
 92 
     | 
    
         
            +
                def initialize(server, crl)
         
     | 
| 
      
 93 
     | 
    
         
            +
                  super(server)
         
     | 
| 
      
 94 
     | 
    
         
            +
                  @crl = crl
         
     | 
| 
      
 95 
     | 
    
         
            +
                end
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
                def do_GET request, response
         
     | 
| 
      
 98 
     | 
    
         
            +
                  response['Content-Type'] = 'text/plain'
         
     | 
| 
      
 99 
     | 
    
         
            +
                  response.body = @crl.to_pem
         
     | 
| 
      
 100 
     | 
    
         
            +
                end
         
     | 
| 
      
 101 
     | 
    
         
            +
              end
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
              class CertificateRequestServlet < WEBrick::HTTPServlet::AbstractServlet
         
     | 
| 
      
 104 
     | 
    
         
            +
                def do_PUT request, response
         
     | 
| 
      
 105 
     | 
    
         
            +
                  response.status = 404
         
     | 
| 
      
 106 
     | 
    
         
            +
                end
         
     | 
| 
      
 107 
     | 
    
         
            +
              end
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
       75 
109 
     | 
    
         
             
              def initialize
         
     | 
| 
       76 
110 
     | 
    
         
             
                @ca_cert = cert_fixture('ca.pem')
         
     | 
| 
       77 
111 
     | 
    
         
             
                @ca_crl = crl_fixture('crl.pem')
         
     | 
| 
         @@ -125,15 +159,18 @@ class PuppetSpec::Puppetserver 
     | 
|
| 
       125 
159 
     | 
    
         
             
                register_mount('/puppet/v3/static_file_content', mounts[:static_file_content], StaticFileContentServlet)
         
     | 
| 
       126 
160 
     | 
    
         
             
                register_mount('/puppet/v3/report', mounts[:report], ReportServlet)
         
     | 
| 
       127 
161 
     | 
    
         
             
                register_mount('/puppet/v3/file_bucket_file', mounts[:filebucket], FilebucketServlet)
         
     | 
| 
      
 162 
     | 
    
         
            +
                register_mount('/puppet-ca/v1/certificate', mounts[:certificate], CertificateServlet, @ca_cert)
         
     | 
| 
      
 163 
     | 
    
         
            +
                register_mount('/puppet-ca/v1/certificate_revocation_list', mounts[:certificate_revocation_list], CertificateRevocationListServlet, @ca_crl)
         
     | 
| 
      
 164 
     | 
    
         
            +
                register_mount('/puppet-ca/v1/certificate_request', mounts[:certificate_request], CertificateRequestServlet)
         
     | 
| 
       128 
165 
     | 
    
         
             
              end
         
     | 
| 
       129 
166 
     | 
    
         | 
| 
       130 
     | 
    
         
            -
              def register_mount(path, user_proc, default_servlet)
         
     | 
| 
      
 167 
     | 
    
         
            +
              def register_mount(path, user_proc, default_servlet, *args)
         
     | 
| 
       131 
168 
     | 
    
         
             
                handler = if user_proc
         
     | 
| 
       132 
169 
     | 
    
         
             
                            WEBrick::HTTPServlet::ProcHandler.new(user_proc)
         
     | 
| 
       133 
170 
     | 
    
         
             
                          else
         
     | 
| 
       134 
171 
     | 
    
         
             
                            default_servlet
         
     | 
| 
       135 
172 
     | 
    
         
             
                          end
         
     | 
| 
       136 
     | 
    
         
            -
                @https.mount(path, handler)
         
     | 
| 
      
 173 
     | 
    
         
            +
                @https.mount(path, handler, *args)
         
     | 
| 
       137 
174 
     | 
    
         
             
              end
         
     | 
| 
       138 
175 
     | 
    
         | 
| 
       139 
176 
     | 
    
         
             
              def upload_directory
         
     | 
    
        data/spec/unit/agent_spec.rb
    CHANGED
    
    | 
         @@ -36,6 +36,10 @@ describe Puppet::Agent do 
     | 
|
| 
       36 
36 
     | 
    
         
             
                    end
         
     | 
| 
       37 
37 
     | 
    
         
             
                  end
         
     | 
| 
       38 
38 
     | 
    
         
             
                end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                ssl_context = Puppet::SSL::SSLContext.new
         
     | 
| 
      
 41 
     | 
    
         
            +
                machine = instance_double("Puppet::SSL::StateMachine", ensure_client_certificate: ssl_context)
         
     | 
| 
      
 42 
     | 
    
         
            +
                allow(Puppet::SSL::StateMachine).to receive(:new).and_return(machine)
         
     | 
| 
       39 
43 
     | 
    
         
             
              end
         
     | 
| 
       40 
44 
     | 
    
         | 
| 
       41 
45 
     | 
    
         
             
              after do
         
     | 
| 
         @@ -97,6 +101,8 @@ describe Puppet::Agent do 
     | 
|
| 
       97 
101 
     | 
    
         
             
                end
         
     | 
| 
       98 
102 
     | 
    
         | 
| 
       99 
103 
     | 
    
         
             
                it "should splay" do
         
     | 
| 
      
 104 
     | 
    
         
            +
                  Puppet[:splay] = true
         
     | 
| 
      
 105 
     | 
    
         
            +
             
     | 
| 
       100 
106 
     | 
    
         
             
                  expect(@agent).to receive(:splay)
         
     | 
| 
       101 
107 
     | 
    
         | 
| 
       102 
108 
     | 
    
         
             
                  @agent.run
         
     | 
| 
         @@ -179,6 +185,26 @@ describe Puppet::Agent do 
     | 
|
| 
       179 
185 
     | 
    
         
             
                  expect(@agent.run).to eq(:result)
         
     | 
| 
       180 
186 
     | 
    
         
             
                end
         
     | 
| 
       181 
187 
     | 
    
         | 
| 
      
 188 
     | 
    
         
            +
                it "should check if it's disabled after splaying and log a message" do
         
     | 
| 
      
 189 
     | 
    
         
            +
                  Puppet[:splay] = true
         
     | 
| 
      
 190 
     | 
    
         
            +
                  Puppet[:splaylimit] = '5s'
         
     | 
| 
      
 191 
     | 
    
         
            +
                  Puppet[:onetime] = true
         
     | 
| 
      
 192 
     | 
    
         
            +
             
     | 
| 
      
 193 
     | 
    
         
            +
                  expect(@agent).to receive(:disabled?).and_return(false, true)
         
     | 
| 
      
 194 
     | 
    
         
            +
             
     | 
| 
      
 195 
     | 
    
         
            +
                  allow(Puppet).to receive(:notice).and_call_original
         
     | 
| 
      
 196 
     | 
    
         
            +
                  expect(Puppet).to receive(:notice).with(/Skipping run of .*; administratively disabled.*/)
         
     | 
| 
      
 197 
     | 
    
         
            +
                  @agent.run
         
     | 
| 
      
 198 
     | 
    
         
            +
                end
         
     | 
| 
      
 199 
     | 
    
         
            +
             
     | 
| 
      
 200 
     | 
    
         
            +
                it "should check if it's disabled after acquiring the lock and log a message" do
         
     | 
| 
      
 201 
     | 
    
         
            +
                  expect(@agent).to receive(:disabled?).and_return(false, true)
         
     | 
| 
      
 202 
     | 
    
         
            +
             
     | 
| 
      
 203 
     | 
    
         
            +
                  allow(Puppet).to receive(:notice).and_call_original
         
     | 
| 
      
 204 
     | 
    
         
            +
                  expect(Puppet).to receive(:notice).with(/Skipping run of .*; administratively disabled.*/)
         
     | 
| 
      
 205 
     | 
    
         
            +
                  @agent.run
         
     | 
| 
      
 206 
     | 
    
         
            +
                end
         
     | 
| 
      
 207 
     | 
    
         
            +
             
     | 
| 
       182 
208 
     | 
    
         
             
                describe "and a puppet agent is already running" do
         
     | 
| 
       183 
209 
     | 
    
         
             
                  before(:each) do
         
     | 
| 
       184 
210 
     | 
    
         
             
                    allow_any_instance_of(Object).to receive(:sleep)
         
     | 
| 
         @@ -195,7 +221,7 @@ describe Puppet::Agent do 
     | 
|
| 
       195 
221 
     | 
    
         
             
                    @agent.run
         
     | 
| 
       196 
222 
     | 
    
         
             
                  end
         
     | 
| 
       197 
223 
     | 
    
         | 
| 
       198 
     | 
    
         
            -
                  it "should inform that a run is already in  
     | 
| 
      
 224 
     | 
    
         
            +
                  it "should inform that a run is already in progress and try to run every X seconds if waitforlock is used" do
         
     | 
| 
       199 
225 
     | 
    
         
             
                    # so the locked file exists
         
     | 
| 
       200 
226 
     | 
    
         
             
                    allow(File).to receive(:file?).and_return(true)
         
     | 
| 
       201 
227 
     | 
    
         
             
                    # so we don't have to wait again for the run to exit (default maxwaitforcert is 60)
         
     | 
| 
         @@ -224,7 +250,7 @@ describe Puppet::Agent do 
     | 
|
| 
       224 
250 
     | 
    
         
             
                    @agent.run
         
     | 
| 
       225 
251 
     | 
    
         
             
                  end
         
     | 
| 
       226 
252 
     | 
    
         
             
                end
         
     | 
| 
       227 
     | 
    
         
            -
             
     | 
| 
      
 253 
     | 
    
         
            +
             
     | 
| 
       228 
254 
     | 
    
         
             
                describe "when should_fork is true", :if => Puppet.features.posix? && RUBY_PLATFORM != 'java' do
         
     | 
| 
       229 
255 
     | 
    
         
             
                  before do
         
     | 
| 
       230 
256 
     | 
    
         
             
                    @agent = Puppet::Agent.new(AgentTestClient, true)
         
     | 
| 
         @@ -4,6 +4,11 @@ require 'puppet/agent' 
     | 
|
| 
       4 
4 
     | 
    
         
             
            require 'puppet/application/agent'
         
     | 
| 
       5 
5 
     | 
    
         
             
            require 'puppet/daemon'
         
     | 
| 
       6 
6 
     | 
    
         | 
| 
      
 7 
     | 
    
         
            +
            class TestAgentClientClass
         
     | 
| 
      
 8 
     | 
    
         
            +
              def initialize(transaction_uuid = nil, job_id = nil); end
         
     | 
| 
      
 9 
     | 
    
         
            +
              def run(options = {}); end
         
     | 
| 
      
 10 
     | 
    
         
            +
            end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
       7 
12 
     | 
    
         
             
            describe Puppet::Application::Agent do
         
     | 
| 
       8 
13 
     | 
    
         
             
              include PuppetSpec::Files
         
     | 
| 
       9 
14 
     | 
    
         | 
| 
         @@ -12,13 +17,20 @@ describe Puppet::Application::Agent do 
     | 
|
| 
       12 
17 
     | 
    
         
             
              before :each do
         
     | 
| 
       13 
18 
     | 
    
         
             
                @puppetd = Puppet::Application[:agent]
         
     | 
| 
       14 
19 
     | 
    
         | 
| 
       15 
     | 
    
         
            -
                @ 
     | 
| 
      
 20 
     | 
    
         
            +
                @client = TestAgentClientClass.new
         
     | 
| 
      
 21 
     | 
    
         
            +
                allow(TestAgentClientClass).to receive(:new).and_return(@client)
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                @agent = Puppet::Agent.new(TestAgentClientClass, false)
         
     | 
| 
       16 
24 
     | 
    
         
             
                allow(Puppet::Agent).to receive(:new).and_return(@agent)
         
     | 
| 
       17 
25 
     | 
    
         | 
| 
       18 
     | 
    
         
            -
                 
     | 
| 
      
 26 
     | 
    
         
            +
                Puppet[:pidfile] = tmpfile('pidfile')
         
     | 
| 
      
 27 
     | 
    
         
            +
                @daemon = Puppet::Daemon.new(@agent, Puppet::Util::Pidlock.new(Puppet[:pidfile]))
         
     | 
| 
       19 
28 
     | 
    
         
             
                allow(@daemon).to receive(:daemonize)
         
     | 
| 
       20 
     | 
    
         
            -
                allow(@daemon).to receive(:start)
         
     | 
| 
       21 
29 
     | 
    
         
             
                allow(@daemon).to receive(:stop)
         
     | 
| 
      
 30 
     | 
    
         
            +
                # simulate one run so we don't infinite looptwo runs of the agent, then return so we don't infinite loop
         
     | 
| 
      
 31 
     | 
    
         
            +
                allow(@daemon).to receive(:run_event_loop) do
         
     | 
| 
      
 32 
     | 
    
         
            +
                  @agent.run(splay: false)
         
     | 
| 
      
 33 
     | 
    
         
            +
                end
         
     | 
| 
       22 
34 
     | 
    
         
             
                allow(Puppet::Daemon).to receive(:new).and_return(@daemon)
         
     | 
| 
       23 
35 
     | 
    
         
             
                Puppet[:daemonize] = false
         
     | 
| 
       24 
36 
     | 
    
         | 
| 
         @@ -92,10 +104,6 @@ describe Puppet::Application::Agent do 
     | 
|
| 
       92 
104 
     | 
    
         
             
              end
         
     | 
| 
       93 
105 
     | 
    
         | 
| 
       94 
106 
     | 
    
         
             
              describe "when handling options" do
         
     | 
| 
       95 
     | 
    
         
            -
                before do
         
     | 
| 
       96 
     | 
    
         
            -
                  allow(@puppetd.command_line).to receive(:args).and_return([])
         
     | 
| 
       97 
     | 
    
         
            -
                end
         
     | 
| 
       98 
     | 
    
         
            -
             
     | 
| 
       99 
107 
     | 
    
         
             
                [:enable, :debug, :fqdn, :test, :verbose, :digest].each do |option|
         
     | 
| 
       100 
108 
     | 
    
         
             
                  it "should declare handle_#{option} method" do
         
     | 
| 
       101 
109 
     | 
    
         
             
                    expect(@puppetd).to respond_to("handle_#{option}".to_sym)
         
     | 
| 
         @@ -127,32 +135,34 @@ describe Puppet::Application::Agent do 
     | 
|
| 
       127 
135 
     | 
    
         
             
                end
         
     | 
| 
       128 
136 
     | 
    
         | 
| 
       129 
137 
     | 
    
         
             
                it "should set waitforcert to 0 with --onetime and if --waitforcert wasn't given" do
         
     | 
| 
       130 
     | 
    
         
            -
                  allow(@ 
     | 
| 
      
 138 
     | 
    
         
            +
                  allow(@client).to receive(:run).and_return(2)
         
     | 
| 
       131 
139 
     | 
    
         
             
                  Puppet[:onetime] = true
         
     | 
| 
       132 
140 
     | 
    
         | 
| 
       133 
     | 
    
         
            -
                  expect(Puppet::SSL::StateMachine).to receive(:new).with(waitforcert: 0).and_return(machine)
         
     | 
| 
      
 141 
     | 
    
         
            +
                  expect(Puppet::SSL::StateMachine).to receive(:new).with(hash_including(waitforcert: 0)).and_return(machine)
         
     | 
| 
       134 
142 
     | 
    
         | 
| 
       135 
143 
     | 
    
         
             
                  expect { execute_agent }.to exit_with 0
         
     | 
| 
       136 
144 
     | 
    
         
             
                end
         
     | 
| 
       137 
145 
     | 
    
         | 
| 
       138 
146 
     | 
    
         
             
                it "should use supplied waitforcert when --onetime is specified" do
         
     | 
| 
       139 
     | 
    
         
            -
                  allow(@ 
     | 
| 
      
 147 
     | 
    
         
            +
                  allow(@client).to receive(:run).and_return(2)
         
     | 
| 
       140 
148 
     | 
    
         
             
                  Puppet[:onetime] = true
         
     | 
| 
       141 
149 
     | 
    
         
             
                  @puppetd.handle_waitforcert(60)
         
     | 
| 
       142 
150 
     | 
    
         | 
| 
       143 
     | 
    
         
            -
                  expect(Puppet::SSL::StateMachine).to receive(:new).with(waitforcert: 60).and_return(machine)
         
     | 
| 
      
 151 
     | 
    
         
            +
                  expect(Puppet::SSL::StateMachine).to receive(:new).with(hash_including(waitforcert: 60)).and_return(machine)
         
     | 
| 
       144 
152 
     | 
    
         | 
| 
       145 
153 
     | 
    
         
             
                  expect { execute_agent }.to exit_with 0
         
     | 
| 
       146 
154 
     | 
    
         
             
                end
         
     | 
| 
       147 
155 
     | 
    
         | 
| 
       148 
156 
     | 
    
         
             
                it "should use a default value for waitforcert when --onetime and --waitforcert are not specified" do
         
     | 
| 
       149 
     | 
    
         
            -
                   
     | 
| 
      
 157 
     | 
    
         
            +
                  allow(@client).to receive(:run).and_return(2)
         
     | 
| 
      
 158 
     | 
    
         
            +
             
     | 
| 
      
 159 
     | 
    
         
            +
                  expect(Puppet::SSL::StateMachine).to receive(:new).with(hash_including(waitforcert: 120)).and_return(machine)
         
     | 
| 
       150 
160 
     | 
    
         | 
| 
       151 
161 
     | 
    
         
             
                  execute_agent
         
     | 
| 
       152 
162 
     | 
    
         
             
                end
         
     | 
| 
       153 
163 
     | 
    
         | 
| 
       154 
164 
     | 
    
         
             
                it "should register ssl OIDs" do
         
     | 
| 
       155 
     | 
    
         
            -
                  expect(Puppet::SSL::StateMachine).to receive(:new).with(waitforcert: 120).and_return( 
     | 
| 
      
 165 
     | 
    
         
            +
                  expect(Puppet::SSL::StateMachine).to receive(:new).with(hash_including(waitforcert: 120)).and_return(machine)
         
     | 
| 
       156 
166 
     | 
    
         
             
                  expect(Puppet::SSL::Oids).to receive(:register_puppet_oids)
         
     | 
| 
       157 
167 
     | 
    
         | 
| 
       158 
168 
     | 
    
         
             
                  execute_agent
         
     | 
| 
         @@ -161,7 +171,7 @@ describe Puppet::Application::Agent do 
     | 
|
| 
       161 
171 
     | 
    
         
             
                it "should use the waitforcert setting when checking for a signed certificate" do
         
     | 
| 
       162 
172 
     | 
    
         
             
                  Puppet[:waitforcert] = 10
         
     | 
| 
       163 
173 
     | 
    
         | 
| 
       164 
     | 
    
         
            -
                  expect(Puppet::SSL::StateMachine).to receive(:new).with(waitforcert: 10).and_return(machine)
         
     | 
| 
      
 174 
     | 
    
         
            +
                  expect(Puppet::SSL::StateMachine).to receive(:new).with(hash_including(waitforcert: 10)).and_return(machine)
         
     | 
| 
       165 
175 
     | 
    
         | 
| 
       166 
176 
     | 
    
         
             
                  execute_agent
         
     | 
| 
       167 
177 
     | 
    
         
             
                end
         
     | 
| 
         @@ -413,9 +423,9 @@ describe Puppet::Application::Agent do 
     | 
|
| 
       413 
423 
     | 
    
         
             
                end
         
     | 
| 
       414 
424 
     | 
    
         | 
| 
       415 
425 
     | 
    
         
             
                it "should wait for a certificate" do
         
     | 
| 
       416 
     | 
    
         
            -
                   
     | 
| 
      
 426 
     | 
    
         
            +
                  Puppet[:waitforcert] = 123
         
     | 
| 
       417 
427 
     | 
    
         | 
| 
       418 
     | 
    
         
            -
                  expect(Puppet::SSL::StateMachine).to receive(:new).with(waitforcert: 123).and_return(machine)
         
     | 
| 
      
 428 
     | 
    
         
            +
                  expect(Puppet::SSL::StateMachine).to receive(:new).with(hash_including(waitforcert: 123)).and_return(machine)
         
     | 
| 
       419 
429 
     | 
    
         | 
| 
       420 
430 
     | 
    
         
             
                  execute_agent
         
     | 
| 
       421 
431 
     | 
    
         
             
                end
         
     | 
    
        data/spec/unit/daemon_spec.rb
    CHANGED
    
    | 
         @@ -1,6 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            require 'spec_helper'
         
     | 
| 
       2 
2 
     | 
    
         
             
            require 'puppet/daemon'
         
     | 
| 
       3 
3 
     | 
    
         
             
            require 'puppet/agent'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'puppet/configurer'
         
     | 
| 
       4 
5 
     | 
    
         | 
| 
       5 
6 
     | 
    
         
             
            def without_warnings
         
     | 
| 
       6 
7 
     | 
    
         
             
              flag = $VERBOSE
         
     | 
| 
         @@ -9,12 +10,6 @@ def without_warnings 
     | 
|
| 
       9 
10 
     | 
    
         
             
              $VERBOSE = flag
         
     | 
| 
       10 
11 
     | 
    
         
             
            end
         
     | 
| 
       11 
12 
     | 
    
         | 
| 
       12 
     | 
    
         
            -
            class TestClient
         
     | 
| 
       13 
     | 
    
         
            -
              def lockfile_path
         
     | 
| 
       14 
     | 
    
         
            -
                "/dev/null"
         
     | 
| 
       15 
     | 
    
         
            -
              end
         
     | 
| 
       16 
     | 
    
         
            -
            end
         
     | 
| 
       17 
     | 
    
         
            -
             
     | 
| 
       18 
13 
     | 
    
         
             
            describe Puppet::Daemon, :unless => Puppet::Util::Platform.windows? do
         
     | 
| 
       19 
14 
     | 
    
         
             
              include PuppetSpec::Files
         
     | 
| 
       20 
15 
     | 
    
         | 
| 
         @@ -26,7 +21,7 @@ describe Puppet::Daemon, :unless => Puppet::Util::Platform.windows? do 
     | 
|
| 
       26 
21 
     | 
    
         
             
                end
         
     | 
| 
       27 
22 
     | 
    
         
             
              end
         
     | 
| 
       28 
23 
     | 
    
         | 
| 
       29 
     | 
    
         
            -
              let(:agent) { Puppet::Agent.new( 
     | 
| 
      
 24 
     | 
    
         
            +
              let(:agent) { Puppet::Agent.new(Puppet::Configurer, false) }
         
     | 
| 
       30 
25 
     | 
    
         
             
              let(:server) { double("Server", :start => nil, :wait_for_shutdown => nil) }
         
     | 
| 
       31 
26 
     | 
    
         | 
| 
       32 
27 
     | 
    
         
             
              let(:pidfile) { double("PidFile", :lock => true, :unlock => true, :file_path => 'fake.pid') }
         
     | 
| 
         @@ -131,10 +126,6 @@ describe Puppet::Daemon, :unless => Puppet::Util::Platform.windows? do 
     | 
|
| 
       131 
126 
     | 
    
         
             
              end
         
     | 
| 
       132 
127 
     | 
    
         | 
| 
       133 
128 
     | 
    
         
             
              describe "when reloading" do
         
     | 
| 
       134 
     | 
    
         
            -
                it "should do nothing if no agent is configured" do
         
     | 
| 
       135 
     | 
    
         
            -
                  daemon.reload
         
     | 
| 
       136 
     | 
    
         
            -
                end
         
     | 
| 
       137 
     | 
    
         
            -
             
     | 
| 
       138 
129 
     | 
    
         
             
                it "should do nothing if the agent is running" do
         
     | 
| 
       139 
130 
     | 
    
         
             
                  expect(agent).to receive(:run).with({:splay => false}).and_raise(Puppet::LockError, 'Failed to aquire lock')
         
     | 
| 
       140 
131 
     | 
    
         
             
                  expect(Puppet).to receive(:notice).with('Not triggering already-running agent')
         
     | 
| 
         @@ -227,4 +227,30 @@ describe "puppet module list" do 
     | 
|
| 
       227 
227 
     | 
    
         
             
                  console_output(:tree => true)
         
     | 
| 
       228 
228 
     | 
    
         
             
                end
         
     | 
| 
       229 
229 
     | 
    
         
             
              end
         
     | 
| 
      
 230 
     | 
    
         
            +
             
     | 
| 
      
 231 
     | 
    
         
            +
              describe "when rendering as json" do
         
     | 
| 
      
 232 
     | 
    
         
            +
                let(:face) { Puppet::Face[:module, :current] }
         
     | 
| 
      
 233 
     | 
    
         
            +
                let(:action) { face.get_action(:list) }
         
     | 
| 
      
 234 
     | 
    
         
            +
             
     | 
| 
      
 235 
     | 
    
         
            +
                it "should warn about missing dependencies" do
         
     | 
| 
      
 236 
     | 
    
         
            +
                  PuppetSpec::Modules.create('depender', @modpath1, :metadata => {
         
     | 
| 
      
 237 
     | 
    
         
            +
                    :version => '1.0.0',
         
     | 
| 
      
 238 
     | 
    
         
            +
                    :dependencies => [{
         
     | 
| 
      
 239 
     | 
    
         
            +
                      "version_requirement" => ">= 0.0.5",
         
     | 
| 
      
 240 
     | 
    
         
            +
                      "name"                => "puppetlabs/dependable"
         
     | 
| 
      
 241 
     | 
    
         
            +
                    }]
         
     | 
| 
      
 242 
     | 
    
         
            +
                  })
         
     | 
| 
      
 243 
     | 
    
         
            +
             
     | 
| 
      
 244 
     | 
    
         
            +
                  result = face.list
         
     | 
| 
      
 245 
     | 
    
         
            +
                  expect(result.dig(:unmet_dependencies, :missing)).to include(
         
     | 
| 
      
 246 
     | 
    
         
            +
                    "puppetlabs/dependable" => {
         
     | 
| 
      
 247 
     | 
    
         
            +
                      errors: ["'puppetlabs-depender' (v1.0.0) requires 'puppetlabs-dependable' (>= 0.0.5)"],
         
     | 
| 
      
 248 
     | 
    
         
            +
                      parent: {
         
     | 
| 
      
 249 
     | 
    
         
            +
                        name: "puppetlabs/depender", :version=>"v1.0.0"
         
     | 
| 
      
 250 
     | 
    
         
            +
                      },
         
     | 
| 
      
 251 
     | 
    
         
            +
                      version: nil
         
     | 
| 
      
 252 
     | 
    
         
            +
                    }
         
     | 
| 
      
 253 
     | 
    
         
            +
                  )
         
     | 
| 
      
 254 
     | 
    
         
            +
                end
         
     | 
| 
      
 255 
     | 
    
         
            +
              end
         
     | 
| 
       230 
256 
     | 
    
         
             
            end
         
     | 
| 
         @@ -120,6 +120,24 @@ describe Puppet::HTTP::Client do 
     | 
|
| 
       120 
120 
     | 
    
         | 
| 
       121 
121 
     | 
    
         
             
                  client.close
         
     | 
| 
       122 
122 
     | 
    
         
             
                end
         
     | 
| 
      
 123 
     | 
    
         
            +
             
     | 
| 
      
 124 
     | 
    
         
            +
                it 'reloads the default ssl context' do
         
     | 
| 
      
 125 
     | 
    
         
            +
                  expect(client.pool).to receive(:with_connection) do |_, verifier|
         
     | 
| 
      
 126 
     | 
    
         
            +
                    expect(verifier.ssl_context).to_not equal(puppet_context)
         
     | 
| 
      
 127 
     | 
    
         
            +
                  end
         
     | 
| 
      
 128 
     | 
    
         
            +
             
     | 
| 
      
 129 
     | 
    
         
            +
                  client.close
         
     | 
| 
      
 130 
     | 
    
         
            +
                  client.connect(uri)
         
     | 
| 
      
 131 
     | 
    
         
            +
                end
         
     | 
| 
      
 132 
     | 
    
         
            +
             
     | 
| 
      
 133 
     | 
    
         
            +
                it 'reloads the default system ssl context' do
         
     | 
| 
      
 134 
     | 
    
         
            +
                  expect(client.pool).to receive(:with_connection) do |_, verifier|
         
     | 
| 
      
 135 
     | 
    
         
            +
                    expect(verifier.ssl_context).to_not equal(system_context)
         
     | 
| 
      
 136 
     | 
    
         
            +
                  end
         
     | 
| 
      
 137 
     | 
    
         
            +
             
     | 
| 
      
 138 
     | 
    
         
            +
                  client.close
         
     | 
| 
      
 139 
     | 
    
         
            +
                  client.connect(uri, options: {include_system_store: true})
         
     | 
| 
      
 140 
     | 
    
         
            +
                end
         
     | 
| 
       123 
141 
     | 
    
         
             
              end
         
     | 
| 
       124 
142 
     | 
    
         | 
| 
       125 
143 
     | 
    
         
             
              context "for GET requests" do
         
     | 
| 
         @@ -11,6 +11,9 @@ describe "Puppet::InfoService" do 
     | 
|
| 
       11 
11 
     | 
    
         | 
| 
       12 
12 
     | 
    
         
             
              context 'task information service' do
         
     | 
| 
       13 
13 
     | 
    
         
             
                let(:mod_name) { 'test1' }
         
     | 
| 
      
 14 
     | 
    
         
            +
                let(:metadata) {
         
     | 
| 
      
 15 
     | 
    
         
            +
                  { "private" => true,
         
     | 
| 
      
 16 
     | 
    
         
            +
                    "description" => "a task that does a thing" } }
         
     | 
| 
       14 
17 
     | 
    
         
             
                let(:task_name) { "#{mod_name}::thingtask" }
         
     | 
| 
       15 
18 
     | 
    
         
             
                let(:modpath) { tmpdir('modpath') }
         
     | 
| 
       16 
19 
     | 
    
         
             
                let(:env_name) { 'testing' }
         
     | 
| 
         @@ -20,8 +23,13 @@ describe "Puppet::InfoService" do 
     | 
|
| 
       20 
23 
     | 
    
         
             
                context 'tasks_per_environment method' do
         
     | 
| 
       21 
24 
     | 
    
         
             
                  it "returns task data for the tasks in an environment" do
         
     | 
| 
       22 
25 
     | 
    
         
             
                    Puppet.override(:environments => env_loader) do
         
     | 
| 
       23 
     | 
    
         
            -
                      PuppetSpec::Modules.create(mod_name, modpath, {:environment => env, 
     | 
| 
       24 
     | 
    
         
            -
             
     | 
| 
      
 26 
     | 
    
         
            +
                      PuppetSpec::Modules.create(mod_name, modpath, {:environment => env,
         
     | 
| 
      
 27 
     | 
    
         
            +
                                                                     :tasks => [['thingtask',
         
     | 
| 
      
 28 
     | 
    
         
            +
                                                                                 {:name => 'thingtask.json',
         
     | 
| 
      
 29 
     | 
    
         
            +
                                                                                  :content => metadata.to_json}]]})
         
     | 
| 
      
 30 
     | 
    
         
            +
                      expect(Puppet::InfoService.tasks_per_environment(env_name)).to eq([{:name => task_name,
         
     | 
| 
      
 31 
     | 
    
         
            +
                                                                                          :module => {:name => mod_name},
         
     | 
| 
      
 32 
     | 
    
         
            +
                                                                                          :metadata => metadata}  ])
         
     | 
| 
       25 
33 
     | 
    
         
             
                    end
         
     | 
| 
       26 
34 
     | 
    
         
             
                  end
         
     | 
| 
       27 
35 
     | 
    
         | 
| 
         @@ -207,7 +215,7 @@ describe "Puppet::InfoService" do 
     | 
|
| 
       207 
215 
     | 
    
         
             
                  end
         
     | 
| 
       208 
216 
     | 
    
         
             
                end
         
     | 
| 
       209 
217 
     | 
    
         
             
              end
         
     | 
| 
       210 
     | 
    
         
            -
             
     | 
| 
      
 218 
     | 
    
         
            +
             
     | 
| 
       211 
219 
     | 
    
         
             
              context 'plan information service' do
         
     | 
| 
       212 
220 
     | 
    
         
             
                let(:mod_name) { 'test1' }
         
     | 
| 
       213 
221 
     | 
    
         
             
                let(:plan_name) { "#{mod_name}::thingplan" }
         
     | 
| 
         @@ -17,4 +17,30 @@ describe Puppet::Pops::Evaluator::DeferredResolver do 
     | 
|
| 
       17 
17 
     | 
    
         | 
| 
       18 
18 
     | 
    
         
             
                expect(catalog.resource(:notify, 'deferred')[:message]).to eq('1:2:3')
         
     | 
| 
       19 
19 
     | 
    
         
             
              end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
              it 'lazily resolves deferred values in a catalog' do
         
     | 
| 
      
 22 
     | 
    
         
            +
                catalog = compile_to_catalog(<<~END)
         
     | 
| 
      
 23 
     | 
    
         
            +
                  notify { "deferred":
         
     | 
| 
      
 24 
     | 
    
         
            +
                    message => Deferred("join", [[1,2,3], ":"])
         
     | 
| 
      
 25 
     | 
    
         
            +
                  }
         
     | 
| 
      
 26 
     | 
    
         
            +
                END
         
     | 
| 
      
 27 
     | 
    
         
            +
                described_class.resolve_and_replace(facts, catalog, environment, false)
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                deferred = catalog.resource(:notify, 'deferred')[:message]
         
     | 
| 
      
 30 
     | 
    
         
            +
                expect(deferred.resolve).to eq('1:2:3')
         
     | 
| 
      
 31 
     | 
    
         
            +
              end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
              it 'lazily resolves nested deferred values in a catalog' do
         
     | 
| 
      
 34 
     | 
    
         
            +
                catalog = compile_to_catalog(<<~END)
         
     | 
| 
      
 35 
     | 
    
         
            +
                  $args = Deferred("inline_epp", ["<%= 'a,b,c' %>"])
         
     | 
| 
      
 36 
     | 
    
         
            +
                  notify { "deferred":
         
     | 
| 
      
 37 
     | 
    
         
            +
                    message => Deferred("split", [$args, ","])
         
     | 
| 
      
 38 
     | 
    
         
            +
                  }
         
     | 
| 
      
 39 
     | 
    
         
            +
                END
         
     | 
| 
      
 40 
     | 
    
         
            +
                described_class.resolve_and_replace(facts, catalog, environment, false)
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                deferred = catalog.resource(:notify, 'deferred')[:message]
         
     | 
| 
      
 43 
     | 
    
         
            +
                expect(deferred.resolve).to eq(["a", "b", "c"])
         
     | 
| 
      
 44 
     | 
    
         
            +
              end
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
       20 
46 
     | 
    
         
             
            end
         
     | 
| 
         @@ -606,7 +606,7 @@ describe 'loaders' do 
     | 
|
| 
       606 
606 
     | 
    
         
             
                it "an illegal function is loaded" do
         
     | 
| 
       607 
607 
     | 
    
         
             
                  expect {
         
     | 
| 
       608 
608 
     | 
    
         
             
                    loader.load_typed(typed_name(:function, 'bad_func_load3')).value
         
     | 
| 
       609 
     | 
    
         
            -
                  }.to raise_error(SecurityError, /Illegal method definition of method 'bad_func_load3_illegal_method' on line 8 in legacy function/)
         
     | 
| 
      
 609 
     | 
    
         
            +
                  }.to raise_error(SecurityError, /Illegal method definition of method 'bad_func_load3_illegal_method' in source .*bad_func_load3.rb on line 8 in legacy function/)
         
     | 
| 
       610 
610 
     | 
    
         
             
                end
         
     | 
| 
       611 
611 
     | 
    
         
             
              end
         
     | 
| 
       612 
612 
     | 
    
         | 
| 
         @@ -1,12 +1,178 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            require 'spec_helper'
         
     | 
| 
       2 
2 
     | 
    
         
             
            require 'puppet/pops'
         
     | 
| 
       3 
3 
     | 
    
         
             
            require 'puppet_spec/compiler'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'puppet_spec/files'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'puppet/loaders'
         
     | 
| 
       4 
6 
     | 
    
         | 
| 
       5 
7 
     | 
    
         
             
            module Puppet::Pops
         
     | 
| 
       6 
8 
     | 
    
         
             
            module Types
         
     | 
| 
       7 
9 
     | 
    
         | 
| 
       8 
10 
     | 
    
         
             
            describe 'the type mismatch describer' do
         
     | 
| 
       9 
     | 
    
         
            -
              include PuppetSpec::Compiler
         
     | 
| 
      
 11 
     | 
    
         
            +
              include PuppetSpec::Compiler, PuppetSpec::Files
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
              context 'with deferred functions' do
         
     | 
| 
      
 14 
     | 
    
         
            +
                let(:env_name) { 'spec' }
         
     | 
| 
      
 15 
     | 
    
         
            +
                let(:code_dir) { Puppet[:environmentpath] }
         
     | 
| 
      
 16 
     | 
    
         
            +
                let(:env_dir) { File.join(code_dir, env_name) }
         
     | 
| 
      
 17 
     | 
    
         
            +
                let(:env) { Puppet::Node::Environment.create(env_name.to_sym, [File.join(populated_code_dir, env_name, 'modules')]) }
         
     | 
| 
      
 18 
     | 
    
         
            +
                let(:node) { Puppet::Node.new('fooname', environment: env) }
         
     | 
| 
      
 19 
     | 
    
         
            +
                let(:populated_code_dir) do
         
     | 
| 
      
 20 
     | 
    
         
            +
                  dir_contained_in(code_dir, env_name => env_content)
         
     | 
| 
      
 21 
     | 
    
         
            +
                  PuppetSpec::Files.record_tmp(env_dir)
         
     | 
| 
      
 22 
     | 
    
         
            +
                  code_dir
         
     | 
| 
      
 23 
     | 
    
         
            +
                end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                let(:env_content) {
         
     | 
| 
      
 26 
     | 
    
         
            +
                  {
         
     | 
| 
      
 27 
     | 
    
         
            +
                    'lib' => {
         
     | 
| 
      
 28 
     | 
    
         
            +
                      'puppet' => {
         
     | 
| 
      
 29 
     | 
    
         
            +
                        'functions' => {
         
     | 
| 
      
 30 
     | 
    
         
            +
                          'string_return.rb' => <<-RUBY.unindent,
         
     | 
| 
      
 31 
     | 
    
         
            +
                          Puppet::Functions.create_function(:string_return) do
         
     | 
| 
      
 32 
     | 
    
         
            +
                            dispatch :string_return do
         
     | 
| 
      
 33 
     | 
    
         
            +
                              param 'String', :arg1
         
     | 
| 
      
 34 
     | 
    
         
            +
                              return_type 'String'
         
     | 
| 
      
 35 
     | 
    
         
            +
                            end
         
     | 
| 
      
 36 
     | 
    
         
            +
                            def string_return(arg1)
         
     | 
| 
      
 37 
     | 
    
         
            +
                              arg1
         
     | 
| 
      
 38 
     | 
    
         
            +
                            end
         
     | 
| 
      
 39 
     | 
    
         
            +
                          end
         
     | 
| 
      
 40 
     | 
    
         
            +
                          RUBY
         
     | 
| 
      
 41 
     | 
    
         
            +
                          'variant_return.rb' => <<-RUBY.unindent,
         
     | 
| 
      
 42 
     | 
    
         
            +
                          Puppet::Functions.create_function(:variant_return) do
         
     | 
| 
      
 43 
     | 
    
         
            +
                            dispatch :variant_return do
         
     | 
| 
      
 44 
     | 
    
         
            +
                              param 'String', :arg1
         
     | 
| 
      
 45 
     | 
    
         
            +
                              return_type 'Variant[Integer,Float]'
         
     | 
| 
      
 46 
     | 
    
         
            +
                            end
         
     | 
| 
      
 47 
     | 
    
         
            +
                            def variant_return(arg1)
         
     | 
| 
      
 48 
     | 
    
         
            +
                              arg1
         
     | 
| 
      
 49 
     | 
    
         
            +
                            end
         
     | 
| 
      
 50 
     | 
    
         
            +
                          end
         
     | 
| 
      
 51 
     | 
    
         
            +
                          RUBY
         
     | 
| 
      
 52 
     | 
    
         
            +
                          'no_return.rb' => <<-RUBY.unindent,
         
     | 
| 
      
 53 
     | 
    
         
            +
                          Puppet::Functions.create_function(:no_return) do
         
     | 
| 
      
 54 
     | 
    
         
            +
                            dispatch :no_return do
         
     | 
| 
      
 55 
     | 
    
         
            +
                              param 'String', :arg1
         
     | 
| 
      
 56 
     | 
    
         
            +
                            end
         
     | 
| 
      
 57 
     | 
    
         
            +
                            def variant_return(arg1)
         
     | 
| 
      
 58 
     | 
    
         
            +
                              arg1
         
     | 
| 
      
 59 
     | 
    
         
            +
                            end
         
     | 
| 
      
 60 
     | 
    
         
            +
                          end
         
     | 
| 
      
 61 
     | 
    
         
            +
                          RUBY
         
     | 
| 
      
 62 
     | 
    
         
            +
                        }
         
     | 
| 
      
 63 
     | 
    
         
            +
                      }
         
     | 
| 
      
 64 
     | 
    
         
            +
                    }
         
     | 
| 
      
 65 
     | 
    
         
            +
                  }
         
     | 
| 
      
 66 
     | 
    
         
            +
                }
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                before(:each) do
         
     | 
| 
      
 69 
     | 
    
         
            +
                  Puppet.push_context(:loaders => Puppet::Pops::Loaders.new(env))
         
     | 
| 
      
 70 
     | 
    
         
            +
                end
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
                after(:each) do
         
     | 
| 
      
 73 
     | 
    
         
            +
                  Puppet.pop_context
         
     | 
| 
      
 74 
     | 
    
         
            +
                end
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
                it 'will compile when the parameter type matches the function return_type' do
         
     | 
| 
      
 77 
     | 
    
         
            +
                  code = <<-CODE
         
     | 
| 
      
 78 
     | 
    
         
            +
                    $d = Deferred("string_return", ['/a/non/existing/path'])
         
     | 
| 
      
 79 
     | 
    
         
            +
                    class testclass(String $classparam) {
         
     | 
| 
      
 80 
     | 
    
         
            +
                    }
         
     | 
| 
      
 81 
     | 
    
         
            +
                    class { 'testclass':
         
     | 
| 
      
 82 
     | 
    
         
            +
                      classparam => $d
         
     | 
| 
      
 83 
     | 
    
         
            +
                    }
         
     | 
| 
      
 84 
     | 
    
         
            +
                  CODE
         
     | 
| 
      
 85 
     | 
    
         
            +
                  expect { eval_and_collect_notices(code, node) }.to_not raise_error
         
     | 
| 
      
 86 
     | 
    
         
            +
                end
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
                it "will compile when a Variant parameter's types matches the return type" do
         
     | 
| 
      
 89 
     | 
    
         
            +
                  code = <<-CODE
         
     | 
| 
      
 90 
     | 
    
         
            +
                    $d = Deferred("string_return", ['/a/non/existing/path'])
         
     | 
| 
      
 91 
     | 
    
         
            +
                    class testclass(Variant[String, Float] $classparam) {
         
     | 
| 
      
 92 
     | 
    
         
            +
                    }
         
     | 
| 
      
 93 
     | 
    
         
            +
                    class { 'testclass':
         
     | 
| 
      
 94 
     | 
    
         
            +
                      classparam => $d
         
     | 
| 
      
 95 
     | 
    
         
            +
                    }
         
     | 
| 
      
 96 
     | 
    
         
            +
                  CODE
         
     | 
| 
      
 97 
     | 
    
         
            +
                  expect { eval_and_collect_notices(code, node) }.to_not raise_error
         
     | 
| 
      
 98 
     | 
    
         
            +
                end
         
     | 
| 
      
 99 
     | 
    
         
            +
             
     | 
| 
      
 100 
     | 
    
         
            +
                it "will compile with a union of a Variant parameters' types and Variant return types" do
         
     | 
| 
      
 101 
     | 
    
         
            +
                  code = <<-CODE
         
     | 
| 
      
 102 
     | 
    
         
            +
                    $d = Deferred("variant_return", ['/a/non/existing/path'])
         
     | 
| 
      
 103 
     | 
    
         
            +
                    class testclass(Variant[Any,Float] $classparam) {
         
     | 
| 
      
 104 
     | 
    
         
            +
                    }
         
     | 
| 
      
 105 
     | 
    
         
            +
                    class { 'testclass':
         
     | 
| 
      
 106 
     | 
    
         
            +
                      classparam => $d
         
     | 
| 
      
 107 
     | 
    
         
            +
                    }
         
     | 
| 
      
 108 
     | 
    
         
            +
                  CODE
         
     | 
| 
      
 109 
     | 
    
         
            +
                  expect { eval_and_collect_notices(code, node) }.to_not raise_error
         
     | 
| 
      
 110 
     | 
    
         
            +
                end
         
     | 
| 
      
 111 
     | 
    
         
            +
             
     | 
| 
      
 112 
     | 
    
         
            +
                it 'will warn when there is no defined return_type for the function definition' do
         
     | 
| 
      
 113 
     | 
    
         
            +
                  code = <<-CODE
         
     | 
| 
      
 114 
     | 
    
         
            +
                    $d = Deferred("no_return", ['/a/non/existing/path'])
         
     | 
| 
      
 115 
     | 
    
         
            +
                    class testclass(Variant[String,Boolean] $classparam) {
         
     | 
| 
      
 116 
     | 
    
         
            +
                    }
         
     | 
| 
      
 117 
     | 
    
         
            +
                    class { 'testclass':
         
     | 
| 
      
 118 
     | 
    
         
            +
                      classparam => $d
         
     | 
| 
      
 119 
     | 
    
         
            +
                    }
         
     | 
| 
      
 120 
     | 
    
         
            +
                  CODE
         
     | 
| 
      
 121 
     | 
    
         
            +
                  expect(Puppet).to receive(:warn_once).with(anything, anything, /.+function no_return has no return_type/).at_least(:once)
         
     | 
| 
      
 122 
     | 
    
         
            +
                  expect { eval_and_collect_notices(code, node) }.to_not raise_error
         
     | 
| 
      
 123 
     | 
    
         
            +
                end
         
     | 
| 
      
 124 
     | 
    
         
            +
             
     | 
| 
      
 125 
     | 
    
         
            +
                it 'will report a mismatch between a deferred function return type and class parameter value' do
         
     | 
| 
      
 126 
     | 
    
         
            +
                  code = <<-CODE
         
     | 
| 
      
 127 
     | 
    
         
            +
                    $d = Deferred("string_return", ['/a/non/existing/path'])
         
     | 
| 
      
 128 
     | 
    
         
            +
                    class testclass(Integer $classparam) {
         
     | 
| 
      
 129 
     | 
    
         
            +
                    }
         
     | 
| 
      
 130 
     | 
    
         
            +
                    class { 'testclass':
         
     | 
| 
      
 131 
     | 
    
         
            +
                      classparam => $d
         
     | 
| 
      
 132 
     | 
    
         
            +
                    }
         
     | 
| 
      
 133 
     | 
    
         
            +
                  CODE
         
     | 
| 
      
 134 
     | 
    
         
            +
                  expect { eval_and_collect_notices(code, node) }.to raise_error(Puppet::Error, /.+'classparam' expects an Integer value, got String/)
         
     | 
| 
      
 135 
     | 
    
         
            +
                end
         
     | 
| 
      
 136 
     | 
    
         
            +
             
     | 
| 
      
 137 
     | 
    
         
            +
                it 'will report an argument error when no matching arity is found' do
         
     | 
| 
      
 138 
     | 
    
         
            +
                  code = <<-CODE
         
     | 
| 
      
 139 
     | 
    
         
            +
                    $d = Deferred("string_return", ['/a/non/existing/path', 'second-invalid-arg'])
         
     | 
| 
      
 140 
     | 
    
         
            +
                    class testclass(Integer $classparam) {
         
     | 
| 
      
 141 
     | 
    
         
            +
                    }
         
     | 
| 
      
 142 
     | 
    
         
            +
                    class { 'testclass':
         
     | 
| 
      
 143 
     | 
    
         
            +
                      classparam => $d
         
     | 
| 
      
 144 
     | 
    
         
            +
                    }
         
     | 
| 
      
 145 
     | 
    
         
            +
                  CODE
         
     | 
| 
      
 146 
     | 
    
         
            +
                  expect { eval_and_collect_notices(code,node) }.to raise_error(Puppet::Error, /.+ No matching arity found for string_return/)
         
     | 
| 
      
 147 
     | 
    
         
            +
                end
         
     | 
| 
      
 148 
     | 
    
         
            +
             
     | 
| 
      
 149 
     | 
    
         
            +
                it 'will error with no matching Variant class parameters and return_type' do
         
     | 
| 
      
 150 
     | 
    
         
            +
                  code = <<-CODE
         
     | 
| 
      
 151 
     | 
    
         
            +
                    $d = Deferred("string_return", ['/a/non/existing/path'])
         
     | 
| 
      
 152 
     | 
    
         
            +
                    class testclass(Variant[Integer,Float] $classparam) {
         
     | 
| 
      
 153 
     | 
    
         
            +
                    }
         
     | 
| 
      
 154 
     | 
    
         
            +
                    class { 'testclass':
         
     | 
| 
      
 155 
     | 
    
         
            +
                      classparam => $d
         
     | 
| 
      
 156 
     | 
    
         
            +
                    }
         
     | 
| 
      
 157 
     | 
    
         
            +
                  CODE
         
     | 
| 
      
 158 
     | 
    
         
            +
                  expect { eval_and_collect_notices(code,node) }.to raise_error(Puppet::Error, /.+'classparam' expects a value of type Integer or Float, got String/)
         
     | 
| 
      
 159 
     | 
    
         
            +
                end
         
     | 
| 
      
 160 
     | 
    
         
            +
             
     | 
| 
      
 161 
     | 
    
         
            +
                # This test exposes a shortcoming in the #message function for Puppet::Pops::Type::TypeMismatch
         
     | 
| 
      
 162 
     | 
    
         
            +
                # where the `actual` is not introspected for the list of Variant types, so the error message
         
     | 
| 
      
 163 
     | 
    
         
            +
                # shows that the list of expected types does not match Variant, instead of a list of actual types.
         
     | 
| 
      
 164 
     | 
    
         
            +
                it 'will error with no matching Variant class parameters and Variant return_type' do
         
     | 
| 
      
 165 
     | 
    
         
            +
                  code = <<-CODE
         
     | 
| 
      
 166 
     | 
    
         
            +
                    $d = Deferred("variant_return", ['/a/non/existing/path'])
         
     | 
| 
      
 167 
     | 
    
         
            +
                    class testclass(Variant[String,Boolean] $classparam) {
         
     | 
| 
      
 168 
     | 
    
         
            +
                    }
         
     | 
| 
      
 169 
     | 
    
         
            +
                    class { 'testclass':
         
     | 
| 
      
 170 
     | 
    
         
            +
                      classparam => $d
         
     | 
| 
      
 171 
     | 
    
         
            +
                    }
         
     | 
| 
      
 172 
     | 
    
         
            +
                  CODE
         
     | 
| 
      
 173 
     | 
    
         
            +
                  expect { eval_and_collect_notices(code, node) }.to raise_error(Puppet::Error, /.+'classparam' expects a value of type String or Boolean, got Variant/)
         
     | 
| 
      
 174 
     | 
    
         
            +
                end
         
     | 
| 
      
 175 
     | 
    
         
            +
              end
         
     | 
| 
       10 
176 
     | 
    
         | 
| 
       11 
177 
     | 
    
         
             
              it 'will report a mismatch between a hash and a struct with details' do
         
     | 
| 
       12 
178 
     | 
    
         
             
                code = <<-CODE
         
     |