Writing Custom Puppet Types and Providers to Manage Web-Based Applications

116
TIM CINEL BUILD WHISPERER ATLASSIAN @TIMCINEL Writing Custom Types to Manage Web-Based Applications

Transcript of Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Page 1: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

TIM CINEL • BUILD WHISPERER • ATLASSIAN • @TIMCINEL

Writing Custom Types to Manage Web-Based Applications

Page 2: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

O U R S I T U AT I O N

W O R K E D E X A M P L E

D E M O

This Talk

N E X T S T E P S

Page 3: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Our Situation

Page 4: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Atlassian BambooSonatype Nexus

Atlassian’s Build Engineering team uses Puppet to manage manage many services, including…

• Repositories

• Security

• Proxy features

• Variables

• Global defaults

• Security

Page 5: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Managing config files has drawbacks…

• Nexus’s config file changes are picked up after restart

• Changes require brief service outage

• Changes made using Nexus and Bamboo UI during runtime not detected by Puppet

• Risk of configuration drift

• Most Bamboo configuration is in its database, not configuration files

• Ability to manage service is limited

Uptime Drift Limited

Page 6: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

How do we address these drawbacks?

Custom Types.

Page 7: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Concepts Refresher

Page 8: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Concept and terminology refresher

• Type

• Name

• Attributes

Can be considered as instances of types

Native Type

• Ruby implementation

• Attributes

• Provider(s)

Allows the representation of a type of resource in Puppet DSL

• Ruby implementation

• Type

Providers interact with target system to manage resources

Resource Type Provider

Page 9: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

What Are Custom Types?

user Type(Default)

useradd Provider for user Type

Manifest

bamboo_agent Type(Custom)

rest Provider for bamboo_agent Type

Manifest

Page 10: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

What Are Custom Types?

user Type(Default)

useradd Provider for user Type

Manifest

bamboo_agent Type(Custom)

rest Provider for bamboo_agent Type

Manifest

Page 11: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Custom Types can be created to manage

web-based services.

Page 12: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Custom Types

The Good Fine Configuration

No need to restart or reload services to pick up configuration changes.

No More DriftCustom types can directly query the application state runtime.

Fewer Restarts

If it’s configurable, a custom type can manage it. No need to manually tweak service configuration.

Page 13: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Custom Types

The Bad Authentication

Somebody has to create and maintain the custom types

More DependenciesThe module containing the custom types, custom providers and libraries

Engineering Cost

Configuration APIs often require credentials

Page 14: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

It’s not OK to manually configure

Bamboo instances

20

Page 15: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

bamboo_rest

Automated awayThese properties used to be configured on each server manually.

Not anymore. Thanks Custom Types!

https://forge.puppetlabs.com/atlassian/bamboo_rest

Page 16: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Nexus instances

18It’s not OK to allow config to drift on

Page 17: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

nexus_rest

Seamless changesChanges to these properties used to cause Nexus to restart, resulting in down time.

Not anymore. Thanks Custom Types!

https://forge.puppetlabs.com/atlassian/nexus_rest

Page 18: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Configuration Only

These modules are only responsible for configuring installed services via REST APIs.

Installation of these services is managed by another module.

Page 19: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

I M P L E M E N T A T Y P E

S E T U P

W R I T E A P R O V I D E R

A D D I N G M O R E P R O P E R T I E S

Worked Example

I N T E R A C T I O N B E T W E E N T Y P E S

Page 20: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

I M P L E M E N T A T Y P E

S E T U P

W R I T E A P R O V I D E R

A D D I N G M O R E P R O P E R T I E S

Worked Example

I N T E R A C T I O N B E T W E E N T Y P E S

Page 21: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

https://bitbucket.org/TCinel/puppet-camp-example/

Page 22: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Helpful Tools• Puppet• Ruby• Bundler• irb• curl and Firebug• Docker

"Tools" (CC BY-NC-ND 2.0) by jlgriffiths

Page 23: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

What makes Nexus 3 a good candidate?

• Completely different API to Nexus 2• Easy to run using Docker• A repository manager is a good fit with the Puppet resource model

Nexus 3We’e going to create custom types for Nexus 3 in our worked example.

Page 24: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Our Nexus 3 Types

Hosted Maven repository.

Attributes

• name

• online

• blobstore

Abstract storage used by repositories.

Attributes

• name

• path

nexus3_repository nexus3_blobstore

Page 25: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Discover Service Endpoints

Useful Endpoints• Query all resources• Create new resource• Delete existing resource• Update existing resource

Before starting work on a custom type, we should confirm the necessary endpoints are available.

Page 26: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Query Repositories

Nexus Endpoint Example

Page 27: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

