zabbix/templates/entrypoints/internal/bootstrap/config.go
2026-07-15 17:51:41 +09:00

125 lines
3.1 KiB
Go

//go:build windows
package bootstrap
import (
"bytes"
"fmt"
"os"
"strings"
)
// UpdateConfigMultiple replaces the name option in the configuration file
// with one line per comma-separated item of rawValue. An empty value removes
// the option.
func UpdateConfigMultiple(configPath, name, rawValue string) error {
value := strings.Trim(strings.TrimSpace(rawValue), `"`)
if value == "" {
return rewriteConfig(configPath, name, nil, false)
}
items := strings.Split(value, ",")
values := make([]string, 0, len(items))
for _, item := range items {
if item != "" {
values = append(values, item)
}
}
return rewriteConfig(configPath, name, values, true)
}
// UpdateConfigValue sets a single-value option in the configuration file.
func UpdateConfigValue(configPath, name, value string) error {
return rewriteConfig(configPath, name, []string{value}, false)
}
func rewriteConfig(configPath, name string, values []string, preserveExisting bool) error {
data, err := os.ReadFile(configPath)
if err != nil {
return fmt.Errorf("missing configuration file %s: %w", configPath, err)
}
lines := strings.Split(strings.TrimSuffix(string(data), "\n"), "\n")
activePrefix := name + "="
commentPrefixes := []string{"# " + activePrefix, "; " + activePrefix}
output := make([]string, 0, len(lines)+len(values)+1)
existing := make(map[string]struct{})
insertAt := -1
for _, line := range lines {
if strings.HasPrefix(line, activePrefix) {
if preserveExisting {
output = append(output, line)
existing[strings.TrimPrefix(line, activePrefix)] = struct{}{}
insertAt = len(output)
}
continue
}
output = append(output, line)
if insertAt == -1 && hasAnyPrefix(line, commentPrefixes) {
insertAt = len(output)
}
}
newLines := make([]string, 0, len(values))
for _, value := range values {
if value == "" {
continue
}
if _, found := existing[value]; !found {
newLines = append(newLines, activePrefix+value)
}
}
if insertAt >= 0 {
updated := make([]string, 0, len(output)+len(newLines))
updated = append(updated, output[:insertAt]...)
updated = append(updated, newLines...)
updated = append(updated, output[insertAt:]...)
output = updated
} else if len(newLines) > 0 {
if len(output) > 0 && output[len(output)-1] != "" {
output = append(output, "")
}
output = append(output, newLines...)
}
requested := false
for _, value := range values {
if value != "" {
requested = true
break
}
}
updatedData := []byte(strings.Join(output, "\n") + "\n")
changed := !bytes.Equal(data, updatedData)
if changed {
if err := WriteFilePreservingMode(configPath, updatedData); err != nil {
return fmt.Errorf("update configuration file %s: %w", configPath, err)
}
}
if !requested {
if changed {
LogInfo("** Removing %s parameter '%s'", configPath, name)
}
return nil
}
loggedValue := strings.Join(values, ",")
if changed {
LogInfo("** Updating %s parameter '%s': '%s'", configPath, name, loggedValue)
} else {
LogInfo("** Updating %s parameter '%s': '%s'... exists", configPath, name, loggedValue)
}
return nil
}