From a12112316b2c76782d58aa3a2707cad09f03d708 Mon Sep 17 00:00:00 2001 From: Andrew Morozko Date: Sun, 11 Feb 2024 20:51:27 +0400 Subject: [PATCH] fix --- parser/caller.go | 23 +++------------ parser/definedBlocks.go | 8 +++++ parser/definitions/config.go | 5 ++++ parser/definitions/configEmpty.go | 49 +++++++++++++++++++++++++++++++ parser/definitions/configPtr.go | 5 ++++ parser/evaluation/evaluation.go | 1 + parser/parsePluginBlock.go | 12 ++++---- 7 files changed, 78 insertions(+), 25 deletions(-) create mode 100644 parser/definitions/configEmpty.go diff --git a/parser/caller.go b/parser/caller.go index 74cfdf12..c7aa2be7 100644 --- a/parser/caller.go +++ b/parser/caller.go @@ -84,13 +84,11 @@ func (c *Caller) callPlugin(kind, name string, config evaluation.Configuration, return } - // TODO: check that nil interface values are checked like this everywhere - needsConfig := !utils.IsNil(data.ConfigSpec) - hasConfig := !utils.IsNil(config) + acceptsConfig := !utils.IsNil(data.ConfigSpec) + hasConfig := config.Exists() var configVal cty.Value - switch { - case needsConfig && hasConfig: // happy path + if acceptsConfig { var stdDiag diagnostics.Diag configVal, stdDiag = config.ParseConfig(data.ConfigSpec) if !diags.Extend(stdDiag) { @@ -105,20 +103,7 @@ func (c *Caller) callPlugin(kind, name string, config evaluation.Configuration, } } } - case !needsConfig && !hasConfig: - // happy path, do nothing - case needsConfig && !hasConfig: - diags.Append(&hcl.Diagnostic{ - Severity: hcl.DiagError, - Summary: "Plugin requires configuration", - Detail: fmt.Sprintf("Plugin '%s %s' has no default configuration and "+ - "no configuration was provided at the plugin invocation. "+ - "Provide an inline config block or a config attribute", - kind, name), - Subject: invocation.MissingItemRange().Ptr(), - Context: invocation.Range().Ptr(), - }) - case !needsConfig && hasConfig: + } else if hasConfig { diags.Append(&hcl.Diagnostic{ Severity: hcl.DiagWarning, Summary: "Plugin doesn't support configuration", diff --git a/parser/definedBlocks.go b/parser/definedBlocks.go index 4150bad7..75bd86e9 100644 --- a/parser/definedBlocks.go +++ b/parser/definedBlocks.go @@ -69,6 +69,14 @@ func (db *DefinedBlocks) GetConfig(expr hcl.Expression) (cfg *definitions.Config return } +func (db *DefinedBlocks) DefaultConfigFor(plugin *definitions.Plugin) (config *definitions.Config) { + return db.Config[definitions.Key{ + PluginKind: plugin.Kind(), + PluginName: plugin.Name(), + BlockName: "", + }] +} + func (db *DefinedBlocks) Merge(other *DefinedBlocks) (diags diagnostics.Diag) { for k, v := range other.Config { diags.Append(AddIfMissing(db.Config, k, v)) diff --git a/parser/definitions/config.go b/parser/definitions/config.go index e8375a80..637527cd 100644 --- a/parser/definitions/config.go +++ b/parser/definitions/config.go @@ -20,6 +20,11 @@ type Config struct { value cty.Value } +// Exists implements evaluation.Configuration. +func (c *Config) Exists() bool { + return c != nil +} + var _ evaluation.Configuration = (*Config)(nil) // ParseConfig implements Configuration. diff --git a/parser/definitions/configEmpty.go b/parser/definitions/configEmpty.go new file mode 100644 index 00000000..1e798d62 --- /dev/null +++ b/parser/definitions/configEmpty.go @@ -0,0 +1,49 @@ +package definitions + +import ( + "fmt" + + "github.com/hashicorp/hcl/v2" + "github.com/hashicorp/hcl/v2/hcldec" + "github.com/hashicorp/hcl/v2/hclsyntax" + "github.com/zclconf/go-cty/cty" + + "github.com/blackstork-io/fabric/parser/evaluation" + "github.com/blackstork-io/fabric/pkg/diagnostics" +) + +// Empty config, storing the range of the original block +type ConfigEmpty struct { + MissingItemRange hcl.Range +} + +// Exists implements evaluation.Configuration. +func (c *ConfigEmpty) Exists() bool { + return false +} + +// ParseConfig implements Configuration. +func (c *ConfigEmpty) ParseConfig(spec hcldec.Spec) (val cty.Value, diags diagnostics.Diag) { + emptyBody := &hclsyntax.Body{ + SrcRange: c.MissingItemRange, + EndRange: hcl.Range{ + Filename: c.MissingItemRange.Filename, + Start: c.MissingItemRange.End, + End: c.MissingItemRange.End, + }, + } + + var diag hcl.Diagnostics + val, diag = hcldec.Decode(emptyBody, spec, nil) + for _, d := range diag { + d.Summary = fmt.Sprintf("Missing required configuration: %s", d.Summary) + } + return val, diagnostics.Diag(diag) +} + +// Range implements Configuration. +func (c *ConfigEmpty) Range() hcl.Range { + return c.MissingItemRange +} + +var _ evaluation.Configuration = (*ConfigEmpty)(nil) diff --git a/parser/definitions/configPtr.go b/parser/definitions/configPtr.go index 464358c5..2002eb9a 100644 --- a/parser/definitions/configPtr.go +++ b/parser/definitions/configPtr.go @@ -15,6 +15,11 @@ type ConfigPtr struct { Ptr *hcl.Attribute } +// Exists implements evaluation.Configuration. +func (c *ConfigPtr) Exists() bool { + return c != nil +} + // ParseConfig implements Configuration. func (c *ConfigPtr) ParseConfig(spec hcldec.Spec) (val cty.Value, diags diagnostics.Diag) { return c.Cfg.ParseConfig(spec) diff --git a/parser/evaluation/evaluation.go b/parser/evaluation/evaluation.go index 737aa5e3..43e64557 100644 --- a/parser/evaluation/evaluation.go +++ b/parser/evaluation/evaluation.go @@ -13,6 +13,7 @@ import ( type Configuration interface { ParseConfig(spec hcldec.Spec) (cty.Value, diagnostics.Diag) Range() hcl.Range + Exists() bool } // To act as a plugin invocation (body of the plugin call block) diff --git a/parser/parsePluginBlock.go b/parser/parsePluginBlock.go index 11be71ca..d2f313d6 100644 --- a/parser/parsePluginBlock.go +++ b/parser/parsePluginBlock.go @@ -190,13 +190,13 @@ func (db *DefinedBlocks) parsePluginConfig(plugin *definitions.Plugin, configAtt } } else if plugin.IsRef() { config = refBaseConfig - } else { + } else if defaultCfg := db.DefaultConfigFor(plugin); defaultCfg != nil { // Apply default configs to non-refs only - config = db.Config[definitions.Key{ - PluginKind: plugin.Kind(), - PluginName: plugin.Name(), - BlockName: "", - }] + config = defaultCfg + } else { + config = &definitions.ConfigEmpty{ + MissingItemRange: plugin.Block.Body.MissingItemRange(), + } } return }