Class: PDK::Config

Inherits:
Object
  • Object
show all
Defined in:
lib/pdk/config.rb,
lib/pdk/config/json.rb,
lib/pdk/config/yaml.rb,
lib/pdk/config/errors.rb,
lib/pdk/config/setting.rb,
lib/pdk/config/ini_file.rb,
lib/pdk/config/namespace.rb,
lib/pdk/config/validator.rb,
lib/pdk/config/ini_file_setting.rb,
lib/pdk/config/json_with_schema.rb,
lib/pdk/config/yaml_with_schema.rb,
lib/pdk/config/json_schema_setting.rb,
lib/pdk/config/json_schema_namespace.rb

Defined Under Namespace

Modules: Validator Classes: IniFile, IniFileSetting, JSON, JSONSchemaNamespace, JSONSchemaSetting, JSONWithSchema, LoadError, Namespace, Setting, YAML, YAMLWithSchema

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = nil) ⇒ Config

Create a new instance of the PDK Configuration

Parameters:

  • options (Hash[String => Object]) (defaults to: nil)

    Optional hash to override configuration options

Options Hash (options):

  • 'system.path' (String)

    Path to the system PDK configuration file

  • 'system.module_defaults.path' (String)

    Path to the system module answers PDK configuration file

  • 'user.path' (String)

    Path to the user PDK configuration file

  • 'user.module_defaults.path' (String)

    Path to the user module answers PDK configuration file

  • 'user.analytics.path' (String)

    Path to the user analytics PDK configuration file

  • 'context' (PDK::Context::AbstractContext)

    The context that the configuration should be created in



24
25
26
27
28
29
30
31
32
33
34
# File 'lib/pdk/config.rb', line 24

def initialize(options = nil)
  options = {} if options.nil?
  @config_options = {
    'system.path'                 => PDK::Config.system_config_path,
    'system.module_defaults.path' => PDK::Config.system_answers_path,
    'user.path'                   => PDK::Config.user_config_path,
    'user.module_defaults.path'   => PDK::AnswerFile.default_answer_file_path,
    'user.analytics.path'         => PDK::Config.analytics_config_path,
    'context'                     => PDK.context,
  }.merge(options)
end

Class Method Details

.analytics_config_exist?Boolean

Returns:

  • (Boolean)


208
209
210
# File 'lib/pdk/config.rb', line 208

def self.analytics_config_exist?
  PDK::Util::Filesystem.file?(analytics_config_path)
end

.analytics_config_interview!Object



212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
# File 'lib/pdk/config.rb', line 212

def self.analytics_config_interview!
  require 'pdk/cli/util'

  return unless PDK::CLI::Util.interactive?

  pre_message = _(
    'PDK collects anonymous usage information to help us understand how ' \
    'it is being used and make decisions on how to improve it. You can ' \
    'find out more about what data we collect and how it is used in the ' \
    "PDK documentation at %{url}.\n",
  ) % { url: 'https://puppet.com/docs/pdk/latest/pdk_install.html' }
  post_message = _(
    'You can opt in or out of the usage data collection at any time by ' \
    'editing the analytics configuration file at %{path} and changing ' \
    "the '%{key}' value.",
  ) % {
    path: PDK::Config.analytics_config_path,
    key:  'disabled',
  }

  questions = [
    {
      name:     'enabled',
      question: _('Do you consent to the collection of anonymous PDK usage information?'),
      type:     :yes,
    },
  ]

  require 'pdk/cli/util/interview'

  PDK.logger.info(text: pre_message, wrap: true)
  prompt = TTY::Prompt.new(help_color: :cyan)
  interview = PDK::CLI::Util::Interview.new(prompt)
  interview.add_questions(questions)
  answers = interview.run

  if answers.nil?
    PDK.logger.info _('No answer given, opting out of analytics collection.')
    PDK.config.user['analytics']['disabled'] = true
  else
    PDK.config.user['analytics']['disabled'] = !answers['enabled']
  end

  PDK.logger.info(text: post_message, wrap: true)
