mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-20 10:20:51 +00:00
Merge pull request #78836 from dims/verify-import-aliases-during-typecheck
Verify import aliases
This commit is contained in:
commit
465e96535d
@ -31,6 +31,7 @@ filegroup(
|
||||
"//cmd/kubelet:all-srcs",
|
||||
"//cmd/kubemark:all-srcs",
|
||||
"//cmd/linkcheck:all-srcs",
|
||||
"//cmd/preferredimports:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
|
32
cmd/preferredimports/BUILD
Normal file
32
cmd/preferredimports/BUILD
Normal file
@ -0,0 +1,32 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_binary",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_binary(
|
||||
name = "preferredimports",
|
||||
embed = [":go_default_library"],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["preferredimports.go"],
|
||||
importpath = "k8s.io/kubernetes/cmd/preferredimports",
|
||||
deps = ["//vendor/golang.org/x/crypto/ssh/terminal:go_default_library"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
8
cmd/preferredimports/OWNERS
Normal file
8
cmd/preferredimports/OWNERS
Normal file
@ -0,0 +1,8 @@
|
||||
# See the OWNERS docs at https://go.k8s.io/owners
|
||||
|
||||
reviewers:
|
||||
- johnSchnake
|
||||
approvers:
|
||||
- dims
|
||||
- cblecker
|
||||
- spiffxp
|
263
cmd/preferredimports/preferredimports.go
Normal file
263
cmd/preferredimports/preferredimports.go
Normal file
@ -0,0 +1,263 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
// verify that all the imports have our preferred alias(es).
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/build"
|
||||
"go/format"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"golang.org/x/crypto/ssh/terminal"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
importAliases = flag.String("import-aliases", "hack/.import-aliases", "json file with import aliases")
|
||||
confirm = flag.Bool("confirm", false, "update file with the preferred aliases for imports")
|
||||
regex = flag.String("include-path", "(test/e2e/|test/e2e_node)", "only files with paths matching this regex is touched")
|
||||
isTerminal = terminal.IsTerminal(int(os.Stdout.Fd()))
|
||||
logPrefix = ""
|
||||
aliases map[string]string
|
||||
)
|
||||
|
||||
type analyzer struct {
|
||||
fset *token.FileSet // positions are relative to fset
|
||||
ctx build.Context
|
||||
failed bool
|
||||
donePaths map[string]interface{}
|
||||
errors []string
|
||||
}
|
||||
|
||||
func newAnalyzer() *analyzer {
|
||||
ctx := build.Default
|
||||
ctx.CgoEnabled = true
|
||||
|
||||
a := &analyzer{
|
||||
fset: token.NewFileSet(),
|
||||
ctx: ctx,
|
||||
donePaths: make(map[string]interface{}),
|
||||
}
|
||||
|
||||
return a
|
||||
}
|
||||
|
||||
// collect extracts test metadata from a file.
|
||||
func (a *analyzer) collect(dir string) {
|
||||
if _, ok := a.donePaths[dir]; ok {
|
||||
return
|
||||
}
|
||||
a.donePaths[dir] = nil
|
||||
|
||||
// Create the AST by parsing src.
|
||||
fs, err := parser.ParseDir(a.fset, dir, nil, parser.AllErrors|parser.ParseComments)
|
||||
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, "ERROR(syntax)", logPrefix, err)
|
||||
a.failed = true
|
||||
return
|
||||
}
|
||||
|
||||
for _, p := range fs {
|
||||
// returns first error, but a.handleError deals with it
|
||||
files := a.filterFiles(p.Files)
|
||||
for _, file := range files {
|
||||
replacements := make(map[string]string)
|
||||
pathToFile := a.fset.File(file.Pos()).Name()
|
||||
for _, imp := range file.Imports {
|
||||
importPath := strings.Replace(imp.Path.Value, "\"", "", -1)
|
||||
pathSegments := strings.Split(importPath, "/")
|
||||
importName := pathSegments[len(pathSegments)-1]
|
||||
if imp.Name != nil {
|
||||
importName = imp.Name.Name
|
||||
}
|
||||
if alias, ok := aliases[importPath]; ok {
|
||||
if alias != importName {
|
||||
if !*confirm {
|
||||
fmt.Fprintf(os.Stderr, "%sERROR wrong alias for import \"%s\" should be %s in file %s\n", logPrefix, importPath, alias, pathToFile)
|
||||
a.failed = true
|
||||
}
|
||||
replacements[importName] = alias
|
||||
if imp.Name != nil {
|
||||
imp.Name.Name = alias
|
||||
} else {
|
||||
imp.Name = ast.NewIdent(alias)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(replacements) > 0 {
|
||||
if *confirm {
|
||||
fmt.Printf("%sReplacing imports with aliases in file %s\n", logPrefix, pathToFile)
|
||||
for key, value := range replacements {
|
||||
renameImportUsages(file, key, value)
|
||||
}
|
||||
ast.SortImports(a.fset, file)
|
||||
var buffer bytes.Buffer
|
||||
if err = format.Node(&buffer, a.fset, file); err != nil {
|
||||
panic(fmt.Sprintf("Error formatting ast node after rewriting import.\n%s\n", err.Error()))
|
||||
}
|
||||
|
||||
fileInfo, err := os.Stat(pathToFile)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Error stat'ing file: %s\n%s\n", pathToFile, err.Error()))
|
||||
}
|
||||
|
||||
err = ioutil.WriteFile(pathToFile, buffer.Bytes(), fileInfo.Mode())
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Error writing file: %s\n%s\n", pathToFile, err.Error()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func renameImportUsages(f *ast.File, old, new string) {
|
||||
// use this to avoid renaming the package declaration, eg:
|
||||
// given: package foo; import foo "bar"; foo.Baz, rename foo->qux
|
||||
// yield: package foo; import qux "bar"; qux.Baz
|
||||
var pkg *ast.Ident
|
||||
|
||||
// Rename top-level old to new, both unresolved names
|
||||
// (probably defined in another file) and names that resolve
|
||||
// to a declaration we renamed.
|
||||
ast.Inspect(f, func(node ast.Node) bool {
|
||||
if node == nil {
|
||||
return false
|
||||
}
|
||||
switch id := node.(type) {
|
||||
case *ast.File:
|
||||
pkg = id.Name
|
||||
case *ast.Ident:
|
||||
if pkg != nil && id == pkg {
|
||||
return false
|
||||
}
|
||||
if id.Name == old {
|
||||
id.Name = new
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
func (a *analyzer) filterFiles(fs map[string]*ast.File) []*ast.File {
|
||||
var files []*ast.File
|
||||
for _, f := range fs {
|
||||
files = append(files, f)
|
||||
}
|
||||
return files
|
||||
}
|
||||
|
||||
type collector struct {
|
||||
dirs []string
|
||||
regex *regexp.Regexp
|
||||
}
|
||||
|
||||
// handlePath walks the filesystem recursively, collecting directories,
|
||||
// ignoring some unneeded directories (hidden/vendored) that are handled
|
||||
// specially later.
|
||||
func (c *collector) handlePath(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if info.IsDir() {
|
||||
// Ignore hidden directories (.git, .cache, etc)
|
||||
if len(path) > 1 && path[0] == '.' ||
|
||||
// Staging code is symlinked from vendor/k8s.io, and uses import
|
||||
// paths as if it were inside of vendor/. It fails typechecking
|
||||
// inside of staging/, but works when typechecked as part of vendor/.
|
||||
path == "staging" ||
|
||||
// OS-specific vendor code tends to be imported by OS-specific
|
||||
// packages. We recursively typecheck imported vendored packages for
|
||||
// each OS, but don't typecheck everything for every OS.
|
||||
path == "vendor" ||
|
||||
path == "_output" ||
|
||||
// This is a weird one. /testdata/ is *mostly* ignored by Go,
|
||||
// and this translates to kubernetes/vendor not working.
|
||||
// edit/record.go doesn't compile without gopkg.in/yaml.v2
|
||||
// in $GOSRC/$GOROOT (both typecheck and the shell script).
|
||||
path == "pkg/kubectl/cmd/testdata/edit" {
|
||||
return filepath.SkipDir
|
||||
}
|
||||
if c.regex.MatchString(path) {
|
||||
c.dirs = append(c.dirs, path)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
args := flag.Args()
|
||||
|
||||
if len(args) == 0 {
|
||||
args = append(args, ".")
|
||||
}
|
||||
|
||||
regex, err := regexp.Compile(*regex)
|
||||
if err != nil {
|
||||
log.Fatalf("Error compiling regex: %v", err)
|
||||
}
|
||||
c := collector{regex: regex}
|
||||
for _, arg := range args {
|
||||
err := filepath.Walk(arg, c.handlePath)
|
||||
if err != nil {
|
||||
log.Fatalf("Error walking: %v", err)
|
||||
}
|
||||
}
|
||||
sort.Strings(c.dirs)
|
||||
|
||||
if len(*importAliases) > 0 {
|
||||
bytes, err := ioutil.ReadFile(*importAliases)
|
||||
if err != nil {
|
||||
log.Fatalf("Error reading import aliases: %v", err)
|
||||
}
|
||||
err = json.Unmarshal(bytes, &aliases)
|
||||
if err != nil {
|
||||
log.Fatalf("Error loading aliases: %v", err)
|
||||
}
|
||||
}
|
||||
if isTerminal {
|
||||
logPrefix = "\r" // clear status bar when printing
|
||||
}
|
||||
fmt.Println("checking-imports: ")
|
||||
|
||||
a := newAnalyzer()
|
||||
for _, dir := range c.dirs {
|
||||
if isTerminal {
|
||||
fmt.Printf("\r\033[0m %-80s", dir)
|
||||
}
|
||||
a.collect(dir)
|
||||
}
|
||||
fmt.Println()
|
||||
if a.failed {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
3
hack/.import-aliases
Normal file
3
hack/.import-aliases
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1": "kubeletstatsv1alpha1"
|
||||
}
|
@ -35,6 +35,7 @@ EXCLUDED_PATTERNS=(
|
||||
"verify-linkcheck.sh" # runs in separate Jenkins job once per day due to high network usage
|
||||
"verify-test-owners.sh" # TODO(rmmh): figure out how to avoid endless conflicts
|
||||
"verify-*-dockerized.sh" # Don't run any scripts that intended to be run dockerized
|
||||
"verify-import-aliases.sh" # to be run periodically by folks working on conformance tests
|
||||
)
|
||||
|
||||
# Exclude typecheck in certain cases, if they're running in a separate job.
|
||||
|
34
hack/update-import-aliases.sh
Executable file
34
hack/update-import-aliases.sh
Executable file
@ -0,0 +1,34 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# 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.
|
||||
|
||||
set -o errexit
|
||||
set -o nounset
|
||||
set -o pipefail
|
||||
|
||||
KUBE_ROOT=$(dirname "${BASH_SOURCE[0]}")/..
|
||||
source "${KUBE_ROOT}/hack/lib/init.sh"
|
||||
|
||||
kube::golang::verify_go_version
|
||||
|
||||
cd "${KUBE_ROOT}"
|
||||
|
||||
ret=0
|
||||
go run cmd/preferredimports/preferredimports.go --confirm "$@" || ret=$?
|
||||
if [[ $ret -ne 0 ]]; then
|
||||
echo "!!! Unable to fix imports programmatically. Please see errors above." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
34
hack/verify-import-aliases.sh
Executable file
34
hack/verify-import-aliases.sh
Executable file
@ -0,0 +1,34 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# 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.
|
||||
|
||||
set -o errexit
|
||||
set -o nounset
|
||||
set -o pipefail
|
||||
|
||||
KUBE_ROOT=$(dirname "${BASH_SOURCE[0]}")/..
|
||||
source "${KUBE_ROOT}/hack/lib/init.sh"
|
||||
|
||||
kube::golang::verify_go_version
|
||||
|
||||
cd "${KUBE_ROOT}"
|
||||
|
||||
ret=0
|
||||
go run cmd/preferredimports/preferredimports.go "$@" || ret=$?
|
||||
if [[ $ret -ne 0 ]]; then
|
||||
echo "!!! Please see hack/.import-aliases for the preferred aliases for imports." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
@ -34,7 +34,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
stats "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1"
|
||||
kubeletstatsv1alpha1 "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1"
|
||||
dockermetrics "k8s.io/kubernetes/pkg/kubelet/dockershim/metrics"
|
||||
kubeletmetrics "k8s.io/kubernetes/pkg/kubelet/metrics"
|
||||
"k8s.io/kubernetes/pkg/master/ports"
|
||||
@ -285,7 +285,7 @@ func HighLatencyKubeletOperations(c clientset.Interface, threshold time.Duration
|
||||
}
|
||||
|
||||
// GetStatsSummary contacts kubelet for the container information.
|
||||
func GetStatsSummary(c clientset.Interface, nodeName string) (*stats.Summary, error) {
|
||||
func GetStatsSummary(c clientset.Interface, nodeName string) (*kubeletstatsv1alpha1.Summary, error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), SingleCallTimeout)
|
||||
defer cancel()
|
||||
|
||||
@ -301,7 +301,7 @@ func GetStatsSummary(c clientset.Interface, nodeName string) (*stats.Summary, er
|
||||
return nil, err
|
||||
}
|
||||
|
||||
summary := stats.Summary{}
|
||||
summary := kubeletstatsv1alpha1.Summary{}
|
||||
err = json.Unmarshal(data, &summary)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -356,7 +356,7 @@ func getOneTimeResourceUsageOnNode(
|
||||
return nil, err
|
||||
}
|
||||
|
||||
f := func(name string, newStats *stats.ContainerStats) *ContainerResourceUsage {
|
||||
f := func(name string, newStats *kubeletstatsv1alpha1.ContainerStats) *ContainerResourceUsage {
|
||||
if newStats == nil || newStats.CPU == nil || newStats.Memory == nil {
|
||||
return nil
|
||||
}
|
||||
@ -395,7 +395,7 @@ func getOneTimeResourceUsageOnNode(
|
||||
return usageMap, nil
|
||||
}
|
||||
|
||||
func getNodeStatsSummary(c clientset.Interface, nodeName string) (*stats.Summary, error) {
|
||||
func getNodeStatsSummary(c clientset.Interface, nodeName string) (*kubeletstatsv1alpha1.Summary, error) {
|
||||
data, err := c.CoreV1().RESTClient().Get().
|
||||
Resource("nodes").
|
||||
SubResource("proxy").
|
||||
@ -408,7 +408,7 @@ func getNodeStatsSummary(c clientset.Interface, nodeName string) (*stats.Summary
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var summary *stats.Summary
|
||||
var summary *kubeletstatsv1alpha1.Summary
|
||||
err = json.Unmarshal(data, &summary)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -416,16 +416,16 @@ func getNodeStatsSummary(c clientset.Interface, nodeName string) (*stats.Summary
|
||||
return summary, nil
|
||||
}
|
||||
|
||||
func getSystemContainerStats(summary *stats.Summary) map[string]*stats.ContainerStats {
|
||||
func getSystemContainerStats(summary *kubeletstatsv1alpha1.Summary) map[string]*kubeletstatsv1alpha1.ContainerStats {
|
||||
statsList := summary.Node.SystemContainers
|
||||
statsMap := make(map[string]*stats.ContainerStats)
|
||||
statsMap := make(map[string]*kubeletstatsv1alpha1.ContainerStats)
|
||||
for i := range statsList {
|
||||
statsMap[statsList[i].Name] = &statsList[i]
|
||||
}
|
||||
|
||||
// Create a root container stats using information available in
|
||||
// stats.NodeStats. This is necessary since it is a different type.
|
||||
statsMap[rootContainerName] = &stats.ContainerStats{
|
||||
statsMap[rootContainerName] = &kubeletstatsv1alpha1.ContainerStats{
|
||||
CPU: summary.Node.CPU,
|
||||
Memory: summary.Node.Memory,
|
||||
}
|
||||
@ -440,8 +440,8 @@ const (
|
||||
func TargetContainers() []string {
|
||||
return []string{
|
||||
rootContainerName,
|
||||
stats.SystemContainerRuntime,
|
||||
stats.SystemContainerKubelet,
|
||||
kubeletstatsv1alpha1.SystemContainerRuntime,
|
||||
kubeletstatsv1alpha1.SystemContainerKubelet,
|
||||
}
|
||||
}
|
||||
|
||||
@ -508,10 +508,10 @@ func GetKubeletHeapStats(c clientset.Interface, nodeName string) (string, error)
|
||||
if errRaw != nil {
|
||||
return "", err
|
||||
}
|
||||
stats := string(raw)
|
||||
kubeletstatsv1alpha1 := string(raw)
|
||||
// Only dumping the runtime.MemStats numbers to avoid polluting the log.
|
||||
numLines := 23
|
||||
lines := strings.Split(stats, "\n")
|
||||
lines := strings.Split(kubeletstatsv1alpha1, "\n")
|
||||
return strings.Join(lines[len(lines)-numLines:], "\n"), nil
|
||||
}
|
||||
|
||||
@ -531,7 +531,7 @@ func PrintAllKubeletPods(c clientset.Interface, nodeName string) {
|
||||
}
|
||||
}
|
||||
|
||||
func computeContainerResourceUsage(name string, oldStats, newStats *stats.ContainerStats) *ContainerResourceUsage {
|
||||
func computeContainerResourceUsage(name string, oldStats, newStats *kubeletstatsv1alpha1.ContainerStats) *ContainerResourceUsage {
|
||||
return &ContainerResourceUsage{
|
||||
Name: name,
|
||||
Timestamp: newStats.CPU.Time.Time,
|
||||
@ -571,7 +571,7 @@ func newResourceCollector(c clientset.Interface, nodeName string, containerNames
|
||||
func (r *resourceCollector) Start() {
|
||||
r.stopCh = make(chan struct{}, 1)
|
||||
// Keep the last observed stats for comparison.
|
||||
oldStats := make(map[string]*stats.ContainerStats)
|
||||
oldStats := make(map[string]*kubeletstatsv1alpha1.ContainerStats)
|
||||
go wait.Until(func() { r.collectStats(oldStats) }, r.pollingInterval, r.stopCh)
|
||||
}
|
||||
|
||||
@ -582,7 +582,7 @@ func (r *resourceCollector) Stop() {
|
||||
|
||||
// collectStats gets the latest stats from kubelet stats summary API, computes
|
||||
// the resource usage, and pushes it to the buffer.
|
||||
func (r *resourceCollector) collectStats(oldStatsMap map[string]*stats.ContainerStats) {
|
||||
func (r *resourceCollector) collectStats(oldStatsMap map[string]*kubeletstatsv1alpha1.ContainerStats) {
|
||||
summary, err := getNodeStatsSummary(r.client, r.node)
|
||||
if err != nil {
|
||||
e2elog.Logf("Error getting node stats summary on %q, err: %v", r.node, err)
|
||||
@ -613,15 +613,15 @@ func (r *resourceCollector) collectStats(oldStatsMap map[string]*stats.Container
|
||||
func (r *resourceCollector) GetLatest() (ResourceUsagePerContainer, error) {
|
||||
r.lock.RLock()
|
||||
defer r.lock.RUnlock()
|
||||
stats := make(ResourceUsagePerContainer)
|
||||
kubeletstatsv1alpha1 := make(ResourceUsagePerContainer)
|
||||
for _, name := range r.containers {
|
||||
contStats, ok := r.buffers[name]
|
||||
if !ok || len(contStats) == 0 {
|
||||
return nil, fmt.Errorf("Resource usage on node %q is not ready yet", r.node)
|
||||
}
|
||||
stats[name] = contStats[len(contStats)-1]
|
||||
kubeletstatsv1alpha1[name] = contStats[len(contStats)-1]
|
||||
}
|
||||
return stats, nil
|
||||
return kubeletstatsv1alpha1, nil
|
||||
}
|
||||
|
||||
// Reset frees the stats and start over.
|
||||
|
@ -24,7 +24,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apimachinery/pkg/util/uuid"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
stats "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1"
|
||||
kubeletstatsv1alpha1 "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1"
|
||||
"k8s.io/kubernetes/test/e2e/framework"
|
||||
e2elog "k8s.io/kubernetes/test/e2e/framework/log"
|
||||
testutils "k8s.io/kubernetes/test/utils"
|
||||
@ -234,24 +234,24 @@ var _ = SIGDescribe("Kubelet [Serial] [Slow]", func() {
|
||||
{
|
||||
podsPerNode: 0,
|
||||
cpuLimits: framework.ContainersCPUSummary{
|
||||
stats.SystemContainerKubelet: {0.50: 0.10, 0.95: 0.20},
|
||||
stats.SystemContainerRuntime: {0.50: 0.10, 0.95: 0.20},
|
||||
kubeletstatsv1alpha1.SystemContainerKubelet: {0.50: 0.10, 0.95: 0.20},
|
||||
kubeletstatsv1alpha1.SystemContainerRuntime: {0.50: 0.10, 0.95: 0.20},
|
||||
},
|
||||
memLimits: framework.ResourceUsagePerContainer{
|
||||
stats.SystemContainerKubelet: &framework.ContainerResourceUsage{MemoryRSSInBytes: 200 * 1024 * 1024},
|
||||
kubeletstatsv1alpha1.SystemContainerKubelet: &framework.ContainerResourceUsage{MemoryRSSInBytes: 200 * 1024 * 1024},
|
||||
// The detail can be found at https://github.com/kubernetes/kubernetes/issues/28384#issuecomment-244158892
|
||||
stats.SystemContainerRuntime: &framework.ContainerResourceUsage{MemoryRSSInBytes: 125 * 1024 * 1024},
|
||||
kubeletstatsv1alpha1.SystemContainerRuntime: &framework.ContainerResourceUsage{MemoryRSSInBytes: 125 * 1024 * 1024},
|
||||
},
|
||||
},
|
||||
{
|
||||
cpuLimits: framework.ContainersCPUSummary{
|
||||
stats.SystemContainerKubelet: {0.50: 0.35, 0.95: 0.50},
|
||||
stats.SystemContainerRuntime: {0.50: 0.10, 0.95: 0.50},
|
||||
kubeletstatsv1alpha1.SystemContainerKubelet: {0.50: 0.35, 0.95: 0.50},
|
||||
kubeletstatsv1alpha1.SystemContainerRuntime: {0.50: 0.10, 0.95: 0.50},
|
||||
},
|
||||
podsPerNode: 100,
|
||||
memLimits: framework.ResourceUsagePerContainer{
|
||||
stats.SystemContainerKubelet: &framework.ContainerResourceUsage{MemoryRSSInBytes: 300 * 1024 * 1024},
|
||||
stats.SystemContainerRuntime: &framework.ContainerResourceUsage{MemoryRSSInBytes: 350 * 1024 * 1024},
|
||||
kubeletstatsv1alpha1.SystemContainerKubelet: &framework.ContainerResourceUsage{MemoryRSSInBytes: 300 * 1024 * 1024},
|
||||
kubeletstatsv1alpha1.SystemContainerRuntime: &framework.ContainerResourceUsage{MemoryRSSInBytes: 350 * 1024 * 1024},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
kubeletconfig "k8s.io/kubernetes/pkg/kubelet/apis/config"
|
||||
stats "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1"
|
||||
kubeletstatsv1alpha1 "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1"
|
||||
kubemetrics "k8s.io/kubernetes/pkg/kubelet/metrics"
|
||||
"k8s.io/kubernetes/test/e2e/framework"
|
||||
e2elog "k8s.io/kubernetes/test/e2e/framework/log"
|
||||
@ -77,12 +77,12 @@ var _ = framework.KubeDescribe("Density [Serial] [Slow]", func() {
|
||||
podsNr: 10,
|
||||
interval: 0 * time.Millisecond,
|
||||
cpuLimits: framework.ContainersCPUSummary{
|
||||
stats.SystemContainerKubelet: {0.50: 0.30, 0.95: 0.50},
|
||||
stats.SystemContainerRuntime: {0.50: 0.40, 0.95: 0.60},
|
||||
kubeletstatsv1alpha1.SystemContainerKubelet: {0.50: 0.30, 0.95: 0.50},
|
||||
kubeletstatsv1alpha1.SystemContainerRuntime: {0.50: 0.40, 0.95: 0.60},
|
||||
},
|
||||
memLimits: framework.ResourceUsagePerContainer{
|
||||
stats.SystemContainerKubelet: &framework.ContainerResourceUsage{MemoryRSSInBytes: 100 * 1024 * 1024},
|
||||
stats.SystemContainerRuntime: &framework.ContainerResourceUsage{MemoryRSSInBytes: 500 * 1024 * 1024},
|
||||
kubeletstatsv1alpha1.SystemContainerKubelet: &framework.ContainerResourceUsage{MemoryRSSInBytes: 100 * 1024 * 1024},
|
||||
kubeletstatsv1alpha1.SystemContainerRuntime: &framework.ContainerResourceUsage{MemoryRSSInBytes: 500 * 1024 * 1024},
|
||||
},
|
||||
// percentile limit of single pod startup latency
|
||||
podStartupLimits: framework.LatencyMetric{
|
||||
@ -224,12 +224,12 @@ var _ = framework.KubeDescribe("Density [Serial] [Slow]", func() {
|
||||
podsNr: 10,
|
||||
bgPodsNr: 50,
|
||||
cpuLimits: framework.ContainersCPUSummary{
|
||||
stats.SystemContainerKubelet: {0.50: 0.30, 0.95: 0.50},
|
||||
stats.SystemContainerRuntime: {0.50: 0.40, 0.95: 0.60},
|
||||
kubeletstatsv1alpha1.SystemContainerKubelet: {0.50: 0.30, 0.95: 0.50},
|
||||
kubeletstatsv1alpha1.SystemContainerRuntime: {0.50: 0.40, 0.95: 0.60},
|
||||
},
|
||||
memLimits: framework.ResourceUsagePerContainer{
|
||||
stats.SystemContainerKubelet: &framework.ContainerResourceUsage{MemoryRSSInBytes: 100 * 1024 * 1024},
|
||||
stats.SystemContainerRuntime: &framework.ContainerResourceUsage{MemoryRSSInBytes: 500 * 1024 * 1024},
|
||||
kubeletstatsv1alpha1.SystemContainerKubelet: &framework.ContainerResourceUsage{MemoryRSSInBytes: 100 * 1024 * 1024},
|
||||
kubeletstatsv1alpha1.SystemContainerRuntime: &framework.ContainerResourceUsage{MemoryRSSInBytes: 500 * 1024 * 1024},
|
||||
},
|
||||
podStartupLimits: framework.LatencyMetric{
|
||||
Perc50: 5000 * time.Millisecond,
|
||||
|
@ -30,7 +30,7 @@ import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/fields"
|
||||
kubeletconfig "k8s.io/kubernetes/pkg/kubelet/apis/config"
|
||||
stats "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1"
|
||||
kubeletstatsv1alpha1 "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1"
|
||||
"k8s.io/kubernetes/pkg/kubelet/eviction"
|
||||
evictionapi "k8s.io/kubernetes/pkg/kubelet/eviction/api"
|
||||
kubeletmetrics "k8s.io/kubernetes/pkg/kubelet/metrics"
|
||||
@ -751,7 +751,7 @@ func logMemoryMetrics() {
|
||||
e2elog.Logf("Node.Memory.WorkingSetBytes: %d, Node.Memory.AvailableBytes: %d", *summary.Node.Memory.WorkingSetBytes, *summary.Node.Memory.AvailableBytes)
|
||||
}
|
||||
for _, sysContainer := range summary.Node.SystemContainers {
|
||||
if sysContainer.Name == stats.SystemContainerPods && sysContainer.Memory != nil && sysContainer.Memory.WorkingSetBytes != nil && sysContainer.Memory.AvailableBytes != nil {
|
||||
if sysContainer.Name == kubeletstatsv1alpha1.SystemContainerPods && sysContainer.Memory != nil && sysContainer.Memory.WorkingSetBytes != nil && sysContainer.Memory.AvailableBytes != nil {
|
||||
e2elog.Logf("Allocatable.Memory.WorkingSetBytes: %d, Allocatable.Memory.AvailableBytes: %d", *sysContainer.Memory.WorkingSetBytes, *sysContainer.Memory.AvailableBytes)
|
||||
}
|
||||
}
|
||||
@ -776,7 +776,7 @@ func logPidMetrics() {
|
||||
}
|
||||
}
|
||||
|
||||
func eventuallyGetSummary() (s *stats.Summary) {
|
||||
func eventuallyGetSummary() (s *kubeletstatsv1alpha1.Summary) {
|
||||
Eventually(func() error {
|
||||
summary, err := getNodeSummary()
|
||||
if err != nil {
|
||||
|
@ -40,7 +40,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/uuid"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
stats "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1"
|
||||
kubeletstatsv1alpha1 "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1"
|
||||
"k8s.io/kubernetes/pkg/util/procfs"
|
||||
"k8s.io/kubernetes/test/e2e/framework"
|
||||
e2elog "k8s.io/kubernetes/test/e2e/framework/log"
|
||||
@ -92,8 +92,8 @@ func (r *ResourceCollector) Start() {
|
||||
runtimeContainer, err2 := getContainerNameForProcess(framework.TestContext.ContainerRuntimeProcessName, framework.TestContext.ContainerRuntimePidFile)
|
||||
if err1 == nil && err2 == nil {
|
||||
systemContainers = map[string]string{
|
||||
stats.SystemContainerKubelet: kubeletContainer,
|
||||
stats.SystemContainerRuntime: runtimeContainer,
|
||||
kubeletstatsv1alpha1.SystemContainerKubelet: kubeletContainer,
|
||||
kubeletstatsv1alpha1.SystemContainerRuntime: runtimeContainer,
|
||||
}
|
||||
} else {
|
||||
framework.Failf("Failed to get runtime container name in test-e2e-node resource collector.")
|
||||
@ -190,15 +190,15 @@ func computeContainerResourceUsage(name string, oldStats, newStats *cadvisorapiv
|
||||
func (r *ResourceCollector) GetLatest() (framework.ResourceUsagePerContainer, error) {
|
||||
r.lock.RLock()
|
||||
defer r.lock.RUnlock()
|
||||
stats := make(framework.ResourceUsagePerContainer)
|
||||
kubeletstatsv1alpha1 := make(framework.ResourceUsagePerContainer)
|
||||
for key, name := range systemContainers {
|
||||
contStats, ok := r.buffers[name]
|
||||
if !ok || len(contStats) == 0 {
|
||||
return nil, fmt.Errorf("No resource usage data for %s container (%s)", key, name)
|
||||
}
|
||||
stats[key] = contStats[len(contStats)-1]
|
||||
kubeletstatsv1alpha1[key] = contStats[len(contStats)-1]
|
||||
}
|
||||
return stats, nil
|
||||
return kubeletstatsv1alpha1, nil
|
||||
}
|
||||
|
||||
type resourceUsageByCPU []*framework.ContainerResourceUsage
|
||||
|
@ -24,7 +24,7 @@ import (
|
||||
"time"
|
||||
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
stats "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1"
|
||||
kubeletstatsv1alpha1 "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1"
|
||||
"k8s.io/kubernetes/test/e2e/framework"
|
||||
e2elog "k8s.io/kubernetes/test/e2e/framework/log"
|
||||
imageutils "k8s.io/kubernetes/test/utils/image"
|
||||
@ -68,12 +68,12 @@ var _ = SIGDescribe("Resource-usage [Serial] [Slow]", func() {
|
||||
{
|
||||
podsNr: 10,
|
||||
cpuLimits: framework.ContainersCPUSummary{
|
||||
stats.SystemContainerKubelet: {0.50: 0.30, 0.95: 0.35},
|
||||
stats.SystemContainerRuntime: {0.50: 0.30, 0.95: 0.40},
|
||||
kubeletstatsv1alpha1.SystemContainerKubelet: {0.50: 0.30, 0.95: 0.35},
|
||||
kubeletstatsv1alpha1.SystemContainerRuntime: {0.50: 0.30, 0.95: 0.40},
|
||||
},
|
||||
memLimits: framework.ResourceUsagePerContainer{
|
||||
stats.SystemContainerKubelet: &framework.ContainerResourceUsage{MemoryRSSInBytes: 200 * 1024 * 1024},
|
||||
stats.SystemContainerRuntime: &framework.ContainerResourceUsage{MemoryRSSInBytes: 400 * 1024 * 1024},
|
||||
kubeletstatsv1alpha1.SystemContainerKubelet: &framework.ContainerResourceUsage{MemoryRSSInBytes: 200 * 1024 * 1024},
|
||||
kubeletstatsv1alpha1.SystemContainerRuntime: &framework.ContainerResourceUsage{MemoryRSSInBytes: 400 * 1024 * 1024},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ import (
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
stats "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1"
|
||||
kubeletstatsv1alpha1 "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1"
|
||||
"k8s.io/kubernetes/test/e2e/framework"
|
||||
e2elog "k8s.io/kubernetes/test/e2e/framework/log"
|
||||
"k8s.io/kubernetes/test/e2e/framework/volume"
|
||||
@ -382,13 +382,13 @@ func getSummaryTestPods(f *framework.Framework, numRestarts int32, names ...stri
|
||||
// Mapping function for gstruct.MatchAllElements
|
||||
func summaryObjectID(element interface{}) string {
|
||||
switch el := element.(type) {
|
||||
case stats.PodStats:
|
||||
case kubeletstatsv1alpha1.PodStats:
|
||||
return fmt.Sprintf("%s::%s", el.PodRef.Namespace, el.PodRef.Name)
|
||||
case stats.ContainerStats:
|
||||
case kubeletstatsv1alpha1.ContainerStats:
|
||||
return el.Name
|
||||
case stats.VolumeStats:
|
||||
case kubeletstatsv1alpha1.VolumeStats:
|
||||
return el.Name
|
||||
case stats.UserDefinedMetric:
|
||||
case kubeletstatsv1alpha1.UserDefinedMetric:
|
||||
return el.Name
|
||||
default:
|
||||
framework.Failf("Unknown type: %T", el)
|
||||
|
@ -43,7 +43,7 @@ import (
|
||||
kubeletconfig "k8s.io/kubernetes/pkg/kubelet/apis/config"
|
||||
"k8s.io/kubernetes/pkg/kubelet/apis/podresources"
|
||||
podresourcesapi "k8s.io/kubernetes/pkg/kubelet/apis/podresources/v1alpha1"
|
||||
stats "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1"
|
||||
kubeletstatsv1alpha1 "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1"
|
||||
"k8s.io/kubernetes/pkg/kubelet/cm"
|
||||
kubeletconfigcodec "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/codec"
|
||||
kubeletmetrics "k8s.io/kubernetes/pkg/kubelet/metrics"
|
||||
@ -75,7 +75,7 @@ const (
|
||||
defaultPodResourcesMaxSize = 1024 * 1024 * 16 // 16 Mb
|
||||
)
|
||||
|
||||
func getNodeSummary() (*stats.Summary, error) {
|
||||
func getNodeSummary() (*kubeletstatsv1alpha1.Summary, error) {
|
||||
req, err := http.NewRequest("GET", *kubeletAddress+"/stats/summary", nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to build http request: %v", err)
|
||||
@ -95,7 +95,7 @@ func getNodeSummary() (*stats.Summary, error) {
|
||||
}
|
||||
|
||||
decoder := json.NewDecoder(strings.NewReader(string(contentsBytes)))
|
||||
summary := stats.Summary{}
|
||||
summary := kubeletstatsv1alpha1.Summary{}
|
||||
err = decoder.Decode(&summary)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse /stats/summary to go struct: %+v", resp)
|
||||
|
Loading…
Reference in New Issue
Block a user