Saturday, 16 September 2017

Puppet Part Three: In Which I Write My First Module

In my previous post I wrote a manifest for stark that removed specific groups/users and added specific groups/users. This allowed me to do some user standardisation on stark (if this doesn't make sense to you, please read my previous post, Puppet Part Two). On cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 whole it's pretty nifty, right? I mean, I could copy and paste cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user/group stuff from stark's manifest into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 manifests for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r systems and have my user needs satisfied...but is that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 best way?

Modules: A Quick Overview


There are _a lot_ of things to say about modules and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Puppet documentation on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m is here:


The short, short version is that modules let you write something one time and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n use it in lots of places. Modules are made up of classes and a class, ideally, should do one thing (object-oriented programming is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 programmer's derivative of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Unix philosophy?). For example, you may have a module called 'ssh' - cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n that module may have one class for installing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 SSH server package, anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r class to configure sshd_config and anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r class to configure cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 system ssh_config.

Using my scenario above, I have a group of accounts that I want to exist on my servers. Instead of creating those accounts in every manifest I have, I can write a module that does account-y stuff and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n add that one module to each server's manifest. Then when I need to delete an account I can do it one time, in my module, and as my servers check in, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y'll get cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 new configuration and remove cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 account. Write once, use lots of places, problem solved!

One quick note: remember, I'm a Puppet noob. I've written very basic modules to do user-y and basic administration-y type stuff. I've not written modules to do more complex things. That's okay, we're learning (more or less) togecá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Puppet folks on Twitter (@puppetize) are phenomenally supportive.  Their documentation covers doing interesting things, I'm just covering getting started. I may do some more complex things in several months but for now, I'm relying mostly on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 work of ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365rs and I'm keeping MY work fairly simple.

With that said, let's write a module that does some basic administration-y type things that allow for standardisation of some system services.

The Layout


There are some requirements for Puppet to use a module. It needs to be in a directory that is designated for modules in Puppet's configuration. On Ubuntu, by default, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se are:

/etc/puppetlabs/code/modules
/etc/puppetlabs/code/environments/production/modules

This is configurable but that configuration is outside cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 scope of this post. Maybe later, if I dive into multiple environments or custom paths for multiple maintainers.

A module itself needs a few things to work. At a bare minimum, it needs:

o a metadata.json file that gives cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 module name, version, author, summary, license and some ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r information
o a manifests directory
o a manifests/init.pp file that has cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 initial class declaration; cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 initial class is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same name as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 module

I know, that last bullet may be a little confusing. It will make more sense when we take a look at one.

Three Choices


There are three ways to create a module. You can copy an existing module into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 appropriate directory and modify it to fit your needs but that can be a lot of work - it is worth it to have a template you can copy over for new modules if you're going to write several of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m but that may be unlikely.

The second option is to use cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 'puppet module' command. This is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same way you install and remove 3rd party modules and it is an easy way to create cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 initial directory structure, metadata file, init.pp file and basic documentation. Using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 'puppet module' command also creates several more files and sub-directories built around cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 idea that you're going to share your module with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 world and do testing across multiple platforms. It is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 most complete method available and everyone writing puppet modules should use it at least once.

The third option is to create cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 necessary directories and files yourself. This was my choice since it's not a lot of work, I'm not doing anything especially complex in my modules and I don't plan on sharing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m with anyone. By choosing this option I'm almost guaranteeing to do something in an incorrect way, do it manually at your own risk!

Create cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Module


Puppet lets you store modules pretty much anywhere on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 filesystem you want to, provided you tell it where to find cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m. I like using /etc/puppetlabs/code/modules so that's where I'll create this one.

First I'll change to that directory:

cd /etc/puppetlabs/code/modules

Then I'll make cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 directory structure and required files for my new module, "my_users". Ordinarily I would name using "camel case" or "stair-stepped case" - "myUsers" - but when cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 puppet agent does a manifest lookup it would look for "myusers" and that would fail. I have several classes with an underscore in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 name now...

mkdir my_users
mkdir my_users/manifests
touch my_users/metadata.json
touch my_users/manifests/init.pp

Then I'll add cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 'my_users/metadata.json' file:


Here is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 copy/paste version:

{
  "name": "test-my_users",
  "version": "0.0.1",
  "author": "my name",
  "summary": "User and group standardisation for my VMs",
  "license": "BSD 3-Clause",
  "source": "",
  "project_page": "",
  "issues_url": "",
  "dependencies": [
    { "name":"puppetlabs-stdlib", "version_requirement":">=1.0.0" }
  ],
  "data_provider": null
}

A few quick items. Notice I've named it "test-my_users". The name of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 module is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 format -. I'm just using "test" because, well, this is a test after all! I've used "my name" as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 author but it doesn't matter which name you use here. I like cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 3-Clause BSD licence, also known as BSD 2.0, so that's what I'm using - it basically says use cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 module however you want but do so at your own risk, I'm not liable if it destroys your data centre, just using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 module doesn't mean you'll get support, I'm not endorsing your product and, if you use cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 module in your product, you have to say you're using it. Read cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 licences that are out cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y're important.

Right now I just want to get a module that loads so I'm going to use a very basic my_users/init.pp file. All I'm putting in it is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 initial class declaration:


At this point it doesn't do anything but it's a good time to see if I can use it with a manifest.

Include and Require


There are two ways to make sure a manifest uses a module or class - eicá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r by using "include" or by using "require". These have two very different meanings!

"include" tells puppet to make sure cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 contents of a class are included when it generates cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 list of things for an agent to do. You could, in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ory, include ten different classes that all include each ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r and puppet can sort that out. Using "include" does not put any specific constraints on ordering - it lets puppet sort all of that out.

"require" tells puppet to make sure cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 contents of a class are included *in a specific order". If puppet sees a "require" statement, it will make sure everything that is part of that "require" statement is done before continuing. That is great if you need to have things happen in a certain order, ensure specific files exist before starting a service, etc., but in general it can lead to some serious management headaches. I will use "include" unless I absolutely need to use a "require".

Using a Module or Class in a Manifest


I know that baracá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365on, my actual puppet server, is set to be managed by puppet because I configured it that way in my Puppet Part One post - if you read that post, though, you'll see it has an empty manifest. All cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 manifest contains is:

node baracá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365on { }

(reminder: I put that file at /etc/puppetlabs/code/environments/production/manifests/baracá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365on.pp)

To use cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 'my_users' module, I need to add a single line to baracá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365on's manifest file. After editing, it will look like this:


For copy/paste, that is:

node baracá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365on {
  include my_users
}

This tells puppet to look in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 module directories and use/include cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 class named 'my_users'. I also could have used:

node baracá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365on {
  require Class['my_users']
}

Again, I don't have a specific need to use "require" so I'm using "include".

The Test...


Now that I've told puppet to use cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 "my_users" module, I need to test it. I can do that with:

sudo /opt/puppet/bin/puppet agent --test

If everything is good, it should compile cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 catalogue and return me to a prompt:


Success! Now I'm ready to make cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 module do something useful.

Make my_users Useful


A module is made of classes and classes do one thing. Ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365rwise, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y do cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same thing as a system's manifest! Since I have already written cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code/configuration necessary to do user stuff in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 stark.pp manifest, I'm going to copy it into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 my_users class:


Then I'm going to test it with "puppet agent --test":


Oh no, something went wrong! ... or did it? Remember, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 problem I'm trying to solve from Puppet Part Two is that I have Ubuntu systems with a user named 'test' and CentOS systems with a user named 'demo'. My goal is to remove those users and add one named 'secops'. Since I'm logged in as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 'test' user, it's going to fail on deleting cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 'test' user and group. I have two choices - I can eicá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r logout and wait ten minutes (because I have puppet configured to run every ten minutes) or I can just reboot cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 machine. I'm going to reboot...

With cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 VM rebooted, I'm going to see if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 'test' user still exists:


Notice cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 'Login incorrect' - cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 system did remove cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 'test' user! But am I locked out?


No, I'm not! Success!

Just because you can use puppet to manage itself doesn't mean that's always a good idea. Weigh cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 cost/benefit before doing this. I like this example because it shows how quickly and easily you can lock yourself out of your management server. BE CAREFUL!

Wrapping Up


Now that I have a class for user management, I can start to simplify management. First, I can edit cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 manifest for stark and cut out everything I have in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re -- and replace it with an include for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 my_users module, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same way I did for baracá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365on. I can add cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same include statement to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 manifests for lannister and bolton. By using modules/classes, I can write one time and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n include it everywhere I want to have cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 'secops' user with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 'secopspass' password.

To go even furcá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r, if I need to change cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 password for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 'secops' user on all of my systems, add a different user, add an SSH key or more, I only need to edit cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 my_users class and that change propagates to all systems that use it. That is MUCH more efficient (and reliable!) than having that functionality in each server's manifest and editing possibly hundreds or thousands of files just to make one small change.

As I pointed out in a previous post, Puppet is not alone in this functionality. SCCM, ansible, chef and ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365rs are all capable and each brings cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir own strengths/weaknesses to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 table. Each one deserves a close look and consideration, even in smaller environments.

No comments:

Post a Comment

Note: only a member of this blog may post a comment.

Parallelising Python: What Happens When a Beginner Discovers Multiprocessing

Some of you will remember that I have a few scripts that can be used for incident response in G Suite environments, available at: https...