File: LayeredInclude.pm

package info (click to toggle)
libconfig-model-perl 2.155-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,172 kB
  • sloc: perl: 15,117; makefile: 19
file content (114 lines) | stat: -rw-r--r-- 2,945 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
package Config::Model::Value::LayeredInclude;

use v5.20;
use Mouse;
use strict;
use warnings;
use Log::Log4perl qw(get_logger :levels);

use base qw/Config::Model::Value/;

use feature qw/postderef signatures/;
no warnings qw/experimental::postderef experimental::signatures/;

my $logger = get_logger("Tree::Element::Value::LayeredInclude");

# should we clear all layered value when include value is changed ?
# If yes, beware of recursive includes. Clear should only be done once.

around _store => sub ($orig, $self, %args) {
    my ( $value, $check, $silent, $notify_change, $ok, $callback ) =
        @args{qw/value check silent notify_change ok callback/};

    my $old_value = $self->_fetch_no_check;

    $orig->($self, %args);
    {
        ## no critic (TestingAndDebugging::ProhibitNoWarnings)
        no warnings 'uninitialized';
        return $value if $value eq $old_value;
    }

    my $i                  = $self->instance;
    my $already_in_layered = $i->layered;

    # layered stuff here
    if ( not $already_in_layered ) {
        $i->layered_clear;
        $i->layered_start;
    }

    {
        ## no critic (TestingAndDebugging::ProhibitNoWarnings)
        no warnings 'uninitialized';
        $logger->debug("Loading layered config from $value (old_data is $old_value)");
    }

    # load included file in layered mode
    $self->root->read_config_data(
        # check => 'no',
        config_file => $value,
        auto_create => 0,        # included file must exist
    );

    if ( not $already_in_layered ) {
        $i->layered_stop;
    }

    # test if already in layered mode -> if no, clear layered,
    $logger->debug("Done loading layered config from $value");

    return $value;
};

1;

# ABSTRACT: Include a sub layer configuration

__END__

=head1 SYNOPSIS

    # in a model declaration:
    'element' => [
      'include' => {
        'class' => 'Config::Model::Value::LayeredInclude',

        # usual Config::Model::Value parameters
        'type' => 'leaf',
        'value_type' => 'uniline',
        'convert' => 'lc',
        'summary' => 'Include file for cascaded configuration',
        'description' => 'To support multiple variants of ...'
      },
    ]

=head1 DESCRIPTION

This class inherits from L<Config::Model::Value>. It overrides
L<_store> to trigger a refresh of layered value when a value is
changed. I.e. changing this value trigger a reload of the referred configuration
file which values are used as default value. This class was designed to
cope with L<multistrap|http://wiki.debian.org/Multistrap> configuration.

=head2 CAUTION

A configuration file can support 2 kinds of include:

=over

=item *

Layered include which sets default values like multistrap or ssh. These includes are
read-only.

=item *

Real includes like C<apache>. In this cases modified configuration items can be written to
included files.

=back

This class works only with the first type

=cut