Skip to content
This repository has been archived by the owner on Jun 6, 2024. It is now read-only.

Commit

Permalink
fix: add --skip-validation flag (#798)
Browse files Browse the repository at this point in the history
  • Loading branch information
myishay committed Sep 18, 2022
1 parent 023cdc4 commit f178374
Show file tree
Hide file tree
Showing 8 changed files with 77 additions and 32 deletions.
22 changes: 17 additions & 5 deletions bl/validation/k8sValidator.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,19 +61,31 @@ type FileWithWarning struct {
WarningKind WarningKind
}

func (val *K8sValidator) ValidateResources(filesConfigurationsChan chan *extractor.FileConfigurations, concurrency int) (chan *extractor.FileConfigurations, chan *extractor.InvalidFile, chan *FileWithWarning) {
validK8sFilesConfigurationsChan := make(chan *extractor.FileConfigurations, concurrency)
func (val *K8sValidator) ValidateResources(filesConfigurationsChan chan *extractor.FileConfigurations, concurrency int, skipSchemaValidation bool) (chan *extractor.FileConfigurations, chan *extractor.InvalidFile, chan *FileWithWarning) {
validOrSkippedK8sFilesConfigurationsChan := make(chan *extractor.FileConfigurations, concurrency)
invalidK8sFilesChan := make(chan *extractor.InvalidFile, concurrency)
k8sValidationWarningPerValidFileChan := make(chan *FileWithWarning, concurrency)

go func() {

defer func() {
close(invalidK8sFilesChan)
close(validK8sFilesConfigurationsChan)
close(validOrSkippedK8sFilesConfigurationsChan)
close(k8sValidationWarningPerValidFileChan)
}()

if skipSchemaValidation {
for fileConfigurations := range filesConfigurationsChan {
validOrSkippedK8sFilesConfigurationsChan <- fileConfigurations
k8sValidationWarningPerValidFileChan <- &FileWithWarning{
Filename: fileConfigurations.FileName,
Warning: "Skipped schema validation",
WarningKind: Skipped,
}
}
return
}

for fileConfigurations := range filesConfigurationsChan {

isValid, validationErrors, validationWarning, err := val.validateResource(fileConfigurations.FileName)
Expand All @@ -84,7 +96,7 @@ func (val *K8sValidator) ValidateResources(filesConfigurationsChan chan *extract
}
}
if isValid {
validK8sFilesConfigurationsChan <- fileConfigurations
validOrSkippedK8sFilesConfigurationsChan <- fileConfigurations
if validationWarning != nil {
k8sValidationWarningPerValidFileChan <- &FileWithWarning{
Filename: fileConfigurations.FileName,
Expand All @@ -101,7 +113,7 @@ func (val *K8sValidator) ValidateResources(filesConfigurationsChan chan *extract
}
}()

return validK8sFilesConfigurationsChan, invalidK8sFilesChan, k8sValidationWarningPerValidFileChan
return validOrSkippedK8sFilesConfigurationsChan, invalidK8sFilesChan, k8sValidationWarningPerValidFileChan
}

func (val *K8sValidator) GetK8sFiles(filesConfigurationsChan chan *extractor.FileConfigurations, concurrency int) (chan *extractor.FileConfigurations, chan *extractor.FileConfigurations) {
Expand Down
10 changes: 5 additions & 5 deletions bl/validation/k8sValidator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func test_valid_multiple_configurations(t *testing.T) {
Configurations: []extractor.Configuration{},
}
close(filesConfigurationsChan)
validConfigurationsChan, _, _ := k8sValidator.ValidateResources(filesConfigurationsChan, 1)
validConfigurationsChan, _, _ := k8sValidator.ValidateResources(filesConfigurationsChan, 1, false)

for p := range validConfigurationsChan {
assert.Equal(t, path, p.FileName)
Expand Down Expand Up @@ -99,7 +99,7 @@ func test_invalid_file(t *testing.T) {
Configurations: []extractor.Configuration{},
}
close(filesConfigurationsChan)
_, invalidFilesChan, _ := k8sValidator.ValidateResources(filesConfigurationsChan, 1)
_, invalidFilesChan, _ := k8sValidator.ValidateResources(filesConfigurationsChan, 1, false)

for p := range invalidFilesChan {
assert.Equal(t, path, p.Path)
Expand All @@ -123,7 +123,7 @@ func test_empty_file(t *testing.T) {
Configurations: []extractor.Configuration{},
}
close(filesConfigurationsChan)
_, invalidFilesChan, _ := k8sValidator.ValidateResources(filesConfigurationsChan, 1)
_, invalidFilesChan, _ := k8sValidator.ValidateResources(filesConfigurationsChan, 1, false)

for p := range invalidFilesChan {
assert.Equal(t, path, p.Path)
Expand All @@ -150,7 +150,7 @@ func test_offline_with_remote_custom_schema_location(t *testing.T) {
}
close(filesConfigurationsChan)

_, invalidFilesChan, filesWithWarningsChan := k8sValidator.ValidateResources(filesConfigurationsChan, 1)
_, invalidFilesChan, filesWithWarningsChan := k8sValidator.ValidateResources(filesConfigurationsChan, 1, false)
for p := range invalidFilesChan {
assert.Equal(t, 1, len(p.ValidationErrors))
assert.Equal(t, "k8s schema validation error: no such host\n", p.ValidationErrors[0].Error())
Expand Down Expand Up @@ -180,7 +180,7 @@ func test_missing_schema_skipped(t *testing.T) {
k8sValidationWarningPerValidFile := make(K8sValidationWarningPerValidFile)

var wg sync.WaitGroup
filesConfigurationsChanRes, invalidFilesChan, filesWithWarningsChan := k8sValidator.ValidateResources(filesConfigurationsChan, 1)
filesConfigurationsChanRes, invalidFilesChan, filesWithWarningsChan := k8sValidator.ValidateResources(filesConfigurationsChan, 1, false)
wg.Add(1)
go func() {
for p := range filesConfigurationsChanRes {
Expand Down
2 changes: 1 addition & 1 deletion cmd/kustomize/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ type k8sValidatorMock struct {
mock.Mock
}

func (kv *k8sValidatorMock) ValidateResources(filesConfigurationsChan chan *extractor.FileConfigurations, concurrency int) (chan *extractor.FileConfigurations, chan *extractor.InvalidFile, chan *validation.FileWithWarning) {
func (kv *k8sValidatorMock) ValidateResources(filesConfigurationsChan chan *extractor.FileConfigurations, concurrency int, skipSchemaValidation bool) (chan *extractor.FileConfigurations, chan *extractor.InvalidFile, chan *validation.FileWithWarning) {
args := kv.Called(filesConfigurationsChan, concurrency)
return args.Get(0).(chan *extractor.FileConfigurations), args.Get(1).(chan *extractor.InvalidFile), args.Get(2).(chan *validation.FileWithWarning)
}
Expand Down
34 changes: 31 additions & 3 deletions cmd/test/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"github.com/datreeio/datree/pkg/evaluation"
"github.com/datreeio/datree/pkg/policy"
"github.com/pkg/errors"
"k8s.io/utils/strings/slices"

"github.com/datreeio/datree/pkg/extractor"
"github.com/datreeio/datree/pkg/localConfig"
Expand All @@ -43,7 +44,7 @@ type Messager interface {
}

type K8sValidator interface {
ValidateResources(filesConfigurations chan *extractor.FileConfigurations, concurrency int) (chan *extractor.FileConfigurations, chan *extractor.InvalidFile, chan *validation.FileWithWarning)
ValidateResources(filesConfigurations chan *extractor.FileConfigurations, concurrency int, skipSchemaValidation bool) (chan *extractor.FileConfigurations, chan *extractor.InvalidFile, chan *validation.FileWithWarning)
InitClient(k8sVersion string, ignoreMissingSchemas bool, schemaLocations []string)
GetK8sFiles(filesConfigurationsChan chan *extractor.FileConfigurations, concurrency int) (chan *extractor.FileConfigurations, chan *extractor.FileConfigurations)
}
Expand All @@ -58,6 +59,7 @@ type TestCommandFlags struct {
SchemaLocations []string
PolicyConfig string
NoRecord bool
SkipValidation string
}

// TestCommandFlags constructor
Expand All @@ -70,9 +72,21 @@ func NewTestCommandFlags() *TestCommandFlags {
Verbose: false,
PolicyName: "",
SchemaLocations: make([]string, 0),
SkipValidation: "",
}
}

func validateSkipValidationFlag(flags *TestCommandFlags) error {
supportedSkipValidation := []string{"schema"}

if flags.SkipValidation != "" && !slices.Contains(supportedSkipValidation, flags.SkipValidation) {
return fmt.Errorf("invalid --skip-validation option - %q\n"+
"Valid values are: %v", flags.SkipValidation, supportedSkipValidation)
}

return nil
}

func (flags *TestCommandFlags) Validate() error {
outputValue := flags.Output

Expand All @@ -87,6 +101,11 @@ func (flags *TestCommandFlags) Validate() error {
return err
}

err = validateSkipValidationFlag(flags)
if err != nil {
return err
}

return nil

}
Expand Down Expand Up @@ -128,6 +147,7 @@ type TestCommandData struct {
RegistrationURL string
PromptRegistrationURL string
ClientId string
SkipSchemaValidation bool
}

type TestCommandContext struct {
Expand Down Expand Up @@ -236,6 +256,8 @@ func (flags *TestCommandFlags) AddFlags(cmd *cobra.Command) {
cmd.Flags().BoolVar(&flags.Verbose, "verbose", false, "Display 'How to Fix' link")
cmd.Flags().BoolVar(&flags.NoRecord, "no-record", false, "Don鈥檛 send policy checks metadata to the backend")

cmd.Flags().StringVar(&flags.SkipValidation, "skip-validation", "", "Skip validation step. Possible values: 'schema'")

// kubeconform flag
cmd.Flags().StringArrayVarP(&flags.SchemaLocations, "schema-location", "", []string{}, "Override schemas location search path (can be specified multiple times)")
cmd.Flags().BoolVarP(&flags.IgnoreMissingSchemas, "ignore-missing-schemas", "", false, "Ignore missing schemas when executing schema validation step")
Expand Down Expand Up @@ -292,6 +314,7 @@ func GenerateTestCommandData(testCommandFlags *TestCommandFlags, localConfigCont
ClientId: localConfigContent.ClientId,
RegistrationURL: evaluationPrerunDataResp.RegistrationURL,
PromptRegistrationURL: evaluationPrerunDataResp.PromptRegistrationURL,
SkipSchemaValidation: testCommandFlags.SkipValidation == "schema",
}

return testCommandOptions, nil
Expand Down Expand Up @@ -472,8 +495,13 @@ func evaluate(ctx *TestCommandContext, filesPaths []string, testCommandData *Tes
go validationManager.AggregateIgnoredYamlFiles(ignoredYamlFilesChan, &wg)
}

validK8sFilesConfigurationsChan, invalidK8sFilesChan, filesWithWarningsChan := ctx.K8sValidator.ValidateResources(validYamlConfigurationsChan, concurrency)
var validK8sFilesConfigurationsChan chan *extractor.FileConfigurations
var invalidK8sFilesChan chan *extractor.InvalidFile
var filesWithWarningsChan chan *validation.FileWithWarning

validK8sFilesConfigurationsChan, invalidK8sFilesChan, filesWithWarningsChan = ctx.K8sValidator.ValidateResources(
validYamlConfigurationsChan, concurrency, testCommandData.SkipSchemaValidation,
)
wg.Add(3)
go validationManager.AggregateValidK8sFiles(validK8sFilesConfigurationsChan, &wg)
go validationManager.AggregateInvalidK8sFiles(invalidK8sFilesChan, &wg)
Expand All @@ -484,7 +512,7 @@ func evaluate(ctx *TestCommandContext, filesPaths []string, testCommandData *Tes
policyName := testCommandData.Policy.Name

policyCheckData := evaluation.PolicyCheckData{
FilesConfigurations: validationManager.ValidK8sFilesConfigurations(),
FilesConfigurations: validationManager.ValidOrSkippedK8sFilesConfigurations(),
IsInteractiveMode: isInteractiveMode,
PolicyName: policyName,
Policy: testCommandData.Policy,
Expand Down
6 changes: 3 additions & 3 deletions cmd/test/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ type K8sValidatorMock struct {
mock.Mock
}

func (kv *K8sValidatorMock) ValidateResources(filesConfigurationsChan chan *extractor.FileConfigurations, concurrency int) (chan *extractor.FileConfigurations, chan *extractor.InvalidFile, chan *validation.FileWithWarning) {
func (kv *K8sValidatorMock) ValidateResources(filesConfigurationsChan chan *extractor.FileConfigurations, concurrency int, skipSchemaValidation bool) (chan *extractor.FileConfigurations, chan *extractor.InvalidFile, chan *validation.FileWithWarning) {
args := kv.Called(filesConfigurationsChan, concurrency)
return args.Get(0).(chan *extractor.FileConfigurations), args.Get(1).(chan *extractor.InvalidFile), args.Get(2).(chan *validation.FileWithWarning)
}
Expand Down Expand Up @@ -687,7 +687,7 @@ func setup() {
ignoredFilesChan := newIgnoredYamlFilesChan()
k8sValidationWarningsChan := newK8sValidationWarningsChan()

k8sValidatorMock.On("ValidateResources", mock.Anything, mock.Anything).Return(filesConfigurationsChan, invalidK8sFilesChan, k8sValidationWarningsChan, newErrorsChan())
k8sValidatorMock.On("ValidateResources", mock.Anything, mock.Anything, mock.Anything).Return(filesConfigurationsChan, invalidK8sFilesChan, k8sValidationWarningsChan, newErrorsChan())
k8sValidatorMock.On("GetK8sFiles", mock.Anything, mock.Anything).Return(filesConfigurationsChan, ignoredFilesChan, newErrorsChan())
k8sValidatorMock.On("InitClient", mock.Anything, mock.Anything, mock.Anything).Return()

Expand Down Expand Up @@ -853,7 +853,7 @@ func TestTestCommandNoInternetConnection(t *testing.T) {
WarningKind: validation.NetworkError,
}}

k8sValidatorMock.On("ValidateResources", mock.Anything, mock.Anything).Return(filesConfigurationsChan, invalidK8sFilesChan, K8sValidationWarnings, newErrorsChan())
k8sValidatorMock.On("ValidateResources", mock.Anything, mock.Anything, mock.Anything).Return(filesConfigurationsChan, invalidK8sFilesChan, K8sValidationWarnings, newErrorsChan())

k8sValidatorMock.AssertCalled(t, "ValidateResources", mock.Anything, 100)
mockedEvaluator.AssertCalled(t, "Evaluate", policyCheckData)
Expand Down
22 changes: 11 additions & 11 deletions cmd/test/validationManager.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ import (
)

type ValidationManager struct {
invalidYamlFiles []*extractor.InvalidFile
invalidK8sFiles []*extractor.InvalidFile
validK8sFilesConfigurations []*extractor.FileConfigurations
k8sValidationWarningPerValidFile validation.K8sValidationWarningPerValidFile
ignoredFiles []extractor.FileConfigurations
invalidYamlFiles []*extractor.InvalidFile
invalidK8sFiles []*extractor.InvalidFile
validAndSkippedSchemaValidationConfigurations []*extractor.FileConfigurations
k8sValidationWarningPerValidFile validation.K8sValidationWarningPerValidFile
ignoredFiles []extractor.FileConfigurations
}

func NewValidationManager() *ValidationManager {
Expand Down Expand Up @@ -54,13 +54,13 @@ func (v *ValidationManager) InvalidK8sFilesCount() int {

func (v *ValidationManager) AggregateValidK8sFiles(validK8sFilesConfigurationsChan chan *extractor.FileConfigurations, wg *sync.WaitGroup) {
for fileConfigurations := range validK8sFilesConfigurationsChan {
v.validK8sFilesConfigurations = append(v.validK8sFilesConfigurations, fileConfigurations)
v.validAndSkippedSchemaValidationConfigurations = append(v.validAndSkippedSchemaValidationConfigurations, fileConfigurations)
}
wg.Done()
}

func (v *ValidationManager) ValidK8sFilesConfigurations() []*extractor.FileConfigurations {
return v.validK8sFilesConfigurations
func (v *ValidationManager) ValidOrSkippedK8sFilesConfigurations() []*extractor.FileConfigurations {
return v.validAndSkippedSchemaValidationConfigurations
}

func (v *ValidationManager) GetK8sValidationSummaryStr(filesCount int) string {
Expand Down Expand Up @@ -91,13 +91,13 @@ func (v *ValidationManager) countFilesWithWarningsOfKind(warningKind validation.
}

func (v *ValidationManager) ValidK8sFilesConfigurationsCount() int {
return len(v.validK8sFilesConfigurations)
return len(v.validAndSkippedSchemaValidationConfigurations)
}

func (v *ValidationManager) ValidK8sConfigurationsCount() int {
totalConfigs := 0

for _, fileConfiguration := range v.validK8sFilesConfigurations {
for _, fileConfiguration := range v.validAndSkippedSchemaValidationConfigurations {
totalConfigs += len(fileConfiguration.Configurations)
}

Expand Down Expand Up @@ -125,7 +125,7 @@ func (v *ValidationManager) AggregateIgnoredYamlFiles(ignoredFilesChan chan *ext
}

func (v *ValidationManager) IgnoredFiles() []*extractor.FileConfigurations {
return v.validK8sFilesConfigurations
return v.validAndSkippedSchemaValidationConfigurations
}

func (v *ValidationManager) IgnoredFilesCount() int {
Expand Down
4 changes: 3 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ require (
github.com/goccy/go-json v0.9.11 // indirect
github.com/goccy/go-yaml v1.9.5 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/google/go-cmp v0.5.8 // indirect
github.com/jinzhu/copier v0.3.5 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
golang.org/x/net v0.0.0-20220708220712-1185a9018129 // indirect
Expand Down Expand Up @@ -64,7 +65,7 @@ require (
github.com/tklauser/numcpus v0.3.0 // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
golang.org/x/sys v0.0.0-20220712014510-0a85c31ab51e // indirect
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect
golang.org/x/text v0.3.7 // indirect
gopkg.in/ini.v1 v1.51.0 // indirect
)
Expand All @@ -75,4 +76,5 @@ require (
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/shirou/gopsutil/v3 v3.22.2
github.com/yusufpapurcu/wmi v1.2.2 // indirect
k8s.io/utils v0.0.0-20220823124924-e9cbc92d1a73
)
9 changes: 6 additions & 3 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,9 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
Expand Down Expand Up @@ -585,8 +586,8 @@ golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220712014510-0a85c31ab51e h1:NHvCuwuS43lGnYhten69ZWqi2QOj/CiDNcKbVqwVoew=
golang.org/x/sys v0.0.0-20220712014510-0a85c31ab51e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
Expand Down Expand Up @@ -798,6 +799,8 @@ k8s.io/klog/v2 v2.30.0/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65/go.mod h1:sX9MT8g7NVZM5lVL/j8QyCCJe8YSMW30QvGZWaCIDIk=
k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
k8s.io/utils v0.0.0-20211116205334-6203023598ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
k8s.io/utils v0.0.0-20220823124924-e9cbc92d1a73 h1:H9TCJUUx+2VA0ZiD9lvtaX8fthFsMoD+Izn93E/hm8U=
k8s.io/utils v0.0.0-20220823124924-e9cbc92d1a73/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
Expand Down

0 comments on commit f178374

Please sign in to comment.