Perl: overriding command line configuration file settings?

I create a script that uses the configuration file (YAML) to read all the necessary configuration information, then prints out all the necessary steps that the Linux administrator must take to create the server.

It is required that the Linux administrator on which the script is running can override any of the item / value pairs from the configuration file on the command line.

The way I handle it now seems too cumbersome, and I know that for this you need to be in a more innovative and less awkward way.


In code I:

  • Parse the YAML configuration file using YAML :: Tiny

    location: continent: na country: us city: rh 
  • Create variables with the same names as the elements of the configuration file by assigning values ​​from the configuration file.

     my $yaml = YAML::Tiny->new; $yaml = YAML::Tiny->read($config_yml); my $continent = $yaml->[0]->{location}->{continent}; my $country = $yaml->[0]->{location}->{country}; my $city = $yaml->[0]->{location}->{city}; 
  • Use Getopt :: Long and assign variables, overriding everything that was passed on the command line.

     GetOptions ( "city=s" => \$city, "continent=s" => \$continent, "country=s" => \$country, ); 

So this is just 3 pairs of item / values, my actual configuration is over 40 and will change ... This makes me work a bit to keep updating. Any suggestions?

+4
source share
3 answers

You can let the administrator override the YAML settings with one flexible switch, similar to ssh(1) working with -o . This is especially useful if configuration options are numerous and subject to change.

 $ myscript -o location:city=rh --option location:country=us 

Now, inside the script, you can save the entire runtime configuration, combined into a hash for convenience (instead of having the scalars grow over $this_and_that_opt over time). Then, parsing the parameters would look something like this:

 # First, set up %GlobalAppCfg from defaults and YAML # now handle "-o location:country=us" GetOptions('option|o=s' => sub { my (undef, $optstring) = @_; my ($userkey, $val) = split('=', $optstring, 2); my ($major, $minor) = split(':', $userkey, 2); $GlobalAppCfg->{$major}->{$minor} = $val; }, ...); 

or whatever. You can normalize keys and configuration values, process arbitrarily deep keys / subsections / subsections, etc. This can become slippery, so you may need to key-lock this global hash.

+3
source

Take a look at some of the Config modules that marry GetOpt and YAML, possibly Config :: YAML or Config :: YAML :: Tiny

+2
source

Only a sketch, but

  • In your GetOptions call, could you use "deep links" in the YAML structure, thereby getting rid of the "intermediate" variables?

  • By looking at the created YAML structure, could you automatically generate a GetOptions call (based on what variables you actually see in YAML). Having generated, I mean, create the call as a string, and then use "eval" to actually execute it.

  • If you need "intermediate variables" for convenience, you can probably generate them yourself from the YAML structure, just like a string, and then use "eval" to create the variables.

As I said, just a sketch.

+1
source

Source: https://habr.com/ru/post/1386775/


All Articles