Streamlining Workflows with Puppet Faces

Preview:

DESCRIPTION

An in depth look at the Puppet Faces API and how to leverage it to streamline your configuration management workflow. During this talk a data driven Puppet Face will be created from the ground up. The goal is to automate a common workflow scenario which involves updating Puppet Dashboard external node configuration (ENC) data in bulk.

Citation preview

PUPPET FACESStreamlining Workflows

Kelsey Hightower

AgendaFirst World Problems

Puppet Faces

Familiar Faces

A New Face

Core Components

Why?

puppet dashboard

Puppet DashboardVisualize Your Infrastructure: Status, Graphs, and Reports

External Node Classifier (ENC)

Puppet DashboardVisualize Your Infrastructure: Status, Graphs, and Reports

External Node Classifier (ENC)

manage parameters, groups and classes

First World Problems

First World ProblemsOne key/value pair at a time

First World ProblemsOne key/value pair at a time

Time consuming

First World ProblemsOne key/value pair at a time

Time consuming

Managing ENC data in dashboard could be better

First World Problems

First World ProblemsClick Chrome icon

First World ProblemsClick Chrome icon

Click on Puppet Dashboard bookmark

First World ProblemsClick Chrome icon

Click on Puppet Dashboard bookmark

Click on each system

First World ProblemsClick Chrome icon

Click on Puppet Dashboard bookmark

Click on each system

Click edit

First World ProblemsClick Chrome icon

Click on Puppet Dashboard bookmark

Click on each system

Click edit

Click add new parameter

First World ProblemsClick Chrome icon

Click on Puppet Dashboard bookmark

Click on each system

Click edit

Click add new parameter

Click save

First World ProblemsClick Chrome icon

Click on Puppet Dashboard bookmark

Click on each system

Click edit

Click add new parameter

Click save

Click on each group

First World ProblemsClick Chrome icon

Click on Puppet Dashboard bookmark

Click on each system

Click edit

Click add new parameter

Click save

Click on each group

Click edit

First World ProblemsClick Chrome icon

Click on Puppet Dashboard bookmark

Click on each system

Click edit

Click add new parameter

Click save

Click on each group

Click edit

Click some more.

Lots of clicking!!

Puppet?

parameters: node: - "el6.puppetize.me": "domain": "puppetize.me"

group: - "webservers": "apache_version": "2.2.16"

puppet cool-subcommand import data.yaml

Puppet Faces

What are Puppet Faces?

What are Puppet Faces?API for extending existing Puppet functionality

What are Puppet Faces?API for extending existing Puppet functionality

API for creating Puppet subcommands and actions

Familiar Facescatalog

certificate

certificate_request

config

facts

file

man

node

report

resource

status

catalog

catalogpuppet catalog select puppet.testing.org package

catalogpuppet catalog select puppet.testing.org package

Package[openssh-server]

catalog

puppet catalog download

puppet catalog select puppet.testing.org package

Package[openssh-server]

catalog

puppet catalog download

notice: Saved catalog for puppet.testing.org to yaml

puppet catalog select puppet.testing.org package

Package[openssh-server]

catalog

puppet catalog download

notice: Saved catalog for puppet.testing.org to yaml

puppet catalog select puppet.testing.org package

Package[openssh-server]

puppet catalog apply

catalog

puppet catalog download

notice: Saved catalog for puppet.testing.org to yaml

puppet catalog select puppet.testing.org package

Package[openssh-server]

puppet catalog apply

notice: Finished catalog run in 0.39 seconds"#<Puppet::Transaction::Report:0x98eafcc>"

config

configpuppet config print server --mode agent

configpuppet config print server --mode agent

puppet.testing.org

configpuppet config print server --mode agent

puppet.testing.org

puppet config print all --mode agent

configpuppet config print server --mode agent

puppet.testing.org

puppet config print all --mode agent

allow_duplicate_certs = falsearchive_file_server = puppet.testing.orgarchive_files = falseasync_storeconfigs = falseauthconfig = /etc/puppet/namespaceauth.confautoflush = falseautosign = /etc/puppet/autosign.confbindaddress = ""bucketdir = /var/lib/puppet/bucket...

