vagrant-bolt 0.1.0

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.
Files changed (67) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/.rspec +2 -0
  4. data/.rubocop.yml +124 -0
  5. data/.travis.yml +28 -0
  6. data/.yardopts +1 -0
  7. data/Gemfile +37 -0
  8. data/LICENSE +12 -0
  9. data/Puppetfile +7 -0
  10. data/README.md +431 -0
  11. data/Rakefile +19 -0
  12. data/Vagrantfile +47 -0
  13. data/acceptance/artifacts/.keep +0 -0
  14. data/acceptance/components/bolt_spec.rb +98 -0
  15. data/acceptance/skeletons/advanced/Vagrantfile +26 -0
  16. data/acceptance/skeletons/base/Vagrantfile +11 -0
  17. data/acceptance/skeletons/base/modules/facts/CHANGELOG.md +26 -0
  18. data/acceptance/skeletons/base/modules/facts/CONTRIBUTING.md +279 -0
  19. data/acceptance/skeletons/base/modules/facts/Gemfile +98 -0
  20. data/acceptance/skeletons/base/modules/facts/LICENSE +201 -0
  21. data/acceptance/skeletons/base/modules/facts/README.md +45 -0
  22. data/acceptance/skeletons/base/modules/facts/Rakefile +8 -0
  23. data/acceptance/skeletons/base/modules/facts/checksums.json +42 -0
  24. data/acceptance/skeletons/base/modules/facts/lib/puppet/functions/facts/group_by.rb +14 -0
  25. data/acceptance/skeletons/base/modules/facts/metadata.json +62 -0
  26. data/acceptance/skeletons/base/modules/facts/plans/info.pp +16 -0
  27. data/acceptance/skeletons/base/modules/facts/plans/init.pp +13 -0
  28. data/acceptance/skeletons/base/modules/facts/tasks/bash.json +5 -0
  29. data/acceptance/skeletons/base/modules/facts/tasks/bash.sh +93 -0
  30. data/acceptance/skeletons/base/modules/facts/tasks/init.json +10 -0
  31. data/acceptance/skeletons/base/modules/facts/tasks/powershell.json +4 -0
  32. data/acceptance/skeletons/base/modules/facts/tasks/powershell.ps1 +56 -0
  33. data/acceptance/skeletons/base/modules/facts/tasks/ruby.json +4 -0
  34. data/acceptance/skeletons/base/modules/facts/tasks/ruby.rb +40 -0
  35. data/acceptance/skeletons/provisioner/Vagrantfile +19 -0
  36. data/acceptance/skeletons/trigger/Vagrantfile +22 -0
  37. data/acceptance/vagrant-spec.config.rb +22 -0
  38. data/lib/vagrant-bolt.rb +57 -0
  39. data/lib/vagrant-bolt/command.rb +65 -0
  40. data/lib/vagrant-bolt/config.rb +6 -0
  41. data/lib/vagrant-bolt/config/bolt.rb +135 -0
  42. data/lib/vagrant-bolt/config/global.rb +172 -0
  43. data/lib/vagrant-bolt/config_builder.rb +11 -0
  44. data/lib/vagrant-bolt/config_builder/config.rb +150 -0
  45. data/lib/vagrant-bolt/config_builder/monkey_patches.rb +71 -0
  46. data/lib/vagrant-bolt/config_builder/provisioner.rb +106 -0
  47. data/lib/vagrant-bolt/config_builder/triggers.rb +29 -0
  48. data/lib/vagrant-bolt/plugin.rb +39 -0
  49. data/lib/vagrant-bolt/provisioner.rb +18 -0
  50. data/lib/vagrant-bolt/runner.rb +88 -0
  51. data/lib/vagrant-bolt/util/bolt.rb +139 -0
  52. data/lib/vagrant-bolt/util/config.rb +43 -0
  53. data/lib/vagrant-bolt/util/machine.rb +73 -0
  54. data/lib/vagrant-bolt/version.rb +5 -0
  55. data/spec/spec_helper.rb +12 -0
  56. data/spec/unit/config/bolt_spec.rb +150 -0
  57. data/spec/unit/config/global_spec.rb +95 -0
  58. data/spec/unit/provisioner/bolt_spec.rb +39 -0
  59. data/spec/unit/runner/runner_spec.rb +122 -0
  60. data/spec/unit/util/bolt_spec.rb +148 -0
  61. data/spec/unit/util/config_spec.rb +53 -0
  62. data/spec/unit/vagrant_spec.rb +9 -0
  63. data/tasks/acceptance.rake +45 -0
  64. data/tasks/spec.rake +5 -0
  65. data/templates/locales/en.yml +24 -0
  66. data/vagrant-bolt.gemspec +24 -0
  67. metadata +109 -0
