From: Stephen Gran <steve@lobefin.net> Date: Thu, 5 Apr 2012 06:59:22 +0000 (+0100) Subject: add tools directory X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=66b30d19cf524bbae55a178445fbb6079ba07765;p=dsa-puppet.git add tools directory Signed-off-by: Stephen Gran <steve@lobefin.net> --- diff --git a/tools/git-hooks/pre-commit b/tools/git-hooks/pre-commit new file mode 100755 index 00000000..23e6e6aa --- /dev/null +++ b/tools/git-hooks/pre-commit @@ -0,0 +1,151 @@ +#!/bin/bash + +if git rev-parse --verify HEAD &>/dev/null; then + against=HEAD +else + # Initial commit: diff against an empty tree object + against=4b825dc642cb6eb9a060e54bf8d69288fbee4904 +fi + +check_puppet_manifest () { + local file=$1 + + local pp=${workdir}/${file} + mkdir -p $(dirname ${pp}) + git cat-file blob :0:${file} | sed 's/^import .*/#&/' >${pp} + trap "rm -f ${pp}" RETURN + + local output=$(puppet apply --noop --ignoreimport ${pp} 2>&1) + if [ $? -ne 0 ] || [ -n "${output}" ]; then + echo '** Syntax check failed:' >&2 + echo "${output}" >&2 + return 1 + fi + + # Check manifests for exactly one class or define per file. + case "${file}" in + modules/*/manifests/*) + if [[ "$(egrep -c '^(class|define) ' ${file})" != "1" ]]; then + echo "** Multiple class/defines:" >&2 + egrep -n '^(class|define) ' ${file} >&2 + return 1 + fi + ;; + esac + + case "${file}" in + manifests/site.pp|modules/*/manifests/*) ;; + *) return + esac + + if [ -x /usr/bin/pcregrep ]; then + local wsfail=$({ + # grep -nPT would be nice. grep -P seems broken on gudeploy01. + # Patterns checked for are (in this order): + # - leading SPACE + # - SPACE followed by TAB + # - TAB followed by SPACE + # - non-leading TAB (but allow around '#' comment leader) + # - trailing whitespace + pcregrep -n -e '^ ' -e ' \t' -e '\t ' -e '[^\t#]\t+(?!#)' -e '\s+$' ${pp} + }) + if [[ $(wc -l <${pp}) > $(cat -s ${pp}|wc -l) ]]; then + wsfail+="Excess blank line(s). 'cat -s' is your friend." + fi + if [[ -n "${wsfail}" ]]; then + echo '** Bad whitespace (see Manifest Standards):' >&2 + echo "${wsfail}" >&2 + return 1 + fi + else + echo "Missing pcregrep: apt-get install pcregrep" >&2 + fi + + case "${file}" in + manifests/site.pp|modules/*/manifests/*) + if [[ -n "$(which puppet-lint)" ]]; then + puppet-lint --no-hard_tabs-check --no-80chars-check ${pp} >&2 | uniq + else + echo "Please install puppet-lint (gem install puppet-lint)" >&2 + fi + ;; + *) + return + ;; + esac + + return 0 +} + +# Check a Puppet template. +# +check_puppet_template () { + local file=$1 + + # Beware of 'Syntax OK' message on success. + local output=$((git cat-file blob :0:${file}|erb -x -P -T -|ruby -c >/dev/null) 2>&1) + if [[ $? -ne 0 || -n "${output}" ]]; then + echo '** Syntax check failed:' >&2 + echo "${output}" >&2 + return 1 + fi + + return 0 +} + +readonly failed=$(mktemp ${TMPDIR:-/tmp}/git.puppet.pre-commit.XXXXXXXXXX) +readonly missing=$(mktemp ${TMPDIR:-/tmp}/git.puppet.pre-commit.XXXXXXXXXX) +readonly parse=$(mktemp ${TMPDIR:-/tmp}/git.puppet.pre-commit.XXXXXXXXXX) +readonly retest=$(mktemp ${TMPDIR:-/tmp}/git.puppet.pre-commit.XXXXXXXXXX) +readonly workdir=$(mktemp -d ${TMPDIR:-/tmp}/git.puppet.pre-commit.XXXXXXXXXX) +trap "rm -f ${failed} ${missing} ${parse} ${retest}; rm -rf ${workdir}" EXIT + +error=0 +warning=0 +for file in $(git diff-index --name-only --diff-filter=AM --cached ${against}); do + output="" + rc=0 + + case "${file}" in + manifests/site.pp) + output=$(check_puppet_manifest ${file} 2>&1); rc=$?;; + modules/*) + + case "${file}" in + modules/*/manifests/*) + case "${file}" in + # FIXME: doing this so the whitespace check happens + *.pp) output=$(check_puppet_manifest ${file} 2>&1); rc=$?;; + esac + ;; + modules/*/templates/*) + output=$(check_puppet_template ${file} 2>&1); rc=$?;; + esac + ;; + + esac + + if [[ ${rc} -ne 0 || -n "${output}" ]]; then + echo "** ${file}" >&2 + echo "${output}" >&2 + if [[ ${file} != *.pp ]]; then + error=1 + # puppet-lint warnings are acceptable. + elif [[ -n "$(egrep -v '^WARNING: ' <<<${output})" ]]; then + error=1 + else + warning=1 + fi + fi +done + +if [ "$error" -ne 0 ]; then + echo "** Please correct the above errors." >&2 + exit 1 +fi + +if [ "$warning" -ne 0 ]; then + sleep 5 +fi + +exit 0 diff --git a/tools/vim/after/syntax/puppet.vim b/tools/vim/after/syntax/puppet.vim new file mode 100644 index 00000000..20e60367 --- /dev/null +++ b/tools/vim/after/syntax/puppet.vim @@ -0,0 +1,18 @@ +setlocal noexpandtab +setlocal shiftwidth=2 +setlocal tabstop=2 + +syn match puppetBadWhitespace /^ \+/ " leading spaces +syn match puppetBadWhitespace /\s\+$/ " trailing whitespace +syn match puppetBadWhitespace /[^\t]\zs\t\+/ " embedded tab +syn match puppetBadWhitespace /\t\zs \+/ " space(s) following tab +highlight puppetBadWhitespace ctermbg=red guibg=red + +" Spellcheck in comments. +setlocal spell +syn match puppetComment "\s*#.*$" contains=puppetTodo,@Spell +syn region puppetComment start="/\*" end="\*/" contains=puppetTodo,@Spell extend + +" Play nicely with ctags. +setlocal iskeyword=@,48-57,_,:,- " not strictly valid but required +setlocal tags=~/Projects/puppet/tags " you probably need to change this diff --git a/tools/vim/ftdetect/puppet.vim b/tools/vim/ftdetect/puppet.vim new file mode 100644 index 00000000..c9d15ea5 --- /dev/null +++ b/tools/vim/ftdetect/puppet.vim @@ -0,0 +1,2 @@ +" detect puppet filetype +au BufRead,BufNewFile *.pp set filetype=puppet diff --git a/tools/vim/ftplugin/puppet.vim b/tools/vim/ftplugin/puppet.vim new file mode 100644 index 00000000..b6491554 --- /dev/null +++ b/tools/vim/ftplugin/puppet.vim @@ -0,0 +1,94 @@ +" Vim filetype plugin +" Language: Puppet +" Maintainer: Todd Zullinger <tmz@pobox.com> +" Last Change: 2009 Aug 19 +" vim: set sw=4 sts=4: + +if exists("b:did_ftplugin") + finish +endif +let b:did_ftplugin = 1 + +if !exists("no_plugin_maps") && !exists("no_puppet_maps") + if !hasmapto("<Plug>AlignRange") + map <buffer> <LocalLeader>= <Plug>AlignRange + endif +endif + +noremap <buffer> <unique> <script> <Plug>AlignArrows :call <SID>AlignArrows()<CR> +noremap <buffer> <unique> <script> <Plug>AlignRange :call <SID>AlignRange()<CR> + +iabbrev => =><C-R>=<SID>AlignArrows('=>')<CR> +iabbrev +> +><C-R>=<SID>AlignArrows('+>')<CR> + +if exists('*s:AlignArrows') + finish +endif + +let s:arrow_re = '[=+]>' +let s:selector_re = '[=+]>\s*\$.*\s*?\s*{\s*$' + +function! s:AlignArrows(op) + let cursor_pos = getpos('.') + let lnum = line('.') + let line = getline(lnum) + if line !~ s:arrow_re + return + endif + let pos = stridx(line, a:op) + let start = lnum + let end = lnum + let pnum = lnum - 1 + while 1 + let pline = getline(pnum) + if pline !~ s:arrow_re || pline =~ s:selector_re + break + endif + let start = pnum + let pnum -= 1 + endwhile + let cnum = end + while 1 + let cline = getline(cnum) + if cline !~ s:arrow_re || + \ (indent(cnum) != indent(cnum+1) && getline(cnum+1) !~ '\s*}') + break + endif + let end = cnum + let cnum += 1 + endwhile + call s:AlignSection(start, end) + let cursor_pos[2] = stridx(getline('.'), a:op) + strlen(a:op) + 1 + call setpos('.', cursor_pos) + return '' +endfunction + +function! s:AlignRange() range + call s:AlignSection(a:firstline, a:lastline) +endfunction + +" AlignSection and AlignLine are from the vim wiki: +" http://vim.wikia.com/wiki/Regex-based_text_alignment +function! s:AlignSection(start, end) + let extra = 1 + let sep = s:arrow_re + let maxpos = 0 + let section = getline(a:start, a:end) + for line in section + let pos = match(line, ' *'.sep) + if maxpos < pos + let maxpos = pos + endif + endfor + call map(section, 's:AlignLine(v:val, sep, maxpos, extra)') + call setline(a:start, section) +endfunction + +function! s:AlignLine(line, sep, maxpos, extra) + let m = matchlist(a:line, '\(.\{-}\) \{-}\('.a:sep.'.*\)') + if empty(m) + return a:line + endif + let spaces = repeat(' ', a:maxpos - strlen(m[1]) + a:extra) + return m[1] . spaces . m[2] +endfunction diff --git a/tools/vim/indent/puppet.vim b/tools/vim/indent/puppet.vim new file mode 100644 index 00000000..689e0687 --- /dev/null +++ b/tools/vim/indent/puppet.vim @@ -0,0 +1,76 @@ +" Vim indent file +" Language: Puppet +" Maintainer: Todd Zullinger <tmz@pobox.com> +" Last Change: 2009 Aug 19 +" vim: set sw=4 sts=4: + +if exists("b:did_indent") + finish +endif +let b:did_indent = 1 + +setlocal autoindent smartindent +setlocal indentexpr=GetPuppetIndent() +setlocal indentkeys+=0],0) + +if exists("*GetPuppetIndent") + finish +endif + +" Check if a line is part of an include 'block', e.g.: +" include foo, +" bar, +" baz +function! s:PartOfInclude(lnum) + let lnum = a:lnum + while lnum + let lnum = lnum - 1 + let line = getline(lnum) + if line !~ ',$' + break + endif + if line =~ '^\s*include\s\+[^,]\+,$' + return 1 + endif + endwhile + return 0 +endfunction + +function! s:OpenBrace(lnum) + call cursor(a:lnum, 1) + return searchpair('{\|\[\|(', '', '}\|\]\|)', 'nbW') +endfunction + +function! GetPuppetIndent() + let pnum = prevnonblank(v:lnum - 1) + if pnum == 0 + return 0 + endif + + let line = getline(v:lnum) + let pline = getline(pnum) + let ind = indent(pnum) + + if pline =~ '^\s*#' + return ind + endif + + if pline =~ '\({\|\[\|(\|:\)$' + let ind += &sw + elseif pline =~ ';$' && pline !~ '[^:]\+:.*[=+]>.*' + let ind -= &sw + elseif pline =~ '^\s*include\s\+.*,$' + let ind += &sw + endif + + if pline !~ ',$' && s:PartOfInclude(pnum) + let ind -= &sw + endif + + " Match } }, }; ] ]: ) + if line =~ '^\s*\(}\(,\|;\)\?$\|]:\?$\|)\)' + let ind = indent(s:OpenBrace(v:lnum)) + endif + + return ind +endfunction diff --git a/tools/vim/syntax/puppet.vim b/tools/vim/syntax/puppet.vim new file mode 100644 index 00000000..96052104 --- /dev/null +++ b/tools/vim/syntax/puppet.vim @@ -0,0 +1,115 @@ +" puppet syntax file +" Filename: puppet.vim +" Language: puppet configuration file +" Maintainer: Luke Kanies <luke@madstop.com> +" URL: +" Last Change: +" Version: +" + +" Copied from the cfengine, ruby, and perl syntax files +" For version 5.x: Clear all syntax items +" For version 6.x: Quit when a syntax file was already loaded +if version < 600 + syntax clear +elseif exists("b:current_syntax") + finish +endif + +" match class/definition/node declarations +syn region puppetDefine start="^\s*\(class\|define\|node\)\s" end="{" contains=puppetDefType,puppetDefName,puppetDefArguments,puppetNodeRe +syn keyword puppetDefType class define node inherits contained +syn region puppetDefArguments start="(" end=")" contained contains=puppetArgument,puppetString +syn match puppetArgument "\w\+" contained +syn match puppetArgument "\$\w\+" contained +syn match puppetArgument "'[^']+'" contained +syn match puppetArgument '"[^"]+"' contained +syn match puppetDefName "\w\+" contained +syn match puppetNodeRe "/.*/" contained + +" match 'foo' in 'class foo { ...' +" match 'foo::bar' in 'class foo::bar { ...' +" match 'Foo::Bar' in 'Foo::Bar["..."] +"FIXME: "Foo-bar" doesn't get highlighted as expected, although "foo-bar" does. +syn match puppetInstance "[A-Za-z0-9_-]\+\(::[A-Za-z0-9_-]\+\)*\s*{" contains=puppetTypeName,puppetTypeDefault +syn match puppetInstance "[A-Z][a-z_-]\+\(::[A-Z][a-z_-]\+\)*\s*[[{]" contains=puppetTypeName,puppetTypeDefault +syn match puppetInstance "[A-Z][a-z_-]\+\(::[A-Z][a-z_-]\+\)*\s*<\?<|" contains=puppetTypeName,puppetTypeDefault +syn match puppetTypeName "[a-z]\w*" contained +syn match puppetTypeDefault "[A-Z]\w*" contained + +" match 'foo' in 'foo => "bar"' +syn match puppetParam "\w\+\s*[=+]>" contains=puppetParamName +syn match puppetParamName "\w\+" contained + +" match 'present' in 'ensure => present' +" match '2755' in 'mode => 2755' +" don't match 'bar' in 'foo => bar' +syn match puppetParam "\w\+\s*[=+]>\s*[a-z0-9]\+" contains=puppetParamString,puppetParamName +syn match puppetParamString "[=+]>\s*\w\+" contains=puppetParamKeyword,puppetParamSpecial,puppetParamDigits contained +syn keyword puppetParamKeyword present absent purged latest installed running stopped mounted unmounted role configured file directory link contained +syn keyword puppetParamSpecial true false undef contained +syn match puppetParamDigits "[0-9]\+" + +" match 'template' in 'content => template("...")' +syn match puppetParam "\w\+\s*[=+]>\s*\w\+\s*(" contains=puppetFunction,puppetParamName +" statements +syn region puppetFunction start="^\s*\(alert\|crit\|debug\|emerg\|err\|fail\|include\|info\|notice\|realize\|require\|search\|tag\|warning\)\s*(" end=")" contained contains=puppetString +" rvalues +syn region puppetFunction start="^\s*\(defined\|file\|fqdn_rand\|generate\|inline_template\|regsubst\|sha1\|shellquote\|split\|sprintf\|tagged\|template\|versioncmp\)\s*(" end=")" contained contains=puppetString + +syn match puppetVariable "$[a-zA-Z0-9_:]\+" +syn match puppetVariable "${[a-zA-Z0-9_:]\+}" + +" match anything between simple/double quotes. +" don't match variables if preceded by a backslash. +syn region puppetString start=+'+ skip=+\\\\\|\\'+ end=+'+ +syn region puppetString start=+"+ skip=+\\\\\|\\"+ end=+"+ contains=puppetVariable,puppetNotVariable +syn match puppetString "/[^/]*/" +syn match puppetNotVariable "\\$\w\+" contained +syn match puppetNotVariable "\\${\w\+}" contained + +syn keyword puppetKeyword import inherits include +syn keyword puppetControl case default if else elsif +syn keyword puppetSpecial true false undef + +" comments last overriding everything else +syn match puppetComment "\s*#.*$" contains=puppetTodo +syn region puppetComment start="/\*" end="\*/" contains=puppetTodo extend +syn keyword puppetTodo TODO NOTE FIXME XXX BUG HACK contained + +" Define the default highlighting. +" For version 5.7 and earlier: only when not done already +" For version 5.8 and later: only when an item doesn't have highlighting yet +if version >= 508 || !exists("did_puppet_syn_inits") + if version < 508 + let did_puppet_syn_inits = 1 + command -nargs=+ HiLink hi link <args> + else + command -nargs=+ HiLink hi def link <args> + endif + + HiLink puppetVariable Identifier + HiLink puppetType Identifier + HiLink puppetKeyword Define + HiLink puppetComment Comment + HiLink puppetString String + HiLink puppetParamKeyword String + HiLink puppetParamDigits String + HiLink puppetNotVariable String + HiLink puppetParamSpecial Special + HiLink puppetSpecial Special + HiLink puppetTodo Todo + HiLink puppetControl Statement + HiLink puppetDefType Define + HiLink puppetDefName Type + HiLink puppetNodeRe Type + HiLink puppetTypeName Statement + HiLink puppetTypeDefault Type + HiLink puppetParamName Identifier + HiLink puppetArgument Identifier + HiLink puppetFunction Function + + delcommand HiLink +endif + +let b:current_syntax = "puppet"