[freeside-devel] FS:Conf patches

ivan ivan at 420.am
Mon May 8 14:38:59 PDT 2000


I'm a little hesitant to add something to the standard distribution which
makes implementing write-access to configuration values much more
difficult.  This may be better implemented as a generator for the
current-style configuration files.

Incidentally, why IniConf?  IIRC your original proposal was to use
App::Config.  It looks like App::Config may have the same problem with
complicating write access, unfortunately.

[1] Question: why is write-access to configuration values important? 
    Answer: interactive configuration tools

On Fri, Apr 07, 2000 at 12:08:57PM -0500, David Morton wrote:
> Attached are two patches for UID.pm and Conf.pm files.   These
> patches allow for configuration to be set in a more limited
> area.   This seems to work for me so far... I'm sure it could use a
> little cleanup.  
> 
> Here's a brief description of what it does/expects:
> 
> Upon the first use of FS:Conf, it loads system wide
> values from /usr/local/etc/freeside/freeside.conf.
> 
> UID.pm looks in the mapsecrets file for the username/directory pair,
> and then loads the Conf module with that new directory, for example,
> /usr/local/etc/freeside/osprey/freeside.conf
> This file has the datasource names, and most of the configuration.
> 
> (The only reason for having two files, is if this is supposed to support
> two different companies on the same setup.  I wouldn't mind dropping
> this expectation for a while)
> 
> IniConf needs to be installed from CPAN...  I may change this part, but
> the
> configuration file format won't need to change.
> 
> 
> the freeside.conf file has the format:
> 
> 
> #comments start with '#'
> [default]   #section names in []'s   
> key=value
> array=<<EOT
> value1
> value2
> value3
> EOT
> 
> bool=true
> anotherbool=1
> yetanother=something rediculous.
> 
> #this next line doesn't work.
> 
> badbool=          
> 
> badbool=                    #although this does; value is spaces.  It's
> a bug.
>                             #the comment makes it read the spaces.
> [other]
> foo=bar
> 
> ______________________
> 
> 
> For exists() to work, the  value must have a value, although it doesn't
> matter what.
> 
> exists("yetanother")  is true
> exists("badbool=") is not true for the first entry, although the second
> entry would overwrite the first.
> --- /home/freeside/dist/freeside_current/FS/FS/UID.pm	Thu Apr  6 11:57:00 2000
> +++ FS/UID.pm	Thu Apr  6 11:19:21 2000
> @@ -215,15 +215,27 @@
>    my($setuser) = shift;
>    $user = $setuser if $setuser;
>    die "No user!" unless $user;
> -  my($conf) = new FS::Conf $conf_dir;
> -  my($line) = grep /^\s*$user\s/, $conf->config('mapsecrets');
> -  die "User not found in mapsecrets!" unless $line;
> -  $line =~ /^\s*$user\s+(.*)$/;
> -  $secrets = $1;
> +  
> +  open MAPSECRETS, $conf_dir . "/mapsecrets";
> +  
> +  while (<MAPSECRETS>) {
> +  	if (/^\s*$user\s+(.*)$/) {
> +		$secrets = $1;
> +		last;
> +	}
> +  }
>    die "Illegal mapsecrets line for user?!" unless $secrets;
> -  ($datasrc, $db_user, $db_pass) = $conf->config($secrets)
> +  
> +  
> +  my($conf) = new FS::Conf "$conf_dir$secrets" ;
> +  ($datasrc, $db_user, $db_pass) = $conf->config("datasource")
>      or die "Can't get secrets: $!";
> -  $FS::Conf::default_dir = $conf_dir. "/conf.$datasrc";
>    ($datasrc, $db_user, $db_pass);
>  }
>  

