mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-14 18:53:35 +00:00
Fresh dep ensure
This commit is contained in:
64
vendor/k8s.io/kubernetes/pkg/kubectl/util/BUILD
generated
vendored
64
vendor/k8s.io/kubernetes/pkg/kubectl/util/BUILD
generated
vendored
@ -7,51 +7,19 @@ load(
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"pod_port.go",
|
||||
"service_port.go",
|
||||
"umask.go",
|
||||
"umask_windows.go",
|
||||
"util.go",
|
||||
] + select({
|
||||
"@io_bazel_rules_go//go/platform:android": [
|
||||
"umask.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:darwin": [
|
||||
"umask.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:dragonfly": [
|
||||
"umask.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:freebsd": [
|
||||
"umask.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:linux": [
|
||||
"umask.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:nacl": [
|
||||
"umask.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:netbsd": [
|
||||
"umask.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:openbsd": [
|
||||
"umask.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:plan9": [
|
||||
"umask.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:solaris": [
|
||||
"umask.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:windows": [
|
||||
"umask_windows.go",
|
||||
],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/pkg/kubectl/util",
|
||||
visibility = ["//build/visible_to:pkg_kubectl_util_CONSUMERS"],
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library",
|
||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/intstr:go_default_library",
|
||||
] + select({
|
||||
"@io_bazel_rules_go//go/platform:android": [
|
||||
"//vendor/golang.org/x/sys/unix:go_default_library",
|
||||
@ -98,10 +66,21 @@ filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [
|
||||
":package-srcs",
|
||||
"//pkg/kubectl/util/certificate:all-srcs",
|
||||
"//pkg/kubectl/util/deployment:all-srcs",
|
||||
"//pkg/kubectl/util/event:all-srcs",
|
||||
"//pkg/kubectl/util/fieldpath:all-srcs",
|
||||
"//pkg/kubectl/util/hash:all-srcs",
|
||||
"//pkg/kubectl/util/i18n:all-srcs",
|
||||
"//pkg/kubectl/util/logs:all-srcs",
|
||||
"//pkg/kubectl/util/podutils:all-srcs",
|
||||
"//pkg/kubectl/util/printers:all-srcs",
|
||||
"//pkg/kubectl/util/qos:all-srcs",
|
||||
"//pkg/kubectl/util/rbac:all-srcs",
|
||||
"//pkg/kubectl/util/resource:all-srcs",
|
||||
"//pkg/kubectl/util/slice:all-srcs",
|
||||
"//pkg/kubectl/util/storage:all-srcs",
|
||||
"//pkg/kubectl/util/templates:all-srcs",
|
||||
"//pkg/kubectl/util/term:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
@ -111,12 +90,13 @@ filegroup(
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"pod_port_test.go",
|
||||
"service_port_test.go",
|
||||
"util_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library",
|
||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/intstr:go_default_library",
|
||||
],
|
||||
)
|
||||
|
23
vendor/k8s.io/kubernetes/pkg/kubectl/util/certificate/BUILD
generated
vendored
Normal file
23
vendor/k8s.io/kubernetes/pkg/kubectl/util/certificate/BUILD
generated
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["certificate.go"],
|
||||
importpath = "k8s.io/kubernetes/pkg/kubectl/util/certificate",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = ["//staging/src/k8s.io/api/certificates/v1beta1: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"],
|
||||
)
|
42
vendor/k8s.io/kubernetes/pkg/kubectl/util/certificate/certificate.go
generated
vendored
Normal file
42
vendor/k8s.io/kubernetes/pkg/kubectl/util/certificate/certificate.go
generated
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
Copyright 2016 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 certificate
|
||||
|
||||
import (
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
|
||||
certificatesv1beta1 "k8s.io/api/certificates/v1beta1"
|
||||
)
|
||||
|
||||
// TODO(yue9944882): Remove this helper package once it's copied to k/api
|
||||
|
||||
// ParseCSR extracts the CSR from the API object and decodes it.
|
||||
func ParseCSR(obj *certificatesv1beta1.CertificateSigningRequest) (*x509.CertificateRequest, error) {
|
||||
// extract PEM from request object
|
||||
pemBytes := obj.Spec.Request
|
||||
block, _ := pem.Decode(pemBytes)
|
||||
if block == nil || block.Type != "CERTIFICATE REQUEST" {
|
||||
return nil, errors.New("PEM block type must be CERTIFICATE REQUEST")
|
||||
}
|
||||
csr, err := x509.ParseCertificateRequest(block.Bytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return csr, nil
|
||||
}
|
32
vendor/k8s.io/kubernetes/pkg/kubectl/util/deployment/BUILD
generated
vendored
Normal file
32
vendor/k8s.io/kubernetes/pkg/kubectl/util/deployment/BUILD
generated
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["deployment.go"],
|
||||
importpath = "k8s.io/kubernetes/pkg/kubectl/util/deployment",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//staging/src/k8s.io/api/apps/v1:go_default_library",
|
||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/equality:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/meta:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/intstr:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/kubernetes/typed/apps/v1: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"],
|
||||
)
|
230
vendor/k8s.io/kubernetes/pkg/kubectl/util/deployment/deployment.go
generated
vendored
Normal file
230
vendor/k8s.io/kubernetes/pkg/kubectl/util/deployment/deployment.go
generated
vendored
Normal file
@ -0,0 +1,230 @@
|
||||
/*
|
||||
Copyright 2016 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 deployment
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"strconv"
|
||||
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
apiequality "k8s.io/apimachinery/pkg/api/equality"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
intstrutil "k8s.io/apimachinery/pkg/util/intstr"
|
||||
appsclient "k8s.io/client-go/kubernetes/typed/apps/v1"
|
||||
)
|
||||
|
||||
const (
|
||||
// RevisionAnnotation is the revision annotation of a deployment's replica sets which records its rollout sequence
|
||||
RevisionAnnotation = "deployment.kubernetes.io/revision"
|
||||
// RevisionHistoryAnnotation maintains the history of all old revisions that a replica set has served for a deployment.
|
||||
RevisionHistoryAnnotation = "deployment.kubernetes.io/revision-history"
|
||||
// DesiredReplicasAnnotation is the desired replicas for a deployment recorded as an annotation
|
||||
// in its replica sets. Helps in separating scaling events from the rollout process and for
|
||||
// determining if the new replica set for a deployment is really saturated.
|
||||
DesiredReplicasAnnotation = "deployment.kubernetes.io/desired-replicas"
|
||||
// MaxReplicasAnnotation is the maximum replicas a deployment can have at a given point, which
|
||||
// is deployment.spec.replicas + maxSurge. Used by the underlying replica sets to estimate their
|
||||
// proportions in case the deployment has surge replicas.
|
||||
MaxReplicasAnnotation = "deployment.kubernetes.io/max-replicas"
|
||||
// RollbackRevisionNotFound is not found rollback event reason
|
||||
RollbackRevisionNotFound = "DeploymentRollbackRevisionNotFound"
|
||||
// RollbackTemplateUnchanged is the template unchanged rollback event reason
|
||||
RollbackTemplateUnchanged = "DeploymentRollbackTemplateUnchanged"
|
||||
// RollbackDone is the done rollback event reason
|
||||
RollbackDone = "DeploymentRollback"
|
||||
// TimedOutReason is added in a deployment when its newest replica set fails to show any progress
|
||||
// within the given deadline (progressDeadlineSeconds).
|
||||
TimedOutReason = "ProgressDeadlineExceeded"
|
||||
)
|
||||
|
||||
// GetDeploymentCondition returns the condition with the provided type.
|
||||
func GetDeploymentCondition(status appsv1.DeploymentStatus, condType appsv1.DeploymentConditionType) *appsv1.DeploymentCondition {
|
||||
for i := range status.Conditions {
|
||||
c := status.Conditions[i]
|
||||
if c.Type == condType {
|
||||
return &c
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Revision returns the revision number of the input object.
|
||||
func Revision(obj runtime.Object) (int64, error) {
|
||||
acc, err := meta.Accessor(obj)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
v, ok := acc.GetAnnotations()[RevisionAnnotation]
|
||||
if !ok {
|
||||
return 0, nil
|
||||
}
|
||||
return strconv.ParseInt(v, 10, 64)
|
||||
}
|
||||
|
||||
// GetAllReplicaSets returns the old and new replica sets targeted by the given Deployment. It gets PodList and
|
||||
// ReplicaSetList from client interface. Note that the first set of old replica sets doesn't include the ones
|
||||
// with no pods, and the second set of old replica sets include all old replica sets. The third returned value
|
||||
// is the new replica set, and it may be nil if it doesn't exist yet.
|
||||
func GetAllReplicaSets(deployment *appsv1.Deployment, c appsclient.AppsV1Interface) ([]*appsv1.ReplicaSet, []*appsv1.ReplicaSet, *appsv1.ReplicaSet, error) {
|
||||
rsList, err := listReplicaSets(deployment, rsListFromClient(c))
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
oldRSes, allOldRSes := findOldReplicaSets(deployment, rsList)
|
||||
newRS := findNewReplicaSet(deployment, rsList)
|
||||
return oldRSes, allOldRSes, newRS, nil
|
||||
}
|
||||
|
||||
// RsListFromClient returns an rsListFunc that wraps the given client.
|
||||
func rsListFromClient(c appsclient.AppsV1Interface) rsListFunc {
|
||||
return func(namespace string, options metav1.ListOptions) ([]*appsv1.ReplicaSet, error) {
|
||||
rsList, err := c.ReplicaSets(namespace).List(options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var ret []*appsv1.ReplicaSet
|
||||
for i := range rsList.Items {
|
||||
ret = append(ret, &rsList.Items[i])
|
||||
}
|
||||
return ret, err
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: switch this to full namespacers
|
||||
type rsListFunc func(string, metav1.ListOptions) ([]*appsv1.ReplicaSet, error)
|
||||
type podListFunc func(string, metav1.ListOptions) (*corev1.PodList, error)
|
||||
|
||||
// listReplicaSets returns a slice of RSes the given deployment targets.
|
||||
// Note that this does NOT attempt to reconcile ControllerRef (adopt/orphan),
|
||||
// because only the controller itself should do that.
|
||||
// However, it does filter out anything whose ControllerRef doesn't match.
|
||||
func listReplicaSets(deployment *appsv1.Deployment, getRSList rsListFunc) ([]*appsv1.ReplicaSet, error) {
|
||||
// TODO: Right now we list replica sets by their labels. We should list them by selector, i.e. the replica set's selector
|
||||
// should be a superset of the deployment's selector, see https://github.com/kubernetes/kubernetes/issues/19830.
|
||||
namespace := deployment.Namespace
|
||||
selector, err := metav1.LabelSelectorAsSelector(deployment.Spec.Selector)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
options := metav1.ListOptions{LabelSelector: selector.String()}
|
||||
all, err := getRSList(namespace, options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Only include those whose ControllerRef matches the Deployment.
|
||||
owned := make([]*appsv1.ReplicaSet, 0, len(all))
|
||||
for _, rs := range all {
|
||||
if metav1.IsControlledBy(rs, deployment) {
|
||||
owned = append(owned, rs)
|
||||
}
|
||||
}
|
||||
return owned, nil
|
||||
}
|
||||
|
||||
// EqualIgnoreHash returns true if two given podTemplateSpec are equal, ignoring the diff in value of Labels[pod-template-hash]
|
||||
// We ignore pod-template-hash because:
|
||||
// 1. The hash result would be different upon podTemplateSpec API changes
|
||||
// (e.g. the addition of a new field will cause the hash code to change)
|
||||
// 2. The deployment template won't have hash labels
|
||||
func equalIgnoreHash(template1, template2 *corev1.PodTemplateSpec) bool {
|
||||
t1Copy := template1.DeepCopy()
|
||||
t2Copy := template2.DeepCopy()
|
||||
// Remove hash labels from template.Labels before comparing
|
||||
delete(t1Copy.Labels, appsv1.DefaultDeploymentUniqueLabelKey)
|
||||
delete(t2Copy.Labels, appsv1.DefaultDeploymentUniqueLabelKey)
|
||||
return apiequality.Semantic.DeepEqual(t1Copy, t2Copy)
|
||||
}
|
||||
|
||||
// FindNewReplicaSet returns the new RS this given deployment targets (the one with the same pod template).
|
||||
func findNewReplicaSet(deployment *appsv1.Deployment, rsList []*appsv1.ReplicaSet) *appsv1.ReplicaSet {
|
||||
sort.Sort(replicaSetsByCreationTimestamp(rsList))
|
||||
for i := range rsList {
|
||||
if equalIgnoreHash(&rsList[i].Spec.Template, &deployment.Spec.Template) {
|
||||
// In rare cases, such as after cluster upgrades, Deployment may end up with
|
||||
// having more than one new ReplicaSets that have the same template as its template,
|
||||
// see https://github.com/kubernetes/kubernetes/issues/40415
|
||||
// We deterministically choose the oldest new ReplicaSet.
|
||||
return rsList[i]
|
||||
}
|
||||
}
|
||||
// new ReplicaSet does not exist.
|
||||
return nil
|
||||
}
|
||||
|
||||
// replicaSetsByCreationTimestamp sorts a list of ReplicaSet by creation timestamp, using their names as a tie breaker.
|
||||
type replicaSetsByCreationTimestamp []*appsv1.ReplicaSet
|
||||
|
||||
func (o replicaSetsByCreationTimestamp) Len() int { return len(o) }
|
||||
func (o replicaSetsByCreationTimestamp) Swap(i, j int) { o[i], o[j] = o[j], o[i] }
|
||||
func (o replicaSetsByCreationTimestamp) Less(i, j int) bool {
|
||||
if o[i].CreationTimestamp.Equal(&o[j].CreationTimestamp) {
|
||||
return o[i].Name < o[j].Name
|
||||
}
|
||||
return o[i].CreationTimestamp.Before(&o[j].CreationTimestamp)
|
||||
}
|
||||
|
||||
// // FindOldReplicaSets returns the old replica sets targeted by the given Deployment, with the given slice of RSes.
|
||||
// // Note that the first set of old replica sets doesn't include the ones with no pods, and the second set of old replica sets include all old replica sets.
|
||||
func findOldReplicaSets(deployment *appsv1.Deployment, rsList []*appsv1.ReplicaSet) ([]*appsv1.ReplicaSet, []*appsv1.ReplicaSet) {
|
||||
var requiredRSs []*appsv1.ReplicaSet
|
||||
var allRSs []*appsv1.ReplicaSet
|
||||
newRS := findNewReplicaSet(deployment, rsList)
|
||||
for _, rs := range rsList {
|
||||
// Filter out new replica set
|
||||
if newRS != nil && rs.UID == newRS.UID {
|
||||
continue
|
||||
}
|
||||
allRSs = append(allRSs, rs)
|
||||
if *(rs.Spec.Replicas) != 0 {
|
||||
requiredRSs = append(requiredRSs, rs)
|
||||
}
|
||||
}
|
||||
return requiredRSs, allRSs
|
||||
}
|
||||
|
||||
// ResolveFenceposts resolves both maxSurge and maxUnavailable. This needs to happen in one
|
||||
// step. For example:
|
||||
//
|
||||
// 2 desired, max unavailable 1%, surge 0% - should scale old(-1), then new(+1), then old(-1), then new(+1)
|
||||
// 1 desired, max unavailable 1%, surge 0% - should scale old(-1), then new(+1)
|
||||
// 2 desired, max unavailable 25%, surge 1% - should scale new(+1), then old(-1), then new(+1), then old(-1)
|
||||
// 1 desired, max unavailable 25%, surge 1% - should scale new(+1), then old(-1)
|
||||
// 2 desired, max unavailable 0%, surge 1% - should scale new(+1), then old(-1), then new(+1), then old(-1)
|
||||
// 1 desired, max unavailable 0%, surge 1% - should scale new(+1), then old(-1)
|
||||
func ResolveFenceposts(maxSurge, maxUnavailable *intstrutil.IntOrString, desired int32) (int32, int32, error) {
|
||||
surge, err := intstrutil.GetValueFromIntOrPercent(intstrutil.ValueOrDefault(maxSurge, intstrutil.FromInt(0)), int(desired), true)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
unavailable, err := intstrutil.GetValueFromIntOrPercent(intstrutil.ValueOrDefault(maxUnavailable, intstrutil.FromInt(0)), int(desired), false)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
|
||||
if surge == 0 && unavailable == 0 {
|
||||
// Validation should never allow the user to explicitly use zero values for both maxSurge
|
||||
// maxUnavailable. Due to rounding down maxUnavailable though, it may resolve to zero.
|
||||
// If both fenceposts resolve to zero, then we should set maxUnavailable to 1 on the
|
||||
// theory that surge might not work due to quota.
|
||||
unavailable = 1
|
||||
}
|
||||
|
||||
return int32(surge), int32(unavailable), nil
|
||||
}
|
37
vendor/k8s.io/kubernetes/pkg/kubectl/util/event/BUILD
generated
vendored
Normal file
37
vendor/k8s.io/kubernetes/pkg/kubectl/util/event/BUILD
generated
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["sorted_event_list.go"],
|
||||
importpath = "k8s.io/kubernetes/pkg/kubectl/util/event",
|
||||
deps = ["//staging/src/k8s.io/api/core/v1:go_default_library"],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["sorted_event_list_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
36
vendor/k8s.io/kubernetes/pkg/kubectl/util/event/sorted_event_list.go
generated
vendored
Normal file
36
vendor/k8s.io/kubernetes/pkg/kubectl/util/event/sorted_event_list.go
generated
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
Copyright 2014 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 event
|
||||
|
||||
import (
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
)
|
||||
|
||||
// SortableEvents implements sort.Interface for []api.Event based on the Timestamp field
|
||||
type SortableEvents []corev1.Event
|
||||
|
||||
func (list SortableEvents) Len() int {
|
||||
return len(list)
|
||||
}
|
||||
|
||||
func (list SortableEvents) Swap(i, j int) {
|
||||
list[i], list[j] = list[j], list[i]
|
||||
}
|
||||
|
||||
func (list SortableEvents) Less(i, j int) bool {
|
||||
return list[i].LastTimestamp.Time.Before(list[j].LastTimestamp.Time)
|
||||
}
|
66
vendor/k8s.io/kubernetes/pkg/kubectl/util/event/sorted_event_list_test.go
generated
vendored
Normal file
66
vendor/k8s.io/kubernetes/pkg/kubectl/util/event/sorted_event_list_test.go
generated
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
Copyright 2014 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 event
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
func TestSortableEvents(t *testing.T) {
|
||||
// Arrange
|
||||
list := SortableEvents([]corev1.Event{
|
||||
{
|
||||
Source: corev1.EventSource{Component: "kubelet"},
|
||||
Message: "Item 1",
|
||||
FirstTimestamp: metav1.NewTime(time.Date(2014, time.January, 15, 0, 0, 0, 0, time.UTC)),
|
||||
LastTimestamp: metav1.NewTime(time.Date(2014, time.January, 15, 0, 0, 0, 0, time.UTC)),
|
||||
Count: 1,
|
||||
Type: corev1.EventTypeNormal,
|
||||
},
|
||||
{
|
||||
Source: corev1.EventSource{Component: "scheduler"},
|
||||
Message: "Item 2",
|
||||
FirstTimestamp: metav1.NewTime(time.Date(1987, time.June, 17, 0, 0, 0, 0, time.UTC)),
|
||||
LastTimestamp: metav1.NewTime(time.Date(1987, time.June, 17, 0, 0, 0, 0, time.UTC)),
|
||||
Count: 1,
|
||||
Type: corev1.EventTypeNormal,
|
||||
},
|
||||
{
|
||||
Source: corev1.EventSource{Component: "kubelet"},
|
||||
Message: "Item 3",
|
||||
FirstTimestamp: metav1.NewTime(time.Date(2002, time.December, 25, 0, 0, 0, 0, time.UTC)),
|
||||
LastTimestamp: metav1.NewTime(time.Date(2002, time.December, 25, 0, 0, 0, 0, time.UTC)),
|
||||
Count: 1,
|
||||
Type: corev1.EventTypeNormal,
|
||||
},
|
||||
})
|
||||
|
||||
// Act
|
||||
sort.Sort(list)
|
||||
|
||||
// Assert
|
||||
if list[0].Message != "Item 2" ||
|
||||
list[1].Message != "Item 3" ||
|
||||
list[2].Message != "Item 1" {
|
||||
t.Fatal("List is not sorted by time. List: ", list)
|
||||
}
|
||||
}
|
27
vendor/k8s.io/kubernetes/pkg/kubectl/util/fieldpath/BUILD
generated
vendored
Normal file
27
vendor/k8s.io/kubernetes/pkg/kubectl/util/fieldpath/BUILD
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["fieldpath.go"],
|
||||
importpath = "k8s.io/kubernetes/pkg/kubectl/util/fieldpath",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/meta:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/validation: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"],
|
||||
)
|
111
vendor/k8s.io/kubernetes/pkg/kubectl/util/fieldpath/fieldpath.go
generated
vendored
Normal file
111
vendor/k8s.io/kubernetes/pkg/kubectl/util/fieldpath/fieldpath.go
generated
vendored
Normal file
@ -0,0 +1,111 @@
|
||||
/*
|
||||
Copyright 2015 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 fieldpath
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apimachinery/pkg/util/validation"
|
||||
)
|
||||
|
||||
// TODO(yue9944882): Remove this helper package once it's copied to k/apimachinery
|
||||
|
||||
// FormatMap formats map[string]string to a string.
|
||||
func FormatMap(m map[string]string) (fmtStr string) {
|
||||
// output with keys in sorted order to provide stable output
|
||||
keys := sets.NewString()
|
||||
for key := range m {
|
||||
keys.Insert(key)
|
||||
}
|
||||
for _, key := range keys.List() {
|
||||
fmtStr += fmt.Sprintf("%v=%q\n", key, m[key])
|
||||
}
|
||||
fmtStr = strings.TrimSuffix(fmtStr, "\n")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// ExtractFieldPathAsString extracts the field from the given object
|
||||
// and returns it as a string. The object must be a pointer to an
|
||||
// API type.
|
||||
func ExtractFieldPathAsString(obj interface{}, fieldPath string) (string, error) {
|
||||
accessor, err := meta.Accessor(obj)
|
||||
if err != nil {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
if path, subscript, ok := SplitMaybeSubscriptedPath(fieldPath); ok {
|
||||
switch path {
|
||||
case "metadata.annotations":
|
||||
if errs := validation.IsQualifiedName(strings.ToLower(subscript)); len(errs) != 0 {
|
||||
return "", fmt.Errorf("invalid key subscript in %s: %s", fieldPath, strings.Join(errs, ";"))
|
||||
}
|
||||
return accessor.GetAnnotations()[subscript], nil
|
||||
case "metadata.labels":
|
||||
if errs := validation.IsQualifiedName(subscript); len(errs) != 0 {
|
||||
return "", fmt.Errorf("invalid key subscript in %s: %s", fieldPath, strings.Join(errs, ";"))
|
||||
}
|
||||
return accessor.GetLabels()[subscript], nil
|
||||
default:
|
||||
return "", fmt.Errorf("fieldPath %q does not support subscript", fieldPath)
|
||||
}
|
||||
}
|
||||
|
||||
switch fieldPath {
|
||||
case "metadata.annotations":
|
||||
return FormatMap(accessor.GetAnnotations()), nil
|
||||
case "metadata.labels":
|
||||
return FormatMap(accessor.GetLabels()), nil
|
||||
case "metadata.name":
|
||||
return accessor.GetName(), nil
|
||||
case "metadata.namespace":
|
||||
return accessor.GetNamespace(), nil
|
||||
case "metadata.uid":
|
||||
return string(accessor.GetUID()), nil
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("unsupported fieldPath: %v", fieldPath)
|
||||
}
|
||||
|
||||
// SplitMaybeSubscriptedPath checks whether the specified fieldPath is
|
||||
// subscripted, and
|
||||
// - if yes, this function splits the fieldPath into path and subscript, and
|
||||
// returns (path, subscript, true).
|
||||
// - if no, this function returns (fieldPath, "", false).
|
||||
//
|
||||
// Example inputs and outputs:
|
||||
// - "metadata.annotations['myKey']" --> ("metadata.annotations", "myKey", true)
|
||||
// - "metadata.annotations['a[b]c']" --> ("metadata.annotations", "a[b]c", true)
|
||||
// - "metadata.labels['']" --> ("metadata.labels", "", true)
|
||||
// - "metadata.labels" --> ("metadata.labels", "", false)
|
||||
func SplitMaybeSubscriptedPath(fieldPath string) (string, string, bool) {
|
||||
if !strings.HasSuffix(fieldPath, "']") {
|
||||
return fieldPath, "", false
|
||||
}
|
||||
s := strings.TrimSuffix(fieldPath, "']")
|
||||
parts := strings.SplitN(s, "['", 2)
|
||||
if len(parts) < 2 {
|
||||
return fieldPath, "", false
|
||||
}
|
||||
if len(parts[0]) == 0 {
|
||||
return fieldPath, "", false
|
||||
}
|
||||
return parts[0], parts[1], true
|
||||
}
|
4
vendor/k8s.io/kubernetes/pkg/kubectl/util/hash/BUILD
generated
vendored
4
vendor/k8s.io/kubernetes/pkg/kubectl/util/hash/BUILD
generated
vendored
@ -10,14 +10,14 @@ go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["hash_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
deps = ["//vendor/k8s.io/api/core/v1:go_default_library"],
|
||||
deps = ["//staging/src/k8s.io/api/core/v1:go_default_library"],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["hash.go"],
|
||||
importpath = "k8s.io/kubernetes/pkg/kubectl/util/hash",
|
||||
deps = ["//vendor/k8s.io/api/core/v1:go_default_library"],
|
||||
deps = ["//staging/src/k8s.io/api/core/v1:go_default_library"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
|
4
vendor/k8s.io/kubernetes/pkg/kubectl/util/i18n/BUILD
generated
vendored
4
vendor/k8s.io/kubernetes/pkg/kubectl/util/i18n/BUILD
generated
vendored
@ -11,9 +11,9 @@ go_library(
|
||||
srcs = ["i18n.go"],
|
||||
importpath = "k8s.io/kubernetes/pkg/kubectl/util/i18n",
|
||||
deps = [
|
||||
"//pkg/generated:go_default_library",
|
||||
"//pkg/kubectl/generated:go_default_library",
|
||||
"//vendor/github.com/chai2010/gettext-go/gettext:go_default_library",
|
||||
"//vendor/github.com/golang/glog:go_default_library",
|
||||
"//vendor/k8s.io/klog:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
23
vendor/k8s.io/kubernetes/pkg/kubectl/util/i18n/i18n.go
generated
vendored
23
vendor/k8s.io/kubernetes/pkg/kubectl/util/i18n/i18n.go
generated
vendored
@ -24,10 +24,10 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"k8s.io/kubernetes/pkg/generated"
|
||||
"k8s.io/kubernetes/pkg/kubectl/generated"
|
||||
|
||||
"github.com/chai2010/gettext-go/gettext"
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/klog"
|
||||
)
|
||||
|
||||
var knownTranslations = map[string][]string{
|
||||
@ -50,14 +50,23 @@ var knownTranslations = map[string][]string{
|
||||
}
|
||||
|
||||
func loadSystemLanguage() string {
|
||||
langStr := os.Getenv("LANG")
|
||||
// Implements the following locale priority order: LC_ALL, LC_MESSAGES, LANG
|
||||
// Similarly to: https://www.gnu.org/software/gettext/manual/html_node/Locale-Environment-Variables.html
|
||||
langStr := os.Getenv("LC_ALL")
|
||||
if langStr == "" {
|
||||
glog.V(3).Infof("Couldn't find the LANG environment variable, defaulting to en_US")
|
||||
langStr = os.Getenv("LC_MESSAGES")
|
||||
}
|
||||
if langStr == "" {
|
||||
langStr = os.Getenv("LANG")
|
||||
}
|
||||
|
||||
if langStr == "" {
|
||||
klog.V(3).Infof("Couldn't find the LC_ALL, LC_MESSAGES or LANG environment variables, defaulting to en_US")
|
||||
return "default"
|
||||
}
|
||||
pieces := strings.Split(langStr, ".")
|
||||
if len(pieces) != 2 {
|
||||
glog.V(3).Infof("Unexpected system language (%s), defaulting to en_US", langStr)
|
||||
klog.V(3).Infof("Unexpected system language (%s), defaulting to en_US", langStr)
|
||||
return "default"
|
||||
}
|
||||
return pieces[0]
|
||||
@ -74,7 +83,7 @@ func findLanguage(root string, getLanguageFn func() string) string {
|
||||
}
|
||||
}
|
||||
}
|
||||
glog.V(3).Infof("Couldn't find translations for %s, using default", langStr)
|
||||
klog.V(3).Infof("Couldn't find translations for %s, using default", langStr)
|
||||
return "default"
|
||||
}
|
||||
|
||||
@ -92,7 +101,7 @@ func LoadTranslations(root string, getLanguageFn func() string) error {
|
||||
fmt.Sprintf("%s/%s/LC_MESSAGES/k8s.mo", root, langStr),
|
||||
}
|
||||
|
||||
glog.V(3).Infof("Setting language to %s", langStr)
|
||||
klog.V(3).Infof("Setting language to %s", langStr)
|
||||
// TODO: list the directory and load all files.
|
||||
buf := new(bytes.Buffer)
|
||||
w := zip.NewWriter(buf)
|
||||
|
109
vendor/k8s.io/kubernetes/pkg/kubectl/util/i18n/i18n_test.go
generated
vendored
109
vendor/k8s.io/kubernetes/pkg/kubectl/util/i18n/i18n_test.go
generated
vendored
@ -21,6 +21,8 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
var knownTestLocale = "en_US.UTF-8"
|
||||
|
||||
func TestTranslation(t *testing.T) {
|
||||
err := LoadTranslations("test", func() string { return "default" })
|
||||
if err != nil {
|
||||
@ -50,15 +52,106 @@ func TestTranslationPlural(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestTranslationEnUSEnv(t *testing.T) {
|
||||
os.Setenv("LANG", "en_US.UTF-8")
|
||||
err := LoadTranslations("test", nil)
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
func TestTranslationUsingEnvVar(t *testing.T) {
|
||||
// We must backup and restore env vars before setting test values in tests
|
||||
// othervise we are risking to break other tests/test cases
|
||||
// which rely on the same env vars
|
||||
envVarsToBackup := []string{"LC_MESSAGES", "LANG", "LC_ALL"}
|
||||
expectedStrEnUSLocale := "baz"
|
||||
expectedStrFallback := "foo"
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
setenvFn func()
|
||||
expectedStr string
|
||||
}{
|
||||
{
|
||||
name: "Only LC_ALL is set",
|
||||
setenvFn: func() { os.Setenv("LC_ALL", knownTestLocale) },
|
||||
expectedStr: expectedStrEnUSLocale,
|
||||
},
|
||||
{
|
||||
name: "Only LC_MESSAGES is set",
|
||||
setenvFn: func() { os.Setenv("LC_MESSAGES", knownTestLocale) },
|
||||
expectedStr: expectedStrEnUSLocale,
|
||||
},
|
||||
{
|
||||
name: "Only LANG",
|
||||
setenvFn: func() { os.Setenv("LANG", knownTestLocale) },
|
||||
expectedStr: expectedStrEnUSLocale,
|
||||
},
|
||||
{
|
||||
name: "LC_MESSAGES overrides LANG",
|
||||
setenvFn: func() {
|
||||
os.Setenv("LANG", "be_BY.UTF-8") // Unknown locale
|
||||
os.Setenv("LC_MESSAGES", knownTestLocale)
|
||||
},
|
||||
expectedStr: expectedStrEnUSLocale,
|
||||
},
|
||||
{
|
||||
name: "LC_ALL overrides LANG",
|
||||
setenvFn: func() {
|
||||
os.Setenv("LANG", "be_BY.UTF-8") // Unknown locale
|
||||
os.Setenv("LC_ALL", knownTestLocale)
|
||||
},
|
||||
expectedStr: expectedStrEnUSLocale,
|
||||
},
|
||||
{
|
||||
name: "LC_ALL overrides LC_MESSAGES",
|
||||
setenvFn: func() {
|
||||
os.Setenv("LC_MESSAGES", "be_BY.UTF-8") // Unknown locale
|
||||
os.Setenv("LC_ALL", knownTestLocale)
|
||||
},
|
||||
expectedStr: expectedStrEnUSLocale,
|
||||
},
|
||||
{
|
||||
name: "Unknown locale in LANG",
|
||||
setenvFn: func() { os.Setenv("LANG", "be_BY.UTF-8") },
|
||||
expectedStr: expectedStrFallback,
|
||||
},
|
||||
{
|
||||
name: "Unknown locale in LC_MESSAGES",
|
||||
setenvFn: func() { os.Setenv("LC_MESSAGES", "be_BY.UTF-8") },
|
||||
expectedStr: expectedStrFallback,
|
||||
},
|
||||
{
|
||||
name: "Unknown locale in LC_ALL",
|
||||
setenvFn: func() { os.Setenv("LC_ALL", "be_BY.UTF-8") },
|
||||
expectedStr: expectedStrFallback,
|
||||
},
|
||||
{
|
||||
name: "Invalid env var",
|
||||
setenvFn: func() { os.Setenv("LC_MESSAGES", "fake.locale.UTF-8") },
|
||||
expectedStr: expectedStrFallback,
|
||||
},
|
||||
{
|
||||
name: "No env vars",
|
||||
setenvFn: func() {},
|
||||
expectedStr: expectedStrFallback,
|
||||
},
|
||||
}
|
||||
|
||||
result := T("test_string")
|
||||
if result != "baz" {
|
||||
t.Errorf("expected: %s, saw: %s", "baz", result)
|
||||
for _, test := range testCases {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
for _, envVar := range envVarsToBackup {
|
||||
if envVarValue := os.Getenv(envVar); envVarValue != "" {
|
||||
os.Unsetenv(envVar)
|
||||
// Restore env var at the end
|
||||
defer func() { os.Setenv(envVar, envVarValue) }()
|
||||
}
|
||||
}
|
||||
|
||||
test.setenvFn()
|
||||
|
||||
err := LoadTranslations("test", nil)
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
}
|
||||
|
||||
result := T("test_string")
|
||||
if result != test.expectedStr {
|
||||
t.Errorf("expected: %s, saw: %s", test.expectedStr, result)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
4
vendor/k8s.io/kubernetes/pkg/kubectl/util/logs/BUILD
generated
vendored
4
vendor/k8s.io/kubernetes/pkg/kubectl/util/logs/BUILD
generated
vendored
@ -10,9 +10,9 @@ go_library(
|
||||
srcs = ["logs.go"],
|
||||
importpath = "k8s.io/kubernetes/pkg/kubectl/util/logs",
|
||||
deps = [
|
||||
"//vendor/github.com/golang/glog:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
||||
"//vendor/github.com/spf13/pflag:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
||||
"//vendor/k8s.io/klog:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
21
vendor/k8s.io/kubernetes/pkg/kubectl/util/logs/logs.go
generated
vendored
21
vendor/k8s.io/kubernetes/pkg/kubectl/util/logs/logs.go
generated
vendored
@ -21,41 +21,42 @@ import (
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/spf13/pflag"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/klog"
|
||||
)
|
||||
|
||||
var logFlushFreq = pflag.Duration("log-flush-frequency", 5*time.Second, "Maximum number of seconds between log flushes")
|
||||
|
||||
// TODO(thockin): This is temporary until we agree on log dirs and put those into each cmd.
|
||||
func init() {
|
||||
klog.InitFlags(flag.CommandLine)
|
||||
flag.Set("logtostderr", "true")
|
||||
}
|
||||
|
||||
// GlogWriter serves as a bridge between the standard log package and the glog package.
|
||||
type GlogWriter struct{}
|
||||
// KlogWriter serves as a bridge between the standard log package and the glog package.
|
||||
type KlogWriter struct{}
|
||||
|
||||
// Write implements the io.Writer interface.
|
||||
func (writer GlogWriter) Write(data []byte) (n int, err error) {
|
||||
glog.Info(string(data))
|
||||
func (writer KlogWriter) Write(data []byte) (n int, err error) {
|
||||
klog.InfoDepth(1, string(data))
|
||||
return len(data), nil
|
||||
}
|
||||
|
||||
// InitLogs initializes logs the way we want for kubernetes.
|
||||
func InitLogs() {
|
||||
log.SetOutput(GlogWriter{})
|
||||
log.SetOutput(KlogWriter{})
|
||||
log.SetFlags(0)
|
||||
// The default glog flush interval is 5 seconds.
|
||||
go wait.Until(glog.Flush, *logFlushFreq, wait.NeverStop)
|
||||
go wait.Until(klog.Flush, *logFlushFreq, wait.NeverStop)
|
||||
}
|
||||
|
||||
// FlushLogs flushes logs immediately.
|
||||
func FlushLogs() {
|
||||
glog.Flush()
|
||||
klog.Flush()
|
||||
}
|
||||
|
||||
// NewLogger creates a new log.Logger which sends logs to glog.Info.
|
||||
// NewLogger creates a new log.Logger which sends logs to klog.Info.
|
||||
func NewLogger(prefix string) *log.Logger {
|
||||
return log.New(GlogWriter{}, prefix, 0)
|
||||
return log.New(KlogWriter{}, prefix, 0)
|
||||
}
|
||||
|
36
vendor/k8s.io/kubernetes/pkg/kubectl/util/pod_port.go
generated
vendored
Normal file
36
vendor/k8s.io/kubernetes/pkg/kubectl/util/pod_port.go
generated
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
Copyright 2018 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 util
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
)
|
||||
|
||||
// LookupContainerPortNumberByName find containerPort number by its named port name
|
||||
func LookupContainerPortNumberByName(pod v1.Pod, name string) (int32, error) {
|
||||
for _, ctr := range pod.Spec.Containers {
|
||||
for _, ctrportspec := range ctr.Ports {
|
||||
if ctrportspec.Name == name {
|
||||
return ctrportspec.ContainerPort, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return int32(-1), fmt.Errorf("Pod '%s' does not have a named port '%s'", pod.Name, name)
|
||||
}
|
98
vendor/k8s.io/kubernetes/pkg/kubectl/util/pod_port_test.go
generated
vendored
Normal file
98
vendor/k8s.io/kubernetes/pkg/kubectl/util/pod_port_test.go
generated
vendored
Normal file
@ -0,0 +1,98 @@
|
||||
/*
|
||||
Copyright 2018 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 util
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
)
|
||||
|
||||
func TestLookupContainerPortNumberByName(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
pod v1.Pod
|
||||
portname string
|
||||
portnum int32
|
||||
err bool
|
||||
}{
|
||||
{
|
||||
name: "test success 1",
|
||||
pod: v1.Pod{
|
||||
Spec: v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
{
|
||||
Ports: []v1.ContainerPort{
|
||||
{
|
||||
Name: "https",
|
||||
ContainerPort: int32(443)},
|
||||
{
|
||||
Name: "http",
|
||||
ContainerPort: int32(80)},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
portname: "http",
|
||||
portnum: int32(80),
|
||||
err: false,
|
||||
},
|
||||
{
|
||||
name: "test faulure 1",
|
||||
pod: v1.Pod{
|
||||
Spec: v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
{
|
||||
Ports: []v1.ContainerPort{
|
||||
{
|
||||
Name: "https",
|
||||
ContainerPort: int32(443)},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
portname: "www",
|
||||
portnum: int32(0),
|
||||
err: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
portnum, err := LookupContainerPortNumberByName(tt.pod, tt.portname)
|
||||
if err != nil {
|
||||
if tt.err {
|
||||
return
|
||||
}
|
||||
|
||||
t.Errorf("%v: unexpected error: %v", tt.name, err)
|
||||
return
|
||||
}
|
||||
|
||||
if tt.err {
|
||||
t.Errorf("%v: unexpected success", tt.name)
|
||||
return
|
||||
}
|
||||
|
||||
if portnum != tt.portnum {
|
||||
t.Errorf("%v: expected port number %v; got %v", tt.name, tt.portnum, portnum)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
27
vendor/k8s.io/kubernetes/pkg/kubectl/util/podutils/BUILD
generated
vendored
Normal file
27
vendor/k8s.io/kubernetes/pkg/kubectl/util/podutils/BUILD
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["podutils.go"],
|
||||
importpath = "k8s.io/kubernetes/pkg/kubectl/util/podutils",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/util/integer: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"],
|
||||
)
|
190
vendor/k8s.io/kubernetes/pkg/kubectl/util/podutils/podutils.go
generated
vendored
Normal file
190
vendor/k8s.io/kubernetes/pkg/kubectl/util/podutils/podutils.go
generated
vendored
Normal file
@ -0,0 +1,190 @@
|
||||
/*
|
||||
Copyright 2014 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 podutils
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/util/integer"
|
||||
)
|
||||
|
||||
// IsPodAvailable returns true if a pod is available; false otherwise.
|
||||
// Precondition for an available pod is that it must be ready. On top
|
||||
// of that, there are two cases when a pod can be considered available:
|
||||
// 1. minReadySeconds == 0, or
|
||||
// 2. LastTransitionTime (is set) + minReadySeconds < current time
|
||||
func IsPodAvailable(pod *corev1.Pod, minReadySeconds int32, now metav1.Time) bool {
|
||||
if !IsPodReady(pod) {
|
||||
return false
|
||||
}
|
||||
|
||||
c := getPodReadyCondition(pod.Status)
|
||||
minReadySecondsDuration := time.Duration(minReadySeconds) * time.Second
|
||||
if minReadySeconds == 0 || !c.LastTransitionTime.IsZero() && c.LastTransitionTime.Add(minReadySecondsDuration).Before(now.Time) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// IsPodReady returns true if a pod is ready; false otherwise.
|
||||
func IsPodReady(pod *corev1.Pod) bool {
|
||||
return isPodReadyConditionTrue(pod.Status)
|
||||
}
|
||||
|
||||
// IsPodReadyConditionTrue returns true if a pod is ready; false otherwise.
|
||||
func isPodReadyConditionTrue(status corev1.PodStatus) bool {
|
||||
condition := getPodReadyCondition(status)
|
||||
return condition != nil && condition.Status == corev1.ConditionTrue
|
||||
}
|
||||
|
||||
// GetPodReadyCondition extracts the pod ready condition from the given status and returns that.
|
||||
// Returns nil if the condition is not present.
|
||||
func getPodReadyCondition(status corev1.PodStatus) *corev1.PodCondition {
|
||||
_, condition := getPodCondition(&status, corev1.PodReady)
|
||||
return condition
|
||||
}
|
||||
|
||||
// GetPodCondition extracts the provided condition from the given status and returns that.
|
||||
// Returns nil and -1 if the condition is not present, and the index of the located condition.
|
||||
func getPodCondition(status *corev1.PodStatus, conditionType corev1.PodConditionType) (int, *corev1.PodCondition) {
|
||||
if status == nil {
|
||||
return -1, nil
|
||||
}
|
||||
return getPodConditionFromList(status.Conditions, conditionType)
|
||||
}
|
||||
|
||||
// GetPodConditionFromList extracts the provided condition from the given list of condition and
|
||||
// returns the index of the condition and the condition. Returns -1 and nil if the condition is not present.
|
||||
func getPodConditionFromList(conditions []corev1.PodCondition, conditionType corev1.PodConditionType) (int, *corev1.PodCondition) {
|
||||
if conditions == nil {
|
||||
return -1, nil
|
||||
}
|
||||
for i := range conditions {
|
||||
if conditions[i].Type == conditionType {
|
||||
return i, &conditions[i]
|
||||
}
|
||||
}
|
||||
return -1, nil
|
||||
}
|
||||
|
||||
// ByLogging allows custom sorting of pods so the best one can be picked for getting its logs.
|
||||
type ByLogging []*corev1.Pod
|
||||
|
||||
func (s ByLogging) Len() int { return len(s) }
|
||||
func (s ByLogging) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
||||
|
||||
func (s ByLogging) Less(i, j int) bool {
|
||||
// 1. assigned < unassigned
|
||||
if s[i].Spec.NodeName != s[j].Spec.NodeName && (len(s[i].Spec.NodeName) == 0 || len(s[j].Spec.NodeName) == 0) {
|
||||
return len(s[i].Spec.NodeName) > 0
|
||||
}
|
||||
// 2. PodRunning < PodUnknown < PodPending
|
||||
m := map[corev1.PodPhase]int{corev1.PodRunning: 0, corev1.PodUnknown: 1, corev1.PodPending: 2}
|
||||
if m[s[i].Status.Phase] != m[s[j].Status.Phase] {
|
||||
return m[s[i].Status.Phase] < m[s[j].Status.Phase]
|
||||
}
|
||||
// 3. ready < not ready
|
||||
if IsPodReady(s[i]) != IsPodReady(s[j]) {
|
||||
return IsPodReady(s[i])
|
||||
}
|
||||
// TODO: take availability into account when we push minReadySeconds information from deployment into pods,
|
||||
// see https://github.com/kubernetes/kubernetes/issues/22065
|
||||
// 4. Been ready for more time < less time < empty time
|
||||
if IsPodReady(s[i]) && IsPodReady(s[j]) && !podReadyTime(s[i]).Equal(podReadyTime(s[j])) {
|
||||
return afterOrZero(podReadyTime(s[j]), podReadyTime(s[i]))
|
||||
}
|
||||
// 5. Pods with containers with higher restart counts < lower restart counts
|
||||
if maxContainerRestarts(s[i]) != maxContainerRestarts(s[j]) {
|
||||
return maxContainerRestarts(s[i]) > maxContainerRestarts(s[j])
|
||||
}
|
||||
// 6. older pods < newer pods < empty timestamp pods
|
||||
if !s[i].CreationTimestamp.Equal(&s[j].CreationTimestamp) {
|
||||
return afterOrZero(&s[j].CreationTimestamp, &s[i].CreationTimestamp)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// ActivePods type allows custom sorting of pods so a controller can pick the best ones to delete.
|
||||
type ActivePods []*corev1.Pod
|
||||
|
||||
func (s ActivePods) Len() int { return len(s) }
|
||||
func (s ActivePods) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
||||
|
||||
func (s ActivePods) Less(i, j int) bool {
|
||||
// 1. Unassigned < assigned
|
||||
// If only one of the pods is unassigned, the unassigned one is smaller
|
||||
if s[i].Spec.NodeName != s[j].Spec.NodeName && (len(s[i].Spec.NodeName) == 0 || len(s[j].Spec.NodeName) == 0) {
|
||||
return len(s[i].Spec.NodeName) == 0
|
||||
}
|
||||
// 2. PodPending < PodUnknown < PodRunning
|
||||
m := map[corev1.PodPhase]int{corev1.PodPending: 0, corev1.PodUnknown: 1, corev1.PodRunning: 2}
|
||||
if m[s[i].Status.Phase] != m[s[j].Status.Phase] {
|
||||
return m[s[i].Status.Phase] < m[s[j].Status.Phase]
|
||||
}
|
||||
// 3. Not ready < ready
|
||||
// If only one of the pods is not ready, the not ready one is smaller
|
||||
if IsPodReady(s[i]) != IsPodReady(s[j]) {
|
||||
return !IsPodReady(s[i])
|
||||
}
|
||||
// TODO: take availability into account when we push minReadySeconds information from deployment into pods,
|
||||
// see https://github.com/kubernetes/kubernetes/issues/22065
|
||||
// 4. Been ready for empty time < less time < more time
|
||||
// If both pods are ready, the latest ready one is smaller
|
||||
if IsPodReady(s[i]) && IsPodReady(s[j]) && !podReadyTime(s[i]).Equal(podReadyTime(s[j])) {
|
||||
return afterOrZero(podReadyTime(s[i]), podReadyTime(s[j]))
|
||||
}
|
||||
// 5. Pods with containers with higher restart counts < lower restart counts
|
||||
if maxContainerRestarts(s[i]) != maxContainerRestarts(s[j]) {
|
||||
return maxContainerRestarts(s[i]) > maxContainerRestarts(s[j])
|
||||
}
|
||||
// 6. Empty creation time pods < newer pods < older pods
|
||||
if !s[i].CreationTimestamp.Equal(&s[j].CreationTimestamp) {
|
||||
return afterOrZero(&s[i].CreationTimestamp, &s[j].CreationTimestamp)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// afterOrZero checks if time t1 is after time t2; if one of them
|
||||
// is zero, the zero time is seen as after non-zero time.
|
||||
func afterOrZero(t1, t2 *metav1.Time) bool {
|
||||
if t1.Time.IsZero() || t2.Time.IsZero() {
|
||||
return t1.Time.IsZero()
|
||||
}
|
||||
return t1.After(t2.Time)
|
||||
}
|
||||
|
||||
func podReadyTime(pod *corev1.Pod) *metav1.Time {
|
||||
if IsPodReady(pod) {
|
||||
for _, c := range pod.Status.Conditions {
|
||||
// we only care about pod ready conditions
|
||||
if c.Type == corev1.PodReady && c.Status == corev1.ConditionTrue {
|
||||
return &c.LastTransitionTime
|
||||
}
|
||||
}
|
||||
}
|
||||
return &metav1.Time{}
|
||||
}
|
||||
|
||||
func maxContainerRestarts(pod *corev1.Pod) int {
|
||||
maxRestarts := 0
|
||||
for _, c := range pod.Status.ContainerStatuses {
|
||||
maxRestarts = integer.IntMax(maxRestarts, int(c.RestartCount))
|
||||
}
|
||||
return maxRestarts
|
||||
}
|
22
vendor/k8s.io/kubernetes/pkg/kubectl/util/printers/BUILD
generated
vendored
Normal file
22
vendor/k8s.io/kubernetes/pkg/kubectl/util/printers/BUILD
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["tabwriter.go"],
|
||||
importpath = "k8s.io/kubernetes/pkg/kubectl/util/printers",
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
35
vendor/k8s.io/kubernetes/pkg/kubectl/util/printers/tabwriter.go
generated
vendored
Normal file
35
vendor/k8s.io/kubernetes/pkg/kubectl/util/printers/tabwriter.go
generated
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
Copyright 2018 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 printers
|
||||
|
||||
import (
|
||||
"io"
|
||||
"text/tabwriter"
|
||||
)
|
||||
|
||||
const (
|
||||
tabwriterMinWidth = 6
|
||||
tabwriterWidth = 4
|
||||
tabwriterPadding = 3
|
||||
tabwriterPadChar = ' '
|
||||
tabwriterFlags = 0
|
||||
)
|
||||
|
||||
// GetNewTabWriter returns a tabwriter that translates tabbed columns in input into properly aligned text.
|
||||
func GetNewTabWriter(output io.Writer) *tabwriter.Writer {
|
||||
return tabwriter.NewWriter(output, tabwriterMinWidth, tabwriterWidth, tabwriterPadding, tabwriterPadChar, tabwriterFlags)
|
||||
}
|
27
vendor/k8s.io/kubernetes/pkg/kubectl/util/qos/BUILD
generated
vendored
Normal file
27
vendor/k8s.io/kubernetes/pkg/kubectl/util/qos/BUILD
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["qos.go"],
|
||||
importpath = "k8s.io/kubernetes/pkg/kubectl/util/qos",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/sets: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"],
|
||||
)
|
95
vendor/k8s.io/kubernetes/pkg/kubectl/util/qos/qos.go
generated
vendored
Normal file
95
vendor/k8s.io/kubernetes/pkg/kubectl/util/qos/qos.go
generated
vendored
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
Copyright 2015 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 qos
|
||||
|
||||
import (
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
)
|
||||
|
||||
var supportedQoSComputeResources = sets.NewString(string(corev1.ResourceCPU), string(corev1.ResourceMemory))
|
||||
|
||||
func isSupportedQoSComputeResource(name corev1.ResourceName) bool {
|
||||
return supportedQoSComputeResources.Has(string(name))
|
||||
}
|
||||
|
||||
// GetPodQOS returns the QoS class of a pod.
|
||||
// A pod is besteffort if none of its containers have specified any requests or limits.
|
||||
// A pod is guaranteed only when requests and limits are specified for all the containers and they are equal.
|
||||
// A pod is burstable if limits and requests do not match across all containers.
|
||||
func GetPodQOS(pod *corev1.Pod) corev1.PodQOSClass {
|
||||
requests := corev1.ResourceList{}
|
||||
limits := corev1.ResourceList{}
|
||||
zeroQuantity := resource.MustParse("0")
|
||||
isGuaranteed := true
|
||||
for _, container := range pod.Spec.Containers {
|
||||
// process requests
|
||||
for name, quantity := range container.Resources.Requests {
|
||||
if !isSupportedQoSComputeResource(name) {
|
||||
continue
|
||||
}
|
||||
if quantity.Cmp(zeroQuantity) == 1 {
|
||||
delta := quantity.Copy()
|
||||
if _, exists := requests[name]; !exists {
|
||||
requests[name] = *delta
|
||||
} else {
|
||||
delta.Add(requests[name])
|
||||
requests[name] = *delta
|
||||
}
|
||||
}
|
||||
}
|
||||
// process limits
|
||||
qosLimitsFound := sets.NewString()
|
||||
for name, quantity := range container.Resources.Limits {
|
||||
if !isSupportedQoSComputeResource(name) {
|
||||
continue
|
||||
}
|
||||
if quantity.Cmp(zeroQuantity) == 1 {
|
||||
qosLimitsFound.Insert(string(name))
|
||||
delta := quantity.Copy()
|
||||
if _, exists := limits[name]; !exists {
|
||||
limits[name] = *delta
|
||||
} else {
|
||||
delta.Add(limits[name])
|
||||
limits[name] = *delta
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !qosLimitsFound.HasAll(string(corev1.ResourceMemory), string(corev1.ResourceCPU)) {
|
||||
isGuaranteed = false
|
||||
}
|
||||
}
|
||||
if len(requests) == 0 && len(limits) == 0 {
|
||||
return corev1.PodQOSBestEffort
|
||||
}
|
||||
// Check is requests match limits for all resources.
|
||||
if isGuaranteed {
|
||||
for name, req := range requests {
|
||||
if lim, exists := limits[name]; !exists || lim.Cmp(req) != 0 {
|
||||
isGuaranteed = false
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if isGuaranteed &&
|
||||
len(requests) == len(limits) {
|
||||
return corev1.PodQOSGuaranteed
|
||||
}
|
||||
return corev1.PodQOSBurstable
|
||||
}
|
23
vendor/k8s.io/kubernetes/pkg/kubectl/util/rbac/BUILD
generated
vendored
Normal file
23
vendor/k8s.io/kubernetes/pkg/kubectl/util/rbac/BUILD
generated
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["rbac.go"],
|
||||
importpath = "k8s.io/kubernetes/pkg/kubectl/util/rbac",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = ["//staging/src/k8s.io/api/rbac/v1: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"],
|
||||
)
|
128
vendor/k8s.io/kubernetes/pkg/kubectl/util/rbac/rbac.go
generated
vendored
Normal file
128
vendor/k8s.io/kubernetes/pkg/kubectl/util/rbac/rbac.go
generated
vendored
Normal file
@ -0,0 +1,128 @@
|
||||
/*
|
||||
Copyright 2018 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 rbac
|
||||
|
||||
import (
|
||||
rbacv1 "k8s.io/api/rbac/v1"
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type simpleResource struct {
|
||||
Group string
|
||||
Resource string
|
||||
ResourceNameExist bool
|
||||
ResourceName string
|
||||
}
|
||||
|
||||
// CompactRules combines rules that contain a single APIGroup/Resource, differ only by verb, and contain no other attributes.
|
||||
// this is a fast check, and works well with the decomposed "missing rules" list from a Covers check.
|
||||
func CompactRules(rules []rbacv1.PolicyRule) ([]rbacv1.PolicyRule, error) {
|
||||
compacted := make([]rbacv1.PolicyRule, 0, len(rules))
|
||||
|
||||
simpleRules := map[simpleResource]*rbacv1.PolicyRule{}
|
||||
for _, rule := range rules {
|
||||
if resource, isSimple := isSimpleResourceRule(&rule); isSimple {
|
||||
if existingRule, ok := simpleRules[resource]; ok {
|
||||
// Add the new verbs to the existing simple resource rule
|
||||
if existingRule.Verbs == nil {
|
||||
existingRule.Verbs = []string{}
|
||||
}
|
||||
existingRule.Verbs = append(existingRule.Verbs, rule.Verbs...)
|
||||
} else {
|
||||
// Copy the rule to accumulate matching simple resource rules into
|
||||
simpleRules[resource] = rule.DeepCopy()
|
||||
}
|
||||
} else {
|
||||
compacted = append(compacted, rule)
|
||||
}
|
||||
}
|
||||
|
||||
// Once we've consolidated the simple resource rules, add them to the compacted list
|
||||
for _, simpleRule := range simpleRules {
|
||||
compacted = append(compacted, *simpleRule)
|
||||
}
|
||||
|
||||
return compacted, nil
|
||||
}
|
||||
|
||||
// isSimpleResourceRule returns true if the given rule contains verbs, a single resource, a single API group, at most one Resource Name, and no other values
|
||||
func isSimpleResourceRule(rule *rbacv1.PolicyRule) (simpleResource, bool) {
|
||||
resource := simpleResource{}
|
||||
|
||||
// If we have "complex" rule attributes, return early without allocations or expensive comparisons
|
||||
if len(rule.ResourceNames) > 1 || len(rule.NonResourceURLs) > 0 {
|
||||
return resource, false
|
||||
}
|
||||
// If we have multiple api groups or resources, return early
|
||||
if len(rule.APIGroups) != 1 || len(rule.Resources) != 1 {
|
||||
return resource, false
|
||||
}
|
||||
|
||||
// Test if this rule only contains APIGroups/Resources/Verbs/ResourceNames
|
||||
simpleRule := &rbacv1.PolicyRule{APIGroups: rule.APIGroups, Resources: rule.Resources, Verbs: rule.Verbs, ResourceNames: rule.ResourceNames}
|
||||
if !reflect.DeepEqual(simpleRule, rule) {
|
||||
return resource, false
|
||||
}
|
||||
|
||||
if len(rule.ResourceNames) == 0 {
|
||||
resource = simpleResource{Group: rule.APIGroups[0], Resource: rule.Resources[0], ResourceNameExist: false}
|
||||
} else {
|
||||
resource = simpleResource{Group: rule.APIGroups[0], Resource: rule.Resources[0], ResourceNameExist: true, ResourceName: rule.ResourceNames[0]}
|
||||
}
|
||||
|
||||
return resource, true
|
||||
}
|
||||
|
||||
// BreakdownRule takes a rule and builds an equivalent list of rules that each have at most one verb, one
|
||||
// resource, and one resource name
|
||||
func BreakdownRule(rule rbacv1.PolicyRule) []rbacv1.PolicyRule {
|
||||
subrules := []rbacv1.PolicyRule{}
|
||||
for _, group := range rule.APIGroups {
|
||||
for _, resource := range rule.Resources {
|
||||
for _, verb := range rule.Verbs {
|
||||
if len(rule.ResourceNames) > 0 {
|
||||
for _, resourceName := range rule.ResourceNames {
|
||||
subrules = append(subrules, rbacv1.PolicyRule{APIGroups: []string{group}, Resources: []string{resource}, Verbs: []string{verb}, ResourceNames: []string{resourceName}})
|
||||
}
|
||||
|
||||
} else {
|
||||
subrules = append(subrules, rbacv1.PolicyRule{APIGroups: []string{group}, Resources: []string{resource}, Verbs: []string{verb}})
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Non-resource URLs are unique because they only combine with verbs.
|
||||
for _, nonResourceURL := range rule.NonResourceURLs {
|
||||
for _, verb := range rule.Verbs {
|
||||
subrules = append(subrules, rbacv1.PolicyRule{NonResourceURLs: []string{nonResourceURL}, Verbs: []string{verb}})
|
||||
}
|
||||
}
|
||||
|
||||
return subrules
|
||||
}
|
||||
|
||||
// SortableRuleSlice is used to sort rule slice
|
||||
type SortableRuleSlice []rbacv1.PolicyRule
|
||||
|
||||
func (s SortableRuleSlice) Len() int { return len(s) }
|
||||
func (s SortableRuleSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
||||
func (s SortableRuleSlice) Less(i, j int) bool {
|
||||
return strings.Compare(s[i].String(), s[j].String()) < 0
|
||||
}
|
27
vendor/k8s.io/kubernetes/pkg/kubectl/util/resource/BUILD
generated
vendored
Normal file
27
vendor/k8s.io/kubernetes/pkg/kubectl/util/resource/BUILD
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["resource.go"],
|
||||
importpath = "k8s.io/kubernetes/pkg/kubectl/util/resource",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/sets: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"],
|
||||
)
|
138
vendor/k8s.io/kubernetes/pkg/kubectl/util/resource/resource.go
generated
vendored
Normal file
138
vendor/k8s.io/kubernetes/pkg/kubectl/util/resource/resource.go
generated
vendored
Normal file
@ -0,0 +1,138 @@
|
||||
/*
|
||||
Copyright 2018 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 resource
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
)
|
||||
|
||||
// PodRequestsAndLimits returns a dictionary of all defined resources summed up for all
|
||||
// containers of the pod.
|
||||
func PodRequestsAndLimits(pod *corev1.Pod) (reqs, limits corev1.ResourceList) {
|
||||
reqs, limits = corev1.ResourceList{}, corev1.ResourceList{}
|
||||
for _, container := range pod.Spec.Containers {
|
||||
addResourceList(reqs, container.Resources.Requests)
|
||||
addResourceList(limits, container.Resources.Limits)
|
||||
}
|
||||
// init containers define the minimum of any resource
|
||||
for _, container := range pod.Spec.InitContainers {
|
||||
maxResourceList(reqs, container.Resources.Requests)
|
||||
maxResourceList(limits, container.Resources.Limits)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// addResourceList adds the resources in newList to list
|
||||
func addResourceList(list, new corev1.ResourceList) {
|
||||
for name, quantity := range new {
|
||||
if value, ok := list[name]; !ok {
|
||||
list[name] = *quantity.Copy()
|
||||
} else {
|
||||
value.Add(quantity)
|
||||
list[name] = value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// maxResourceList sets list to the greater of list/newList for every resource
|
||||
// either list
|
||||
func maxResourceList(list, new corev1.ResourceList) {
|
||||
for name, quantity := range new {
|
||||
if value, ok := list[name]; !ok {
|
||||
list[name] = *quantity.Copy()
|
||||
continue
|
||||
} else {
|
||||
if quantity.Cmp(value) > 0 {
|
||||
list[name] = *quantity.Copy()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ExtractContainerResourceValue extracts the value of a resource
|
||||
// in an already known container
|
||||
func ExtractContainerResourceValue(fs *corev1.ResourceFieldSelector, container *corev1.Container) (string, error) {
|
||||
divisor := resource.Quantity{}
|
||||
if divisor.Cmp(fs.Divisor) == 0 {
|
||||
divisor = resource.MustParse("1")
|
||||
} else {
|
||||
divisor = fs.Divisor
|
||||
}
|
||||
|
||||
switch fs.Resource {
|
||||
case "limits.cpu":
|
||||
return convertResourceCPUToString(container.Resources.Limits.Cpu(), divisor)
|
||||
case "limits.memory":
|
||||
return convertResourceMemoryToString(container.Resources.Limits.Memory(), divisor)
|
||||
case "limits.ephemeral-storage":
|
||||
return convertResourceEphemeralStorageToString(container.Resources.Limits.StorageEphemeral(), divisor)
|
||||
case "requests.cpu":
|
||||
return convertResourceCPUToString(container.Resources.Requests.Cpu(), divisor)
|
||||
case "requests.memory":
|
||||
return convertResourceMemoryToString(container.Resources.Requests.Memory(), divisor)
|
||||
case "requests.ephemeral-storage":
|
||||
return convertResourceEphemeralStorageToString(container.Resources.Requests.StorageEphemeral(), divisor)
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("Unsupported container resource : %v", fs.Resource)
|
||||
}
|
||||
|
||||
// convertResourceCPUToString converts cpu value to the format of divisor and returns
|
||||
// ceiling of the value.
|
||||
func convertResourceCPUToString(cpu *resource.Quantity, divisor resource.Quantity) (string, error) {
|
||||
c := int64(math.Ceil(float64(cpu.MilliValue()) / float64(divisor.MilliValue())))
|
||||
return strconv.FormatInt(c, 10), nil
|
||||
}
|
||||
|
||||
// convertResourceMemoryToString converts memory value to the format of divisor and returns
|
||||
// ceiling of the value.
|
||||
func convertResourceMemoryToString(memory *resource.Quantity, divisor resource.Quantity) (string, error) {
|
||||
m := int64(math.Ceil(float64(memory.Value()) / float64(divisor.Value())))
|
||||
return strconv.FormatInt(m, 10), nil
|
||||
}
|
||||
|
||||
// convertResourceEphemeralStorageToString converts ephemeral storage value to the format of divisor and returns
|
||||
// ceiling of the value.
|
||||
func convertResourceEphemeralStorageToString(ephemeralStorage *resource.Quantity, divisor resource.Quantity) (string, error) {
|
||||
m := int64(math.Ceil(float64(ephemeralStorage.Value()) / float64(divisor.Value())))
|
||||
return strconv.FormatInt(m, 10), nil
|
||||
}
|
||||
|
||||
var standardContainerResources = sets.NewString(
|
||||
string(corev1.ResourceCPU),
|
||||
string(corev1.ResourceMemory),
|
||||
string(corev1.ResourceEphemeralStorage),
|
||||
)
|
||||
|
||||
// IsStandardContainerResourceName returns true if the container can make a resource request
|
||||
// for the specified resource
|
||||
func IsStandardContainerResourceName(str string) bool {
|
||||
return standardContainerResources.Has(str) || IsHugePageResourceName(corev1.ResourceName(str))
|
||||
}
|
||||
|
||||
// IsHugePageResourceName returns true if the resource name has the huge page
|
||||
// resource prefix.
|
||||
func IsHugePageResourceName(name corev1.ResourceName) bool {
|
||||
return strings.HasPrefix(string(name), corev1.ResourceHugePagesPrefix)
|
||||
}
|
40
vendor/k8s.io/kubernetes/pkg/kubectl/util/service_port.go
generated
vendored
40
vendor/k8s.io/kubernetes/pkg/kubectl/util/service_port.go
generated
vendored
@ -19,45 +19,41 @@ package util
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
)
|
||||
|
||||
// Lookup containerPort number by its named port name
|
||||
func LookupContainerPortNumberByName(pod api.Pod, name string) (int32, error) {
|
||||
for _, ctr := range pod.Spec.Containers {
|
||||
for _, ctrportspec := range ctr.Ports {
|
||||
if ctrportspec.Name == name {
|
||||
return ctrportspec.ContainerPort, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return int32(-1), fmt.Errorf("Pod '%s' does not have a named port '%s'", pod.Name, name)
|
||||
}
|
||||
|
||||
// Lookup containerPort number from Service port number
|
||||
// It implements the handling of resolving container named port, as well as ignoring targetPort when clusterIP=None
|
||||
// LookupContainerPortNumberByServicePort implements
|
||||
// the handling of resolving container named port, as well as ignoring targetPort when clusterIP=None
|
||||
// It returns an error when a named port can't find a match (with -1 returned), or when the service does not
|
||||
// declare such port (with the input port number returned).
|
||||
func LookupContainerPortNumberByServicePort(svc api.Service, pod api.Pod, port int32) (int32, error) {
|
||||
func LookupContainerPortNumberByServicePort(svc v1.Service, pod v1.Pod, port int32) (int32, error) {
|
||||
for _, svcportspec := range svc.Spec.Ports {
|
||||
if svcportspec.Port != port {
|
||||
continue
|
||||
}
|
||||
if svc.Spec.ClusterIP == api.ClusterIPNone {
|
||||
if svc.Spec.ClusterIP == v1.ClusterIPNone {
|
||||
return port, nil
|
||||
}
|
||||
if svcportspec.TargetPort.Type == intstr.Int {
|
||||
if svcportspec.TargetPort.IntValue() == 0 {
|
||||
// targetPort is omitted, and the IntValue() would be zero
|
||||
return svcportspec.Port, nil
|
||||
} else {
|
||||
return int32(svcportspec.TargetPort.IntValue()), nil
|
||||
}
|
||||
} else {
|
||||
return LookupContainerPortNumberByName(pod, svcportspec.TargetPort.String())
|
||||
return int32(svcportspec.TargetPort.IntValue()), nil
|
||||
}
|
||||
return LookupContainerPortNumberByName(pod, svcportspec.TargetPort.String())
|
||||
}
|
||||
return port, fmt.Errorf("Service %s does not have a service port %d", svc.Name, port)
|
||||
}
|
||||
|
||||
// LookupServicePortNumberByName find service port number by its named port name
|
||||
func LookupServicePortNumberByName(svc v1.Service, name string) (int32, error) {
|
||||
for _, svcportspec := range svc.Spec.Ports {
|
||||
if svcportspec.Name == name {
|
||||
return svcportspec.Port, nil
|
||||
}
|
||||
}
|
||||
|
||||
return int32(-1), fmt.Errorf("Service '%s' does not have a named port '%s'", svc.Name, name)
|
||||
}
|
||||
|
221
vendor/k8s.io/kubernetes/pkg/kubectl/util/service_port_test.go
generated
vendored
221
vendor/k8s.io/kubernetes/pkg/kubectl/util/service_port_test.go
generated
vendored
@ -19,97 +19,24 @@ package util
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
)
|
||||
|
||||
func TestLookupContainerPortNumberByName(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
pod api.Pod
|
||||
portname string
|
||||
portnum int32
|
||||
err bool
|
||||
}{
|
||||
{
|
||||
name: "test success 1",
|
||||
pod: api.Pod{
|
||||
Spec: api.PodSpec{
|
||||
Containers: []api.Container{
|
||||
{
|
||||
Ports: []api.ContainerPort{
|
||||
{
|
||||
Name: "https",
|
||||
ContainerPort: int32(443)},
|
||||
{
|
||||
Name: "http",
|
||||
ContainerPort: int32(80)},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
portname: "http",
|
||||
portnum: int32(80),
|
||||
err: false,
|
||||
},
|
||||
{
|
||||
name: "test faulure 1",
|
||||
pod: api.Pod{
|
||||
Spec: api.PodSpec{
|
||||
Containers: []api.Container{
|
||||
{
|
||||
Ports: []api.ContainerPort{
|
||||
{
|
||||
Name: "https",
|
||||
ContainerPort: int32(443)},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
portname: "www",
|
||||
portnum: int32(0),
|
||||
err: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
portnum, err := LookupContainerPortNumberByName(tc.pod, tc.portname)
|
||||
if err != nil {
|
||||
if tc.err {
|
||||
continue
|
||||
}
|
||||
|
||||
t.Errorf("%v: unexpected error: %v", tc.name, err)
|
||||
continue
|
||||
}
|
||||
|
||||
if tc.err {
|
||||
t.Errorf("%v: unexpected success", tc.name)
|
||||
continue
|
||||
}
|
||||
|
||||
if portnum != tc.portnum {
|
||||
t.Errorf("%v: expected port number %v; got %v", tc.name, tc.portnum, portnum)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestLookupContainerPortNumberByServicePort(t *testing.T) {
|
||||
cases := []struct {
|
||||
tests := []struct {
|
||||
name string
|
||||
svc api.Service
|
||||
pod api.Pod
|
||||
svc v1.Service
|
||||
pod v1.Pod
|
||||
port int32
|
||||
containerPort int32
|
||||
err bool
|
||||
}{
|
||||
{
|
||||
name: "test success 1 (int port)",
|
||||
svc: api.Service{
|
||||
Spec: api.ServiceSpec{
|
||||
Ports: []api.ServicePort{
|
||||
svc: v1.Service{
|
||||
Spec: v1.ServiceSpec{
|
||||
Ports: []v1.ServicePort{
|
||||
{
|
||||
Port: 80,
|
||||
TargetPort: intstr.FromInt(8080),
|
||||
@ -117,11 +44,11 @@ func TestLookupContainerPortNumberByServicePort(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
pod: api.Pod{
|
||||
Spec: api.PodSpec{
|
||||
Containers: []api.Container{
|
||||
pod: v1.Pod{
|
||||
Spec: v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
{
|
||||
Ports: []api.ContainerPort{
|
||||
Ports: []v1.ContainerPort{
|
||||
{
|
||||
Name: "http",
|
||||
ContainerPort: int32(8080)},
|
||||
@ -136,10 +63,10 @@ func TestLookupContainerPortNumberByServicePort(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "test success 2 (clusterIP: None)",
|
||||
svc: api.Service{
|
||||
Spec: api.ServiceSpec{
|
||||
ClusterIP: api.ClusterIPNone,
|
||||
Ports: []api.ServicePort{
|
||||
svc: v1.Service{
|
||||
Spec: v1.ServiceSpec{
|
||||
ClusterIP: v1.ClusterIPNone,
|
||||
Ports: []v1.ServicePort{
|
||||
{
|
||||
Port: 80,
|
||||
TargetPort: intstr.FromInt(8080),
|
||||
@ -147,11 +74,11 @@ func TestLookupContainerPortNumberByServicePort(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
pod: api.Pod{
|
||||
Spec: api.PodSpec{
|
||||
Containers: []api.Container{
|
||||
pod: v1.Pod{
|
||||
Spec: v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
{
|
||||
Ports: []api.ContainerPort{
|
||||
Ports: []v1.ContainerPort{
|
||||
{
|
||||
Name: "http",
|
||||
ContainerPort: int32(8080)},
|
||||
@ -166,9 +93,9 @@ func TestLookupContainerPortNumberByServicePort(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "test success 3 (named port)",
|
||||
svc: api.Service{
|
||||
Spec: api.ServiceSpec{
|
||||
Ports: []api.ServicePort{
|
||||
svc: v1.Service{
|
||||
Spec: v1.ServiceSpec{
|
||||
Ports: []v1.ServicePort{
|
||||
{
|
||||
Port: 80,
|
||||
TargetPort: intstr.FromString("http"),
|
||||
@ -176,11 +103,11 @@ func TestLookupContainerPortNumberByServicePort(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
pod: api.Pod{
|
||||
Spec: api.PodSpec{
|
||||
Containers: []api.Container{
|
||||
pod: v1.Pod{
|
||||
Spec: v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
{
|
||||
Ports: []api.ContainerPort{
|
||||
Ports: []v1.ContainerPort{
|
||||
{
|
||||
Name: "http",
|
||||
ContainerPort: int32(8080)},
|
||||
@ -195,20 +122,20 @@ func TestLookupContainerPortNumberByServicePort(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "test success (targetPort omitted)",
|
||||
svc: api.Service{
|
||||
Spec: api.ServiceSpec{
|
||||
Ports: []api.ServicePort{
|
||||
svc: v1.Service{
|
||||
Spec: v1.ServiceSpec{
|
||||
Ports: []v1.ServicePort{
|
||||
{
|
||||
Port: 80,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
pod: api.Pod{
|
||||
Spec: api.PodSpec{
|
||||
Containers: []api.Container{
|
||||
pod: v1.Pod{
|
||||
Spec: v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
{
|
||||
Ports: []api.ContainerPort{
|
||||
Ports: []v1.ContainerPort{
|
||||
{
|
||||
Name: "http",
|
||||
ContainerPort: int32(80)},
|
||||
@ -223,9 +150,9 @@ func TestLookupContainerPortNumberByServicePort(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "test failure 1 (cannot find a matching named port)",
|
||||
svc: api.Service{
|
||||
Spec: api.ServiceSpec{
|
||||
Ports: []api.ServicePort{
|
||||
svc: v1.Service{
|
||||
Spec: v1.ServiceSpec{
|
||||
Ports: []v1.ServicePort{
|
||||
{
|
||||
Port: 80,
|
||||
TargetPort: intstr.FromString("http"),
|
||||
@ -233,11 +160,11 @@ func TestLookupContainerPortNumberByServicePort(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
pod: api.Pod{
|
||||
Spec: api.PodSpec{
|
||||
Containers: []api.Container{
|
||||
pod: v1.Pod{
|
||||
Spec: v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
{
|
||||
Ports: []api.ContainerPort{
|
||||
Ports: []v1.ContainerPort{
|
||||
{
|
||||
Name: "https",
|
||||
ContainerPort: int32(443)},
|
||||
@ -252,9 +179,9 @@ func TestLookupContainerPortNumberByServicePort(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "test failure 2 (cannot find a matching service port)",
|
||||
svc: api.Service{
|
||||
Spec: api.ServiceSpec{
|
||||
Ports: []api.ServicePort{
|
||||
svc: v1.Service{
|
||||
Spec: v1.ServiceSpec{
|
||||
Ports: []v1.ServicePort{
|
||||
{
|
||||
Port: 80,
|
||||
TargetPort: intstr.FromString("http"),
|
||||
@ -262,11 +189,11 @@ func TestLookupContainerPortNumberByServicePort(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
pod: api.Pod{
|
||||
Spec: api.PodSpec{
|
||||
Containers: []api.Container{
|
||||
pod: v1.Pod{
|
||||
Spec: v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
{
|
||||
Ports: []api.ContainerPort{
|
||||
Ports: []v1.ContainerPort{
|
||||
{
|
||||
Name: "https",
|
||||
ContainerPort: int32(443)},
|
||||
@ -281,10 +208,10 @@ func TestLookupContainerPortNumberByServicePort(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "test failure 2 (cannot find a matching service port, but ClusterIP: None)",
|
||||
svc: api.Service{
|
||||
Spec: api.ServiceSpec{
|
||||
ClusterIP: api.ClusterIPNone,
|
||||
Ports: []api.ServicePort{
|
||||
svc: v1.Service{
|
||||
Spec: v1.ServiceSpec{
|
||||
ClusterIP: v1.ClusterIPNone,
|
||||
Ports: []v1.ServicePort{
|
||||
{
|
||||
Port: 80,
|
||||
TargetPort: intstr.FromString("http"),
|
||||
@ -292,11 +219,11 @@ func TestLookupContainerPortNumberByServicePort(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
pod: api.Pod{
|
||||
Spec: api.PodSpec{
|
||||
Containers: []api.Container{
|
||||
pod: v1.Pod{
|
||||
Spec: v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
{
|
||||
Ports: []api.ContainerPort{
|
||||
Ports: []v1.ContainerPort{
|
||||
{
|
||||
Name: "http",
|
||||
ContainerPort: int32(80)},
|
||||
@ -311,27 +238,29 @@ func TestLookupContainerPortNumberByServicePort(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
containerPort, err := LookupContainerPortNumberByServicePort(tc.svc, tc.pod, tc.port)
|
||||
if err != nil {
|
||||
if tc.err {
|
||||
if containerPort != tc.containerPort {
|
||||
t.Errorf("%v: expected port %v; got %v", tc.name, tc.containerPort, containerPort)
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
containerPort, err := LookupContainerPortNumberByServicePort(tt.svc, tt.pod, tt.port)
|
||||
if err != nil {
|
||||
if tt.err {
|
||||
if containerPort != tt.containerPort {
|
||||
t.Errorf("%v: expected port %v; got %v", tt.name, tt.containerPort, containerPort)
|
||||
}
|
||||
return
|
||||
}
|
||||
continue
|
||||
|
||||
t.Errorf("%v: unexpected error: %v", tt.name, err)
|
||||
return
|
||||
}
|
||||
|
||||
t.Errorf("%v: unexpected error: %v", tc.name, err)
|
||||
continue
|
||||
}
|
||||
if tt.err {
|
||||
t.Errorf("%v: unexpected success", tt.name)
|
||||
return
|
||||
}
|
||||
|
||||
if tc.err {
|
||||
t.Errorf("%v: unexpected success", tc.name)
|
||||
continue
|
||||
}
|
||||
|
||||
if containerPort != tc.containerPort {
|
||||
t.Errorf("%v: expected port %v; got %v", tc.name, tc.containerPort, containerPort)
|
||||
}
|
||||
if containerPort != tt.containerPort {
|
||||
t.Errorf("%v: expected port %v; got %v", tt.name, tt.containerPort, containerPort)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
16
vendor/k8s.io/kubernetes/pkg/kubectl/util/slice/slice.go
generated
vendored
16
vendor/k8s.io/kubernetes/pkg/kubectl/util/slice/slice.go
generated
vendored
@ -20,5 +20,19 @@ import (
|
||||
"sort"
|
||||
)
|
||||
|
||||
// Sorts []int64 in increasing order
|
||||
// SortInts64 sorts []int64 in increasing order
|
||||
func SortInts64(a []int64) { sort.Slice(a, func(i, j int) bool { return a[i] < a[j] }) }
|
||||
|
||||
// ContainsString checks if a given slice of strings contains the provided string.
|
||||
// If a modifier func is provided, it is called with the slice item before the comparation.
|
||||
func ContainsString(slice []string, s string, modifier func(s string) string) bool {
|
||||
for _, item := range slice {
|
||||
if item == s {
|
||||
return true
|
||||
}
|
||||
if modifier != nil && modifier(item) == s {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
26
vendor/k8s.io/kubernetes/pkg/kubectl/util/storage/BUILD
generated
vendored
Normal file
26
vendor/k8s.io/kubernetes/pkg/kubectl/util/storage/BUILD
generated
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["storage.go"],
|
||||
importpath = "k8s.io/kubernetes/pkg/kubectl/util/storage",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1: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"],
|
||||
)
|
107
vendor/k8s.io/kubernetes/pkg/kubectl/util/storage/storage.go
generated
vendored
Normal file
107
vendor/k8s.io/kubernetes/pkg/kubectl/util/storage/storage.go
generated
vendored
Normal file
@ -0,0 +1,107 @@
|
||||
/*
|
||||
Copyright 2018 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 storage
|
||||
|
||||
import (
|
||||
"k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// TODO(yue9944882): Remove this helper package once it's copied to k/api
|
||||
|
||||
// IsDefaultStorageClassAnnotation represents a StorageClass annotation that
|
||||
// marks a class as the default StorageClass
|
||||
const IsDefaultStorageClassAnnotation = "storageclass.kubernetes.io/is-default-class"
|
||||
|
||||
// BetaIsDefaultStorageClassAnnotation is the beta version of BetaIsDefaultStorageClassAnnotation.
|
||||
const BetaIsDefaultStorageClassAnnotation = "storageclass.beta.kubernetes.io/is-default-class"
|
||||
|
||||
// IsDefaultAnnotationText returns a pretty Yes/No String if
|
||||
// the annotation is set
|
||||
func IsDefaultAnnotationText(obj metav1.ObjectMeta) string {
|
||||
if obj.Annotations[IsDefaultStorageClassAnnotation] == "true" {
|
||||
return "Yes"
|
||||
}
|
||||
if obj.Annotations[BetaIsDefaultStorageClassAnnotation] == "true" {
|
||||
return "Yes"
|
||||
}
|
||||
|
||||
return "No"
|
||||
}
|
||||
|
||||
// GetAccessModesAsString returns a string representation of an array of access modes.
|
||||
// modes, when present, are always in the same order: RWO,ROX,RWX.
|
||||
func GetAccessModesAsString(modes []v1.PersistentVolumeAccessMode) string {
|
||||
modes = removeDuplicateAccessModes(modes)
|
||||
modesStr := []string{}
|
||||
if containsAccessMode(modes, v1.ReadWriteOnce) {
|
||||
modesStr = append(modesStr, "RWO")
|
||||
}
|
||||
if containsAccessMode(modes, v1.ReadOnlyMany) {
|
||||
modesStr = append(modesStr, "ROX")
|
||||
}
|
||||
if containsAccessMode(modes, v1.ReadWriteMany) {
|
||||
modesStr = append(modesStr, "RWX")
|
||||
}
|
||||
return strings.Join(modesStr, ",")
|
||||
}
|
||||
|
||||
// removeDuplicateAccessModes returns an array of access modes without any duplicates
|
||||
func removeDuplicateAccessModes(modes []v1.PersistentVolumeAccessMode) []v1.PersistentVolumeAccessMode {
|
||||
accessModes := []v1.PersistentVolumeAccessMode{}
|
||||
for _, m := range modes {
|
||||
if !containsAccessMode(accessModes, m) {
|
||||
accessModes = append(accessModes, m)
|
||||
}
|
||||
}
|
||||
return accessModes
|
||||
}
|
||||
|
||||
func containsAccessMode(modes []v1.PersistentVolumeAccessMode, mode v1.PersistentVolumeAccessMode) bool {
|
||||
for _, m := range modes {
|
||||
if m == mode {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// GetPersistentVolumeClass returns StorageClassName.
|
||||
func GetPersistentVolumeClass(volume *v1.PersistentVolume) string {
|
||||
// Use beta annotation first
|
||||
if class, found := volume.Annotations[v1.BetaStorageClassAnnotation]; found {
|
||||
return class
|
||||
}
|
||||
|
||||
return volume.Spec.StorageClassName
|
||||
}
|
||||
|
||||
// GetPersistentVolumeClaimClass returns StorageClassName. If no storage class was
|
||||
// requested, it returns "".
|
||||
func GetPersistentVolumeClaimClass(claim *v1.PersistentVolumeClaim) string {
|
||||
// Use beta annotation first
|
||||
if class, found := claim.Annotations[v1.BetaStorageClassAnnotation]; found {
|
||||
return class
|
||||
}
|
||||
|
||||
if claim.Spec.StorageClassName != nil {
|
||||
return *claim.Spec.StorageClassName
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
41
vendor/k8s.io/kubernetes/pkg/kubectl/util/templates/BUILD
generated
vendored
Normal file
41
vendor/k8s.io/kubernetes/pkg/kubectl/util/templates/BUILD
generated
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"command_groups.go",
|
||||
"markdown.go",
|
||||
"normalizers.go",
|
||||
"templater.go",
|
||||
"templates.go",
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/pkg/kubectl/util/templates",
|
||||
visibility = [
|
||||
"//build/visible_to:pkg_kubectl_util_templates_CONSUMERS",
|
||||
],
|
||||
deps = [
|
||||
"//pkg/kubectl/util/term:go_default_library",
|
||||
"//vendor/github.com/MakeNowJust/heredoc:go_default_library",
|
||||
"//vendor/github.com/russross/blackfriday:go_default_library",
|
||||
"//vendor/github.com/spf13/cobra:go_default_library",
|
||||
"//vendor/github.com/spf13/pflag:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
visibility = [
|
||||
"//build/visible_to:pkg_kubectl_util_templates_CONSUMERS",
|
||||
],
|
||||
)
|
59
vendor/k8s.io/kubernetes/pkg/kubectl/util/templates/command_groups.go
generated
vendored
Normal file
59
vendor/k8s.io/kubernetes/pkg/kubectl/util/templates/command_groups.go
generated
vendored
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
Copyright 2016 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 templates
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
type CommandGroup struct {
|
||||
Message string
|
||||
Commands []*cobra.Command
|
||||
}
|
||||
|
||||
type CommandGroups []CommandGroup
|
||||
|
||||
func (g CommandGroups) Add(c *cobra.Command) {
|
||||
for _, group := range g {
|
||||
c.AddCommand(group.Commands...)
|
||||
}
|
||||
}
|
||||
|
||||
func (g CommandGroups) Has(c *cobra.Command) bool {
|
||||
for _, group := range g {
|
||||
for _, command := range group.Commands {
|
||||
if command == c {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func AddAdditionalCommands(g CommandGroups, message string, cmds []*cobra.Command) CommandGroups {
|
||||
group := CommandGroup{Message: message}
|
||||
for _, c := range cmds {
|
||||
// Don't show commands that have no short description
|
||||
if !g.Has(c) && len(c.Short) != 0 {
|
||||
group.Commands = append(group.Commands, c)
|
||||
}
|
||||
}
|
||||
if len(group.Commands) == 0 {
|
||||
return g
|
||||
}
|
||||
return append(g, group)
|
||||
}
|
145
vendor/k8s.io/kubernetes/pkg/kubectl/util/templates/markdown.go
generated
vendored
Normal file
145
vendor/k8s.io/kubernetes/pkg/kubectl/util/templates/markdown.go
generated
vendored
Normal file
@ -0,0 +1,145 @@
|
||||
/*
|
||||
Copyright 2016 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 templates
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/russross/blackfriday"
|
||||
)
|
||||
|
||||
const linebreak = "\n"
|
||||
|
||||
// ASCIIRenderer implements blackfriday.Renderer
|
||||
var _ blackfriday.Renderer = &ASCIIRenderer{}
|
||||
|
||||
// ASCIIRenderer is a blackfriday.Renderer intended for rendering markdown
|
||||
// documents as plain text, well suited for human reading on terminals.
|
||||
type ASCIIRenderer struct {
|
||||
Indentation string
|
||||
|
||||
listItemCount uint
|
||||
listLevel uint
|
||||
}
|
||||
|
||||
// NormalText gets a text chunk *after* the markdown syntax was already
|
||||
// processed and does a final cleanup on things we don't expect here, like
|
||||
// removing linebreaks on things that are not a paragraph break (auto unwrap).
|
||||
func (r *ASCIIRenderer) NormalText(out *bytes.Buffer, text []byte) {
|
||||
raw := string(text)
|
||||
lines := strings.Split(raw, linebreak)
|
||||
for _, line := range lines {
|
||||
trimmed := strings.Trim(line, " \n\t")
|
||||
out.WriteString(trimmed)
|
||||
out.WriteString(" ")
|
||||
}
|
||||
}
|
||||
|
||||
// List renders the start and end of a list.
|
||||
func (r *ASCIIRenderer) List(out *bytes.Buffer, text func() bool, flags int) {
|
||||
r.listLevel++
|
||||
out.WriteString(linebreak)
|
||||
text()
|
||||
r.listLevel--
|
||||
}
|
||||
|
||||
// ListItem renders list items and supports both ordered and unordered lists.
|
||||
func (r *ASCIIRenderer) ListItem(out *bytes.Buffer, text []byte, flags int) {
|
||||
if flags&blackfriday.LIST_ITEM_BEGINNING_OF_LIST != 0 {
|
||||
r.listItemCount = 1
|
||||
} else {
|
||||
r.listItemCount++
|
||||
}
|
||||
indent := strings.Repeat(r.Indentation, int(r.listLevel))
|
||||
var bullet string
|
||||
if flags&blackfriday.LIST_TYPE_ORDERED != 0 {
|
||||
bullet += fmt.Sprintf("%d.", r.listItemCount)
|
||||
} else {
|
||||
bullet += "*"
|
||||
}
|
||||
out.WriteString(indent + bullet + " ")
|
||||
r.fw(out, text)
|
||||
out.WriteString(linebreak)
|
||||
}
|
||||
|
||||
// Paragraph renders the start and end of a paragraph.
|
||||
func (r *ASCIIRenderer) Paragraph(out *bytes.Buffer, text func() bool) {
|
||||
out.WriteString(linebreak)
|
||||
text()
|
||||
out.WriteString(linebreak)
|
||||
}
|
||||
|
||||
// BlockCode renders a chunk of text that represents source code.
|
||||
func (r *ASCIIRenderer) BlockCode(out *bytes.Buffer, text []byte, lang string) {
|
||||
out.WriteString(linebreak)
|
||||
lines := []string{}
|
||||
for _, line := range strings.Split(string(text), linebreak) {
|
||||
indented := r.Indentation + line
|
||||
lines = append(lines, indented)
|
||||
}
|
||||
out.WriteString(strings.Join(lines, linebreak))
|
||||
}
|
||||
|
||||
func (r *ASCIIRenderer) GetFlags() int { return 0 }
|
||||
func (r *ASCIIRenderer) HRule(out *bytes.Buffer) {
|
||||
out.WriteString(linebreak + "----------" + linebreak)
|
||||
}
|
||||
func (r *ASCIIRenderer) LineBreak(out *bytes.Buffer) { out.WriteString(linebreak) }
|
||||
func (r *ASCIIRenderer) TitleBlock(out *bytes.Buffer, text []byte) { r.fw(out, text) }
|
||||
func (r *ASCIIRenderer) Header(out *bytes.Buffer, text func() bool, level int, id string) { text() }
|
||||
func (r *ASCIIRenderer) BlockHtml(out *bytes.Buffer, text []byte) { r.fw(out, text) }
|
||||
func (r *ASCIIRenderer) BlockQuote(out *bytes.Buffer, text []byte) { r.fw(out, text) }
|
||||
func (r *ASCIIRenderer) TableRow(out *bytes.Buffer, text []byte) { r.fw(out, text) }
|
||||
func (r *ASCIIRenderer) TableHeaderCell(out *bytes.Buffer, text []byte, align int) { r.fw(out, text) }
|
||||
func (r *ASCIIRenderer) TableCell(out *bytes.Buffer, text []byte, align int) { r.fw(out, text) }
|
||||
func (r *ASCIIRenderer) Footnotes(out *bytes.Buffer, text func() bool) { text() }
|
||||
func (r *ASCIIRenderer) FootnoteItem(out *bytes.Buffer, name, text []byte, flags int) { r.fw(out, text) }
|
||||
func (r *ASCIIRenderer) AutoLink(out *bytes.Buffer, link []byte, kind int) { r.fw(out, link) }
|
||||
func (r *ASCIIRenderer) CodeSpan(out *bytes.Buffer, text []byte) { r.fw(out, text) }
|
||||
func (r *ASCIIRenderer) DoubleEmphasis(out *bytes.Buffer, text []byte) { r.fw(out, text) }
|
||||
func (r *ASCIIRenderer) Emphasis(out *bytes.Buffer, text []byte) { r.fw(out, text) }
|
||||
func (r *ASCIIRenderer) RawHtmlTag(out *bytes.Buffer, text []byte) { r.fw(out, text) }
|
||||
func (r *ASCIIRenderer) TripleEmphasis(out *bytes.Buffer, text []byte) { r.fw(out, text) }
|
||||
func (r *ASCIIRenderer) StrikeThrough(out *bytes.Buffer, text []byte) { r.fw(out, text) }
|
||||
func (r *ASCIIRenderer) FootnoteRef(out *bytes.Buffer, ref []byte, id int) { r.fw(out, ref) }
|
||||
func (r *ASCIIRenderer) Entity(out *bytes.Buffer, entity []byte) { r.fw(out, entity) }
|
||||
func (r *ASCIIRenderer) Smartypants(out *bytes.Buffer, text []byte) { r.fw(out, text) }
|
||||
func (r *ASCIIRenderer) DocumentHeader(out *bytes.Buffer) {}
|
||||
func (r *ASCIIRenderer) DocumentFooter(out *bytes.Buffer) {}
|
||||
func (r *ASCIIRenderer) TocHeaderWithAnchor(text []byte, level int, anchor string) {}
|
||||
func (r *ASCIIRenderer) TocHeader(text []byte, level int) {}
|
||||
func (r *ASCIIRenderer) TocFinalize() {}
|
||||
|
||||
func (r *ASCIIRenderer) Table(out *bytes.Buffer, header []byte, body []byte, columnData []int) {
|
||||
r.fw(out, header, body)
|
||||
}
|
||||
|
||||
func (r *ASCIIRenderer) Link(out *bytes.Buffer, link []byte, title []byte, content []byte) {
|
||||
r.fw(out, link)
|
||||
}
|
||||
|
||||
func (r *ASCIIRenderer) Image(out *bytes.Buffer, link []byte, title []byte, alt []byte) {
|
||||
r.fw(out, link)
|
||||
}
|
||||
|
||||
func (r *ASCIIRenderer) fw(out *bytes.Buffer, text ...[]byte) {
|
||||
for _, t := range text {
|
||||
out.Write(t)
|
||||
}
|
||||
}
|
97
vendor/k8s.io/kubernetes/pkg/kubectl/util/templates/normalizers.go
generated
vendored
Normal file
97
vendor/k8s.io/kubernetes/pkg/kubectl/util/templates/normalizers.go
generated
vendored
Normal file
@ -0,0 +1,97 @@
|
||||
/*
|
||||
Copyright 2016 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 templates
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/MakeNowJust/heredoc"
|
||||
"github.com/russross/blackfriday"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
const Indentation = ` `
|
||||
|
||||
// LongDesc normalizes a command's long description to follow the conventions.
|
||||
func LongDesc(s string) string {
|
||||
if len(s) == 0 {
|
||||
return s
|
||||
}
|
||||
return normalizer{s}.heredoc().markdown().trim().string
|
||||
}
|
||||
|
||||
// Examples normalizes a command's examples to follow the conventions.
|
||||
func Examples(s string) string {
|
||||
if len(s) == 0 {
|
||||
return s
|
||||
}
|
||||
return normalizer{s}.trim().indent().string
|
||||
}
|
||||
|
||||
// Normalize perform all required normalizations on a given command.
|
||||
func Normalize(cmd *cobra.Command) *cobra.Command {
|
||||
if len(cmd.Long) > 0 {
|
||||
cmd.Long = LongDesc(cmd.Long)
|
||||
}
|
||||
if len(cmd.Example) > 0 {
|
||||
cmd.Example = Examples(cmd.Example)
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
|
||||
// NormalizeAll perform all required normalizations in the entire command tree.
|
||||
func NormalizeAll(cmd *cobra.Command) *cobra.Command {
|
||||
if cmd.HasSubCommands() {
|
||||
for _, subCmd := range cmd.Commands() {
|
||||
NormalizeAll(subCmd)
|
||||
}
|
||||
}
|
||||
Normalize(cmd)
|
||||
return cmd
|
||||
}
|
||||
|
||||
type normalizer struct {
|
||||
string
|
||||
}
|
||||
|
||||
func (s normalizer) markdown() normalizer {
|
||||
bytes := []byte(s.string)
|
||||
formatted := blackfriday.Markdown(bytes, &ASCIIRenderer{Indentation: Indentation}, 0)
|
||||
s.string = string(formatted)
|
||||
return s
|
||||
}
|
||||
|
||||
func (s normalizer) heredoc() normalizer {
|
||||
s.string = heredoc.Doc(s.string)
|
||||
return s
|
||||
}
|
||||
|
||||
func (s normalizer) trim() normalizer {
|
||||
s.string = strings.TrimSpace(s.string)
|
||||
return s
|
||||
}
|
||||
|
||||
func (s normalizer) indent() normalizer {
|
||||
indentedLines := []string{}
|
||||
for _, line := range strings.Split(s.string, "\n") {
|
||||
trimmed := strings.TrimSpace(line)
|
||||
indented := Indentation + trimmed
|
||||
indentedLines = append(indentedLines, indented)
|
||||
}
|
||||
s.string = strings.Join(indentedLines, "\n")
|
||||
return s
|
||||
}
|
284
vendor/k8s.io/kubernetes/pkg/kubectl/util/templates/templater.go
generated
vendored
Normal file
284
vendor/k8s.io/kubernetes/pkg/kubectl/util/templates/templater.go
generated
vendored
Normal file
@ -0,0 +1,284 @@
|
||||
/*
|
||||
Copyright 2016 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 templates
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strings"
|
||||
"text/template"
|
||||
"unicode"
|
||||
|
||||
"k8s.io/kubernetes/pkg/kubectl/util/term"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
flag "github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
type FlagExposer interface {
|
||||
ExposeFlags(cmd *cobra.Command, flags ...string) FlagExposer
|
||||
}
|
||||
|
||||
func ActsAsRootCommand(cmd *cobra.Command, filters []string, groups ...CommandGroup) FlagExposer {
|
||||
if cmd == nil {
|
||||
panic("nil root command")
|
||||
}
|
||||
templater := &templater{
|
||||
RootCmd: cmd,
|
||||
UsageTemplate: MainUsageTemplate(),
|
||||
HelpTemplate: MainHelpTemplate(),
|
||||
CommandGroups: groups,
|
||||
Filtered: filters,
|
||||
}
|
||||
cmd.SetUsageFunc(templater.UsageFunc())
|
||||
cmd.SetHelpFunc(templater.HelpFunc())
|
||||
return templater
|
||||
}
|
||||
|
||||
func UseOptionsTemplates(cmd *cobra.Command) {
|
||||
templater := &templater{
|
||||
UsageTemplate: OptionsUsageTemplate(),
|
||||
HelpTemplate: OptionsHelpTemplate(),
|
||||
}
|
||||
cmd.SetUsageFunc(templater.UsageFunc())
|
||||
cmd.SetHelpFunc(templater.HelpFunc())
|
||||
}
|
||||
|
||||
type templater struct {
|
||||
UsageTemplate string
|
||||
HelpTemplate string
|
||||
RootCmd *cobra.Command
|
||||
CommandGroups
|
||||
Filtered []string
|
||||
}
|
||||
|
||||
func (templater *templater) ExposeFlags(cmd *cobra.Command, flags ...string) FlagExposer {
|
||||
cmd.SetUsageFunc(templater.UsageFunc(flags...))
|
||||
return templater
|
||||
}
|
||||
|
||||
func (templater *templater) HelpFunc() func(*cobra.Command, []string) {
|
||||
return func(c *cobra.Command, s []string) {
|
||||
t := template.New("help")
|
||||
t.Funcs(templater.templateFuncs())
|
||||
template.Must(t.Parse(templater.HelpTemplate))
|
||||
out := term.NewResponsiveWriter(c.OutOrStdout())
|
||||
err := t.Execute(out, c)
|
||||
if err != nil {
|
||||
c.Println(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (templater *templater) UsageFunc(exposedFlags ...string) func(*cobra.Command) error {
|
||||
return func(c *cobra.Command) error {
|
||||
t := template.New("usage")
|
||||
t.Funcs(templater.templateFuncs(exposedFlags...))
|
||||
template.Must(t.Parse(templater.UsageTemplate))
|
||||
out := term.NewResponsiveWriter(c.OutOrStderr())
|
||||
return t.Execute(out, c)
|
||||
}
|
||||
}
|
||||
|
||||
func (templater *templater) templateFuncs(exposedFlags ...string) template.FuncMap {
|
||||
return template.FuncMap{
|
||||
"trim": strings.TrimSpace,
|
||||
"trimRight": func(s string) string { return strings.TrimRightFunc(s, unicode.IsSpace) },
|
||||
"trimLeft": func(s string) string { return strings.TrimLeftFunc(s, unicode.IsSpace) },
|
||||
"gt": cobra.Gt,
|
||||
"eq": cobra.Eq,
|
||||
"rpad": rpad,
|
||||
"appendIfNotPresent": appendIfNotPresent,
|
||||
"flagsNotIntersected": flagsNotIntersected,
|
||||
"visibleFlags": visibleFlags,
|
||||
"flagsUsages": flagsUsages,
|
||||
"cmdGroups": templater.cmdGroups,
|
||||
"cmdGroupsString": templater.cmdGroupsString,
|
||||
"rootCmd": templater.rootCmdName,
|
||||
"isRootCmd": templater.isRootCmd,
|
||||
"optionsCmdFor": templater.optionsCmdFor,
|
||||
"usageLine": templater.usageLine,
|
||||
"exposed": func(c *cobra.Command) *flag.FlagSet {
|
||||
exposed := flag.NewFlagSet("exposed", flag.ContinueOnError)
|
||||
if len(exposedFlags) > 0 {
|
||||
for _, name := range exposedFlags {
|
||||
if flag := c.Flags().Lookup(name); flag != nil {
|
||||
exposed.AddFlag(flag)
|
||||
}
|
||||
}
|
||||
}
|
||||
return exposed
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (templater *templater) cmdGroups(c *cobra.Command, all []*cobra.Command) []CommandGroup {
|
||||
if len(templater.CommandGroups) > 0 && c == templater.RootCmd {
|
||||
all = filter(all, templater.Filtered...)
|
||||
return AddAdditionalCommands(templater.CommandGroups, "Other Commands:", all)
|
||||
}
|
||||
all = filter(all, "options")
|
||||
return []CommandGroup{
|
||||
{
|
||||
Message: "Available Commands:",
|
||||
Commands: all,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (t *templater) cmdGroupsString(c *cobra.Command) string {
|
||||
groups := []string{}
|
||||
for _, cmdGroup := range t.cmdGroups(c, c.Commands()) {
|
||||
cmds := []string{cmdGroup.Message}
|
||||
for _, cmd := range cmdGroup.Commands {
|
||||
if cmd.IsAvailableCommand() {
|
||||
cmds = append(cmds, " "+rpad(cmd.Name(), cmd.NamePadding())+" "+cmd.Short)
|
||||
}
|
||||
}
|
||||
groups = append(groups, strings.Join(cmds, "\n"))
|
||||
}
|
||||
return strings.Join(groups, "\n\n")
|
||||
}
|
||||
|
||||
func (t *templater) rootCmdName(c *cobra.Command) string {
|
||||
return t.rootCmd(c).CommandPath()
|
||||
}
|
||||
|
||||
func (t *templater) isRootCmd(c *cobra.Command) bool {
|
||||
return t.rootCmd(c) == c
|
||||
}
|
||||
|
||||
func (t *templater) parents(c *cobra.Command) []*cobra.Command {
|
||||
parents := []*cobra.Command{c}
|
||||
for current := c; !t.isRootCmd(current) && current.HasParent(); {
|
||||
current = current.Parent()
|
||||
parents = append(parents, current)
|
||||
}
|
||||
return parents
|
||||
}
|
||||
|
||||
func (t *templater) rootCmd(c *cobra.Command) *cobra.Command {
|
||||
if c != nil && !c.HasParent() {
|
||||
return c
|
||||
}
|
||||
if t.RootCmd == nil {
|
||||
panic("nil root cmd")
|
||||
}
|
||||
return t.RootCmd
|
||||
}
|
||||
|
||||
func (t *templater) optionsCmdFor(c *cobra.Command) string {
|
||||
if !c.Runnable() {
|
||||
return ""
|
||||
}
|
||||
rootCmdStructure := t.parents(c)
|
||||
for i := len(rootCmdStructure) - 1; i >= 0; i-- {
|
||||
cmd := rootCmdStructure[i]
|
||||
if _, _, err := cmd.Find([]string{"options"}); err == nil {
|
||||
return cmd.CommandPath() + " options"
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (t *templater) usageLine(c *cobra.Command) string {
|
||||
usage := c.UseLine()
|
||||
suffix := "[options]"
|
||||
if c.HasFlags() && !strings.Contains(usage, suffix) {
|
||||
usage += " " + suffix
|
||||
}
|
||||
return usage
|
||||
}
|
||||
|
||||
func flagsUsages(f *flag.FlagSet) string {
|
||||
x := new(bytes.Buffer)
|
||||
|
||||
f.VisitAll(func(flag *flag.Flag) {
|
||||
if flag.Hidden {
|
||||
return
|
||||
}
|
||||
format := "--%s=%s: %s\n"
|
||||
|
||||
if flag.Value.Type() == "string" {
|
||||
format = "--%s='%s': %s\n"
|
||||
}
|
||||
|
||||
if len(flag.Shorthand) > 0 {
|
||||
format = " -%s, " + format
|
||||
} else {
|
||||
format = " %s " + format
|
||||
}
|
||||
|
||||
fmt.Fprintf(x, format, flag.Shorthand, flag.Name, flag.DefValue, flag.Usage)
|
||||
})
|
||||
|
||||
return x.String()
|
||||
}
|
||||
|
||||
func rpad(s string, padding int) string {
|
||||
template := fmt.Sprintf("%%-%ds", padding)
|
||||
return fmt.Sprintf(template, s)
|
||||
}
|
||||
|
||||
func appendIfNotPresent(s, stringToAppend string) string {
|
||||
if strings.Contains(s, stringToAppend) {
|
||||
return s
|
||||
}
|
||||
return s + " " + stringToAppend
|
||||
}
|
||||
|
||||
func flagsNotIntersected(l *flag.FlagSet, r *flag.FlagSet) *flag.FlagSet {
|
||||
f := flag.NewFlagSet("notIntersected", flag.ContinueOnError)
|
||||
l.VisitAll(func(flag *flag.Flag) {
|
||||
if r.Lookup(flag.Name) == nil {
|
||||
f.AddFlag(flag)
|
||||
}
|
||||
})
|
||||
return f
|
||||
}
|
||||
|
||||
func visibleFlags(l *flag.FlagSet) *flag.FlagSet {
|
||||
hidden := "help"
|
||||
f := flag.NewFlagSet("visible", flag.ContinueOnError)
|
||||
l.VisitAll(func(flag *flag.Flag) {
|
||||
if flag.Name != hidden {
|
||||
f.AddFlag(flag)
|
||||
}
|
||||
})
|
||||
return f
|
||||
}
|
||||
|
||||
func filter(cmds []*cobra.Command, names ...string) []*cobra.Command {
|
||||
out := []*cobra.Command{}
|
||||
for _, c := range cmds {
|
||||
if c.Hidden {
|
||||
continue
|
||||
}
|
||||
skip := false
|
||||
for _, name := range names {
|
||||
if name == c.Name() {
|
||||
skip = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if skip {
|
||||
continue
|
||||
}
|
||||
out = append(out, c)
|
||||
}
|
||||
return out
|
||||
}
|
102
vendor/k8s.io/kubernetes/pkg/kubectl/util/templates/templates.go
generated
vendored
Normal file
102
vendor/k8s.io/kubernetes/pkg/kubectl/util/templates/templates.go
generated
vendored
Normal file
@ -0,0 +1,102 @@
|
||||
/*
|
||||
Copyright 2016 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 templates
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
const (
|
||||
// SectionVars is the help template section that declares variables to be used in the template.
|
||||
SectionVars = `{{$isRootCmd := isRootCmd .}}` +
|
||||
`{{$rootCmd := rootCmd .}}` +
|
||||
`{{$visibleFlags := visibleFlags (flagsNotIntersected .LocalFlags .PersistentFlags)}}` +
|
||||
`{{$explicitlyExposedFlags := exposed .}}` +
|
||||
`{{$optionsCmdFor := optionsCmdFor .}}` +
|
||||
`{{$usageLine := usageLine .}}`
|
||||
|
||||
// SectionAliases is the help template section that displays command aliases.
|
||||
SectionAliases = `{{if gt .Aliases 0}}Aliases:
|
||||
{{.NameAndAliases}}
|
||||
|
||||
{{end}}`
|
||||
|
||||
// SectionExamples is the help template section that displays command examples.
|
||||
SectionExamples = `{{if .HasExample}}Examples:
|
||||
{{trimRight .Example}}
|
||||
|
||||
{{end}}`
|
||||
|
||||
// SectionSubcommands is the help template section that displays the command's subcommands.
|
||||
SectionSubcommands = `{{if .HasAvailableSubCommands}}{{cmdGroupsString .}}
|
||||
|
||||
{{end}}`
|
||||
|
||||
// SectionFlags is the help template section that displays the command's flags.
|
||||
SectionFlags = `{{ if or $visibleFlags.HasFlags $explicitlyExposedFlags.HasFlags}}Options:
|
||||
{{ if $visibleFlags.HasFlags}}{{trimRight (flagsUsages $visibleFlags)}}{{end}}{{ if $explicitlyExposedFlags.HasFlags}}{{trimRight (flagsUsages $explicitlyExposedFlags)}}{{end}}
|
||||
|
||||
{{end}}`
|
||||
|
||||
// SectionUsage is the help template section that displays the command's usage.
|
||||
SectionUsage = `{{if and .Runnable (ne .UseLine "") (ne .UseLine $rootCmd)}}Usage:
|
||||
{{$usageLine}}
|
||||
|
||||
{{end}}`
|
||||
|
||||
// SectionTipsHelp is the help template section that displays the '--help' hint.
|
||||
SectionTipsHelp = `{{if .HasSubCommands}}Use "{{$rootCmd}} <command> --help" for more information about a given command.
|
||||
{{end}}`
|
||||
|
||||
// SectionTipsGlobalOptions is the help template section that displays the 'options' hint for displaying global flags.
|
||||
SectionTipsGlobalOptions = `{{if $optionsCmdFor}}Use "{{$optionsCmdFor}}" for a list of global command-line options (applies to all commands).
|
||||
{{end}}`
|
||||
)
|
||||
|
||||
// MainHelpTemplate if the template for 'help' used by most commands.
|
||||
func MainHelpTemplate() string {
|
||||
return `{{with or .Long .Short }}{{. | trim}}{{end}}{{if or .Runnable .HasSubCommands}}{{.UsageString}}{{end}}`
|
||||
}
|
||||
|
||||
// MainUsageTemplate if the template for 'usage' used by most commands.
|
||||
func MainUsageTemplate() string {
|
||||
sections := []string{
|
||||
"\n\n",
|
||||
SectionVars,
|
||||
SectionAliases,
|
||||
SectionExamples,
|
||||
SectionSubcommands,
|
||||
SectionFlags,
|
||||
SectionUsage,
|
||||
SectionTipsHelp,
|
||||
SectionTipsGlobalOptions,
|
||||
}
|
||||
return strings.TrimRightFunc(strings.Join(sections, ""), unicode.IsSpace)
|
||||
}
|
||||
|
||||
// OptionsHelpTemplate if the template for 'help' used by the 'options' command.
|
||||
func OptionsHelpTemplate() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// OptionsUsageTemplate if the template for 'usage' used by the 'options' command.
|
||||
func OptionsUsageTemplate() string {
|
||||
return `{{ if .HasInheritedFlags}}The following options can be passed to any command:
|
||||
|
||||
{{flagsUsages .InheritedFlags}}{{end}}`
|
||||
}
|
43
vendor/k8s.io/kubernetes/pkg/kubectl/util/term/BUILD
generated
vendored
43
vendor/k8s.io/kubernetes/pkg/kubectl/util/term/BUILD
generated
vendored
@ -10,51 +10,18 @@ go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"resize.go",
|
||||
"resizeevents.go",
|
||||
"resizeevents_windows.go",
|
||||
"term.go",
|
||||
"term_writer.go",
|
||||
] + select({
|
||||
"@io_bazel_rules_go//go/platform:android": [
|
||||
"resizeevents.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:darwin": [
|
||||
"resizeevents.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:dragonfly": [
|
||||
"resizeevents.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:freebsd": [
|
||||
"resizeevents.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:linux": [
|
||||
"resizeevents.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:nacl": [
|
||||
"resizeevents.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:netbsd": [
|
||||
"resizeevents.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:openbsd": [
|
||||
"resizeevents.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:plan9": [
|
||||
"resizeevents.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:solaris": [
|
||||
"resizeevents.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:windows": [
|
||||
"resizeevents_windows.go",
|
||||
],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/pkg/kubectl/util/term",
|
||||
deps = [
|
||||
"//pkg/util/interrupt:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/runtime:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/tools/remotecommand:go_default_library",
|
||||
"//vendor/github.com/docker/docker/pkg/term:go_default_library",
|
||||
"//vendor/github.com/mitchellh/go-wordwrap:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library",
|
||||
"//vendor/k8s.io/client-go/tools/remotecommand:go_default_library",
|
||||
] + select({
|
||||
"@io_bazel_rules_go//go/platform:android": [
|
||||
"//vendor/golang.org/x/sys/unix:go_default_library",
|
||||
|
1
vendor/k8s.io/kubernetes/pkg/kubectl/util/umask.go
generated
vendored
1
vendor/k8s.io/kubernetes/pkg/kubectl/util/umask.go
generated
vendored
@ -22,6 +22,7 @@ import (
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// Umask is a wrapper for `unix.Umask()` on non-Windows platforms
|
||||
func Umask(mask int) (old int, err error) {
|
||||
return unix.Umask(mask), nil
|
||||
}
|
||||
|
1
vendor/k8s.io/kubernetes/pkg/kubectl/util/umask_windows.go
generated
vendored
1
vendor/k8s.io/kubernetes/pkg/kubectl/util/umask_windows.go
generated
vendored
@ -22,6 +22,7 @@ import (
|
||||
"errors"
|
||||
)
|
||||
|
||||
// Umask returns an error on Windows
|
||||
func Umask(mask int) (int, error) {
|
||||
return 0, errors.New("platform and architecture is not supported")
|
||||
}
|
||||
|
7
vendor/k8s.io/kubernetes/pkg/kubectl/util/util.go
generated
vendored
7
vendor/k8s.io/kubernetes/pkg/kubectl/util/util.go
generated
vendored
@ -41,6 +41,7 @@ func ParseRFC3339(s string, nowFn func() metav1.Time) (metav1.Time, error) {
|
||||
return metav1.Time{Time: t}, nil
|
||||
}
|
||||
|
||||
// HashObject returns the hash of a Object hash by a Codec
|
||||
func HashObject(obj runtime.Object, codec runtime.Codec) (string, error) {
|
||||
data, err := runtime.Encode(codec, obj)
|
||||
if err != nil {
|
||||
@ -63,11 +64,11 @@ func ParseFileSource(source string) (keyName, filePath string, err error) {
|
||||
case numSeparators == 0:
|
||||
return path.Base(filepath.ToSlash(source)), source, nil
|
||||
case numSeparators == 1 && strings.HasPrefix(source, "="):
|
||||
return "", "", fmt.Errorf("key name for file path %v missing.", strings.TrimPrefix(source, "="))
|
||||
return "", "", fmt.Errorf("key name for file path %v missing", strings.TrimPrefix(source, "="))
|
||||
case numSeparators == 1 && strings.HasSuffix(source, "="):
|
||||
return "", "", fmt.Errorf("file path for key name %v missing.", strings.TrimSuffix(source, "="))
|
||||
return "", "", fmt.Errorf("file path for key name %v missing", strings.TrimSuffix(source, "="))
|
||||
case numSeparators > 1:
|
||||
return "", "", errors.New("Key names or file paths cannot contain '='.")
|
||||
return "", "", errors.New("Key names or file paths cannot contain '='")
|
||||
default:
|
||||
components := strings.Split(source, "=")
|
||||
return components[0], components[1], nil
|
||||
|
88
vendor/k8s.io/kubernetes/pkg/kubectl/util/util_test.go
generated
vendored
88
vendor/k8s.io/kubernetes/pkg/kubectl/util/util_test.go
generated
vendored
@ -19,7 +19,7 @@ package util
|
||||
import "testing"
|
||||
|
||||
func TestParseFileSource(t *testing.T) {
|
||||
cases := []struct {
|
||||
tests := []struct {
|
||||
name string
|
||||
input string
|
||||
key string
|
||||
@ -88,35 +88,37 @@ func TestParseFileSource(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
key, filepath, err := ParseFileSource(tc.input)
|
||||
if err != nil {
|
||||
if tc.err {
|
||||
continue
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
key, filepath, err := ParseFileSource(tt.input)
|
||||
if err != nil {
|
||||
if tt.err {
|
||||
return
|
||||
}
|
||||
|
||||
t.Errorf("%v: unexpected error: %v", tt.name, err)
|
||||
return
|
||||
}
|
||||
|
||||
t.Errorf("%v: unexpected error: %v", tc.name, err)
|
||||
continue
|
||||
}
|
||||
if tt.err {
|
||||
t.Errorf("%v: unexpected success", tt.name)
|
||||
return
|
||||
}
|
||||
|
||||
if tc.err {
|
||||
t.Errorf("%v: unexpected success", tc.name)
|
||||
continue
|
||||
}
|
||||
if e, a := tt.key, key; e != a {
|
||||
t.Errorf("%v: expected key %v; got %v", tt.name, e, a)
|
||||
return
|
||||
}
|
||||
|
||||
if e, a := tc.key, key; e != a {
|
||||
t.Errorf("%v: expected key %v; got %v", tc.name, e, a)
|
||||
continue
|
||||
}
|
||||
|
||||
if e, a := tc.filepath, filepath; e != a {
|
||||
t.Errorf("%v: expected filepath %v; got %v", tc.name, e, a)
|
||||
}
|
||||
if e, a := tt.filepath, filepath; e != a {
|
||||
t.Errorf("%v: expected filepath %v; got %v", tt.name, e, a)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseLiteralSource(t *testing.T) {
|
||||
cases := []struct {
|
||||
tests := []struct {
|
||||
name string
|
||||
input string
|
||||
key string
|
||||
@ -170,29 +172,31 @@ func TestParseLiteralSource(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
key, value, err := ParseLiteralSource(tc.input)
|
||||
if err != nil {
|
||||
if tc.err {
|
||||
continue
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
key, value, err := ParseLiteralSource(tt.input)
|
||||
if err != nil {
|
||||
if tt.err {
|
||||
return
|
||||
}
|
||||
|
||||
t.Errorf("%v: unexpected error: %v", tt.name, err)
|
||||
return
|
||||
}
|
||||
|
||||
t.Errorf("%v: unexpected error: %v", tc.name, err)
|
||||
continue
|
||||
}
|
||||
if tt.err {
|
||||
t.Errorf("%v: unexpected success", tt.name)
|
||||
return
|
||||
}
|
||||
|
||||
if tc.err {
|
||||
t.Errorf("%v: unexpected success", tc.name)
|
||||
continue
|
||||
}
|
||||
if e, a := tt.key, key; e != a {
|
||||
t.Errorf("%v: expected key %v; got %v", tt.name, e, a)
|
||||
return
|
||||
}
|
||||
|
||||
if e, a := tc.key, key; e != a {
|
||||
t.Errorf("%v: expected key %v; got %v", tc.name, e, a)
|
||||
continue
|
||||
}
|
||||
|
||||
if e, a := tc.value, value; e != a {
|
||||
t.Errorf("%v: expected value %v; got %v", tc.name, e, a)
|
||||
}
|
||||
if e, a := tt.value, value; e != a {
|
||||
t.Errorf("%v: expected value %v; got %v", tt.name, e, a)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user