Merge pull request #95016 from Jefftree/remove-kubeconform

Remove kubeconform
This commit is contained in:
Kubernetes Prow Robot 2020-10-06 16:54:42 -07:00 committed by GitHub
commit 7a5b058f27
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 0 additions and 505 deletions

1
go.mod
View File

@ -44,7 +44,6 @@ require (
github.com/evanphx/json-patch v4.9.0+incompatible github.com/evanphx/json-patch v4.9.0+incompatible
github.com/fsnotify/fsnotify v1.4.9 github.com/fsnotify/fsnotify v1.4.9
github.com/go-bindata/go-bindata v3.1.1+incompatible github.com/go-bindata/go-bindata v3.1.1+incompatible
github.com/go-openapi/analysis v0.19.5
github.com/go-openapi/loads v0.19.4 github.com/go-openapi/loads v0.19.4
github.com/go-openapi/spec v0.19.3 github.com/go-openapi/spec v0.19.3
github.com/go-openapi/strfmt v0.19.3 github.com/go-openapi/strfmt v0.19.3

View File

@ -32,7 +32,6 @@ filegroup(
srcs = [ srcs = [
":package-srcs", ":package-srcs",
"//test/conformance/behaviors:all-srcs", "//test/conformance/behaviors:all-srcs",
"//test/conformance/kubeconform:all-srcs",
"//test/conformance/testdata:all-srcs", "//test/conformance/testdata:all-srcs",
], ],
tags = ["automanaged"], tags = ["automanaged"],

View File

@ -1 +0,0 @@
kubetestgen

View File

@ -1,40 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
go_library(
name = "go_default_library",
srcs = [
"gen.go",
"kubeconform.go",
"link.go",
],
importpath = "k8s.io/kubernetes/test/conformance/kubeconform",
visibility = ["//visibility:private"],
deps = [
"//test/conformance/behaviors:go_default_library",
"//vendor/github.com/go-openapi/analysis:go_default_library",
"//vendor/github.com/go-openapi/loads:go_default_library",
"//vendor/github.com/go-openapi/spec:go_default_library",
"//vendor/gopkg.in/yaml.v2:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
go_binary(
name = "kubeconform",
data = ["//api/openapi-spec"],
embed = [":go_default_library"],
visibility = ["//visibility:public"],
)

View File

@ -1,32 +0,0 @@
# kubeconform
`kubeconform` is used to manage the creation and coverage analysis of conformance behaviors and tests. Currently it performs two functions:
* `gen`. This command generates a list of behaviors for a resource based on the OpenAPI schema. The purpose is to bootstrap a list of behaviors, and not to produce the final list of behaviors. We expect that the resulting files will be curated to identify a meaningful set of behaviors for the conformance requirements of the targeted resource. This may include addition, modification, and removal of behaviors from the generated list.
* `link`. This command prints the defined behaviors not covered by any test.
## gen
**Example usage for PodSpec:**
From the root directory of the k/k repo, will produce `pod.yaml` in
`test/conformance/behaviors`. The `pwd` is needed because of how bazel handles
working directories with `run`.
```
$ bazel run //test/conformance/kubeconform:kubeconform -- --resource io.k8s.api.core.v1.PodSpec --area pod --schema api/openapi-spec/swagger.json --dir `pwd`/test/conformance/behaviors/ gen
```
**Flags:**
- `schema` - a URL or local file name pointing to the JSON OpenAPI schema
- `resource` - the specific OpenAPI definition for which to generate behaviors
- `area` - the name to use for the area
- `dir` - the path to the behaviors directory (default current directory)
**Note**: The tool automatically generates suites based on the object type for a field. All primitive data types are grouped into a default suite, while object data types are grouped into their own suite, one per object.
## link
```
$ bazel run //test/conformance/kubeconform:kubeconform -- -dir `pwd`/test/conformance/behaviors/sig-node -testdata `pwd`/test/conformance/testdata/conformance.yaml link
```

View File

@ -1,218 +0,0 @@
/*
Copyright 2019 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"fmt"
"os"
"path/filepath"
"sort"
"strings"
"github.com/go-openapi/analysis"
"github.com/go-openapi/loads"
"github.com/go-openapi/spec"
"gopkg.in/yaml.v2"
"k8s.io/kubernetes/test/conformance/behaviors"
)
var defMap map[string]analysis.SchemaRef
func gen(o *options) error {
defMap = make(map[string]analysis.SchemaRef)
d, err := loads.JSONSpec(o.schemaPath)
if err != nil {
return err
}
defs := d.Analyzer.AllDefinitions()
sort.Slice(defs, func(i, j int) bool { return defs[i].Name < defs[j].Name })
for _, d := range defs {
if !d.TopLevel {
continue
}
defMap[d.Ref.String()] = d
}
var suites []behaviors.Suite
var suiteMapping = make(map[string]*behaviors.Suite)
for _, v := range defs {
if !v.TopLevel || o.resource != v.Name {
continue
}
name := trimObjectName(v.Name)
defaultsuite := behaviors.Suite{
Suite: o.area + "/spec",
Description: "Base suite for " + o.area,
Behaviors: []behaviors.Behavior{},
}
_ = defaultsuite
for p, propSchema := range v.Schema.Properties {
id := o.area + p + "/"
if propSchema.Ref.String() != "" || propSchema.Type[0] == "array" {
if _, ok := suiteMapping[id]; !ok {
newsuite := behaviors.Suite{
Suite: o.area + "/" + p,
Description: "Suite for " + o.area + "/" + p,
Behaviors: []behaviors.Behavior{},
}
suiteMapping[id] = &newsuite
}
behaviors := suiteMapping[id].Behaviors
behaviors = append(behaviors, schemaBehavior(o.area, name, p, propSchema)...)
suiteMapping[id].Behaviors = behaviors
} else {
if _, ok := suiteMapping["default"]; !ok {
newsuite := behaviors.Suite{
Suite: o.area + "/spec",
Description: "Base suite for " + o.area,
Behaviors: []behaviors.Behavior{},
}
suiteMapping["default"] = &newsuite
}
behaviors := suiteMapping["default"].Behaviors
behaviors = append(behaviors, schemaBehavior(o.area, name, p, propSchema)...)
suiteMapping["default"].Behaviors = behaviors
}
}
for _, v := range suiteMapping {
suites = append(suites, *v)
}
break
}
var area behaviors.Area = behaviors.Area{Area: o.area, Suites: suites}
countFields(suites)
return printYAML(filepath.Join(o.behaviorsDir, o.area), area)
}
func printYAML(fileName string, areaO behaviors.Area) error {
f, err := os.Create(fileName + ".yaml")
if err != nil {
return err
}
defer f.Close()
y, err := yaml.Marshal(areaO)
if err != nil {
return err
}
_, err = f.WriteString(string(y))
if err != nil {
return err
}
return nil
}
func countFields(suites []behaviors.Suite) {
var fieldsMapping map[string]int
fieldsMapping = make(map[string]int)
for _, suite := range suites {
for _, behavior := range suite.Behaviors {
if _, exists := fieldsMapping[behavior.APIType]; exists {
fieldsMapping[behavior.APIType]++
} else {
fieldsMapping[behavior.APIType] = 1
}
}
}
for k, v := range fieldsMapping {
fmt.Printf("Type %v, Count %v\n", k, v)
}
}
func trimObjectName(name string) string {
if strings.Index(name, "#/definitions/") == 0 {
name = name[len("#/definitions/"):]
}
if strings.Index(name, "io.k8s.api.") == 0 {
return name[len("io.k8s.api."):]
}
return name
}
func objectBehaviors(id string, s *spec.Schema) []behaviors.Behavior {
if strings.Contains(id, "openAPIV3Schema") || strings.Contains(id, "JSONSchema") || strings.Contains(s.Ref.String(), "JSONSchema") {
return []behaviors.Behavior{}
}
ref, ok := defMap[s.Ref.String()]
if !ok {
return []behaviors.Behavior{}
}
return schemaBehaviors(id, trimObjectName(ref.Name), ref.Schema)
}
func schemaBehaviors(base, apiObject string, s *spec.Schema) []behaviors.Behavior {
var behaviors []behaviors.Behavior
for p, propSchema := range s.Properties {
b := schemaBehavior(base, apiObject, p, propSchema)
behaviors = append(behaviors, b...)
}
return behaviors
}
func schemaBehavior(base, apiObject, p string, propSchema spec.Schema) []behaviors.Behavior {
id := strings.Join([]string{base, p}, "/")
if propSchema.Ref.String() != "" {
if apiObject == trimObjectName(propSchema.Ref.String()) {
return []behaviors.Behavior{}
}
return objectBehaviors(id, &propSchema)
}
var b []behaviors.Behavior
switch propSchema.Type[0] {
case "array":
b = objectBehaviors(id, propSchema.Items.Schema)
case "boolean":
b = []behaviors.Behavior{
{
ID: id,
APIObject: apiObject,
APIField: p,
APIType: propSchema.Type[0],
Description: "Boolean set to true. " + propSchema.Description,
},
{
ID: id,
APIObject: apiObject,
APIField: p,
APIType: propSchema.Type[0],
Description: "Boolean set to false. " + propSchema.Description,
},
}
default:
b = []behaviors.Behavior{{
ID: id,
APIObject: apiObject,
APIField: p,
APIType: propSchema.Type[0],
Description: propSchema.Description,
}}
}
return b
}

View File

@ -1,119 +0,0 @@
/*
Copyright 2020 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"flag"
"fmt"
"os"
)
// homegrown command structures now but if this grows we may
// want to adopt whatever kubectl uses
type options struct {
// Flags only used for generating behaviors
schemaPath string
resource string
area string
// Flags only used for linking behaviors
testdata string
listAll bool
// Flags shared between CLI tools
behaviorsDir string
}
type actionFunc func(*options) error
func parseFlags() (actionFunc, *options) {
o := &options{}
f := flag.NewFlagSet(os.Args[0], flag.ExitOnError)
f.StringVar(&o.schemaPath, "schema", "", "Path to the OpenAPI schema")
f.StringVar(&o.resource, "resource", "", "Resource name")
f.StringVar(&o.area, "area", "", "Area name to use")
f.StringVar(&o.testdata, "testdata", "test/conformance/testdata/conformance.yaml", "YAML file containing test linkage data")
f.BoolVar(&o.listAll, "all", false, "List all behaviors, not just those missing tests")
f.StringVar(&o.behaviorsDir, "dir", "test/conformance/behaviors/", "Path to the behaviors directory")
f.Usage = func() {
fmt.Fprintf(os.Stderr,
"USAGE\n-----\n%s [ options ] { link | gen }\n",
os.Args[0])
fmt.Fprintf(os.Stderr, "\nOPTIONS\n-------\n")
flag.PrintDefaults()
fmt.Fprintf(os.Stderr, "\nACTIONS\n------------")
fmt.Fprintf(os.Stderr, `
'link' lists behaviors associated with tests
'gen' generates behaviors based on the API schema
`)
}
flag.CommandLine = f
flag.Parse()
if len(flag.Args()) != 1 {
flag.CommandLine.Usage()
os.Exit(2)
}
var action actionFunc
switch flag.Args()[0] {
case "gen":
action = gen
if o.schemaPath == "" {
action = nil
fmt.Fprintf(os.Stderr, "-schema is required for 'gen'\n")
}
if o.resource == "" {
action = nil
fmt.Fprintf(os.Stderr, "-resource is required for 'gen'\n")
}
if o.area == "" {
action = nil
fmt.Fprintf(os.Stderr, "-area is required for 'gen'\n")
}
case "link":
action = link
if o.testdata == "" {
action = nil
fmt.Fprintf(os.Stderr, "-testdata is required for 'link'\n")
}
}
if o.behaviorsDir == "" {
action = nil
fmt.Fprintf(os.Stderr, "-dir is required\n")
}
if action == nil {
flag.CommandLine.Usage()
os.Exit(2)
}
return action, o
}
func main() {
action, o := parseFlags()
err := action(o)
if err != nil {
fmt.Printf("Error: %s\n", err)
os.Exit(1)
}
}

View File

@ -1,92 +0,0 @@
/*
Copyright 2020 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"fmt"
"io/ioutil"
"gopkg.in/yaml.v2"
"k8s.io/kubernetes/test/conformance/behaviors"
)
func link(o *options) error {
behaviorsMapping := make(map[string][]string)
var conformanceDataList []behaviors.ConformanceData
behaviorFiles, err := behaviors.BehaviorFileList(o.behaviorsDir)
if err != nil {
return err
}
fmt.Println()
fmt.Printf("Using behaviors from these %d files:\n", len(behaviorFiles))
for _, f := range behaviorFiles {
fmt.Println(" ", f)
}
fmt.Println()
if o.listAll {
fmt.Println("All behaviors:")
} else {
fmt.Println("Behaviors not covered by any conformance test:")
}
for _, behaviorFile := range behaviorFiles {
suite, err := behaviors.LoadSuite(behaviorFile)
if err != nil {
return err
}
err = behaviors.ValidateSuite(suite)
if err != nil {
return fmt.Errorf("error validating %s: %q", behaviorFile, err.Error())
}
for _, behavior := range suite.Behaviors {
behaviorsMapping[behavior.ID] = nil
}
}
conformanceYaml, err := ioutil.ReadFile(o.testdata)
if err != nil {
return fmt.Errorf("%s: %v", o.testdata, err)
}
err = yaml.Unmarshal(conformanceYaml, &conformanceDataList)
if err != nil {
return fmt.Errorf("%s: %v", o.testdata, err)
}
for _, data := range conformanceDataList {
for _, behaviorID := range data.Behaviors {
if _, ok := behaviorsMapping[behaviorID]; !ok {
return fmt.Errorf("cannot find behavior %q", behaviorID)
}
behaviorsMapping[behaviorID] = append(behaviorsMapping[behaviorID], data.CodeName)
}
}
printBehaviorsMapping(behaviorsMapping, o)
return nil
}
func printBehaviorsMapping(behaviorsMapping map[string][]string, o *options) {
for behaviorID, tests := range behaviorsMapping {
if o.listAll || tests == nil {
fmt.Println(" ", behaviorID)
}
}
}

1
vendor/modules.txt vendored
View File

@ -408,7 +408,6 @@ github.com/go-bindata/go-bindata/go-bindata
github.com/go-logr/logr github.com/go-logr/logr
# github.com/go-logr/logr => github.com/go-logr/logr v0.2.0 # github.com/go-logr/logr => github.com/go-logr/logr v0.2.0
# github.com/go-openapi/analysis v0.19.5 => github.com/go-openapi/analysis v0.19.5 # github.com/go-openapi/analysis v0.19.5 => github.com/go-openapi/analysis v0.19.5
## explicit
github.com/go-openapi/analysis github.com/go-openapi/analysis
# github.com/go-openapi/analysis => github.com/go-openapi/analysis v0.19.5 # github.com/go-openapi/analysis => github.com/go-openapi/analysis v0.19.5
github.com/go-openapi/analysis/internal github.com/go-openapi/analysis/internal