File Structure• lib/ - All code

• lib/puppet/ Puppet API code• lib/puppet/provider/<type>/<provider>.rb Provider definition

• lib/puppet/type/<type>.rb Type definition

• lib/puppet_x helper code

Page 28: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

I M P L E M E N T A T Y P E

S E T U P

W R I T E A P R O V I D E R

A D D I N G M O R E P R O P E R T I E S

Worked Example

I N T E R A C T I O N B E T W E E N T Y P E S

Page 29: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Creating a new type

It’s as simple as adding these two lines.

tag: step-01

Page 30: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Creating a new type

It’s as simple as adding these two lines.

tag: step-01

Page 31: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Creating a new type

It’s as simple as adding these two lines.

tag: step-01

Page 32: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

It’s not quite ready.At least we have our dev loop now.

tag: step-01

Page 33: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Make sure RUBYLIB contains the path to lib/ before running puppet

It’s not quite ready.At least we have our dev loop now.

tag: step-01

Page 34: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

puppet resource and puppet apply are your friends

It’s not quite ready.At least we have our dev loop now.

tag: step-01

Page 35: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Add namevar

A type’s namevar acts like a primary key

tag: step-02

Page 36: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Add namevar

A type’s namevar acts like a primary key

tag: step-02

Page 37: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

tag: step-02

Page 38: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

`puppet resource` won’t work until we implement a provider

tag: step-02

Page 39: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

`puppet apply` works because currently nexus3_repository is not ensurable

tag: step-02

Page 40: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Inline documentation and ensurablenessNon-ensurable types (like exec) do not have persistent state.

tag: step-03

Page 41: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Inline documentation and ensurablenessNon-ensurable types (like exec) do not have persistent state.

tag: step-03

Page 42: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Inline documentation and ensurablenessAdding inline documentation is easy.

tag: step-03

Page 43: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Oops. We broke it again.Looks like we need to implement a provider.

ensurable resources have state, so their provider must have logic to determine state

tag: step-03

Page 44: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

I M P L E M E N T A T Y P E

S E T U P

W R I T E A P R O V I D E R

A D D I N G M O R E P R O P E R T I E S

Worked Example

I N T E R A C T I O N B E T W E E N T Y P E S

Page 45: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Before we start writing the provider…We could do with some helper classes so we don’t get bogged

down in implementation details.

tag: step-04

Page 46: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Before we start writing the provider…We could do with some helper classes so we don’t get bogged

down in implementation details.

helper classes in puppet_x

tag: step-04

Page 47: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Before we start writing the provider…We could do with some helper classes so we don’t get bogged

down in implementation details.

providers only need to use this class method

tag: step-04

Page 48: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Before we start writing the provider…We could do with some helper classes so we don’t get bogged

down in implementation details.

lazily load application config from file

tag: step-04

Page 49: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

A basic providertag: step-05

Page 50: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

A basic provider

the provider name is usually the name of the underlying tool used to manage resources

tag: step-05

Page 51: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

A basic provider

if implemented, self.instances is used to enumerate all resources of type

tag: step-05

Page 52: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

A basic provider

exists? provides logic for determining the presence of a resource

tag: step-05

Page 53: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Aw yeah.

now that we’ve implemented a basic provider, puppet resource is working

tag: step-05

Page 54: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Aw yeah.

now that we’ve implemented a basic provider, puppet resource is working

tag: step-05

Page 55: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Ability to create and destroytag: step-06

Page 56: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Ability to create and destroymethod used when Puppet determines

that a resource should be created

tag: step-06

Page 57: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Ability to create and destroymethod used when Puppet wants to

destroy a resource

tag: step-06

Page 58: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Now we’re getting somewhere.

tag: step-06

Page 59: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Now we’re getting somewhere.

purges any discovered resources that are not in the manifest

tag: step-06

Page 60: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Now we’re getting somewhere.

ensures that repo_1 and number-two are present

tag: step-06

Page 61: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Now we’re getting somewhere.

destroyed unmanaged resources

tag: step-06

Page 62: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Now we’re getting somewhere.

created new resources

tag: step-06

Page 63: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Now we’re getting somewhere.

tag: step-06

Page 64: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Well, sort of.resources are being created again

even though they already exist

tag: step-06

Page 65: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Implement prefetch`prefetch` must be defined if your `exists?` and getter methods don’t

query the system.

tag: step-07

Page 66: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Implement prefetch`prefetch` must be defined if your `exists?` and getter methods don’t

query the system.

tag: step-07

Page 67: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Yep, now we’ve got it.

tag: step-07

Page 68: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Yep, now we’ve got it.

no resources recreated

tag: step-07

Page 69: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