certificate

certificatepuppet certificate find puppet.testing.org --ca-location=remote

certificatepuppet certificate find puppet.testing.org --ca-location=remote

-----BEGIN CERTIFICATE-----MIIClzCCAgCgAwIBAgIBBjANBgkqhkiG9w0BAQUFADAoMSYwJAYDVQQDDB1QdXBwZXQgQ0E6IHB1cHBldC50ZXN0aW5nLm9yZzAeFw0xMTA5MDcxNzE1MjJaFw0xNjA5MDUxNzE1MjJaMB0xGzAZBgNVBAMMEnB1cHBldC50ZXN0aW5nLm9yZzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0C8WqEYaZiYRGb0mY1LFSEp7M3NIpugcmhJ1eZ9gck0gEtYrk2FetOqBqwF45df3FDXUvHKovcNaJeJ05Gn0XFrAZ8Y7IQsboX993Dd3d+7yq0T4gK1myjnizzqPaa/cgJrAtc1caByoxe1fYL1SJKnm+/u9z6YOT4OI8UtfYskCAwEAAaOB2zCB2DA4BglghkgBhvhCAQ0EKxYpUHVwcGV0IFJ1YnkvT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUaBiSUyQXKLtAj+cNlcEAsVwjRNkwCwYDVR0PBAQDAgWgMCcGA1UdJQQgMB4GCCsGAQUFBwMBBggrBgEFBQcDAgYIKwYBBQUHAwQwOQYDVR0RBDIwMIIGcHVwcGV0ghJwdXBwZXQudGVzdGluZy5vcmeCEnB1cHBldC50ZXN0aW5nLm9yZzANBgkqhkiG9w0BAQUFAAOBgQBgOYHKMehXRba77I0zOLmnZMh0Y0HvyuSX843e++pXrje/+fCBIqvVai7wCrElLB6pdLsFYVyeLkONGRB6eGGeHr9yRWwSVhEPPySdh2uRER3M530JxCG+tkz4BNtnGGQB+wI12p8EL47axxP/OiCMGCdS8Xi21+FIg2/dwQnsPA==-----END CERTIFICATE-----

resource

resourcepuppet resource package telnet ensure=present

resourcepuppet resource package telnet ensure=present

notice: /Package[telnet]/ensure: created

resourcepuppet resource package telnet ensure=present

notice: /Package[telnet]/ensure: created

package { 'telnet': ensure => '0.17-36',}

dashboard face

dashboard

dashboardQuery Puppet Dashboard

dashboardQuery Puppet Dashboard

Import/Export data

How?

Programming Motherfu*ker

Project LayoutLICENSE

README

lib/puppet/application/dashboard.rb

lib/puppet/face/dashboard.rb

