File Coverage

blib/lib/Advanced/Config/Examples.pm
Criterion Covered Total %
statement 15 15 100.0
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 20 20 100.0


line stmt bran cond sub pod time code
1             ###
2             ### Copyright (c) 2015 - 2026 Curtis Leach. All rights reserved.
3             ###
4             ### Module: Advanced::Config::Examples
5              
6             package Advanced::Config::Examples;
7              
8 1     1   141223 use strict;
  1         1  
  1         30  
9 1     1   3 use warnings;
  1         1  
  1         39  
10              
11 1     1   4 use vars qw ( @ISA @EXPORT @EXPORT_OK $VERSION );
  1         1  
  1         40  
12 1     1   3 use Exporter;
  1         1  
  1         46  
13              
14 1     1   4 use Fred::Fish::DBUG 2.09 qw / on_if_set ADVANCED_CONFIG_FISH /;
  1         14  
  1         6  
15              
16             $VERSION = "1.14";
17             @ISA = qw ( Exporter );
18             @EXPORT = qw ();
19             @EXPORT_OK = qw ();
20              
21              
22             # Required if module is included w/ require command;
23             1;
24              
25             # =============================================================================
26             # Only POD text appears below this line!
27             # =============================================================================
28              
29             =head1 NAME
30              
31             Advanced::Config::Examples - Defines sample config files supported by this
32             module. Sourcing this module in does nothing for you.
33              
34             =head1 SYNOPSIS
35              
36             In many cases it's just easier to show an example instead of trying
37             to put things into words. So this module is just some POD text to document
38             what this module is expecting to load into memory as your config file.
39              
40             Just be aware that it's possible to override many of the operators defined in
41             the config file. So for example the B<=> operator could be B<:=> and the
42             B<#> operator could have been B.
43              
44             =head1 HISTORY
45              
46             This module started out as a parser of unix shell script data files so that
47             shell scripts and perl programs could share the same config files. Hence the
48             support of shell script variables, quotes and the sourcing in of sub-files.
49             Allowing for limited logic in your config files.
50              
51             From there it just grew to support non-unix features such as windows batch
52             files and more generic configuration features. Such as being able handle
53             various formatting of config files and the ability to obscure or encrypt values
54             from casual snooping. Or the addition of sections to allow the same config
55             file to be used on multiple servers and OS.
56              
57             So today it's a powerful tool that turns your config files into objects your
58             perl code can reference and manipulate.
59              
60             =head1 SURROUNDING A VALUE WITH QUOTES IN YOUR CONFIG FILE
61              
62             If you surround a value with balanced quotes, those quotes are automatically
63             removed before that value is assigned to it's tag. Quotes are supported mostly
64             for readability and as a way to allow comment symbols in your value. Or a way
65             to force leading and trailing spaces to your value. Where without quotes those
66             spaces are stripped off.
67              
68             =head1 VARIABLE SUBSTITUTIONS
69              
70             All config files support variable substitution. A variable can be any B
71             that appears above it in the config file. If not defined there, it will check
72             if it's defined as an environment variable in the B<%ENV> hash instead. If
73             still not found it will check for several predefined special variables for this
74             module. If it can't find a variable it's value is always the empty string.
75              
76             By default variables are in the format of B<${>...B<}>. Where ... is your
77             variable's name and the B<${> & B<}> strings are the default surrounding anchors
78             that define it as a variable.
79              
80             For more on this see the following link on Parameter Expansion:
81             L
82             This module supports most of the parameter expansions listed in the link except
83             for those dealing with arrays. Other modifier rules may be added upon request.
84              
85             Things get a bit more complex evaluating variables if you've defined sections
86             in your config file.
87              
88             See the POD for B() in L for step by step
89             instructions on expanding a variable's name.
90              
91             For a list of special variables try calling:
92             Sprint_special_vars();>
93              
94             =head1 SOURCING IN OTHER CONFIG FILES
95              
96             It's possible to source multiple config files together as if they were one big
97             config file. You can either use absolute paths to each config file, or more
98             likely relative paths.
99              
100             Sourcing in sub-config files using relative paths works a little different than
101             you might expect. It's the relative path from the location of the config file
102             doing the sourcing, not the current directory your program is running in.
103              
104             This way the writer of the config file, not the programmer, controls which
105             config file gets sourced in. Of course the config file writer can give control
106             back to the programmer by using variables as part of the name of the config
107             file being sourced in.
108              
109             If recursion is detected, this module silently refuses to reload the problem
110             config file and breaks the recursion. But you have the option of treating it
111             as a fatal error instead. Recursion is detected even if you source in a
112             symbolic link back to the original file.
113              
114             It is always a fatal error if the requested config file doesn't exist!
115              
116             =head1 CONTROLLING THE PARSING OF YOUR CONFIG FILES
117              
118             See I section of L for what options
119             are available for customizing how your configuration files gets parsed.
120              
121             While I section covers options for looking up the value for
122             a given tag generated.
123              
124             =head1 ENCRYPTING VALUES IN YOUR CONFIG FILE
125              
126             This module has hooks to allow the encryption/decryption of values in your
127             config file. It can do it in two levels. Simple obscuring of the tag's value
128             or true encryption/decryption. See L for more
129             details on how to do this.
130              
131             =head1 CONFIG FILE EXAMPLES
132              
133             =over 4
134              
135             =item A VERY SIMPLE CONFIG FILE. (simple.cfg)
136              
137             # This is a comment
138              
139             tag1 = abc # A simple assignment.
140              
141             # The balanced quotes will automatically be removed from the value ...
142             tag2="efg" # See we put surrounding quotes around the value.
143              
144             tag3 = 'l m n' # The alternate quotes.
145              
146             tag4 = p q r # See quotes are completely optional.
147              
148             tag5 = ${tag1} # Performs variable substitution, same as: tag5 = "abc".
149              
150             tag1 = xyz # See I've overridden tag1's original value to "xyz".
151             TAG1 = 123 # tag1 is still xyz, tags are case sensitive.
152              
153             To load it into memory do:
154              
155             my $cfg = Advanced::config->new ("simple.cfg")->load_config();
156              
157             =item A SLIGHTLY MORE COMPLEX CONFIG FILE. (complex.cfg)
158              
159             # Merge in this config file. Looks in the same directory as
160             # this config file is in. Not the program's current directory.
161             . simple.cfg
162              
163             # Sourcing in another config file. (contents not shown)
164             # Offset is from the same directory this config file is in.
165             # Not the program's current directory!
166             . ../Alt-Config/relative.cfg
167              
168             # See I'm referencing variables defined in simple.cfg!
169             tag1 = ${tag1} ${tag3} ${tag1} # tag1 now equals: "xyz l m n xyz".
170              
171             tag 6 = abc = 7 # "tag 6" now contains: "abc = 7".
172             tag 6 = ${TAG1} # "tag 6" is now: 123
173              
174             messy = "I have a # in my value" # See comment symbol in the value.
175              
176             # A neat little trick ...
177             # Implements: a = $ENV{test} ? "TRUE" : "FALSE";
178             a = ${test:+TRUE} # Set to TRUE if $ENV{test} is set, else undef
179             a = ${a:-FALSE} # Set to FALSE if ${a} is undef, else set to ${a}.
180              
181             # Does variables within variables ...
182             # Implements: b = $ENV{test} ? $y : $z;
183             y = YES
184             z = NO
185             b = ${test:+${y}} # Set to ${y} if $ENV{test} is set, else undef
186             b = ${b:-${z}} # Set to ${z} if ${b} is undef, else set to ${b}.
187              
188             # So (a,b) = (TRUE,YES) or (FALSE,NO).
189              
190             # How about testing for a specific value for $ENV{test}? This can be
191             # done in a limited way.
192             message_abc = I know my abc's.
193             message_123 = I know my 123's
194             message_hello = Hello World!
195             msg = ${message_${test}:-Unknown Message.}
196              
197             # So if test is "abc", "123" or "hello" it will use the appropriate
198             # value for tag msg. Otherwise it will be "Unknown Message.".
199              
200             # This shows that you can put some logic in your config files so that
201             # your config files can be shared across platforms without having
202             # to have multiple versions of that config file or add complex platform
203             # specific logic into your perl code.
204              
205             To load it into memory do:
206              
207             my $cfg = Advanced::config->new ("complex.cfg")->load_config();
208              
209             =item BREAKING YOUR CONFIG FILE INTO SECTIONS (section.cfg)
210              
211             abc = lmn # Has no section, so considered in section "main".
212             user = me
213             pwd = nope!
214              
215             [ host 1 ]
216             abc = xyz
217             pwd = password1
218              
219             [host 2]
220             abc=abc
221             pwd = password2
222              
223             [ HOST 3 ]
224             abc = 123
225             pwd = password3
226              
227             [ HOST 2 ]
228             efg = repeat # Section "host 2" has 3 tags in it. "abc", "efg" & "pwd".
229              
230             [ Host 4 ]
231             user = you
232              
233             Please note that section names are case insensitive and the tag abc's value
234             depends on what section of the config file you are currently looking at. This
235             way you may repeat tags between sections and know that each section is
236             independent of each other. As if each section was in its own config file.
237              
238             Or you can interpret each section as overrides to tags in the main section
239             using the B option. Where if a tag isn't defined in the current
240             section, it then looks in the main section for it. Say you're on host 1 and
241             you want to log into your application. You need both a user & pwd pair to do
242             this. When you look up the pwd, you find it in host 1, but when you try to
243             look up the user, it can't find it in the current section, so it looks in the
244             main section for it instead. In effect all 4 sections have all variables from
245             main included in each section. With the local tags overriding what's in main.
246             A neat way to handle minor differences that would otherwise require you to
247             have multiple config files you'd need to keep in sync.
248              
249             To load it into memory do:
250              
251             my $cfg = Advanced::config->new ("section.cfg")->load_config();
252             or
253             my $cfg = Advanced::config->new ("section.cfg", {inherit => 1})->load_config();
254              
255             =item SOURCING IN FILES WITH SECTIONS (src_sect.cfg)
256              
257             By default, when sourcing in another config file it's default section is
258             also called "B
". This is true even when you are sourcing in a file
259             inside a named section block. That name isn't inherited by default.
260              
261             And if that config file also uses sections, those section names are preserved.
262              
263             But sometimes you'd like to source in a sub-file as if any tag appearing
264             outside a section was defined in the original file's current section. In
265             that case follow the file name with the appropriate label. Which by default
266             is B.
267              
268             . simple.cfg # All variables appear in the main section.
269              
270             [ section 1 ]
271             . simple.cfg # All variables appear in the main section as well.
272              
273             [ section 2 ]
274             . simple.cfg # DEFAULT - all variables from this config file will appear as members of "section 2".
275              
276             [ section 3 ]
277             . section.cfg # DEFAULT - tags abc, user & pwd are now in 'section 3', while everything else stays in it's defined section.
278              
279             To load it into memory do:
280              
281             my $cfg = Advanced::config->new ("src_sect.cfg")->load_config();
282              
283             =item USING STRANGE LOOKING CONFIG FILES (product-1.cfg)
284              
285             Sometimes you want to look at a config file owned by another product that
286             doesn't follow the formatting expected by this module by default. So this
287             module allows you a way to provide new rules for parsing a config file to
288             make these differences irrelevant.
289              
290             Lets assume this config file used ";", not "#" as the comment char, "::", not
291             "=" as it's assignment operator, and finally used "include", not "." when
292             sourcing in another config file. So you'd get something like the following:
293              
294             ; This is a comment ...
295             include product-2.cfg
296              
297             abc :: xyz ; Tag "abc" now equals "xyz"!
298              
299             The possibilities are practically endless! You can even write your own wrapper
300             config file and use the "source_cb" callback option to redefine the parsing
301             rules for a particular config file being sourced in if the parsing rules
302             are different!
303              
304             In fact, one of the test cases does just this! (t/30-alt_symbols_cfg.t)
305              
306             To load it into memory do:
307              
308             my $cfg = Advanced::config->new ("product-1.cfg",
309             { "assign => "::", "comment" => ";", "source" => "include" }
310             )->load_config();
311              
312              
313             =item ENCRYPTING/DECRYPTING CONFIG FILES
314              
315             Sometimes you need to protect sensitive information inside your config files.
316             Such as the user names and passwords that your application requires to run.
317             This module allows this at the individual tag/value pair level. Not at the
318             file level!
319              
320             The 1st example shows tags whose values are pending the encryption process.
321             While the 2nd example shows what happens after it's been encrypted. You can
322             have config files that have both pending and encrypted tags in it. As well
323             as tags whose values are never encrypted. It is controlled by having the
324             appropriate label in the comment after the tag/value pair.
325              
326             # Waiting to encrypt these values ...
327             my_username_1 = "anonymous" # ENCRYPT
328             my_password_1 = "This is too much fun!" # ENCRYPT me ...
329              
330             # They've already been encrypted!
331             my_username_2 = '4aka54D3eZ4aea5' # DECRYPT
332             my_password_2 = '^M^Mn1\pmeaq>n\q?Z[x537z3A' # DECRYPT me ...
333              
334             # This value will never be encrypted/decrypted ...
335             dummy = "Just some strange value that is always in clear text."
336              
337             The encrypted value is automatically decrypted for you when the config file
338             is loaded into memory. So it's already in clear text when C is
339             called. See L for more details on the options
340             used to control the encrypt/decrypt process. See C in
341             L for how to encrypt the contents of the config file itself.
342              
343             You can use C to reverse the process if needed.
344              
345             =item PLUS MUCH, MUCH, MORE ...
346              
347             I could go on and on with many more examples. I'll add more in the future as
348             I consider more significant issues to cover. In the mean time you can find
349             many more examples from the build under: I
350              
351             =back
352              
353             =head1 COPYRIGHT
354              
355             Copyright (c) 2015 - 2026 Curtis Leach. All rights reserved.
356              
357             This program is free software. You can redistribute it and/or modify it under
358             the same terms as Perl itself.
359              
360             =head1 SEE ALSO
361              
362             L - Covers the options that allow you to modify
363             how a config file gets parsed. It defines the controls allowing the various
364             examples shown above.
365              
366             L - Handles date parsing for get_date().
367              
368             L - Handles the parsing of the config file per the
369             options defined above.
370              
371             L - Defines the configuration object that you wish to
372             manipulate.
373              
374             =cut
375