Class: BoltServer::PE::PAL

Inherits:
Bolt::PAL show all
Defined in:
lib/bolt_server/pe/pal.rb

Constant Summary collapse

PE_BOLTLIB_PATH =

PE_BOLTLIB_PATH is intended to function exactly like the BOLTLIB_PATH used in Bolt::PAL. Paths and variable names are similar to what exists in Bolt::PAL, but with a ‘PE’ prefix.

'/opt/puppetlabs/server/apps/bolt-server/pe-bolt-modules'
DEFAULT_BOLT_CODEDIR =

For now at least, we maintain an entirely separate codedir from puppetserver by default, so that filesync can work properly. If filesync is not used, this can instead match the usual puppetserver codedir. See the ‘orchestrator.bolt.codedir` tk config setting.

'/opt/puppetlabs/server/data/orchestration-services/code'

Constants inherited from Bolt::PAL

Bolt::PAL::BOLTLIB_PATH, Bolt::PAL::MODULES_PATH

Instance Attribute Summary

Attributes inherited from Bolt::PAL

#modulepath

Instance Method Summary collapse

Methods inherited from Bolt::PAL

#alias_types, configure_logging, #convert_plan, #generate_types, #get_plan_info, #get_task, #in_bolt_compiler, #in_plan_compiler, #in_task_compiler, #list_modulepath, #list_modules, #list_plans, #list_tasks, load_puppet, #parse_manifest, #parse_params, #register_resource_types, #run_plan, #run_task, #setup, #task_signature, #with_bolt_executor, #with_puppet_settings

Constructor Details

#initialize(plan_executor_config, environment_name, hiera_config = nil, max_compiles = nil) ⇒ PAL

Returns a new instance of PAL.



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/bolt_server/pe/pal.rb', line 44

def initialize(plan_executor_config, environment_name, hiera_config = nil, max_compiles = nil)
  # Bolt::PAL#initialize takes the modulepath as its first argument, but we
  # want to customize it later, so we pass an empty value:
  super([], hiera_config, max_compiles)

  codedir = plan_executor_config['codedir'] || DEFAULT_BOLT_CODEDIR
  environmentpath = plan_executor_config['environmentpath'] || "#{codedir}/environments"
  basemodulepath = plan_executor_config['basemodulepath'] || "#{codedir}/modules:/opt/puppetlabs/puppet/modules"

  with_pe_pal_init_settings(codedir, environmentpath, basemodulepath) do
    modulepath_dirs = []
    modulepath_setting_from_bolt = nil
    environment = Puppet.lookup(:environments).get!(environment_name)
    path_to_env = environment.configuration.path_to_env

    # In the instance where the environment is "production" but no production dir
    # exists, the lookup will succeed, but the configuration will be mostly empty.
    # For other environments the lookup will fail, but for production we don't
    # want cryptic messages sent to the user about combining `nil` with a string.
    # Thus if we do get here and `path_to_env` is empty, just assume it's the
    # default production environment and continue.
    #
    # This should hopefully match puppet's behavior for the default 'production'
    # environment: _technically_ that environment always exists, but if the dir
    # isn't there it won't find the module and fail with "plan not found" rather
    # than "environment doesn't exist"
    if path_to_env
      bolt_yaml = File.join(environment.configuration.path_to_env, 'bolt.yaml')
      modulepath_setting_from_bolt = Bolt::Util.read_optional_yaml_hash(bolt_yaml, 'config')['modulepath']
    end

    # If we loaded a bolt.yaml in the environment root and it contained a modulepath setting:
    # we will use that modulepath rather than the one loaded through puppet. modulepath will
    # be the _only_ setting that will work from bolt.yaml in plans in PE.
    if modulepath_setting_from_bolt
      modulepath_setting_from_bolt.split(File::PATH_SEPARATOR).each do |path|
        if Pathname.new(path).absolute? && File.exist?(path)
          modulepath_dirs << path
        elsif File.exist?(File.join(path_to_env, path))
          modulepath_dirs << File.join(path_to_env, path)
        end
      end

      # Append the basemodulepath to include "built-in" modules.
      modulepath_dirs.concat(basemodulepath.split(File::PATH_SEPARATOR))
    else
      modulepath_dirs = environment.modulepath
    end

    # A new modulepath is created from scratch (rather than using super's @modulepath)
    # so that we can have full control over all the entries in modulepath. In the future
    # it's likely we will need to preceed _both_ Bolt::PAL::BOLTLIB_PATH _and_
    # Bolt::PAL::MODULES_PATH which would be more complex if we tried to use @modulepath since
    # we need to append our modulepaths and exclude modules shiped in bolt gem code
    @original_modulepath = modulepath_dirs
    @modulepath = [PE_BOLTLIB_PATH, Bolt::PAL::BOLTLIB_PATH, *modulepath_dirs]
  end
end

Instance Method Details

#with_pe_pal_init_settings(codedir, environmentpath, basemodulepath) ⇒ Object

This function is nearly identical to Bolt::Pal’s ‘with_puppet_settings` with the one difference that we set the codedir to point to actual code, rather than the tmpdir. We only use this funtion inside the PEBolt::PAL initializer so that Puppet is correctly configured to pull environment configuration correctly. If we don’t set codedir in this way: when we try to load and interpolate the modulepath it won’t correctly load.



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/bolt_server/pe/pal.rb', line 26

def with_pe_pal_init_settings(codedir, environmentpath, basemodulepath)
  Dir.mktmpdir('pe-bolt') do |dir|
    cli = []
    Puppet::Settings::REQUIRED_APP_SETTINGS.each do |setting|
      dir = setting == :codedir ? codedir : dir
      cli << "--#{setting}" << dir
    end
    cli << "--environmentpath" << environmentpath
    cli << "--basemodulepath" << basemodulepath
    Puppet.settings.send(:clear_everything_for_tests)
    Puppet.initialize_settings(cli)
    yield
    # Ensure the puppet settings go back to what bolt expects after
    # we finish with the settings we need for PEBolt::PAL init.
    with_puppet_settings { |_| nil }
  end
end