diff --git a/pkg/control/init_data.go b/pkg/control/init_data.go index 585483c6d..37662456a 100644 --- a/pkg/control/init_data.go +++ b/pkg/control/init_data.go @@ -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 { diff --git a/pkg/dashboard/dashboardexecute/referenced_variables.go b/pkg/dashboard/dashboardexecute/referenced_variables.go index 7e359df29..049f01c8e 100644 --- a/pkg/dashboard/dashboardexecute/referenced_variables.go +++ b/pkg/dashboard/dashboardexecute/referenced_variables.go @@ -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. // . // the VariableValues map will contain these variables with the name format .var., // 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) diff --git a/pkg/steampipeconfig/load_mod.go b/pkg/steampipeconfig/load_mod.go index ec71dbac3..cbc5bf250 100644 --- a/pkg/steampipeconfig/load_mod.go +++ b/pkg/steampipeconfig/load_mod.go @@ -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 } diff --git a/pkg/steampipeconfig/load_mod_variables.go b/pkg/steampipeconfig/load_mod_variables.go index 988d337db..7c592755d 100644 --- a/pkg/steampipeconfig/load_mod_variables.go +++ b/pkg/steampipeconfig/load_mod_variables.go @@ -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 } diff --git a/pkg/steampipeconfig/modconfig/mod_variable_map.go b/pkg/steampipeconfig/modconfig/mod_variable_map.go index 31d07a162..3b5401766 100644 --- a/pkg/steampipeconfig/modconfig/mod_variable_map.go +++ b/pkg/steampipeconfig/modconfig/mod_variable_map.go @@ -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 diff --git a/pkg/steampipeconfig/parse/mod_parse_context.go b/pkg/steampipeconfig/parse/mod_parse_context.go index fbc605710..19eeb93bc 100644 --- a/pkg/steampipeconfig/parse/mod_parse_context.go +++ b/pkg/steampipeconfig/parse/mod_parse_context.go @@ -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() +} diff --git a/pkg/steampipeconfig/parse/parser.go b/pkg/steampipeconfig/parse/parser.go index dcc60c2dd..3152f398a 100644 --- a/pkg/steampipeconfig/parse/parser.go +++ b/pkg/steampipeconfig/parse/parser.go @@ -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 diff --git a/pkg/steampipeconfig/versionmap/resolved_version_map.go b/pkg/steampipeconfig/versionmap/resolved_version_map.go index 8291bed6b..e1c7c8440 100644 --- a/pkg/steampipeconfig/versionmap/resolved_version_map.go +++ b/pkg/steampipeconfig/versionmap/resolved_version_map.go @@ -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 +} diff --git a/pkg/version/version.go b/pkg/version/version.go index 15e14d621..86fb3d54f 100644 --- a/pkg/version/version.go +++ b/pkg/version/version.go @@ -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 diff --git a/pkg/workspace/workspace.go b/pkg/workspace/workspace.go index 7187b7b5d..0ab452299 100644 --- a/pkg/workspace/workspace.go +++ b/pkg/workspace/workspace.go @@ -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}