Skip to content

Commit

Permalink
#53: Improve --list-impacted option
Browse files Browse the repository at this point in the history
  • Loading branch information
iignatevich committed Nov 1, 2024
1 parent d3b9111 commit 8e6c626
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 56 deletions.
76 changes: 43 additions & 33 deletions actionSync.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ func (s *SyncAction) propagate(modifiedFiles []string) error {
}

if s.listImpacted {
s.printResources("List of impacted resources:", toPropagate)
s.showImpacted(inv, timeline, toPropagate)
}

// update resources.
Expand Down Expand Up @@ -844,7 +844,7 @@ func (s *SyncAction) buildPropagationMap(buildInv *sync.Inventory, timeline []sy
}

launchr.Term().Info().Printfln("Collecting %s dependencies:", r.GetName())
err := s.propagateResourceDeps(r, i.GetVersion(), toPropagate, buildInv.GetRequiredMap(), resourceVersionMap)
err := s.propagateResourceDeps(r, i.GetVersion(), toPropagate, buildInv.GetRequiredByMap(), resourceVersionMap)
if err != nil {
return toPropagate, resourceVersionMap, err
}
Expand Down Expand Up @@ -883,7 +883,7 @@ func (s *SyncAction) buildPropagationMap(buildInv *sync.Inventory, timeline []sy
continue
}

s.propagateDepsRecursively(r, version, toPropagate, buildInv.GetRequiredMap(), resourceVersionMap)
s.propagateDepsRecursively(r, version, toPropagate, buildInv.GetRequiredByMap(), resourceVersionMap)
}
}
}
Expand Down Expand Up @@ -922,6 +922,46 @@ func (s *SyncAction) copyHistory(history *sync.OrderedMap[*sync.Resource]) error
return nil
}

func (s *SyncAction) showImpacted(inv *sync.Inventory, timeline []sync.TimelineItem, propagated *sync.OrderedMap[*sync.Resource]) {
result := sync.NewOrderedMap[bool]()

for _, item := range timeline {
switch i := item.(type) {
case *sync.TimelineResourcesItem:
resources := i.GetResources()
iterateTimelineItem:
for _, mrn := range resources.Keys() {
deps := inv.GetRequiredByResources(mrn, -1)
for d := range deps {
if _, ok := propagated.Get(d); ok {
continue iterateTimelineItem
}
}

result.Set(mrn, true)
}
}
}

iteratePropagate:
for _, mrn := range propagated.Keys() {
deps := inv.GetRequiredByResources(mrn, -1)
for d := range deps {
if _, ok := propagated.Get(d); ok {
continue iteratePropagate
}
}

result.Set(mrn, true)
}
result.OrderBy(inv.GetResourcesOrder())

launchr.Term().Info().Printf("List of impacted resources:\n")
for _, k := range result.Keys() {
launchr.Term().Printf(k + "\n")
}
}

