diff --git a/cmd/main.go b/cmd/main.go index 9f8bbe6..7853af6 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -83,11 +83,14 @@ func main() { panic(fmt.Sprintf("Error while writing ss matrix to file :%v", err)) } // generate the diff matrix between the enpointslice and the ss matrix - diff := commatrix.GenerateMatrixDiff(*mat, *ssMat) + diff, err := commatrix.GenerateMatrixDiff(*mat, *ssMat) + if err != nil { + panic(fmt.Sprintf("Error while generating matrix diff :%v", err)) + } // write the diff matrix between the enpointslice and the ss matrix to file err = os.WriteFile(filepath.Join(destDir, "matrix-diff-ss"), []byte(diff), 0644) if err != nil { - panic(fmt.Sprintf("Error writing the diff matrix :%v", err)) + panic(fmt.Sprintf("Error writing the diff matrix file: %v", err)) } } diff --git a/commatrix/generate.go b/commatrix/generate.go index a866f8a..ad1c561 100644 --- a/commatrix/generate.go +++ b/commatrix/generate.go @@ -6,6 +6,8 @@ import ( "os" "path" "path/filepath" + "reflect" + "strings" "sync" "golang.org/x/sync/errgroup" @@ -164,14 +166,22 @@ func writeMatrixToFile(matrix types.ComMatrix, fileName, format string, printFn return os.WriteFile(comMatrixFileName, res, 0644) } -func GenerateMatrixDiff(mat1 types.ComMatrix, mat2 types.ComMatrix) string { - diff := consts.CSVHeaders + "\n" +// GenerateMatrixDiff generates the diff between mat1 to mat2. +func GenerateMatrixDiff(mat1, mat2 types.ComMatrix) (string, error) { + colNames, err := getComMatrixHeadersByFormat(types.FormatCSV) + if err != nil { + return "", fmt.Errorf("error getting commatrix CSV tags: %v", err) + } + + diff := colNames + "\n" + for _, cd := range mat1.Matrix { if mat2.Contains(cd) { diff += fmt.Sprintf("%s\n", cd) continue } + // add "+" before cd's mat1 contains but mat2 doesn't diff += fmt.Sprintf("+ %s\n", cd) } @@ -183,11 +193,28 @@ func GenerateMatrixDiff(mat1 types.ComMatrix, mat2 types.ComMatrix) string { } if !mat1.Contains(cd) { + // add "-" before cd's mat1 doesn't contain but mat2 does diff += fmt.Sprintf("- %s\n", cd) } } - return diff + return diff, nil +} + +func getComMatrixHeadersByFormat(format string) (string, error) { + typ := reflect.TypeOf(types.ComDetails{}) + + var tagsList []string + for i := 0; i < typ.NumField(); i++ { + field := typ.Field(i) + tag := field.Tag.Get(format) + if tag == "" { + return "", fmt.Errorf("field %v has no tag of format %s", field, format) + } + tagsList = append(tagsList, tag) + } + + return strings.Join(tagsList, ","), nil } func separateMatrixByRole(matrix types.ComMatrix) (types.ComMatrix, types.ComMatrix) { diff --git a/consts/consts.go b/consts/consts.go index 76a6a7f..61ebb4d 100644 --- a/consts/consts.go +++ b/consts/consts.go @@ -8,5 +8,4 @@ const ( RoleLabel = "node-role.kubernetes.io/" DefaultDebugNamespace = "openshift-commatrix-debug" DefaultDebugPodImage = "quay.io/openshift-release-dev/ocp-release:4.15.12-multi" - CSVHeaders = "Direction,Protocol,Port,Namespace,Service,Pod,Container,Node Role,Optional" ) diff --git a/commatrix/example-custom-entries.csv b/samples/custom-entries/example-custom-entries.csv similarity index 71% rename from commatrix/example-custom-entries.csv rename to samples/custom-entries/example-custom-entries.csv index a596aa8..bf347cf 100644 --- a/commatrix/example-custom-entries.csv +++ b/samples/custom-entries/example-custom-entries.csv @@ -1,3 +1,3 @@ -Direction,Protocol,Port,Namespace,Service,Pod,Container,NodeRole,Optional +Direction,Protocol,Port,Namespace,Service,Pod,Container,Node Role,Optional ingress,TCP,9050,example-namespace,example-service,example-pod,example-container,master,false ingress,UDP,9051,example-namespace2,example-service2,example-pod2,example-container2,woker,false diff --git a/commatrix/example-custom-entries.json b/samples/custom-entries/example-custom-entries.json similarity index 92% rename from commatrix/example-custom-entries.json rename to samples/custom-entries/example-custom-entries.json index 0db991c..f06354a 100644 --- a/commatrix/example-custom-entries.json +++ b/samples/custom-entries/example-custom-entries.json @@ -2,7 +2,7 @@ { "direction": "ingress", "protocol": "TCP", - "port": "9050", + "port": 9050, "namespace": "example-namespace", "service": "example-service", "pod": "example-pod", @@ -13,7 +13,7 @@ { "direction": "ingress", "protocol": "UDP", - "port": "9051", + "port": 9051, "namespace": "example-namespace2", "service": "example-service2", "pod": "example-pod2", diff --git a/commatrix/example-custom-entries.yaml b/samples/custom-entries/example-custom-entries.yaml similarity index 92% rename from commatrix/example-custom-entries.yaml rename to samples/custom-entries/example-custom-entries.yaml index 0c20e52..3848cb0 100644 --- a/commatrix/example-custom-entries.yaml +++ b/samples/custom-entries/example-custom-entries.yaml @@ -4,7 +4,7 @@ nodeRole: master optional: false pod: example-pod - port: "9050" + port: 9050 protocol: TCP service: example-service - container: example-container2 @@ -13,6 +13,6 @@ nodeRole: worker optional: false pod: example-pod2 - port: "9051" + port: 9051 protocol: UDP service: example-service2 diff --git a/types/types.go b/types/types.go index 9acbaea..0046af9 100644 --- a/types/types.go +++ b/types/types.go @@ -9,7 +9,7 @@ import ( "slices" "strings" - "github.com/openshift-kni/commatrix/consts" + "github.com/gocarina/gocsv" "sigs.k8s.io/yaml" ) @@ -34,15 +34,15 @@ type ComMatrix struct { } type ComDetails struct { - Direction string `json:"direction" yaml:"direction"` - Protocol string `json:"protocol" yaml:"protocol"` - Port int `json:"port" yaml:"port"` - Namespace string `json:"namespace" yaml:"namespace"` - Service string `json:"service" yaml:"service"` - Pod string `json:"pod" yaml:"pod"` - Container string `json:"container" yaml:"container"` - NodeRole string `json:"nodeRole" yaml:"nodeRole"` - Optional bool `json:"optional" yaml:"optional"` + Direction string `json:"direction" yaml:"direction" csv:"Direction"` + Protocol string `json:"protocol" yaml:"protocol" csv:"Protocol"` + Port int `json:"port" yaml:"port" csv:"Port"` + Namespace string `json:"namespace" yaml:"namespace" csv:"Namespace"` + Service string `json:"service" yaml:"service" csv:"Service"` + Pod string `json:"pod" yaml:"pod" csv:"Pod"` + Container string `json:"container" yaml:"container" csv:"Container"` + NodeRole string `json:"nodeRole" yaml:"nodeRole" csv:"Node Role"` + Optional bool `json:"optional" yaml:"optional" csv:"Optional"` } func ToCSV(m ComMatrix) ([]byte, error) { @@ -50,18 +50,11 @@ func ToCSV(m ComMatrix) ([]byte, error) { w := bytes.NewBuffer(out) csvwriter := csv.NewWriter(w) - err := csvwriter.Write(strings.Split(consts.CSVHeaders, ",")) + err := gocsv.MarshalCSV(&m.Matrix, csvwriter) if err != nil { - return nil, fmt.Errorf("failed to write to CSV: %w", err) + return nil, err } - for _, cd := range m.Matrix { - record := strings.Split(cd.String(), ",") - err := csvwriter.Write(record) - if err != nil { - return nil, fmt.Errorf("failed to convert to CSV foramt: %w", err) - } - } csvwriter.Flush() return w.Bytes(), nil