Pushing code around with Git
As we have already seen in the decentralized model, Git can be used to transfer files between machines using a combination of ssh
and ssh
keys. It can also be useful to have a Git hook do the same on each successful commit to the repository.
There exists a hook called post-commit that can be run after a successful commit to the repository. In this recipe, we'll create a hook that updates the code on our Puppet master with code from our Git repository on the Git server.
Getting ready
Follow these steps to get started:
- Create an
ssh
key that can access your Puppet user on your Puppet master and install this key into the Git user's account ongit.example.com
:[git@git ~]$ ssh-keygen -f ~/.ssh/puppet_rsa Generating public/private rsa key pair. Your identification has been saved in /home/git/.ssh/puppet_rsa. Your public key has been saved in /home/git/.ssh/puppet_rsa.pub. Copy the public key into the authorized_keys file of the puppet user on your puppetmaster puppet@puppet:~/.ssh$ cat puppet_rsa.pub >>authorized_keys
- Modify the Puppet account to allow the Git user to log in as follows:
root@puppet:~# chsh puppet -s /bin/bash
How to do it...
Perform the following steps:
- Now that the Git user can log in to the Puppet master as the Puppet user, modify the Git user's
ssh
configuration to use the newly createdssh
key by default:[git@git ~]$ vim .ssh/config Host puppet.example.com IdentityFile ~/.ssh/puppet_rsa
- Add the Puppet master as a remote location for the Puppet repository on the Git server with the following command:
[git@git puppet.git]$ git remote add puppetmaster puppet@puppet.example.com:/etc/puppet/environments/puppet.git
- On the Puppet master, move the
production
directory out of the way and check out your Puppet repository:root@puppet:~# chown -R puppet:puppet /etc/puppet/environments root@puppet:~# sudo -iu puppet puppet@puppet:~$ cd /etc/puppet/environments/ puppet@puppet:/etc/puppet/environments$ mv production production.orig puppet@puppet:/etc/puppet/environments$ git clone git@git.example.com:repos/puppet.git Cloning into 'puppet.git'... remote: Counting objects: 63, done. remote: Compressing objects: 100% (52/52), done. remote: Total 63 (delta 10), reused 0 (delta 0) Receiving objects: 100% (63/63), 9.51 KiB, done. Resolving deltas: 100% (10/10), done.
- Now we have a local bare repository on the Puppet server that we can push to, to remotely clone this into the
production
directory:puppet@puppet:/etc/puppet/environments$ git clone puppet.git production Cloning into 'production'... done.
- Now perform a Git push from the Git server to the Puppet master:
[git@git ~]$ cd repos/puppet.git/ [git@git puppet.git]$ git push puppetmaster Everything up-to-date
- Create a post-commit file in the
hooks
directory of the repository on the Git server with the following contents:[git@git puppet.git]$ vim hooks/post-commit #!/bin/sh git push puppetmaster ssh puppet@puppet.example.com "cd /etc/puppet/environments/production && git pull" [git@git puppet.git]$ chmod 755 hooks/post-commit
- Commit a change to the repository from your laptop and verify that the change is propagated to the Puppet master as follows:
t@mylaptop puppet$ vim README t@mylaptop puppet$ git add README t@mylaptop puppet$ git commit -m "Adding README" [master 8148902] Adding README 1 file changed, 4 deletions(-) t@mylaptop puppet$ git push X11 forwarding request failed on channel 0 Counting objects: 5, done. Delta compression using up to 4 threads. Compressing objects: 100% (3/3), done. Writing objects: 100% (3/3), 371 bytes | 0 bytes/s, done. Total 3 (delta 1), reused 0 (delta 0) remote: To puppet@puppet.example.com:/etc/puppet/environments/puppet.git remote: 377ed44..8148902 master -> master remote: From /etc/puppet/environments/puppet remote: 377ed44..8148902 master -> origin/master remote: Updating 377ed44..8148902 remote: Fast-forward remote: README | 4 ---- remote: 1 file changed, 4 deletions(-) To git@git.example.com:repos/puppet.git 377ed44..8148902 master -> master
How it works...
We created a bare repository on the Puppet master that we then use as a remote for the repository on git.example.com
(remote repositories must be bare). We then clone that bare repository into the production
directory. We add the bare repository on puppet.example.com
as a remote to the bare repository on git.example.com
. We then create a post-receive hook in the repository on git.example.com
.
The hook issues a Git push to the Puppet master bare repository. We then update the production
directory from the updated bare repository on the Puppet master. In the next section, we'll modify the hook to use branches.