> --- /home/freeside/dist/freeside_current/FS/FS/Conf.pm	Thu Apr  6 11:57:00 2000
> +++ FS/Conf.pm	Fri Apr  7 11:37:14 2000
> @@ -1,7 +1,9 @@
>  package FS::Conf;
>  
> -use vars qw($default_dir);
> +use vars qw(%configs $config_main);
>  use IO::File;
> +use IniConf;
> +use Carp;
>  
>  =head1 NAME
>  
> @@ -19,38 +21,83 @@
>    $dir = $conf->dir;
>  
>    $value = $conf->config('key');
> +  $value = $conf->config('key','section');
>    @list  = $conf->config('key');
>    $bool  = $conf->exists('key');
>  
>  =head1 DESCRIPTION
>  
> -Read access to Freeside configuration values.  Keys currently map to filenames,
> -but this may change in the future.
> +Read access to Freeside configuration values.  Freeside looks for a file named 
> +F<freeside.conf> in the directory named, or F</usr/local/etc/freeside> as default.
> +FS::Conf stores the configuration in a class variable %configs, so that it won't
> +have to be reloaded if new is called again.  The freeside.conf file is formatted
> +like an .ini  file;  see the manpage for IniConf 
>  
>  =head1 METHODS
>  
>  =over 4
>  
> +=cut
> +
> +BEGIN {
> +	$default_dir = "/usr/local/etc/freeside";	#if this could be set be a command
> +											#line argument, that would be nifty
> +
> +
> +    if ($config_main = IniConf->new( -file => $default_dir .
> +	                                          "/freeside.conf"))  {
> +			my $mainself={ 'dir' => $default_dir,
> +				   'config' =>  $config_main} ;
> +		bless $mainself, "FS::Conf";
> +		$configs{$default_dir} = $mainself;
> +	} else {
> +		print STDERR "Could not open config file: $default_dir/freeside.conf\n"
> +		. "There were problems on the following lines:\n" . 
> +		join "\n", @IniConf::errors;
> +		print "\n";
> +		exit();
> +	}
> +}
> +
> +
>  =item new [ DIRECTORY ]
>  
> -Create a new configuration object.  A directory arguement is required if
> -$FS::Conf::default_dir has not been set.
> +Create a new configuration object.  Defaults to F</usr/local/etc/freeside/> if 
> +no parameter is passed; otherwise it looks for the F<freeside.conf> file in the
> +directory indicated.
>  
>  =cut
>  
>  sub new {
> -  my($proto,$dir) = @_;
> -  my($class) = ref($proto) || $proto;
> -  my($self) = { 'dir' => $dir || $default_dir } ;
> -  bless ($self, $class);
> +	my($proto,$dir) = @_;
> +	my($class) = ref($proto) || $proto;
> +	
> +	$dir = $default_dir if !defined($dir);
> +	$dir =~ s/(.*)\/$/$1/;
> +	
> +	if (exists $configs{$dir}) {
> +		return  $configs{$dir};
> +	} 
> +	
> +	#print "loading more config values from $dir/freeside.conf\n";
> +	
> +	
> +	my $config = IniConf->new( -file => $dir . "/freeside.conf");
> +	my($self) = { 'dir' => $dir,
> +				 'config' => $config} ;
> +
> +	bless $self, $class;
> +	$configs{$dir} = $self;
> +	
>  }
>  
>  =item dir
>  
> -Returns the directory.
> +Returns the directory.  (Not sure if this is needed anymore - DGM)
>  
>  =cut
>  
> +
>  sub dir {
>    my($self) = @_;
>    my $dir = $self->{dir};
> @@ -64,49 +111,56 @@
>  =item config 
>  
>  Returns the configuration value or values (depending on context) for key.
> +Optional section parameter specifies which section to look in for the key;
> +defaults to "default".   A temporary hack allows for the key to include
> +a directory path - this will be interpreted as a section, ie.
> +C<config("/foo/bar/file")> translates to C<config("file", "/foo/bar")>
>  
>  =cut
>  
>  sub config {
> -  my($self,$file)=@_;
> -  my($dir)=$self->dir;
> -  my $fh = new IO::File "<$dir/$file" or return;
> -  if ( wantarray ) {
> -    map {
> -      /^(.*)$/
> -        or die "Illegal line (array context) in $dir/$file:\n$_\n";
> -      $1;
> -    } <$fh>;
> -  } else {
> -    <$fh> =~ /^(.*)$/
> -      or die "Illegal line (scalar context) in $dir/$file:\n$_\n";
> -    $1;
> -  }
> +	my($self,$file, $section)=@_;
> +	my($dir)=$self->{dir};
> +	
> +	$section = "default" if !defined $section;
> +	
> +	if ($file =~ /(.*)\/(.*)/) {  #subdirectories translate to sections?
> +		$section = $1;            #backwards compatability hack
> +		$file = $2;
> +	}
> +
> +	my $result = eval '$configs{$dir}->{config}->val($section, $file)';
> +
> +	
> +
>  }
>  
>  =item exists
>  
> -Returns true if the specified key exists, even if the corresponding value
> -is undefined.
> +Returns true if the specified key exists, no matter what the value. (A value
> +must exist in the configuration file, though.)  Parameters are the same as
> +C<config>
>  
>  =cut
>  
>  sub exists {
> -  my($self,$file)=@_;
> -  my($dir) = $self->dir;
> -  -e "$dir/$file";
> +  my($self,$file, $section)=@_;
> +  my($dir) = $self->{dir};
> +  $section = "default" if !defined $section;
> +  
> +  if ($file =~ /(.*)\/(.*)/) {  #subdirectories translate to sections...
> +		$section = $1;          #backwards compatability hack
> +		$file = $2;
> +  }
> +  
> +  my $result = eval '$configs{$dir}->{config}->val("default",$file)';
> +  
> +  if ($@) {
> +  	croak "FATAL:  Problem in FS::Conf::exists!";
> +  } else {
> +  	return $result;
> +  }
>  }
>  
> -=back
> -
> -=head1 BUGS
> -
> -Write access (with locking) should be implemented.
> -
> -=head1 SEE ALSO
> -
> -config.html from the base documentation contains a list of configuration files.
> -
> -=cut
>  
>  1;


-- 
meow
_ivan



More information about the freeside-devel mailing list