Merge pull request #21736 from resouer/check-register

Auto commit by PR queue bot
pull/6/head
k8s-merge-robot 2016-03-01 02:21:56 -08:00
commit e7d0f06c4a
4 changed files with 177 additions and 4 deletions

View File

@ -0,0 +1,80 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
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 codeinspector
import (
"fmt"
"go/ast"
"go/parser"
"go/token"
"io/ioutil"
"strings"
"unicode"
)
// GetPublicFunctions lists all public functions (not methods) from a golang source file.
func GetPublicFunctions(filePath string) ([]string, error) {
var functionNames []string
// Create the AST by parsing src.
fset := token.NewFileSet() // positions are relative to fset
f, err := parser.ParseFile(fset, filePath, nil, 0)
if err != nil {
return nil, fmt.Errorf("failed parse file to list functions: %v", err)
}
// Inspect the AST and print all identifiers and literals.
ast.Inspect(f, func(n ast.Node) bool {
var s string
switch x := n.(type) {
case *ast.FuncDecl:
s = x.Name.Name
// It's a function (not method), and is public, record it.
if x.Recv == nil && isPublic(s) {
functionNames = append(functionNames, s)
}
}
return true
})
return functionNames, nil
}
// isPublic checks if a given string is a public function name.
func isPublic(myString string) bool {
a := []rune(myString)
a[0] = unicode.ToUpper(a[0])
return myString == string(a)
}
// GetSourceCodeFiles lists golang source code files from directory, excluding sub-directory and tests files.
func GetSourceCodeFiles(dir string) ([]string, error) {
files, err := ioutil.ReadDir(dir)
if err != nil {
return nil, err
}
var filenames []string
for _, file := range files {
if strings.HasSuffix(file.Name(), ".go") && !strings.HasSuffix(file.Name(), "_test.go") {
filenames = append(filenames, file.Name())
}
}
return filenames, nil
}

View File

@ -469,9 +469,9 @@ func NewSelectorMatchPredicate(info NodeInfo) algorithm.FitPredicate {
return selector.PodSelectorMatches
}
// NodeMatchesNodeSelectorTerms checks if a node's labels satisfy a list of node selector terms,
// nodeMatchesNodeSelectorTerms checks if a node's labels satisfy a list of node selector terms,
// terms are ORed, and an emtpy a list of terms will match nothing.
func NodeMatchesNodeSelectorTerms(node *api.Node, nodeSelectorTerms []api.NodeSelectorTerm) bool {
func nodeMatchesNodeSelectorTerms(node *api.Node, nodeSelectorTerms []api.NodeSelectorTerm) bool {
for _, req := range nodeSelectorTerms {
nodeSelector, err := api.NodeSelectorRequirementsAsSelector(req.MatchExpressions)
if err != nil {
@ -524,14 +524,14 @@ func PodMatchesNodeLabels(pod *api.Pod, node *api.Node) bool {
// if nodeAffinity.RequiredDuringSchedulingRequiredDuringExecution != nil {
// nodeSelectorTerms := nodeAffinity.RequiredDuringSchedulingRequiredDuringExecution.NodeSelectorTerms
// glog.V(10).Infof("Match for RequiredDuringSchedulingRequiredDuringExecution node selector terms %+v", nodeSelectorTerms)
// nodeAffinityMatches = NodeMatchesNodeSelectorTerms(node, nodeSelectorTerms)
// nodeAffinityMatches = nodeMatchesNodeSelectorTerms(node, nodeSelectorTerms)
// }
// Match node selector for requiredDuringSchedulingIgnoredDuringExecution.
if nodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution != nil {
nodeSelectorTerms := nodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms
glog.V(10).Infof("Match for RequiredDuringSchedulingIgnoredDuringExecution node selector terms %+v", nodeSelectorTerms)
nodeAffinityMatches = nodeAffinityMatches && NodeMatchesNodeSelectorTerms(node, nodeSelectorTerms)
nodeAffinityMatches = nodeAffinityMatches && nodeMatchesNodeSelectorTerms(node, nodeSelectorTerms)
}
}

View File

@ -18,11 +18,13 @@ package predicates
import (
"fmt"
"os/exec"
"reflect"
"testing"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/resource"
"k8s.io/kubernetes/pkg/util/codeinspector"
"k8s.io/kubernetes/plugin/pkg/scheduler/algorithm"
"k8s.io/kubernetes/plugin/pkg/scheduler/schedulercache"
)
@ -1408,3 +1410,48 @@ func TestEBSVolumeCountConflicts(t *testing.T) {
}
}
}
func TestPredicatesRegistered(t *testing.T) {
var functionNames []string
// Files and directories which predicates may be referenced
targetFiles := []string{
"./../../algorithmprovider/defaults/defaults.go", // Default algorithm
"./../../factory/plugins.go", // Registered in init()
"./../../../../../pkg/", // kubernetes/pkg, often used by kubelet or controller
}
// List all golang source files under ./predicates/, excluding test files and sub-directories.
files, err := codeinspector.GetSourceCodeFiles(".")
if err != nil {
t.Errorf("unexpected error: %v when listing files in current directory", err)
}
// Get all public predicates in files.
for _, filePath := range files {
functions, err := codeinspector.GetPublicFunctions(filePath)
if err == nil {
functionNames = append(functionNames, functions...)
} else {
t.Errorf("unexpected error when parsing %s", filePath)
}
}
// Check if all public predicates are referenced in target files.
for _, functionName := range functionNames {
args := []string{"-rl", functionName}
args = append(args, targetFiles...)
err := exec.Command("grep", args...).Run()
if err != nil {
switch err.Error() {
case "exit status 2":
t.Errorf("unexpected error when checking %s", functionName)
case "exit status 1":
t.Errorf("predicate %s is implemented as public but seems not registered or used in any other place",
functionName)
}
}
}
}

View File

@ -17,6 +17,7 @@ limitations under the License.
package priorities
import (
"os/exec"
"reflect"
"sort"
"strconv"
@ -25,6 +26,7 @@ import (
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/resource"
"k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/util/codeinspector"
"k8s.io/kubernetes/plugin/pkg/scheduler"
"k8s.io/kubernetes/plugin/pkg/scheduler/algorithm"
priorityutil "k8s.io/kubernetes/plugin/pkg/scheduler/algorithm/priorities/util"
@ -883,3 +885,47 @@ func makeImageNode(node string, status api.NodeStatus) api.Node {
Status: status,
}
}
func TestPrioritiesRegistered(t *testing.T) {
var functionNames []string
// Files and directories which priorities may be referenced
targetFiles := []string{
"./../../algorithmprovider/defaults/defaults.go", // Default algorithm
"./../../factory/plugins.go", // Registered in init()
}
// List all golang source files under ./priorities/, excluding test files and sub-directories.
files, err := codeinspector.GetSourceCodeFiles(".")
if err != nil {
t.Errorf("unexpected error: %v when listing files in current directory", err)
}
// Get all public priorities in files.
for _, filePath := range files {
functions, err := codeinspector.GetPublicFunctions(filePath)
if err == nil {
functionNames = append(functionNames, functions...)
} else {
t.Errorf("unexpected error when parsing %s", filePath)
}
}
// Check if all public priorities are referenced in target files.
for _, functionName := range functionNames {
args := []string{"-rl", functionName}
args = append(args, targetFiles...)
err := exec.Command("grep", args...).Run()
if err != nil {
switch err.Error() {
case "exit status 2":
t.Errorf("unexpected error when checking %s", functionName)
case "exit status 1":
t.Errorf("priority %s is implemented as public but seems not registered or used in any other place",
functionName)
}
}
}
}