kitchen-salt 0.0.24 → 0.0.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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