diff --git a/server/cmd/cao-dashboard/canvas.go b/server/cmd/cao-dashboard/canvas.go index 7a6952c56..922642312 100644 --- a/server/cmd/cao-dashboard/canvas.go +++ b/server/cmd/cao-dashboard/canvas.go @@ -33,15 +33,22 @@ func parseCanvasConfig(content []byte) (*server.LocalCanvasConfig, error) { func readOperatorConfig(path string) (*server.LocalOperatorConfig, error) { if path == "" { + commandLog.Printf("native operator integration disabled: reason=no_config_path") return nil, nil //nolint:nilnil // An omitted adapter configuration disables native maintenance. } content, err := os.ReadFile(path) // #nosec G304 -- explicitly selected private native adapter configuration. if err != nil { return nil, errors.New("read native operator configuration") } + return parseOperatorConfig(content) +} + +// parseOperatorConfig decodes a native operator configuration document. +func parseOperatorConfig(content []byte) (*server.LocalOperatorConfig, error) { var config server.LocalOperatorConfig if err := json.Unmarshal(content, &config); err != nil { return nil, errors.New("invalid native operator configuration") } + commandLog.Printf("loaded native operator configuration") return &config, nil } diff --git a/server/cmd/cao-dashboard/canvas_test.go b/server/cmd/cao-dashboard/canvas_test.go index 300cfab3a..fbc01f477 100644 --- a/server/cmd/cao-dashboard/canvas_test.go +++ b/server/cmd/cao-dashboard/canvas_test.go @@ -46,3 +46,36 @@ func TestParseCanvasConfig(t *testing.T) { } } } + +func TestReadOperatorConfigOmittedPathDisablesMaintenance(t *testing.T) { + config, err := readOperatorConfig("") + if err != nil || config != nil { + t.Fatalf("got %v, %v; want nil, nil", config, err) + } +} + +func TestReadOperatorConfigFromFile(t *testing.T) { + path := filepath.Join(t.TempDir(), "operator.json") + if err := os.WriteFile(path, []byte(`{"adapterUrl":"http://127.0.0.1:1"}`), 0o600); err != nil { + t.Fatal(err) + } + config, err := readOperatorConfig(path) + if err != nil || config.AdapterURL != "http://127.0.0.1:1" || config.OperatorActions != nil { + t.Fatalf("got %+v, %v", config, err) + } +} + +func TestReadOperatorConfigMissingFile(t *testing.T) { + _, err := readOperatorConfig(filepath.Join(t.TempDir(), "absent.json")) + if err == nil || err.Error() != "read native operator configuration" { + t.Fatalf("got %v", err) + } +} + +func TestParseOperatorConfigRejectsInvalidDocuments(t *testing.T) { + for _, bad := range []string{"", "not json", `{"adapterUrl":1}`} { + if _, err := parseOperatorConfig([]byte(bad)); err == nil || err.Error() != "invalid native operator configuration" { + t.Errorf("%q: got %v", bad, err) + } + } +}