SlideShare a Scribd company logo
2014 
Presented by 
The Grand Puppet 
Sub-Systems Tour 
Nick Fagerlund 
Technical Writer / Weird Bugs | Puppet 
Labs 
@nfagerlund
Presented by 
PIPES
Presented by 
What does Puppet DO? 
• Gather system information 
• Compile a catalog 
• Apply catalog 
• Report
Presented by 
What does Puppet DO? 
AGENT 
• Gather system 
information 
• Apply catalog 
• Report 
MASTER 
• Compile a catalog
STOP 1: Command Line and the 
Presented by
Presented by 
Someone ran puppet agent
Presented by 
??? 
• /opt/puppet/bin/puppet 
• Puppet::Util::CommandLine.new.execute 
• Puppet::Application.find 
• Puppet::Application::Agent.new 
• Puppet::Application::Agent#setup 
• Puppet::Application::Agent#run_command
Presented by 
#run_command 
# 
lib/puppet/application/agent.rb 
def 
run_command 
if 
options[:fingerprint] 
fingerprint 
else 
# 
It'd 
be 
nice 
to 
daemonize 
later, 
but 
we 
have 
to 
daemonize 
before 
# 
waiting 
for 
certificates 
so 
that 
we 
don't 
block 
daemon 
= 
daemonize_process_when(Puppet[:daemonize]) 
! 
wait_for_certificates 
! 
if 
Puppet[:onetime] 
onetime(daemon) 
else 
main(daemon) 
end
Presented by 
onetime() and main() 
# 
lib/puppet/application/agent.rb 
begin 
exitstatus 
= 
daemon.agent.run 
rescue 
=> 
detail 
Puppet.log_exception(detail) 
end 
! 
daemon.stop(:exit 
=> 
false) 
! 
if 
not 
exitstatus 
exit(1) 
elsif 
options[:detailed_exitcodes] 
then 
exit(exitstatus) 
else 
exit(0) 
end 
# 
lib/puppet/application/agent.rb 
def 
main(daemon) 
if 
Puppet[:listen] 
setup_listen(daemon) 
end 
Puppet.notice 
"Starting 
Puppet 
client 
version 
#{Puppet.version}" 
! 
daemon.start 
end
Presented by 
Obtaining the daemon 
# 
lib/puppet/application/agent.rb 
def 
daemonize_process_when(should_daemonize) 
daemon 
= 
Puppet::Daemon.new(Puppet::Util::Pidlock.new(Puppet[:pidfile])) 
daemon.argv 
= 
@argv 
daemon.agent 
= 
@agent 
! 
daemon.daemonize 
if 
should_daemonize 
! 
daemon 
end
STOP 2: The Daemon and the 
Presented by
Presented by 
DAEMON LAND?! 
Nope 
Bye
Presented by 
Puppet::Agent 
• Run a thing
Presented by 
Puppet::Daemon 
• Run a thing that runs the other thing
Lots of layers of abstraction?? 
• Historical reasons! 
Presented by
Presented by 
STOP 3: The Configurer
Presented by 
Puppet::Configurer
Puppet::Configurer#run_internal 
Presented by 
# 
lib/puppet/configurer.rb 
def 
run_internal(options) 
# 
We 
create 
the 
report 
pre-­‐populated 
with 
default 
settings 
for 
# 
environment 
and 
transaction_uuid 
very 
early, 
this 
is 
to 
ensure 
# 
they 
are 
sent 
regardless 
of 
any 
catalog 
compilation 
failures 
or 
# 
exceptions. 
options[:report] 
||= 
Puppet::Transaction::Report.new("apply", 
nil, 
@environment, 
@transaction_uuid) 
report 
= 
options[:report] 
init_storage 
! 
Puppet::Util::Log.newdestination(report) 
… 
… 
…
Puppet::Configurer#run_internal 
Presented by 
# 
lib/puppet/configurer.rb 
… 
query_options 
= 
get_facts(options) 
unless 
query_options 
…
Puppet::Configurer#run_internal 
Presented by 
# 
lib/puppet/configurer/fact_handler.rb 
… 
facts 
= 
Puppet::Node::Facts.indirection.find(Puppet[:node_name_value], 
:environment 
=> 
@environment) 
…
Puppet::Configurer#run_internal 
Presented by 
# 
lib/puppet/configurer.rb 
… 
unless 
catalog 
= 
prepare_and_retrieve_catalog(options, 
query_options) 
return 
nil 
end 
…
Puppet::Configurer#run_internal 
Presented by 
# 
lib/puppet/configurer.rb 
… 
apply_catalog(catalog, 
options) 
…
Presented by 
Where next? 
Retrieve Apply
STOP 4: The Transaction 
Presented by
Presented by 
(Puppet::Resource::Catalog)
Presented by 
Puppet::Resource::Catalog 
Catalog 
Resource Other 
Stuff
Presented by 
Puppet::Configurer (again) 
# 
lib/puppet/configurer.rb 
def 
convert_catalog(result, 
duration) 
catalog 
= 
result.to_ral 
catalog.finalize 
catalog.retrieval_duration 
= 
duration 
catalog.write_class_file 
catalog.write_resource_file 
catalog 
end
Presented by 
RAL Catalog
Presented by 
RAL Catalog 
# 
lib/puppet/resource/catalog.rb 
def 
to_catalog(convert) 
result 
= 
self.class.new(self.name, 
self.environment_instance) 
result.version 
= 
self.version 
map 
= 
{} 
resources.each 
do 
|resource| 
next 
if 
virtual_not_exported?(resource) 
next 
if 
block_given? 
and 
yield 
resource 
newres 
= 
resource.copy_as_resource 
newres.catalog 
= 
result 
if 
convert 
!= 
:to_resource 
newres 
= 
newres.to_ral 
end 
# 
We 
can't 
guarantee 
that 
resources 
don't 
munge 
their 
names 
# 
(like 
files 
do 
with 
trailing 
slashes), 
so 
we 
have 
to 
keep 
track 
# 
of 
what 
a 
resource 
got 
converted 
to. 
map[resource.ref] 
= 
newres 
result.add_resource 
newres 
end
Presented by 
RAL Catalog 
Puppet::Resource 
! 
↓ 
! 
(something) << Puppet::Type
Presented by 
RAL Catalog 
???
Presented by 
RAL Catalog 
# 
lib/puppet/configurer.rb 
def 
apply_catalog(catalog, 
options) 
report 
= 
options[:report] 
report.configuration_version 
= 
catalog.version 
! 
benchmark(:notice, 
"Finished 
catalog 
run") 
do 
catalog.apply(options) 
end 
! 
report.finalize_report 
report 
end
Puppet::Resource::Catalog#apply 
Presented by 
# 
lib/puppet/resource/catalog.rb 
def 
apply(options 
= 
{}) 
Puppet::Util::Storage.load 
if 
host_config? 
! 
transaction 
= 
create_transaction(options) 
! 
begin 
transaction.report.as_logging_destination 
do 
transaction.evaluate 
end 
rescue 
Puppet::Error 
=> 
detail 
!
Presented by 
Transaction 
???
Presented by 
Transaction 
• Ral catalog 
• Prioritizer 
• Report
Presented by 
Transaction 
• Ral catalog 
• Prioritizer 
• Report 
• Event manager 
• Resource harness 
• Relationship graph
Presented by 
Transaction 
• Ral catalog 
• Prioritizer 
• Report 
• Event manager 
• Resource harness 
• Relationship graph 
• relationship_graph.traverse
Presented by 
Transaction 
• Ral catalog 
• Prioritizer 
• Report 
• Event manager 
• Resource harness 
• Relationship graph 
• relationship_graph.traverse 
• *ollies out*
Presented by 
STOP 5: The Indirector
Presented by 
Back to Puppet::Configurer 
• #prepare_and_retrieve_catalog
Presented by 
Back to Puppet::Configurer 
# 
lib/puppet/configurer.rb 
result 
= 
Puppet::Resource::Catalog.indirection.find( 
Puppet[:node_name_value], 
query_options.merge(:ignore_cache 
=> 
true, 
:environment 
=> 
@environment, 
:fail_on_404 
=> 
true) 
)
Presented by 
The Indirector 
! 
Puppet::Resource::Catalog.indirection.find()
Presented by 
The Indirector 
← 
↑ 
↓ 
?
Presented by 
The Indirector 
• Globally configured 
• Abstract 
• Gets stuff for you
Presented by 
The Indirector 
# 
lib/puppet/resource/catalog.rb 
extend 
Puppet::Indirector 
indirects 
:catalog, 
:terminus_setting 
=> 
:catalog_terminus
Presented by 
The Indirector 
• find 
• search 
• save 
• destroy
Presented by 
The Indirector 
• find 
• search 
• save 
• destroy 
• terminus_class 
• cache_class 
• lib/puppet/indirector/…
Presented by 
Puppet Agent 
• Catalog => REST 
• Report => REST 
• Facts => Facter
Presented by 
Puppet Apply 
• Catalog => Compiler 
• Report => Processor 
• Facts => Facter
Presented by 
Avoiding the cache 
# 
lib/puppet/configurer.rb 
result 
= 
Puppet::Resource::Catalog.indirection.find( 
Puppet[:node_name_value], 
query_options.merge(:ignore_cache 
=> 
true, 
:environment 
=> 
@environment, 
:fail_on_404 
=> 
true) 
)
Presented by 
The Indirector 
• Why?
Presented by 
The Indirector 
• Why? 
• Global? Rigid?
Presented by 
The Indirector 
• Why? 
• Global? Rigid? 
• IT MAKES SENSE IN CONTEXT
Presented by 
The Indirector 
• …Catalog.find( <FACTS> ) 
• REST terminus 
• HTTP POST request to master
STOP 6: The Puppet Master’s 
Presented by
Presented by 
Rack 
Web server 
↓ 
Rack server 
↓ 
“App” object that responds to #call() 
↓ 
Actual application logic
Presented by 
config.ru 
$0 
= 
"master" 
! 
ARGV 
<< 
"-­‐-­‐rack" 
! 
ARGV 
<< 
"-­‐-­‐confdir" 
<< 
"/etc/puppet" 
ARGV 
<< 
"-­‐-­‐vardir" 
<< 
"/var/lib/puppet" 
! 
require 
'puppet/util/command_line' 
run 
Puppet::Util::CommandLine.new.execute 
!
Presented by 
Starting master w/ Rack 
# 
lib/puppet/application/master.rb 
def 
start_rack_master 
require 
'puppet/network/http/rack' 
! 
announce_start_of_master 
! 
return 
Puppet::Network::HTTP::Rack.new() 
end
Presented by 
The app object 
# 
lib/puppet/network/http/rack.rb 
class 
Puppet::Network::HTTP::Rack 
def 
call(env) 
request 
= 
Rack::Request.new(env) 
response 
= 
Rack::Response.new 
Puppet.debug 
'Handling 
request: 
%s 
%s' 
% 
[request.request_method, 
request.fullpath] 
! 
begin 
Puppet::Network::HTTP::RackREST.new.process(request, 
response) 
rescue 
=> 
detail 
# 
Send 
a 
Status 
500 
Error 
on 
unhandled 
exceptions. 
response.status 
= 
500 
response['Content-­‐Type'] 
= 
'text/plain' 
response.write 
'Internal 
Server 
Error: 
"%s"' 
% 
detail.message 
# 
log 
what 
happened 
Puppet.log_exception(detail, 
"Puppet 
Server 
(Rack): 
Internal 
Server 
Error: 
Unhandled 
Exception: 
"%s"" 
% 
detail.message) 
end 
response.finish
Presented by 
#process 
# 
lib/puppet/network/http/handler.rb 
def 
process(request, 
response) 
new_response 
= 
Puppet::Network::HTTP::Response.new(self, 
response) 
! 
request_headers 
= 
headers(request) 
request_params 
= 
params(request) 
request_method 
= 
http_method(request) 
request_path 
= 
path(request) 
… 
!
Presented by 
#process 
# 
lib/puppet/network/http/handler.rb 
if 
route 
= 
@routes.find 
{ 
|route| 
route.matches?(new_request) 
} 
route.process(new_request, 
new_response)
lib/puppet/network/http/api/v1.rb 
Presented by
lib/puppet/network/http/api/v1.rb 
• GET => indirection.find() 
• POST => indirection.find() (for catalogs) 
• (There was an issue with some servers rejecting GET 
parameters that were too long. Funny story about that.) 
• DELETE => indirection.destroy() 
• PUT => indirection.save() 
• GET to magical plural name => indirection.search() 
Presented by
Presented by 
BIG PICTURE 
Configurer calls catalog.indirection.find() 
↓ 
HTTP POST request to master 
↓ 
Request handler calls catalog.indirection.find() 
↓ 
Compiler terminus handles it 
↓
Presented by 
STOP 7: The Compiler
Presented by 
MOSTLY SKIPPING THIS 
Lexer 
↓ 
Parser 
↓ 
AST 
↓ 
Evaluator 
↓
Presented by 
THIS IS THE TEST 
“Compiler terminus to the catalog 
indirection” 
! 
???
Presented by 
THIS IS THE TEST 
GOOD WORK 
EVERYBODY!
Presented by 
Questions?
Presented by 
THANKS!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 
•Hope we’ll see you next year in 
Portland!

More Related Content

PDF
Whirlwind Tour of Puppet 4
PDF
Testing for Ops: Going Beyond the Manifest - PuppetConf 2013
PDF
Bootstrapping Puppet and Application Deployment - PuppetConf 2013
PPTX
DevOps with Fabric
PDF
BASH Variables Part 1: Basic Interpolation
PDF
Puppet Performance Profiling - CM Camp 2015
PPTX
Troubleshooting Puppet
PDF
BSDM with BASH: Command Interpolation
Whirlwind Tour of Puppet 4
Testing for Ops: Going Beyond the Manifest - PuppetConf 2013
Bootstrapping Puppet and Application Deployment - PuppetConf 2013
DevOps with Fabric
BASH Variables Part 1: Basic Interpolation
Puppet Performance Profiling - CM Camp 2015
Troubleshooting Puppet
BSDM with BASH: Command Interpolation

What's hot (20)

PDF
What we Learned Implementing Puppet at Backstop
PDF
Can you upgrade to Puppet 4.x? (Beginner) Can you upgrade to Puppet 4.x? (Beg...
PDF
Memory Manglement in Raku
PDF
Unit Testing Lots of Perl
PDF
Puppet Performance Profiling
PDF
Refactor Dance - Puppet Labs 'Best Practices'
PDF
External Data in Puppet 4
PDF
Orchestrated Functional Testing with Puppet-spec and Mspectator - PuppetConf ...
PDF
Object Trampoline: Why having not the object you want is what you need.
PDF
CPANTS: Kwalitative website and its tools
PDF
The $path to knowledge: What little it take to unit-test Perl.
PDF
Rugged Driven Development with Gauntlt
PDF
Ansible leveraging 2.0
PDF
Git::Hooks
PDF
Keeping objects healthy with Object::Exercise.
KEY
Picconf12
PPTX
Puppet camp chicago-automated_testing2
PDF
The Puppet Debugging Kit: Building Blocks for Exploration and Problem Solving...
PDF
Tracking huge files with Git LFS (GlueCon 2016)
PDF
PuppetCamp SEA 1 - Use of Puppet
What we Learned Implementing Puppet at Backstop
Can you upgrade to Puppet 4.x? (Beginner) Can you upgrade to Puppet 4.x? (Beg...
Memory Manglement in Raku
Unit Testing Lots of Perl
Puppet Performance Profiling
Refactor Dance - Puppet Labs 'Best Practices'
External Data in Puppet 4
Orchestrated Functional Testing with Puppet-spec and Mspectator - PuppetConf ...
Object Trampoline: Why having not the object you want is what you need.
CPANTS: Kwalitative website and its tools
The $path to knowledge: What little it take to unit-test Perl.
Rugged Driven Development with Gauntlt
Ansible leveraging 2.0
Git::Hooks
Keeping objects healthy with Object::Exercise.
Picconf12
Puppet camp chicago-automated_testing2
The Puppet Debugging Kit: Building Blocks for Exploration and Problem Solving...
Tracking huge files with Git LFS (GlueCon 2016)
PuppetCamp SEA 1 - Use of Puppet
Ad

Viewers also liked (6)

PDF
Automating Node Classification
PDF
Node Classifier Fundamentals - PuppetConf 2014
PPT
Rapid scaling in_the_cloud_with_puppet
ODP
Puppet Node Classifiers Talk - Patrick Buckley
ZIP
Puppet and the Model-Driven Infrastructure
PDF
SCM Puppet: from an intro to the scaling
Automating Node Classification
Node Classifier Fundamentals - PuppetConf 2014
Rapid scaling in_the_cloud_with_puppet
Puppet Node Classifiers Talk - Patrick Buckley
Puppet and the Model-Driven Infrastructure
SCM Puppet: from an intro to the scaling
Ad

Similar to The Grand Puppet Sub-Systems Tour - Nicholas Fagerlund, Puppet Labs (20)

PDF
Performance Tuning Your Puppet Infrastructure - PuppetConf 2014
PDF
Puppi. Puppet strings to the shell
PDF
Puppet getting started by Dirk Götz
PDF
Can you upgrade to Puppet 4.x?
PDF
Strategies for Puppet code upgrade and refactoring
PPTX
DevOps Hackathon: Session 3 - Test Driven Infrastructure
PDF
Lean Php Presentation
PDF
Puppet Camp Duesseldorf 2014: Martin Alfke - Can you upgrade to puppet 4.x?
PPTX
Puppet Troubleshooting
PDF
Bangpypers april-meetup-2012
PDF
Intro to-puppet
PDF
Loops and Unicorns - The Future of the Puppet Language - PuppetConf 2013
PDF
Catalyst MVC
PDF
Building Cloud Castles
PDF
Oliver hookins puppetcamp2011
PDF
Our Puppet Story (GUUG FFG 2015)
PDF
Puppet at Bazaarvoice
PDF
Orchestrated Functional Testing with Puppet-spec and Mspectator
PDF
Fabric workshop(1) - (MOSG)
PPTX
Puppet atbazaarvoice
Performance Tuning Your Puppet Infrastructure - PuppetConf 2014
Puppi. Puppet strings to the shell
Puppet getting started by Dirk Götz
Can you upgrade to Puppet 4.x?
Strategies for Puppet code upgrade and refactoring
DevOps Hackathon: Session 3 - Test Driven Infrastructure
Lean Php Presentation
Puppet Camp Duesseldorf 2014: Martin Alfke - Can you upgrade to puppet 4.x?
Puppet Troubleshooting
Bangpypers april-meetup-2012
Intro to-puppet
Loops and Unicorns - The Future of the Puppet Language - PuppetConf 2013
Catalyst MVC
Building Cloud Castles
Oliver hookins puppetcamp2011
Our Puppet Story (GUUG FFG 2015)
Puppet at Bazaarvoice
Orchestrated Functional Testing with Puppet-spec and Mspectator
Fabric workshop(1) - (MOSG)
Puppet atbazaarvoice

More from Puppet (20)

PPTX
Puppet Community Day: Planning the Future Together
PPTX
The Evolution of Puppet: Key Changes and Modernization Tips
PPTX
Can You Help Me Upgrade to Puppet 8? Tips, Tools & Best Practices for Your Up...
PPTX
Bolt Dynamic Inventory: Making Puppet Easier
PPTX
Customizing Reporting with the Puppet Report Processor
PPTX
Puppet at ConfigMgmtCamp 2025 Sponsor Deck
PPTX
The State of Puppet in 2025: A Presentation from Developer Relations Lead Dav...
PPTX
Let Red be Red and Green be Green: The Automated Workflow Restarter in GitHub...
PDF
Puppet camp2021 testing modules and controlrepo
PPTX
Puppetcamp r10kyaml
PDF
2021 04-15 operational verification (with notes)
PPTX
Puppet camp vscode
PDF
Modules of the twenties
PDF
Applying Roles and Profiles method to compliance code
PPTX
KGI compliance as-code approach
PDF
Enforce compliance policy with model-driven automation
PDF
Keynote: Puppet camp compliance
PPTX
Automating it management with Puppet + ServiceNow
PPTX
Puppet: The best way to harden Windows
PPTX
Simplified Patch Management with Puppet - Oct. 2020
Puppet Community Day: Planning the Future Together
The Evolution of Puppet: Key Changes and Modernization Tips
Can You Help Me Upgrade to Puppet 8? Tips, Tools & Best Practices for Your Up...
Bolt Dynamic Inventory: Making Puppet Easier
Customizing Reporting with the Puppet Report Processor
Puppet at ConfigMgmtCamp 2025 Sponsor Deck
The State of Puppet in 2025: A Presentation from Developer Relations Lead Dav...
Let Red be Red and Green be Green: The Automated Workflow Restarter in GitHub...
Puppet camp2021 testing modules and controlrepo
Puppetcamp r10kyaml
2021 04-15 operational verification (with notes)
Puppet camp vscode
Modules of the twenties
Applying Roles and Profiles method to compliance code
KGI compliance as-code approach
Enforce compliance policy with model-driven automation
Keynote: Puppet camp compliance
Automating it management with Puppet + ServiceNow
Puppet: The best way to harden Windows
Simplified Patch Management with Puppet - Oct. 2020

Recently uploaded (20)

PDF
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
PDF
MIND Revenue Release Quarter 2 2025 Press Release
PPTX
Programs and apps: productivity, graphics, security and other tools
PPTX
SOPHOS-XG Firewall Administrator PPT.pptx
PDF
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
PDF
Diabetes mellitus diagnosis method based random forest with bat algorithm
PDF
Approach and Philosophy of On baking technology
PDF
Mobile App Security Testing_ A Comprehensive Guide.pdf
PPTX
Tartificialntelligence_presentation.pptx
PDF
Reach Out and Touch Someone: Haptics and Empathic Computing
PPTX
A Presentation on Artificial Intelligence
PDF
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
PPTX
1. Introduction to Computer Programming.pptx
PPTX
Machine Learning_overview_presentation.pptx
PPTX
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
PPTX
OMC Textile Division Presentation 2021.pptx
PDF
A comparative analysis of optical character recognition models for extracting...
PDF
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
PDF
NewMind AI Weekly Chronicles - August'25-Week II
PPTX
TechTalks-8-2019-Service-Management-ITIL-Refresh-ITIL-4-Framework-Supports-Ou...
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
MIND Revenue Release Quarter 2 2025 Press Release
Programs and apps: productivity, graphics, security and other tools
SOPHOS-XG Firewall Administrator PPT.pptx
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
Diabetes mellitus diagnosis method based random forest with bat algorithm
Approach and Philosophy of On baking technology
Mobile App Security Testing_ A Comprehensive Guide.pdf
Tartificialntelligence_presentation.pptx
Reach Out and Touch Someone: Haptics and Empathic Computing
A Presentation on Artificial Intelligence
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
1. Introduction to Computer Programming.pptx
Machine Learning_overview_presentation.pptx
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
OMC Textile Division Presentation 2021.pptx
A comparative analysis of optical character recognition models for extracting...
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
NewMind AI Weekly Chronicles - August'25-Week II
TechTalks-8-2019-Service-Management-ITIL-Refresh-ITIL-4-Framework-Supports-Ou...

The Grand Puppet Sub-Systems Tour - Nicholas Fagerlund, Puppet Labs

  • 1. 2014 Presented by The Grand Puppet Sub-Systems Tour Nick Fagerlund Technical Writer / Weird Bugs | Puppet Labs @nfagerlund
  • 3. Presented by What does Puppet DO? • Gather system information • Compile a catalog • Apply catalog • Report
  • 4. Presented by What does Puppet DO? AGENT • Gather system information • Apply catalog • Report MASTER • Compile a catalog
  • 5. STOP 1: Command Line and the Presented by
  • 6. Presented by Someone ran puppet agent
  • 7. Presented by ??? • /opt/puppet/bin/puppet • Puppet::Util::CommandLine.new.execute • Puppet::Application.find • Puppet::Application::Agent.new • Puppet::Application::Agent#setup • Puppet::Application::Agent#run_command
  • 8. Presented by #run_command # lib/puppet/application/agent.rb def run_command if options[:fingerprint] fingerprint else # It'd be nice to daemonize later, but we have to daemonize before # waiting for certificates so that we don't block daemon = daemonize_process_when(Puppet[:daemonize]) ! wait_for_certificates ! if Puppet[:onetime] onetime(daemon) else main(daemon) end
  • 9. Presented by onetime() and main() # lib/puppet/application/agent.rb begin exitstatus = daemon.agent.run rescue => detail Puppet.log_exception(detail) end ! daemon.stop(:exit => false) ! if not exitstatus exit(1) elsif options[:detailed_exitcodes] then exit(exitstatus) else exit(0) end # lib/puppet/application/agent.rb def main(daemon) if Puppet[:listen] setup_listen(daemon) end Puppet.notice "Starting Puppet client version #{Puppet.version}" ! daemon.start end
  • 10. Presented by Obtaining the daemon # lib/puppet/application/agent.rb def daemonize_process_when(should_daemonize) daemon = Puppet::Daemon.new(Puppet::Util::Pidlock.new(Puppet[:pidfile])) daemon.argv = @argv daemon.agent = @agent ! daemon.daemonize if should_daemonize ! daemon end
  • 11. STOP 2: The Daemon and the Presented by
  • 12. Presented by DAEMON LAND?! Nope Bye
  • 13. Presented by Puppet::Agent • Run a thing
  • 14. Presented by Puppet::Daemon • Run a thing that runs the other thing
  • 15. Lots of layers of abstraction?? • Historical reasons! Presented by
  • 16. Presented by STOP 3: The Configurer
  • 18. Puppet::Configurer#run_internal Presented by # lib/puppet/configurer.rb def run_internal(options) # We create the report pre-­‐populated with default settings for # environment and transaction_uuid very early, this is to ensure # they are sent regardless of any catalog compilation failures or # exceptions. options[:report] ||= Puppet::Transaction::Report.new("apply", nil, @environment, @transaction_uuid) report = options[:report] init_storage ! Puppet::Util::Log.newdestination(report) … … …
  • 19. Puppet::Configurer#run_internal Presented by # lib/puppet/configurer.rb … query_options = get_facts(options) unless query_options …
  • 20. Puppet::Configurer#run_internal Presented by # lib/puppet/configurer/fact_handler.rb … facts = Puppet::Node::Facts.indirection.find(Puppet[:node_name_value], :environment => @environment) …
  • 21. Puppet::Configurer#run_internal Presented by # lib/puppet/configurer.rb … unless catalog = prepare_and_retrieve_catalog(options, query_options) return nil end …
  • 22. Puppet::Configurer#run_internal Presented by # lib/puppet/configurer.rb … apply_catalog(catalog, options) …
  • 23. Presented by Where next? Retrieve Apply
  • 24. STOP 4: The Transaction Presented by
  • 26. Presented by Puppet::Resource::Catalog Catalog Resource Other Stuff
  • 27. Presented by Puppet::Configurer (again) # lib/puppet/configurer.rb def convert_catalog(result, duration) catalog = result.to_ral catalog.finalize catalog.retrieval_duration = duration catalog.write_class_file catalog.write_resource_file catalog end
  • 28. Presented by RAL Catalog
  • 29. Presented by RAL Catalog # lib/puppet/resource/catalog.rb def to_catalog(convert) result = self.class.new(self.name, self.environment_instance) result.version = self.version map = {} resources.each do |resource| next if virtual_not_exported?(resource) next if block_given? and yield resource newres = resource.copy_as_resource newres.catalog = result if convert != :to_resource newres = newres.to_ral end # We can't guarantee that resources don't munge their names # (like files do with trailing slashes), so we have to keep track # of what a resource got converted to. map[resource.ref] = newres result.add_resource newres end
  • 30. Presented by RAL Catalog Puppet::Resource ! ↓ ! (something) << Puppet::Type
  • 31. Presented by RAL Catalog ???
  • 32. Presented by RAL Catalog # lib/puppet/configurer.rb def apply_catalog(catalog, options) report = options[:report] report.configuration_version = catalog.version ! benchmark(:notice, "Finished catalog run") do catalog.apply(options) end ! report.finalize_report report end
  • 33. Puppet::Resource::Catalog#apply Presented by # lib/puppet/resource/catalog.rb def apply(options = {}) Puppet::Util::Storage.load if host_config? ! transaction = create_transaction(options) ! begin transaction.report.as_logging_destination do transaction.evaluate end rescue Puppet::Error => detail !
  • 35. Presented by Transaction • Ral catalog • Prioritizer • Report
  • 36. Presented by Transaction • Ral catalog • Prioritizer • Report • Event manager • Resource harness • Relationship graph
  • 37. Presented by Transaction • Ral catalog • Prioritizer • Report • Event manager • Resource harness • Relationship graph • relationship_graph.traverse
  • 38. Presented by Transaction • Ral catalog • Prioritizer • Report • Event manager • Resource harness • Relationship graph • relationship_graph.traverse • *ollies out*
  • 39. Presented by STOP 5: The Indirector
  • 40. Presented by Back to Puppet::Configurer • #prepare_and_retrieve_catalog
  • 41. Presented by Back to Puppet::Configurer # lib/puppet/configurer.rb result = Puppet::Resource::Catalog.indirection.find( Puppet[:node_name_value], query_options.merge(:ignore_cache => true, :environment => @environment, :fail_on_404 => true) )
  • 42. Presented by The Indirector ! Puppet::Resource::Catalog.indirection.find()
  • 43. Presented by The Indirector ← ↑ ↓ ?
  • 44. Presented by The Indirector • Globally configured • Abstract • Gets stuff for you
  • 45. Presented by The Indirector # lib/puppet/resource/catalog.rb extend Puppet::Indirector indirects :catalog, :terminus_setting => :catalog_terminus
  • 46. Presented by The Indirector • find • search • save • destroy
  • 47. Presented by The Indirector • find • search • save • destroy • terminus_class • cache_class • lib/puppet/indirector/…
  • 48. Presented by Puppet Agent • Catalog => REST • Report => REST • Facts => Facter
  • 49. Presented by Puppet Apply • Catalog => Compiler • Report => Processor • Facts => Facter
  • 50. Presented by Avoiding the cache # lib/puppet/configurer.rb result = Puppet::Resource::Catalog.indirection.find( Puppet[:node_name_value], query_options.merge(:ignore_cache => true, :environment => @environment, :fail_on_404 => true) )
  • 51. Presented by The Indirector • Why?
  • 52. Presented by The Indirector • Why? • Global? Rigid?
  • 53. Presented by The Indirector • Why? • Global? Rigid? • IT MAKES SENSE IN CONTEXT
  • 54. Presented by The Indirector • …Catalog.find( <FACTS> ) • REST terminus • HTTP POST request to master
  • 55. STOP 6: The Puppet Master’s Presented by
  • 56. Presented by Rack Web server ↓ Rack server ↓ “App” object that responds to #call() ↓ Actual application logic
  • 57. Presented by config.ru $0 = "master" ! ARGV << "-­‐-­‐rack" ! ARGV << "-­‐-­‐confdir" << "/etc/puppet" ARGV << "-­‐-­‐vardir" << "/var/lib/puppet" ! require 'puppet/util/command_line' run Puppet::Util::CommandLine.new.execute !
  • 58. Presented by Starting master w/ Rack # lib/puppet/application/master.rb def start_rack_master require 'puppet/network/http/rack' ! announce_start_of_master ! return Puppet::Network::HTTP::Rack.new() end
  • 59. Presented by The app object # lib/puppet/network/http/rack.rb class Puppet::Network::HTTP::Rack def call(env) request = Rack::Request.new(env) response = Rack::Response.new Puppet.debug 'Handling request: %s %s' % [request.request_method, request.fullpath] ! begin Puppet::Network::HTTP::RackREST.new.process(request, response) rescue => detail # Send a Status 500 Error on unhandled exceptions. response.status = 500 response['Content-­‐Type'] = 'text/plain' response.write 'Internal Server Error: "%s"' % detail.message # log what happened Puppet.log_exception(detail, "Puppet Server (Rack): Internal Server Error: Unhandled Exception: "%s"" % detail.message) end response.finish
  • 60. Presented by #process # lib/puppet/network/http/handler.rb def process(request, response) new_response = Puppet::Network::HTTP::Response.new(self, response) ! request_headers = headers(request) request_params = params(request) request_method = http_method(request) request_path = path(request) … !
  • 61. Presented by #process # lib/puppet/network/http/handler.rb if route = @routes.find { |route| route.matches?(new_request) } route.process(new_request, new_response)
  • 63. lib/puppet/network/http/api/v1.rb • GET => indirection.find() • POST => indirection.find() (for catalogs) • (There was an issue with some servers rejecting GET parameters that were too long. Funny story about that.) • DELETE => indirection.destroy() • PUT => indirection.save() • GET to magical plural name => indirection.search() Presented by
  • 64. Presented by BIG PICTURE Configurer calls catalog.indirection.find() ↓ HTTP POST request to master ↓ Request handler calls catalog.indirection.find() ↓ Compiler terminus handles it ↓
  • 65. Presented by STOP 7: The Compiler
  • 66. Presented by MOSTLY SKIPPING THIS Lexer ↓ Parser ↓ AST ↓ Evaluator ↓
  • 67. Presented by THIS IS THE TEST “Compiler terminus to the catalog indirection” ! ???
  • 68. Presented by THIS IS THE TEST GOOD WORK EVERYBODY!
  • 70. Presented by THANKS!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! •Hope we’ll see you next year in Portland!