File Coverage

blib/lib/Config/Model/Backend/Yaml.pm
Criterion Covered Total %
statement 75 80 93.7
branch 6 10 60.0
condition 7 10 70.0
subroutine 21 21 100.0
pod 2 3 66.6
total 111 124 89.5


line stmt bran cond sub pod time code
1             #
2             # This file is part of Config-Model-Backend-Yaml
3             #
4             # This software is Copyright (c) 2018 by Dominique Dumont.
5             #
6             # This is free software, licensed under:
7             #
8             # The GNU Lesser General Public License, Version 2.1, February 1999
9             #
10             package Config::Model::Backend::Yaml;
11             $Config::Model::Backend::Yaml::VERSION = '2.134';
12 2     2   129175 use 5.10.1;
  2         7  
13 2     2   13 use Carp;
  2         5  
  2         146  
14 2     2   14 use strict;
  2         8  
  2         45  
15 2     2   9 use warnings;
  2         4  
  2         87  
16 2     2   13 use Config::Model 2.131;
  2         45  
  2         86  
17 2     2   12 use Config::Model::Exception;
  2         5  
  2         61  
18 2     2   23 use File::Path;
  2         6  
  2         138  
19 2     2   13 use Log::Log4perl qw(get_logger :levels);
  2         4  
  2         20  
20 2     2   1384 use boolean;
  2         2467  
  2         11  
21 2     2   1151 use YAML::XS 0.69;
  2         6083  
  2         246  
22              
23 2     2   22 use base qw/Config::Model::Backend::Any/;
  2         5  
  2         1277  
