Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add trivial r10k integration point. #853

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions manifests/init.pp
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,10 @@
#
# $server_git_repo_user:: Git repository user
#
# $server_git_repo_r10k:: Git repository contains Puppetfile for r10k
#
# $server_git_repo_gen_types:: Generate types for environment isolation
#
# $server_git_branch_map:: Git branch to puppet env mapping for the
# default post receive hook
#
Expand Down Expand Up @@ -659,6 +663,8 @@
Array[String] $server_cipher_suites = $puppet::params::server_cipher_suites,
Integer[0] $server_connect_timeout = $puppet::params::server_connect_timeout,
Boolean $server_git_repo = $puppet::params::server_git_repo,
Boolean $server_git_repo_r10k = $puppet::params::server_git_repo_r10k,
Boolean $server_git_repo_gen_types = $puppet::params::server_git_repo_gen_types,
Boolean $server_default_manifest = $puppet::params::server_default_manifest,
Stdlib::Absolutepath $server_default_manifest_path = $puppet::params::server_default_manifest_path,
String $server_default_manifest_content = $puppet::params::server_default_manifest_content,
Expand Down
4 changes: 4 additions & 0 deletions manifests/params.pp
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,10 @@
$server_git_repo_user = $user
# group of the repository
$server_git_repo_group = $user
# check repositories for r10k modules
$server_git_repo_r10k = false
# generate environment specific types
$server_git_repo_gen_types = false
# Override these if you need your own hooks
$server_post_hook_content = 'puppet/server/post-receive.erb'
$server_post_hook_name = 'post-receive'
Expand Down
6 changes: 6 additions & 0 deletions manifests/server.pp
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,10 @@
#
# $git_repo_user:: Git repository user
#
# $git_repo_r10k:: Git repository contains Puppetfile for r10k
#
# $git_repo_gen_types:: Generate types for environment isolation
#
# $git_branch_map:: Git branch to puppet env mapping for the
# default post receive hook
#
Expand Down Expand Up @@ -375,6 +379,8 @@
Integer[0] $connect_timeout = $puppet::server_connect_timeout,
Integer[0] $web_idle_timeout = $puppet::server_web_idle_timeout,
Boolean $git_repo = $puppet::server_git_repo,
Boolean $git_repo_r10k = $puppet::server_git_repo_r10k,
Boolean $git_repo_gen_types = $puppet::server_git_repo_gen_types,
Boolean $default_manifest = $puppet::server_default_manifest,
Stdlib::Absolutepath $default_manifest_path = $puppet::server_default_manifest_path,
String $default_manifest_content = $puppet::server_default_manifest_content,
Expand Down
122 changes: 73 additions & 49 deletions templates/server/post-receive.erb
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
#!/usr/bin/env ruby
# frozen_string_literal: true

#
# Managed by Puppet
#

require 'English'
require 'fileutils'
require 'etc'

$stdout.sync = true
$stderr.sync = true

# Set this to where you want to keep your environments
ENVIRONMENT_BASEDIR = "<%= scope.lookupvar("puppet::server::config::primary_envs_dir") %>"
ENVIRONMENT_BASEDIR = "<%= scope.lookupvar('puppet::server::config::primary_envs_dir') %>"

# post-receive hooks set GIT_DIR to the current repository. If you want to
# clone from a non-local repository, set this to the URL of the repository,
Expand All @@ -25,7 +28,7 @@ BRANCH_MAP = {
"<%= g %>" => "<%= p %>",
<% end -%>
<% end -%>
}
}.freeze