end

.analytics_config_pathObject



183
184
185
# File 'lib/pdk/config.rb', line 183

def self.analytics_config_path
  PDK::Util::Env['PDK_ANALYTICS_CONFIG'] || File.join(File.dirname(PDK::Util.configdir), 'puppet', 'analytics.yml')
end

.bolt_analytics_configObject



172
173
174
175
176
177
178
179
180
181
# File 'lib/pdk/config.rb', line 172

def self.bolt_analytics_config
  file = PDK::Util::Filesystem.expand_path('~/.puppetlabs/bolt/analytics.yaml')
  PDK::Config::YAML.new(file: file)
rescue PDK::Config::LoadError => e
  PDK.logger.debug _('Unable to load %{file}: %{message}') % {
    file:    file,
    message: e.message,
  }
  PDK::Config::YAML.new
end

.json_schema(name) ⇒ Object

return nil if not exist



204
205
206
# File 'lib/pdk/config.rb', line 204

def self.json_schema(name)
  File.join(json_schemas_path, name + '_schema.json')
end

.json_schemas_pathObject



199
200
201
# File 'lib/pdk/config.rb', line 199

def self.json_schemas_path
  File.join(__dir__, 'config')
end

.system_answers_pathObject



195
196
197
# File 'lib/pdk/config.rb', line 195

def self.system_answers_path
  File.join(PDK::Util.system_configdir, 'answers.json')
end

.system_config_pathObject



191
192
193
# File 'lib/pdk/config.rb', line 191

def self.system_config_path
  File.join(PDK::Util.system_configdir, 'system_config.json')
end

.user_config_pathObject



187
188
189
# File 'lib/pdk/config.rb', line 187

def self.user_config_path
  File.join(PDK::Util.configdir, 'user_config.json')
end

Instance Method Details

#get(root, *keys) ⇒ PDK::Config::Namespace, ...

Returns a configuration setting by name. This name can either be a String, Array or parameters e.g. These are equivalent

  • PDK.config.get(‘user.a.b.c’)

  • PDK.config.get([‘user’, ‘a’, ‘b’, ‘c’])

  • PDK.config.get(‘user’, ‘a’, ‘b’, ‘c’)

Returns:

  • (PDK::Config::Namespace, Object, nil)

    The value of the configuration setting. Returns nil if it does no exist



123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/pdk/config.rb', line 123

def get(root, *keys)
  return nil if root.nil? || root.empty?

  if keys.empty?
    if root.is_a?(Array)
      name = root
    elsif root.is_a?(String)
      name = split_key_string(root)
    else
      return nil
    end
  else
    name = [root].concat(keys)
  end

  get_within_scopes(name[1..-1], [name[0]])
end

#get_within_scopes(setting_name, scopes = nil) ⇒ PDK::Config::Namespace, ...

Returns a configuration setting by name, using scope precedence rules. If no scopes are passed, then all scopes are queried using the default precedence rules

Returns:

  • (PDK::Config::Namespace, Object, nil)

    The value of the configuration setting. Returns nil if it does no exist

Raises:

  • (ArgumentError)


145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/pdk/config.rb', line 145

def get_within_scopes(setting_name, scopes = nil)
  raise ArgumentError, _('Expected an Array but got \'%{klass}\' for scopes') % { klass: scopes.class } unless scopes.nil? || scopes.is_a?(Array)
  raise ArgumentError, _('Expected an Array or String but got \'%{klass}\' for setting_name') % { klass: setting_name.class } unless setting_name.is_a?(Array) || setting_name.is_a?(String)

  setting_arr = setting_name.is_a?(String) ? split_key_string(setting_name) : setting_name
  all_scope_names = all_scopes.keys

  # Use only valid scope names
  scopes = scopes.nil? ? all_scope_names : scopes & all_scope_names

  scopes.each do |scope_name|
    value = traverse_object(send(all_scopes[scope_name]), *setting_arr)
    return value unless value.nil?
  end
  nil
end

#project_configPDK::Config::Namespace

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

