Config-Resolver

 view release on metacpan or  search on metacpan

bin/config-resolver.pl  view on Meta::CPAN


=item -g,  --debug

Logs debug messages to STDERR.

=item -k, --key

A key to dump from the parameters file.

=item -P, --pretty

Pretty print JSON output.

default: false

=item -m, --manifest

Specifies a manifest file (YAML or JSON) for batch-processing multiple
templates in a single run.

See L</BATCH PROCESSING USING A MANIFEST FILE>

=item -o, --outfile

Name of the output file to create.  If not present, output is sent to STDOUT.

default: STDOUT

=item -O, --output-dir

The target directory for writing output files.

**Required** when C<--template> is a directory.

=item -p, -- parameter-file

A JSON or YAML file that contains the parameters used for
interpolation.

The parameter file is used to populate the template.  Parameters
I<values> should be constants or special values of the form:

 xxx://key-path

...where "xxx" represents the protocol prefix for a plugin
(e.g. ssm:// for retrieving values from thhe AWS SSM Parameter Store
API).

default: none

=item --plugins

A comma delimited list of plugin names. See L</PLUGINS>

=item --plugin xxx:key=value

This is the mechanism you use to pass options to your plugins.

Example:

 --plugin ssm:endpoint_url=http://localhost:4566

=item -V, --parameters

You can supply key/value pairs at the command line to do simple
templating operations.

 echo 'foo=${foo}' | config-resolver -V 'foo=bar&bar=buz'

=item -r, --resolve

Resolve the parameters only and print out the resulting JSON.

B<Example:>

 config-resolver -p /etc/tbc-prod.json -r -P

 config-resolover -p /etc/tbc-prod.json --pretty resolve

=item -S, --separator

If you want to dump a hash as a flatten list of key/value pairs use
the C<--format> csv option. This option will set the separator character(s).

default: ' = '

=item -t, --template

Name of the template file **or directory**.

**File Mode:**
If a file is specified, it treats it as a single template.

**Directory Mode:**
If a directory is specified, the script automatically scans it for files ending in
C<.tpl>. It then generates a corresponding output file for each template in the
directory specified by C<--output-dir>.

See L</BATCH PROCESSING USING A MANIFEST FILE> for details.

=item -u, --umask

A umask to use when creating an output file.  The default is the umask
of the current process.  Use 0027 to create a file that can only be read
by the owner and the group that the owner belongs too.  Hence, if run
by root, the output file will only be readable by root.

default: none

=item -w, --warn-level

Determines how errors or missing paramters are handled. See below.

=over 10

=item warn

Continues on errors but outtputs warning error messages when values
cannot be resolved.

=item error

bin/config-resolver.pl  view on Meta::CPAN

  jobs:
    # JOB 1: USES CONVENTION
    # 'template' is not specified, so it is derived:
    # -> /opt/my-app/templates/app.properties.tpl
    - outfile: /etc/my-app/app.properties

    # JOB 2: USES CONVENTION
    # 'template' is derived:
    # -> /opt/my-app/templates/database.ini.tpl
    - outfile: /etc/my-app/database.ini

    # JOB 3: "ONE-OFF" (Overrides Globals)
    # This job overrides 'parameters' and 'template'
    # but still inherits 'umask' from globals.
    - parameters: /etc/my-app/nginx-config.json
      template: /opt/my-app/templates/special/nginx.conf.tpl
      outfile: /etc/nginx/sites-available/my-app.conf

=head1 PLUGINS

Plugins (or "protocol handlers") are the core feature of
C<Config::Resolver>. They allow you to fetch values from external
sources directly from within your templates or parameter files.

The script recognizes special value strings formatted as a URI:

  protocol://path/to/value