# The git_dir environment variable will override the --git-dir, so we remove it
# to allow us to create new directories cleanly.
Expand All @@ -34,89 +37,110 @@ ENV.delete('GIT_DIR')
# Ensure that we have the underlying directories, otherwise the later commands
# may fail in somewhat cryptic manners.
unless File.directory? ENVIRONMENT_BASEDIR
puts %Q{#{ENVIRONMENT_BASEDIR} does not exist, cannot create environment directories.}
puts %(#{ENVIRONMENT_BASEDIR} does not exist, cannot create environment directories.)
exit 1
end

# If we're running as root we change our UID to the owner of this file.
file_uid = File.stat($0).uid
if file_uid != Process.uid and Process.uid == 0
file_uid = File.stat($PROGRAM_NAME).uid
if (file_uid != Process.uid) && Process.uid.zero?
Process::UID.change_privilege(file_uid)
# Set LOGNAME and HOME directories to file-owning user's values
# so git can read ~/.config/git/attributes (for example) without error
file_pwuid = Etc::getpwuid(file_uid)
ENV.store('LOGNAME',file_pwuid.name)
ENV.store('HOME',file_pwuid.dir)
file_pwuid = Etc.getpwuid(file_uid)
ENV.store('LOGNAME', file_pwuid.name)
ENV.store('HOME', file_pwuid.dir)
end

# Run a command, return its output and abort if it fails
def do_cmd(cmd)
ret = %x{#{cmd}}
if $?.exitstatus != 0
puts("'#{cmd}' failed. Giving up.")
exit 1
end
ret
ret = %x{#{cmd}}
if $CHILD_STATUS.exitstatus != 0
puts("'#{cmd}' failed. Giving up.")
exit 1
end
ret
end

# You can push multiple refspecs at once, like 'git push origin branch1 branch2',
# so we need to handle each one.
$stdin.each_line do |line|
oldrev, newrev, refname = line.split(" ")
$stdin.each_line do |line| # rubocop:disable Metrics/BlockLength
_oldrev, newrev, refname = line.split(' ')

# Determine the branch name from the refspec we're received, which is in the
# format refs/heads/<branch>, and make sure that it doesn't have any possibly
# dangerous characters
branchname = refname.sub(%r{^refs/heads/(.*$)}) { $1 }
if branchname =~ /[\W]/
puts %Q{Branch "#{branchname}" contains non-word characters, ignoring it.}
branchname = refname.sub(%r{^refs/heads/(.*$)}) { Regexp.last_match(1) }
if branchname =~ /\W/
puts %(Branch "#{branchname}" contains non-word characters, ignoring it.)
next
end

if BRANCH_MAP[branchname] != nil
if !BRANCH_MAP[branchname].nil?
environment_name = BRANCH_MAP[branchname]
environment_path = "#{ENVIRONMENT_BASEDIR}/#{BRANCH_MAP[branchname]}"
else
environment_name = branchname
environment_path = "#{ENVIRONMENT_BASEDIR}/#{branchname}"
end

# Perform one of these operations:
# - delete
# - update
# - create
if newrev =~ /^0+$/
# We've received a push with a null revision, something like 000000000000,
# which means that we should delete the given branch.
puts "Deleting existing environment #{environment_name}"
if File.directory? environment_path
FileUtils.rm_rf environment_path, :secure => true
end
else
# We have been given a branch that needs to be created or updated. If the
# environment exists, update it. Else, create it.

if File.directory? environment_path
# Update an existing environment. We do a fetch and then reset in the
# case that someone did a force push to a branch.

puts "Updating existing environment #{environment_name}"
Dir.chdir environment_path
do_cmd("git fetch --all")
do_cmd("git reset --hard 'origin/#{branchname}'")
if File.exists? "#{environment_path}/.gitmodules"
# ensure that we remove deleted sub modules too
do_cmd("git status --short").split("\n").each do |file|
# ?? old_submodule/
if file =~ /\s*\?{2}\s*(\S*)/
puts "Found a few unknown files.. deleting #{$1}"
FileUtils.rm_rf $1, :secure => true
end
FileUtils.rm_rf environment_path, secure: true if File.directory? environment_path
elsif File.directory? environment_path
# Update an existing environment. We do a fetch and then reset in the
# case that someone did a force push to a branch.
# We have been given a branch that needs to be updated.

puts "Updating existing environment #{environment_name}"
Dir.chdir environment_path
do_cmd('git fetch --all')
do_cmd("git reset --hard 'origin/#{branchname}'")
if File.exist? "#{environment_path}/.gitmodules"
# ensure that we remove deleted sub modules too
do_cmd('git status --short').split("\n").each do |file|
# ?? old_submodule/
if file =~ /\s*\?{2}\s*(\S*)/
puts "Found a few unknown files.. deleting #{Regexp.last_match(1)}"
FileUtils.rm_rf Regexp.last_match(1), secure: true
end
do_cmd("git submodule sync")
do_cmd("git submodule update --init --recursive")
end
else
# Instantiate a new environment from the current repository.
do_cmd('git submodule sync')
do_cmd('git submodule update --init --recursive')
<% if @git_repo_r10k -%>
if File.exist? 'Puppetfile'
puts('Installing modules using r10k')
do_cmd('r10k puppetfile install')
end
<% end -%>
<% if @git_repo_gen_types -%>
puts("Generating types for #{environment_name}")
do_cmd("puppet generate types --environmentpath #{ENVIRONMENT_BASEDIR} --environment #{environment_name}")
<% end -%>
end

puts "Creating new environment #{environment_name}"
do_cmd("git clone --recursive #{SOURCE_REPOSITORY} #{environment_path} --branch #{branchname}")
else
# Instantiate a new environment from the current repository.
# We have been given a new branch that needs to be created

puts "Creating new environment #{environment_name}"
do_cmd("git clone --recursive #{SOURCE_REPOSITORY} #{environment_path} --branch #{branchname}")
Dir.chdir environment_path
<% if @git_repo_r10k -%>
if File.exist? 'Puppetfile'
puts('Installing modules using r10k')
do_cmd('r10k puppetfile install')
end
<% end -%>
<% if @git_repo_gen_types -%>
puts("Generating types for #{environment_name}")
do_cmd("puppet generate types --environmentpath #{ENVIRONMENT_BASEDIR} --environment #{environment_name}")
<% end -%>
end
end