I M P L E M E N T A T Y P E

S E T U P

W R I T E A P R O V I D E R

A D D I N G M O R E P R O P E R T I E S

Worked Example

I N T E R A C T I O N B E T W E E N T Y P E S

Page 70: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Adding an attribute to the Typetag: step-08

Page 71: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Adding an attribute to the Type

nexus3_repository type now has an online attribute

tag: step-08

Page 72: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Adding an attribute to the Type

input value restriction

tag: step-08

Page 73: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Adding an attribute to the Type

input value normalisation

tag: step-08

Page 74: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Adding an attribute to the Providertag: step-08

Page 75: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Adding an attribute to the Provider

fetch the new attribute value from system and normalise it

tag: step-08

Page 76: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Adding an attribute to the Provider

submit the new attribute to the system on create and update

tag: step-08

Page 77: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Adding an attribute to the Providertag: step-08

Page 78: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Adding an attribute to the Provider

property getters and setters

tag: step-08

Page 79: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Adding an attribute to the Provider

flush can be used to implement update logic

tag: step-08

Page 80: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Aw yeah.

tag: step-08

Page 81: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Aw yeah.

puppet resource is reporting online status

tag: step-08

Page 82: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Aw yeah.

puppet apply updated the online attribute

tag: step-08

Page 83: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Aw yeah.

puppet apply updated the online attribute

tag: step-08

Page 84: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Adding another attribute to the Typetag: step-09

Page 85: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Adding another attribute to the Type

custom input validation logic

tag: step-09

Page 86: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Adding another attribute to the Providertag: step-09

Page 87: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Adding another attribute to the Provider

immutable property using fail method

tag: step-09

Page 88: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

puppet resource is reporting blobstore value

tag: step-09

Page 89: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

puppet resource is reporting blobstore value

tag: step-09

Page 90: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

changing the blobstore value for an existing repository is failing

tag: step-09

Page 91: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

changing the blobstore value for an existing repository is failing

tag: step-09

Page 92: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

That’s nexus3_repository

done.

Page 93: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

"Silbury Hill" (CC BY 2.0) by rightee

We’re over the hump.

Page 94: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

I M P L E M E N T A T Y P E

S E T U P

W R I T E A P R O V I D E R

A D D I N G M O R E P R O P E R T I E S

Worked Example

I N T E R A C T I O N B E T W E E N T Y P E S

Page 95: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

We’ve created another TypeThis one is called nexus3_blobstore

We won’t walk through it like we did for nexus3_repository.

tag: step-10

Page 96: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Mostly good. But…tag: step-10

Page 97: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

tag: step-10

Page 98: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

tag: step-10

Page 99: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

nexus3_repositorys instances are being created before nexus3_blobstore instances. not good.

tag: step-10

Page 100: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

nexus3_repository instances are being created before nexus3_blobstore instances. not good.

tag: step-10

Page 101: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Relationships between TypesTypes can define soft require relationships with arbitrary resources

tag: step-11

Page 102: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Relationships between TypesTypes can define soft require relationships with arbitrary resources

if puppet manages this config file, then all nexus3_repository resources will depend on it

tag: step-11

Page 103: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Relationships between TypesTypes can define soft require relationships with arbitrary resources

the associated nexus3_blobstore resource will become a dependency (if it exists)

tag: step-11

Page 104: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Better.tag: step-11

Page 105: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

blobstore created before each dependent repository

tag: step-11

Page 106: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Even better.tag: step-11

Page 107: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

allow Puppet to manage the config file

tag: step-11

Page 108: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

prefetch fails due to missing provider configuration file

tag: step-11

Page 109: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Puppet creates config file, then succeeds to create resources in the right order using our custom types and providers

tag: step-11

Page 110: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

I M P L E M E N T A T Y P E

S E T U P

W R I T E A P R O V I D E R

A D D I N G M O R E P R O P E R T I E S

Worked Example

I N T E R A C T I O N B E T W E E N T Y P E S

Done 👌

Page 111: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Demo

Page 112: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Next Steps

Page 113: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Areas for Improvement

Publish to Forge

Incorporate better error handling, logging.

TestsUnit tests with RSpec, acceptance tests with Beaker and some CI.

Robustness

Make the module and its glorious types available to the community.

Page 114: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Puppet SourceShit Garry SaysPuppet Types and Providers http://garylarizza.com/blog/

Other Resources

Page 115: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Now go, and write some custom types

already!

Page 116: Writing Custom Puppet Types and Providers to Manage Web-Based Applications

Thank you

TIM CINEL • BUILD WHISPERER • ATLASSIAN • @TIMCINEL

https://bitbucket.org/TCinel/puppet-camp-example/