biohell
biohell

Reputation: 314

Edit conf files and change values with sed or awk in the dockerfile?

i have a bunch of conf files, which can be described as two types:

Type 1 (Typical conf-file-like ini files):

[server]
# Protocol (http, https)
;protocol = http

# The ip address to bind to, empty will bind to all interfaces
;http_addr = 192.168.33.2

# The http port  to use
;http_port = 3000    

Type 2 (malformated conf file):

###
### [http]
###

[http]
# Determines whether HTTP endpoint is enabled.
# enabled = true

# The bind address used by the HTTP service.
# bind-address = ":8080"

For Type1 conf files, i successfully could use tools like crudini p.a with crudini --set filename.conf server protocol https which actually adds a new entry under server section instead of uncommenting the existing. As long it works its ok.

crudini failes with Type 2 files with a parse error, because the conf file is not a proper ini file. For these i tried using sed but failed.

What i want to achieve is to use one script/tool to be able to modify both type of files. Maybe a good approach could be to:

I found a lot of scripts, with a lot of code for this, but need a small footprint solution working with Docker conf files.

Can you help me to find a elegant solution for this?

Upvotes: 0

Views: 620

Answers (1)

rojo
rojo

Reputation: 24466

Here. Pay it forward. The leg work is handled by gawk. I tested it with the --posix switch, so I think it should work with mawk and other awk variants as well.

The script will quote values containing spaces and equal signs, and values where the value being replaced was quoted. I'm not familiar with Docker files, but since ":8000" was quoted in your second example I thought the quoting might be important.

#!/bin/bash

usage() {
    echo "Usage: $(basename $0) -s section -i item -v value filename"
    exit
}

export LC_ALL=C

while getopts "s:i:v:" i || (( $# )); do {
    case $i in
        s) section="$OPTARG";;
        i) item="$OPTARG";;
        v) value="$OPTARG";;
        ?) [[ -f $1 ]] && filename="$1";shift;;
    esac
}; done

[[ -z "$section" ]] || [[ -z "$item" ]] || [[ -z "$filename" ]] && usage

[[ -w "$filename" ]] && {
    tmpfile="$(mktemp -p /dev/shm)"
    [[ $(whoami) = "root" ]] && chown --reference="$filename" "$tmpfile"
    chmod --reference="$filename" "$tmpfile"
} || {
    echo "Invalid filename: $filename"
    usage
}

cleanup() {
    [[ -f "$tmpfile" ]] && rm -f "$tmpfile"
    exit
}
trap cleanup EXIT

awk -v section="$section" -v item="$item" -v value="$value" '
function quote(str) { return "\"" str "\"" }
/^\[[^\]]+\]/ {
    if (flag) {
        printf "%s = %s\n", item, value ~ /[[:space:]=]/ ? quote(value) : value
        flag = 0
    }
    else flag = (section == substr($0, 2, index($0, "]") - 2))
}
$0 ~ ("^[[:space:]#;]*" item "[[:space:]]*=") {
    if (flag) {
        $0 = sprintf("%s = %s", item, /"/ || value ~ /[[:space:]=]/ ? quote(value) : value)
        flag = 0
    }
}
1
END { if (flag) printf "%s = %s", item, value ~ /[[:space:]=]/ ? quote(value) : value }
' "$filename" >"$tmpfile"

[[ -s "$tmpfile" ]] && mv "$tmpfile" "$filename" || echo "Something went horribly wrong."

Upvotes: 2

Related Questions