func (s *SyncAction) updateResources(toPropagate *sync.OrderedMap[*sync.Resource], resourceVersionMap map[string]string) error {
var sortList []string
updateMap := make(map[string]map[string]string)
Expand Down Expand Up @@ -988,36 +1028,6 @@ func (s *SyncAction) updateResources(toPropagate *sync.OrderedMap[*sync.Resource
return nil
}

func (s *SyncAction) printResources(message string, resources *sync.OrderedMap[*sync.Resource]) {
if message != "" {
launchr.Term().Info().Println(message)
}

for _, key := range resources.Keys() {
value, _ := resources.Get(key)
launchr.Term().Printfln("- %s", value.GetName())
}
}

//
//func (s *SyncAction) printVariablesInfo(rvm map[string]map[string]bool) {
// if len(rvm) == 0 {
// return
// }
//
// info := make(map[string][]string)
// for resourceName, vars := range rvm {
// for variable := range vars {
// info[variable] = append(info[variable], resourceName)
// }
// }
//
// log.Info("Modified variables in diff (group_vars and vaults):")
// for k, v := range info {
// log.Info("- %s used in: %s", k, strings.Join(v, ", "))
// }
//}

func (s *SyncAction) propagateResourceDeps(resource *sync.Resource, version string, toPropagate *sync.OrderedMap[*sync.Resource], resourcesGraph map[string]*sync.OrderedMap[bool], resourceVersionMap map[string]string) error {
if itemsMap, ok := resourcesGraph[resource.GetName()]; ok {
itemsMap.SortKeysAlphabetically()
Expand Down
79 changes: 56 additions & 23 deletions pkg/sync/inventory.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,9 @@ type Inventory struct {
ResourcesCrawler *ResourcesCrawler

//internal
resourcesMap *OrderedMap[bool]
requiredMap map[string]*OrderedMap[bool]
dependencyMap map[string]*OrderedMap[bool]
resourcesMap *OrderedMap[bool]
requiredBy map[string]*OrderedMap[bool]
dependsOn map[string]*OrderedMap[bool]

// options
sourceDir string
Expand All @@ -112,8 +112,8 @@ func NewInventory(sourceDir string) (*Inventory, error) {
sourceDir: sourceDir,
ResourcesCrawler: NewResourcesCrawler(sourceDir),
resourcesMap: NewOrderedMap[bool](),
requiredMap: make(map[string]*OrderedMap[bool]),
dependencyMap: make(map[string]*OrderedMap[bool]),
requiredBy: make(map[string]*OrderedMap[bool]),
dependsOn: make(map[string]*OrderedMap[bool]),
}

err := inv.Init()
Expand All @@ -138,16 +138,14 @@ func (i *Inventory) GetResourcesOrder() []string {
return i.resourcesMap.Keys()
}

// GetRequiredMap returns the required map, which represents the dependencies between resources in the Inventory.
// The map is of type `map[string]map[string]bool`, where the keys are the resource names and the values are maps of dependent resource names.
func (i *Inventory) GetRequiredMap() map[string]*OrderedMap[bool] {
return i.requiredMap
// GetRequiredByMap returns the required by map, which represents the `required by` dependencies between resources in the Inventory.
func (i *Inventory) GetRequiredByMap() map[string]*OrderedMap[bool] {
return i.requiredBy
}

// GetDependenciesMap returns the map, which represents the dependencies between resources in the Inventory.
// The map is of type `map[string]map[string]bool`, where the keys are the resource names and the values are maps of dependent resource names.
func (i *Inventory) GetDependenciesMap() map[string]*OrderedMap[bool] {
return i.dependencyMap
// GetDependsOnMap returns the map, which represents the 'depends on' dependencies between resources in the Inventory.
func (i *Inventory) GetDependsOnMap() map[string]*OrderedMap[bool] {
return i.dependsOn
}

func (i *Inventory) buildResourcesGraph() error {
Expand Down Expand Up @@ -208,19 +206,19 @@ func (i *Inventory) buildResourcesGraph() error {
return nil
}

if i.dependencyMap[resourceName] == nil {
i.dependencyMap[resourceName] = NewOrderedMap[bool]()
if i.dependsOn[resourceName] == nil {
i.dependsOn[resourceName] = NewOrderedMap[bool]()
}

for _, dep := range deps {
if dep.IncludeRole.Name != "" {
depName := strings.ReplaceAll(dep.IncludeRole.Name, ".", "__")
if i.requiredMap[depName] == nil {
i.requiredMap[depName] = NewOrderedMap[bool]()
if i.requiredBy[depName] == nil {
i.requiredBy[depName] = NewOrderedMap[bool]()
}

i.requiredMap[depName].Set(resourceName, true)
i.dependencyMap[resourceName].Set(depName, true)
i.requiredBy[depName].Set(resourceName, true)
i.dependsOn[resourceName].Set(depName, true)
}
}
}
Expand All @@ -232,15 +230,15 @@ func (i *Inventory) buildResourcesGraph() error {
}

platformItems := NewOrderedMap[bool]()
for resourceName := range i.requiredMap {
if _, ok := i.dependencyMap[resourceName]; !ok {
for resourceName := range i.requiredBy {
if _, ok := i.dependsOn[resourceName]; !ok {
platformItems.Set(resourceName, true)
}
}

i.requiredMap[rootPlatform] = platformItems
i.requiredBy[rootPlatform] = platformItems
graph := topsort.NewGraph()
for platform, resources := range i.requiredMap {
for platform, resources := range i.requiredBy {
for _, resource := range resources.Keys() {
graph.AddNode(resource)
edgeErr := graph.AddEdge(platform, resource)
Expand Down Expand Up @@ -491,6 +489,41 @@ func (i *Inventory) SearchVariablesAffectedResources(variables []*Variable) (*Or
return resources, resourceVariablesMap, nil
}

// GetRequiredByResources returns list of resources which depend on argument resource (directly or not).
func (i *Inventory) GetRequiredByResources(resourceName string, depth int8) map[string]bool {
return i.lookupDependencies(resourceName, i.GetRequiredByMap(), depth)
}

// GetDependsOnResources returns list of resources which are used by argument resource (directly or not).
func (i *Inventory) GetDependsOnResources(resourceName string, depth int8) map[string]bool {
return i.lookupDependencies(resourceName, i.GetDependsOnMap(), depth)
}

func (i *Inventory) lookupDependencies(resourceName string, resourcesMap map[string]*OrderedMap[bool], depth int8) map[string]bool {
result := make(map[string]bool)
if m, ok := resourcesMap[resourceName]; ok {
for _, item := range m.Keys() {
result[item] = true
i.lookupDependenciesRecursively(item, resourcesMap, result, 1, depth)
}
}

return result
}

func (i *Inventory) lookupDependenciesRecursively(resourceName string, resourcesMap map[string]*OrderedMap[bool], result map[string]bool, depth, limit int8) {
if depth == limit {
return
}

if m, ok := resourcesMap[resourceName]; ok {
for _, item := range m.Keys() {
result[item] = true
i.lookupDependenciesRecursively(item, resourcesMap, result, depth+1, limit)
}
}
}

func (i *Inventory) pushRequiredVariables(requiredMap map[string]map[string]bool) {
for k, v := range requiredMap {
for name := range v {
Expand Down

0 comments on commit 8e6c626

Please sign in to comment.