Edición de archivos tipo INI con un script

Edición de archivos tipo INI con un script

Estoy escribiendo un script para automatizar la configuración de archivos de configuración del agente Puppet en Docker.

Básicamente, necesito asegurarme de que la siguiente sección esté en /etc/puppet/puppet.conf:

[agent]
server=$PUPPETMASTER_HOSTNAME
masterport=$PUPPETMASTER_PORT

Lo que he estado haciendo hasta ahora en mi script runit del agente Puppet es esto:

function write_puppet_config () {
    read -d '' puppet_config <<EOF
[agent]
server=$1
masterport=$2
EOF

    echo -e "$puppet_config" >> /etc/puppet/puppet.conf
}

# default puppet master port is 8410
test -z "$PUPPET_MASTER_TCP_PORT" && export PUPPET_MASTER_TCP_PORT="8410"

# if there is a puppet master host defined, rewrite the config to match
if [ ! -z "$PUPPET_MASTER_TCP_HOST" ]; then 
    write_puppet_config "$PUPPET_MASTER_TCP_HOST" "$PUPPET_MASTER_TCP_PORT"
fi

El problema debería ser bastante evidente. Si la configuración de Puppet ya especifica la configuración, simplemente agregaré otra [agent]sección, lo cual es malo.

Podría simplemente activar la lógica condicional (es decir, grep si está ahí y luego reescribirla con sed si está), pero ¿hay alguna manera de realizar una edición desde la línea de comando? Básicamente, me gustaría ejecutar un comando que diga "si no hay una sección de agente, agréguela y luego asegúrese de que el servidor y el puerto maestro estén configurados con los valores correctos en esa sección".

Sé que existen herramientas estructuradas como esta para XML, pero ¿qué pasa con los archivos de estilo INI?

Respuesta1

Mira estocrudini, que es una herramienta de shell diseñada para esto

conf=/etc/puppet/puppet.conf
crudini --set "$conf" agent server "$PUPPET_MASTER_TCP_HOST"
crudini --set "$conf" agent masterport "$PUPPET_MASTER_TCP_PORT"

o una única invocación atómica como:

echo "
[agent]
server=$1
masterport=$2" |

crudini --merge /etc/puppet/puppet.conf

Respuesta2

A continuación se muestran algunos ejemplos de guiones. Estos son mínimos y no molestan con la verificación de errores, las opciones de la línea de comando, etc. Indiqué si ejecuté el script yo mismo para verificar su corrección.

Rubí

Instale inifileRubygem para este script. Este guión esprobado.

#!/usr/bin/env ruby
# filename: ~/config.rb

require 'inifile'

PUPPETMASTER_HOSTNAME='hello'
PUPPETMASTER_PORT='world'

ini = IniFile::load('/etc/puppet/puppet.conf')
ini['agent']['server'] = PUPPETMASTER_HOSTNAME
ini['agent']['masterport'] = PUPPETMASTER_PORT
ini.save

Uso:

$ chmod 700 ~/config.rb
$ sudo ~/config.rb     # or, if using rvm, rvmsudo ~/config.rb

perla

Instálelo Config::IniFilesusando cpano el administrador de paquetes de su sistema operativo (si hay un paquete disponible). Este guión esno probadoya que dejé de usarlo perl en mi sistema. Puede que necesite un poco de trabajo y las correcciones son bienvenidas.

#!/usr/bin/env perl
# filename: ~/config.pl

use Config::IniFiles;

my $PUPPETMASTER_HOSTNAME='perl';
my $PUPPETMASTER_PORT='1234';

my $ini = Config::IniFiles->new(-file => '/etc/puppet/puppet.conf');

if (! $ini->SectionExists('agent')) {
    $ini->AddSection('agent');
}

if ($ini->exists('agent', 'server')) {
    $ini->setval('agent', 'server', $PUPPETMASTER_HOSTNAME);
}
else {
    $ini->newval('agent', 'server', $PUPPETMASTER_HOSTNAME);
}

if ($ini->exists('agent', 'masterport')) {
    $ini->setval('agent', 'masterport', $PUPPETMASTER_PORT);
}
else {
    $ini->newval('agent', 'masterport', $PUPPETMASTER_PORT);
}

$ini->RewriteConfig();

Uso:

$ chmod 700 ~/config.pl
$ sudo ~/config.pl

awk

Este script es más compatible con Bash y *nix y utiliza una utilidad común de los sistemas operativos *nix, awk. Este guión esprobado.

#!/usr/bin/env awk
# filename: ~/config.awk

BEGIN {
    in_agent_section=0;
    is_host_done=0;
    is_port_done=0;
    host = "awk.com";
    port = "4567";
}

in_agent_section == 1 {
    if ($0 ~ /^server[[:space:]]*=/) {
        print "server="host;
        is_host_done = 1;
        next;
    }
    else if ($0 ~ /^masterport[[:space:]]*=/) {
        print "masterport="port;
        is_port_done = 1;
        next;
    }
    else if ($0 ~ /^\[/) {
        in_agent_section = 0;
        if (! is_host_done) {
            print "server="host;
        }
        if (! is_port_done) {
            print "masterport="port;
        }
    }
}

/^\[agent\]/ {
    in_agent_section=1;
}

{ print; }

Uso:

$ awk -f ~/config.awk < /etc/puppet/puppet.conf > /tmp/puppet.conf
$ sudo mv /tmp/puppet.conf /etc/puppet/puppet.conf

Respuesta3

Si puede permitirse el lujo de instalar herramientas externas, le recomendaría Augeas: esta es la única herramienta para trabajar con archivos de configuración que necesitará. Representa las configuraciones como un árbol. Leer másaquí.

información relacionada