add POST /logs installer log relay to VictoriaLogs
A host being PXE-discovered or installed is not in Kubernetes, so vlagent cannot collect its logs and a failed install leaves no record; the installer environment has no internal-CA trust or credentials for the HTTPS log ingest, and bootapi is already the plain-HTTP broker it can reach. - add POST /logs, token-guarded like POST /provisioned, relaying ndjson to vlinsert's jsonline endpoint keyed on serial+phase - stamp observed source IP and resolved NetBox device name into extra_fields - return 202 on a sink failure so logs never block an install - add BOOTAPI_VLINSERT_URL/_TIMEOUT and bootapi_log_relay metrics
This commit is contained in:
@@ -79,6 +79,15 @@ type Config struct {
|
||||
// endpoint (fail closed). Prefer ProvisionTokenFile in k8s.
|
||||
ProvisionToken string
|
||||
|
||||
// VLInsertURL is the VictoriaLogs vlinsert base that POST /logs relays
|
||||
// installer logs to. Empty disables the endpoint (it then 503s): a host
|
||||
// being installed has no vlagent and no credentials for the HTTPS ingest,
|
||||
// so bootapi relays for it.
|
||||
VLInsertURL string
|
||||
// VLInsertTimeout bounds the single best-effort forward attempt. Short on
|
||||
// purpose — an install must not wait on the log sink.
|
||||
VLInsertTimeout time.Duration
|
||||
|
||||
// PuppetServer / PuppetCAServer are baked into kickstart %post so the
|
||||
// freshly-installed host checks in to the k8s puppetserver.
|
||||
PuppetServer string
|
||||
@@ -118,6 +127,16 @@ func Load() (*Config, error) {
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid BOOTAPI_TEMPLATE_GIT_INTERVAL: %w", err)
|
||||
}
|
||||
vlTimeout, err := time.ParseDuration(getenv("BOOTAPI_VLINSERT_TIMEOUT", "5s"))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid BOOTAPI_VLINSERT_TIMEOUT: %w", err)
|
||||
}
|
||||
// Unlike the other URLs, an explicitly EMPTY value is meaningful here: it
|
||||
// disables the log relay, so LookupEnv rather than getenv.
|
||||
vlURL, ok := os.LookupEnv("BOOTAPI_VLINSERT_URL")
|
||||
if !ok {
|
||||
vlURL = "http://vlinsert-logs.logging.svc.cluster.local:9481"
|
||||
}
|
||||
|
||||
token, err := readSecret("BOOTAPI_NETBOX_TOKEN")
|
||||
if err != nil {
|
||||
@@ -169,6 +188,8 @@ func Load() (*Config, error) {
|
||||
ArtifactBaseURL: strings.TrimRight(getenv("BOOTAPI_ARTIFACT_BASE_URL", "https://artifactapi.k8s.syd1.au.unkin.net/api/v1/remote"), "/"),
|
||||
BootBaseURL: strings.TrimRight(os.Getenv("BOOTAPI_BOOT_BASE_URL"), "/"),
|
||||
ProvisionToken: provToken,
|
||||
VLInsertURL: strings.TrimRight(vlURL, "/"),
|
||||
VLInsertTimeout: vlTimeout,
|
||||
PuppetServer: getenv("BOOTAPI_PUPPET_SERVER", "puppet.k8s.syd1.au.unkin.net"),
|
||||
PuppetCAServer: getenv("BOOTAPI_PUPPET_CA_SERVER", "puppetca.k8s.syd1.au.unkin.net"),
|
||||
PuppetCAURL: getenv("BOOTAPI_PUPPET_CA_URL", "puppetca.k8s.syd1.au.unkin.net"),
|
||||
|
||||
@@ -40,6 +40,34 @@ func TestLoadDefaults(t *testing.T) {
|
||||
if c.ArtifactBaseURL != "https://artifactapi.k8s.syd1.au.unkin.net/api/v1/remote" {
|
||||
t.Errorf("ArtifactBaseURL = %q", c.ArtifactBaseURL)
|
||||
}
|
||||
if c.VLInsertURL != "http://vlinsert-logs.logging.svc.cluster.local:9481" {
|
||||
t.Errorf("VLInsertURL = %q", c.VLInsertURL)
|
||||
}
|
||||
if c.VLInsertTimeout != 5*time.Second {
|
||||
t.Errorf("VLInsertTimeout = %v, want 5s", c.VLInsertTimeout)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVLInsertURLEmptyDisablesRelay(t *testing.T) {
|
||||
clearEnv(t)
|
||||
// An explicitly empty value must NOT fall back to the default: it disables
|
||||
// the /logs relay.
|
||||
t.Setenv("BOOTAPI_VLINSERT_URL", "")
|
||||
c, err := Load()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if c.VLInsertURL != "" {
|
||||
t.Errorf("VLInsertURL = %q, want empty (relay disabled)", c.VLInsertURL)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVLInsertBadTimeout(t *testing.T) {
|
||||
clearEnv(t)
|
||||
t.Setenv("BOOTAPI_VLINSERT_TIMEOUT", "soon")
|
||||
if _, err := Load(); err == nil {
|
||||
t.Fatal("expected error for invalid BOOTAPI_VLINSERT_TIMEOUT")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCallbackBaseDefaultsToBase(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user