The project level configuration settings.



99
100
101
102
103
104
105
106
# File 'lib/pdk/config.rb', line 99

def project_config
  context = @config_options['context']
  @project ||= PDK::Config::Namespace.new('project') do
    if context.is_a?(PDK::Context::ControlRepo)
      mount :environment, PDK::ControlRepo.environment_conf_as_config(File.join(context.root_path, 'environment.conf'))
    end
  end
end

#resolve(filter = nil) ⇒ Hash{String => Object}

Resolves all filtered settings from all namespaces

Parameters:

  • filter (String) (defaults to: nil)

    Only resolve setting names which match the filter. See PDK::Config::Namespace.be_resolved? for matching rules

Returns:

  • (Hash{String => Object})

    All resolved settings for example => ‘johndoe’



112
113
114
115
116
# File 'lib/pdk/config.rb', line 112

def resolve(filter = nil)
  all_scopes.values.reverse.reduce({}) do |result, method_name|
    result.merge(send(method_name).resolve(filter))
  end
end

#system_configPDK::Config::Namespace

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

The system level configuration settings.



47
48
49
50
51
52
# File 'lib/pdk/config.rb', line 47

def system_config
  local_options = @config_options
  @system ||= PDK::Config::JSON.new('system', file: local_options['system.path']) do
    mount :module_defaults, PDK::Config::JSON.new(file: local_options['system.module_defaults.path'])
  end
end

#userPDK::Config::Namespace

Deprecated.

This method is only provided as a courtesy until the ‘pdk set config` CLI and associated changes in this class, are completed. Any read-only operations should be using `.get` or `.get_within_scopes`

The user configuration settings.



40
41
42
# File 'lib/pdk/config.rb', line 40

def user
  user_config
end

#user_configPDK::Config::Namespace

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

The user level configuration settings.



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
# File 'lib/pdk/config.rb', line 57

def user_config
  local_options = @config_options
  @user ||= PDK::Config::JSON.new('user', file: local_options['user.path']) do
    mount :module_defaults, PDK::Config::JSON.new(file: local_options['user.module_defaults.path'])

    # Due to the json-schema gem having issues with Windows based paths, and only supporting Draft 05 (or less) do
    # not use JSON validation yet.  Once PDK drops support for EOL rubies, we will be able to use the json_schemer gem
    # Which has much more modern support
    # Reference - https://github.com/puppetlabs/pdk/pull/777
    # Reference - https://tickets.puppetlabs.com/browse/PDK-1526
    mount :analytics, PDK::Config::YAML.new(file: local_options['user.analytics.path'], persistent_defaults: true) do
      setting :disabled do
        validate PDK::Config::Validator.boolean
        default_to { PDK::Config.bolt_analytics_config.fetch('disabled', true) }
      end

      setting 'user-id' do
        validate PDK::Config::Validator.uuid
        default_to do
          require 'securerandom'

          PDK::Config.bolt_analytics_config.fetch('user-id', SecureRandom.uuid)
        end
      end
    end

    # Display the feature flags
    mount :pdk_feature_flags, PDK::Config::Namespace.new('pdk_feature_flags') do
      setting 'available' do
        default_to { PDK.available_feature_flags }
      end

      setting 'requested' do
        default_to { PDK.requested_feature_flags }
      end
    end
  end
end

#with_scoped_value(setting_name, scopes = nil) {|PDK::Config::Namespace, Object| ... } ⇒ Object

Yields a configuration setting value by name, using scope precedence rules. If no scopes are passed, then all scopes are queried using the default precedence rules

Yields:

  • (PDK::Config::Namespace, Object)

    The value of the configuration setting. Does not yield if the setting does not exist or is nil

Raises:

  • (ArgumentError)


166
167
168
169
170
# File 'lib/pdk/config.rb', line 166

def with_scoped_value(setting_name, scopes = nil)
  raise ArgumentError, _('must be passed a block') unless block_given?
  value = get_within_scopes(setting_name, scopes)
  yield value unless value.nil?
end