lib/puppet/face/dashboard/*.rb

Core Componentsapplication

options

arguments

actions

Only limited by your imagination.

Only limited by your imagination.

Dragon Face

puppet dashboard import data.yaml

puppet dashboard import data.yaml

application

Applicationcopyright

license

summary

description

short_description

action

Application Class

require 'puppet/face'require 'puppet/application/face_base'

class Puppet::Application::Dashboard < Puppet::Application::FaceBaseend

dashboard-puppet-face/lib/puppet/application/dashboard.rb

Application Class

require 'puppet/face'require 'puppet/application/face_base'

class Puppet::Application::Dashboard < Puppet::Application::FaceBaseend

dashboard-puppet-face/lib/puppet/application/dashboard.rb

inherit FaceBase

Applicationpuppet-dashboard-face/lib/puppet/face/dashboard.rb

require 'puppet'require 'puppet/face'

Puppet::Face.define(:dashboard, '0.0.1') do summary "Puppet Dashboard Integration" copyright "Kelsey Hightower", 2011 license "Apache 2 license" description "Puppet Dashboard Integration"end

Applicationpuppet-dashboard-face/lib/puppet/face/dashboard.rb

require 'puppet'require 'puppet/face'

Puppet::Face.define(:dashboard, '0.0.1') do summary "Puppet Dashboard Integration" copyright "Kelsey Hightower", 2011 license "Apache 2 license" description "Puppet Dashboard Integration"end

subcommand

Applicationpuppet-dashboard-face/lib/puppet/face/dashboard.rb

require 'puppet'require 'puppet/face'

Puppet::Face.define(:dashboard, '0.0.1') do summary "Puppet Dashboard Integration" copyright "Kelsey Hightower", 2011 license "Apache 2 license" description "Puppet Dashboard Integration"end

api version

puppet dashboard import data.yaml\--adapter=mysql --host=127.0.0.1

puppet dashboard import data.yaml\--adapter=mysql --host=127.0.0.1

options

Optionsadapter

username

password

host

database

Optionspuppet-dashboard-face/lib/puppet/face/dashboard.rb

require 'puppet'require 'puppet/face'

Puppet::Face.define(:dashboard, '0.0.1') do ... option "--adapter ADAPTER" do summary "Active Record database adapter" description <<-'EOT' The adapter for to use when accessing the Puppet Dashboard database. EOT end ...end

Optionspuppet-dashboard-face/lib/puppet/face/dashboard.rb

require 'puppet'require 'puppet/face'

Puppet::Face.define(:dashboard, '0.0.1') do ... option "--adapter ADAPTER" do summary "Active Record database adapter" description <<-'EOT' The adapter for to use when accessing the Puppet Dashboard database. EOT end ...end

define options

puppet dashboard import data.yaml

puppet dashboard import data.yaml

arguments

ArgumentsFaces can accept positional arguments

Argumentspuppet-dashboard-face/lib/puppet/face/dashboard/import.rb

Puppet::Face.define(:dashboard, '0.0.1') do action :import do summary "Import ENC paramters" arguments "<data>" description <<-'EOT' Bulk import external nodes configuration data into dashboard EOT endend

puppet dashboard import data.yaml

puppet dashboard import data.yaml

action

Actionssummary

arguments

returns

description

notes

examples

when_invoked

when_rendering

Actionspuppet-dashboard-face/lib/puppet/face/dashboard/import.rb

Puppet::Face.define(:dashboard, '0.0.1') do action :import do summary "Import ENC paramters" arguments "<data>" description <<-'EOT' Bulk import external nodes configuration data into dashboard EOT

when_invoked do |data, options| ... end endend

Actionspuppet-dashboard-face/lib/puppet/face/dashboard/import.rb

Puppet::Face.define(:dashboard, '0.0.1') do action :import do summary "Import ENC paramters" arguments "<data>" description <<-'EOT' Bulk import external nodes configuration data into dashboard EOT

when_invoked do |data, options| ... end endend

Action

Actionspuppet-dashboard-face/lib/puppet/face/dashboard/import.rb

Puppet::Face.define(:dashboard, '0.0.1') do action :import do summary "Import ENC paramters" arguments "<data>" description <<-'EOT' Bulk import external nodes configuration data into dashboard EOT

when_invoked do |data, options| ... end endend This is where the

works gets done.

Almost ready to solve this problem.

Deploying our Face

Deployment

Deploymentrsync -av puppet-dashboard-face/lib/puppet/ \/opt/ruby/lib/ruby/gems/1.8/gems/puppet-2.7.3/lib/puppet/

Deploymentrsync -av puppet-dashboard-face/lib/puppet/ \/opt/ruby/lib/ruby/gems/1.8/gems/puppet-2.7.3/lib/puppet/

sending incremental file list./application/application/dashboard.rbface/face/dashboard.rbface/dashboard/face/dashboard/import.rbface/dashboard/list.rbface/dashboard/models.rbface/dashboard/report.rbface/dashboard/search.rb

sent 9069 bytes received 160 bytes 18458.00 bytes/sectotal size is 8546 speedup is 0.93

Deployment

Deploymentpuppet help

Deploymentpuppet help

Usage: puppet <subcommand> [options] <action> [options]

Available subcommands, from Puppet Faces: catalog Compile, save, view, and convert catalogs. facts Retrieve and store facts. help Display Puppet help. dashboard Puppet Dashboard Integration. man Display Puppet manual pages. node View and manage node definitions. parser Interact directly with the parser.

Help

Helppuppet help dashboard

Helppuppet help dashboard

USAGE: puppet dashboard <action> [--host HOST] ...

Interact with Puppet Dashboard

OPTIONS: ... --adapter ADAPTER - Active Record Database Adapter --host HOST - Database Hostname

ACTIONS: import Import data into Puppet Dashboard.

See 'puppet man dashboard' or 'man puppet-dashboard' for full help.

RTFM

Read The Face Manual

Read The Face Manualpuppet man dashboard

Read The Face Manualpuppet man dashboard

PUPPET-DASHBOARD(8) Puppet Manual PUPPET-DASHBOARD(8)

NAME puppet-dashboard - Interact with Puppet Dashboard

SYNOPSIS puppet dashboard action [--adapter ADAPTER] [--database DATBASE] [--username USER] [--password PASSWORD] [--host HOST]

OPTIONS Note that any configuration parameter that's valid in the configuration file is also a valid long argument, although it may or may not be rele- vant to the present action. For example, server is a valid configura- tion parameter, so you can specify --server <servername> as an argu- ment.

Putting it all together

parameters: node: - "master.lab.org": "domain": "puppetize.me"

group: - "webservers": "apache_version": "2.2.16"

puppet dashboard import data.yaml

Problem solved!

Better for the environment

75% less batteries

Why Puppet Faces?

Consolidation

Consolidation/usr/sbin/dashboard_importer

Consolidation/usr/sbin/dashboard_importer

/usr/sbin/dashboard_importer.bak

Consolidation/usr/sbin/dashboard_importer

/usr/sbin/dashboard_importer.bak

/usr/sbin/dashboardImporter

Consolidation/usr/sbin/dashboard_importer

/usr/sbin/dashboard_importer.bak

/usr/sbin/dashboardImporter

/usr/sbin/dashboard_importer.new

Consolidation/usr/sbin/dashboard_importer

/usr/sbin/dashboard_importer.bak

/usr/sbin/dashboardImporter

/usr/sbin/dashboard_importer.new

puppet dashboard importer

Free Documentationpuppet man dashboard

puppet help dashboard

Free Ruby API

Free Ruby APIirb

Free Ruby APIirb

irb> require 'rubygems'

Free Ruby APIirb

irb> require 'rubygems'irb> require 'puppet/face'

Free Ruby APIirb

irb> require 'rubygems'irb> require 'puppet/face'irb> arguments = '/tmp/data.yaml'

Free Ruby APIirb

irb> require 'rubygems'irb> require 'puppet/face'irb> arguments = '/tmp/data.yaml'irb> options = {:adapter => 'mysql', :password => ..

Free Ruby APIirb

irb> require 'rubygems'irb> require 'puppet/face'irb> arguments = '/tmp/data.yaml'irb> options = {:adapter => 'mysql', :password => ..irb> dashboard = Puppet::Face[:dashboard,'0.0.1']

Free Ruby APIirb

irb> require 'rubygems'irb> require 'puppet/face'irb> arguments = '/tmp/data.yaml'irb> options = {:adapter => 'mysql', :password => ..irb> dashboard = Puppet::Face[:dashboard,'0.0.1']irb> dashboard.import(arguments, options)

Free Ruby APIirb

irb> require 'rubygems'irb> require 'puppet/face'irb> arguments = '/tmp/data.yaml'irb> options = {:adapter => 'mysql', :password => ..irb> dashboard = Puppet::Face[:dashboard,'0.0.1']irb> dashboard.import(arguments, options)

puppet dashboard import /tmp/data.yaml --adapter=mysql ...

Good Investment

The FutureReference custom parameters from puppet.conf

Expose Faces to external REST API

khightower/puppet-dashboard-face

github

@kelseyhightowertwitter

puppetize.meweb

Questions?

Recommended