Tag Archives: puppet

Testing puppet configs with docker

Many moons ago at $dayjob I created puppet configurations for various systems, at the time my development process was to write the code in a development environment, and then deploy it to a test VM. This gave me the benefits of being able to setup a machine with the standard company baseline, take a snapshot in VMWare, apply my work in progress config, and revert the snapshot back to try again with changes. This works brilliantly. However it does require you have snapshotting available on your VM infrastructure.

Fast forward to today, my aims are a little smaller (my own personal infrastructure of machines) but I still don’t want to wipe anything out so I am obviously wanting to test my code safely before committing to “prod”. Rather than dig into snapshots again, I thought I’d try something a little different. Can I do roughly the same with Docker?

It looks like I might just be able to, although this is pretty rough, it should hopefully be a foot in the door, it certainly seems to work for my experiments.

I am using a simple Dockerfile to build and configure a container which has Puppet installed and a signed certificate. With this container I have essentially a blank server that is registered with my Puppet Master. Each time I stop and start the server I am back to this blank slate, perfect for making sure my scripts will take bare metal to finished product.

The build does require generation of a cert, and you will quite likely end up with a “fun” docker host name in your system. To prevent the Puppet agent generating a new cert each time you run the container, you need to name the certificate in the agent config that will be used. This will be what it is called in your Puppet Master CA too, so make it some thing obvious, it also won’t match the hostname as those are generated by Docker as it runs, and you cannot force one easily whilst building a container (which is the point the cert if being generated and signed). To keep things simple I also downloaded the puppet6-release-bionic.deb file

wget https://apt.puppetlabs.com/puppet6-release-bionic.deb

My configuration files for my little hack are as follows, agent.conf:

[agent]
  server = your.puppet.server.here
  certname = your.certificate.name.here
  environment = dev
  listen = false
  pluginsync = true
  report = true

and the dockerfile:

FROM ubuntu:18.04
COPY puppet6-release-bionic.deb .
RUN dpkg -i puppet6-release-bionic.deb && echo PATH=\$PATH:/opt/puppetlabs/bin >> /root/.bashrc && apt update && apt install -y puppet-agent
COPY agent.conf /etc/puppetlabs/puppet/puppet.conf
RUN /opt/puppetlabs/bin/puppet agent --test --waitforcert 10

Now to build the container:

docker build -t puppet-test . -f puppet-test.Dockerfile

Which will install the packages and perform the initial run of Puppet agent generating a cert and waiting for it to be signed. Once it hits this stage it will poll the Puppet Master CA every 10 seconds to check for a signed cert, so find and sign that cert

# puppetserver ca list
Requested Certificates:
    your.certificate.name.here     (SHA256)  Cert fingerprint
# puppetserver ca sign --certname your.certificate.name.here
Successfully signed certificate request for your.certificate.name.here

At which point Docker build should complete and if you check your docker images you should see puppet-test (or whatever you decided to call it). If you check Foreman or however you are viewing your hosts you will likely see some Docker hostname’d box has appeared with your build machines domain name attached. This is the entity that you need to apply your configuration to test to. With the config set run the container

docker run -it --rm puppet-test

and you will be dropped in at the command prompt, all you need to do now is run Puppet Agent and watch that config apply!

root@6921f888d861:/# puppet agent --test
Info: Using configured environment 'dev'
Info: Retrieving pluginfacts
Info: Retrieving plugin
Info: Retrieving locales
Info: Loading facts
....

Ctrl-D or exit will get you out of the container, and running it again will put you right back with a blank config! perfect for testing new changes.

(remember, if you don’t run your container with –rm you will need to clean up old instances and volumes at some point before you run out of disk 🙂 )

Hopefully this will be useful to someone else, mostly this will help me remember what I did when I forget in 5 minutes 🙂