Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improved error handling #70

Merged
merged 30 commits into from
Sep 7, 2022
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
51e654a
discoverConnections has no errors to return
zivnevo Aug 23, 2022
72c7c2c
error if parsing k8s object fails
zivnevo Aug 23, 2022
0cc6fcd
Types for reporting file-processing errors
zivnevo Aug 23, 2022
555c61b
Functions to return multiple error objects
zivnevo Aug 23, 2022
eca78b1
unit testing
zivnevo Aug 23, 2022
866bb8e
Merge branch 'main' into improved_error_handling
zivnevo Aug 25, 2022
4fe9786
not exporting parse functions
zivnevo Aug 29, 2022
f1cbaa2
ScanK8sDeployObject -> ScanK8sWorkloadObject
zivnevo Aug 29, 2022
bea96f0
Moving regexs to vars at the top of the file
zivnevo Aug 29, 2022
292ab3a
Moving error type to controller package
zivnevo Aug 29, 2022
dc760f9
discard FileProcessingErrorList
zivnevo Aug 29, 2022
619d6e1
error should not start with a capital letter
zivnevo Aug 29, 2022
31e98d5
Merge branch 'main' into improved_error_handling
zivnevo Aug 30, 2022
331182a
create all error objects in error_types.go
zivnevo Aug 30, 2022
85dced6
DocumentID() returns an error + Location() method
zivnevo Aug 31, 2022
2150312
Work with externally-provided logger
zivnevo Aug 31, 2022
593a495
A missing not
zivnevo Aug 31, 2022
196fa2a
implemented stop-on-first-error option
zivnevo Aug 31, 2022
2c043cc
Merge branch 'improved_error_handling' of github.com:np-guard/cluster…
zivnevo Aug 31, 2022
24c3749
Fix lint issue
zivnevo Aug 31, 2022
61d02ac
report line number when marshaling fails
zivnevo Sep 1, 2022
aba244d
PoliciesFromFolderPath() -> PoliciesSynthesizer
zivnevo Sep 1, 2022
3ff6fd3
Logger.Errorf() takes error as an arg
zivnevo Sep 5, 2022
23af03a
A missing check to stop on first error
zivnevo Sep 5, 2022
946f0ea
Always stop processing on fatal error
zivnevo Sep 5, 2022
b666218
Not assuming a severe error is always last
zivnevo Sep 5, 2022
64f2146
separate logging from custom error interface
zivnevo Sep 5, 2022
7e13a74
not relying on fatal error being the last error
zivnevo Sep 5, 2022
4bca39e
Do not rely on fatal errors to be last
zivnevo Sep 5, 2022
ab39190
Merge branch 'main' into improved_error_handling
zivnevo Sep 7, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions pkg/analyzer/scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ func matchLabelSelectorToStrLabels(labels map[string]string) []string {

func ScanK8sConfigmapObject(kind string, objDataBuf []byte) (common.CfgMap, error) {
obj := ParseConfigMap(bytes.NewReader(objDataBuf))
if obj == nil {
vikin91 marked this conversation as resolved.
Show resolved Hide resolved
return common.CfgMap{}, fmt.Errorf("unable to parse configmap")
}

fullName := obj.ObjectMeta.Namespace + "/" + obj.ObjectMeta.Name
data := map[string]string{}
Expand All @@ -96,6 +99,9 @@ func ScanK8sServiceObject(kind string, objDataBuf []byte) (common.Service, error

var serviceCtx common.Service
svcObj := ParseService(bytes.NewReader(objDataBuf))
if svcObj == nil {
vikin91 marked this conversation as resolved.
Show resolved Hide resolved
return common.Service{}, fmt.Errorf("failed to parse Service resource")
}
serviceCtx.Resource.Name = svcObj.GetName()
serviceCtx.Resource.Namespace = svcObj.Namespace
serviceCtx.Resource.Kind = kind
Expand Down Expand Up @@ -129,8 +135,7 @@ func parseDeployResource(podSpec *v1.PodTemplateSpec, obj metaV1.Object, resourc
}
for _, e := range container.Env {
if e.Value != "" {
isPotentialAddress := IsNetworkAddressValue(e.Value)
if isPotentialAddress {
if IsNetworkAddressValue(e.Value) {
resourceCtx.Resource.Envs = append(resourceCtx.Resource.Envs, e.Value)
}
} else if e.ValueFrom != nil && e.ValueFrom.ConfigMapKeyRef != nil {
Expand Down
46 changes: 46 additions & 0 deletions pkg/common/error_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package common
vikin91 marked this conversation as resolved.
Show resolved Hide resolved

import (
"fmt"
)

type FileProcessingError struct {
Msg string
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest to store the value as an error, because it does not forces the caller to interpret the error in a given way but leaves the freedom of printing the error the way it is actually needed.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

FilePath string
LineNum int
DocID int // the number of YAML document where the error originates from (0-based)
}

func (e *FileProcessingError) Error() string {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Returning string here would not allow the consumer to unwrap errors. Having exported the methods File, LineNo, and DocumentID allows the consumer to craft the string representation of the error message as long as we have the original error, so I would suggest to keep the returned type as error.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

errorMsg := fmt.Sprintf("In file %s", e.FilePath)
if e.LineNum > 0 {
errorMsg += fmt.Sprintf(", line %d", e.LineNum)
}
if e.DocID >= 0 {
errorMsg += fmt.Sprintf(", document %d", e.DocID)
}
errorMsg += fmt.Sprintf(": %s", e.Msg)
return errorMsg
}

func (e *FileProcessingError) File() string {
return e.FilePath
}

func (e *FileProcessingError) LineNo() int {
return e.LineNum
}

func (e *FileProcessingError) DocumentID() int {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We were discussing about returning an error here to mark that the int value should not be treated as valid. Do you think we could introduce this now?

Suggested change
func (e *FileProcessingError) DocumentID() int {
func (e *FileProcessingError) DocumentID() (int, error) {

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

return e.DocID
}

type FileProcessingErrorList []*FileProcessingError

func (e FileProcessingErrorList) Error() string {
errMsg := ""
for _, err := range e {
errMsg += err.Error() + "\n"
}
return errMsg
}
vikin91 marked this conversation as resolved.
Show resolved Hide resolved
10 changes: 3 additions & 7 deletions pkg/controller/connections.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,9 @@ import (
"github.com/np-guard/cluster-topology-analyzer/pkg/common"
)

var debug = false

// This function is at the core of the topology analysis
// For each resource, it finds other resources that may use it and compiles a list of connections holding these dependencies
func discoverConnections(resources []common.Resource, links []common.Service) ([]common.Connections, error) {
func discoverConnections(resources []common.Resource, links []common.Service) []common.Connections {
connections := []common.Connections{}
for destResIdx := range resources {
destRes := &resources[destResIdx]
Expand All @@ -31,7 +29,7 @@ func discoverConnections(resources []common.Resource, links []common.Service) ([
}
}
}
return connections, nil
return connections
}

// areSelectorsContained returns true if selectors2 is contained in selectors1
Expand Down Expand Up @@ -65,9 +63,7 @@ func findServices(resource *common.Resource, links []common.Service) []common.Se
}
}

if debug {
zap.S().Debugf("matched service: %v", matchedSvc)
}
zap.S().Debugf("services matched to %v: %v", resource.Resource.Name, matchedSvc)
return matchedSvc
}

Expand Down
59 changes: 44 additions & 15 deletions pkg/controller/controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ import (
// TestOutput calls controller.Start() with an example repo dir tests/onlineboutique/ ,
// checking for the json output to match expected output at tests/expected_output.json
func TestConnectionsOutput(t *testing.T) {
currentDir, _ := os.Getwd()
dirPath := filepath.Join(currentDir, "..", "..", "tests", "onlineboutique", "kubernetes-manifests.yaml")
outFile := filepath.Join(currentDir, "..", "..", "tests", "onlineboutique", "output.json")
expectedOutput := filepath.Join(currentDir, "..", "..", "tests", "onlineboutique", "expected_output.json")
testsDir := getTestsDir()
dirPath := filepath.Join(testsDir, "onlineboutique", "kubernetes-manifests.yaml")
outFile := filepath.Join(testsDir, "onlineboutique", "output.json")
expectedOutput := filepath.Join(testsDir, "onlineboutique", "expected_output.json")
args := getTestArgs(dirPath, outFile, false)

err := Start(args)
Expand All @@ -40,10 +40,10 @@ func TestConnectionsOutput(t *testing.T) {
}

func TestDirScan(t *testing.T) {
currentDir, _ := os.Getwd()
dirPath := filepath.Join(currentDir, "..", "..", "tests", "onlineboutique")
outFile := filepath.Join(currentDir, "..", "..", "tests", "onlineboutique", "output.json")
expectedOutput := filepath.Join(currentDir, "..", "..", "tests", "onlineboutique", "expected_dirscan_output.json")
testsDir := getTestsDir()
dirPath := filepath.Join(testsDir, "onlineboutique")
outFile := filepath.Join(dirPath, "output.json")
expectedOutput := filepath.Join(dirPath, "expected_dirscan_output.json")
args := getTestArgs(dirPath, outFile, false)

err := Start(args)
Expand All @@ -70,8 +70,7 @@ type TestDetails struct {
}

func TestNetpolsJsonOutput(t *testing.T) {
currentDir, _ := os.Getwd()
testsDir := filepath.Join(currentDir, "..", "..", "tests")
testsDir := getTestsDir()
tests := map[string]TestDetails{} // map from test name to test details
tests["onlineboutique"] = TestDetails{dirPath: filepath.Join(testsDir, "onlineboutique", "kubernetes-manifests.yaml"),
outFile: filepath.Join(testsDir, "onlineboutique", "output.json"),
Expand Down Expand Up @@ -104,15 +103,14 @@ func TestNetpolsJsonOutput(t *testing.T) {
}

func TestNetpolsInterface(t *testing.T) {
currentDir, _ := os.Getwd()
testsDir := filepath.Join(currentDir, "..", "..", "tests")
testsDir := getTestsDir()
dirPath := filepath.Join(testsDir, "onlineboutique", "kubernetes-manifests.yaml")
outFile := filepath.Join(testsDir, "onlineboutique", "output.json")
expectedOutput := filepath.Join(testsDir, "onlineboutique", "expected_netpol_interface_output.json")

netpols, err := PoliciesFromFolderPath(dirPath)
if err != nil {
t.Fatalf("expected err to be nil, but got %v", err)
netpols, fileScanningErrors := PoliciesFromFolderPath(dirPath)
if len(fileScanningErrors) > 0 {
t.Fatalf("expected no file-scanning errors, but got %v", fileScanningErrors)
}
if len(netpols) == 0 {
t.Fatalf("expected policies to be non-empty, but got empty")
Expand All @@ -139,6 +137,32 @@ func TestNetpolsInterface(t *testing.T) {
os.Remove(outFile)
}

func TestExtractConnectionsNoK8sResources(t *testing.T) {
testsDir := getTestsDir()
dirPath := filepath.Join(testsDir, "bad_yamls", "irrelevant_k8s_resources.yaml")
args := getTestArgs(dirPath, "", false)
conns, errs := extractConnections(args)
if len(errs) != 1 {
t.Fatalf("expected one error but got %d", len(errs))
}
if len(conns) > 0 {
t.Fatalf("expected no conns but got %d", len(conns))
}
vikin91 marked this conversation as resolved.
Show resolved Hide resolved
}

func TestExtractConnectionsBadConfigMapRefs(t *testing.T) {
testsDir := getTestsDir()
dirPath := filepath.Join(testsDir, "bad_yamls", "bad_configmap_refs.yaml")
args := getTestArgs(dirPath, "", false)
conns, errs := extractConnections(args)
if len(errs) != 3 {
t.Fatalf("expected 3 errors but got %d", len(errs))
}
if len(conns) > 0 {
t.Fatalf("expected no conns but got %d", len(conns))
}
}

func readLines(path string) ([]string, error) {
file, err := os.Open(path)
if err != nil {
Expand All @@ -154,6 +178,11 @@ func readLines(path string) ([]string, error) {
return lines, scanner.Err()
}

func getTestsDir() string {
currentDir, _ := os.Getwd()
return filepath.Join(currentDir, "..", "..", "tests")
}

func getTestArgs(dirPath, outFile string, netpols bool) common.InArgs {
args := common.InArgs{}
emptyStr := ""
Expand Down
68 changes: 42 additions & 26 deletions pkg/controller/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,15 @@ import (
// (or NetworkPolicies to allow only this connectivity)
func Start(args common.InArgs) error {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI: I am not considering this function as a part of the interface of our focus, but I think, it would be nice that the NP-Guard CLI and roxctl CLI would consume the same exported interface, i.e., PoliciesFromFolderPath. Maybe the function Start could be moved to the CLI-related pkg?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will handle within the context of Issues #81 and #68

// 1. Discover all connections between resources
connections, err := extractConnections(args)
if err != nil {
return err
connections, fileScanErrors := extractConnections(args)
if len(fileScanErrors) > 0 {
return fileScanErrors
}

// 2. Write the output to a file or to stdout
const indent = " "
var buf []byte
var err error
if args.SynthNetpols != nil && *args.SynthNetpols {
buf, err = json.MarshalIndent(synthNetpolList(connections), "", indent)
} else {
Expand Down Expand Up @@ -56,47 +57,44 @@ func Start(args common.InArgs) error {
return nil
}

func PoliciesFromFolderPath(fullTargetPath string) ([]*networking.NetworkPolicy, error) {
func PoliciesFromFolderPath(fullTargetPath string) ([]*networking.NetworkPolicy, common.FileProcessingErrorList) {
vikin91 marked this conversation as resolved.
Show resolved Hide resolved
emptyStr := ""
args := common.InArgs{}
args.DirPath = &fullTargetPath
args.CommitID = &emptyStr
args.GitBranch = &emptyStr
args.GitURL = &emptyStr

connections, err := extractConnections(args)
if err != nil {
return []*networking.NetworkPolicy{}, err
}
return synthNetpols(connections), nil
connections, fileProcessingErrors := extractConnections(args)
return synthNetpols(connections), fileProcessingErrors
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I see this kind of construct, a question arises whether it would make sense to separately expose an API for extracting connections and separately for synthesizing the policies. On the NPG page, these parts are presented graphically as separate modules, so it is a bit surprising to see that the synthesizer is actually an unexported function.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be handled in Issue #75

}

func extractConnections(args common.InArgs) ([]common.Connections, error) {
func extractConnections(args common.InArgs) ([]common.Connections, common.FileProcessingErrorList) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For this function, I have mixed feelings. Here are my thoughts:

  1. Based on the name, it should extract connections out of something. Currently it does it out of common.InArgs, which is not transparent. As it actually uses only args.DirPath, then maybe we could simply pass a string as a parameter?
  2. This function returns file processing errors, but it is meant to extract connections. It feels more natural that this function should return connection-extraction errors.

To solve this, this function would need to be most probably decomposed into smaller parts and composed again. I could imagine (roughly) the following pipeline:

  • read directories and return list of files
  • read file and return yaml documents
  • read yaml document and return k8s resource
  • read a set of k8s resources and return connections

These functions would make the testing much easier and would allow to quickly adapt the behavior of the library to the potential future changes of the interfaces.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issues #81 and #68 should address some of the above concerns

// 1. Get all relevant resources from the repo and parse them
dObjs := getK8sDeploymentResources(args.DirPath)
dObjs, fileErrors := getK8sDeploymentResources(*args.DirPath)
if len(dObjs) == 0 {
msg := "no deployment objects discovered in the repository"
fileErrors = append(fileErrors, &common.FileProcessingError{Msg: msg})
zap.S().Errorf(msg)
return []common.Connections{}, errors.New(msg)
return []common.Connections{}, fileErrors
}
resources, links := parseResources(dObjs, args)
resources, links, parseErrors := parseResources(dObjs, args)
fileErrors = append(fileErrors, parseErrors...)

// 2. Discover all connections between resources
return discoverConnections(resources, links)
return discoverConnections(resources, links), fileErrors
}

func parseResources(objs []parsedK8sObjects, args common.InArgs) ([]common.Resource, []common.Service) {
func parseResources(objs []parsedK8sObjects, args common.InArgs) ([]common.Resource, []common.Service, common.FileProcessingErrorList) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are quite many things happening in this function and it is relatively difficult to follow the data flow. I will try to provide details inline.

resources := []common.Resource{}
links := []common.Service{}
configmaps := map[string]common.CfgMap{} // map from a configmap's full-name to its data
parseErrors := common.FileProcessingErrorList{}
for _, o := range objs {
r, l, c := parseResource(o)
if len(r) != 0 {
resources = append(resources, r...)
}
if len(l) != 0 {
links = append(links, l...)
}
r, l, c, e := parseResource(o)
resources = append(resources, r...)
links = append(links, l...)
parseErrors = append(parseErrors, e...)
for _, cfgObj := range c {
configmaps[cfgObj.FullName] = cfgObj
}
Expand All @@ -112,8 +110,12 @@ func parseResources(objs []parsedK8sObjects, args common.InArgs) ([]common.Resou
configmapFullName := res.Resource.Namespace + "/" + cfgMapRef
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the block starting with for _, cfgMapRef := range res.Resource.ConfigMapRefs { could be extracted to a separate function that analyzes the resources and returns the envs.

Moreover, I am not sure if the parse errors should be simply attached to all other errors, because the configmap has been already parsed in r, l, c, e := parseResource(o), so now this must be some different kind of error.

if cfgMap, ok := configmaps[configmapFullName]; ok {
for _, v := range cfgMap.Data {
res.Resource.Envs = append(res.Resource.Envs, v)
if analyzer.IsNetworkAddressValue(v) {
res.Resource.Envs = append(res.Resource.Envs, v)
}
}
} else {
parseErrors = append(parseErrors, getConfigMapNotFoundError(configmapFullName, res.Resource.Name))
}
}
for _, cfgMapKeyRef := range res.Resource.ConfigMapKeyRefs {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this for-block, there is a lot of repetition with the previous block. Maybe, we could extract it to a separate function that would handle both of them and extract only the differences?

Expand All @@ -123,7 +125,12 @@ func parseResources(objs []parsedK8sObjects, args common.InArgs) ([]common.Resou
if analyzer.IsNetworkAddressValue(val) {
res.Resource.Envs = append(res.Resource.Envs, val)
}
} else {
msg := fmt.Sprintf("configmap %s does not have key %s (referenced by %s)", cfgMapKeyRef.Name, cfgMapKeyRef.Key, res.Resource.Name)
parseErrors = append(parseErrors, &common.FileProcessingError{Msg: msg})
}
} else {
parseErrors = append(parseErrors, getConfigMapNotFoundError(configmapFullName, res.Resource.Name))
}
}
}
Expand All @@ -133,20 +140,27 @@ func parseResources(objs []parsedK8sObjects, args common.InArgs) ([]common.Resou
links[idx].GitBranch = *args.GitBranch
links[idx].GitURL = *args.GitURL
}
return resources, links
return resources, links, parseErrors
}

func getConfigMapNotFoundError(cfgMapName, resourceName string) *common.FileProcessingError {
msg := fmt.Sprintf("configmap %s not found (referenced by %s)", cfgMapName, resourceName)
return &common.FileProcessingError{Msg: msg}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel that returning a structure with just a single field set to a value could be improved by simply returning the string, or better, an error. This is what I think about:

Suggested change
func getConfigMapNotFoundError(cfgMapName, resourceName string) *common.FileProcessingError {
msg := fmt.Sprintf("configmap %s not found (referenced by %s)", cfgMapName, resourceName)
return &common.FileProcessingError{Msg: msg}
}
func getConfigMapNotFoundError(cfgMapName, resourceName string) error {
return fmt.Errorf("configmap %s not found (referenced by %s)", cfgMapName, resourceName)
}

and as this results in a oneliner function, we could just use the return fmt.Errorf( instead wrapping it in getConfigMapNotFoundError


func parseResource(obj parsedK8sObjects) ([]common.Resource, []common.Service, []common.CfgMap) {
func parseResource(obj parsedK8sObjects) ([]common.Resource, []common.Service, []common.CfgMap, common.FileProcessingErrorList) {
links := []common.Service{}
deployments := []common.Resource{}
configMaps := []common.CfgMap{}
parseErrors := common.FileProcessingErrorList{}

for _, p := range obj.DeployObjects {
switch p.GroupKind {
case "Service":
res, err := analyzer.ScanK8sServiceObject(p.GroupKind, p.RuntimeObject)
if err != nil {
zap.S().Errorf("error scanning service object: %v", err)
parseErrors = append(parseErrors, &common.FileProcessingError{Msg: err.Error(), FilePath: obj.ManifestFilepath})
continue
}
Comment on lines 146 to 147
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Maybe we could use the else part instead of continuing?

res.Resource.FilePath = obj.ManifestFilepath
Expand All @@ -155,19 +169,21 @@ func parseResource(obj parsedK8sObjects) ([]common.Resource, []common.Service, [
res, err := analyzer.ScanK8sConfigmapObject(p.GroupKind, p.RuntimeObject)
if err != nil {
zap.S().Errorf("error scanning Configmap object: %v", err)
parseErrors = append(parseErrors, &common.FileProcessingError{Msg: err.Error(), FilePath: obj.ManifestFilepath})
continue
}
configMaps = append(configMaps, res)
default:
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't we use case "Deployment" here and save the default case for new unexpected types of objects?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because this can be any one of the workload resources (e.g. ReplicaSet, Job)

res, err := analyzer.ScanK8sDeployObject(p.GroupKind, p.RuntimeObject)
if err != nil {
zap.S().Debugf("Skipping object with type: %s", p.GroupKind)
parseErrors = append(parseErrors, &common.FileProcessingError{Msg: err.Error(), FilePath: obj.ManifestFilepath})
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it mean that if we receive another type of k8s object that is not a deployment, we would throw an error here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The name ScanK8sDeployObject is a bit misleading. I'll rename it to ScanK8sWorkloadObject.
Any k8s resource that is not a Service, a ConfigMap or a workload resource, shouldn't have got this far, as we already filtered the objects in parsedK8sObjects by their kind.
Hence, an error is only issued if we fail to construct one of these objects out of its buffer.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed function

continue
}
res.Resource.FilePath = obj.ManifestFilepath
deployments = append(deployments, res)
}
}

return deployments, links, configMaps
return deployments, links, configMaps, parseErrors
}
Loading