For example, to fetch a value from AWS SSM Parameter Store, you would use:

  ${ssm:///path/to/my/secret}

=head2 Built-in Backends

The resolver engine includes two built-in backends that are always
available and do not require any configuration:

=over 4

=item B<env://PATH>

Resolves the value from C<$ENV{PATH}>. This is the recommended
way to inject environment variables.

  ${env://USER}

=item B<file://PATH>

Resolves the value by reading the entire contents of the file at
C<PATH>. This is the recommended way to inject secrets, certificates,
or tokens when more advanced plugins (AWS SSM, AWS Secrets Manager,
etc) are not available.

  ${file:///var/run/secrets/token}

=back

=head2 Plugin Configuration

Many plugins, like C<ssm>, require configuration (e.g., the AWS
region, or a custom endpoint for local testing). You can provide this
configuration in two ways, which are layered:

=head3 1. The RC File (Defaults)

On startup, the script will attempt to load a configuration file from:

  $HOME/.config-resolverrc

This file (in JSON or YAML format) is the perfect place to set your
team- or user-wide defaults.

B<Example C<~/.config-resolverrc>:>

 {
   "ssm": {
     "region": "us-east-1",
     "endpoint_url": "http://localhost:4566"
   },
   "another_plugin": {
     "foo": "bar"
   }
 }

=head3 2. Command-Line Overrides (Specifics)

You can override or provide new settings for any plugin on the command
line using the C<--plugin:*> option. This is the top layer and will
*always* win over the RC file.

The syntax is:

  --plugin PROTOCOL:key=value

You can repeat the C<--plugin> option to build up the configuration.

B<Example:>

  config-resolver.pl \
      --plugin ssm:region=us-west-2 \
      --plugin ssm:endpoint_url=http://localhost:4566 \
      -t my-template.tpl

The script merges these two sources, giving command-line options final
priority, and passes the result to the resolver engine.

=head2 Plugin "Setup-Only" Execution Mode

This script does not have a default command (like C<resolve> or C<dump>).
This intentional design enables a powerful "init-only" workflow for plugins
that need to perform on-demand setup or initialization tasks.

If you run C<config-resolver.pl> *without* a command, it will:

=over 4

=item Execute its full initialization phase (parsing all CLI args,
loading plugins, and running their C<new()> or C<init()> methods).

=item Proceed to the C<run()> phase, find no command, and exit cleanly.

=back

This allows you to add features to your plugin's C<init()> method
that are triggered by a specific CLI flag. This is the recommended
pattern for tasks like seeding a local datastore (e.g., LocalStack) or
performing a one-time authentication.

=head3 Recipe for a Plugin "Init-Task"

Follow this 3-step recipe to add an on-demand setup task to your
plugin.

=over 4

=item 1. Define Configuration Keys

In your plugin's documentation, define the keys a user must set in
their C<.config-resolverrc> file .

  # In .config-resolverrc
  [plugin ssm]
    endpoint_url = http://localhost:4566
    
    # --- Keys for your one-time setup ---
    seed_file = /opt/my-app/localstack-seed.json
    load_on_init = false # <-- Default to false!

=item 2. Add Logic to Your Plugin's C<new()>

In your plugin's C<new()> constructor, check for your flag.

  # In lib/Config/Resolver/Plugin/SSM.pm
  sub new {
      my ($class, $options) = @_;
      my $self = $class->SUPER::new($options);

      # --- This is the "on-demand" hook ---
      if ( my $seed_file = $self->get_load_on_init ) {
          print {*STDERR} "Seeding SSM from $seed_file...\n";
          $self->load_data_from_file( $seed_file );
      }
      # --- End of hook ---

      return $self;
  }

=item 3. Document the User's Command

Finally, document the command the user must run. Because the CLI 
flag trumps the config file , this single command
will trigger your logic:

  # Triggers the one-time setup:
  $ config-resolver.pl --plugins SSM --plugin ssm:load_on_init=true

B<How This Works:> The script runs, but no command (like C<resolve>)
is given. The C<init()> phase runs, loading your plugin. The
C<--plugin> flag overrides the config file, setting C<load_on_init> to
true. Your C<new()> method fires, sees the flag, and runs your setup
logic. The script then exits cleanly because no command was specified.

=back

This workflow is fully compatible with STDIN. If your plugin's C<init()>
task reads from STDIN (e.g., C<ssm:load=-_>), C<config-resolver.pl> will
politely detect that the STDIN stream has already been consumed and
will not attempt to read from it again.

=head1 AUTHOR

Rob Lauer - <rclauer@gmail.com>

=head1 SEE ALSO 

L<Config::Resolver>, L<Config::Resolver::Plugin::SSM>, L<Config::Resolver::Plugin::SecretsManager>



( run in 3.103 seconds using v1.01-cache-2.11-cpan-df04353d9ac )