kitchen-salt 0.0.24 → 0.0.25

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 85be745fefb172f73d8e9ee2ae396fe3d508396b
4
- data.tar.gz: f75956c111096fbe7cc7e724b4712a4dbc9d5fa3
3
+ metadata.gz: 2508f6579671b6cfbb285f7024faa9c4265645d9
4
+ data.tar.gz: f506596a5019cea93aaada988025bcc1b691a9d2
5
5
  SHA512:
6
- metadata.gz: ae57f141df5166427ba4cbade9ffe04b3a5fbb0bf9579d4d1822128a3b55ecca3afc51ffd343b831feb412e1f91ec45339c01041f25fba46c3916f95c1276904
7
- data.tar.gz: 8987519c6d89c2010dee394e96df3f1eb6bba1237c3b8044bd527662c24f0d19aadb1f644825275b615cbac7eee58e0deb824d88f81fad8b3fbee21a400fcb5e
6
+ metadata.gz: 8af0c3817e2fd7e454eb7343dd2b9d013caa7e42a228c53a2fe46231390bb8b1f73b9aa08a59d74ce6e5c565039ae53ec21979c424a8cc99b9b74986cf8fa6ed
7
+ data.tar.gz: 34f6645a153a85fd2126491768c2402776d4235f31e132b5e7e75de757cd40e63de05119b9d4c2330698732ba4ff199e3bbcc43391d8841f11ef29be2ee4918d
@@ -0,0 +1,73 @@
1
+ module Kitchen
2
+ module Salt
3
+ module Pillars
4
+ private
5
+
6
+ def prepare_pillars
7
+ info("Preparing pillars into #{config[:salt_pillar_root]}")
8
+
9
+ pillars = config[:pillars]
10
+ pillars_from_files = config[:'pillars-from-files']
11
+ debug("Pillars Hash: #{pillars}")
12
+
13
+ if pillars.nil? && pillars_from_files.nil?
14
+ if not config[:local_salt_root].nil?
15
+ pillars_location = File.join(config[:local_salt_root], 'pillar')
16
+ sandbox_pillar_path = File.join(sandbox_path, config[:salt_pillar_root])
17
+ cp_r_with_filter(pillars_location, sandbox_pillar_path, config[:salt_copy_filter])
18
+ return
19
+ end
20
+ return
21
+ end
22
+
23
+ # we get a hash with all the keys converted to symbols, salt doesn't like this
24
+ # to convert all the keys back to strings again
25
+ pillars = unsymbolize(pillars)
26
+ debug("unsymbolized pillars hash: #{pillars}")
27
+
28
+ # write out each pillar (we get key/contents pairs)
29
+ prepare_pillar_files(pillars)
30
+
31
+ # copy the pillars from files straight across, as YAML.load/to_yaml and
32
+ # munge multiline strings
33
+ unless pillars_from_files.nil?
34
+ prepare_pillars_from_files(pillars_from_files)
35
+ end
36
+ end
37
+
38
+ def prepare_pillar_files(pillars)
39
+ pillars.each do |key, contents|
40
+ # convert the hash to yaml
41
+ pillar = contents.to_yaml
42
+
43
+ # .to_yaml will produce ! '*' for a key, Salt doesn't like this either
44
+ pillar.gsub!(/(!\s'\*')/, "'*'")
45
+
46
+ # generate the filename
47
+ sandbox_pillar_path = File.join(sandbox_path, config[:salt_pillar_root], key)
48
+
49
+ debug("Rendered pillar yaml for #{key}:\n #{pillar}")
50
+ write_raw_file(sandbox_pillar_path, pillar)
51
+ end
52
+ end
53
+
54
+ def copy_pillar(key, srcfile)
55
+ debug("Copying external pillar: #{key}, #{srcfile}")
56
+ # generate the filename
57
+ sandbox_pillar_path = File.join(sandbox_path, config[:salt_pillar_root], key)
58
+ # create the directory where the pillar file will go
59
+ FileUtils.mkdir_p(File.dirname(sandbox_pillar_path))
60
+ # copy the file across
61
+ FileUtils.copy srcfile, sandbox_pillar_path
62
+ end
63
+
64
+ def prepare_pillars_from_files(pillars)
65
+ external_pillars = unsymbolize(pillars)
66
+ debug("external_pillars (unsymbolize): #{external_pillars}")
67
+ external_pillars.each do |key, srcfile|
68
+ copy_pillar(key, srcfile)
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,107 @@
1
+ module Kitchen
2
+ module Salt
3
+ module States
4
+ private
5
+
6
+ def prepare_state_top
7
+ info('Preparing state_top')
8
+
9
+ sandbox_state_top_path = File.join(sandbox_path, config[:salt_state_top])
10
+
11
+ if config[:state_top_from_file] == false
12
+ # use the top.sls embedded in .kitchen.yml
13
+
14
+ # we get a hash with all the keys converted to symbols, salt doesn't like this
15
+ # to convert all the keys back to strings again
16
+ state_top_content = unsymbolize(config[:state_top]).to_yaml
17
+ # .to_yaml will produce ! '*' for a key, Salt doesn't like this either
18
+ state_top_content.gsub!(/(!\s'\*')/, "'*'")
19
+ else
20
+ # load a top.sls from disk
21
+ if config[:local_salt_root].nil?
22
+ top_file = 'top.sls'
23
+ else
24
+ top_file = File.join(config[:local_salt_root], 'salt/top.sls')
25
+ end
26
+ state_top_content = File.read(top_file)
27
+ end
28
+
29
+ write_raw_file(sandbox_state_top_path, state_top_content)
30
+ end
31
+
32
+ def prepare_states
33
+ if config[:state_collection] || config[:is_file_root] || !config[:local_salt_root].nil?
34
+ prepare_state_collection
35
+ else
36
+ prepare_formula config[:kitchen_root], config[:formula]
37
+ prepare_vendor_states
38
+ end
39
+
40
+ end
41
+
42
+ def prepare_vendor_states
43
+ vendor_path = config[:vendor_path]
44
+
45
+ unless vendor_path.nil?
46
+ if Pathname.new(vendor_path).exist?
47
+ Dir[File.join(vendor_path, '*')].each do |d|
48
+ prepare_formula vendor_path, File.basename(d)
49
+ end
50
+ else
51
+ # :vendor_path was set, but not valid
52
+ raise UserError, "kitchen-salt: Invalid vendor_path set: #{vendor_path}"
53
+ end
54
+ end
55
+ end
56
+
57
+ def prepare_formula_dir(path, subdir)
58
+ src = File.join(path, subdir)
59
+
60
+ if File.directory?(src)
61
+ debug("prepare_formula_dir: #{src} exists, copying..")
62
+ subdir_path = File.join(sandbox_path, config[:salt_file_root], subdir)
63
+ FileUtils.mkdir_p(subdir_path)
64
+ cp_r_with_filter(src, subdir_path, config[:salt_copy_filter])
65
+ else
66
+ debug("prepare_formula_dir: #{src} doesn't exist, skipping.")
67
+ end
68
+ end
69
+
70
+ def prepare_formula(path, formula)
71
+ info("Preparing formula: #{formula} from #{path}")
72
+ debug("Using config #{config}")
73
+
74
+ formula_dir = File.join(sandbox_path, config[:salt_file_root], formula)
75
+ FileUtils.mkdir_p(formula_dir)
76
+ cp_r_with_filter(File.join(path, formula), formula_dir, config[:salt_copy_filter])
77
+
78
+ # copy across the _modules etc directories for python implementation
79
+ %w(_modules _states _grains _renderers _returners).each do |extrapath|
80
+ prepare_formula_dir(path, extrapath)
81
+ end
82
+ end
83
+
84
+ def prepare_state_collection
85
+ info('Preparing state collection')
86
+ collection_name = config[:collection_name]
87
+ formula = config[:formula]
88
+
89
+ if collection_name.nil? && formula.nil?
90
+ info('neither collection_name or formula have been set, assuming this is a pre-built collection')
91
+ collection_name = ''
92
+ elsif collection_name.nil?
93
+ collection_name = formula
94
+ end
95
+
96
+ if config[:local_salt_root].nil?
97
+ states_location = config[:kitchen_root]
98
+ else
99
+ states_location = File.join(config[:local_salt_root], 'salt')
100
+ end
101
+ collection_dir = File.join(sandbox_path, config[:salt_file_root], collection_name)
102
+ FileUtils.mkdir_p(collection_dir)
103
+ cp_r_with_filter(states_location, collection_dir, config[:salt_copy_filter])
104
+ end
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,69 @@
1
+ require 'find'
2
+
3
+ module Kitchen
4
+ module Salt
5
+ module Util
6
+ private
7
+
8
+ def unsymbolize(obj)
9
+ if obj.is_a? Hash
10
+ obj.each_with_object({}) do |(k, v), a|
11
+ a[k.to_s] = unsymbolize(v)
12
+ a
13
+ end
14
+ elsif obj.is_a? Array
15
+ obj.each_with_object([]) do |e, a|
16
+ a << unsymbolize(e)
17
+ a
18
+ end
19
+ else
20
+ obj
21
+ end
22
+ end
23
+
24
+ def cp_r_with_filter(source_paths, target_path, filter = [])
25
+ debug("cp_r_with_filter:source_paths = #{source_paths}")
26
+ debug("cp_r_with_filter:target_path = #{target_path}")
27
+ debug("cp_r_with_filter:filter = #{filter}")
28
+
29
+ Array(source_paths).each do |source_path|
30
+ _cp_r_with_filter(source_path, target_path, filter)
31
+ end
32
+ end
33
+
34
+ def _cp_r_with_filter(source_path, target_path, filter = [])
35
+ Find.find(source_path) do |source|
36
+ target = source.sub(/^#{source_path}/, target_path)
37
+ debug("cp_r_with_filter:source = #{source}")
38
+ debug("cp_r_with_filter:target = #{target}")
39
+ filtered = filter.include?(File.basename(source))
40
+ if File.directory? source
41
+ if filtered
42
+ debug("Found #{source} in #{filter}, pruning it from the Find")
43
+ Find.prune
44
+ end
45
+ FileUtils.mkdir_p target unless File.exist? target
46
+
47
+ FileUtils.cp_r "#{source}/.", target if File.symlink? source
48
+ elsif filtered
49
+ debug("Found #{source} in #{filter}, not copying file")
50
+ else
51
+ FileUtils.copy source, target
52
+ end
53
+ end
54
+ end
55
+
56
+ def write_raw_file(name, contents)
57
+ FileUtils.mkdir_p(File.dirname(name))
58
+ File.open(name, 'wb') do |file|
59
+ file.write(contents)
60
+ end
61
+ end
62
+
63
+ def write_hash_file(name, contents)
64
+ raw_contents = unsymbolize(contents).to_yaml
65
+ write_raw_file(name, raw_contents)
66
+ end
67
+ end
68
+ end
69
+ end
@@ -1,5 +1,5 @@
1
1
  module Kitchen
2
2
  module Salt
3
- VERSION = "0.0.24"
3
+ VERSION = '0.0.25'.freeze
4
4
  end
5
5
  end
@@ -0,0 +1,99 @@
1
+ <%=
2
+
3
+ def install_dependencies
4
+ script = ''
5
+
6
+ script += <<-INSTALL
7
+ test ! -e "$(dirname $0)/formula-fetch.sh" || . "$(dirname $0)/formula-fetch.sh"
8
+ test ! -e "$(dirname $0)/repository-setup.sh" || . "$(dirname $0)/repository-setup.sh"
9
+
10
+ export SALT_ROOT="#{config[:root_path]}/#{config[:salt_file_root]}";
11
+ mkdir -p "${SALT_ROOT}";
12
+ INSTALL
13
+
14
+
15
+ # setup apt
16
+ config[:vendor_repo].select{|x| x[:type]=='apt'}.each do |repo|
17
+ id =repo[:url].gsub(/[htp:\/.]/,'')
18
+ arch=repo[:arch] || '[arch=amd64]'
19
+ rurl=repo[:url]
20
+ comp=repo[:components] || 'main'
21
+ dist=repo[:distribution] || '$DISTRIB_CODENAME'
22
+ rkey=repo[:key_url]
23
+ script += <<-INSTALL
24
+ apt_repo_add "#{id}" "#{arch}" "#{rurl}" "#{comp}" "#{dist}" "#{rkey}";
25
+ INSTALL
26
+ end
27
+
28
+ # setup ppa
29
+ config[:vendor_repo].select{|x| x[:type]=='ppa'}.each do |repo|
30
+ script += <<-INSTALL
31
+ #{sudo('add-apt-repository')} "ppa:#{repo[:name]}" -y;
32
+ INSTALL
33
+ end
34
+
35
+ # TODO, setup yum repo
36
+
37
+ # update resources
38
+ config[:vendor_repo].map{|x| x[:type]}.uniq.each do |type|
39
+ case type
40
+ when 'apt'
41
+ script += <<-INSTALL
42
+ #{sudo('apt-get')} update -q;
43
+ sleep 10;
44
+ INSTALL
45
+ when 'yum'
46
+ script += <<-INSTALL
47
+ #{sudo('yum')} update;
48
+ sleep 10;
49
+ INSTALL
50
+ when 'spm'
51
+ script += <<-INSTALL
52
+ #{sudo('spm')} update_repo;
53
+ INSTALL
54
+ end
55
+ end
56
+
57
+ # install formulas
58
+ config[:dependencies].select{|dependency| dependency.has_key?(:repo)}.each do |formula|
59
+ #unless config[:vendor_repo].has_key?(formula[:repo])
60
+ # raise UserError, "kitchen-salt: Invalid dependency formula :repo, no such vendor_repo '#{formula[:repo]}' specified."
61
+ #end
62
+ case formula[:repo]
63
+ when 'git'
64
+ script += <<-INSTALL
65
+ fetchGitFormula #{formula[:source]} "#{formula[:name]}" "#{formula[:branch] || 'master'}"
66
+ INSTALL
67
+ when 'spm'
68
+ # TODO: SPM should know the sandbox_path is /tmp/kitchen/etc
69
+ script += <<-INSTALL
70
+ #{sudo('spm')} install #{formula[:package]||formula[:name]};
71
+ INSTALL
72
+ when 'yum'
73
+ script += <<-INSTALL
74
+ #{sudo('yum')} install -y #{formula[:package]||formula[:name]};
75
+ INSTALL
76
+ when 'apt'
77
+ script += <<-INSTALL
78
+ #{sudo('apt-get')} install -y #{formula[:package]||formula[:name]};
79
+ INSTALL
80
+ end
81
+ end
82
+ script += <<-INSTALL
83
+ linkFormulas "$SALT_ROOT"
84
+ #{sudo('chown')} kitchen.kitchen -R /usr/share/salt-formulas;
85
+ #{sudo('chown')} kitchen.kitchen -R "$SALT_ROOT";
86
+ ls -la "$SALT_ROOT";
87
+ INSTALL
88
+ return script
89
+ end
90
+
91
+
92
+ <<-INSTALL
93
+ #!/bin/bash
94
+
95
+ echo "Install External Dependencies";
96
+ #{install_dependencies}
97
+
98
+ INSTALL
99
+ %>
@@ -0,0 +1,82 @@
1
+ #!/bin/bash
2
+
3
+ # Usage:
4
+ # ./formula-fetch.sh <Formula URL> <Name> <Branch>
5
+ #
6
+ # Example:
7
+ # GIT_FORMULAS_PATH=.vendor/formulas ./formula-fetch.sh https://github.com/salt-formulas/salt-formula-salt
8
+ # --
9
+ # GIT_FORMULAS_PATH=/usr/share/salt-formulas/env/_formulas
10
+ # xargs -n1 ./formula-fetch.sh < dependencies.txt
11
+
12
+
13
+ # Parse git dependencies from metadata.yml
14
+ # $1 - path to <formula>/metadata.yml
15
+ # sample to output:
16
+ # https://github.com/salt-formulas/salt-formula-git git
17
+ # https://github.com/salt-formulas/salt-formula-salt salt
18
+ function fetchDependencies() {
19
+ METADATA="$1";
20
+ grep -E "^dependencies:" "$METADATA" >/dev/null || return 0
21
+ # shellcheck disable=SC2086
22
+ (python - "$METADATA" | while read -r dep; do fetchGitFormula $dep; done) <<-DEPS
23
+ import sys,yaml
24
+ for dep in yaml.load(open(sys.argv[1], "ro"))["dependencies"]:
25
+ print("{source} {name}").format(**dep)
26
+ DEPS
27
+ }
28
+
29
+ # Fetch formula from git repo
30
+ # $1 - formula git repo url
31
+ # $2 - formula name (optional)
32
+ # $3 - branch (optional)
33
+ function fetchGitFormula() {
34
+ test -n "${FETCHED}" || declare -a FETCHED=()
35
+ export GIT_FORMULAS_PATH=${GIT_FORMULAS_PATH:-/usr/share/salt-formulas/env/_formulas}
36
+ mkdir -p "$GIT_FORMULAS_PATH"
37
+ if [ -n "$1" ]; then
38
+ source="$1"
39
+ name="$2"
40
+ test -n "$name" || name="${source//*salt-formula-}"
41
+ test -z "$3" && branch=master || branch=$3
42
+ if ! [[ "${FETCHED[*]}" =~ $name ]]; then # dependency not yet fetched
43
+ echo "Fetching: $name"
44
+ if test -e "$GIT_FORMULAS_PATH/$name"; then
45
+ pushd "$GIT_FORMULAS_PATH/$name" &>/dev/null
46
+ test ! -e .git || git pull -r
47
+ popd &>/dev/null
48
+ else
49
+ echo "git clone $source $GIT_FORMULAS_PATH/$name -b $branch"
50
+ git clone "$source" "$GIT_FORMULAS_PATH/$name" -b "$branch"
51
+ fi
52
+ # install dependencies
53
+ FETCHED+=($name)
54
+ fetchDependencies "$GIT_FORMULAS_PATH/$name/metadata.yml"
55
+ fi
56
+ else
57
+ echo Usage: fetchGitFormula "<git repo>" "[local formula directory name]" "[branch]"
58
+ fi
59
+ }
60
+
61
+ function linkFormulas() {
62
+ # OPTIONAL: Link formulas from git/pkg
63
+
64
+ SALT_ROOT=$1
65
+ SALT_ENV=${2:-/usr/share/salt-formulas/env}
66
+
67
+ # form git, development versions
68
+ find "$SALT_ENV"/_formulas -maxdepth 1 -mindepth 1 -type d -print0| xargs -0 -n1 basename | xargs -I{} \
69
+ ln -fs "$SALT_ENV"/_formulas/{}/{} "$SALT_ROOT"/{};
70
+
71
+ # form pkgs
72
+ find "$SALT_ENV" -path "*_formulas*" -prune -o -name "*" -maxdepth 1 -mindepth 1 -type d -print0| xargs -0 -n1 basename | xargs -I{} \
73
+ ln -fs "$SALT_ENV"/{} "$SALT_ROOT"/{};
74
+
75
+ }
76
+
77
+ # detect if file is being sourced
78
+ [[ "$0" != "${BASH_SOURCE[@]}" ]] || {
79
+ # if executed, run implicit function
80
+ fetchGitFormula "${@}"
81
+ }
82
+
@@ -0,0 +1,82 @@
1
+
2
+ <%=
3
+ salt_install = config[:salt_install]
4
+ salt_url = config[:salt_bootstrap_url]
5
+ bootstrap_options = config[:salt_bootstrap_options]
6
+ salt_version = config[:salt_version]
7
+ salt_apt_repo = config[:salt_apt_repo]
8
+ salt_apt_repo_key = config[:salt_apt_repo_key]
9
+ salt_ppa = config[:salt_ppa]
10
+
11
+ <<-INSTALL
12
+ sh -c '
13
+ #{Util.shell_helpers}
14
+
15
+ # what version of salt is installed?
16
+ SALT_VERSION=`salt-call --version | cut -d " " -f 2`
17
+ set +x
18
+
19
+
20
+ if [ -z "${SALT_VERSION}" -a "#{salt_install}" = "bootstrap" ]
21
+ then
22
+ do_download #{salt_url} /tmp/bootstrap-salt.sh
23
+ #{sudo('sh')} /tmp/bootstrap-salt.sh #{bootstrap_options}
24
+ elif [ -z "${SALT_VERSION}" -a "#{salt_install}" = "apt" ]
25
+ then
26
+ if [ ! $(command -v lsb_release &>/dev/null) ]; then
27
+ . /etc/lsb-release
28
+ else
29
+ DISTRIB_CODENAME=$(lsb_release -s -c)
30
+ fi
31
+
32
+ echo "-----> Configuring apt repo for salt #{salt_version}"
33
+ echo "deb #{salt_apt_repo}/#{salt_version} ${DISTRIB_CODENAME} main" | #{sudo('tee')} /etc/apt/sources.list.d/salt-#{salt_version}.list
34
+
35
+ do_download #{salt_apt_repo_key} /tmp/repo.key
36
+ #{sudo('apt-key')} add /tmp/repo.key
37
+
38
+ #{sudo('apt-get')} update
39
+ sleep 10
40
+ echo "-----> Installing salt-minion (#{salt_version})"
41
+ #{sudo('apt-get')} install -y python-support
42
+ #{sudo('apt-get')} install -y salt-minion salt-common
43
+ elif [ -z "${SALT_VERSION}" -a "#{salt_install}" = "distrib" ]
44
+ then
45
+ #{sudo('apt-get')} update
46
+ #{sudo('apt-get')} install -y salt-minion
47
+ elif [ -z "${SALT_VERSION}" -a "#{salt_install}" = "ppa" ]
48
+ then
49
+ #{sudo('apt-add-repository')} -y #{salt_ppa}
50
+ #{sudo('apt-get')} update
51
+ #{sudo('apt-get')} install -y salt-minion salt-common
52
+ fi
53
+
54
+ # check again, now that an install of some form should have happened
55
+ SALT_VERSION=`salt-call --version | cut -d " " -f 2`
56
+
57
+ if [ -z "${SALT_VERSION}" ]
58
+ then
59
+ echo "No salt-minion installed, install must have failed!!"
60
+ echo "salt_install = #{salt_install}"
61
+ echo "salt_url = #{salt_url}"
62
+ echo "bootstrap_options = #{bootstrap_options}"
63
+ echo "salt_version = #{salt_version}"
64
+ echo "salt_apt_repo = #{salt_apt_repo}"
65
+ echo "salt_apt_repo_key = #{salt_apt_repo_key}"
66
+ echo "salt_ppa = #{salt_ppa}"
67
+ exit 2
68
+ elif [ "${SALT_VERSION}" = "#{salt_version}" -o "#{salt_version}" = "latest" ]
69
+ then
70
+ echo "You asked for #{salt_version} and you have ${SALT_VERSION} installed, sweet!"
71
+ elif [ ! -z "${SALT_VERSION}" -a "#{salt_install}" = "bootstrap" ]
72
+ then
73
+ echo "You asked for bootstrap install and you have got ${SALT_VERSION}, hope thats ok!"
74
+ else
75
+ echo "You asked for #{salt_version} and you have got ${SALT_VERSION} installed, dunno how to fix that, sorry!"
76
+ exit 2
77
+ fi
78
+
79
+ #{install_chef}
80
+ '
81
+ INSTALL
82
+ %>
@@ -0,0 +1,32 @@
1
+ <%=
2
+ salt_install = config[:salt_install]
3
+ salt_url = config[:salt_bootstrap_url]
4
+ bootstrap_options = config[:salt_bootstrap_options]
5
+ salt_version = config[:salt_version]
6
+
7
+ <<-POWERSHELL
8
+ if (Test-Path c:\\salt\\salt-call.bat) {
9
+ $installed_version = $(c:\\salt\\salt-call.bat --version).split(' ')[1]
10
+ }
11
+ if (-Not $(Test-Path c:\\temp)) {
12
+ New-Item -Path c:\\temp -itemtype directory
13
+ }
14
+ if (-Not $installed_version -And "#{salt_install}" -eq "bootstrap") {
15
+ (New-Object net.webclient).DownloadFile("#{salt_url}", "c:\\temp\\salt_bootstrap.ps1")
16
+ #{sudo('powershell')} c:\\temp\\salt_bootstrap.ps1 #{bootstrap_options}
17
+ }
18
+ $installed_version = $(c:\\salt\\salt-call.bat --version).split(' ')[1]
19
+ if (-Not $installed_version) {
20
+ write-host "No salt-minion installed, install must have failed!!"
21
+ write-host "salt_install = #{salt_install}"
22
+ write-host "salt_url = #{salt_url}"
23
+ write-host "bootstrap_options = #{bootstrap_options}"
24
+ } elseif ($installed_version -And "#{salt_install}" -eq "bootstrap") {
25
+ write-host "You asked for bootstrap install and you have got $installed_version, hope that's ok!"
26
+ } else {
27
+ write-host "You asked for #{salt_version} and you have got $installed_version installed, dunno ho to fix that, sorry!"
28
+ exit 2
29
+ }
30
+ #{install_chef}
31
+ POWERSHELL
32
+ %>
@@ -0,0 +1,13 @@
1
+ state_top: top.sls
2
+
3
+ file_client: local
4
+
5
+ file_roots:
6
+ <%= config[:salt_env] %>:
7
+
8
+ - <%= File.join(config[:root_path], (windows_os? ? config[:salt_file_root].gsub('/', '\\') : config[:salt_file_root])) %>
9
+ - <%= File.join(config[:root_path], (windows_os? ? config[:salt_file_root].gsub('/', '\\') : config[:salt_file_root]), 'spm') %>
10
+
11
+ pillar_roots:
12
+ <%= config[:salt_env] %>:
13
+ - <%= File.join(config[:root_path], (windows_os? ? config[:salt_pillar_root].gsub('/', '\\') : config[:salt_pillar_root])) %>
@@ -0,0 +1,26 @@
1
+ #!/bin/bash
2
+
3
+ function apt_repo_add {
4
+ id="$1"
5
+ arch="$2"
6
+ rurl="$3"
7
+ comp="$4"
8
+ dist="$5"
9
+ rkey="$6"
10
+ test -e /tmp/apt_repo_vendor_"${id}".key || {
11
+ echo "-----> Configuring formula apt vendor_repo ${rurl}"
12
+ eval "$(cat /etc/lsb-release)"
13
+ if curl -k "${rkey}" -o /tmp/apt_repo_vendor_"${id}".key; then
14
+ echo "deb ${arch} ${rurl} ${dist} ${comp}" | tee /etc/apt/sources.list.d/vendor-repo.list
15
+ apt-key add /tmp/apt_repo_vendor_"${id}".key
16
+ fi
17
+ };
18
+ }
19
+
20
+ # detect if file is being sourced
21
+ [[ "$0" != "${BASH_SOURCE[@]}" ]] || {
22
+ # if executed, run implicit function
23
+ #apt_repo_add "${@}"
24
+ echo 'Usage: apt_repo_add "custom id" "arch" "repo url" "components" "distribution" "repo gpg key"';
25
+ }
26
+
@@ -17,163 +17,122 @@
17
17
  # limitations under the License.
18
18
 
19
19
  require 'kitchen/provisioner/base'
20
- require 'find'
20
+ require 'kitchen-salt/util'
21
+ require 'kitchen-salt/pillars'
22
+ require 'kitchen-salt/states'
21
23
  require 'fileutils'
22
24
  require 'yaml'
23
25
 
24
26
  module Kitchen
25
-
26
27
  module Provisioner
27
-
28
28
  # Basic Salt Masterless Provisioner, based on work by
29
29
  #
30
30
  # @author Chris Lundquist (<chris.ludnquist@github.com>)
31
- class SaltSolo < Base
32
-
33
- default_config :salt_version, "latest"
34
-
35
- # supported install methods: bootstrap|apt
36
- default_config :salt_install, "bootstrap"
37
-
38
- default_config :salt_bootstrap_url, "http://bootstrap.saltstack.org"
39
- default_config :salt_bootstrap_options, ""
40
31
 
41
- # alternative method of installing salt
42
- default_config :salt_apt_repo, "http://apt.mccartney.ie"
43
- default_config :salt_apt_repo_key, "http://apt.mccartney.ie/KEY"
44
- default_config :salt_ppa, "ppa:saltstack/salt"
45
-
46
- default_config :chef_bootstrap_url, "https://www.getchef.com/chef/install.sh"
47
-
48
- default_config :salt_config, "/etc/salt"
49
- default_config :salt_minion_config, "/etc/salt/minion"
50
- default_config :salt_env, "base"
51
- default_config :salt_file_root, "/srv/salt"
52
- default_config :salt_pillar_root, "/srv/pillar"
53
- default_config :salt_state_top, "/srv/salt/top.sls"
54
- default_config :state_collection, false
55
- default_config :state_top, {}
56
- default_config :state_top_from_file, false
57
- default_config :salt_run_highstate, true
58
- default_config :salt_copy_filter, []
59
- default_config :is_file_root, false
60
- default_config :require_chef, true
61
-
62
- default_config :dependencies, []
63
- default_config :vendor_path, nil
64
- default_config :omnibus_cachier, false
32
+ class SaltSolo < Base
33
+ include Kitchen::Salt::Util
34
+ include Kitchen::Salt::Pillars
35
+ include Kitchen::Salt::States
36
+
37
+ DEFAULT_CONFIG = {
38
+ dry_run: false,
39
+ salt_version: 'latest',
40
+ salt_install: 'bootstrap',
41
+ salt_bootstrap_url: 'https://bootstrap.saltstack.org',
42
+ salt_bootstrap_options: '',
43
+ salt_apt_repo: 'https://repo.saltstack.com/apt/ubuntu/16.04/amd64/latest',
44
+ salt_apt_repo_key: 'https://repo.saltstack.com/apt/ubuntu/16.04/amd64/latest/SALTSTACK-GPG-KEY.pub',
45
+ salt_ppa: 'ppa:saltstack/salt',
46
+ bootstrap_url: 'https://raw.githubusercontent.com/saltstack/kitchen-salt/master/assets/install.sh',
47
+ chef_bootstrap_url: 'https://www.getchef.com/chef/install.sh',
48
+ salt_config: '/etc/salt',
49
+ salt_minion_config: '/etc/salt/minion',
50
+ salt_minion_config_template: nil,
51
+ salt_minion_id: nil,
52
+ salt_env: 'base',
53
+ salt_file_root: '/srv/salt',
54
+ salt_pillar_root: '/srv/pillar',
55
+ salt_spm_root: '/srv/spm',
56
+ salt_state_top: '/srv/salt/top.sls',
57
+ state_collection: false,
58
+ state_top: {},
59
+ state_top_from_file: false,
60
+ salt_run_highstate: true,
61
+ salt_copy_filter: [],
62
+ is_file_root: false,
63
+ require_chef: true,
64
+ dependencies: [],
65
+ vendor_path: nil,
66
+ vendor_repo: {},
67
+ omnibus_cachier: false,
68
+ local_salt_root: nil
69
+ }
65
70
 
66
71
  # salt-call version that supports the undocumented --retcode-passthrough command
67
- RETCODE_VERSION = '0.17.5'
72
+ RETCODE_VERSION = '0.17.5'.freeze
73
+
74
+ DEFAULT_CONFIG.each do |k, v|
75
+ default_config k, v
76
+ end
68
77
 
69
78
  def install_command
70
- debug(diagnose())
79
+ debug(diagnose)
80
+ salt_version = config[:salt_version]
71
81
 
72
82
  # if salt_verison is set, bootstrap is being used & bootstrap_options is empty,
73
83
  # set the bootstrap_options string to git install the requested version
74
- if ((config[:salt_version] != 'latest') && (config[:salt_install] == 'bootstrap') && config[:salt_bootstrap_options].empty?)
75
- debug("Using bootstrap git to install #{config[:salt_version]}")
76
- config[:salt_bootstrap_options] = "-P git v#{config[:salt_version]}"
84
+ if (salt_version != 'latest') && (config[:salt_install] == 'bootstrap') && config[:salt_bootstrap_options].empty?
85
+ debug("Using bootstrap git to install #{salt_version}")
86
+ config[:salt_bootstrap_options] = "-P git v#{salt_version}"
77
87
  end
78
88
 
79
- salt_install = config[:salt_install]
80
-
81
- salt_url = config[:salt_bootstrap_url]
82
- bootstrap_options = config[:salt_bootstrap_options]
83
-
84
- salt_version = config[:salt_version]
85
- salt_apt_repo = config[:salt_apt_repo]
86
- salt_apt_repo_key = config[:salt_apt_repo_key]
87
- salt_ppa = config[:salt_ppa]
88
-
89
-
90
- <<-INSTALL
91
- sh -c '
92
- #{Util.shell_helpers}
93
-
94
- # what version of salt is installed?
95
- SALT_VERSION=`salt-call --version | cut -d " " -f 2`
96
-
97
-
98
- if [ -z "${SALT_VERSION}" -a "#{salt_install}" = "bootstrap" ]
99
- then
100
- do_download #{salt_url} /tmp/bootstrap-salt.sh
101
- #{sudo('sh')} /tmp/bootstrap-salt.sh #{bootstrap_options}
102
- elif [ -z "${SALT_VERSION}" -a "#{salt_install}" = "apt" ]
103
- then
104
- if [ -z "`which lsb_release`" ]; then
105
- . /etc/lsb-release
106
- else
107
- DISTRIB_CODENAME=`lsb_release -s -c`
108
- fi
109
-
110
- echo "-----> Configuring apt repo for salt #{salt_version}"
111
- echo "deb #{salt_apt_repo}/salt-#{salt_version} ${DISTRIB_CODENAME} main" | #{sudo('tee')} /etc/apt/sources.list.d/salt-#{salt_version}.list
112
-
113
- do_download #{salt_apt_repo_key} /tmp/repo.key
114
- #{sudo('apt-key')} add /tmp/repo.key
115
-
116
- #{sudo('apt-get')} update
117
- sleep 10
118
- echo "-----> Installing salt-minion (#{salt_version})"
119
- #{sudo('apt-get')} install -y python-support
120
- #{sudo('apt-get')} install -y salt-minion
121
- #{sudo('apt-get')} install -y salt-common
122
- #{sudo('apt-get')} install -y salt-minion
123
- elif [ -z "${SALT_VERSION}" -a "#{salt_install}" = "ppa" ]
124
- then
125
- #{sudo('apt-add-repository')} -y #{salt_ppa}
126
- #{sudo('apt-get')} update
127
- #{sudo('apt-get')} install -y salt-minion
128
- fi
129
-
130
- # check again, now that an install of some form should have happened
131
- SALT_VERSION=`salt-call --version | cut -d " " -f 2`
132
-
133
- if [ -z "${SALT_VERSION}" ]
134
- then
135
- echo "No salt-minion installed, install must have failed!!"
136
- echo "salt_install = #{salt_install}"
137
- echo "salt_url = #{salt_url}"
138
- echo "bootstrap_options = #{bootstrap_options}"
139
- echo "salt_version = #{salt_version}"
140
- echo "salt_apt_repo = #{salt_apt_repo}"
141
- echo "salt_apt_repo_key = #{salt_apt_repo_key}"
142
- echo "salt_ppa = #{salt_ppa}"
143
- exit 2
144
- elif [ "${SALT_VERSION}" = "#{salt_version}" -o "#{salt_version}" = "latest" ]
145
- then
146
- echo "You asked for #{salt_version} and you have ${SALT_VERSION} installed, sweet!"
147
- elif [ ! -z "${SALT_VERSION}" -a "#{salt_install}" = "bootstrap" ]
148
- then
149
- echo "You asked for bootstrap install and you have got ${SALT_VERSION}, hope thats ok!"
150
- else
151
- echo "You asked for #{salt_version} and you have got ${SALT_VERSION} installed, dunno how to fix that, sorry!"
152
- exit 2
153
- fi
154
-
155
- #{install_chef}
89
+ if windows_os?
90
+ install_template = File.expand_path("./../install_win.erb", __FILE__)
91
+ else
92
+ install_template = File.expand_path("./../install.erb", __FILE__)
93
+ end
156
94
 
157
- '
158
- INSTALL
95
+ erb = ERB.new(File.read(install_template)).result(binding)
96
+ debug("Install Command:" + erb.to_s)
97
+ erb
159
98
  end
160
99
 
161
100
  def install_chef
162
101
  return unless config[:require_chef]
163
102
  chef_url = config[:chef_bootstrap_url]
164
- omnibus_download_dir = config[:omnibus_cachier] ? "/tmp/vagrant-cache/omnibus_chef" : "/tmp"
165
- <<-INSTALL
166
- if [ ! -d "/opt/chef" ]
167
- then
168
- echo "-----> Installing Chef Omnibus (for busser/serverspec ruby support)"
169
- mkdir -p #{omnibus_download_dir}
170
- if [ ! -x #{omnibus_download_dir}/install.sh ]
171
- then
172
- do_download #{chef_url} #{omnibus_download_dir}/install.sh
173
- fi
174
- #{sudo('sh')} #{omnibus_download_dir}/install.sh -d #{omnibus_download_dir}
175
- fi
176
- INSTALL
103
+ if windows_os?
104
+ <<-POWERSHELL
105
+ if (-Not $(test-path c:\\opscode\\chef) {
106
+ if (-Not $(Test-Path c:\\temp)) {
107
+ New-Item -Path c:\\temp -itemtype directory
108
+ }
109
+ (New-Object net.webclient).DownloadFile("#{chef_url}", "c:\\temp\\chef_bootstrap.ps1")
110
+ write-host "-----> Installing Chef Omnibus (for busser/serverspec ruby support)"
111
+ #{sudo('powershell')} c:\\temp\\chef_bootstrap.ps1
112
+ }
113
+ POWERSHELL
114
+ else
115
+ omnibus_download_dir = config[:omnibus_cachier] ? '/tmp/vagrant-cache/omnibus_chef' : '/tmp'
116
+ bootstrap_url = config[:bootstrap_url]
117
+ bootstrap_download_dir = '/tmp'
118
+ <<-INSTALL
119
+ echo "-----> Trying to install ruby(-dev) using assets.sh from kitchen-salt"
120
+ mkdir -p #{bootstrap_download_dir}
121
+ if [ ! -x #{bootstrap_download_dir}/install.sh ]
122
+ then
123
+ do_download #{bootstrap_url} #{bootstrap_download_dir}/install.sh
124
+ fi
125
+ #{sudo('sh')} #{bootstrap_download_dir}/install.sh -d #{bootstrap_download_dir}
126
+ if [ $? -ne 0 ] || [ ! -d "/opt/chef" ]
127
+ then
128
+ echo "Failed install ruby(-dev) using assets.sh from kitchen-salt"
129
+ echo "-----> Fallback to Chef Bootstrap script (for busser/serverspec ruby support)"
130
+ mkdir -p "#{omnibus_download_dir}"
131
+ if [ ! -x #{omnibus_download_dir}/install.sh ]
132
+ #{sudo('sh')} #{omnibus_download_dir}/install.sh -d #{omnibus_download_dir}
133
+ fi;
134
+ INSTALL
135
+ end
177
136
  end
178
137
 
179
138
  def create_sandbox
@@ -182,75 +141,78 @@ module Kitchen
182
141
  prepare_minion
183
142
  prepare_pillars
184
143
  prepare_grains
185
-
186
- if config[:state_collection] || config[:is_file_root]
187
- prepare_state_collection
188
- else
189
- prepare_formula config[:kitchen_root], config[:formula]
190
-
191
- unless config[:vendor_path].nil?
192
- if Pathname.new(config[:vendor_path]).exist?
193
- deps = if Pathname.new(config[:vendor_path]).absolute?
194
- Dir["#{config[:vendor_path]}/*"]
195
- else
196
- Dir["#{config[:kitchen_root]}/#{config[:vendor_path]}/*"]
197
- end
198
-
199
- deps.each do |d|
200
- prepare_formula "#{config[:kitchen_root]}/#{config[:vendor_path]}", File.basename(d)
201
- end
202
- else
203
- # :vendor_path was set, but not valid
204
- raise UserError, "kitchen-salt: Invalid vendor_path set: #{config[:vendor_path]}"
205
- end
206
- end
207
- end
208
-
209
- config[:dependencies].each do |formula|
210
- prepare_formula formula[:path], formula[:name]
211
- end
144
+ prepare_states
212
145
  prepare_state_top
146
+ # upload scripts, cached formulas, and setup system repositories
147
+ prepare_dependencies
213
148
  end
214
149
 
215
150
  def init_command
216
- debug("Initialising Driver #{self.name} by cleaning #{config[:root_path]}")
217
- "#{sudo('rm')} -rf #{config[:root_path]} ; mkdir -p #{config[:root_path]}"
151
+ debug("Initialising Driver #{name}")
152
+ if windows_os?
153
+ cmd = "mkdir -Force -Path ""#{config[:root_path]}"""
154
+ else
155
+ cmd = "mkdir -p '#{config[:root_path]}';"
156
+ end
157
+ cmd += <<-INSTALL
158
+ #{config[:init_environment]}
159
+ INSTALL
160
+ cmd
218
161
  end
219
162
 
220
- def run_command
221
- debug("running driver #{self.name}")
222
- # sudo(File.join(config[:root_path], File.basename(config[:script])))
223
- debug(diagnose())
224
- if config[:salt_run_highstate]
225
- cmd = sudo("salt-call --config-dir=#{File.join(config[:root_path], config[:salt_config])} --local state.highstate")
226
- end
163
+ def salt_command
164
+ salt_version = config[:salt_version]
227
165
 
228
- if config[:log_level]
229
- cmd << " --log-level=#{config[:log_level]}"
166
+ cmd = ""
167
+ if windows_os?
168
+ salt_call = "c:\\salt\\salt-call.bat"
169
+ salt_config_path = config[:salt_config].gsub('/', '\\')
170
+ cmd << "(get-content #{File.join(config[:root_path], salt_config_path, 'minion').gsub('/', '\\')}).replace(\"`$env`:TEMP\", $env:TEMP) | set-content #{File.join(config[:root_path], salt_config_path, 'minion').gsub('/', '\\')} ;"
171
+ else
172
+ # install/update dependencies
173
+ cmd << sudo("chmod +x #{config[:root_path]}/*.sh;")
174
+ cmd << sudo("#{config[:root_path]}/dependencies.sh;")
175
+ salt_config_path = config[:salt_config]
176
+ salt_call = "salt-call"
177
+ end
178
+ cmd << sudo("#{salt_call} --state-output=changes --config-dir=#{File.join(config[:root_path], salt_config_path)} --local state.highstate")
179
+ cmd << " --log-level=#{config[:log_level]}" if config[:log_level]
180
+ cmd << " --id=#{config[:salt_minion_id]}" if config[:salt_minion_id]
181
+ cmd << " test=#{config[:dry_run]}" if config[:dry_run]
182
+ if salt_version > RETCODE_VERSION || salt_version == 'latest'
183
+ # hope for the best and hope it works eventually
184
+ cmd << ' --retcode-passthrough'
230
185
  end
186
+ if windows_os?
187
+ cmd << ' ; exit $LASTEXITCODE'
188
+ end
189
+ cmd
190
+ end
191
+
192
+ def run_command
193
+ debug("running driver #{name}")
194
+ debug(diagnose)
231
195
 
232
196
  # config[:salt_version] can be 'latest' or 'x.y.z', 'YYYY.M.x' etc
233
197
  # error return codes are a mess in salt:
234
198
  # https://github.com/saltstack/salt/pull/11337
235
199
  # Unless we know we have a version that supports --retcode-passthrough
236
200
  # attempt to scan the output for signs of failure
237
- if config[:salt_version] > RETCODE_VERSION || config[:salt_version] == 'latest'
238
- # hope for the best and hope it works eventually
239
- cmd = cmd + " --retcode-passthrough"
240
- else
201
+ if config[:salt_version] <= RETCODE_VERSION
241
202
  # scan the output for signs of failure, there is a risk of false negatives
242
203
  fail_grep = 'grep -e Result.*False -e Data.failed.to.compile -e No.matching.sls.found.for'
243
204
  # capture any non-zero exit codes from the salt-call | tee pipe
244
- cmd = 'set -o pipefail ; ' << cmd
205
+ cmd = 'set -o pipefail ; ' << salt_command
245
206
  # Capture the salt-call output & exit code
246
- cmd << " 2>&1 | tee /tmp/salt-call-output ; SC=$? ; echo salt-call exit code: $SC ;"
207
+ cmd << ' 2>&1 | tee /tmp/salt-call-output ; SC=$? ; echo salt-call exit code: $SC ;'
247
208
  # check the salt-call output for fail messages
248
209
  cmd << " (sed '/#{fail_grep}/d' /tmp/salt-call-output | #{fail_grep} ; EC=$? ; echo salt-call output grep exit code ${EC} ;"
249
210
  # use the non-zer exit code from salt-call, then invert the results of the grep for failures
250
- cmd << " [ ${SC} -ne 0 ] && exit ${SC} ; [ ${EC} -eq 0 ] && exit 1 ; [ ${EC} -eq 1 ] && exit 0)"
211
+ cmd << ' [ ${SC} -ne 0 ] && exit ${SC} ; [ ${EC} -eq 0 ] && exit 1 ; [ ${EC} -eq 1 ] && exit 0)'
212
+ cmd
213
+ else
214
+ salt_command
251
215
  end
252
-
253
- cmd
254
216
  end
255
217
 
256
218
  protected
@@ -258,123 +220,34 @@ module Kitchen
258
220
  def prepare_data
259
221
  return unless config[:data_path]
260
222
 
261
- info("Preparing data")
223
+ info('Preparing data')
262
224
  debug("Using data from #{config[:data_path]}")
263
225
 
264
- tmpdata_dir = File.join(sandbox_path, "data")
226
+ tmpdata_dir = File.join(sandbox_path, 'data')
265
227
  FileUtils.mkdir_p(tmpdata_dir)
266
- #FileUtils.cp_r(Dir.glob("#{config[:data_path]}/*"), tmpdata_dir)
267
228
  cp_r_with_filter(config[:data_path], tmpdata_dir, config[:salt_copy_filter])
268
229
  end
269
230
 
270
231
  def prepare_minion
271
- info("Preparing salt-minion")
272
-
273
- minion_config_content = <<-MINION_CONFIG.gsub(/^ {10}/, '')
274
- state_top: top.sls
275
-
276
- file_client: local
277
-
278
- file_roots:
279
- #{config[:salt_env]}:
280
- - #{File.join(config[:root_path], config[:salt_file_root])}
281
-
282
- pillar_roots:
283
- #{config[:salt_env]}:
284
- - #{File.join(config[:root_path], config[:salt_pillar_root])}
285
- MINION_CONFIG
286
-
287
- # create the temporary path for the salt-minion config file
288
- debug("sandbox is #{sandbox_path}")
289
- sandbox_minion_config_path = File.join(sandbox_path, config[:salt_minion_config])
290
-
291
- # create the directory & drop the file in
292
- FileUtils.mkdir_p(File.dirname(sandbox_minion_config_path))
293
- File.open(sandbox_minion_config_path, "wb") do |file|
294
- file.write(minion_config_content)
295
- end
232
+ info('Preparing salt-minion')
296
233
 
297
- end
298
-
299
- def unsymbolize(obj)
300
- return obj.inject({}){|memo,(k,v)| memo[k.to_s] = unsymbolize(v); memo} if obj.is_a? Hash
301
- return obj.inject([]){|memo,v| memo << unsymbolize(v); memo} if obj.is_a? Array
302
- return obj
303
- end
304
-
305
- def prepare_state_top
306
- info("Preparing state_top")
307
-
308
- sandbox_state_top_path = File.join(sandbox_path, config[:salt_state_top])
309
-
310
- if (config[:state_top_from_file] == false)
311
- # use the top.sls embedded in .kitchen.yml
312
-
313
- # we get a hash with all the keys converted to symbols, salt doesn't like this
314
- # to convert all the keys back to strings again
315
- state_top_content = unsymbolize(config[:state_top]).to_yaml
316
- # .to_yaml will produce ! '*' for a key, Salt doesn't like this either
317
- state_top_content.gsub!(/(!\s'\*')/, "'*'")
234
+ if config[:salt_minion_config_template]
235
+ minion_template = File.expand_path(config[:salt_minion_config_template], Kitchen::Config.new.kitchen_root)
318
236
  else
319
- # load a top.sls from disk
320
- state_top_content = File.read("top.sls")
237
+ minion_template = File.expand_path("./../minion.erb", __FILE__)
321
238
  end
322
239
 
323
- # create the directory & drop the file in
324
- FileUtils.mkdir_p(File.dirname(sandbox_state_top_path))
325
- File.open(sandbox_state_top_path, "wb") do |file|
326
- file.write(state_top_content)
240
+ if File.extname(minion_template) == ".erb"
241
+ minion_config_content = ERB.new(File.read(minion_template)).result(binding)
242
+ else
243
+ minion_config_content = File.read(minion_template)
327
244
  end
328
- end
329
-
330
- def prepare_pillars
331
- info("Preparing pillars into #{config[:salt_pillar_root]}")
332
- debug("Pillars Hash: #{config[:pillars]}")
333
-
334
- return if config[:pillars].nil? && config[:'pillars-from-files'].nil?
335
245
 
336
- # we get a hash with all the keys converted to symbols, salt doesn't like this
337
- # to convert all the keys back to strings again
338
- pillars = unsymbolize(config[:pillars])
339
- debug("unsymbolized pillars hash: #{pillars}")
340
-
341
- # write out each pillar (we get key/contents pairs)
342
- pillars.each do |key,contents|
343
-
344
- # convert the hash to yaml
345
- pillar = contents.to_yaml
346
-
347
- # .to_yaml will produce ! '*' for a key, Salt doesn't like this either
348
- pillar.gsub!(/(!\s'\*')/, "'*'")
349
-
350
- # generate the filename
351
- sandbox_pillar_path = File.join(sandbox_path, config[:salt_pillar_root], key)
352
-
353
- # create the directory where the pillar file will go
354
- FileUtils.mkdir_p(File.dirname(sandbox_pillar_path))
355
-
356
- debug("Rendered pillar yaml for #{key}:\n #{pillar}")
357
- # create the directory & drop the file in
358
- File.open(sandbox_pillar_path, "wb") do |file|
359
- file.write(pillar)
360
- end
361
- end
246
+ # create the temporary path for the salt-minion config file
247
+ debug("sandbox is #{sandbox_path}")
248
+ sandbox_minion_config_path = File.join(sandbox_path, config[:salt_minion_config])
362
249
 
363
- # copy the pillars from files straight across, as YAML.load/to_yaml and
364
- # munge multiline strings
365
- if !config[:'pillars-from-files'].nil?
366
- external_pillars = unsymbolize(config[:'pillars-from-files'])
367
- debug("external_pillars (unsymbolize): #{external_pillars}")
368
- external_pillars.each do |key, srcfile|
369
- debug("Copying external pillar: #{key}, #{srcfile}")
370
- # generate the filename
371
- sandbox_pillar_path = File.join(sandbox_path, config[:salt_pillar_root], key)
372
- # create the directory where the pillar file will go
373
- FileUtils.mkdir_p(File.dirname(sandbox_pillar_path))
374
- # copy the file across
375
- FileUtils.copy srcfile, sandbox_pillar_path
376
- end
377
- end
250
+ write_raw_file(sandbox_minion_config_path, minion_config_content)
378
251
  end
379
252
 
380
253
  def prepare_grains
@@ -383,101 +256,44 @@ module Kitchen
383
256
  return if config[:grains].nil?
384
257
 
385
258
  info("Preparing grains into #{config[:salt_config]}/grains")
386
- # we get a hash with all the keys converted to symbols, salt doesn't like this
387
- # to convert all the keys back to strings again we use unsymbolize
388
- # then we convert the hash to yaml
389
- grains = unsymbolize(config[:grains]).to_yaml
390
259
 
391
260
  # generate the filename
392
261
  sandbox_grains_path = File.join(sandbox_path, config[:salt_config], 'grains')
393
262
  debug("sandbox_grains_path: #{sandbox_grains_path}")
394
263
 
395
- # create the directory where the pillar file will go
396
- FileUtils.mkdir_p(File.dirname(sandbox_grains_path))
397
-
398
- debug("Rendered grains yaml")
399
- # create the directory & drop the file in
400
- File.open(sandbox_grains_path, "wb") do |file|
401
- file.write(grains)
402
- end
264
+ write_hash_file(sandbox_grains_path, config[:grains])
403
265
  end
404
266
 
405
- def prepare_formula(path, formula)
406
- info("Preparing formula: #{formula} from #{path}")
407
- debug("Using config #{config}")
408
-
409
- formula_dir = File.join(sandbox_path, config[:salt_file_root], formula)
410
- FileUtils.mkdir_p(formula_dir)
411
- cp_r_with_filter(File.join(path, formula), formula_dir, config[:salt_copy_filter])
412
-
413
- # copy across the _modules etc directories for python implementation
414
- ['_modules', '_states', '_grains', '_renderers', '_returners'].each do |extrapath|
415
- src = File.join(path, extrapath)
416
-
417
- if (File.directory?(src))
418
- debug("prepare_formula: #{src} exists, copying..")
419
- extrapath_dir = File.join(sandbox_path, config[:salt_file_root], extrapath)
420
- FileUtils.mkdir_p(extrapath_dir)
421
- #FileUtils.cp_r(Dir.glob(File.join(src, "*")), extrapath_dir)
422
- cp_r_with_filter(src, extrapath_dir, config[:salt_copy_filter])
423
- else
424
- debug("prepare_formula: #{src} doesn't exist, skipping.")
425
- end
426
- end
427
- end
267
+ def prepare_dependencies
268
+ # upload scripts
269
+ sandbox_scripts_path = File.join(sandbox_path, config[:salt_config], 'scripts')
270
+ info("Preparing scripts into #{config[:salt_config]}/scripts")
428
271
 
429
- def prepare_state_collection
430
- info("Preparing state collection")
431
- debug("Using config #{config}")
272
+ # PLACEHOLDER, git formulas might be fetched locally to temp and uploaded
432
273
 
433
- if config[:collection_name].nil? and config[:formula].nil?
434
- info("neither collection_name or formula have been set, assuming this is a pre-built collection")
435
- config[:collection_name] = ""
436
- else
437
- if config[:collection_name].nil?
438
- debug("collection_name not set, using #{config[:formula]}")
439
- config[:collection_name] = config[:formula]
440
- end
441
- end
274
+ # setup spm
275
+ spm_repos = config[:vendor_repo].select{|x| x[:type]=='spm'}.each{|x| x[:url]}.map {|x| x[:url] }
276
+ spm_repos.each do |url|
277
+ id=url.gsub(/[htp:\/.]/,'')
278
+ spmreposd = File.join(sandbox_path, 'etc', 'salt', 'spm.repos.d')
279
+ repo_spec = File.join(spmreposd, 'spm.repo')
280
+ FileUtils.mkdir_p(spmreposd)
281
+ repo_content = '
282
+ #{id}:
283
+ url: #{url}
442
284
 
443
- debug("sandbox_path = #{sandbox_path}")
444
- debug("salt_file_root = #{config[:salt_file_root]}")
445
- debug("collection_name = #{config[:collection_name]}")
446
- collection_dir = File.join(sandbox_path, config[:salt_file_root], config[:collection_name])
447
- FileUtils.mkdir_p(collection_dir)
448
- cp_r_with_filter(config[:kitchen_root], collection_dir, config[:salt_copy_filter])
449
-
450
- end
285
+ '
286
+ write_raw_file(repo_spec, repo_content)
287
+ end
451
288
 
452
- def cp_r_with_filter(source_path, target_path, filter=[])
453
- debug("cp_r_with_filter:source_path = #{source_path}")
454
- debug("cp_r_with_filter:target_path = #{target_path}")
455
- debug("cp_r_with_filter:filter = #{filter}")
456
-
457
- Array(source_path).each do |source_path|
458
- Find.find(source_path) do |source|
459
- target = source.sub(/^#{source_path}/, target_path)
460
- debug("cp_r_with_filter:source = #{source}")
461
- debug("cp_r_with_filter:target = #{target}")
462
- filtered = filter.include?(File.basename(source))
463
- if File.directory? source
464
- if filtered
465
- debug("Found #{source} in #{filter}, pruning it from the Find")
466
- Find.prune
467
- end
468
- FileUtils.mkdir target unless File.exists? target
469
- if File.symlink? source
470
- FileUtils.cp_r "#{source}/.", target
471
- end
472
- else
473
- if filtered
474
- debug("Found #{source} in #{filter}, not copying file")
475
- else
476
- FileUtils.copy source, target
477
- end
478
- end
479
- end
289
+ # upload scripts
290
+ %w(formula-fetch.sh repository-setup.sh).each do |script|
291
+ write_raw_file(File.join(sandbox_path, script), File.read(File.expand_path("../#{script}", __FILE__)))
480
292
  end
293
+ dependencies_script = File.expand_path("./../dependencies.erb", __FILE__)
294
+ dependencies_content = ERB.new(File.read(dependencies_script)).result(binding)
295
+ write_raw_file(File.join(sandbox_path, 'dependencies.sh'), dependencies_content)
296
+
481
297
  end
482
298
  end
483
299
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kitchen-salt
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.24
4
+ version: 0.0.25
5
5
  platform: ruby
6
6
  authors:
7
7
  - Simon McCartney
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-08-24 00:00:00.000000000 Z
11
+ date: 2017-06-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: test-kitchen
@@ -73,7 +73,16 @@ executables: []
73
73
  extensions: []
74
74
  extra_rdoc_files: []
75
75
  files:
76
+ - lib/kitchen-salt/pillars.rb
77
+ - lib/kitchen-salt/states.rb
78
+ - lib/kitchen-salt/util.rb
76
79
  - lib/kitchen-salt/version.rb
80
+ - lib/kitchen/provisioner/dependencies.erb
81
+ - lib/kitchen/provisioner/formula-fetch.sh
82
+ - lib/kitchen/provisioner/install.erb
83
+ - lib/kitchen/provisioner/install_win.erb
84
+ - lib/kitchen/provisioner/minion.erb
85
+ - lib/kitchen/provisioner/repository-setup.sh
77
86
  - lib/kitchen/provisioner/salt_solo.rb
78
87
  homepage: https://github.com//kitchen-salt
79
88
  licenses:
@@ -95,7 +104,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
95
104
  version: '0'
96
105
  requirements: []
97
106
  rubyforge_project: "[none]"
98
- rubygems_version: 2.5.1
107
+ rubygems_version: 2.6.12
99
108
  signing_key:
100
109
  specification_version: 4
101
110
  summary: salt provisioner for test-kitchen