Editing INI-like files with a script

Have a look at crudini, which is a shell tool designed for this

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

or a single atomic invocation like:

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

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

Here are a few script examples. These are bare minimum and don't bother with error checking, command line options, etc. I've indicated whether I've run the script myself to verify its correctness.

Ruby

Install the inifile rubygem for this script. This script is tested.

#!/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

Usage:

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

Perl

Install Config::IniFiles using cpan or your OS package manager (if there is a package available). This script is untested as I've stopped using perl on my system. It may need a little work, and corrections are welcome.

#!/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();

Usage:

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

awk

This script is more Bash and *nix friendly and uses a common utility of *nix OS's, awk. This script is tested.

#!/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; }

Usage:

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

If you can afford to install external tools, than I would recommend Augeas - this is the only tool for working with config files you will ever need. It represents configs as a tree. Read more here.