forked from zarf-dev/zarf
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: run schema validation on create (zarf-dev#2585)
Signed-off-by: Austin Abro <[email protected]> Signed-off-by: Tim Seagren <[email protected]>
- Loading branch information
1 parent
39108d6
commit b835d34
Showing
23 changed files
with
825 additions
and
778 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// SPDX-FileCopyrightText: 2021-Present The Zarf Authors | ||
|
||
// Package lint contains functions for verifying zarf yaml files are valid | ||
package lint | ||
|
||
import ( | ||
"fmt" | ||
"path/filepath" | ||
|
||
"github.com/defenseunicorns/pkg/helpers/v2" | ||
"github.com/fatih/color" | ||
"github.com/zarf-dev/zarf/src/pkg/message" | ||
) | ||
|
||
// PackageFinding is a struct that contains a finding about something wrong with a package | ||
type PackageFinding struct { | ||
// YqPath is the path to the key where the error originated from, this is sometimes empty in the case of a general error | ||
YqPath string | ||
Description string | ||
// Item is the value of a key that is causing an error, for example a bad image name | ||
Item string | ||
// PackageNameOverride shows the name of the package that the error originated from | ||
// If it is not set the base package will be used when displaying the error | ||
PackageNameOverride string | ||
// PackagePathOverride shows the path to the package that the error originated from | ||
// If it is not set the base package will be used when displaying the error | ||
PackagePathOverride string | ||
Severity Severity | ||
} | ||
|
||
// Severity is the type of finding | ||
type Severity int | ||
|
||
// different severities of package errors | ||
const ( | ||
SevErr Severity = iota + 1 | ||
SevWarn | ||
) | ||
|
||
func (f PackageFinding) itemizedDescription() string { | ||
if f.Item == "" { | ||
return f.Description | ||
} | ||
return fmt.Sprintf("%s - %s", f.Description, f.Item) | ||
} | ||
|
||
func colorWrapSev(s Severity) string { | ||
if s == SevErr { | ||
return message.ColorWrap("Error", color.FgRed) | ||
} else if s == SevWarn { | ||
return message.ColorWrap("Warning", color.FgYellow) | ||
} | ||
return "unknown" | ||
} | ||
|
||
func filterLowerSeverity(findings []PackageFinding, severity Severity) []PackageFinding { | ||
findings = helpers.RemoveMatches(findings, func(finding PackageFinding) bool { | ||
return finding.Severity > severity | ||
}) | ||
return findings | ||
} | ||
|
||
// PrintFindings prints the findings of the given severity in a table | ||
func PrintFindings(findings []PackageFinding, severity Severity, baseDir string, packageName string) { | ||
findings = filterLowerSeverity(findings, severity) | ||
if len(findings) == 0 { | ||
return | ||
} | ||
mapOfFindingsByPath := GroupFindingsByPath(findings, packageName) | ||
|
||
header := []string{"Type", "Path", "Message"} | ||
|
||
for _, findings := range mapOfFindingsByPath { | ||
lintData := [][]string{} | ||
for _, finding := range findings { | ||
lintData = append(lintData, []string{ | ||
colorWrapSev(finding.Severity), | ||
message.ColorWrap(finding.YqPath, color.FgCyan), | ||
finding.itemizedDescription(), | ||
}) | ||
} | ||
var packagePathFromUser string | ||
if helpers.IsOCIURL(findings[0].PackagePathOverride) { | ||
packagePathFromUser = findings[0].PackagePathOverride | ||
} else { | ||
packagePathFromUser = filepath.Join(baseDir, findings[0].PackagePathOverride) | ||
} | ||
message.Notef("Linting package %q at %s", findings[0].PackageNameOverride, packagePathFromUser) | ||
message.Table(header, lintData) | ||
} | ||
} | ||
|
||
// GroupFindingsByPath groups findings by their package path | ||
func GroupFindingsByPath(findings []PackageFinding, packageName string) map[string][]PackageFinding { | ||
for i := range findings { | ||
if findings[i].PackageNameOverride == "" { | ||
findings[i].PackageNameOverride = packageName | ||
} | ||
if findings[i].PackagePathOverride == "" { | ||
findings[i].PackagePathOverride = "." | ||
} | ||
} | ||
|
||
mapOfFindingsByPath := make(map[string][]PackageFinding) | ||
for _, finding := range findings { | ||
mapOfFindingsByPath[finding.PackagePathOverride] = append(mapOfFindingsByPath[finding.PackagePathOverride], finding) | ||
} | ||
return mapOfFindingsByPath | ||
} | ||
|
||
// HasSevOrHigher returns true if the findings contain a severity equal to or greater than the given severity | ||
func HasSevOrHigher(findings []PackageFinding, severity Severity) bool { | ||
return len(filterLowerSeverity(findings, severity)) > 0 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// SPDX-FileCopyrightText: 2021-Present The Zarf Authors | ||
|
||
// Package lint contains functions for verifying zarf yaml files are valid | ||
package lint | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestGroupFindingsByPath(t *testing.T) { | ||
t.Parallel() | ||
tests := []struct { | ||
name string | ||
findings []PackageFinding | ||
severity Severity | ||
packageName string | ||
want map[string][]PackageFinding | ||
}{ | ||
{ | ||
name: "same package multiple findings", | ||
findings: []PackageFinding{ | ||
{Severity: SevWarn, PackageNameOverride: "import", PackagePathOverride: "path"}, | ||
{Severity: SevWarn, PackageNameOverride: "import", PackagePathOverride: "path"}, | ||
}, | ||
packageName: "testPackage", | ||
want: map[string][]PackageFinding{ | ||
"path": { | ||
{Severity: SevWarn, PackageNameOverride: "import", PackagePathOverride: "path"}, | ||
{Severity: SevWarn, PackageNameOverride: "import", PackagePathOverride: "path"}, | ||
}, | ||
}, | ||
}, | ||
{ | ||
name: "different packages single finding", | ||
findings: []PackageFinding{ | ||
{Severity: SevWarn, PackageNameOverride: "import", PackagePathOverride: "path"}, | ||
{Severity: SevErr, PackageNameOverride: "", PackagePathOverride: ""}, | ||
}, | ||
packageName: "testPackage", | ||
want: map[string][]PackageFinding{ | ||
"path": {{Severity: SevWarn, PackageNameOverride: "import", PackagePathOverride: "path"}}, | ||
".": {{Severity: SevErr, PackageNameOverride: "testPackage", PackagePathOverride: "."}}, | ||
}, | ||
}, | ||
} | ||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
t.Parallel() | ||
require.Equal(t, tt.want, GroupFindingsByPath(tt.findings, tt.packageName)) | ||
}) | ||
} | ||
} | ||
|
||
func TestHasSeverity(t *testing.T) { | ||
t.Parallel() | ||
tests := []struct { | ||
name string | ||
severity Severity | ||
expected bool | ||
findings []PackageFinding | ||
}{ | ||
{ | ||
name: "error severity present", | ||
findings: []PackageFinding{ | ||
{ | ||
Severity: SevErr, | ||
}, | ||
}, | ||
severity: SevErr, | ||
expected: true, | ||
}, | ||
{ | ||
name: "error severity not present", | ||
findings: []PackageFinding{ | ||
{ | ||
Severity: SevWarn, | ||
}, | ||
}, | ||
severity: SevErr, | ||
expected: false, | ||
}, | ||
{ | ||
name: "err and warning severity present", | ||
findings: []PackageFinding{ | ||
{ | ||
Severity: SevWarn, | ||
}, | ||
{ | ||
Severity: SevErr, | ||
}, | ||
}, | ||
severity: SevErr, | ||
expected: true, | ||
}, | ||
} | ||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
t.Parallel() | ||
require.Equal(t, tt.expected, HasSevOrHigher(tt.findings, tt.severity)) | ||
}) | ||
} | ||
} |
Oops, something went wrong.