24              
25             my $logger = get_logger("Backend::Yaml");
26              
27             sub single_element {
28 17     17 0 27 my $self = shift;
29              
30 17         113 my @elts = $self->node->children;
31 17 100       49050 return if @elts != 1;
32              
33 9         50 my $obj = $self->node->fetch_element($elts[0]);
34 9         573 my $type = $obj->get_type;
35 9 50       113 return $type =~ /^(list|hash)$/ ? $obj : undef ;
36             }
37              
38             sub read {
39 11     11 1 108223 my $self = shift;
40 11         104 my %args = @_;
41              
42 11         33 local $YAML::XS::LoadBlessed = 0;
43              
44             # args is:
45             # object => $obj, # Config::Model::Node object
46             # root => './my_test', # fake root directory, userd for tests
47             # config_dir => /etc/foo', # absolute path
48             # file => 'foo.conf', # file name
49             # file_path => './my_test/etc/foo/foo.conf'
50             # check => yes|no|skip
51              
52 11 100       46 return 0 unless $args{file_path}->exists; # no file to read
53              
54             # load yaml file
55 8         219 my $yaml = $args{file_path}->slurp_raw;
56              
57             # convert to perl data
58 8         1866 my $perl_data = Load($yaml) ;
59 8 50       48 if ( not defined $perl_data ) {
60 0         0 my $msg = "No data found in YAML file $args{file_path}";
61 0 0       0 if ($args{auto_create}) {
62 0         0 $logger->info($msg);
63             }
64             else {
65 0         0 $logger->warn($msg);
66             }
67 0         0 return 1;
68             }
69              
70 8   66     34 my $target = $self->single_element // $self->node ;
71              
72             # load perl data in tree
73 8   50     55 $target->load_data( data => $perl_data, check => $args{check} || 'yes' );
74 8         31991 return 1;
75             }
76              
77             sub write {
78 9     9 1 162466 my $self = shift;
79 9         73 my %args = @_;
80              
81             # args is:
82             # object => $obj, # Config::Model::Node object
83             # root => './my_test', # fake root directory, userd for tests
84             # config_dir => /etc/foo', # absolute path
85             # file => 'foo.conf', # file name
86             # file_path => './my_test/etc/foo/foo.conf'
87             # check => yes|no|skip
88              
89 9         26 local $YAML::XS::Boolean = "boolean";
90              
91 9   66     36 my $target = $self->single_element // $self->node ;
92              
93             my $perl_data = $target->dump_as_data(
94             full_dump => $args{full_dump} // 0,
95 6     6   3351 to_boolean => sub { return boolean($_[0]) }
96 9   100     105 );
97              
98 2     2   17 my $yaml = Dump( $perl_data );
  2     2   4  
  2     2   171  
  2     1   18  
  2     1   5  
  2     1   97  
  2         22  
  2         4  
  2         137  
  1         8  
  1         2  
  1         28  
  1         8  
  1         5  
  1         106  
  1         9  
  1         3  
  1         13  
  9         34800  
99              
100 9         169 $args{file_path}->spew_raw($yaml);
101              
102 9         4488 return 1;
103             }
104              
105             1;
106              
107             # ABSTRACT: Read and write config as a YAML data structure
108              
109             __END__
110              
111             =pod
112              
113             =encoding UTF-8
114              
115             =head1 NAME
116              
117             Config::Model::Backend::Yaml - Read and write config as a YAML data structure
118              
119             =head1 VERSION
120              
121             version 2.134
122              
123             =head1 SYNOPSIS
124              
125             use Config::Model ;
126             use Data::Dumper ;
127              
128             # define configuration tree object
129             my $model = Config::Model->new ;
130             $model ->create_config_class (
131             name => "MyClass",
132             element => [
133             [qw/foo bar/] => {
134             type => 'leaf',
135             value_type => 'string'
136             },
137             baz => {
138             type => 'hash',
139             index_type => 'string' ,
140             cargo => {
141             type => 'leaf',
142             value_type => 'string',
143             },
144             },
145             ],
146             rw_config => {
147             backend => 'yaml',
148             config_dir => '/tmp',
149             file => 'foo.yml',
150             auto_create => 1,
151             }
152             ) ;
153              
154             my $inst = $model->instance(root_class_name => 'MyClass' );
155              
156             my $root = $inst->config_root ;
157              
158             my $steps = 'foo=yada bar="bla bla" baz:en=hello
159             baz:fr=bonjour baz:hr="dobar dan"';
160             $root->load( steps => $steps ) ;
161             $inst->write_back ;
162              
163             Now, C</tmp/foo.yml> contains:
164              
165             ---
166             bar: bla bla
167             baz:
168             en: hello
169             fr: bonjour
170             hr: dobar dan
171             foo: yada
172              
173             =head1 DESCRIPTION
174              
175             This module is used directly by L<Config::Model> to read or write the
176             content of a configuration tree written with YAML syntax in
177             C<Config::Model> configuration tree.
178              
179             Note:
180              
181             =over 4
182              
183             =item *
184              
185             Undefined values are skipped for list element. I.e. if a
186             list element contains C<('a',undef,'b')>, the data structure
187             contains C<'a','b'>.
188              
189             =item *
190              
191             YAML file is not created (and may be deleted) when no data is to be
192             written.
193              
194             =back
195              
196             =head2 Class with only one hash element
197              
198             If the root node contains a single hash or list element, only the
199             content of this hash is written in a YAML file.
200              
201             For example, if a class contains:
202              
203             element => [
204             baz => {
205             type => 'hash',
206             index_type => 'string' ,
207             cargo => {
208             type => 'leaf',
209             value_type => 'string',
210             },
211             },
212              
213             If the configuration is loaded with:
214              
215             $root->load("baz:one=un baz:two=deux")
216              
217             Then the written YAML file does B<not> show C<baz>:
218              
219             ---
220             one: un
221             two: deux
222              
223             Likewise, a YAML file for a class with a single list C<baz> element
224             would be written with:
225              
226             ---
227             - un
228             - deux
229              
230             =head1 YAML class
231              
232             As of v2.129, this backend uses L<YAML::XS> 0.69 or later.
233              
234             For security reason, loading a Perl blessed object is disabled.
235              
236             Value of type boolean are written as boolean values in YAML files.
237              
238             =head1 backend parameter
239              
240             =head2 yaml_class
241              
242             This parameter is ignored as of version 2.129.
243              
244             =head1 CONSTRUCTOR
245              
246             =head2 new
247              
248             Parameters: C<< ( node => $node_obj, name => 'yaml' ) >>
249              
250             Inherited from L<Config::Model::Backend::Any>. The constructor is
251             called by L<Config::Model::BackendMgr>.
252              
253             =head2 read
254              
255             Read YAML file and load into C<$node_obj> tree.
256              
257             When a file is read, C<read> returns 1.
258              
259             =head2 write
260              
261             Write YAML File using C<$node_obj> data.
262              
263             C<write> returns 1.
264              
265             =head1 AUTHOR
266              
267             Dominique Dumont, (ddumont at cpan dot org)
268              
269             =head1 SEE ALSO
270              
271             L<Config::Model>, L<Config::Model::BackendMgr>,
272             L<Config::Model::Backend::Any>, L<YAML::XS>
273              
274             =head1 AUTHOR
275              
276             Dominique Dumont
277              
278             =head1 COPYRIGHT AND LICENSE
279              
280             This software is Copyright (c) 2018 by Dominique Dumont.
281              
282             This is free software, licensed under:
283              
284             The GNU Lesser General Public License, Version 2.1, February 1999
285              
286             =for :stopwords cpan testmatrix url bugtracker rt cpants kwalitee diff irc mailto metadata placeholders metacpan
287              
288             =head1 SUPPORT
289              
290             =head2 Websites
291              
292             The following websites have more information about this module, and may be of help to you. As always,
293             in addition to those websites please use your favorite search engine to discover more resources.
294              
295             =over 4
296              
297             =item *
298              
299             CPANTS
300              
301             The CPANTS is a website that analyzes the Kwalitee ( code metrics ) of a distribution.
302              
303             L<http://cpants.cpanauthors.org/dist/Config-Model-Backend-Yaml>
304              
305             =item *
306              
307             CPAN Testers
308              
309             The CPAN Testers is a network of smoke testers who run automated tests on uploaded CPAN distributions.
310              
311             L<http://www.cpantesters.org/distro/C/Config-Model-Backend-Yaml>
312              
313             =item *
314              
315             CPAN Testers Matrix
316              
317             The CPAN Testers Matrix is a website that provides a visual overview of the test results for a distribution on various Perls/platforms.
318              
319             L<http://matrix.cpantesters.org/?dist=Config-Model-Backend-Yaml>
320              
321             =item *
322              
323             CPAN Testers Dependencies
324              
325             The CPAN Testers Dependencies is a website that shows a chart of the test results of all dependencies for a distribution.
326              
327             L<http://deps.cpantesters.org/?module=Config::Model::Backend::Yaml>
328              
329             =back
330              
331             =head2 Bugs / Feature Requests
332              
333             Please report any bugs or feature requests by email to C<ddumont at cpan.org>, or through
334             the web interface at L<https://github.com/dod38fr/config-model-backend-yaml/issues>. You will be automatically notified of any
335             progress on the request by the system.
336              
337             =head2 Source Code
338              
339             The code is open to the world, and available for you to hack on. Please feel free to browse it and play
340             with it, or whatever. If you want to contribute patches, please send me a diff or prod me to pull
341             from your repository :)
342              
343             L<http://github.com/dod38fr/config-model-backend-yaml>
344              
345             git clone git://github.com/dod38fr/config-model-backend-yaml.git
346              
347             =cut