Search code examples
scriptingcontrolsversionpuppet

version control for scripts and puppet


I am trying to setup our environment with version control. Our shell scripts have been scattered all around different servers. I don't know from where I have to start to organize it to have version control on it. However, we also use puppet for configuration management which also should have version control. I have following 2 questions which I am not sure if they are possible at least:

  1. Is there a way to have version control on the scripts leaving them in the location whatever they are right now as most the scripts are server specific.
  2. Is there any common solution to use version control for puppet modules and shell scripts or put the scripts in puppet and only version control puppet.

Thanks in advance.


Solution

  • tl;dr:

    1. Is there a way to have version control on the scripts leaving them in the location whatever they are right now as most the scripts are server specific?
    2. Is there any common solution to use version control for puppet modules and shell scripts or put the scripts in puppet and only version control puppet.

    This is possible, but unnecessary if you write your Puppet code to deal with your requirements.

    Generally, when you start using a config management tool like Puppet, you're doing it to move away from managing scripts. Puppet is a way of running commands without writing any scripts, and abstracting the actual steps to run to Puppet and letting it handle it.

    Using Puppet to run existing scripts is normally a temporary situation that you want to eventually refactor into using Puppet execs, then more idempotent Puppet modules and manifests, until eventually all the requirements are met by native Puppet code, so changes are managed purely by puppet.

    For more information of why to do this, see this question: https://serverfault.com/questions/504070/why-use-chef-puppet-over-shell-scripts

    So for example, lets say you start off with a script to install a package if you're on a webserver:

    Note: Steps simplified for examples, code might not actually work
    

    Script example:

    #/bin/bash
    if $HOSTNAME='webserver.example'
      yum install nginx
    fi
    

    And this is located at /var/tmp/install_nginx.sh

    First you could run it with Puppet:

    exec {'/var/tmp/install_nginx.sh':}
    

    However, how do we get that script there in the first place? You could put it there with version control, but then how do you set that up?

    Even if you get that working, this is a bit fiddly: what if the name of the webserver changes, what if you want to use it on multiple servers?

    Then you could create the script with Puppet itself:

    $webserver_host = 'webserver.example'
    
    $nginx_install_script = "if $HOSTNAME=${webserver.example}
         yum install nginx
       fi"
    
    exec {'Install Nginx':
       command => $nginx_install_script
    }
    

    So then if you needed to change the webserver name, you could just change the variable.

    But this is still not idempotent. Puppet has native types that take a lot of the work out of things (Documented here or you can write your own)

    So you could change that code to make it a lot better:

    $webserver_host = 'webserver.example'
    
    if $::fqdn == webserver_host {
      package {'nginx':
         ensure => 'present',
      }
    }
    

    This is more idempotent, it's platform independent.

    This refactoring continues from here.