Skip to content

Commit f68d6ec

Browse files
authoredOct 16, 2022
Add debug information to help understand failures finding schemas (#133)
* Add debug information to help understand failures finding schemas * Add debug information to help understand failures finding schemas
1 parent 3cb76bc commit f68d6ec

File tree

9 files changed

+67
-24
lines changed

9 files changed

+67
-24
lines changed
 

‎Readme.md

+2
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ Usage: ./bin/kubeconform [OPTION]... [FILE OR FOLDER]...
7676
cache schemas downloaded via HTTP to this folder
7777
-cpu-prof string
7878
debug - log CPU profiling to file
79+
-debug
80+
print debug information
7981
-exit-on-error
8082
immediately stop execution when the first error is encountered
8183
-h show help information

‎cmd/kubeconform/main.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,10 @@ func realMain() int {
9797
fmt.Fprintln(os.Stderr, err)
9898
return 1
9999
}
100-
101-
v, err := validator.New(cfg.SchemaLocations, validator.Opts{
100+
var v validator.Validator
101+
v, err = validator.New(cfg.SchemaLocations, validator.Opts{
102102
Cache: cfg.Cache,
103+
Debug: cfg.Debug,
103104
SkipTLS: cfg.SkipTLS,
104105
SkipKinds: cfg.SkipKinds,
105106
RejectKinds: cfg.RejectKinds,

‎pkg/config/config.go

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
type Config struct {
1111
Cache string
1212
CPUProfileFile string
13+
Debug bool
1314
ExitOnError bool
1415
Files []string
1516
SchemaLocations []string
@@ -67,6 +68,7 @@ func FromFlags(progName string, args []string) (Config, string, error) {
6768
flags.Var(&schemaLocationsParam, "schema-location", "override schemas location search path (can be specified multiple times)")
6869
flags.StringVar(&skipKindsCSV, "skip", "", "comma-separated list of kinds to ignore")
6970
flags.StringVar(&rejectKindsCSV, "reject", "", "comma-separated list of kinds to reject")
71+
flags.BoolVar(&c.Debug, "debug", false, "print debug information")
7072
flags.BoolVar(&c.ExitOnError, "exit-on-error", false, "immediately stop execution when the first error is encountered")
7173
flags.BoolVar(&c.IgnoreMissingSchemas, "ignore-missing-schemas", false, "skip files with missing schemas instead of failing")
7274
flags.Var(&ignoreFilenamePatterns, "ignore-filename-pattern", "regular expression specifying paths to ignore (can be specified multiple times)")

‎pkg/config/config_test.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -112,9 +112,10 @@ func TestFromFlags(t *testing.T) {
112112
{
113113
[]string{"-cache", "cache", "-ignore-missing-schemas", "-kubernetes-version", "1.16.0", "-n", "2", "-output", "json",
114114
"-schema-location", "folder", "-schema-location", "anotherfolder", "-skip", "kinda,kindb", "-strict",
115-
"-reject", "kindc,kindd", "-summary", "-verbose", "file1", "file2"},
115+
"-reject", "kindc,kindd", "-summary", "-debug", "-verbose", "file1", "file2"},
116116
Config{
117117
Cache: "cache",
118+
Debug: true,
118119
Files: []string{"file1", "file2"},
119120
IgnoreMissingSchemas: true,
120121
KubernetesVersion: "1.16.0",

‎pkg/registry/http.go

+29-5
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@ package registry
22

33
import (
44
"crypto/tls"
5+
"errors"
56
"fmt"
67
"io/ioutil"
8+
"log"
79
"net/http"
810
"os"
911
"time"
@@ -21,9 +23,10 @@ type SchemaRegistry struct {
2123
schemaPathTemplate string
2224
cache cache.Cache
2325
strict bool
26+
debug bool
2427
}
2528

26-
func newHTTPRegistry(schemaPathTemplate string, cacheFolder string, strict bool, skipTLS bool) (*SchemaRegistry, error) {
29+
func newHTTPRegistry(schemaPathTemplate string, cacheFolder string, strict bool, skipTLS bool, debug bool) (*SchemaRegistry, error) {
2730
reghttp := &http.Transport{
2831
MaxIdleConns: 100,
2932
IdleConnTimeout: 3 * time.Second,
@@ -53,6 +56,7 @@ func newHTTPRegistry(schemaPathTemplate string, cacheFolder string, strict bool,
5356
schemaPathTemplate: schemaPathTemplate,
5457
cache: filecache,
5558
strict: strict,
59+
debug: debug,
5660
}, nil
5761
}
5862

@@ -71,21 +75,41 @@ func (r SchemaRegistry) DownloadSchema(resourceKind, resourceAPIVersion, k8sVers
7175

7276
resp, err := r.c.Get(url)
7377
if err != nil {
74-
return nil, fmt.Errorf("failed downloading schema at %s: %s", url, err)
78+
msg := fmt.Sprintf("failed downloading schema at %s: %s", url, err)
79+
if r.debug {
80+
log.Println(msg)
81+
}
82+
return nil, errors.New(msg)
7583
}
7684
defer resp.Body.Close()
7785

7886
if resp.StatusCode == http.StatusNotFound {
79-
return nil, newNotFoundError(fmt.Errorf("no schema found"))
87+
msg := fmt.Sprintf("could not find schema at %s", url)
88+
if r.debug {
89+
log.Print(msg)
90+
}
91+
return nil, newNotFoundError(errors.New(msg))
8092
}
8193

8294
if resp.StatusCode != http.StatusOK {
83-
return nil, fmt.Errorf("error while downloading schema at %s - received HTTP status %d", url, resp.StatusCode)
95+
msg := fmt.Sprintf("error while downloading schema at %s - received HTTP status %d", url, resp.StatusCode)
96+
if r.debug {
97+
log.Print(msg)
98+
}
99+
return nil, fmt.Errorf(msg)
84100
}
85101

86102
body, err := ioutil.ReadAll(resp.Body)
87103
if err != nil {
88-
return nil, fmt.Errorf("failed downloading schema at %s: %s", url, err)
104+
msg := fmt.Sprintf("failed parsing schema from %s: %s", url, err)
105+
if r.debug {
106+
log.Print(msg)
107+
}
108+
return nil, errors.New(msg)
109+
}
110+
111+
if r.debug {
112+
log.Printf("using schema found at %s", url)
89113
}
90114

91115
if r.cache != nil {

‎pkg/registry/http_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ func TestDownloadSchema(t *testing.T) {
5959
"v1",
6060
"1.18.0",
6161
nil,
62-
fmt.Errorf("no schema found"),
62+
fmt.Errorf("could not find schema at http://kubernetesjson.dev"),
6363
},
6464
{
6565
"getting 503",

‎pkg/registry/local.go

+23-3
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,25 @@
11
package registry
22

33
import (
4+
"errors"
45
"fmt"
56
"io/ioutil"
7+
"log"
68
"os"
79
)
810

911
type LocalRegistry struct {
1012
pathTemplate string
1113
strict bool
14+
debug bool
1215
}
1316

1417
// NewLocalSchemas creates a new "registry", that will serve schemas from files, given a list of schema filenames
15-
func newLocalRegistry(pathTemplate string, strict bool) (*LocalRegistry, error) {
18+
func newLocalRegistry(pathTemplate string, strict bool, debug bool) (*LocalRegistry, error) {
1619
return &LocalRegistry{
1720
pathTemplate,
1821
strict,
22+
debug,
1923
}, nil
2024
}
2125

@@ -28,16 +32,32 @@ func (r LocalRegistry) DownloadSchema(resourceKind, resourceAPIVersion, k8sVersi
2832
f, err := os.Open(schemaFile)
2933
if err != nil {
3034
if os.IsNotExist(err) {
31-
return nil, newNotFoundError(fmt.Errorf("no schema found"))
35+
msg := fmt.Sprintf("could not open file %s", schemaFile)
36+
if r.debug {
37+
log.Print(msg)
38+
}
39+
return nil, newNotFoundError(errors.New(msg))
3240
}
33-
return nil, fmt.Errorf("failed to open schema %s", schemaFile)
41+
42+
msg := fmt.Sprintf("failed to open schema at %s: %s", schemaFile, err)
43+
if r.debug {
44+
log.Print(msg)
45+
}
46+
return nil, errors.New(msg)
3447
}
3548

3649
defer f.Close()
3750
content, err := ioutil.ReadAll(f)
3851
if err != nil {
52+
msg := fmt.Sprintf("failed to read schema at %s: %s", schemaFile, err)
53+
if r.debug {
54+
log.Print(msg)
55+
}
3956
return nil, err
4057
}
4158

59+
if r.debug {
60+
log.Printf("using schema found at %s", schemaFile)
61+
}
4262
return content, nil
4363
}

‎pkg/registry/registry.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ func schemaPath(tpl, resourceKind, resourceAPIVersion, k8sVersion string, strict
8181
return buf.String(), nil
8282
}
8383

84-
func New(schemaLocation string, cache string, strict bool, skipTLS bool) (Registry, error) {
84+
func New(schemaLocation string, cache string, strict bool, skipTLS bool, debug bool) (Registry, error) {
8585
if schemaLocation == "default" {
8686
schemaLocation = "https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/{{ .NormalizedKubernetesVersion }}-standalone{{ .StrictSuffix }}/{{ .ResourceKind }}{{ .KindSuffix }}.json"
8787
} else if !strings.HasSuffix(schemaLocation, "json") { // If we dont specify a full templated path, we assume the paths of our fork of kubernetes-json-schema
@@ -94,8 +94,8 @@ func New(schemaLocation string, cache string, strict bool, skipTLS bool) (Regist
9494
}
9595

9696
if strings.HasPrefix(schemaLocation, "http") {
97-
return newHTTPRegistry(schemaLocation, cache, strict, skipTLS)
97+
return newHTTPRegistry(schemaLocation, cache, strict, skipTLS, debug)
9898
}
9999

100-
return newLocalRegistry(schemaLocation, strict)
100+
return newLocalRegistry(schemaLocation, strict, debug)
101101
}

‎pkg/validator/validator.go

+2-9
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ type Validator interface {
4343
// Opts contains a set of options for the validator.
4444
type Opts struct {
4545
Cache string // Cache schemas downloaded via HTTP to this folder
46+
Debug bool // Debug infos will be print here
4647
SkipTLS bool // skip TLS validation when downloading from an HTTP Schema Registry
4748
SkipKinds map[string]struct{} // List of resource Kinds to ignore
4849
RejectKinds map[string]struct{} // List of resource Kinds to reject
@@ -61,7 +62,7 @@ func New(schemaLocations []string, opts Opts) (Validator, error) {
6162

6263
registries := []registry.Registry{}
6364
for _, schemaLocation := range schemaLocations {
64-
reg, err := registry.New(schemaLocation, opts.Cache, opts.Strict, opts.SkipTLS)
65+
reg, err := registry.New(schemaLocation, opts.Cache, opts.Strict, opts.SkipTLS, opts.Debug)
6566
if err != nil {
6667
return nil, err
6768
}
@@ -249,11 +250,3 @@ func downloadSchema(registries []registry.Registry, kind, version, k8sVersion st
249250

250251
return nil, nil // No schema found - we don't consider it an error, resource will be skipped
251252
}
252-
253-
// From kubeval - let's see if absolutely necessary
254-
// func init () {
255-
// gojsonschema.FormatCheckers.Add("int64", ValidFormat{})
256-
// gojsonschema.FormatCheckers.Add("byte", ValidFormat{})
257-
// gojsonschema.FormatCheckers.Add("int32", ValidFormat{})
258-
// gojsonschema.FormatCheckers.Add("int-or-string", ValidFormat{})
259-
// }

0 commit comments

Comments
 (0)
Please sign in to comment.