@@ -0,0 +1,16 @@
1
+ # A plan that prints basic OS information for the specified nodes. It first
2
+ # runs the facts task to retrieve facts from the nodes, then compiles the
3
+ # desired OS information from the os fact value of each nodes.
4
+ #
5
+ # The $nodes parameter is a list of the nodes for which to print the OS
6
+ # information. This plan primarily provides readable formatting, and ignores
7
+ # nodes that error.
8
+ plan facts::info(TargetSpec $nodes) {
9
+ return run_task('facts', $nodes, '_catch_errors' => true).reduce([]) |$info, $r| {
10
+ if ($r.ok) {
11
+ $info + "${r.target.name}: ${r[os][name]} ${r[os][release][full]} (${r[os][family]})"
12
+ } else {
13
+ $info # don't include any info for nodes which failed
14
+ }
15
+ }
16
+ }
@@ -0,0 +1,13 @@
1
+ # A plan that retrieves facts and stores in the inventory for the
2
+ # specified nodes.
3
+ #
4
+ # The $nodes parameter is a list of nodes to retrieve the facts for.
5
+ plan facts(TargetSpec $nodes) {
6
+ $result_set = run_task('facts', $nodes)
7
+
8
+ $result_set.each |$result| {
9
+ add_facts($result.target, $result.value)
10
+ }
11
+
12
+ return $result_set
13
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "description": "Gather system facts using bash",
3
+ "input_method": "environment",
4
+ "parameters": {}
5
+ }
@@ -0,0 +1,93 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # Delegate to facter if available
4
+ export PATH="$PATH:/opt/puppetlabs/bin"
5
+ command -v facter > /dev/null 2>&1 && exec facter -p --json --show-legacy
6
+
7
+ minor () {
8
+ minor="${*#*.}"
9
+ [ "$minor" == "$*" ] || echo "${minor%%.*}"
10
+ }
11
+
12
+ # Determine the OS name
13
+ if [ -f /etc/redhat-release ]; then
14
+ if egrep -iq centos /etc/redhat-release; then
15
+ name=CentOS
16
+ elif egrep -iq 'Fedora release' /etc/redhat-release; then
17
+ name=Fedora
18
+ fi
19
+ release=$(sed -r -e 's/^.* release ([0-9]+(\.[0-9]+)?).*$/\1/' \
20
+ /etc/redhat-release)
21
+ fi
22
+
23
+ if [ -z "${name}" ]; then
24
+ LSB_RELEASE=$(command -v lsb_release)
25
+ if [ -n "$LSB_RELEASE" ]; then
26
+ if [ -z "$name" ]; then
27
+ name=$($LSB_RELEASE -i | sed -re 's/^.*:[ \t]*//')
28
+ fi
29
+ release=$($LSB_RELEASE -r | sed -re 's/^.*:[ \t]*//')
30
+ fi
31
+ fi
32
+
33
+ # if lsb not available try os-release
34
+ if [ -z "${name}" ]; then
35
+ if [ -e /etc/os-release ]; then
36
+ name=$(grep "^NAME" /etc/os-release | cut -d'=' -f2 | sed "s/\"//g")
37
+ release=$(grep "^VERSION_ID" /etc/os-release | cut -d'=' -f2 | sed "s/\"//g")
38
+ elif [-e /usr/lib/os-release ]; then
39
+ name=$(grep "^NAME" /usr/lib/os-release | cut -d'=' -f2 | sed "s/\"//g")
40
+ release=$(grep "^VERSION_ID" /usr/lib/os-release | cut -d'=' -f2 | sed "s/\"//g")
41
+ fi
42
+ if [ -n "${name}" ]; then
43
+ if echo "${name}" | egrep -iq "(.*red)(.*hat)"; then
44
+ name="RedHat"
45
+ elif echo "${name}" | egrep -iq "debian"; then
46
+ name="Debian"
47
+ fi
48
+ fi
49
+ fi
50
+
51
+ if [ -z "${name}" ]; then
52
+ name=$(uname)
53
+ release=$(uname -r)
54
+ fi
55
+
56
+ case $name in
57
+ RedHat|Fedora|CentOS|Scientific|SLC|Ascendos|CloudLinux)
58
+ family=RedHat;;
59
+ HuaweiOS|LinuxMint|Ubuntu|Debian)
60
+ family=Debian;;
61
+ *)
62
+ family=$name;;
63
+ esac
64
+
65
+ # Print it all out
66
+ if [ -z "$name" ]; then
67
+ cat <<JSON
68
+ {
69
+ "_error": {
70
+ "kind": "facts/noname",
71
+ "msg": "Could not determine OS name"
72
+ }
73
+ }
74
+ JSON
75
+ else
76
+ cat <<JSON
77
+ {
78
+ "os": {
79
+ "name": "${name}",
80
+ JSON
81
+ [ -n "$release" ] && cat <<JSON
82
+ "release": {
83
+ "full": "${release}",
84
+ "major": "${release%%.*}",
85
+ "minor": "`minor "${release}"`"
86
+ },
87
+ JSON
88
+ cat <<JSON
89
+ "family": "${family}"
90
+ }
91
+ }
92
+ JSON
93
+ fi
@@ -0,0 +1,10 @@
1
+ {
2
+ "description": "Gather system facts",
3
+ "parameters": {},
4
+ "input_method": "environment",
5
+ "implementations": [
6
+ {"name": "ruby.rb", "requirements": ["puppet-agent"]},
7
+ {"name": "powershell.ps1", "requirements": ["powershell"]},
8
+ {"name": "bash.sh", "requirements": ["shell"]}
9
+ ]
10
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "description": "Gather system facts using powershell",
3
+ "parameters": {}
4
+ }
@@ -0,0 +1,56 @@
1
+ #!powershell.exe
2
+
3
+ # Delegate to facter if available
4
+ if (Get-Command facter -ErrorAction SilentlyContinue) {
5
+ facter -p --json --show-legacy
6
+ }
7
+ else {
8
+ # The number 2 in the condition below is the value of
9
+ # the [System.PlatformID]::Win32NT constant. We don't
10
+ # use the constant here as it doesn't work on Windows
11
+ # Server Core.
12
+ if ([System.Environment]::OSVersion.Platform -gt 2) {
13
+ @'
14
+ {
15
+ "_error": {
16
+ "kind": "facts/noname",
17
+ "msg": "Could not determine OS name"
18
+ }
19
+ }
20
+ '@
21
+ }
22
+ else {
23
+ $release = [System.Environment]::OSVersion.Version.ToString() -replace '\.[^.]*\z'
24
+ $version = $release -replace '\.[^.]*\z'
25
+
26
+ # This fails for regular users unless explicitly enabled
27
+ $os = Get-CimInstance Win32_OperatingSystem -ErrorAction SilentlyContinue
28
+ $consumerrel = $os.ProductType -eq '1'
29
+
30
+ $release = switch($version){
31
+ '10.0'{ if ($consumerrel) { '10' } else { '2016' } }
32
+ '6.3' { if ($consumerrel) { '8.1' } else { '2012 R2' } }
33
+ '6.2' { if ($consumerrel) { '8' } else { '2012' } }
34
+ '6.1' { if ($consumerrel) { '7' } else { '2008 R2' } }
35
+ '6.0' { if ($consumerrel) { 'Vista' } else { '2008' } }
36
+ '5.2' {
37
+ if ($consumerrel) { 'XP' } else {
38
+ if ($os.OtherTypeDescription -eq 'R2') { '2003 R2' } else { '2003' }
39
+ }
40
+ }
41
+ }
42
+
43
+ @"
44
+ {
45
+ "os": {
46
+ "name": "windows",
47
+ "release": {
48
+ "full": "$release",
49
+ "major": "$release"
50
+ },
51
+ "family": "windows"
52
+ }
53
+ }
54
+ "@
55
+ }
56
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "description": "Gather system facts using ruby and facter",
3
+ "parameters": {}
4
+ }
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ def facter_executable
5
+ if Gem.win_platform?
6
+ require 'win32/registry'
7
+ installed_dir =
8
+ begin
9
+ Win32::Registry::HKEY_LOCAL_MACHINE.open('SOFTWARE\Puppet Labs\Puppet') do |reg|
10
+ # rubocop:disable Style/RescueModifier
11
+ # Rescue missing key
12
+ dir = reg['RememberedInstallDir64'] rescue ''
13
+ # Both keys may exist, make sure the dir exists
14
+ break dir if File.exist?(dir)
15
+
16
+ # Rescue missing key
17
+ reg['RememberedInstallDir'] rescue ''
18
+ # rubocop:enable Style/RescueModifier
19
+ end
20
+ rescue Win32::Registry::Error
21
+ # Rescue missing registry path
22
+ ''
23
+ end
24
+
25
+ facter =
26
+ if installed_dir.empty?
27
+ ''
28
+ else
29
+ File.join(installed_dir, 'bin', 'facter')
30
+ end
31
+ else
32
+ facter = '/opt/puppetlabs/puppet/bin/facter'
33
+ end
34
+
35
+ # Fall back to PATH lookup if puppet-agent isn't installed
36
+ File.exist?(facter) ? facter : 'facter'
37
+ end
38
+
39
+ # Delegate to facter
40
+ exec(facter_executable, '-p', '--json', '--show-legacy')
@@ -0,0 +1,19 @@
1
+ require 'vagrant-spec/which'
2
+ Vagrant.configure('2') do |config|
3
+ config.bolt.bolt_exe = Vagrant::Spec::Which.which('bolt')
4
+ config.vm.box = 'box'
5
+ config.vm.define 'server' do |node|
6
+ node.vm.provision :bolt do |bolt|
7
+ bolt.command = :task
8
+ bolt.name = "facts"
9
+ end
10
+ node.vm.provision :bolt do |bolt|
11
+ bolt.command = :plan
12
+ bolt.name = "facts"
13
+ end
14
+ node.vm.provision :bolt do |bolt|
15
+ bolt.command = :command
16
+ bolt.name = "hostname"
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,22 @@
1
+ require 'vagrant-spec/which'
2
+ Vagrant.configure('2') do |config|
3
+ config.bolt.bolt_exe = Vagrant::Spec::Which.which('bolt')
4
+ config.vm.box = 'box'
5
+ config.vm.define 'server' do |node|
6
+ node.trigger.after :up do |trigger|
7
+ trigger.ruby do |env, machine|
8
+ VagrantBolt.task("facts", env, machine)
9
+ end
10
+ end
11
+ node.trigger.after :up do |trigger|
12
+ trigger.ruby do |env, machine|
13
+ VagrantBolt.plan("facts", env, machine)
14
+ end
15
+ end
16
+ node.trigger.after :up do |trigger|
17
+ trigger.ruby do |env, machine|
18
+ VagrantBolt.command("hostname", env, machine)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'pathname'
4
+ require 'vagrant-bolt'
5
+ require 'vagrant-spec/acceptance'
6
+
7
+ # Prevent tests from attempting to load plugins from a Vagrant install
8
+ # that may exist on the host system. We load required plugins below.
9
+ ENV['VAGRANT_DISABLE_PLUGIN_INIT'] = '1'
10
+
11
+ Vagrant::Spec::Acceptance.configure do |c|
12
+ acceptance_dir = Pathname.new File.expand_path(__dir__)
13
+
14
+ c.component_paths = [(acceptance_dir + 'components').to_s]
15
+ c.skeleton_paths = [(acceptance_dir + 'skeletons').to_s]
16
+
17
+ c.provider 'virtualbox',
18
+ box: (acceptance_dir + 'artifacts' + 'virtualbox.box').to_s,
19
+ env_vars: {
20
+ 'VBOX_USER_HOME' => '{{homedir}}',
21
+ }
22
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module VagrantBolt
4
+ require 'vagrant-bolt/version'
5
+ require 'vagrant-bolt/plugin'
6
+ require 'vagrant-bolt/runner'
7
+
8
+ # Runs a bolt task with the specified parameters
9
+ #
10
+ # @param [String] task The name of the bolt task to run
11
+ # @param [Object] env The environment
12
+ # @param [Object] machine The machine
13
+ # @param [Hash] args A optional hash of bolt config overrides. No merging will be done with these overrides.
14
+ # @return [nil]
15
+ # @example
16
+ # VagrantBolt.task('facts', env, machine, run_as: "root", params: {taskparam: "value"})
17
+ def self.task(task, env, machine, **args)
18
+ runner = VagrantBolt::Runner.new(env, machine)
19
+ runner.run(:task, task, **args)
20
+ end
21
+
22
+ # Run a bolt plan with the specified parameters
23
+ #
24
+ # @param [String] plan The name of the bolt plan to run
25
+ # @param [Object] env The environment
26
+ # @param [Object] machine The machine
27
+ # @param [Hash] args A optional hash of bolt config overrides. No merging will be done with these overrides.
28
+ # @return [nil]
29
+ # @example
30
+ # VagrantBolt.plan('facts', env, machine, run_as: "root", params: {planparam: "value"})
31
+ def self.plan(plan, env, machine, **args)
32
+ runner = VagrantBolt::Runner.new(env, machine)
33
+ runner.run(:plan, plan, **args)
34
+ end
35
+
36
+ # Run a bolt command with the specified parameters
37
+ #
38
+ # @param [String] command The command to run
39
+ # @param [Object] env The environment
40
+ # @param [Object] machine The machine
41
+ # @param [Hash] args A optional hash of bolt config overrides. No merging will be done with these overrides.
42
+ # @return [nil]
43
+ # @example
44
+ # VagrantBolt.command('/bin/echo "test"', env, machine, run_as: "root")
45
+ def self.command(command, env, machine, **args)
46
+ runner = VagrantBolt::Runner.new(env, machine)
47
+ runner.run(:command, command, **args)
48
+ end
49
+
50
+ # Return the root directory of the source
51
+ # @return [String] the source root path
52
+ def self.source_root
53
+ @source_root ||= File.expand_path(__DIR__)
54
+ end
55
+ end
56
+
57
+ I18n.load_path << File.expand_path('../templates/locales/en.yml', File.dirname(__FILE__))
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'util/bolt'
4
+ require_relative 'util/machine'
5
+ require_relative 'util/config'
6
+
7
+ class VagrantBolt::Command < Vagrant.plugin('2', :command)
8
+ def self.synopsis
9
+ "Calls the bolt executable with the given options"
10
+ end
11
+
12
+ def execute
13
+ options = {}
14
+ options[:update] = false
15
+
16
+ parser = OptionParser.new do |o|
17
+ o.banner = "Usage: vagrant bolt <options> [bolt options]"
18
+ o.separator ""
19
+ o.separator "Options:"
20
+ o.separator ""
21
+
22
+ o.on("-u", "--[no-]updateinventory", "Update the inventory file (defaults to false)") do |u|
23
+ options[:update] = u
24
+ end
25
+ end
26
+
27
+ # This is a hack. We are passing everything to bolt, but still allow for bolt options.
28
+ # We just remove them from @argv here and use the rest.
29
+ # This allows for not having to define a seperator as long as there are no argument colisions
30
+ return if @argv.empty?
31
+
32
+ args = @argv.dup
33
+ begin
34
+ parser.parse!(args)
35
+ rescue OptionParser::InvalidOption
36
+ retry
37
+ end
38
+ bolt_args = @argv - ['-u', '--updateinventory', '--no-updateinventory']
39
+
40
+ VagrantBolt::Util::Bolt.update_inventory_file(@env) if options[:update]
41
+
42
+ execute_bolt_command(bolt_args)
43
+ end
44
+
45
+ # Run a bolt command with the inventory path, module path, and boltdir
46
+ # @param args [Array<String>] An array containing the bolt arguments
47
+ def execute_bolt_command(args)
48
+ bolt_exe = @env.vagrantfile.config.bolt.bolt_exe
49
+ modulepath = VagrantBolt::Util::Config.full_path(@env.vagrantfile.config.bolt.modulepath, @env.root_path)
50
+ boltdir = VagrantBolt::Util::Config.full_path(@env.vagrantfile.config.bolt.boltdir, @env.root_path)
51
+ inventoryfile = VagrantBolt::Util::Bolt.inventory_file(@env)
52
+
53
+ quoted_args = args.flatten.compact.map { |a| "'#{a}'" }
54
+ command = [
55
+ "\'#{bolt_exe}\'",
56
+ quoted_args,
57
+ '--modulepath',
58
+ "\'#{modulepath}\'",
59
+ '--boltdir',
60
+ "\'#{boltdir}\'",
61
+ ]
62
+ command << ['--inventoryfile', "\'#{inventoryfile}\'"] if File.exist?(inventoryfile)
63
+ VagrantBolt::Util::Machine.run_command(command.flatten.join(" "), @env.ui)
64
+ end
65
+ end