vendor cleanup: remove unused,non-go and test files

This commit is contained in:
Madhu Rajanna
2019-01-16 00:05:52 +05:30
parent 52cf4aa902
commit b10ba188e7
15421 changed files with 17 additions and 4208853 deletions

View File

@ -1,45 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_library(
name = "go_default_library",
srcs = ["util.go"],
importpath = "k8s.io/kubernetes/pkg/api/v1/pod",
deps = [
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library",
],
)
go_test(
name = "go_default_test",
srcs = ["util_test.go"],
embed = [":go_default_library"],
deps = [
"//vendor/github.com/stretchr/testify/assert:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)

View File

@ -1,309 +0,0 @@
/*
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 pod
import (
"fmt"
"time"
"k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
)
// FindPort locates the container port for the given pod and portName. If the
// targetPort is a number, use that. If the targetPort is a string, look that
// string up in all named ports in all containers in the target pod. If no
// match is found, fail.
func FindPort(pod *v1.Pod, svcPort *v1.ServicePort) (int, error) {
portName := svcPort.TargetPort
switch portName.Type {
case intstr.String:
name := portName.StrVal
for _, container := range pod.Spec.Containers {
for _, port := range container.Ports {
if port.Name == name && port.Protocol == svcPort.Protocol {
return int(port.ContainerPort), nil
}
}
}
case intstr.Int:
return portName.IntValue(), nil
}
return 0, fmt.Errorf("no suitable port for manifest: %s", pod.UID)
}
// Visitor is called with each object name, and returns true if visiting should continue
type Visitor func(name string) (shouldContinue bool)
// VisitPodSecretNames invokes the visitor function with the name of every secret
// referenced by the pod spec. If visitor returns false, visiting is short-circuited.
// Transitive references (e.g. pod -> pvc -> pv -> secret) are not visited.
// Returns true if visiting completed, false if visiting was short-circuited.
func VisitPodSecretNames(pod *v1.Pod, visitor Visitor) bool {
for _, reference := range pod.Spec.ImagePullSecrets {
if !visitor(reference.Name) {
return false
}
}
for i := range pod.Spec.InitContainers {
if !visitContainerSecretNames(&pod.Spec.InitContainers[i], visitor) {
return false
}
}
for i := range pod.Spec.Containers {
if !visitContainerSecretNames(&pod.Spec.Containers[i], visitor) {
return false
}
}
var source *v1.VolumeSource
for i := range pod.Spec.Volumes {
source = &pod.Spec.Volumes[i].VolumeSource
switch {
case source.AzureFile != nil:
if len(source.AzureFile.SecretName) > 0 && !visitor(source.AzureFile.SecretName) {
return false
}
case source.CephFS != nil:
if source.CephFS.SecretRef != nil && !visitor(source.CephFS.SecretRef.Name) {
return false
}
case source.Cinder != nil:
if source.Cinder.SecretRef != nil && !visitor(source.Cinder.SecretRef.Name) {
return false
}
case source.FlexVolume != nil:
if source.FlexVolume.SecretRef != nil && !visitor(source.FlexVolume.SecretRef.Name) {
return false
}
case source.Projected != nil:
for j := range source.Projected.Sources {
if source.Projected.Sources[j].Secret != nil {
if !visitor(source.Projected.Sources[j].Secret.Name) {
return false
}
}
}
case source.RBD != nil:
if source.RBD.SecretRef != nil && !visitor(source.RBD.SecretRef.Name) {
return false
}
case source.Secret != nil:
if !visitor(source.Secret.SecretName) {
return false
}
case source.ScaleIO != nil:
if source.ScaleIO.SecretRef != nil && !visitor(source.ScaleIO.SecretRef.Name) {
return false
}
case source.ISCSI != nil:
if source.ISCSI.SecretRef != nil && !visitor(source.ISCSI.SecretRef.Name) {
return false
}
case source.StorageOS != nil:
if source.StorageOS.SecretRef != nil && !visitor(source.StorageOS.SecretRef.Name) {
return false
}
}
}
return true
}
func visitContainerSecretNames(container *v1.Container, visitor Visitor) bool {
for _, env := range container.EnvFrom {
if env.SecretRef != nil {
if !visitor(env.SecretRef.Name) {
return false
}
}
}
for _, envVar := range container.Env {
if envVar.ValueFrom != nil && envVar.ValueFrom.SecretKeyRef != nil {
if !visitor(envVar.ValueFrom.SecretKeyRef.Name) {
return false
}
}
}
return true
}
// VisitPodConfigmapNames invokes the visitor function with the name of every configmap
// referenced by the pod spec. If visitor returns false, visiting is short-circuited.
// Transitive references (e.g. pod -> pvc -> pv -> secret) are not visited.
// Returns true if visiting completed, false if visiting was short-circuited.
func VisitPodConfigmapNames(pod *v1.Pod, visitor Visitor) bool {
for i := range pod.Spec.InitContainers {
if !visitContainerConfigmapNames(&pod.Spec.InitContainers[i], visitor) {
return false
}
}
for i := range pod.Spec.Containers {
if !visitContainerConfigmapNames(&pod.Spec.Containers[i], visitor) {
return false
}
}
var source *v1.VolumeSource
for i := range pod.Spec.Volumes {
source = &pod.Spec.Volumes[i].VolumeSource
switch {
case source.Projected != nil:
for j := range source.Projected.Sources {
if source.Projected.Sources[j].ConfigMap != nil {
if !visitor(source.Projected.Sources[j].ConfigMap.Name) {
return false
}
}
}
case source.ConfigMap != nil:
if !visitor(source.ConfigMap.Name) {
return false
}
}
}
return true
}
func visitContainerConfigmapNames(container *v1.Container, visitor Visitor) bool {
for _, env := range container.EnvFrom {
if env.ConfigMapRef != nil {
if !visitor(env.ConfigMapRef.Name) {
return false
}
}
}
for _, envVar := range container.Env {
if envVar.ValueFrom != nil && envVar.ValueFrom.ConfigMapKeyRef != nil {
if !visitor(envVar.ValueFrom.ConfigMapKeyRef.Name) {
return false
}
}
}
return true
}
// GetContainerStatus extracts the status of container "name" from "statuses".
// It also returns if "name" exists.
func GetContainerStatus(statuses []v1.ContainerStatus, name string) (v1.ContainerStatus, bool) {
for i := range statuses {
if statuses[i].Name == name {
return statuses[i], true
}
}
return v1.ContainerStatus{}, false
}
// GetExistingContainerStatus extracts the status of container "name" from "statuses",
// and returns empty status if "name" does not exist.
func GetExistingContainerStatus(statuses []v1.ContainerStatus, name string) v1.ContainerStatus {
for i := range statuses {
if statuses[i].Name == name {
return statuses[i]
}
}
return v1.ContainerStatus{}
}
// 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 *v1.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 *v1.Pod) bool {
return IsPodReadyConditionTrue(pod.Status)
}
// IsPodReady returns true if a pod is ready; false otherwise.
func IsPodReadyConditionTrue(status v1.PodStatus) bool {
condition := GetPodReadyCondition(status)
return condition != nil && condition.Status == v1.ConditionTrue
}
// Extracts the pod ready condition from the given status and returns that.
// Returns nil if the condition is not present.
func GetPodReadyCondition(status v1.PodStatus) *v1.PodCondition {
_, condition := GetPodCondition(&status, v1.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 *v1.PodStatus, conditionType v1.PodConditionType) (int, *v1.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 []v1.PodCondition, conditionType v1.PodConditionType) (int, *v1.PodCondition) {
if conditions == nil {
return -1, nil
}
for i := range conditions {
if conditions[i].Type == conditionType {
return i, &conditions[i]
}
}
return -1, nil
}
// Updates existing pod condition or creates a new one. Sets LastTransitionTime to now if the
// status has changed.
// Returns true if pod condition has changed or has been added.
func UpdatePodCondition(status *v1.PodStatus, condition *v1.PodCondition) bool {
condition.LastTransitionTime = metav1.Now()
// Try to find this pod condition.
conditionIndex, oldCondition := GetPodCondition(status, condition.Type)
if oldCondition == nil {
// We are adding new pod condition.
status.Conditions = append(status.Conditions, *condition)
return true
} else {
// We are updating an existing condition, so we need to check if it has changed.
if condition.Status == oldCondition.Status {
condition.LastTransitionTime = oldCondition.LastTransitionTime
}
isEqual := condition.Status == oldCondition.Status &&
condition.Reason == oldCondition.Reason &&
condition.Message == oldCondition.Message &&
condition.LastProbeTime.Equal(&oldCondition.LastProbeTime) &&
condition.LastTransitionTime.Equal(&oldCondition.LastTransitionTime)
status.Conditions[conditionIndex] = *condition
// Return true if one of the fields have changed.
return !isEqual
}
}

View File

@ -1,527 +0,0 @@
/*
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 pod
import (
"reflect"
"strings"
"testing"
"time"
"github.com/stretchr/testify/assert"
"k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/util/validation/field"
)
func TestFindPort(t *testing.T) {
testCases := []struct {
name string
containers []v1.Container
port intstr.IntOrString
expected int
pass bool
}{{
name: "valid int, no ports",
containers: []v1.Container{{}},
port: intstr.FromInt(93),
expected: 93,
pass: true,
}, {
name: "valid int, with ports",
containers: []v1.Container{{Ports: []v1.ContainerPort{{
Name: "",
ContainerPort: 11,
Protocol: "TCP",
}, {
Name: "p",
ContainerPort: 22,
Protocol: "TCP",
}}}},
port: intstr.FromInt(93),
expected: 93,
pass: true,
}, {
name: "valid str, no ports",
containers: []v1.Container{{}},
port: intstr.FromString("p"),
expected: 0,
pass: false,
}, {
name: "valid str, one ctr with ports",
containers: []v1.Container{{Ports: []v1.ContainerPort{{
Name: "",
ContainerPort: 11,
Protocol: "UDP",
}, {
Name: "p",
ContainerPort: 22,
Protocol: "TCP",
}, {
Name: "q",
ContainerPort: 33,
Protocol: "TCP",
}}}},
port: intstr.FromString("q"),
expected: 33,
pass: true,
}, {
name: "valid str, two ctr with ports",
containers: []v1.Container{{}, {Ports: []v1.ContainerPort{{
Name: "",
ContainerPort: 11,
Protocol: "UDP",
}, {
Name: "p",
ContainerPort: 22,
Protocol: "TCP",
}, {
Name: "q",
ContainerPort: 33,
Protocol: "TCP",
}}}},
port: intstr.FromString("q"),
expected: 33,
pass: true,
}, {
name: "valid str, two ctr with same port",
containers: []v1.Container{{}, {Ports: []v1.ContainerPort{{
Name: "",
ContainerPort: 11,
Protocol: "UDP",
}, {
Name: "p",
ContainerPort: 22,
Protocol: "TCP",
}, {
Name: "q",
ContainerPort: 22,
Protocol: "TCP",
}}}},
port: intstr.FromString("q"),
expected: 22,
pass: true,
}, {
name: "valid str, invalid protocol",
containers: []v1.Container{{}, {Ports: []v1.ContainerPort{{
Name: "a",
ContainerPort: 11,
Protocol: "snmp",
},
}}},
port: intstr.FromString("a"),
expected: 0,
pass: false,
}, {
name: "valid hostPort",
containers: []v1.Container{{}, {Ports: []v1.ContainerPort{{
Name: "a",
ContainerPort: 11,
HostPort: 81,
Protocol: "TCP",
},
}}},
port: intstr.FromString("a"),
expected: 11,
pass: true,
},
{
name: "invalid hostPort",
containers: []v1.Container{{}, {Ports: []v1.ContainerPort{{
Name: "a",
ContainerPort: 11,
HostPort: -1,
Protocol: "TCP",
},
}}},
port: intstr.FromString("a"),
expected: 11,
pass: true,
//this should fail but passes.
},
{
name: "invalid ContainerPort",
containers: []v1.Container{{}, {Ports: []v1.ContainerPort{{
Name: "a",
ContainerPort: -1,
Protocol: "TCP",
},
}}},
port: intstr.FromString("a"),
expected: -1,
pass: true,
//this should fail but passes
},
{
name: "HostIP Address",
containers: []v1.Container{{}, {Ports: []v1.ContainerPort{{
Name: "a",
ContainerPort: 11,
HostIP: "192.168.1.1",
Protocol: "TCP",
},
}}},
port: intstr.FromString("a"),
expected: 11,
pass: true,
},
}
for _, tc := range testCases {
port, err := FindPort(&v1.Pod{Spec: v1.PodSpec{Containers: tc.containers}},
&v1.ServicePort{Protocol: "TCP", TargetPort: tc.port})
if err != nil && tc.pass {
t.Errorf("unexpected error for %s: %v", tc.name, err)
}
if err == nil && !tc.pass {
t.Errorf("unexpected non-error for %s: %d", tc.name, port)
}
if port != tc.expected {
t.Errorf("wrong result for %s: expected %d, got %d", tc.name, tc.expected, port)
}
}
}
func TestPodSecrets(t *testing.T) {
// Stub containing all possible secret references in a pod.
// The names of the referenced secrets match struct paths detected by reflection.
pod := &v1.Pod{
Spec: v1.PodSpec{
Containers: []v1.Container{{
EnvFrom: []v1.EnvFromSource{{
SecretRef: &v1.SecretEnvSource{
LocalObjectReference: v1.LocalObjectReference{
Name: "Spec.Containers[*].EnvFrom[*].SecretRef"}}}},
Env: []v1.EnvVar{{
ValueFrom: &v1.EnvVarSource{
SecretKeyRef: &v1.SecretKeySelector{
LocalObjectReference: v1.LocalObjectReference{
Name: "Spec.Containers[*].Env[*].ValueFrom.SecretKeyRef"}}}}}}},
ImagePullSecrets: []v1.LocalObjectReference{{
Name: "Spec.ImagePullSecrets"}},
InitContainers: []v1.Container{{
EnvFrom: []v1.EnvFromSource{{
SecretRef: &v1.SecretEnvSource{
LocalObjectReference: v1.LocalObjectReference{
Name: "Spec.InitContainers[*].EnvFrom[*].SecretRef"}}}},
Env: []v1.EnvVar{{
ValueFrom: &v1.EnvVarSource{
SecretKeyRef: &v1.SecretKeySelector{
LocalObjectReference: v1.LocalObjectReference{
Name: "Spec.InitContainers[*].Env[*].ValueFrom.SecretKeyRef"}}}}}}},
Volumes: []v1.Volume{{
VolumeSource: v1.VolumeSource{
AzureFile: &v1.AzureFileVolumeSource{
SecretName: "Spec.Volumes[*].VolumeSource.AzureFile.SecretName"}}}, {
VolumeSource: v1.VolumeSource{
CephFS: &v1.CephFSVolumeSource{
SecretRef: &v1.LocalObjectReference{
Name: "Spec.Volumes[*].VolumeSource.CephFS.SecretRef"}}}}, {
VolumeSource: v1.VolumeSource{
Cinder: &v1.CinderVolumeSource{
SecretRef: &v1.LocalObjectReference{
Name: "Spec.Volumes[*].VolumeSource.Cinder.SecretRef"}}}}, {
VolumeSource: v1.VolumeSource{
FlexVolume: &v1.FlexVolumeSource{
SecretRef: &v1.LocalObjectReference{
Name: "Spec.Volumes[*].VolumeSource.FlexVolume.SecretRef"}}}}, {
VolumeSource: v1.VolumeSource{
Projected: &v1.ProjectedVolumeSource{
Sources: []v1.VolumeProjection{{
Secret: &v1.SecretProjection{
LocalObjectReference: v1.LocalObjectReference{
Name: "Spec.Volumes[*].VolumeSource.Projected.Sources[*].Secret"}}}}}}}, {
VolumeSource: v1.VolumeSource{
RBD: &v1.RBDVolumeSource{
SecretRef: &v1.LocalObjectReference{
Name: "Spec.Volumes[*].VolumeSource.RBD.SecretRef"}}}}, {
VolumeSource: v1.VolumeSource{
Secret: &v1.SecretVolumeSource{
SecretName: "Spec.Volumes[*].VolumeSource.Secret.SecretName"}}}, {
VolumeSource: v1.VolumeSource{
Secret: &v1.SecretVolumeSource{
SecretName: "Spec.Volumes[*].VolumeSource.Secret"}}}, {
VolumeSource: v1.VolumeSource{
ScaleIO: &v1.ScaleIOVolumeSource{
SecretRef: &v1.LocalObjectReference{
Name: "Spec.Volumes[*].VolumeSource.ScaleIO.SecretRef"}}}}, {
VolumeSource: v1.VolumeSource{
ISCSI: &v1.ISCSIVolumeSource{
SecretRef: &v1.LocalObjectReference{
Name: "Spec.Volumes[*].VolumeSource.ISCSI.SecretRef"}}}}, {
VolumeSource: v1.VolumeSource{
StorageOS: &v1.StorageOSVolumeSource{
SecretRef: &v1.LocalObjectReference{
Name: "Spec.Volumes[*].VolumeSource.StorageOS.SecretRef"}}}}},
},
}
extractedNames := sets.NewString()
VisitPodSecretNames(pod, func(name string) bool {
extractedNames.Insert(name)
return true
})
// excludedSecretPaths holds struct paths to fields with "secret" in the name that are not actually references to secret API objects
excludedSecretPaths := sets.NewString(
"Spec.Volumes[*].VolumeSource.CephFS.SecretFile",
)
// expectedSecretPaths holds struct paths to fields with "secret" in the name that are references to secret API objects.
// every path here should be represented as an example in the Pod stub above, with the secret name set to the path.
expectedSecretPaths := sets.NewString(
"Spec.Containers[*].EnvFrom[*].SecretRef",
"Spec.Containers[*].Env[*].ValueFrom.SecretKeyRef",
"Spec.ImagePullSecrets",
"Spec.InitContainers[*].EnvFrom[*].SecretRef",
"Spec.InitContainers[*].Env[*].ValueFrom.SecretKeyRef",
"Spec.Volumes[*].VolumeSource.AzureFile.SecretName",
"Spec.Volumes[*].VolumeSource.CephFS.SecretRef",
"Spec.Volumes[*].VolumeSource.Cinder.SecretRef",
"Spec.Volumes[*].VolumeSource.FlexVolume.SecretRef",
"Spec.Volumes[*].VolumeSource.Projected.Sources[*].Secret",
"Spec.Volumes[*].VolumeSource.RBD.SecretRef",
"Spec.Volumes[*].VolumeSource.Secret",
"Spec.Volumes[*].VolumeSource.Secret.SecretName",
"Spec.Volumes[*].VolumeSource.ScaleIO.SecretRef",
"Spec.Volumes[*].VolumeSource.ISCSI.SecretRef",
"Spec.Volumes[*].VolumeSource.StorageOS.SecretRef",
)
secretPaths := collectSecretPaths(t, nil, "", reflect.TypeOf(&v1.Pod{}))
secretPaths = secretPaths.Difference(excludedSecretPaths)
if missingPaths := expectedSecretPaths.Difference(secretPaths); len(missingPaths) > 0 {
t.Logf("Missing expected secret paths:\n%s", strings.Join(missingPaths.List(), "\n"))
t.Error("Missing expected secret paths. Verify VisitPodSecretNames() is correctly finding the missing paths, then correct expectedSecretPaths")
}
if extraPaths := secretPaths.Difference(expectedSecretPaths); len(extraPaths) > 0 {
t.Logf("Extra secret paths:\n%s", strings.Join(extraPaths.List(), "\n"))
t.Error("Extra fields with 'secret' in the name found. Verify VisitPodSecretNames() is including these fields if appropriate, then correct expectedSecretPaths")
}
if missingNames := expectedSecretPaths.Difference(extractedNames); len(missingNames) > 0 {
t.Logf("Missing expected secret names:\n%s", strings.Join(missingNames.List(), "\n"))
t.Error("Missing expected secret names. Verify the pod stub above includes these references, then verify VisitPodSecretNames() is correctly finding the missing names")
}
if extraNames := extractedNames.Difference(expectedSecretPaths); len(extraNames) > 0 {
t.Logf("Extra secret names:\n%s", strings.Join(extraNames.List(), "\n"))
t.Error("Extra secret names extracted. Verify VisitPodSecretNames() is correctly extracting secret names")
}
}
// collectSecretPaths traverses the object, computing all the struct paths that lead to fields with "secret" in the name.
func collectSecretPaths(t *testing.T, path *field.Path, name string, tp reflect.Type) sets.String {
secretPaths := sets.NewString()
if tp.Kind() == reflect.Ptr {
secretPaths.Insert(collectSecretPaths(t, path, name, tp.Elem()).List()...)
return secretPaths
}
if strings.Contains(strings.ToLower(name), "secret") {
secretPaths.Insert(path.String())
}
switch tp.Kind() {
case reflect.Ptr:
secretPaths.Insert(collectSecretPaths(t, path, name, tp.Elem()).List()...)
case reflect.Struct:
for i := 0; i < tp.NumField(); i++ {
field := tp.Field(i)
secretPaths.Insert(collectSecretPaths(t, path.Child(field.Name), field.Name, field.Type).List()...)
}
case reflect.Interface:
t.Errorf("cannot find secret fields in interface{} field %s", path.String())
case reflect.Map:
secretPaths.Insert(collectSecretPaths(t, path.Key("*"), "", tp.Elem()).List()...)
case reflect.Slice:
secretPaths.Insert(collectSecretPaths(t, path.Key("*"), "", tp.Elem()).List()...)
default:
// all primitive types
}
return secretPaths
}
func newPod(now metav1.Time, ready bool, beforeSec int) *v1.Pod {
conditionStatus := v1.ConditionFalse
if ready {
conditionStatus = v1.ConditionTrue
}
return &v1.Pod{
Status: v1.PodStatus{
Conditions: []v1.PodCondition{
{
Type: v1.PodReady,
LastTransitionTime: metav1.NewTime(now.Time.Add(-1 * time.Duration(beforeSec) * time.Second)),
Status: conditionStatus,
},
},
},
}
}
func TestIsPodAvailable(t *testing.T) {
now := metav1.Now()
tests := []struct {
pod *v1.Pod
minReadySeconds int32
expected bool
}{
{
pod: newPod(now, false, 0),
minReadySeconds: 0,
expected: false,
},
{
pod: newPod(now, true, 0),
minReadySeconds: 1,
expected: false,
},
{
pod: newPod(now, true, 0),
minReadySeconds: 0,
expected: true,
},
{
pod: newPod(now, true, 51),
minReadySeconds: 50,
expected: true,
},
}
for i, test := range tests {
isAvailable := IsPodAvailable(test.pod, test.minReadySeconds, now)
if isAvailable != test.expected {
t.Errorf("[tc #%d] expected available pod: %t, got: %t", i, test.expected, isAvailable)
}
}
}
func TestGetContainerStatus(t *testing.T) {
type ExpectedStruct struct {
status v1.ContainerStatus
exists bool
}
tests := []struct {
status []v1.ContainerStatus
name string
expected ExpectedStruct
desc string
}{
{
status: []v1.ContainerStatus{{Name: "test1", Ready: false, Image: "image1"}, {Name: "test2", Ready: true, Image: "image1"}},
name: "test1",
expected: ExpectedStruct{status: v1.ContainerStatus{Name: "test1", Ready: false, Image: "image1"}, exists: true},
desc: "retrieve ContainerStatus with Name=\"test1\"",
},
{
status: []v1.ContainerStatus{{Name: "test2", Ready: false, Image: "image2"}},
name: "test1",
expected: ExpectedStruct{status: v1.ContainerStatus{}, exists: false},
desc: "no matching ContainerStatus with Name=\"test1\"",
},
{
status: []v1.ContainerStatus{{Name: "test3", Ready: false, Image: "image3"}},
name: "",
expected: ExpectedStruct{status: v1.ContainerStatus{}, exists: false},
desc: "retrieve an empty ContainerStatus with container name empty",
},
{
status: nil,
name: "",
expected: ExpectedStruct{status: v1.ContainerStatus{}, exists: false},
desc: "retrieve an empty ContainerStatus with status nil",
},
}
for _, test := range tests {
resultStatus, exists := GetContainerStatus(test.status, test.name)
assert.Equal(t, test.expected.status, resultStatus, "GetContainerStatus: "+test.desc)
assert.Equal(t, test.expected.exists, exists, "GetContainerStatus: "+test.desc)
resultStatus = GetExistingContainerStatus(test.status, test.name)
assert.Equal(t, test.expected.status, resultStatus, "GetExistingContainerStatus: "+test.desc)
}
}
func TestUpdatePodCondition(t *testing.T) {
time := metav1.Now()
podStatus := v1.PodStatus{
Conditions: []v1.PodCondition{
{
Type: v1.PodReady,
Status: v1.ConditionTrue,
Reason: "successfully",
Message: "sync pod successfully",
LastProbeTime: time,
LastTransitionTime: metav1.NewTime(time.Add(1000)),
},
},
}
tests := []struct {
status *v1.PodStatus
conditions v1.PodCondition
expected bool
desc string
}{
{
status: &podStatus,
conditions: v1.PodCondition{
Type: v1.PodReady,
Status: v1.ConditionTrue,
Reason: "successfully",
Message: "sync pod successfully",
LastProbeTime: time,
LastTransitionTime: metav1.NewTime(time.Add(1000))},
expected: false,
desc: "all equal, no update",
},
{
status: &podStatus,
conditions: v1.PodCondition{
Type: v1.PodScheduled,
Status: v1.ConditionTrue,
Reason: "successfully",
Message: "sync pod successfully",
LastProbeTime: time,
LastTransitionTime: metav1.NewTime(time.Add(1000))},
expected: true,
desc: "not equal Type, should get updated",
},
{
status: &podStatus,
conditions: v1.PodCondition{
Type: v1.PodReady,
Status: v1.ConditionFalse,
Reason: "successfully",
Message: "sync pod successfully",
LastProbeTime: time,
LastTransitionTime: metav1.NewTime(time.Add(1000))},
expected: true,
desc: "not equal Status, should get updated",
},
}
for _, test := range tests {
var resultStatus bool
resultStatus = UpdatePodCondition(test.status, &test.conditions)
assert.Equal(t, test.expected, resultStatus, test.desc)
}
}