Path: blob/main/pkg/flow/internal/controller/config.go
4095 views
package controller12import (3"fmt"45"github.com/grafana/agent/pkg/river/ast"6"github.com/grafana/agent/pkg/river/diag"7)89const (10argumentBlockID = "argument"11exportBlockID = "export"12loggingBlockID = "logging"13tracingBlockID = "tracing"14)1516// NewConfigNode creates a new ConfigNode from an initial ast.BlockStmt.17// The underlying config isn't applied until Evaluate is called.18func NewConfigNode(block *ast.BlockStmt, globals ComponentGlobals) (BlockNode, diag.Diagnostics) {19switch block.GetBlockName() {20case argumentBlockID:21return NewArgumentConfigNode(block, globals), nil22case exportBlockID:23return NewExportConfigNode(block, globals), nil24case loggingBlockID:25return NewLoggingConfigNode(block, globals), nil26case tracingBlockID:27return NewTracingConfigNode(block, globals), nil28default:29var diags diag.Diagnostics30diags.Add(diag.Diagnostic{31Severity: diag.SeverityLevelError,32Message: fmt.Sprintf("invalid config block type %s while creating new config node", block.GetBlockName()),33StartPos: ast.StartPos(block).Position(),34EndPos: ast.EndPos(block).Position(),35})36return nil, diags37}38}3940// ConfigNodeMap represents the config BlockNodes in their explicit types.41// This is helpful when validating node conditions specific to config node42// types.43type ConfigNodeMap struct {44logging *LoggingConfigNode45tracing *TracingConfigNode46argumentMap map[string]*ArgumentConfigNode47exportMap map[string]*ExportConfigNode48}4950// NewConfigNodeMap will create an initial ConfigNodeMap. Append must be called51// to populate NewConfigNodeMap.52func NewConfigNodeMap() *ConfigNodeMap {53return &ConfigNodeMap{54logging: nil,55tracing: nil,56argumentMap: map[string]*ArgumentConfigNode{},57exportMap: map[string]*ExportConfigNode{},58}59}6061// Append will add a config node to the ConfigNodeMap. This will overwrite62// values on the ConfigNodeMap that are matched and previously set.63func (nodeMap *ConfigNodeMap) Append(configNode BlockNode) diag.Diagnostics {64var diags diag.Diagnostics6566switch n := configNode.(type) {67case *ArgumentConfigNode:68nodeMap.argumentMap[n.Label()] = n69case *ExportConfigNode:70nodeMap.exportMap[n.Label()] = n71case *LoggingConfigNode:72nodeMap.logging = n73case *TracingConfigNode:74nodeMap.tracing = n75default:76diags.Add(diag.Diagnostic{77Severity: diag.SeverityLevelError,78Message: fmt.Sprintf("unsupported config node type found %q", n.Block().Name),79StartPos: ast.StartPos(n.Block()).Position(),80EndPos: ast.EndPos(n.Block()).Position(),81})82}8384return diags85}8687// Validate wraps all validators for ConfigNodeMap.88func (nodeMap *ConfigNodeMap) Validate(isInModule bool, args map[string]any) diag.Diagnostics {89var diags diag.Diagnostics9091newDiags := nodeMap.ValidateModuleConstraints(isInModule)92diags = append(diags, newDiags...)9394newDiags = nodeMap.ValidateUnsupportedArguments(args)95diags = append(diags, newDiags...)9697return diags98}99100// ValidateModuleConstraints will make sure config blocks with module101// constraints get followed.102func (nodeMap *ConfigNodeMap) ValidateModuleConstraints(isInModule bool) diag.Diagnostics {103var diags diag.Diagnostics104105if isInModule {106if nodeMap.logging != nil {107diags.Add(diag.Diagnostic{108Severity: diag.SeverityLevelError,109Message: "logging block not allowed inside a module",110StartPos: ast.StartPos(nodeMap.logging.Block()).Position(),111EndPos: ast.EndPos(nodeMap.logging.Block()).Position(),112})113}114115if nodeMap.tracing != nil {116diags.Add(diag.Diagnostic{117Severity: diag.SeverityLevelError,118Message: "tracing block not allowed inside a module",119StartPos: ast.StartPos(nodeMap.tracing.Block()).Position(),120EndPos: ast.EndPos(nodeMap.tracing.Block()).Position(),121})122}123return diags124}125126for key := range nodeMap.argumentMap {127diags.Add(diag.Diagnostic{128Severity: diag.SeverityLevelError,129Message: "argument blocks only allowed inside a module",130StartPos: ast.StartPos(nodeMap.argumentMap[key].Block()).Position(),131EndPos: ast.EndPos(nodeMap.argumentMap[key].Block()).Position(),132})133}134135for key := range nodeMap.exportMap {136diags.Add(diag.Diagnostic{137Severity: diag.SeverityLevelError,138Message: "export blocks only allowed inside a module",139StartPos: ast.StartPos(nodeMap.exportMap[key].Block()).Position(),140EndPos: ast.EndPos(nodeMap.exportMap[key].Block()).Position(),141})142}143144return diags145}146147// ValidateUnsupportedArguments will validate each provided argument is148// supported in the config.149func (nodeMap *ConfigNodeMap) ValidateUnsupportedArguments(args map[string]any) diag.Diagnostics {150var diags diag.Diagnostics151152for argName := range args {153if _, found := nodeMap.argumentMap[argName]; found {154continue155}156diags.Add(diag.Diagnostic{157Severity: diag.SeverityLevelError,158Message: fmt.Sprintf("Provided argument %q is not defined in the module", argName),159})160}161162return diags163}164165166