Skip to content

Commit 1117410

Browse files
authored
Merge pull request kubernetes#91743 from spiffxp/fix-kubeconform-link
Merge behavior loading code
2 parents 42797ad + d960bf1 commit 1117410

File tree

6 files changed

+107
-72
lines changed

6 files changed

+107
-72
lines changed

test/conformance/behaviors/BUILD

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,23 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
22

33
go_library(
44
name = "go_default_library",
5-
srcs = ["types.go"],
5+
srcs = [
6+
"behaviors.go",
7+
"types.go",
8+
],
69
importpath = "k8s.io/kubernetes/test/conformance/behaviors",
710
visibility = ["//visibility:public"],
11+
deps = [
12+
"//staging/src/k8s.io/apimachinery/pkg/util/errors:go_default_library",
13+
"//vendor/gopkg.in/yaml.v2:go_default_library",
14+
],
815
)
916

1017
go_test(
1118
name = "go_default_test",
1219
srcs = ["behaviors_test.go"],
1320
data = glob(["*/*.yaml"]),
1421
embed = [":go_default_library"],
15-
deps = [
16-
"//vendor/gopkg.in/yaml.v2:go_default_library",
17-
],
1822
)
1923

2024
filegroup(
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
Copyright 2020 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package behaviors
18+
19+
import (
20+
"fmt"
21+
"io/ioutil"
22+
utilerrors "k8s.io/apimachinery/pkg/util/errors"
23+
"os"
24+
"path/filepath"
25+
"regexp"
26+
"strings"
27+
28+
"gopkg.in/yaml.v2"
29+
)
30+
31+
// BehaviorFileList returns a list of eligible behavior files in or under dir
32+
func BehaviorFileList(dir string) ([]string, error) {
33+
var behaviorFiles []string
34+
35+
r, _ := regexp.Compile(".+.yaml$")
36+
err := filepath.Walk(dir,
37+
func(path string, info os.FileInfo, err error) error {
38+
if err != nil {
39+
return err
40+
}
41+
if r.MatchString(path) {
42+
behaviorFiles = append(behaviorFiles, path)
43+
}
44+
return nil
45+
},
46+
)
47+
return behaviorFiles, err
48+
}
49+
50+
// LoadSuite loads a Behavior Suite from .yaml file at path
51+
func LoadSuite(path string) (*Suite, error) {
52+
var suite Suite
53+
bytes, err := ioutil.ReadFile(path)
54+
if err != nil {
55+
return nil, fmt.Errorf("error loading suite %s: %v", path, err)
56+
}
57+
err = yaml.UnmarshalStrict(bytes, &suite)
58+
if err != nil {
59+
return nil, fmt.Errorf("error loading suite %s: %v", path, err)
60+
}
61+
return &suite, nil
62+
}
63+
64+
// ValidateSuite validates that the given suite has no duplicate behavior IDs
65+
func ValidateSuite(suite *Suite) error {
66+
var errs []error
67+
behaviorsByID := make(map[string]bool)
68+
for _, b := range suite.Behaviors {
69+
if _, ok := behaviorsByID[b.ID]; ok {
70+
errs = append(errs, fmt.Errorf("Duplicate behavior ID: %s", b.ID))
71+
}
72+
if !strings.HasPrefix(b.ID, suite.Suite) {
73+
errs = append(errs, fmt.Errorf("Invalid behavior ID: %s, must have suite name as prefix: %s", b.ID, suite.Suite))
74+
}
75+
behaviorsByID[b.ID] = true
76+
}
77+
return utilerrors.NewAggregate(errs)
78+
}

test/conformance/behaviors/behaviors_test.go

Lines changed: 4 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -17,30 +17,11 @@ limitations under the License.
1717
package behaviors
1818

1919
import (
20-
"io/ioutil"
21-
"os"
22-
"path/filepath"
23-
"regexp"
2420
"testing"
25-
26-
"gopkg.in/yaml.v2"
2721
)
2822

2923
func TestValidate(t *testing.T) {
30-
var behaviorFiles []string
31-
32-
err := filepath.Walk(".",
33-
func(path string, info os.FileInfo, err error) error {
34-
if err != nil {
35-
t.Errorf("%q", err.Error())
36-
}
37-
38-
r, _ := regexp.Compile(".+.yaml$")
39-
if r.MatchString(path) {
40-
behaviorFiles = append(behaviorFiles, path)
41-
}
42-
return nil
43-
})
24+
behaviorFiles, err := BehaviorFileList(".")
4425
if err != nil {
4526
t.Errorf("%q", err.Error())
4627
}
@@ -51,25 +32,12 @@ func TestValidate(t *testing.T) {
5132
}
5233

5334
func validateSuite(path string, t *testing.T) {
54-
var suite Suite
55-
yamlFile, err := ioutil.ReadFile(path)
35+
suite, err := LoadSuite(path)
5636
if err != nil {
5737
t.Errorf("%q", err.Error())
5838
}
59-
err = yaml.Unmarshal(yamlFile, &suite)
60-
39+
err = ValidateSuite(suite)
6140
if err != nil {
62-
t.Errorf("%q", err.Error())
63-
}
64-
65-
behaviorIDList := make(map[string]bool)
66-
67-
for _, behavior := range suite.Behaviors {
68-
69-
// Ensure no behavior IDs are duplicated
70-
if _, ok := behaviorIDList[behavior.ID]; ok {
71-
t.Errorf("Duplicate behavior ID: %s", behavior.ID)
72-
}
73-
behaviorIDList[behavior.ID] = true
41+
t.Errorf("error validating %s: %q", path, err.Error())
7442
}
7543
}
Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,30 @@
11
suite: service/spec
22
description: Base suite for services
33
behaviors:
4-
- id: service/basic-create/selector
4+
- id: service/spec/selector/present-during-create
55
description: When a Service resource is created with type "ClusterIP", "NodePort", or "LoadBalancer",
66
and a selector is specified, an Endpoints object is generated based with the IPs of pods with
77
label keys and values matching the selector.
8-
- id: service/basic-create/no-selector
8+
- id: service/spec/selector/absent-during-create
99
description: When a Service resource is created and a no selector is specified, no changes are made
1010
to any corresponding Endpoints object.
11-
- id: service/type/ClusterIP/empty
11+
- id: service/spec/type/ClusterIP/empty
1212
description: When the Service type is specified as "ClusterIP" and the clusterIP
1313
field is empty, a cluster-internal IP address for load-balancing to endpoints is
1414
allocated.
15-
- id: service/type/ClusterIP/static
15+
- id: service/spec/type/ClusterIP/static
1616
description: When the Service type is specified as "ClusterIP" and the clusterIP
1717
field is specified as an IP address in the cluster service range, and that IP is
1818
not already assigned to another service, that IP is be allocated as a cluster-internal
1919
IP address for load-balancing to endpoints.
20-
- id: service/type/ClusterIP/None
20+
- id: service/spec/type/ClusterIP/None
2121
description: When the Service type is specified as "ClusterIP" and the clusterIP
2222
field is "None", no virtual IP is allocated and the endpoints are published as a
2323
set of endpoints rather than a stable IP.
24-
- id: service/type/NodePort
24+
- id: service/spec/type/NodePort
2525
description: When the Service type is specified as "NodePort" , a cluster-internal
2626
IP address for load-balancing to endpoints is allocated as for type "ClusterIP".
2727
Additionally, a cluster-wide port is allocated on every node, routing to the clusterIP.
28-
- id: service/type/ExternalName
28+
- id: service/spec/type/ExternalName
2929
description: When the Service type is specified as "ExternalName", the cluster DNS provider
3030
publishes a CNAME pointing from the service to the specified external name.

test/conformance/behaviors/sig-node/pod-spec.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ behaviors:
4242
description: When hostIPC is set to false, the Pod MUST NOT use the host's inter-process
4343
communication namespace.
4444
- id: pod/spec/label/create
45-
decription: Create a Pod with a unique label. Query for the Pod with the label as selector MUST be successful.
45+
description: Create a Pod with a unique label. Query for the Pod with the label as selector MUST be successful.
4646
- id: pod/spec/label/patch
47-
decription: A patch request must be able to update the pod to change the value of an existing Label. Query for the Pod with the new value for the label MUST be successful.
47+
description: A patch request must be able to update the pod to change the value of an existing Label. Query for the Pod with the new value for the label MUST be successful.
4848
- id: pod/spec/container/resources
4949
description: Create a Pod with CPU and Memory request and limits. Pod status MUST have QOSClass set to PodQOSGuaranteed.

test/conformance/kubeconform/link.go

Lines changed: 8 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -19,71 +19,56 @@ package main
1919
import (
2020
"fmt"
2121
"io/ioutil"
22-
"os"
23-
"path/filepath"
24-
"regexp"
2522

2623
"gopkg.in/yaml.v2"
2724

2825
"k8s.io/kubernetes/test/conformance/behaviors"
2926
)
3027

3128
func link(o *options) error {
32-
var behaviorFiles []string
3329
behaviorsMapping := make(map[string][]string)
3430
var conformanceDataList []behaviors.ConformanceData
3531

36-
err := filepath.Walk(o.behaviorsDir,
37-
func(path string, info os.FileInfo, err error) error {
38-
if err != nil {
39-
return err
40-
}
41-
r, _ := regexp.Compile(".+.yaml$")
42-
if r.MatchString(path) {
43-
behaviorFiles = append(behaviorFiles, path)
44-
}
45-
return nil
46-
})
32+
behaviorFiles, err := behaviors.BehaviorFileList(o.behaviorsDir)
4733
if err != nil {
4834
return err
4935
}
36+
5037
fmt.Println()
5138
fmt.Printf("Using behaviors from these %d files:\n", len(behaviorFiles))
5239
for _, f := range behaviorFiles {
5340
fmt.Println(" ", f)
5441
}
5542
fmt.Println()
43+
5644
if o.listAll {
5745
fmt.Println("All behaviors:")
5846
} else {
5947
fmt.Println("Behaviors not covered by any conformance test:")
6048
}
6149

6250
for _, behaviorFile := range behaviorFiles {
63-
var suite behaviors.Suite
64-
65-
yamlFile, err := ioutil.ReadFile(behaviorFile)
51+
suite, err := behaviors.LoadSuite(behaviorFile)
6652
if err != nil {
6753
return err
6854
}
69-
err = yaml.UnmarshalStrict(yamlFile, &suite)
55+
err = behaviors.ValidateSuite(suite)
7056
if err != nil {
71-
return err
57+
return fmt.Errorf("error validating %s: %q", behaviorFile, err.Error())
7258
}
73-
7459
for _, behavior := range suite.Behaviors {
7560
behaviorsMapping[behavior.ID] = nil
7661
}
7762
}
7863

7964
conformanceYaml, err := ioutil.ReadFile(o.testdata)
8065
if err != nil {
81-
return err
66+
return fmt.Errorf("%s: %v", o.testdata, err)
8267
}
8368

8469
err = yaml.Unmarshal(conformanceYaml, &conformanceDataList)
8570
if err != nil {
86-
return err
71+
return fmt.Errorf("%s: %v", o.testdata, err)
8772
}
8873

8974
for _, data := range conformanceDataList {

0 commit comments

Comments
 (0)