mirror of
https://github.com/turbot/steampipe.git
synced 2026-02-17 01:00:09 -05:00
Resource references in depdency mods must be fully qualified. Locals in dependency mods cannot be referenced. Support transitive dependencies referencing variables from different versions of same mod. Closes #3335. Closes #3336. Closes #3337
This commit is contained in:
@@ -57,8 +57,8 @@ func NewInitData(ctx context.Context) *InitData {
|
||||
return i
|
||||
}
|
||||
|
||||
if len(w.GetResourceMaps().Controls) == 0 {
|
||||
i.Result.AddWarnings("no controls found in current workspace")
|
||||
if len(w.GetResourceMaps().Controls)+len(w.GetResourceMaps().Benchmarks) == 0 {
|
||||
i.Result.AddWarnings("no controls or benchmarks found in current workspace")
|
||||
}
|
||||
|
||||
if err := controldisplay.EnsureTemplates(); err != nil {
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
)
|
||||
|
||||
// GetReferencedVariables builds map of variables values containing only those mod variables which are referenced
|
||||
// NOTE: we refer to variables in depdencyt mods in the format which is valid for an SPVARS filer, i.e.
|
||||
// NOTE: we refer to variables in dependency mods in the format which is valid for an SPVARS filer, i.e.
|
||||
// <mod>.<var-name>
|
||||
// the VariableValues map will contain these variables with the name format <mod>.var.<var-name>,
|
||||
// so we must convert the name
|
||||
@@ -22,7 +22,8 @@ func GetReferencedVariables(root dashboardtypes.DashboardTreeRun, w *workspace.W
|
||||
if len(parts) == 2 && parts[0] == "var" {
|
||||
varName := parts[1]
|
||||
varValueName := varName
|
||||
// NOTE: if the ref is NOT for the workspace mod, then use the fully qualifed name
|
||||
// NOTE: if the ref is NOT for the workspace mod, then use the qualified variable name
|
||||
// (e.g. aws_insights.var.v1)
|
||||
if refMod := ref.GetMetadata().ModName; refMod != w.Mod.ShortName {
|
||||
varValueName = fmt.Sprintf("%s.var.%s", refMod, varName)
|
||||
varName = fmt.Sprintf("%s.%s", refMod, varName)
|
||||
|
||||
@@ -38,12 +38,14 @@ func LoadMod(modPath string, parseCtx *parse.ModParseContext, opts ...LoadModOpt
|
||||
o(mod)
|
||||
}
|
||||
|
||||
// set the current mod on the run context
|
||||
parseCtx.SetCurrentMod(mod)
|
||||
|
||||
// load the mod dependencies
|
||||
if err := loadModDependencies(mod, parseCtx); err != nil {
|
||||
return nil, modconfig.NewErrorsAndWarning(err)
|
||||
}
|
||||
// now we have loaded dependencies, set the current mod on the run context
|
||||
parseCtx.CurrentMod = mod
|
||||
|
||||
// populate the resource maps of the current mod using the dependency mods
|
||||
mod.ResourceMaps = parseCtx.GetResourceMaps()
|
||||
// now load the mod resource hcl
|
||||
@@ -64,12 +66,6 @@ func loadModDefinition(modPath string, parseCtx *parse.ModParseContext) (*modcon
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// now we have loaded the mod, if this is a dependency mod, add in any variables we have loaded
|
||||
if parseCtx.ParentParseCtx != nil {
|
||||
parseCtx.Variables = parseCtx.ParentParseCtx.DependencyVariables[mod.ShortName]
|
||||
parseCtx.SetVariablesForDependencyMod(mod, parseCtx.ParentParseCtx.DependencyVariables)
|
||||
}
|
||||
|
||||
} else {
|
||||
// so there is no mod file - should we create a default?
|
||||
if !parseCtx.ShouldCreateDefaultMod() {
|
||||
@@ -124,7 +120,7 @@ func loadModDependency(modDependency *modconfig.ModVersionConstraint, parseCtx *
|
||||
parentFolder := filepath.Dir(filepath.Join(parseCtx.WorkspaceLock.ModInstallationPath, modDependency.Name))
|
||||
|
||||
// search the parent folder for a mod installation which satisfied the given mod dependency
|
||||
dependencyPath, version, err := findInstalledDependency(modDependency, parentFolder)
|
||||
dependencyDir, version, err := findInstalledDependency(modDependency, parentFolder)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -134,22 +130,9 @@ func loadModDependency(modDependency *modconfig.ModVersionConstraint, parseCtx *
|
||||
parseCtx.ListOptions.Exclude = nil
|
||||
defer func() { parseCtx.ListOptions.Exclude = prevExclusions }()
|
||||
|
||||
// create a child run context
|
||||
childRunCtx := parse.NewModParseContext(
|
||||
parseCtx.WorkspaceLock,
|
||||
dependencyPath,
|
||||
parse.CreatePseudoResources,
|
||||
&filehelpers.ListOptions{
|
||||
// listFlag specifies whether to load files recursively
|
||||
Flags: filehelpers.FilesRecursive,
|
||||
// only load .sp files
|
||||
Include: filehelpers.InclusionsFromExtensions([]string{constants.ModDataExtension}),
|
||||
})
|
||||
childRunCtx.BlockTypes = parseCtx.BlockTypes
|
||||
childRunCtx.ParentParseCtx = parseCtx
|
||||
|
||||
childParseCtx := parse.NewChildModParseContext(parseCtx, dependencyDir)
|
||||
// NOTE: pass in the version and dependency path of the mod - these must be set before it loads its depdencies
|
||||
mod, errAndWarnings := LoadMod(dependencyPath, childRunCtx, WithDependencyConfig(modDependency.Name, version))
|
||||
mod, errAndWarnings := LoadMod(dependencyDir, childParseCtx, WithDependencyConfig(modDependency.Name, version))
|
||||
if errAndWarnings.GetError() != nil {
|
||||
return errAndWarnings.GetError()
|
||||
}
|
||||
@@ -158,6 +141,8 @@ func loadModDependency(modDependency *modconfig.ModVersionConstraint, parseCtx *
|
||||
parseCtx.AddLoadedDependencyMod(mod)
|
||||
if parseCtx.ParentParseCtx != nil {
|
||||
parseCtx.ParentParseCtx.AddLoadedDependencyMod(mod)
|
||||
// add mod resources to parent parse context
|
||||
parseCtx.ParentParseCtx.AddModResources(mod)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -191,13 +176,6 @@ func loadModResources(modPath string, parseCtx *parse.ModParseContext) (*modconf
|
||||
|
||||
// parse all hcl files (NOTE - this reads the CurrentMod out of ParseContext and adds to it)
|
||||
mod, errAndWarnings := parse.ParseMod(fileData, pseudoResources, parseCtx)
|
||||
if errAndWarnings.GetError() == nil {
|
||||
// now add fully populated mod to the parent run context
|
||||
if parseCtx.ParentParseCtx != nil {
|
||||
parseCtx.ParentParseCtx.CurrentMod = mod
|
||||
parseCtx.ParentParseCtx.AddMod(mod)
|
||||
}
|
||||
}
|
||||
|
||||
return mod, errAndWarnings
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ func LoadVariableDefinitions(variablePath string, parseCtx *parse.ModParseContex
|
||||
return nil, errAndWarnings.GetError()
|
||||
}
|
||||
|
||||
variableMap := modconfig.NewModVariableMap(mod, parseCtx.GetTopLevelDependencyMods())
|
||||
variableMap := modconfig.NewModVariableMap(mod, parseCtx.LoadedDependencyMods)
|
||||
|
||||
return variableMap, nil
|
||||
}
|
||||
@@ -56,9 +56,6 @@ func GetVariableValues(ctx context.Context, parseCtx *parse.ModParseContext, var
|
||||
}
|
||||
}
|
||||
|
||||
// add workspace mod variables to runContext
|
||||
parseCtx.AddInputVariables(variableMap)
|
||||
|
||||
return variableMap, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -29,11 +29,11 @@ func NewModVariableMap(mod *Mod, dependencyMods ModMap) *ModVariableMap {
|
||||
m.RootVariables[buildVariableMapKey(k)] = v
|
||||
}
|
||||
// now add variables from dependency mods
|
||||
for _, mod := range dependencyMods {
|
||||
for dependencyPath, mod := range dependencyMods {
|
||||
// add variables into map, modifying the key to be the variable short name
|
||||
m.DependencyVariables[mod.ShortName] = make(map[string]*Variable)
|
||||
m.DependencyVariables[dependencyPath] = make(map[string]*Variable)
|
||||
for k, v := range mod.ResourceMaps.Variables {
|
||||
m.DependencyVariables[mod.ShortName][buildVariableMapKey(k)] = v
|
||||
m.DependencyVariables[dependencyPath][buildVariableMapKey(k)] = v
|
||||
}
|
||||
}
|
||||
// build map of all variables
|
||||
|
||||
@@ -43,7 +43,7 @@ type ModParseContext struct {
|
||||
ListOptions *filehelpers.ListOptions
|
||||
// map of loaded dependency mods, keyed by DependencyPath (including version)
|
||||
// there may be multiple versions of same mod in this map
|
||||
loadedDependencyMods modconfig.ModMap
|
||||
LoadedDependencyMods modconfig.ModMap
|
||||
|
||||
// Variables are populated in an initial parse pass top we store them on the run context
|
||||
// so we can set them on the mod when we do the main parse
|
||||
@@ -53,7 +53,8 @@ type ModParseContext struct {
|
||||
Variables map[string]*modconfig.Variable
|
||||
|
||||
// DependencyVariables is a map of the variables in the dependency mods of the current mod
|
||||
// it is used to populate the variables property on the dependency
|
||||
// it is used to populate the variables values on child parseContexts when parsing dependencies
|
||||
// (keyed by mod DependencyPath)
|
||||
DependencyVariables map[string]map[string]*modconfig.Variable
|
||||
ParentParseCtx *ModParseContext
|
||||
|
||||
@@ -68,9 +69,10 @@ type ModParseContext struct {
|
||||
topLevelBlocks map[*hcl.Block]struct{}
|
||||
// map of block names, keyed by a hash of the blopck
|
||||
blockNameMap map[string]string
|
||||
// map of ReferenceTypeValueMaps keyed by mod
|
||||
// map of ReferenceTypeValueMaps keyed by mod name
|
||||
// NOTE: all values from root mod are keyed with "local"
|
||||
referenceValues map[string]ReferenceTypeValueMap
|
||||
|
||||
// a map of just the top level dependencies of the CurrentMod, keyed my full mod DepdencyName (with no version)
|
||||
topLevelDependencyMods modconfig.ModMap
|
||||
}
|
||||
@@ -82,11 +84,11 @@ func NewModParseContext(workspaceLock *versionmap.WorkspaceLock, rootEvalPath st
|
||||
Flags: flags,
|
||||
WorkspaceLock: workspaceLock,
|
||||
ListOptions: listOptions,
|
||||
loadedDependencyMods: make(modconfig.ModMap),
|
||||
LoadedDependencyMods: make(modconfig.ModMap),
|
||||
|
||||
blockChildMap: make(map[string][]string),
|
||||
blockNameMap: make(map[string]string),
|
||||
// initialise variable maps - even though we later overwrite them
|
||||
// initialise reference maps - even though we later overwrite them
|
||||
Variables: make(map[string]*modconfig.Variable),
|
||||
referenceValues: map[string]ReferenceTypeValueMap{
|
||||
"local": make(ReferenceTypeValueMap),
|
||||
@@ -99,6 +101,23 @@ func NewModParseContext(workspaceLock *versionmap.WorkspaceLock, rootEvalPath st
|
||||
return c
|
||||
}
|
||||
|
||||
func NewChildModParseContext(parent *ModParseContext, rootEvalPath string) *ModParseContext {
|
||||
// create a child run context
|
||||
child := NewModParseContext(
|
||||
parent.WorkspaceLock,
|
||||
rootEvalPath,
|
||||
parent.Flags,
|
||||
parent.ListOptions)
|
||||
// copy our block tpyes
|
||||
child.BlockTypes = parent.BlockTypes
|
||||
// set the child's parent
|
||||
child.ParentParseCtx = parent
|
||||
// copy DependencyVariables
|
||||
child.DependencyVariables = parent.DependencyVariables
|
||||
|
||||
return child
|
||||
}
|
||||
|
||||
func (m *ModParseContext) EnsureWorkspaceLock(mod *modconfig.Mod) error {
|
||||
// if the mod has dependencies, there must a workspace lock object in the run context
|
||||
// (mod MUST be the workspace mod, not a dependency, as we would hit this error as soon as we parse it)
|
||||
@@ -127,8 +146,8 @@ func (m *ModParseContext) PeekParent() string {
|
||||
return m.parents[len(m.parents)-1]
|
||||
}
|
||||
|
||||
// VariableValueMap converts a map of variables to a map of the underlying cty value
|
||||
func VariableValueMap(variables map[string]*modconfig.Variable) map[string]cty.Value {
|
||||
// VariableValueCtyMap converts a map of variables to a map of the underlying cty value
|
||||
func VariableValueCtyMap(variables map[string]*modconfig.Variable) map[string]cty.Value {
|
||||
ret := make(map[string]cty.Value, len(variables))
|
||||
for k, v := range variables {
|
||||
ret[k] = v.Value
|
||||
@@ -139,57 +158,77 @@ func VariableValueMap(variables map[string]*modconfig.Variable) map[string]cty.V
|
||||
// AddInputVariables adds variables to the run context.
|
||||
// This function is called for the root run context after loading all input variables
|
||||
func (m *ModParseContext) AddInputVariables(inputVariables *modconfig.ModVariableMap) {
|
||||
m.setRootVariables(inputVariables.RootVariables)
|
||||
m.setDependencyVariables(inputVariables.DependencyVariables)
|
||||
// store the variables
|
||||
m.Variables = inputVariables.RootVariables
|
||||
// store the depdency variables sop we can pass them down to our children
|
||||
m.DependencyVariables = inputVariables.DependencyVariables
|
||||
}
|
||||
|
||||
// SetVariablesForDependencyMod adds variables to the run context.
|
||||
// This function is called for dependent mod run context
|
||||
func (m *ModParseContext) SetVariablesForDependencyMod(mod *modconfig.Mod, dependencyVariablesMap map[string]map[string]*modconfig.Variable) {
|
||||
m.setRootVariables(dependencyVariablesMap[mod.ShortName])
|
||||
m.setDependencyVariables(dependencyVariablesMap)
|
||||
func (m *ModParseContext) AddVariablesToReferenceMap() {
|
||||
m.addRootVariablesToReferenceMap(m.Variables)
|
||||
m.addDependencyVariablesToReferenceMap()
|
||||
// NOTE: we do not rebuild the eval context here as in practice, buildEvalContext will be called after the
|
||||
// mod definition is parsed
|
||||
}
|
||||
|
||||
// setRootVariables sets the Variables property
|
||||
// addRootVariablesToReferenceMap sets the Variables property
|
||||
// and adds the variables to the referenceValues map (used to build the eval context)
|
||||
func (m *ModParseContext) setRootVariables(variables map[string]*modconfig.Variable) {
|
||||
m.Variables = variables
|
||||
func (m *ModParseContext) addRootVariablesToReferenceMap(variables map[string]*modconfig.Variable) {
|
||||
|
||||
// write local variables directly into referenceValues map
|
||||
// NOTE: we add with the name "var" not "variable" as that is how variables are referenced
|
||||
m.referenceValues["local"]["var"] = VariableValueMap(variables)
|
||||
m.referenceValues["local"]["var"] = VariableValueCtyMap(variables)
|
||||
}
|
||||
|
||||
// setDependencyVariables sets the DependencyVariables property
|
||||
// and adds the dependency variables to the referenceValues map (used to build the eval context
|
||||
func (m *ModParseContext) setDependencyVariables(dependencyVariables map[string]map[string]*modconfig.Variable) {
|
||||
m.DependencyVariables = dependencyVariables
|
||||
// addDependencyVariablesToReferenceMap sets the DependencyVariables property
|
||||
// and adds the dependency variables to the referenceValues map (used to build the eval context)
|
||||
func (m *ModParseContext) addDependencyVariablesToReferenceMap() {
|
||||
currentModKey := m.CurrentMod.GetInstallCacheKey()
|
||||
topLevelDependencies := m.WorkspaceLock.InstallCache[currentModKey]
|
||||
|
||||
// convert topLevelDependencies into as map keyed by depdency path
|
||||
topLevelDependencyPathMap := topLevelDependencies.ToDependencyPathMap()
|
||||
// NOTE: we add with the name "var" not "variable" as that is how variables are referenced
|
||||
// add top level variables
|
||||
// add dependency mod variables, scoped by mod name
|
||||
// add dependency mod variables to dependencyVariableValues, scoped by DependencyPath
|
||||
for depModName, depVars := range m.DependencyVariables {
|
||||
// create map for this dependency if needed
|
||||
if m.referenceValues[depModName] == nil {
|
||||
m.referenceValues[depModName] = make(ReferenceTypeValueMap)
|
||||
// only add variables from top level dependencies
|
||||
if _, ok := topLevelDependencyPathMap[depModName]; ok {
|
||||
// create map for this dependency if needed
|
||||
alias := topLevelDependencyPathMap[depModName]
|
||||
if m.referenceValues[alias] == nil {
|
||||
m.referenceValues[alias] = make(ReferenceTypeValueMap)
|
||||
}
|
||||
m.referenceValues[alias]["var"] = VariableValueCtyMap(depVars)
|
||||
}
|
||||
m.referenceValues[depModName]["var"] = VariableValueMap(depVars)
|
||||
}
|
||||
}
|
||||
|
||||
// AddMod is used to add a mod to the eval context
|
||||
func (m *ModParseContext) AddMod(mod *modconfig.Mod) hcl.Diagnostics {
|
||||
// AddModResources is used to add mod resources to the eval context
|
||||
func (m *ModParseContext) AddModResources(mod *modconfig.Mod) hcl.Diagnostics {
|
||||
if len(m.UnresolvedBlocks) > 0 {
|
||||
// should never happen
|
||||
panic("calling SetContent on runContext but there are unresolved blocks from a previous parse")
|
||||
panic("calling AddModResources on ModParseContext but there are unresolved blocks from a previous parse")
|
||||
}
|
||||
|
||||
var diags hcl.Diagnostics
|
||||
|
||||
moreDiags := m.storeResourceInCtyMap(mod)
|
||||
moreDiags := m.storeResourceInReferenceValueMap(mod)
|
||||
diags = append(diags, moreDiags...)
|
||||
|
||||
// do not add variables (as they have already been added)
|
||||
// if the resource is for a dependency mod, do not add locals
|
||||
shouldAdd := func(item modconfig.HclResource) bool {
|
||||
if item.BlockType() == modconfig.BlockTypeVariable ||
|
||||
item.BlockType() == modconfig.BlockTypeLocals && item.(modconfig.ModTreeItem).GetMod().ShortName != m.CurrentMod.ShortName {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
resourceFunc := func(item modconfig.HclResource) (bool, error) {
|
||||
// add all mod resources except variables into cty map
|
||||
if _, ok := item.(*modconfig.Variable); !ok {
|
||||
moreDiags := m.storeResourceInCtyMap(item)
|
||||
// add all mod resources (except those excluded) into cty map
|
||||
if shouldAdd(item) {
|
||||
moreDiags := m.storeResourceInReferenceValueMap(item)
|
||||
diags = append(diags, moreDiags...)
|
||||
}
|
||||
// continue walking
|
||||
@@ -234,9 +273,9 @@ func (m *ModParseContext) CreatePseudoResources() bool {
|
||||
return m.Flags&CreatePseudoResources == CreatePseudoResources
|
||||
}
|
||||
|
||||
// AddResource stores this resource as a variable to be added to the eval context. It alse
|
||||
// AddResource stores this resource as a variable to be added to the eval context.
|
||||
func (m *ModParseContext) AddResource(resource modconfig.HclResource) hcl.Diagnostics {
|
||||
diagnostics := m.storeResourceInCtyMap(resource)
|
||||
diagnostics := m.storeResourceInReferenceValueMap(resource)
|
||||
if diagnostics.HasErrors() {
|
||||
return diagnostics
|
||||
}
|
||||
@@ -258,7 +297,7 @@ func (m *ModParseContext) GetMod(modShortName string) *modconfig.Mod {
|
||||
key := m.CurrentMod.GetInstallCacheKey()
|
||||
deps := m.WorkspaceLock.InstallCache[key]
|
||||
for _, dep := range deps {
|
||||
depMod, ok := m.loadedDependencyMods[dep.DependencyPath()]
|
||||
depMod, ok := m.LoadedDependencyMods[dep.DependencyPath()]
|
||||
if ok && depMod.ShortName == modShortName {
|
||||
return depMod
|
||||
}
|
||||
@@ -287,16 +326,16 @@ func (m *ModParseContext) GetResource(parsedName *modconfig.ParsedResourceName)
|
||||
return m.GetResourceMaps().GetResource(parsedName)
|
||||
}
|
||||
|
||||
// eval functions
|
||||
// build the eval context from the cached reference values
|
||||
func (m *ModParseContext) buildEvalContext() {
|
||||
// convert variables to cty values
|
||||
variables := make(map[string]cty.Value)
|
||||
// convert reference values to cty objects
|
||||
referenceValues := make(map[string]cty.Value)
|
||||
|
||||
// now for each mod add all the values
|
||||
for mod, modMap := range m.referenceValues {
|
||||
if mod == "local" {
|
||||
for k, v := range modMap {
|
||||
variables[k] = cty.ObjectVal(v)
|
||||
referenceValues[k] = cty.ObjectVal(v)
|
||||
}
|
||||
continue
|
||||
}
|
||||
@@ -304,18 +343,25 @@ func (m *ModParseContext) buildEvalContext() {
|
||||
// mod map is map[string]map[string]cty.Value
|
||||
// for each element (i.e. map[string]cty.Value) convert to cty object
|
||||
refTypeMap := make(map[string]cty.Value)
|
||||
for refType, typeValueMap := range modMap {
|
||||
refTypeMap[refType] = cty.ObjectVal(typeValueMap)
|
||||
if mod == "local" {
|
||||
for k, v := range modMap {
|
||||
referenceValues[k] = cty.ObjectVal(v)
|
||||
}
|
||||
} else {
|
||||
for refType, typeValueMap := range modMap {
|
||||
refTypeMap[refType] = cty.ObjectVal(typeValueMap)
|
||||
}
|
||||
}
|
||||
// now convert the cty map to a cty object
|
||||
variables[mod] = cty.ObjectVal(refTypeMap)
|
||||
// now convert the referenceValues itself to a cty object
|
||||
referenceValues[mod] = cty.ObjectVal(refTypeMap)
|
||||
}
|
||||
|
||||
m.ParseContext.buildEvalContext(variables)
|
||||
// rebuild the eval context
|
||||
m.ParseContext.buildEvalContext(referenceValues)
|
||||
}
|
||||
|
||||
// update the cached cty value for the given resource, as long as itr does not already exist
|
||||
func (m *ModParseContext) storeResourceInCtyMap(resource modconfig.HclResource) hcl.Diagnostics {
|
||||
// store the resource as a cty value in the reference valuemap
|
||||
func (m *ModParseContext) storeResourceInReferenceValueMap(resource modconfig.HclResource) hcl.Diagnostics {
|
||||
// add resource to variable map
|
||||
ctyValue, diags := m.getResourceCtyValue(resource)
|
||||
if diags.HasErrors() {
|
||||
@@ -333,6 +379,7 @@ func (m *ModParseContext) storeResourceInCtyMap(resource modconfig.HclResource)
|
||||
return nil
|
||||
}
|
||||
|
||||
// convert a HclResource into a cty value, taking into account nested structs
|
||||
func (m *ModParseContext) getResourceCtyValue(resource modconfig.HclResource) (cty.Value, hcl.Diagnostics) {
|
||||
ctyValue, err := resource.(modconfig.CtyValueProvider).CtyValue()
|
||||
if err != nil {
|
||||
@@ -419,8 +466,16 @@ func (m *ModParseContext) addReferenceValue(resource modconfig.HclResource, valu
|
||||
key := parsedName.Name
|
||||
typeString := parsedName.ItemType
|
||||
|
||||
// the resource name will not have a mod - but the run context knows which mod we are parsing
|
||||
mod := m.CurrentMod
|
||||
// most resources will have a mod property - use this if available
|
||||
var mod *modconfig.Mod
|
||||
if modTreeItem, ok := resource.(modconfig.ModTreeItem); ok {
|
||||
mod = modTreeItem.GetMod()
|
||||
}
|
||||
// fall back to current mod
|
||||
if mod == nil {
|
||||
mod = m.CurrentMod
|
||||
}
|
||||
|
||||
modName := mod.ShortName
|
||||
if mod.ModPath == m.RootEvalPath {
|
||||
modName = "local"
|
||||
@@ -466,7 +521,7 @@ func (m *ModParseContext) GetLoadedDependencyMod(requiredModVersion *modconfig.M
|
||||
return nil, fmt.Errorf("not all dependencies are installed - run 'steampipe mod install'")
|
||||
}
|
||||
// use the full name of the locked version as key
|
||||
d, _ := m.loadedDependencyMods[lockedVersion.FullName()]
|
||||
d, _ := m.LoadedDependencyMods[lockedVersion.FullName()]
|
||||
return d, nil
|
||||
}
|
||||
|
||||
@@ -475,7 +530,7 @@ func (m *ModParseContext) AddLoadedDependencyMod(mod *modconfig.Mod) {
|
||||
if mod.DependencyPath == nil {
|
||||
return
|
||||
}
|
||||
m.loadedDependencyMods[*mod.DependencyPath] = mod
|
||||
m.LoadedDependencyMods[*mod.DependencyPath] = mod
|
||||
}
|
||||
|
||||
// GetTopLevelDependencyMods build a mod map of top level loaded dependencies, keyed by mod name
|
||||
@@ -492,7 +547,7 @@ func (m *ModParseContext) GetTopLevelDependencyMods() modconfig.ModMap {
|
||||
// merge in the dependency mods
|
||||
for _, dep := range deps {
|
||||
key := dep.DependencyPath()
|
||||
loadedDepMod := m.loadedDependencyMods[key]
|
||||
loadedDepMod := m.LoadedDependencyMods[key]
|
||||
if loadedDepMod != nil {
|
||||
// as key use the ModDependencyPath _without_ the version
|
||||
m.topLevelDependencyMods[loadedDepMod.DependencyName] = loadedDepMod
|
||||
@@ -500,3 +555,17 @@ func (m *ModParseContext) GetTopLevelDependencyMods() modconfig.ModMap {
|
||||
}
|
||||
return m.topLevelDependencyMods
|
||||
}
|
||||
|
||||
func (m *ModParseContext) SetCurrentMod(mod *modconfig.Mod) {
|
||||
m.CurrentMod = mod
|
||||
|
||||
// if the current mod is a dependency mod (i.e. has a DependencyPath property set), update the Variables property
|
||||
if dependencyVariables, ok := m.DependencyVariables[mod.GetInstallCacheKey()]; ok {
|
||||
m.Variables = dependencyVariables
|
||||
}
|
||||
// set the root variables from the parent
|
||||
// now the mod is set we can add variables to the reference map
|
||||
// ( we cannot do this until mod as set as we need to identify which variables to use if we are a dependency
|
||||
m.AddVariablesToReferenceMap()
|
||||
m.buildEvalContext()
|
||||
}
|
||||
|
||||
@@ -177,7 +177,7 @@ func ParseMod(fileData map[string][]byte, pseudoResources []modconfig.MappableRe
|
||||
return nil, modconfig.NewErrorsAndWarning(err)
|
||||
}
|
||||
|
||||
// if variables were passed in runcontext, add to the mod
|
||||
// if variables were passed in parsecontext, add to the mod
|
||||
for _, v := range parseCtx.Variables {
|
||||
if diags = mod.AddResource(v); diags.HasErrors() {
|
||||
return nil, modconfig.NewErrorsAndWarning(plugin.DiagsToError("Failed to add resource to mod", diags))
|
||||
@@ -192,7 +192,7 @@ func ParseMod(fileData map[string][]byte, pseudoResources []modconfig.MappableRe
|
||||
|
||||
// add the mod to the run context
|
||||
// - this it to ensure all pseudo resources get added and build the eval context with the variables we just added
|
||||
if diags = parseCtx.AddMod(mod); diags.HasErrors() {
|
||||
if diags = parseCtx.AddModResources(mod); diags.HasErrors() {
|
||||
return nil, modconfig.NewErrorsAndWarning(plugin.DiagsToError("Failed to add mod to run context", diags))
|
||||
}
|
||||
|
||||
@@ -219,7 +219,7 @@ func ParseMod(fileData map[string][]byte, pseudoResources []modconfig.MappableRe
|
||||
// if the number of unresolved blocks has NOT reduced, fail
|
||||
if prevUnresolvedBlocks != 0 && unresolvedBlocks >= prevUnresolvedBlocks {
|
||||
str := parseCtx.FormatDependencies()
|
||||
return nil, modconfig.NewErrorsAndWarning(fmt.Errorf("failed to resolve mod dependencies after %d attempts\nDependencies:\n%s", attempts+1, str))
|
||||
return nil, modconfig.NewErrorsAndWarning(fmt.Errorf("failed to resolve dependencies for mod '%s' after %d attempts\nDependencies:\n%s", mod.FullName, attempts+1, str))
|
||||
}
|
||||
// update prevUnresolvedBlocks
|
||||
prevUnresolvedBlocks = unresolvedBlocks
|
||||
|
||||
@@ -19,3 +19,12 @@ func (m ResolvedVersionMap) ToVersionListMap() ResolvedVersionListMap {
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// ToDependencyPathMap converts to a map of mod aliases, keyed by mod dependency path
|
||||
func (m ResolvedVersionMap) ToDependencyPathMap() map[string]string {
|
||||
res := make(map[string]string, len(m))
|
||||
for _, c := range m {
|
||||
res[c.DependencyPath()] = c.Alias
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ var steampipeVersion = "0.20.0"
|
||||
// A pre-release marker for the version. If this is "" (empty string)
|
||||
// then it means that it is a final release. Otherwise, this is a pre-release
|
||||
// such as "dev" (in development), "beta", "rc1", etc.
|
||||
var prerelease = "alpha.3"
|
||||
var prerelease = "alpha.4"
|
||||
|
||||
// SteampipeVersion is an instance of semver.Version. This has the secondary
|
||||
// benefit of verifying during tests and init time that our version is a
|
||||
|
||||
@@ -259,7 +259,7 @@ func (w *Workspace) loadWorkspaceMod(ctx context.Context) *modconfig.ErrorAndWar
|
||||
if err != nil {
|
||||
return modconfig.NewErrorsAndWarning(err)
|
||||
}
|
||||
// add variables to runContext
|
||||
// add variables
|
||||
parseCtx.AddInputVariables(inputVariables)
|
||||
// do not reload variables as we already have them
|
||||
parseCtx.BlockTypeExclusions = []string{modconfig.BlockTypeVariable}
|
||||
|
||||
Reference in New Issue
Block a user