Files
kubescape/core/pkg/fixhandler/datastructures.go
David Wertenteil 3e2314a269 Bump v3 (#1449)
* bump version

Signed-off-by: David Wertenteil <dwertent@armosec.io>

* change default view

Signed-off-by: David Wertenteil <dwertent@armosec.io>

* fixed tests

Signed-off-by: David Wertenteil <dwertent@armosec.io>

* fixed go mod

Signed-off-by: David Wertenteil <dwertent@armosec.io>

---------

Signed-off-by: David Wertenteil <dwertent@armosec.io>
2023-10-22 17:43:51 +03:00

110 lines
3.0 KiB
Go

package fixhandler
import (
"sort"
"strings"
"github.com/armosec/armoapi-go/armotypes"
metav1 "github.com/kubescape/kubescape/v3/core/meta/datastructures/v1"
"github.com/kubescape/opa-utils/reporthandling"
reporthandlingv2 "github.com/kubescape/opa-utils/reporthandling/v2"
"gopkg.in/yaml.v3"
)
// FixHandler is a struct that holds the information of the report to be fixed
type FixHandler struct {
fixInfo *metav1.FixInfo
reportObj *reporthandlingv2.PostureReport
localBasePath string
}
// ResourceFixInfo is a struct that holds the information about the resource that needs to be fixed
type ResourceFixInfo struct {
YamlExpressions map[string]armotypes.FixPath
Resource *reporthandling.Resource
FilePath string
DocumentIndex int
}
// NodeInfo holds extra information about the node
type nodeInfo struct {
node *yaml.Node
parent *yaml.Node
// position of the node among siblings
index int
}
// FixInfoMetadata holds the arguments "getFixInfo" function needs to pass to the
// functions it uses
type fixInfoMetadata struct {
originalList *[]nodeInfo
fixedList *[]nodeInfo
originalListTracker int
fixedListTracker int
contentToAdd *[]contentToAdd
linesToRemove *[]linesToRemove
}
// contentToAdd holds the information about where to insert the new changes in the existing yaml file
type contentToAdd struct {
// Line where the fix should be applied to
line int
// Content is a string representation of the YAML node that describes a suggested fix
content string
}
func withNewline(content, targetNewline string) string {
replaceNewlines := map[string]bool{
unixNewline: true,
windowsNewline: true,
oldMacNewline: true,
}
replaceNewlines[targetNewline] = false
newlinesToReplace := make([]string, len(replaceNewlines))
i := 0
for k := range replaceNewlines {
newlinesToReplace[i] = k
i++
}
// To ensure that we fully replace Windows newlines (CR LF), and not
// corrupt them into two new newlines (CR CR or LF LF) by partially
// replacing either CR or LF, we have to ensure we replace longer
// Windows newlines first
sort.Slice(newlinesToReplace, func(i int, j int) bool {
return len(newlinesToReplace[i]) > len(newlinesToReplace[j])
})
// strings.Replacer takes a flat list of (oldVal, newVal) pairs, so we
// need to allocate twice the space and assign accordingly
newlinesOldNew := make([]string, 2*len(replaceNewlines))
i = 0
for _, nl := range newlinesToReplace {
newlinesOldNew[2*i] = nl
newlinesOldNew[2*i+1] = targetNewline
i++
}
replacer := strings.NewReplacer(newlinesOldNew...)
return replacer.Replace(content)
}
// Content returns the content that will be added, separated by the explicitly
// provided `targetNewline`
func (c *contentToAdd) Content(targetNewline string) string {
return withNewline(c.content, targetNewline)
}
// LinesToRemove holds the line numbers to remove from the existing yaml file
type linesToRemove struct {
startLine int
endLine int
}
type fileFixInfo struct {
contentsToAdd *[]contentToAdd
linesToRemove *[]linesToRemove
}