diff --git a/README.md b/README.md
index 505aee1..e69de29 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +0,0 @@
-salt-multi-environment-gitfs
-============================
-
-Salt Multi-environment gitfs example.
diff --git a/master b/master
new file mode 100644
index 0000000..f78b27d
--- /dev/null
+++ b/master
@@ -0,0 +1,9 @@
+fileserver_backend:
+ - git
+gitfs_remotes:
+ - git+ssh://git@github.com/bretep/salt-multi-environment-gitfs.git
+gitfs_root: states
+ext_pillar:
+ - git: dev git+ssh://git@github.com/bretep/salt-multi-environment-gitfs.git
+ - git: stg git+ssh://git@github.com/bretep/salt-multi-environment-gitfs.git
+ - git: prd git+ssh://git@github.com/bretep/salt-multi-environment-gitfs.git
diff --git a/minion b/minion
new file mode 100644
index 0000000..bbbaba6
--- /dev/null
+++ b/minion
@@ -0,0 +1,2 @@
+master: salt.example.com
+environment: dev
diff --git a/pillars/dev/init.sls b/pillars/dev/init.sls
new file mode 100644
index 0000000..765cc72
--- /dev/null
+++ b/pillars/dev/init.sls
@@ -0,0 +1,4 @@
+{{ saltenv if saltenv != None else env}}:
+ '*':
+ - pillars.users
+ - pillars.{{ saltenv if saltenv != None else env}}.pkgs
diff --git a/pillars/dev/pkgs.sls b/pillars/dev/pkgs.sls
new file mode 100644
index 0000000..1c703d8
--- /dev/null
+++ b/pillars/dev/pkgs.sls
@@ -0,0 +1,4 @@
+pkgs:
+ pip:
+ awscli: 1.3.0
+ newrelic: 2.14.0.11
diff --git a/pillars/prd/init.sls b/pillars/prd/init.sls
new file mode 100644
index 0000000..765cc72
--- /dev/null
+++ b/pillars/prd/init.sls
@@ -0,0 +1,4 @@
+{{ saltenv if saltenv != None else env}}:
+ '*':
+ - pillars.users
+ - pillars.{{ saltenv if saltenv != None else env}}.pkgs
diff --git a/pillars/prd/pkgs.sls b/pillars/prd/pkgs.sls
new file mode 100644
index 0000000..1c703d8
--- /dev/null
+++ b/pillars/prd/pkgs.sls
@@ -0,0 +1,4 @@
+pkgs:
+ pip:
+ awscli: 1.3.0
+ newrelic: 2.14.0.11
diff --git a/pillars/stg/init.sls b/pillars/stg/init.sls
new file mode 100644
index 0000000..765cc72
--- /dev/null
+++ b/pillars/stg/init.sls
@@ -0,0 +1,4 @@
+{{ saltenv if saltenv != None else env}}:
+ '*':
+ - pillars.users
+ - pillars.{{ saltenv if saltenv != None else env}}.pkgs
diff --git a/pillars/stg/pkgs.sls b/pillars/stg/pkgs.sls
new file mode 100644
index 0000000..1c703d8
--- /dev/null
+++ b/pillars/stg/pkgs.sls
@@ -0,0 +1,4 @@
+pkgs:
+ pip:
+ awscli: 1.3.0
+ newrelic: 2.14.0.11
diff --git a/pillars/users/init.sls b/pillars/users/init.sls
new file mode 100644
index 0000000..5c5c87b
--- /dev/null
+++ b/pillars/users/init.sls
@@ -0,0 +1,17 @@
+users:
+ jdoe:
+ fullname: John Doe
+ shell: /bin/bash
+ groups:
+ - _default
+ - dev
+ - prd
+ - stg
+ ssh_keys:
+ - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCpkoPTGHOdmSVgIlzBY7Z+K3sGWqb2nqVUIwi+8dhK5Wnlg081Swpb9ZXhCAHqogQoZ0e1CHa9z4TppXHB2+8bLkVEXAMPLEm+SJx3f4LraSRNlKiaaR1uMlk0E7A+uglOvQ/6Abu/F3Wid2M9EhMqsNyAbe1fdtZWLQTC3olbO+HxkFjXzVFxlSmzobu5dgFBXo2p9UaPg5e+SBcyyjDgwy3oeuCBBhireDnc547SDWiEc0JaSyt/wl0iE/UziOwtBd5DYErqgjs18t+sk3qjhR8XJvZoNpmwoklYlW08WkPHdHjmSyrw6aZf30Hyc3Xm1DL16BrtWuY7ndyFYJoOx+h jdoe_examplee
+
+ dummy:
+ fullname: Dummy Person
+ shell: /bin/bash
+ groups:
+ - user
diff --git a/states/_grains/ec2_info.py b/states/_grains/ec2_info.py
new file mode 100644
index 0000000..1db56ed
--- /dev/null
+++ b/states/_grains/ec2_info.py
@@ -0,0 +1,88 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+"""
+Get some grains information that is only available in Amazon AWS
+
+Author: Erik Günther
+
+"""
+import logging
+import httplib
+import socket
+import json
+
+# Set up logging
+LOG = logging.getLogger(__name__)
+
+
+def _call_aws(url):
+ """
+ Call AWS via httplib. Require correct path.
+ Host: 169.254.169.254
+
+ """
+ conn = httplib.HTTPConnection("169.254.169.254", 80, timeout=1)
+ conn.request('GET', url)
+ response = conn.getresponse()
+ if response.status == 200:
+ return response.read()
+
+
+def _get_ec2_hostinfo(path="", data={}):
+ """
+ Recursive function that walks the EC2 metadata available to each minion.
+ :param path: URI fragment to append to /latest/meta-data/
+ :param data: Dictionary containing the results from walking the AWS meta-data
+
+ All EC2 variables are prefixed with "ec2_" so they are grouped as grains and to
+ avoid collisions with other grain names.
+ """
+ for line in _call_aws("/latest/meta-data/%s" % path).split("\n"):
+ if line[-1] != "/":
+ call_response = _call_aws("/latest/meta-data/%s" % (path + line))
+ if call_response is not None:
+ data["ec2_" + path.replace("/", "_") + line] = call_response
+ else:
+ data["ec2_" + path.replace("/", "_")[:-1]] = line
+ else:
+ _get_ec2_hostinfo(path + line, data=data)
+
+
+def _get_ec2_region():
+ """
+ Recursive call in _get_ec2_hostinfo() does not retrieve a node's region
+ """
+ data = _call_aws("/latest/dynamic/instance-identity/document")
+ return json.loads(data)['region']
+
+
+def ec2_info():
+ """
+ Collect some extra host information
+ """
+ try:
+ # First check that the AWS magic URL works. If it does
+ # we are running in AWS and will try to get more data.
+ _call_aws('/')
+ except (socket.timeout, socket.error, IOError):
+ return {}
+
+ try:
+ grains = {}
+ _get_ec2_hostinfo(data=grains)
+ grains['ec2_region'] = _get_ec2_region()
+ return grains
+ except socket.timeout, serr:
+ LOG.info("Could not read EC2 data (timeout): %s" % (serr))
+ return {}
+
+ except socket.error, serr:
+ LOG.info("Could not read EC2 data (error): %s" % (serr))
+ return {}
+
+ except IOError, serr:
+ LOG.info("Could not read EC2 data (IOError): %s" % (serr))
+ return {}
+
+if __name__ == "__main__":
+ print ec2_info()
diff --git a/states/dev.sls b/states/dev.sls
new file mode 100644
index 0000000..55ab9ce
--- /dev/null
+++ b/states/dev.sls
@@ -0,0 +1,5 @@
+{{ pillar['master']['environment'] }}:
+ '*':
+ - users
+ - sudo
+ - awscli
diff --git a/states/prd.sls b/states/prd.sls
new file mode 100644
index 0000000..14b5ae0
--- /dev/null
+++ b/states/prd.sls
@@ -0,0 +1,4 @@
+{{ pillar['master']['environment'] }}:
+ '*':
+ - users
+ - sudo
diff --git a/states/stg.sls b/states/stg.sls
new file mode 100644
index 0000000..14b5ae0
--- /dev/null
+++ b/states/stg.sls
@@ -0,0 +1,4 @@
+{{ pillar['master']['environment'] }}:
+ '*':
+ - users
+ - sudo
diff --git a/states/sudo/init.sls b/states/sudo/init.sls
new file mode 100644
index 0000000..4932446
--- /dev/null
+++ b/states/sudo/init.sls
@@ -0,0 +1,13 @@
+sudo:
+ pkg.installed
+
+sudouser:
+ group.present:
+ - system: True
+
+/etc/sudoers.d/sudouser:
+ file.managed:
+ - user: root
+ - group: root
+ - mode: 440
+ - source: salt://sudo/sudouser
diff --git a/states/sudo/sudouser b/states/sudo/sudouser
new file mode 100644
index 0000000..3018765
--- /dev/null
+++ b/states/sudo/sudouser
@@ -0,0 +1 @@
+%sudouser ALL=(ALL) NOPASSWD:ALL
diff --git a/states/top.sls b/states/top.sls
new file mode 100644
index 0000000..a0489b3
--- /dev/null
+++ b/states/top.sls
@@ -0,0 +1,2 @@
+include:
+ - {{ pillar['master']['environment'] }}
diff --git a/states/users/_default/.bash_logout b/states/users/_default/.bash_logout
new file mode 100644
index 0000000..de4f5f7
--- /dev/null
+++ b/states/users/_default/.bash_logout
@@ -0,0 +1,7 @@
+# ~/.bash_logout: executed by bash(1) when login shell exits.
+
+# when leaving the console clear the screen to increase privacy
+
+if [ "$SHLVL" = 1 ]; then
+ [ -x /usr/bin/clear_console ] && /usr/bin/clear_console -q
+fi
diff --git a/states/users/_default/.bashrc b/states/users/_default/.bashrc
new file mode 100644
index 0000000..83b063a
--- /dev/null
+++ b/states/users/_default/.bashrc
@@ -0,0 +1,107 @@
+# ~/.bashrc: executed by bash(1) for non-login shells.
+# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
+# for examples
+
+# If not running interactively, don't do anything
+[ -z "$PS1" ] && return
+
+# don't put duplicate lines or lines starting with space in the history.
+# See bash(1) for more options
+HISTCONTROL=ignoreboth
+
+# append to the history file, don't overwrite it
+shopt -s histappend
+
+# for setting history length see HISTSIZE and HISTFILESIZE in bash(1)
+HISTSIZE=1000
+HISTFILESIZE=2000
+
+# check the window size after each command and, if necessary,
+# update the values of LINES and COLUMNS.
+shopt -s checkwinsize
+
+# If set, the pattern "**" used in a pathname expansion context will
+# match all files and zero or more directories and subdirectories.
+#shopt -s globstar
+
+# make less more friendly for non-text input files, see lesspipe(1)
+[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)"
+
+# set variable identifying the chroot you work in (used in the prompt below)
+if [ -z "$debian_chroot" ] && [ -r /etc/debian_chroot ]; then
+ debian_chroot=$(cat /etc/debian_chroot)
+fi
+
+# set a fancy prompt (non-color, unless we know we "want" color)
+case "$TERM" in
+ xterm-color) color_prompt=yes;;
+esac
+
+# uncomment for a colored prompt, if the terminal has the capability; turned
+# off by default to not distract the user: the focus in a terminal window
+# should be on the output of commands, not on the prompt
+#force_color_prompt=yes
+
+if [ -n "$force_color_prompt" ]; then
+ if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then
+ # We have color support; assume it's compliant with Ecma-48
+ # (ISO/IEC-6429). (Lack of such support is extremely rare, and such
+ # a case would tend to support setf rather than setaf.)
+ color_prompt=yes
+ else
+ color_prompt=
+ fi
+fi
+
+if [ "$color_prompt" = yes ]; then
+ PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
+else
+ PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
+fi
+unset color_prompt force_color_prompt
+
+# If this is an xterm set the title to user@host:dir
+case "$TERM" in
+xterm*|rxvt*)
+ PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1"
+ ;;
+*)
+ ;;
+esac
+
+# enable color support of ls and also add handy aliases
+if [ -x /usr/bin/dircolors ]; then
+ test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)"
+ alias ls='ls --color=auto'
+ #alias dir='dir --color=auto'
+ #alias vdir='vdir --color=auto'
+
+ alias grep='grep --color=auto'
+ alias fgrep='fgrep --color=auto'
+ alias egrep='egrep --color=auto'
+fi
+
+# some more ls aliases
+alias ll='ls -alF'
+alias la='ls -A'
+alias l='ls -CF'
+
+# Add an "alert" alias for long running commands. Use like so:
+# sleep 10; alert
+alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"'
+
+# Alias definitions.
+# You may want to put all your additions into a separate file like
+# ~/.bash_aliases, instead of adding them here directly.
+# See /usr/share/doc/bash-doc/examples in the bash-doc package.
+
+if [ -f ~/.bash_aliases ]; then
+ . ~/.bash_aliases
+fi
+
+# enable programmable completion features (you don't need to enable
+# this, if it's already enabled in /etc/bash.bashrc and /etc/profile
+# sources /etc/bash.bashrc).
+if [ -f /etc/bash_completion ] && ! shopt -oq posix; then
+ . /etc/bash_completion
+fi
diff --git a/states/users/_default/.profile b/states/users/_default/.profile
new file mode 100644
index 0000000..c9db459
--- /dev/null
+++ b/states/users/_default/.profile
@@ -0,0 +1,22 @@
+# ~/.profile: executed by the command interpreter for login shells.
+# This file is not read by bash(1), if ~/.bash_profile or ~/.bash_login
+# exists.
+# see /usr/share/doc/bash/examples/startup-files for examples.
+# the files are located in the bash-doc package.
+
+# the default umask is set in /etc/profile; for setting the umask
+# for ssh logins, install and configure the libpam-umask package.
+#umask 022
+
+# if running bash
+if [ -n "$BASH_VERSION" ]; then
+ # include .bashrc if it exists
+ if [ -f "$HOME/.bashrc" ]; then
+ . "$HOME/.bashrc"
+ fi
+fi
+
+# set PATH so it includes user's private bin if it exists
+if [ -d "$HOME/bin" ] ; then
+ PATH="$HOME/bin:$PATH"
+fi
diff --git a/states/users/init.sls b/states/users/init.sls
new file mode 100644
index 0000000..5787044
--- /dev/null
+++ b/states/users/init.sls
@@ -0,0 +1,46 @@
+{% set salt_env = pillar['master']['environment'] %}
+# Add each user
+{% for user, user_data in pillar['users'].iteritems() %}
+user_{{ user }}:
+ user.present:
+ - name: {{ user }}
+ - fullname: {{ salt['pillar.get']('users:' + user + ':fullname', 'No Name') }}
+ - shell: {{ salt['pillar.get']('users:' + user + ':shell', '/bin/bash') }}
+{% if 'groups' in pillar['users'][user] %}
+ - optional_groups:
+{% for group in salt['pillar.get']('users:' + user + ':groups', []) %}
+ - {{ group }}
+{% if group == salt_env %}
+ - wheel
+{% endif %}{% endfor %}
+ - require:
+ - group: sudouser
+{% endif %}
+
+# Enforce home directory
+cp_user_home_{{ user }}:
+ file.recurse:
+ - name: /home/{{ user }}
+ - user: {{ user }}
+ - group: {{ user }}
+{% if 'users/' + user in salt['cp.list_master_dirs'](salt_env) %}
+ - source: salt://users/{{ user }}
+{% else %}
+ - source: salt://users/_default
+{% endif %}
+ - include_empty: True
+ - require:
+ - user: user_{{ user }}
+
+# Check SSH key and add
+{% if 'ssh_keys' in pillar['users'][user] %}
+ssh_keys_{{ user }}:
+ ssh_auth.present:
+ - user: {{ user }}
+ - names:
+{% for ssh_key in salt['pillar.get']('users:' + user + ':ssh_keys', []) %}
+ - {{ ssh_key }}{% endfor %}
+ - require:
+ - user: user_{{ user }}
+ - file: cp_user_home_{{ user }}
+{% endif %}{% endfor %}
diff --git a/states/users/jdoe/.bashrc b/states/users/jdoe/.bashrc
new file mode 100644
index 0000000..3e77b02
--- /dev/null
+++ b/states/users/jdoe/.bashrc
@@ -0,0 +1,107 @@
+# ~/.bashrc: executed by bash(1) for non-login shells.
+# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
+# for examples
+
+# If not running interactively, don't do anything
+[ -z "$PS1" ] && return
+
+# don't put duplicate lines or lines starting with space in the history.
+# See bash(1) for more options
+HISTCONTROL=ignoreboth
+
+# append to the history file, don't overwrite it
+shopt -s histappend
+
+# for setting history length see HISTSIZE and HISTFILESIZE in bash(1)
+HISTSIZE=1000
+HISTFILESIZE=2000
+
+# check the window size after each command and, if necessary,
+# update the values of LINES and COLUMNS.
+shopt -s checkwinsize
+
+# If set, the pattern "**" used in a pathname expansion context will
+# match all files and zero or more directories and subdirectories.
+#shopt -s globstar
+
+# make less more friendly for non-text input files, see lesspipe(1)
+[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)"
+
+# set variable identifying the chroot you work in (used in the prompt below)
+if [ -z "$debian_chroot" ] && [ -r /etc/debian_chroot ]; then
+ debian_chroot=$(cat /etc/debian_chroot)
+fi
+
+# set a fancy prompt (non-color, unless we know we "want" color)
+case "$TERM" in
+ xterm-color) color_prompt=yes;;
+esac
+
+# uncomment for a colored prompt, if the terminal has the capability; turned
+# off by default to not distract the user: the focus in a terminal window
+# should be on the output of commands, not on the prompt
+#force_color_prompt=yes
+
+if [ -n "$force_color_prompt" ]; then
+ if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then
+ # We have color support; assume it's compliant with Ecma-48
+ # (ISO/IEC-6429). (Lack of such support is extremely rare, and such
+ # a case would tend to support setf rather than setaf.)
+ color_prompt=yes
+ else
+ color_prompt=
+ fi
+fi
+
+if [ "$color_prompt" = yes ]; then
+ PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
+else
+ PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
+fi
+unset color_prompt force_color_prompt
+
+# If this is an xterm set the title to user@host:dir
+case "$TERM" in
+xterm*|rxvt*)
+ PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1"
+ ;;
+*)
+ ;;
+esac
+
+# enable color support of ls and also add handy aliases
+if [ -x /usr/bin/dircolors ]; then
+ test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)"
+ alias ls='ls --color=auto'
+ #alias dir='dir --color=auto'
+ #alias vdir='vdir --color=auto'
+
+ alias grep='grep --color=auto'
+ alias fgrep='fgrep --color=auto'
+ alias egrep='egrep --color=auto'
+fi
+
+# some more ls aliases
+alias ll='ls -alF'
+alias la='ls -A'
+alias l='ls -CF'
+
+# Add an "alert" alias for long running commands. Use like so:
+# sleep 10; alert
+alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"'
+
+# Alias definitions.
+# You may want to put all your additions into a separate file like
+# ~/.bash_aliases, instead of adding them here directly.
+# See /usr/share/doc/bash-doc/examples in the bash-doc package.
+
+if [ -f ~/.bash_aliases ]; then
+ . ~/.bash_aliases
+fi
+
+# enable programmable completion features (you don't need to enable
+# this, if it's already enabled in /etc/bash.bashrc and /etc/profile
+# sources /etc/bash.bashrc).
+if [ -f /etc/bash_completion ] && ! shopt -oq posix; then
+ . /etc/bash_completion
+fi
diff --git a/states/users/jdoe/.vim/.netrwhist b/states/users/jdoe/.vim/.netrwhist
new file mode 100644
index 0000000..ad468ac
--- /dev/null
+++ b/states/users/jdoe/.vim/.netrwhist
@@ -0,0 +1,3 @@
+let g:netrw_dirhistmax =10
+let g:netrw_dirhist_cnt =1
+let g:netrw_dirhist_1='/Users/bpalsson/Documents/Work/git/opensource/salt-development/salt/roots/salt'
diff --git a/states/users/jdoe/.vim/autoload/pathogen.vim b/states/users/jdoe/.vim/autoload/pathogen.vim
new file mode 100644
index 0000000..7b89cca
--- /dev/null
+++ b/states/users/jdoe/.vim/autoload/pathogen.vim
@@ -0,0 +1,326 @@
+" pathogen.vim - path option manipulation
+" Maintainer: Tim Pope
+" Version: 2.2
+
+" Install in ~/.vim/autoload (or ~\vimfiles\autoload).
+"
+" For management of individually installed plugins in ~/.vim/bundle (or
+" ~\vimfiles\bundle), adding `execute pathogen#infect()` to the top of your
+" .vimrc is the only other setup necessary.
+"
+" The API is documented inline below. For maximum ease of reading,
+" :set foldmethod=marker
+
+if exists("g:loaded_pathogen") || &cp
+ finish
+endif
+let g:loaded_pathogen = 1
+
+function! s:warn(msg)
+ echohl WarningMsg
+ echomsg a:msg
+ echohl NONE
+endfunction
+
+" Point of entry for basic default usage. Give a relative path to invoke
+" pathogen#incubate() (defaults to "bundle/{}"), or an absolute path to invoke
+" pathogen#surround(). For backwards compatibility purposes, a full path that
+" does not end in {} or * is given to pathogen#runtime_prepend_subdirectories()
+" instead.
+function! pathogen#infect(...) abort " {{{1
+ for path in a:0 ? reverse(copy(a:000)) : ['bundle/{}']
+ if path =~# '^[^\\/]\+$'
+ call s:warn('Change pathogen#infect('.string(path).') to pathogen#infect('.string(path.'/{}').')')
+ call pathogen#incubate(path . '/{}')
+ elseif path =~# '^[^\\/]\+[\\/]\%({}\|\*\)$'
+ call pathogen#incubate(path)
+ elseif path =~# '[\\/]\%({}\|\*\)$'
+ call pathogen#surround(path)
+ else
+ call s:warn('Change pathogen#infect('.string(path).') to pathogen#infect('.string(path.'/{}').')')
+ call pathogen#surround(path . '/{}')
+ endif
+ endfor
+ call pathogen#cycle_filetype()
+ return ''
+endfunction " }}}1
+
+" Split a path into a list.
+function! pathogen#split(path) abort " {{{1
+ if type(a:path) == type([]) | return a:path | endif
+ let split = split(a:path,'\\\@"),'!isdirectory(v:val)')) && (!filereadable(dir.sep.'doc'.sep.'tags') || filewritable(dir.sep.'doc'.sep.'tags'))
+ silent! execute 'helptags' pathogen#fnameescape(dir.'/doc')
+ endif
+ endfor
+ endfor
+endfunction " }}}1
+
+command! -bar Helptags :call pathogen#helptags()
+
+" Execute the given command. This is basically a backdoor for --remote-expr.
+function! pathogen#execute(...) abort " {{{1
+ for command in a:000
+ execute command
+ endfor
+ return ''
+endfunction " }}}1
+
+" Like findfile(), but hardcoded to use the runtimepath.
+function! pathogen#runtime_findfile(file,count) abort "{{{1
+ let rtp = pathogen#join(1,pathogen#split(&rtp))
+ let file = findfile(a:file,rtp,a:count)
+ if file ==# ''
+ return ''
+ else
+ return fnamemodify(file,':p')
+ endif
+endfunction " }}}1
+
+" Backport of fnameescape().
+function! pathogen#fnameescape(string) abort " {{{1
+ if exists('*fnameescape')
+ return fnameescape(a:string)
+ elseif a:string ==# '-'
+ return '\-'
+ else
+ return substitute(escape(a:string," \t\n*?[{`$\\%#'\"|!<"),'^[+>]','\\&','')
+ endif
+endfunction " }}}1
+
+if exists(':Vedit')
+ finish
+endif
+
+let s:vopen_warning = 0
+
+function! s:find(count,cmd,file,lcd) " {{{1
+ let rtp = pathogen#join(1,pathogen#split(&runtimepath))
+ let file = pathogen#runtime_findfile(a:file,a:count)
+ if file ==# ''
+ return "echoerr 'E345: Can''t find file \"".a:file."\" in runtimepath'"
+ endif
+ if !s:vopen_warning
+ let s:vopen_warning = 1
+ let warning = '|echohl WarningMsg|echo "Install scriptease.vim to continue using :V'.a:cmd.'"|echohl NONE'
+ else
+ let warning = ''
+ endif
+ if a:lcd
+ let path = file[0:-strlen(a:file)-2]
+ execute 'lcd `=path`'
+ return a:cmd.' '.pathogen#fnameescape(a:file) . warning
+ else
+ return a:cmd.' '.pathogen#fnameescape(file) . warning
+ endif
+endfunction " }}}1
+
+function! s:Findcomplete(A,L,P) " {{{1
+ let sep = pathogen#separator()
+ let cheats = {
+ \'a': 'autoload',
+ \'d': 'doc',
+ \'f': 'ftplugin',
+ \'i': 'indent',
+ \'p': 'plugin',
+ \'s': 'syntax'}
+ if a:A =~# '^\w[\\/]' && has_key(cheats,a:A[0])
+ let request = cheats[a:A[0]].a:A[1:-1]
+ else
+ let request = a:A
+ endif
+ let pattern = substitute(request,'/\|\'.sep,'*'.sep,'g').'*'
+ let found = {}
+ for path in pathogen#split(&runtimepath)
+ let path = expand(path, ':p')
+ let matches = split(glob(path.sep.pattern),"\n")
+ call map(matches,'isdirectory(v:val) ? v:val.sep : v:val')
+ call map(matches,'expand(v:val, ":p")[strlen(path)+1:-1]')
+ for match in matches
+ let found[match] = 1
+ endfor
+ endfor
+ return sort(keys(found))
+endfunction " }}}1
+
+command! -bar -bang -range=1 -nargs=1 -complete=customlist,s:Findcomplete Ve :execute s:find(,'edit',,0)
+command! -bar -bang -range=1 -nargs=1 -complete=customlist,s:Findcomplete Vedit :execute s:find(,'edit',,0)
+command! -bar -bang -range=1 -nargs=1 -complete=customlist,s:Findcomplete Vopen :execute s:find(,'edit',,1)
+command! -bar -bang -range=1 -nargs=1 -complete=customlist,s:Findcomplete Vsplit :execute s:find(,'split',,1)
+command! -bar -bang -range=1 -nargs=1 -complete=customlist,s:Findcomplete Vvsplit :execute s:find(,'vsplit',,1)
+command! -bar -bang -range=1 -nargs=1 -complete=customlist,s:Findcomplete Vtabedit :execute s:find(,'tabedit',,1)
+command! -bar -bang -range=1 -nargs=1 -complete=customlist,s:Findcomplete Vpedit :execute s:find(,'pedit',,1)
+command! -bar -bang -range=1 -nargs=1 -complete=customlist,s:Findcomplete Vread :execute s:find(,'read',,1)
+
+" vim:set et sw=2:
diff --git a/states/users/jdoe/.vim/bundle/vim-fugitive b/states/users/jdoe/.vim/bundle/vim-fugitive
new file mode 160000
index 0000000..ea18a6a
--- /dev/null
+++ b/states/users/jdoe/.vim/bundle/vim-fugitive
@@ -0,0 +1 @@
+Subproject commit ea18a6a89bc2ade1a99cf837ab74fe4ba3f457c9
diff --git a/states/users/jdoe/.vim/colors/vividchalk.vim b/states/users/jdoe/.vim/colors/vividchalk.vim
new file mode 100644
index 0000000..d5d4499
--- /dev/null
+++ b/states/users/jdoe/.vim/colors/vividchalk.vim
@@ -0,0 +1,192 @@
+" Vim color scheme
+" Name: vividchalk.vim
+" Author: Tim Pope
+" Version: 2.0
+" GetLatestVimScripts: 1891 1 :AutoInstall: vividchalk.vim
+
+" Based on the Vibrank Ink theme for TextMate
+" Distributable under the same terms as Vim itself (see :help license)
+
+if has("gui_running")
+ set background=dark
+endif
+hi clear
+if exists("syntax_on")
+ syntax reset
+endif
+
+let colors_name = "vividchalk"
+
+" First two functions adapted from inkpot.vim
+
+" map a urxvt cube number to an xterm-256 cube number
+fun! s:M(a)
+ return strpart("0245", a:a, 1) + 0
+endfun
+
+" map a urxvt colour to an xterm-256 colour
+fun! s:X(a)
+ if &t_Co == 88
+ return a:a
+ else
+ if a:a == 8
+ return 237
+ elseif a:a < 16
+ return a:a
+ elseif a:a > 79
+ return 232 + (3 * (a:a - 80))
+ else
+ let l:b = a:a - 16
+ let l:x = l:b % 4
+ let l:y = (l:b / 4) % 4
+ let l:z = (l:b / 16)
+ return 16 + s:M(l:x) + (6 * s:M(l:y)) + (36 * s:M(l:z))
+ endif
+ endif
+endfun
+
+function! E2T(a)
+ return s:X(a:a)
+endfunction
+
+function! s:choose(mediocre,good)
+ if &t_Co != 88 && &t_Co != 256
+ return a:mediocre
+ else
+ return s:X(a:good)
+ endif
+endfunction
+
+function! s:hifg(group,guifg,first,second,...)
+ if a:0 && &t_Co == 256
+ let ctermfg = a:1
+ else
+ let ctermfg = s:choose(a:first,a:second)
+ endif
+ exe "highlight ".a:group." guifg=".a:guifg." ctermfg=".ctermfg
+endfunction
+
+function! s:hibg(group,guibg,first,second)
+ let ctermbg = s:choose(a:first,a:second)
+ exe "highlight ".a:group." guibg=".a:guibg." ctermbg=".ctermbg
+endfunction
+
+hi link railsMethod PreProc
+hi link rubyDefine Keyword
+hi link rubySymbol Constant
+hi link rubyAccess rubyMethod
+hi link rubyAttribute rubyMethod
+hi link rubyEval rubyMethod
+hi link rubyException rubyMethod
+hi link rubyInclude rubyMethod
+hi link rubyStringDelimiter rubyString
+hi link rubyRegexp Regexp
+hi link rubyRegexpDelimiter rubyRegexp
+"hi link rubyConstant Variable
+"hi link rubyGlobalVariable Variable
+"hi link rubyClassVariable Variable
+"hi link rubyInstanceVariable Variable
+hi link javascriptRegexpString Regexp
+hi link javascriptNumber Number
+hi link javascriptNull Constant
+highlight link diffAdded String
+highlight link diffRemoved Statement
+highlight link diffLine PreProc
+highlight link diffSubname Comment
+
+call s:hifg("Normal","#EEEEEE","White",87)
+if &background == "light" || has("gui_running")
+ hi Normal guibg=Black ctermbg=Black
+else
+ hi Normal guibg=Black ctermbg=NONE
+endif
+highlight StatusLine guifg=Black guibg=#aabbee gui=bold ctermfg=Black ctermbg=White cterm=bold
+highlight StatusLineNC guifg=#444444 guibg=#aaaaaa gui=none ctermfg=Black ctermbg=Grey cterm=none
+"if &t_Co == 256
+ "highlight StatusLine ctermbg=117
+"else
+ "highlight StatusLine ctermbg=43
+"endif
+
+highlight Ignore ctermfg=Black
+highlight WildMenu guifg=Black guibg=#ffff00 gui=bold ctermfg=Black ctermbg=Yellow cterm=bold
+highlight Cursor guifg=Black guibg=White ctermfg=Black ctermbg=White
+call s:hibg("ColorColumn","#333333","DarkGrey",81)
+call s:hibg("CursorLine","#333333","DarkGrey",81)
+call s:hibg("CursorColumn","#333333","DarkGrey",81)
+highlight NonText guifg=#404040 ctermfg=8
+highlight SpecialKey guifg=#404040 ctermfg=8
+highlight Directory none
+high link Directory Identifier
+highlight ErrorMsg guibg=Red ctermbg=DarkRed guifg=NONE ctermfg=NONE
+highlight Search guifg=NONE ctermfg=NONE gui=none cterm=none
+call s:hibg("Search" ,"#555555","DarkBlue",81)
+highlight IncSearch guifg=White guibg=Black ctermfg=White ctermbg=Black
+highlight MoreMsg guifg=#00AA00 ctermfg=Green
+highlight LineNr guifg=#DDEEFF ctermfg=White
+call s:hibg("LineNr" ,"#222222","DarkBlue",80)
+highlight Question none
+high link Question MoreMsg
+highlight Title guifg=Magenta ctermfg=Magenta
+highlight VisualNOS gui=none cterm=none
+call s:hibg("Visual" ,"#555577","LightBlue",83)
+call s:hibg("VisualNOS" ,"#444444","DarkBlue",81)
+call s:hibg("MatchParen","#1100AA","DarkBlue",18)
+highlight WarningMsg guifg=Red ctermfg=Red
+highlight Error ctermbg=DarkRed
+highlight SpellBad ctermbg=DarkRed
+" FIXME: Comments
+highlight SpellRare ctermbg=DarkMagenta
+highlight SpellCap ctermbg=DarkBlue
+highlight SpellLocal ctermbg=DarkCyan
+
+call s:hibg("Folded" ,"#110077","DarkBlue",17)
+call s:hifg("Folded" ,"#aaddee","LightCyan",63)
+highlight FoldColumn none
+high link FoldColumn Folded
+highlight DiffAdd ctermbg=4 guibg=DarkBlue
+highlight DiffChange ctermbg=5 guibg=DarkMagenta
+highlight DiffDelete ctermfg=12 ctermbg=6 gui=bold guifg=Blue guibg=DarkCyan
+highlight DiffText ctermbg=DarkRed
+highlight DiffText cterm=bold ctermbg=9 gui=bold guibg=Red
+
+highlight Pmenu guifg=White ctermfg=White gui=bold cterm=bold
+highlight PmenuSel guifg=White ctermfg=White gui=bold cterm=bold
+call s:hibg("Pmenu" ,"#000099","Blue",18)
+call s:hibg("PmenuSel" ,"#5555ff","DarkCyan",39)
+highlight PmenuSbar guibg=Grey ctermbg=Grey
+highlight PmenuThumb guibg=White ctermbg=White
+highlight TabLine gui=underline cterm=underline
+call s:hifg("TabLine" ,"#bbbbbb","LightGrey",85)
+call s:hibg("TabLine" ,"#333333","DarkGrey",80)
+highlight TabLineSel guifg=White guibg=Black ctermfg=White ctermbg=Black
+highlight TabLineFill gui=underline cterm=underline
+call s:hifg("TabLineFill","#bbbbbb","LightGrey",85)
+call s:hibg("TabLineFill","#808080","Grey",83)
+
+hi Type gui=none
+hi Statement gui=none
+if !has("gui_mac")
+ " Mac GUI degrades italics to ugly underlining.
+ hi Comment gui=italic
+ hi railsUserClass gui=italic
+ hi railsUserMethod gui=italic
+endif
+hi Identifier cterm=none
+" Commented numbers at the end are *old* 256 color values
+"highlight PreProc guifg=#EDF8F9
+call s:hifg("Comment" ,"#9933CC","DarkMagenta",34) " 92
+" 26 instead?
+call s:hifg("Constant" ,"#339999","DarkCyan",21) " 30
+call s:hifg("rubyNumber" ,"#CCFF33","Yellow",60) " 190
+call s:hifg("String" ,"#66FF00","LightGreen",44,82) " 82
+call s:hifg("Identifier" ,"#FFCC00","Yellow",72) " 220
+call s:hifg("Statement" ,"#FF6600","Brown",68) " 202
+call s:hifg("PreProc" ,"#AAFFFF","LightCyan",47) " 213
+call s:hifg("railsUserMethod","#AACCFF","LightCyan",27)
+call s:hifg("Type" ,"#AAAA77","Grey",57) " 101
+call s:hifg("railsUserClass" ,"#AAAAAA","Grey",7) " 101
+call s:hifg("Special" ,"#33AA00","DarkGreen",24) " 7
+call s:hifg("Regexp" ,"#44B4CC","DarkCyan",21) " 74
+call s:hifg("rubyMethod" ,"#DDE93D","Yellow",77) " 191
+"highlight railsMethod guifg=#EE1122 ctermfg=1
diff --git a/states/users/jdoe/.vimrc b/states/users/jdoe/.vimrc
new file mode 100644
index 0000000..ffde2dd
--- /dev/null
+++ b/states/users/jdoe/.vimrc
@@ -0,0 +1,312 @@
+" https://github.com/sontek/dotfiles/
+" ==========================================================
+" Dependencies - Libraries/Applications outside of vim
+" ==========================================================
+" Pep8 - http://pypi.python.org/pypi/pep8
+" Pyflakes
+" Ack
+" Rake & Ruby for command-t
+" nose, django-nose
+
+" ==========================================================
+" Plugins included
+" ==========================================================
+" Pathogen
+" Better Management of VIM plugins
+"
+" GunDo
+" Visual Undo in vim with diff's to check the differences
+"
+" Pytest
+" Runs your Python tests in Vim.
+"
+" Commant-T
+" Allows easy search and opening of files within a given path
+"
+" Snipmate
+" Configurable snippets to avoid re-typing common comands
+"
+" PyFlakes
+" Underlines and displays errors with Python on-the-fly
+"
+" Fugitive
+" Interface with git from vim
+"
+" Git
+" Syntax highlighting for git config files
+"
+" Pydoc
+" Opens up pydoc within vim
+"
+" Surround
+" Allows you to surround text with open/close tags
+"
+" Py.test
+" Run py.test test's from within vim
+"
+" MakeGreen
+" Generic test runner that works with nose
+"
+" ==========================================================
+" Shortcuts
+" ==========================================================
+set nocompatible " Don't be compatible with vi
+let mapleader="," " change the leader to be a comma vs slash
+
+" Seriously, guys. It's not like :W is bound to anything anyway.
+command! W :w
+
+fu! SplitScroll()
+ :wincmd v
+ :wincmd w
+ execute "normal! \"
+ :set scrollbind
+ :wincmd w
+ :set scrollbind
+endfu
+
+nmap sb :call SplitScroll()
+
+
+"l:set scrollbind
+
+" sudo write this
+cmap W! w !sudo tee % >/dev/null
+
+" Toggle the tasklist
+map td TaskList
+
+" Run pep8
+let g:pep8_map='8'
+
+" run py.test's
+nmap tf :Pytest file
+nmap tc :Pytest class
+nmap tm :Pytest method
+nmap tn :Pytest next
+nmap tp :Pytest previous
+nmap te :Pytest error
+
+" Run django tests
+map dt :set makeprg=python\ manage.py\ test\|:call MakeGreen()
+
+" Reload Vimrc
+map V :source ~/.vimrc:filetype detect:exe ":echo 'vimrc reloaded'"
+
+" open/close the quickfix window
+nmap c :copen
+nmap cc :cclose
+
+" for when we forget to use sudo to open/edit a file
+cmap w!! w !sudo tee % >/dev/null
+
+" ctrl-jklm changes to that split
+map j
+map k
+map l
+map h
+
+" and lets make these all work in insert mode too ( makes next cmd
+" happen as if in command mode )
+imap
+
+" Open NerdTree
+map n :NERDTreeToggle
+
+" Run command-t file search
+map f :CommandT
+" Ack searching
+nmap a :Ack!
+
+" Load the Gundo window
+map g :GundoToggle
+
+" Jump to the definition of whatever the cursor is on
+map j :RopeGotoDefinition
+
+" Rename whatever the cursor is on (including references to it)
+map r :RopeRename
+" ==========================================================
+" Pathogen - Allows us to organize our vim plugins
+" ==========================================================
+" Load pathogen with docs for all plugins
+filetype off
+call pathogen#incubate()
+call pathogen#helptags()
+
+" ==========================================================
+" Basic Settings
+" ==========================================================
+syntax on " syntax highlighing
+filetype on " try to detect filetypes
+filetype plugin indent on " enable loading indent file for filetype
+set number " Display line numbers
+set numberwidth=1 " using only 1 column (and 1 space) while possible
+set background=dark " We are using dark background in vim
+set title " show title in console title bar
+set wildmenu " Menu completion in command mode on
+set wildmode=full " cycles between all matching choices.
+
+" don't bell or blink
+set noerrorbells
+set vb t_vb=
+
+" Support 256 colors
+set t_Co=256
+
+" Ignore these files when completing
+set wildignore+=*.o,*.obj,.git,*.pyc
+set wildignore+=eggs/**
+set wildignore+=*.egg-info/**
+
+set grepprg=ack " replace the default grep program with ack
+
+
+" Set working directory
+nnoremap . :lcd %:p:h
+
+" Disable the colorcolumn when switching modes. Make sure this is the
+" first autocmd for the filetype here
+"autocmd FileType * setlocal colorcolumn=0
+
+""" Insert completion
+" don't select first item, follow typing in autocomplete
+set completeopt=menuone,longest,preview
+set pumheight=6 " Keep a small completion window
+
+
+""" Moving Around/Editing
+set cursorline " have a line indicate the cursor location
+set ruler " show the cursor position all the time
+set nostartofline " Avoid moving cursor to BOL when jumping around
+set virtualedit=block " Let cursor move past the last char in mode
+set scrolloff=3 " Keep 3 context lines above and below the cursor
+set backspace=2 " Allow backspacing over autoindent, EOL, and BOL
+set showmatch " Briefly jump to a paren once it's balanced
+set nowrap " don't wrap text
+set linebreak " don't wrap textin the middle of a word
+set autoindent " always set autoindenting on
+set smartindent " use smart indent if there is no indent file
+set tabstop=4 " inserts 4 spaces
+set shiftwidth=4 " but an indent level is 2 spaces wide.
+set softtabstop=4 " over an autoindent deletes both spaces.
+set expandtab " Use spaces, not tabs, for autoindent/tab key.
+set shiftround " rounds indent to a multiple of shiftwidth
+set matchpairs+=<:> " show matching <> (html mainly) as well
+set foldmethod=indent " allow us to fold on indents
+set foldlevel=99 " don't fold by default
+
+" don't outdent hashes
+inoremap # #
+
+" close preview window automatically when we move around
+autocmd CursorMovedI * if pumvisible() == 0|pclose|endif
+autocmd InsertLeave * if pumvisible() == 0|pclose|endif
+
+"""" Reading/Writing
+set noautowrite " Never write a file unless I request it.
+set noautowriteall " NEVER.
+set noautoread " Don't automatically re-read changed files.
+set modeline " Allow vim options to be embedded in files;
+set modelines=5 " they must be within the first or last 5 lines.
+set ffs=unix,dos,mac " Try recognizing dos, unix, and mac line endings.
+
+"""" Messages, Info, Status
+set ls=2 " allways show status line
+set vb t_vb= " Disable all bells. I hate ringing/flashing.
+set confirm " Y-N-C prompt if closing with unsaved changes.
+set showcmd " Show incomplete normal mode commands as I type.
+set report=0 " : commands always print changed line count.
+set shortmess+=a " Use [+]/[RO]/[w] for modified/readonly/written.
+set ruler " Show some info, even without statuslines.
+set laststatus=2 " Always show statusline, even if only 1 window.
+set statusline=[%l,%v\ %P%M]\ %f\ %r%h%w\ (%{&ff})\ %{fugitive#statusline()}
+
+" displays tabs with :set list & displays when a line runs off-screen
+set listchars=tab:>-,eol:$,trail:-,precedes:<,extends:>
+set list
+
+""" Searching and Patterns
+set ignorecase " Default to using case insensitive searches,
+set smartcase " unless uppercase letters are used in the regex.
+set smarttab " Handle tabs more intelligently
+set hlsearch " Highlight searches by default.
+set incsearch " Incrementally search while typing a /regex
+
+"""" Display
+if has("gui_running")
+ colorscheme desert
+ " Remove menu bar
+ set guioptions-=m
+
+ " Remove toolbar
+ set guioptions-=T
+else
+ colorscheme torte
+endif
+
+" Paste from clipboard
+map p "+p
+
+" Quit window on q
+nnoremap q :q
+
+" hide matches on space
+nnoremap :nohlsearch
+
+" Remove trailing whitespace on S
+nnoremap S :%s/\s\+$//:let @/=''
+
+" Select the item in the list with enter
+inoremap pumvisible() ? "\" : "\u\"
+
+" ==========================================================
+" Javascript
+" ==========================================================
+au BufRead *.js set makeprg=jslint\ %
+
+" Use tab to scroll through autocomplete menus
+"autocmd VimEnter * imap pumvisible() ? "" : ""
+"autocmd VimEnter * imap pumvisible() ? "" : ""
+
+let g:acp_completeoptPreview=1
+
+" ===========================================================
+" FileType specific changes
+" ============================================================
+" Mako/HTML
+autocmd BufNewFile,BufRead *.mako,*.mak,*.jinja2 setlocal ft=html
+autocmd FileType html,xhtml,xml,css setlocal expandtab shiftwidth=2 tabstop=2 softtabstop=2
+
+" Python
+"au BufRead *.py compiler nose
+au FileType python set omnifunc=pythoncomplete#Complete
+au FileType python setlocal expandtab shiftwidth=4 tabstop=8 softtabstop=4 smartindent cinwords=if,elif,else,for,while,try,except,finally,def,class,with
+au FileType coffee setlocal expandtab shiftwidth=4 tabstop=8 softtabstop=4 smartindent cinwords=if,elif,else,for,while,try,except,finally,def,class,with
+au BufRead *.py set efm=%C\ %.%#,%A\ \ File\ \"%f\"\\,\ line\ %l%.%#,%Z%[%^\ ]%\\@=%m
+" Don't let pyflakes use the quickfix window
+let g:pyflakes_use_quickfix = 0
+
+
+
+" Add the virtualenv's site-packages to vim path
+if has('python')
+py << EOF
+import os.path
+import sys
+import vim
+if 'VIRTUAL_ENV' in os.environ:
+ project_base_dir = os.environ['VIRTUAL_ENV']
+ sys.path.insert(0, project_base_dir)
+ activate_this = os.path.join(project_base_dir, 'bin/activate_this.py')
+ execfile(activate_this, dict(__file__=activate_this))
+EOF
+endif
+
+" Load up virtualenv's vimrc if it exists
+if filereadable($VIRTUAL_ENV . '/.vimrc')
+ source $VIRTUAL_ENV/.vimrc
+endif
+
+set colorcolumn=79
+colorscheme vividchalk
diff --git a/top.sls b/top.sls
new file mode 100644
index 0000000..cfd65a0
--- /dev/null
+++ b/top.sls
@@ -0,0 +1,2 @@
+include:
+ - pillars.{{ saltenv if saltenv != None else env}}