vagrant-bolt 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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