Welcome back to our Puppet and Git 200-series classes. With r10k installed and configured, today we can focus on workflows. The first workflow is for a new module, either a brand new module you are creating or simply a “new to you” module, such as importing more modules from the Forge. In our classrom, we will add a single module from the forge and update the base module to make use of it. This will give us a good understanding of the workflow for r10k.
Workflow To Add A New Module
The first step in our workflow is to decided on a module to add to our setup. If you have a particular module you want to use, feel free to substitute it below. I’ve chosen saz-motd, a very simple module that is visible when installed, but will not have a material impact on your nodes. We can see right now that there is no message of the day, so we’ll know when we’re done:
[root@puppet ~]# cat /etc/motd [root@puppet ~]#
Note: We’ll add our module to a feature branch below. It’s a simple module, so this is fine. More complex modules, such as those that include additional facts and functions, should always be installed on the master first to ensure the plugins are synchronized, which means adding them to production. This was discussed on IRC so I don’t have a link to documentation to show how this works; this is the closest I could find. I’ll mention it again when we install such a module, but I wanted to mention it in case the module you chose provides custom facts/functions.
Working On A Feature Branch
Now that we know what we want to do, our first step is to create a feature branch. We’ll need to do this in both our puppet-tutorial (puppet) and our rnelson0-base (module) repos. Use git checkout -b <featurename> in both repos. In the puppet repo, make sure you’re starting from the production branch. As before, I am doing this on my puppet master but this can be done from anywhere.
[root@puppet ~]# cd git/rnelson0-base/ [root@puppet rnelson0-base]# git checkout -b motd Switched to a new branch 'motd' [root@puppet rnelson0-base]# cd ../puppet-tutorial/ [root@puppet puppet-tutorial]# git checkout production Switched to branch 'production' [root@puppet puppet-tutorial]# git checkout -b motd Switched to a new branch 'motd' [root@puppet puppet-tutorial]# ls manifests Puppetfile README.md
Within the puppet repo, we need to update the Puppetfile to add saz-motd. Here’s the line we add, our commit, and our push:
[root@puppet puppet-tutorial]# git diff diff --git a/Puppetfile b/Puppetfile index 9b19e3c..aba0eda 100644 --- a/Puppetfile +++ b/Puppetfile @@ -9,6 +9,7 @@ mod "puppetlabs/stdlib", "4.1.0" mod "saz/ssh", "1.4.0" mod "yguenane/augeas", "0.1.1" mod "yguenane/ygrpms", "0.1.0" +mod "saz/motd" # For our r10k installer mod "zack/r10k", "1.0.2" [root@puppet puppet-tutorial]# git commit -a -m 'Add saz-motd module to Puppetfile' [motd d4c2b22] Add saz-motd module to Puppetfile 1 files changed, 1 insertions(+), 0 deletions(-) [root@puppet puppet-tutorial]# git push origin motd Counting objects: 5, done. Compressing objects: 100% (3/3), done. Writing objects: 100% (3/3), 380 bytes, done. Total 3 (delta 1), reused 0 (delta 0) To https://rnelson0@github.com/rnelson0/puppet-tutorial * [new branch] motd -> motd
Deploy using r10k. When it’s done, you should see that the production environment is unchanged, but there is a new environment motd that contains saz-motd:
[root@puppet puppet-tutorial]# r10k deploy environment -p Faraday: you may want to install system_timer for reliable timeouts [root@puppet puppet-tutorial]# ls /etc/puppet/environments/{production,motd}/modules /etc/puppet/environments/motd/modules: apache base firewall git make ntp portage ruby stdlib ygrpms augeas concat gcc inifile motd pe_gem r10k ssh vcsrepo /etc/puppet/environments/production/modules: apache base firewall git make pe_gem r10k ssh vcsrepo augeas concat gcc inifile ntp portage ruby stdlib ygrpms
Halfway there! Now it’s time to update the base module. Move over to the module repo and include motd in the class. Commit the change and push it upstream
[root@puppet puppet-tutorial]# cd ../rnelson0-base/ [root@puppet rnelson0-base]# vi manifests/init.pp [root@puppet rnelson0-base]# git diff diff --git a/manifests/init.pp b/manifests/init.pp index f605392..6f78ed2 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -37,6 +37,8 @@ # class base { + include ::motd + include ::ssh ::ssh::server::configline { 'PermitRootLogin': value => 'yes' } [root@puppet rnelson0-base]# git commit -a -m 'Include the motd module in the class' [motd ad2a585] Include the motd module in the class 1 files changed, 2 insertions(+), 0 deletions(-) [root@puppet rnelson0-base]# git push origin motd Counting objects: 7, done. Compressing objects: 100% (4/4), done. Writing objects: 100% (4/4), 392 bytes, done. Total 4 (delta 2), reused 0 (delta 0) To https://rnelson0@github.com/rnelson0/rnelson0-base.git * [new branch] motd -> motd
Have r10k deploy again. Check out the content of the base module in each of our two environments:
[root@puppet rnelson0-base]# r10k deploy environment -p Faraday: you may want to install system_timer for reliable timeouts grep: /etc/puppet/environments/motd/base/manifests/*: No such file or directory [root@puppet rnelson0-base]# grep motd /etc/puppet/environments/{production,motd}/modules/base/manifests/*
What the? Our change isn’t present. We made changes, committed them, and pushed them upstream, but they’re nowhere to be found. The key is in how the Puppetfile works. Let’s look at how the module repo is defined:
# Modules from Github mod "base", :git => "git://github.com/rnelson0/rnelson0-base"
We need to make a slight change here. We need to tell r10k to use the feature branch. We do this by adding a “:ref” key with a value of the branch name. After doing this, we push our change upstream and deploy. This time, the change is visible:
[root@puppet puppet-tutorial]# git diff diff --git a/Puppetfile b/Puppetfile index aba0eda..8c93a0f 100644 --- a/Puppetfile +++ b/Puppetfile @@ -25,3 +25,4 @@ mod "puppetlabs/vcsrepo", "0.2.0" # Modules from Github mod "base", - :git => "git://github.com/rnelson0/rnelson0-base" + :git => "git://github.com/rnelson0/rnelson0-base", + :ref => "motd" [root@puppet puppet-tutorial]# git commit -a -m 'Add motd ref to rnelson0-base' [motd 0c54ff7] Add motd ref to rnelson0-base 1 files changed, 1 insertions(+), 1 deletions(-) [root@puppet puppet-tutorial]# git push origin motd Counting objects: 5, done. Compressing objects: 100% (3/3), done. Writing objects: 100% (3/3), 371 bytes, done. Total 3 (delta 1), reused 0 (delta 0) To https://rnelson0@github.com/rnelson0/puppet-tutorial 84f5c41..0c54ff7 motd -> motd [root@puppet puppet-tutorial]# r10k deploy environment -p Faraday: you may want to install system_timer for reliable timeouts [root@puppet puppet-tutorial]# grep motd /etc/puppet/environments/{production,motd}/modules/base/manifests/* /etc/puppet/environments/motd/modules/base/manifests/init.pp: include ::motd
With the change visible, it’s time to test. Run puppet agent against the production environment (no specified environment) and against the new motd environment. We can see that our change is only available in the motd environment:
[root@puppet puppet-tutorial]# puppet agent --test Info: Applying configuration version '1395849183' Notice: Generated from our notify branch Notice: /Stage[main]/Main/Node[puppet.nelson.va]/Notify[Generated from our notify branch]/message: defined 'message' as 'Generated from our notify branch' Notice: Finished catalog run in 1.12 seconds [root@puppet puppet-tutorial]# puppet agent --test --noop --environment motd Info: Applying configuration version '1395976706' Notice: /Stage[main]/Motd/File[/etc/motd]/content: --- /etc/motd 2010-01-12 13:28:22.000000000 +0000 +++ /tmp/puppet-file20140328-9213-jecidq-0 2014-03-28 14:15:25.749425823 +0000 @@ -0,0 +1,8 @@ + +CentOS 6.5 x86_64 + +FQDN: puppet.nelson.va (10.0.0.35) +Processor: 1x Intel(R) Xeon(R) CPU E31220 @ 3.10GHz +Kernel: 2.6.32-431.3.1.el6.x86_64 +Memory: 1.83 GB + Info: /Stage[main]/Motd/File[/etc/motd]: Filebucketed /etc/motd to puppet with sum d41d8cd98f00b204e9800998ecf8427e Notice: /Stage[main]/Motd/File[/etc/motd]/content: content changed '{md5}d41d8cd98f00b204e9800998ecf8427e' to '{md5}68330ab5f136e99ad54fc05e133da4e7' Notice: Generated from our notify branch Notice: /Stage[main]/Main/Node[puppet.nelson.va]/Notify[Generated from our notify branch]/message: defined 'message' as 'Generated from our notify branch' Notice: Finished catalog run in 1.54 seconds
We have one final test. Open a new ssh session to the puppet master and you should see the message of the day on login:
login as: root root@puppet.nelson.va's password: Last login: Fri Mar 28 14:15:02 2014 from 10.0.0.200 CentOS 6.5 x86_64 FQDN: puppet.nelson.va (10.0.0.35) Processor: 1x Intel(R) Xeon(R) CPU E31220 @ 3.10GHz Kernel: 2.6.32-431.3.1.el6.x86_64 Memory: 1.83 GB [root@puppet ~]#
Our feature branch has everything we need. In a production environment, this is when you run all your tests to make sure everything works. This module and the changes aren’t very complex, however, so now we need to merge this successful feature branch into the production branch.
Merge the New Module
The last part of this workflow is to merge our work. In the module repo, this means merging motd into master. In the puppet repo, we have to make one more change, then merge motd into production. Let’s start with the module repo. You’ve seen this before – checkout the branch you want to merge into and merge the feature branch into it. It’s up to your discretion if you want to keep the old branch or delete it. In my case, I’ll keep the branch for people who are following this tutorial, but in a production environment you would probably only keep release tags, like v1.0.0, v1.1.0, etc., and not keep every feature branch.
[root@puppet rnelson0-base]# git branch master * motd [root@puppet rnelson0-base]# git checkout master Switched to branch 'master' [root@puppet rnelson0-base]# git merge motd Updating af364be..ad2a585 Fast-forward manifests/init.pp | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) [root@puppet rnelson0-base]# grep motd manifests/init.pp include ::motd [root@puppet rnelson0-base]# git push origin master Total 0 (delta 0), reused 0 (delta 0) To https://rnelson0@github.com/rnelson0/rnelson0-base.git af364be..ad2a585 master -> master
You can see that the change has been merged and we pushed it upstream. Re-deploy and you’ll see that motd is now part of both the production and motd environments:
[root@puppet rnelson0-base]# r10k deploy environment -p Faraday: you may want to install system_timer for reliable timeouts [root@puppet rnelson0-base]# grep motd /etc/puppet/environments/{production,motd}/modules/base/manifests/* /etc/puppet/environments/production/modules/base/manifests/init.pp: include ::motd /etc/puppet/environments/motd/modules/base/manifests/init.pp: include ::motd
Let’s take a look at the puppet repo. Everything’s working, so we don’t have anything to change, right? Not quite. Let’s take a look at the Puppetfile contents in the motd branch of the puppet repo:
# Modules from Github mod "base", :git => "git://github.com/rnelson0/rnelson0-base", :ref => "motd"
We now have two problems. First, in production, our master branch would end up not including the base module because it could not find a branch motd to retrieve. We can fix this by removing that ref, committing our changes upstream, and redeploying in a few. The second, and more serious problem, is that our production branch is now broken – it was able to pull down the merged changes from base, but the production Puppetfile doesn’t include the new statement for saz-motd. Even though we see the include ::motd statement above, we’re up a creek without a paddle because the motd module is not present and catalog compilation in the production environment fails:
[root@puppet puppet-tutorial]# ls /etc/puppet/environments/production/modules/motd ls: cannot access /etc/puppet/environments/production/modules/motd: No such file or directory [root@puppet puppet-tutorial]# puppet agent --test Error: Could not retrieve catalog from remote server: Error 400 on SERVER: Could not find class ::motd for puppet.nelson.va on node puppet.nelson.va Warning: Not using cache on failed catalog Error: Could not retrieve catalog; skipping run
We need to fix both problems. We’ll fix the second one first. In the puppet repo, check out the production branch and merge the changes from motd.
[root@puppet puppet-tutorial]# git branch master * motd production [root@puppet puppet-tutorial]# git checkout production Switched to branch 'production' [root@puppet puppet-tutorial]# git merge motd Updating bef7066..0c54ff7 Fast-forward Puppetfile | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-)
Fix the second issue by removing the references to motd in the Puppetfile (don’t forget to remove the trailing space on the mod line!), committing, and pushing the changes to github. After re-deploying, we can see the base class includes motd, the files for motd are present, and the Puppetfile does not reference motd in any way.
[root@puppet puppet-tutorial]# vi Puppetfile [root@puppet puppet-tutorial]# tail -3 Puppetfile # Modules from Github mod "base", :git => "git://github.com/rnelson0/rnelson0-base" [root@puppet puppet-tutorial]# git status # On branch production # Changed but not updated: # (use "git add ..." to update what will be committed) # (use "git checkout -- ..." to discard changes in working directory) # # modified: Puppetfile # no changes added to commit (use "git add" and/or "git commit -a") (reverse-i-search)`push': git ^Csh origin master [root@puppet puppet-tutorial]# git commit -a -m 'Remove references to motd feature branch after merging' [production b8a08d0] Remove references to motd feature branch after merging 1 files changed, 1 insertions(+), 1 deletions(-) [root@puppet puppet-tutorial]# git push origin production Counting objects: 5, done. Compressing objects: 100% (3/3), done. Writing objects: 100% (3/3), 373 bytes, done. Total 3 (delta 1), reused 0 (delta 0) To https://rnelson0@github.com/rnelson0/puppet-tutorial 2af5e8b..b8a08d0 production -> production [root@puppet puppet-tutorial]# r10k deploy environment -p Faraday: you may want to install system_timer for reliable timeouts [root@puppet puppet-tutorial]# ls /etc/puppet/environments/production/modules/motd manifests metadata.json Modulefile README.md spec templates tests [root@puppet puppet-tutorial]# grep motd /etc/puppet/environments/{production,motd}/modules/base/manifests/* /etc/puppet/environments/production/modules/base/manifests/init.pp: include ::motd /etc/puppet/environments/motd/modules/base/manifests/init.pp: include ::motd
Last but not least, ensure catalog compilation. We’ll delete /etc/motd to ensure it gets added back:
[root@puppet puppet-tutorial]# rm /etc/motd rm: remove regular file `/etc/motd'? y [root@puppet puppet-tutorial]# puppet agent --test Notice: /Stage[main]/Motd/File[/etc/motd]/ensure: defined content as '{md5}68330ab5f136e99ad54fc05e133da4e7' Notice: Generated from our notify branch Notice: /Stage[main]/Main/Node[puppet.nelson.va]/Notify[Generated from our notify branch]/message: defined 'message' as 'Generated from our notify branch' Notice: Finished catalog run in 1.28 seconds [root@puppet puppet-tutorial]# cat /etc/motd CentOS 6.5 x86_64 FQDN: puppet.nelson.va (10.0.0.35) Processor: 1x Intel(R) Xeon(R) CPU E31220 @ 3.10GHz Kernel: 2.6.32-431.3.1.el6.x86_64 Memory: 1.83 GB
Summary of New Module Workflow
Our work here is complete! The puppet repo (puppet-tutorial) and the module repo (rnelson0-base) have both been updated to use the new motd module. Here’s a recap of the process:
Module Repo:
- Create a new branch in the existing module repo(s): git checkout -b <feature>
- Modify the existing module(s) as needed to reference the new module(s)
- Commit changes: git commit -a -m ‘Add <feature> reference to module’
- Push upstream: git push origin <feature>
Puppet Repo:
- Create a new branch in the puppet repo: git checkout -b <feature>
- Modify Puppetfile:
- Add a reference to the new module. Optionally, add a version (forge) or :ref (git).
- Add a :ref to existing module repos with a value of the new feature branch’s name.
- Commit changes: git commit -a -m ‘Add module <X> to branch <feature>’
- Push upstream: git push origin <feature>
Puppet Master:
- Deploy environments with r10k: r10k deploy environment -p
- Test catalog compilation in the new feature branch: puppet agent –test –noop –environment <feature>
Repeat the above steps until your changes are complete and all tests succeed. When ready, merge the changes:
Module repo:
- Checkout the master branch: git checkout master
- Merge changes from the feature branch: git merge <feature>
- Push upstream: git push origin master
- OPTIONAL – Delete feature branch (recommended for short lived features, not recommended for version tags): git branch -D feature; git push origin :feature
Puppet repo:
- Checkout the production branch: git checkout production
- Merge changes from the feature branch: git merge <feature>
- Update Puppetfile to remove any references to the feature branch.
- Commit changes: git commit -a -m ‘Remove refs to <feature> branches for module <X>’
- Push upstream: git push origin production
- OPTIONAL – Delete feature branch (recommended for short lived features, not recommended for version tags): git branch -D feature; git push origin :feature
Puppet Master:
- Deploy environments with r10k: r10k deploy environment -p
- Test catalog compilation in the production branch: puppet agent –test –noop
Next Workflow
In the next class, we’ll look at the second workflow, working with an existing module. If you followed everything above, you can probably intuit the differences yourself if you’re trying to stay ahead. Check in next week to see how you did!
2 thoughts on “Puppet and Git, 203: r10k Workflow for New Module”