config: detect duplicate & internal job names at parse time (#908)

Before this PR, config parsing would accept duplicate job names. `zrepl
daemon` would later fail to start with a panic. But tools like `zrepl
configcheck` would pass.

This PR adds a check to ensure job names are unique.

Similarly, internal job names were not being rejected by config parsing
Move that check to parse-time as well.

Last, drive-by change: remove `internal/config/config_include_test.go`
introduced in #856 . These aren't necessary because there is already a
wildcard test for all valid configs.
This PR adds the complimentary "invalid config" wildcard test.
This commit is contained in:
Christian Schwarz
2026-01-19 09:38:43 +01:00
committed by GitHub
parent 4d6583ea5f
commit 860a9be37f
9 changed files with 108 additions and 54 deletions
+5 -8
View File
@@ -5,7 +5,6 @@ import (
"fmt"
"os"
"os/signal"
"strings"
"sync"
"syscall"
"time"
@@ -64,7 +63,7 @@ func Run(ctx context.Context, conf *config.Config) error {
})
for _, job := range confJobs {
if IsInternalJobName(job.Name()) {
if config.IsInternalJobName(job.Name()) {
panic(fmt.Sprintf("internal job name used for config job '%s'", job.Name())) //FIXME
}
}
@@ -211,10 +210,6 @@ const (
jobNameControl = "_control"
)
func IsInternalJobName(s string) bool {
return strings.HasPrefix(s, "_")
}
func (s *jobs) start(ctx context.Context, j job.Job, internal bool) {
s.m.Lock()
defer s.m.Unlock()
@@ -222,10 +217,12 @@ func (s *jobs) start(ctx context.Context, j job.Job, internal bool) {
ctx = logging.WithInjectedField(ctx, logging.JobField, j.Name())
jobName := j.Name()
if !internal && IsInternalJobName(jobName) {
// package `config` enforces these with clean errors, these are just assertions
if !internal && config.IsInternalJobName(jobName) {
panic(fmt.Sprintf("internal job name used for non-internal job %s", jobName))
}
if internal && !IsInternalJobName(jobName) {
if internal && !config.IsInternalJobName(jobName) {
panic(fmt.Sprintf("internal job does not use internal job name %s", jobName))
}
if _, ok := s.jobs[jobName]; ok {