add ut for lifted codes
Signed-off-by: Poor12 <shentiecheng@huawei.com>
This commit is contained in:
parent
da948ce252
commit
d0f76e1070
|
@ -4,69 +4,81 @@
|
|||
package lifted
|
||||
|
||||
/*
|
||||
| lifted file | source file | const/var/type/func | changed |
|
||||
|--------------------------|-------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------|---------|
|
||||
| corehelpers.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/apis/core/helper/helpers.go#L57-L61 | func IsQuotaHugePageResourceName | N |
|
||||
| corehelpers.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/apis/core/helper/helpers.go#L212-L232 | var standardQuotaResources | N |
|
||||
| corehelpers.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/apis/core/helper/helpers.go#L234-L238 | func IsStandardQuotaResourceName | N |
|
||||
| corehelpers.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/apis/core/helper/helpers.go#L240-L261 | var standardResources | N |
|
||||
| corehelpers.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/apis/core/helper/helpers.go#L263-L266 | func IsStandardResourceName | N |
|
||||
| corehelpers.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/apis/core/helper/helpers.go#L268-L278 | var integerResources | N |
|
||||
| corehelpers.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/apis/core/helper/helpers.go#L280-L283 | func IsIntegerResourceName | N |
|
||||
| corev1helpers.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/apis/core/v1/helper/helpers.go#L31-L46 | func IsExtendedResourceName | Y |
|
||||
| corev1helpers.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/apis/core/v1/helper/helpers.go#L48-L51 | func IsPrefixedNativeResource | N |
|
||||
| corev1helpers.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/apis/core/v1/helper/helpers.go#L54-L60 | func IsNativeResource | N |
|
||||
| corev1helpers.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/apis/core/v1/helper/helpers.go#L62-L66 | func IsHugePageResourceName | N |
|
||||
| corev1helpers.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/apis/core/v1/helper/helpers.go#L132-L135 | func IsAttachableVolumeResourceName | N |
|
||||
| corevalidation.go | https://github.com/kubernetes/kubernetes/blob/release-1.22/pkg/apis/core/validation/validation.go#L59 | const isNegativeErrorMsg | N |
|
||||
| corevalidation.go | https://github.com/kubernetes/kubernetes/blob/release-1.22/pkg/apis/core/validation/validation.go#L60 | const isInvalidQuotaResource | N |
|
||||
| corevalidation.go | https://github.com/kubernetes/kubernetes/blob/release-1.22/pkg/apis/core/validation/validation.go#L62 | const isNotIntegerErrorMsg | N |
|
||||
| corevalidation.go | https://github.com/kubernetes/kubernetes/blob/release-1.22/pkg/apis/core/validation/validation.go#L225-L228 | var ValidatePodName | N |
|
||||
| corevalidation.go | https://github.com/kubernetes/kubernetes/blob/release-1.22/pkg/apis/core/validation/validation.go#L311-L318 | func ValidateNonnegativeQuantity | N |
|
||||
| corevalidation.go | https://github.com/kubernetes/kubernetes/blob/release-1.22/pkg/apis/core/validation/validation.go#L5036-L5054 | func validateResourceName | Y |
|
||||
| corevalidation.go | https://github.com/kubernetes/kubernetes/blob/release-1.22/pkg/apis/core/validation/validation.go#L5073-L5084 | func ValidateResourceQuotaResourceName | Y |
|
||||
| corevalidation.go | https://github.com/kubernetes/kubernetes/blob/release-1.22/pkg/apis/core/validation/validation.go#L5651-L5661 | func ValidateResourceQuantityValue | Y |
|
||||
| deployment.go | https://github.com/kubernetes/kubernetes/blob/release-1.22/pkg/controller/controller_utils.go#L1003-L1012 | type ReplicaSetsByCreationTimestamp | N |
|
||||
| deployment.go | https://github.com/kubernetes/kubernetes/blob/release-1.22/pkg/controller/deployment/util/deployment_util.go#L569-L594 | func ListReplicaSetsByDeployment | Y |
|
||||
| deployment.go | https://github.com/kubernetes/kubernetes/blob/release-1.22/pkg/controller/deployment/util/deployment_util.go#L596-L628 | func ListPodsByRS | Y |
|
||||
| deployment.go | https://github.com/kubernetes/kubernetes/blob/release-1.22/pkg/controller/deployment/util/deployment_util.go#L630-L642 | func EqualIgnoreHash | N |
|
||||
| deployment.go | https://github.com/kubernetes/kubernetes/blob/release-1.22/pkg/controller/deployment/util/deployment_util.go#L536-L544 | func GetNewReplicaSet | Y |
|
||||
| deployment.go | https://github.com/kubernetes/kubernetes/blob/release-1.22/pkg/controller/deployment/util/deployment_util.go#L644-L658 | func FindNewReplicaSet | N |
|
||||
| discovery.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/controller/garbagecollector/garbagecollector.go#L696-L732 | func GetDeletableResources | N |
|
||||
| discovery_test.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/controller/garbagecollector/garbagecollector_test.go#L943-L990 | type fakeServerResources | N |
|
||||
| discovery_test.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/controller/garbagecollector/garbagecollector_test.go#L707-L797 | func TestGetDeletableResources | N |
|
||||
| nodeselector.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/apis/core/helper/helpers.go#L365-L397 | func NodeSelectorRequirementsAsSelector | N |
|
||||
| objectwatcher.go | https://github.com/kubernetes-sigs/kubefed/blob/master/pkg/controller/util/propagatedversion.go#L35-L43 | func ObjectVersion | N |
|
||||
| objectwatcher.go | https://github.com/kubernetes-sigs/kubefed/blob/master/pkg/controller/util/propagatedversion.go#L45-L59 | func ObjectNeedsUpdate | N |
|
||||
| objectwatcher.go | https://github.com/kubernetes-sigs/kubefed/blob/master/pkg/controller/util/meta.go#L63-L80 | func objectMetaObjEquivalent | Y |
|
||||
| podtemplate.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/controller/controller_utils.go#L466-L472 | func getPodsLabelSet | N |
|
||||
| podtemplate.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/controller/controller_utils.go#L474-L478 | func getPodsFinalizers | N |
|
||||
| podtemplate.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/controller/controller_utils.go#L480-L486 | func getPodsAnnotationSet | N |
|
||||
| podtemplate.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/controller/controller_utils.go#L488-L495 | func getPodsPrefix | N |
|
||||
| podtemplate.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/controller/controller_utils.go#L539-L562 | func GetPodFromTemplate | Y |
|
||||
| requestinfo.go | https://github.com/kubernetes/apiserver/blob/release-1.23/pkg/endpoints/request/requestinfo.go#L88-L247 | func NewRequestInfo | Y |
|
||||
| requestinfo.go | https://github.com/kubernetes/apiserver/blob/release-1.23/pkg/endpoints/request/requestinfo.go#L267-L274 | func SplitPath | Y |
|
||||
| requestinfo.go | https://github.com/kubernetes/apiserver/blob/release-1.23/pkg/endpoints/request/requestinfo.go#L73-L74 | var specialVerbsNoSubresources | N |
|
||||
| requestinfo.go | https://github.com/kubernetes/apiserver/blob/release-1.23/pkg/endpoints/request/requestinfo.go#L76-L78 | var namespaceSubresources | N |
|
||||
| requestinfo.go | https://github.com/kubernetes/apiserver/blob/release-1.23/pkg/endpoints/request/requestinfo.go#L67-L71 | var specialVerbs | N |
|
||||
| resourcename.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/scheduler/util/utils.go#L144-L148 | func IsScalarResourceName | Y |
|
||||
| retain.go | https://github.com/kubernetes-sigs/kubefed/blob/master/pkg/controller/sync/dispatch/retain.go | func RetainServiceFields | Y |
|
||||
| retain.go | https://github.com/kubernetes-sigs/kubefed/blob/master/pkg/controller/sync/dispatch/retain.go | func retainServiceHealthCheckNodePort | Y |
|
||||
| retain.go | https://github.com/kubernetes-sigs/kubefed/blob/master/pkg/controller/sync/dispatch/retain.go | func retainServiceClusterIP | Y |
|
||||
| retain.go | https://github.com/kubernetes-sigs/kubefed/blob/master/pkg/controller/sync/dispatch/retain.go | func RetainServiceAccountFields | Y |
|
||||
| taint.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/staging/src/k8s.io/kubectl/pkg/cmd/taint/utils.go#L37-L73 | func ParseTaints | N |
|
||||
| taint.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/staging/src/k8s.io/kubectl/pkg/cmd/taint/utils.go#L75-L118 | func parseTaint | N |
|
||||
| taint.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/staging/src/k8s.io/kubectl/pkg/cmd/taint/utils.go#L120-L126 | func validateTaintEffect | N |
|
||||
| validateclustertaints.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/apis/core/validation/validation.go#L5001-L5033 | func ValidateClusterTaints | Y |
|
||||
| validateclustertaints.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/apis/core/validation/validation.go#L3305-L3326 | func validateClusterTaintEffect | Y |
|
||||
| visitpod.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/api/v1/pod/util.go#L53-L63 | type ContainerType | N |
|
||||
| visitpod.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/api/v1/pod/util.go#L65-L66 | const AllContainers | N |
|
||||
| visitpod.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/api/v1/pod/util.go#L78-L80 | type ContainerVisitor | N |
|
||||
| visitpod.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/api/v1/pod/util.go#L82-L83 | type Visitor | N |
|
||||
| visitpod.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/api/v1/pod/util.go#L85-L94 | func skipEmptyNames | N |
|
||||
| visitpod.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/api/v1/pod/util.go#L96-L123 | func VisitContainers | N |
|
||||
| visitpod.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/api/v1/pod/util.go#L125-L195 | func VisitPodSecretNames | N |
|
||||
| visitpod.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/api/v1/pod/util.go#L197-L213 | func visitContainerSecretNames | N |
|
||||
| visitpod.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/api/v1/pod/util.go#L215-L243 | func VisitPodConfigmapNames | N |
|
||||
| visitpod.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/api/v1/pod/util.go#L245-L261 | func visitContainerConfigmapNames | N |
|
||||
| lifted file | source file | const/var/type/func | changed |
|
||||
|--------------------------|------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------|---------|
|
||||
| corehelpers.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/apis/core/helper/helpers.go#L57-L61 | func IsQuotaHugePageResourceName | N |
|
||||
| corehelpers.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/apis/core/helper/helpers.go#L212-L232 | var standardQuotaResources | N |
|
||||
| corehelpers.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/apis/core/helper/helpers.go#L234-L238 | func IsStandardQuotaResourceName | N |
|
||||
| corehelpers.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/apis/core/helper/helpers.go#L240-L261 | var standardResources | N |
|
||||
| corehelpers.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/apis/core/helper/helpers.go#L263-L266 | func IsStandardResourceName | N |
|
||||
| corehelpers.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/apis/core/helper/helpers.go#L268-L278 | var integerResources | N |
|
||||
| corehelpers.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/apis/core/helper/helpers.go#L280-L283 | func IsIntegerResourceName | N |
|
||||
| corev1helpers.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/apis/core/v1/helper/helpers.go#L31-L46 | func IsExtendedResourceName | Y |
|
||||
| corev1helpers.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/apis/core/v1/helper/helpers.go#L48-L51 | func IsPrefixedNativeResource | N |
|
||||
| corev1helpers.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/apis/core/v1/helper/helpers.go#L54-L60 | func IsNativeResource | N |
|
||||
| corev1helpers.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/apis/core/v1/helper/helpers.go#L62-L66 | func IsHugePageResourceName | N |
|
||||
| corev1helpers.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/apis/core/v1/helper/helpers.go#L132-L135 | func IsAttachableVolumeResourceName | N |
|
||||
| corevalidation.go | https://github.com/kubernetes/kubernetes/blob/release-1.22/pkg/apis/core/validation/validation.go#L59 | const isNegativeErrorMsg | N |
|
||||
| corevalidation.go | https://github.com/kubernetes/kubernetes/blob/release-1.22/pkg/apis/core/validation/validation.go#L60 | const isInvalidQuotaResource | N |
|
||||
| corevalidation.go | https://github.com/kubernetes/kubernetes/blob/release-1.22/pkg/apis/core/validation/validation.go#L62 | const isNotIntegerErrorMsg | N |
|
||||
| corevalidation.go | https://github.com/kubernetes/kubernetes/blob/release-1.22/pkg/apis/core/validation/validation.go#L225-L228 | var ValidatePodName | N |
|
||||
| corevalidation.go | https://github.com/kubernetes/kubernetes/blob/release-1.22/pkg/apis/core/validation/validation.go#L311-L318 | func ValidateNonnegativeQuantity | N |
|
||||
| corevalidation.go | https://github.com/kubernetes/kubernetes/blob/release-1.22/pkg/apis/core/validation/validation.go#L5036-L5054 | func validateResourceName | Y |
|
||||
| corevalidation.go | https://github.com/kubernetes/kubernetes/blob/release-1.22/pkg/apis/core/validation/validation.go#L5073-L5084 | func ValidateResourceQuotaResourceName | Y |
|
||||
| corevalidation.go | https://github.com/kubernetes/kubernetes/blob/release-1.22/pkg/apis/core/validation/validation.go#L5651-L5661 | func ValidateResourceQuantityValue | Y |
|
||||
| deployment.go | https://github.com/kubernetes/kubernetes/blob/release-1.22/pkg/controller/controller_utils.go#L1003-L1012 | type ReplicaSetsByCreationTimestamp | N |
|
||||
| deployment.go | https://github.com/kubernetes/kubernetes/blob/release-1.22/pkg/controller/deployment/util/deployment_util.go#L569-L594 | func ListReplicaSetsByDeployment | Y |
|
||||
| deployment.go | https://github.com/kubernetes/kubernetes/blob/release-1.22/pkg/controller/deployment/util/deployment_util.go#L596-L628 | func ListPodsByRS | Y |
|
||||
| deployment.go | https://github.com/kubernetes/kubernetes/blob/release-1.22/pkg/controller/deployment/util/deployment_util.go#L630-L642 | func EqualIgnoreHash | N |
|
||||
| deployment.go | https://github.com/kubernetes/kubernetes/blob/release-1.22/pkg/controller/deployment/util/deployment_util.go#L536-L544 | func GetNewReplicaSet | Y |
|
||||
| deployment.go | https://github.com/kubernetes/kubernetes/blob/release-1.22/pkg/controller/deployment/util/deployment_util.go#L644-L658 | func FindNewReplicaSet | N |
|
||||
| discovery.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/controller/garbagecollector/garbagecollector.go#L696-L732 | func GetDeletableResources | N |
|
||||
| discovery_test.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/controller/garbagecollector/garbagecollector_test.go#L943-L990 | type fakeServerResources | N |
|
||||
| discovery_test.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/controller/garbagecollector/garbagecollector_test.go#L707-L797 | func TestGetDeletableResources | N |
|
||||
| nodeselector.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/apis/core/helper/helpers.go#L365-L397 | func NodeSelectorRequirementsAsSelector | N |
|
||||
| nodeselector_test.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/apis/core/helper/helpers_test.go#L138-L200 | func TestNodeSelectorRequirementsAsSelector | N |
|
||||
| objectwatcher.go | https://github.com/kubernetes-sigs/kubefed/blob/master/pkg/controller/util/propagatedversion.go#L35-L43 | func ObjectVersion | N |
|
||||
| objectwatcher.go | https://github.com/kubernetes-sigs/kubefed/blob/master/pkg/controller/util/propagatedversion.go#L45-L59 | func ObjectNeedsUpdate | N |
|
||||
| objectwatcher.go | https://github.com/kubernetes-sigs/kubefed/blob/master/pkg/controller/util/meta.go#L63-L80 | func objectMetaObjEquivalent | Y |
|
||||
| parallelism_test.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/scheduler/framework/parallelize/parallelism_test.go | func TestChunkSize | N |
|
||||
| podtemplate.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/controller/controller_utils.go#L466-L472 | func getPodsLabelSet | N |
|
||||
| podtemplate.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/controller/controller_utils.go#L474-L478 | func getPodsFinalizers | N |
|
||||
| podtemplate.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/controller/controller_utils.go#L480-L486 | func getPodsAnnotationSet | N |
|
||||
| podtemplate.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/controller/controller_utils.go#L488-L495 | func getPodsPrefix | N |
|
||||
| podtemplate.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/controller/controller_utils.go#L539-L562 | func GetPodFromTemplate | Y |
|
||||
| requestinfo.go | https://github.com/kubernetes/apiserver/blob/release-1.23/pkg/endpoints/request/requestinfo.go#L88-L247 | func NewRequestInfo | Y |
|
||||
| requestinfo.go | https://github.com/kubernetes/apiserver/blob/release-1.23/pkg/endpoints/request/requestinfo.go#L267-L274 | func SplitPath | Y |
|
||||
| requestinfo.go | https://github.com/kubernetes/apiserver/blob/release-1.23/pkg/endpoints/request/requestinfo.go#L73-L74 | var specialVerbsNoSubresources | N |
|
||||
| requestinfo.go | https://github.com/kubernetes/apiserver/blob/release-1.23/pkg/endpoints/request/requestinfo.go#L76-L78 | var namespaceSubresources | N |
|
||||
| requestinfo.go | https://github.com/kubernetes/apiserver/blob/release-1.23/pkg/endpoints/request/requestinfo.go#L67-L71 | var specialVerbs | N |
|
||||
| requestinfo_test.go | https://github.com/kubernetes/apiserver/blob/release-1.23/pkg/endpoints/request/requestinfo_test.go#L30-L148 | func TestGetAPIRequestInfo | Y |
|
||||
| requestinfo_test.go | https://github.com/kubernetes/apiserver/blob/release-1.23/pkg/endpoints/request/requestinfo_test.go#L150-L184 | func TestGetNonAPIRequestInfo | Y |
|
||||
| resourcename.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/scheduler/util/utils.go#L144-L148 | func IsScalarResourceName | Y |
|
||||
| retain.go | https://github.com/kubernetes-sigs/kubefed/blob/master/pkg/controller/sync/dispatch/retain.go | func RetainServiceFields | Y |
|
||||
| retain.go | https://github.com/kubernetes-sigs/kubefed/blob/master/pkg/controller/sync/dispatch/retain.go | func retainServiceHealthCheckNodePort | Y |
|
||||
| retain.go | https://github.com/kubernetes-sigs/kubefed/blob/master/pkg/controller/sync/dispatch/retain.go | func retainServiceClusterIP | Y |
|
||||
| retain.go | https://github.com/kubernetes-sigs/kubefed/blob/master/pkg/controller/sync/dispatch/retain.go | func RetainServiceAccountFields | Y |
|
||||
| retain_test.go | https://github.com/kubernetes-sigs/kubefed/blob/master/pkg/controller/sync/dispatch/retain_test.go#L91-L174 | func TestRetainHealthCheckNodePortInServiceFields | Y |
|
||||
| retain_test.go | https://github.com/kubernetes-sigs/kubefed/blob/master/pkg/controller/sync/dispatch/retain_test.go#L176-L292 | func TestRetainClusterIPInServiceFields | Y |
|
||||
| taint.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/staging/src/k8s.io/kubectl/pkg/cmd/taint/utils.go#L37-L73 | func ParseTaints | N |
|
||||
| taint.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/staging/src/k8s.io/kubectl/pkg/cmd/taint/utils.go#L75-L118 | func parseTaint | N |
|
||||
| taint.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/staging/src/k8s.io/kubectl/pkg/cmd/taint/utils.go#L120-L126 | func validateTaintEffect | N |
|
||||
| validateclustertaints.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/apis/core/validation/validation.go#L5001-L5033 | func ValidateClusterTaints | Y |
|
||||
| validateclustertaints.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/apis/core/validation/validation.go#L3305-L3326 | func validateClusterTaintEffect | Y |
|
||||
| visitpod.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/api/v1/pod/util.go#L53-L63 | type ContainerType | N |
|
||||
| visitpod.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/api/v1/pod/util.go#L65-L66 | const AllContainers | N |
|
||||
| visitpod.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/api/v1/pod/util.go#L78-L80 | type ContainerVisitor | N |
|
||||
| visitpod.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/api/v1/pod/util.go#L82-L83 | type Visitor | N |
|
||||
| visitpod.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/api/v1/pod/util.go#L85-L94 | func skipEmptyNames | N |
|
||||
| visitpod.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/api/v1/pod/util.go#L96-L123 | func VisitContainers | N |
|
||||
| visitpod.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/api/v1/pod/util.go#L125-L195 | func VisitPodSecretNames | N |
|
||||
| visitpod.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/api/v1/pod/util.go#L197-L213 | func visitContainerSecretNames | N |
|
||||
| visitpod.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/api/v1/pod/util.go#L215-L243 | func VisitPodConfigmapNames | N |
|
||||
| visitpod.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/api/v1/pod/util.go#L245-L261 | func visitContainerConfigmapNames | N |
|
||||
| visitpod_test.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/api/v1/pod/util.go#L68-L76 | func AllFeatureEnabledContainers | N |
|
||||
| visitpod_test.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/staging/src/k8s.io/component-base/featuregate/testing/feature_gate.go#L26-L44 | func SetFeatureGateDuringTest | N |
|
||||
| visitpod_test.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/api/v1/pod/util_test.go#L205-L392 | func TestVisitContainers | Y |
|
||||
| visitpod_test.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/api/v1/pod/util_test.go#L394-L551 | func TestPodSecrets | Y |
|
||||
| visitpod_test.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/api/v1/pod/util_test.go#L553-L591 | func collectResourcePaths | N |
|
||||
| visitpod_test.go | https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/api/v1/pod/util_test.go#L593-L695 | func TestPodConfigmaps | Y |
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
Copyright 2020 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.
|
||||
*/
|
||||
|
||||
// This code is directly lifted from the Kubernetes codebase in order to avoid relying on the k8s.io/kubernetes package.
|
||||
// For reference:
|
||||
// https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/apis/core/helper/helpers_test.go#L138-L200
|
||||
|
||||
package lifted
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
)
|
||||
|
||||
// +lifted:source=https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/apis/core/helper/helpers_test.go#L138-L200
|
||||
|
||||
func TestNodeSelectorRequirementsAsSelector(t *testing.T) {
|
||||
matchExpressions := []corev1.NodeSelectorRequirement{{
|
||||
Key: "foo",
|
||||
Operator: corev1.NodeSelectorOpIn,
|
||||
Values: []string{"bar", "baz"},
|
||||
}}
|
||||
mustParse := func(s string) labels.Selector {
|
||||
out, e := labels.Parse(s)
|
||||
if e != nil {
|
||||
panic(e)
|
||||
}
|
||||
return out
|
||||
}
|
||||
tc := []struct {
|
||||
in []corev1.NodeSelectorRequirement
|
||||
out labels.Selector
|
||||
expectErr bool
|
||||
}{
|
||||
{in: nil, out: labels.Nothing()},
|
||||
{in: []corev1.NodeSelectorRequirement{}, out: labels.Nothing()},
|
||||
{
|
||||
in: matchExpressions,
|
||||
out: mustParse("foo in (baz,bar)"),
|
||||
},
|
||||
{
|
||||
in: []corev1.NodeSelectorRequirement{{
|
||||
Key: "foo",
|
||||
Operator: corev1.NodeSelectorOpExists,
|
||||
Values: []string{"bar", "baz"},
|
||||
}},
|
||||
expectErr: true,
|
||||
},
|
||||
{
|
||||
in: []corev1.NodeSelectorRequirement{{
|
||||
Key: "foo",
|
||||
Operator: corev1.NodeSelectorOpGt,
|
||||
Values: []string{"1"},
|
||||
}},
|
||||
out: mustParse("foo>1"),
|
||||
},
|
||||
{
|
||||
in: []corev1.NodeSelectorRequirement{{
|
||||
Key: "bar",
|
||||
Operator: corev1.NodeSelectorOpLt,
|
||||
Values: []string{"7"},
|
||||
}},
|
||||
out: mustParse("bar<7"),
|
||||
},
|
||||
}
|
||||
|
||||
for i, tc := range tc {
|
||||
out, err := NodeSelectorRequirementsAsSelector(tc.in)
|
||||
if err == nil && tc.expectErr {
|
||||
t.Errorf("[%v]expected error but got none.", i)
|
||||
}
|
||||
if err != nil && !tc.expectErr {
|
||||
t.Errorf("[%v]did not expect error but got: %v", i, err)
|
||||
}
|
||||
if !reflect.DeepEqual(out, tc.out) {
|
||||
t.Errorf("[%v]expected:\n\t%+v\nbut got:\n\t%+v", i, tc.out, out)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
Copyright 2020 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.
|
||||
*/
|
||||
|
||||
// This code is directly lifted from the Kubernetes codebase.
|
||||
// For reference:
|
||||
// https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/scheduler/framework/parallelize/parallelism_test.go
|
||||
|
||||
package lifted
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// +lifted:source=https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/scheduler/framework/parallelize/parallelism_test.go
|
||||
|
||||
func TestChunkSize(t *testing.T) {
|
||||
tests := []struct {
|
||||
input int
|
||||
wantOutput int
|
||||
}{
|
||||
{
|
||||
input: 32,
|
||||
wantOutput: 3,
|
||||
},
|
||||
{
|
||||
input: 16,
|
||||
wantOutput: 2,
|
||||
},
|
||||
{
|
||||
input: 1,
|
||||
wantOutput: 1,
|
||||
},
|
||||
{
|
||||
input: 0,
|
||||
wantOutput: 1,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(fmt.Sprintf("%d", test.input), func(t *testing.T) {
|
||||
if chunkSizeFor(test.input, DefaultParallelism) != test.wantOutput {
|
||||
t.Errorf("Expected: %d, got: %d", test.wantOutput, chunkSizeFor(test.input, DefaultParallelism))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,9 +1,12 @@
|
|||
/*
|
||||
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.
|
||||
|
|
|
@ -0,0 +1,178 @@
|
|||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
// This code is directly lifted from the Kubernetes codebase.
|
||||
// For reference:
|
||||
// https://github.com/kubernetes/apiserver/blob/release-1.23/pkg/endpoints/request/requestinfo_test.go#L30-L184
|
||||
|
||||
package lifted
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
// +lifted:source=https://github.com/kubernetes/apiserver/blob/release-1.23/pkg/endpoints/request/requestinfo_test.go#L30-L148
|
||||
// +lifted:changed
|
||||
|
||||
func TestGetAPIRequestInfo(t *testing.T) {
|
||||
namespaceAll := metav1.NamespaceAll
|
||||
successCases := []struct {
|
||||
method string
|
||||
url string
|
||||
expectedVerb string
|
||||
expectedAPIPrefix string
|
||||
expectedAPIGroup string
|
||||
expectedAPIVersion string
|
||||
expectedNamespace string
|
||||
expectedResource string
|
||||
expectedSubresource string
|
||||
expectedName string
|
||||
expectedParts []string
|
||||
}{
|
||||
|
||||
// resource paths
|
||||
{"GET", "/api/v1/namespaces", "list", "api", "", "v1", "", "namespaces", "", "", []string{"namespaces"}},
|
||||
{"GET", "/api/v1/namespaces/other", "get", "api", "", "v1", "other", "namespaces", "", "other", []string{"namespaces", "other"}},
|
||||
|
||||
{"GET", "/api/v1/namespaces/other/pods", "list", "api", "", "v1", "other", "pods", "", "", []string{"pods"}},
|
||||
{"GET", "/api/v1/namespaces/other/pods/foo", "get", "api", "", "v1", "other", "pods", "", "foo", []string{"pods", "foo"}},
|
||||
{"HEAD", "/api/v1/namespaces/other/pods/foo", "get", "api", "", "v1", "other", "pods", "", "foo", []string{"pods", "foo"}},
|
||||
{"GET", "/api/v1/pods", "list", "api", "", "v1", namespaceAll, "pods", "", "", []string{"pods"}},
|
||||
{"HEAD", "/api/v1/pods", "list", "api", "", "v1", namespaceAll, "pods", "", "", []string{"pods"}},
|
||||
{"GET", "/api/v1/namespaces/other/pods/foo", "get", "api", "", "v1", "other", "pods", "", "foo", []string{"pods", "foo"}},
|
||||
{"GET", "/api/v1/namespaces/other/pods", "list", "api", "", "v1", "other", "pods", "", "", []string{"pods"}},
|
||||
|
||||
// special verbs
|
||||
{"GET", "/api/v1/proxy/namespaces/other/pods/foo", "proxy", "api", "", "v1", "other", "pods", "", "foo", []string{"pods", "foo"}},
|
||||
{"GET", "/api/v1/proxy/namespaces/other/pods/foo/subpath/not/a/subresource", "proxy", "api", "", "v1", "other", "pods", "", "foo", []string{"pods", "foo", "subpath", "not", "a", "subresource"}},
|
||||
{"GET", "/api/v1/watch/pods", "watch", "api", "", "v1", namespaceAll, "pods", "", "", []string{"pods"}},
|
||||
{"GET", "/api/v1/pods?watch=true", "watch", "api", "", "v1", namespaceAll, "pods", "", "", []string{"pods"}},
|
||||
{"GET", "/api/v1/pods?watch=false", "list", "api", "", "v1", namespaceAll, "pods", "", "", []string{"pods"}},
|
||||
{"GET", "/api/v1/watch/namespaces/other/pods", "watch", "api", "", "v1", "other", "pods", "", "", []string{"pods"}},
|
||||
{"GET", "/api/v1/namespaces/other/pods?watch=1", "watch", "api", "", "v1", "other", "pods", "", "", []string{"pods"}},
|
||||
{"GET", "/api/v1/namespaces/other/pods?watch=0", "list", "api", "", "v1", "other", "pods", "", "", []string{"pods"}},
|
||||
|
||||
// subresource identification
|
||||
{"GET", "/api/v1/namespaces/other/pods/foo/status", "get", "api", "", "v1", "other", "pods", "status", "foo", []string{"pods", "foo", "status"}},
|
||||
{"GET", "/api/v1/namespaces/other/pods/foo/proxy/subpath", "get", "api", "", "v1", "other", "pods", "proxy", "foo", []string{"pods", "foo", "proxy", "subpath"}},
|
||||
{"PUT", "/api/v1/namespaces/other/finalize", "update", "api", "", "v1", "other", "namespaces", "finalize", "other", []string{"namespaces", "other", "finalize"}},
|
||||
{"PUT", "/api/v1/namespaces/other/status", "update", "api", "", "v1", "other", "namespaces", "status", "other", []string{"namespaces", "other", "status"}},
|
||||
|
||||
// verb identification
|
||||
{"PATCH", "/api/v1/namespaces/other/pods/foo", "patch", "api", "", "v1", "other", "pods", "", "foo", []string{"pods", "foo"}},
|
||||
{"DELETE", "/api/v1/namespaces/other/pods/foo", "delete", "api", "", "v1", "other", "pods", "", "foo", []string{"pods", "foo"}},
|
||||
{"POST", "/api/v1/namespaces/other/pods", "create", "api", "", "v1", "other", "pods", "", "", []string{"pods"}},
|
||||
|
||||
// deletecollection verb identification
|
||||
{"DELETE", "/api/v1/nodes", "deletecollection", "api", "", "v1", "", "nodes", "", "", []string{"nodes"}},
|
||||
{"DELETE", "/api/v1/namespaces", "deletecollection", "api", "", "v1", "", "namespaces", "", "", []string{"namespaces"}},
|
||||
{"DELETE", "/api/v1/namespaces/other/pods", "deletecollection", "api", "", "v1", "other", "pods", "", "", []string{"pods"}},
|
||||
{"DELETE", "/apis/extensions/v1/namespaces/other/pods", "deletecollection", "api", "extensions", "v1", "other", "pods", "", "", []string{"pods"}},
|
||||
|
||||
// api group identification
|
||||
{"POST", "/apis/extensions/v1/namespaces/other/pods", "create", "api", "extensions", "v1", "other", "pods", "", "", []string{"pods"}},
|
||||
|
||||
// api version identification
|
||||
{"POST", "/apis/extensions/v1beta3/namespaces/other/pods", "create", "api", "extensions", "v1beta3", "other", "pods", "", "", []string{"pods"}},
|
||||
}
|
||||
|
||||
for _, successCase := range successCases {
|
||||
req, _ := http.NewRequest(successCase.method, successCase.url, nil)
|
||||
|
||||
apiRequestInfo := NewRequestInfo(req)
|
||||
if !apiRequestInfo.IsResourceRequest {
|
||||
t.Errorf("Expected resource request")
|
||||
}
|
||||
if successCase.expectedVerb != apiRequestInfo.Verb {
|
||||
t.Errorf("Unexpected verb for url: %s, expected: %s, actual: %s", successCase.url, successCase.expectedVerb, apiRequestInfo.Verb)
|
||||
}
|
||||
if successCase.expectedAPIVersion != apiRequestInfo.APIVersion {
|
||||
t.Errorf("Unexpected apiVersion for url: %s, expected: %s, actual: %s", successCase.url, successCase.expectedAPIVersion, apiRequestInfo.APIVersion)
|
||||
}
|
||||
if successCase.expectedNamespace != apiRequestInfo.Namespace {
|
||||
t.Errorf("Unexpected namespace for url: %s, expected: %s, actual: %s", successCase.url, successCase.expectedNamespace, apiRequestInfo.Namespace)
|
||||
}
|
||||
if successCase.expectedResource != apiRequestInfo.Resource {
|
||||
t.Errorf("Unexpected resource for url: %s, expected: %s, actual: %s", successCase.url, successCase.expectedResource, apiRequestInfo.Resource)
|
||||
}
|
||||
if successCase.expectedSubresource != apiRequestInfo.Subresource {
|
||||
t.Errorf("Unexpected resource for url: %s, expected: %s, actual: %s", successCase.url, successCase.expectedSubresource, apiRequestInfo.Subresource)
|
||||
}
|
||||
if successCase.expectedName != apiRequestInfo.Name {
|
||||
t.Errorf("Unexpected name for url: %s, expected: %s, actual: %s", successCase.url, successCase.expectedName, apiRequestInfo.Name)
|
||||
}
|
||||
if !reflect.DeepEqual(successCase.expectedParts, apiRequestInfo.Parts) {
|
||||
t.Errorf("Unexpected parts for url: %s, expected: %v, actual: %v", successCase.url, successCase.expectedParts, apiRequestInfo.Parts)
|
||||
}
|
||||
}
|
||||
|
||||
errorCases := map[string]string{
|
||||
"no resource path": "/",
|
||||
"just apiversion": "/api/version/",
|
||||
"just prefix, group, version": "/apis/group/version/",
|
||||
"apiversion with no resource": "/api/version/",
|
||||
"bad prefix": "/badprefix/version/resource",
|
||||
"missing api group": "/apis/version/resource",
|
||||
}
|
||||
for k, v := range errorCases {
|
||||
req, err := http.NewRequest("GET", v, nil)
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error %v", err)
|
||||
}
|
||||
apiRequestInfo := NewRequestInfo(req)
|
||||
if apiRequestInfo.IsResourceRequest {
|
||||
t.Errorf("%s: expected non-resource request", k)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// +lifted:source=https://github.com/kubernetes/apiserver/blob/release-1.23/pkg/endpoints/request/requestinfo_test.go#L150-L184
|
||||
// +lifted:changed
|
||||
|
||||
func TestGetNonAPIRequestInfo(t *testing.T) {
|
||||
tests := map[string]struct {
|
||||
url string
|
||||
expected bool
|
||||
}{
|
||||
"simple groupless": {"/api/version/resource", true},
|
||||
"simple group": {"/apis/group/version/resource/name/subresource", true},
|
||||
"more steps": {"/api/version/resource/name/subresource", true},
|
||||
"group list": {"/apis/batch/v1/job", true},
|
||||
"group get": {"/apis/batch/v1/job/foo", true},
|
||||
"group subresource": {"/apis/batch/v1/job/foo/scale", true},
|
||||
|
||||
"bad root": {"/not-api/version/resource", false},
|
||||
"group without enough steps": {"/apis/extensions/v1beta1", false},
|
||||
"group without enough steps 2": {"/apis/extensions/v1beta1/", false},
|
||||
"not enough steps": {"/api/version", false},
|
||||
"one step": {"/api", false},
|
||||
"zero step": {"/", false},
|
||||
"empty": {"", false},
|
||||
}
|
||||
|
||||
for testName, tc := range tests {
|
||||
req, _ := http.NewRequest("GET", tc.url, nil)
|
||||
|
||||
apiRequestInfo := NewRequestInfo(req)
|
||||
if e, a := tc.expected, apiRequestInfo.IsResourceRequest; e != a {
|
||||
t.Errorf("%s: expected %v, actual %v", testName, e, a)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,189 @@
|
|||
/*
|
||||
Copyright 2020 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.
|
||||
*/
|
||||
|
||||
// This code is directly lifted from the kubefed codebase.
|
||||
// For reference:
|
||||
// https://github.com/kubernetes-sigs/kubefed/blob/master/pkg/controller/sync/dispatch/retain_test.go#L91-L292
|
||||
|
||||
package lifted
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/utils/pointer"
|
||||
)
|
||||
|
||||
// +lifted:source=https://github.com/kubernetes-sigs/kubefed/blob/master/pkg/controller/sync/dispatch/retain_test.go#L91-L174
|
||||
// +lifted:changed
|
||||
|
||||
func TestRetainHealthCheckNodePortInServiceFields(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
desiredObj *unstructured.Unstructured
|
||||
clusterObj *unstructured.Unstructured
|
||||
retainSucceed bool
|
||||
expectedValue *int64
|
||||
}{
|
||||
{
|
||||
"cluster object has no healthCheckNodePort",
|
||||
&unstructured.Unstructured{
|
||||
Object: map[string]interface{}{},
|
||||
},
|
||||
&unstructured.Unstructured{
|
||||
Object: map[string]interface{}{},
|
||||
},
|
||||
true,
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"cluster object has invalid healthCheckNodePort",
|
||||
&unstructured.Unstructured{
|
||||
Object: map[string]interface{}{},
|
||||
},
|
||||
&unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"spec": map[string]interface{}{
|
||||
"healthCheckNodePort": "invalid string",
|
||||
},
|
||||
},
|
||||
},
|
||||
false,
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"cluster object has healthCheckNodePort 0",
|
||||
&unstructured.Unstructured{
|
||||
Object: map[string]interface{}{},
|
||||
},
|
||||
&unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"spec": map[string]interface{}{
|
||||
"healthCheckNodePort": int64(0),
|
||||
},
|
||||
},
|
||||
},
|
||||
true,
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"cluster object has healthCheckNodePort 1000",
|
||||
&unstructured.Unstructured{
|
||||
Object: map[string]interface{}{},
|
||||
},
|
||||
&unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"spec": map[string]interface{}{
|
||||
"healthCheckNodePort": int64(1000),
|
||||
},
|
||||
},
|
||||
},
|
||||
true,
|
||||
pointer.Int64Ptr(1000),
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
if _, err := RetainServiceFields(test.desiredObj, test.clusterObj); (err == nil) != test.retainSucceed {
|
||||
t.Fatalf("test %s fails: unexpected returned error %v", test.name, err)
|
||||
}
|
||||
|
||||
currentValue, ok, err := unstructured.NestedInt64(test.desiredObj.Object, "spec", "healthCheckNodePort")
|
||||
if err != nil {
|
||||
t.Fatalf("test %s fails: %v", test.name, err)
|
||||
}
|
||||
if !ok && test.expectedValue != nil {
|
||||
t.Fatalf("test %s fails: expect specified healthCheckNodePort but not found", test.name)
|
||||
}
|
||||
if ok && (test.expectedValue == nil || *test.expectedValue != currentValue) {
|
||||
t.Fatalf("test %s fails: unexpected current healthCheckNodePort %d", test.name, currentValue)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// +lifted:source=https://github.com/kubernetes-sigs/kubefed/blob/master/pkg/controller/sync/dispatch/retain_test.go#L176-L292
|
||||
// +lifted:changed
|
||||
|
||||
func TestRetainClusterIPInServiceFields(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
desiredObj *unstructured.Unstructured
|
||||
clusterObj *unstructured.Unstructured
|
||||
retainSucceed bool
|
||||
expectedClusterIPValue *string
|
||||
}{
|
||||
{
|
||||
"cluster object has no clusterIP",
|
||||
&unstructured.Unstructured{
|
||||
Object: map[string]interface{}{},
|
||||
},
|
||||
&unstructured.Unstructured{
|
||||
Object: map[string]interface{}{},
|
||||
},
|
||||
true,
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"cluster object has invalid clusterIP",
|
||||
&unstructured.Unstructured{
|
||||
Object: map[string]interface{}{},
|
||||
},
|
||||
&unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"spec": map[string]interface{}{
|
||||
"clusterIP": -1000,
|
||||
},
|
||||
},
|
||||
},
|
||||
false,
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"cluster object has valid clusterIP",
|
||||
&unstructured.Unstructured{
|
||||
Object: map[string]interface{}{},
|
||||
},
|
||||
&unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"spec": map[string]interface{}{
|
||||
"clusterIP": "1.2.3.4",
|
||||
},
|
||||
},
|
||||
},
|
||||
true,
|
||||
pointer.String("1.2.3.4"),
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
if _, err := RetainServiceFields(test.desiredObj, test.clusterObj); (err == nil) != test.retainSucceed {
|
||||
t.Fatalf("test %s fails: unexpected returned error %v", test.name, err)
|
||||
}
|
||||
|
||||
currentClusterIPValue, ok, err := unstructured.NestedString(test.desiredObj.Object, "spec", "clusterIP")
|
||||
if err != nil {
|
||||
t.Fatalf("test %s fails: %v", test.name, err)
|
||||
}
|
||||
if !ok && test.expectedClusterIPValue != nil {
|
||||
t.Fatalf("test %s fails: expect specified clusterIP but not found", test.name)
|
||||
}
|
||||
if ok && (test.expectedClusterIPValue == nil || *test.expectedClusterIPValue != currentClusterIPValue) {
|
||||
t.Fatalf("test %s fails: unexpected current clusterIP %s", test.name, currentClusterIPValue)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -0,0 +1,585 @@
|
|||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
// This code is directly lifted from the Kubernetes codebase in order to avoid relying on the k8s.io/kubernetes package.
|
||||
// For reference:
|
||||
// https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/api/v1/pod/util_test.go#L205-L695
|
||||
|
||||
package lifted
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
"k8s.io/component-base/featuregate"
|
||||
)
|
||||
|
||||
const (
|
||||
// Allows running an ephemeral container in pod namespaces to troubleshoot a running pod.
|
||||
EphemeralContainersFeature featuregate.Feature = "EphemeralContainers"
|
||||
)
|
||||
|
||||
func init() {
|
||||
testKubernetesFeatureGates := map[featuregate.Feature]featuregate.FeatureSpec{
|
||||
EphemeralContainersFeature: {Default: true, PreRelease: featuregate.Beta},
|
||||
}
|
||||
runtime.Must(utilfeature.DefaultMutableFeatureGate.Add(testKubernetesFeatureGates))
|
||||
}
|
||||
|
||||
// +lifted:source=https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/api/v1/pod/util.go#L68-L76
|
||||
|
||||
// AllFeatureEnabledContainers returns a ContainerType mask which includes all container
|
||||
// types except for the ones guarded by feature gate.
|
||||
func AllFeatureEnabledContainers() ContainerType {
|
||||
containerType := AllContainers
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(EphemeralContainersFeature) {
|
||||
containerType &= ^EphemeralContainers
|
||||
}
|
||||
return containerType
|
||||
}
|
||||
|
||||
// +lifted:source=https://github.com/kubernetes/kubernetes/blob/release-1.23/staging/src/k8s.io/component-base/featuregate/testing/feature_gate.go#L26-L44
|
||||
|
||||
// SetFeatureGateDuringTest sets the specified gate to the specified value, and returns a function that restores the original value.
|
||||
// Failures to set or restore cause the test to fail.
|
||||
//
|
||||
// Example use:
|
||||
//
|
||||
// defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.<FeatureName>, true)()
|
||||
func SetFeatureGateDuringTest(tb testing.TB, gate featuregate.FeatureGate, f featuregate.Feature, value bool) func() {
|
||||
originalValue := gate.Enabled(f)
|
||||
|
||||
if err := gate.(featuregate.MutableFeatureGate).Set(fmt.Sprintf("%s=%v", f, value)); err != nil {
|
||||
tb.Errorf("error setting %s=%v: %v", f, value, err)
|
||||
}
|
||||
|
||||
return func() {
|
||||
if err := gate.(featuregate.MutableFeatureGate).Set(fmt.Sprintf("%s=%v", f, originalValue)); err != nil {
|
||||
tb.Errorf("error restoring %s=%v: %v", f, originalValue, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// +lifted:source=https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/api/v1/pod/util_test.go#L205-L392
|
||||
// +lifted:changed
|
||||
|
||||
func TestVisitContainers(t *testing.T) {
|
||||
setAllFeatureEnabledContainersDuringTest := ContainerType(0)
|
||||
testCases := []struct {
|
||||
desc string
|
||||
spec *corev1.PodSpec
|
||||
wantContainers []string
|
||||
mask ContainerType
|
||||
ephemeralContainersEnabled bool
|
||||
}{
|
||||
{
|
||||
desc: "empty podspec",
|
||||
spec: &corev1.PodSpec{},
|
||||
wantContainers: []string{},
|
||||
mask: AllContainers,
|
||||
},
|
||||
{
|
||||
desc: "regular containers",
|
||||
spec: &corev1.PodSpec{
|
||||
Containers: []corev1.Container{
|
||||
{Name: "c1"},
|
||||
{Name: "c2"},
|
||||
},
|
||||
InitContainers: []corev1.Container{
|
||||
{Name: "i1"},
|
||||
{Name: "i2"},
|
||||
},
|
||||
EphemeralContainers: []corev1.EphemeralContainer{
|
||||
{EphemeralContainerCommon: corev1.EphemeralContainerCommon{Name: "e1"}},
|
||||
{EphemeralContainerCommon: corev1.EphemeralContainerCommon{Name: "e2"}},
|
||||
},
|
||||
},
|
||||
wantContainers: []string{"c1", "c2"},
|
||||
mask: Containers,
|
||||
},
|
||||
{
|
||||
desc: "init containers",
|
||||
spec: &corev1.PodSpec{
|
||||
Containers: []corev1.Container{
|
||||
{Name: "c1"},
|
||||
{Name: "c2"},
|
||||
},
|
||||
InitContainers: []corev1.Container{
|
||||
{Name: "i1"},
|
||||
{Name: "i2"},
|
||||
},
|
||||
EphemeralContainers: []corev1.EphemeralContainer{
|
||||
{EphemeralContainerCommon: corev1.EphemeralContainerCommon{Name: "e1"}},
|
||||
{EphemeralContainerCommon: corev1.EphemeralContainerCommon{Name: "e2"}},
|
||||
},
|
||||
},
|
||||
wantContainers: []string{"i1", "i2"},
|
||||
mask: InitContainers,
|
||||
},
|
||||
{
|
||||
desc: "ephemeral containers",
|
||||
spec: &corev1.PodSpec{
|
||||
Containers: []corev1.Container{
|
||||
{Name: "c1"},
|
||||
{Name: "c2"},
|
||||
},
|
||||
InitContainers: []corev1.Container{
|
||||
{Name: "i1"},
|
||||
{Name: "i2"},
|
||||
},
|
||||
EphemeralContainers: []corev1.EphemeralContainer{
|
||||
{EphemeralContainerCommon: corev1.EphemeralContainerCommon{Name: "e1"}},
|
||||
{EphemeralContainerCommon: corev1.EphemeralContainerCommon{Name: "e2"}},
|
||||
},
|
||||
},
|
||||
wantContainers: []string{"e1", "e2"},
|
||||
mask: EphemeralContainers,
|
||||
},
|
||||
{
|
||||
desc: "all container types",
|
||||
spec: &corev1.PodSpec{
|
||||
Containers: []corev1.Container{
|
||||
{Name: "c1"},
|
||||
{Name: "c2"},
|
||||
},
|
||||
InitContainers: []corev1.Container{
|
||||
{Name: "i1"},
|
||||
{Name: "i2"},
|
||||
},
|
||||
EphemeralContainers: []corev1.EphemeralContainer{
|
||||
{EphemeralContainerCommon: corev1.EphemeralContainerCommon{Name: "e1"}},
|
||||
{EphemeralContainerCommon: corev1.EphemeralContainerCommon{Name: "e2"}},
|
||||
},
|
||||
},
|
||||
wantContainers: []string{"i1", "i2", "c1", "c2", "e1", "e2"},
|
||||
mask: AllContainers,
|
||||
},
|
||||
{
|
||||
desc: "all feature enabled container types with ephemeral containers disabled",
|
||||
spec: &corev1.PodSpec{
|
||||
Containers: []corev1.Container{
|
||||
{Name: "c1"},
|
||||
{Name: "c2"},
|
||||
},
|
||||
InitContainers: []corev1.Container{
|
||||
{Name: "i1"},
|
||||
{Name: "i2"},
|
||||
},
|
||||
EphemeralContainers: []corev1.EphemeralContainer{
|
||||
{EphemeralContainerCommon: corev1.EphemeralContainerCommon{Name: "e1"}},
|
||||
{EphemeralContainerCommon: corev1.EphemeralContainerCommon{Name: "e2"}},
|
||||
},
|
||||
},
|
||||
wantContainers: []string{"i1", "i2", "c1", "c2"},
|
||||
mask: setAllFeatureEnabledContainersDuringTest,
|
||||
},
|
||||
{
|
||||
desc: "all feature enabled container types with ephemeral containers enabled",
|
||||
spec: &corev1.PodSpec{
|
||||
Containers: []corev1.Container{
|
||||
{Name: "c1"},
|
||||
{Name: "c2", SecurityContext: &corev1.SecurityContext{}},
|
||||
},
|
||||
InitContainers: []corev1.Container{
|
||||
{Name: "i1"},
|
||||
{Name: "i2", SecurityContext: &corev1.SecurityContext{}},
|
||||
},
|
||||
EphemeralContainers: []corev1.EphemeralContainer{
|
||||
{EphemeralContainerCommon: corev1.EphemeralContainerCommon{Name: "e1"}},
|
||||
{EphemeralContainerCommon: corev1.EphemeralContainerCommon{Name: "e2"}},
|
||||
},
|
||||
},
|
||||
wantContainers: []string{"i1", "i2", "c1", "c2", "e1", "e2"},
|
||||
mask: setAllFeatureEnabledContainersDuringTest,
|
||||
ephemeralContainersEnabled: true,
|
||||
},
|
||||
{
|
||||
desc: "dropping fields",
|
||||
spec: &corev1.PodSpec{
|
||||
Containers: []corev1.Container{
|
||||
{Name: "c1"},
|
||||
{Name: "c2", SecurityContext: &corev1.SecurityContext{}},
|
||||
},
|
||||
InitContainers: []corev1.Container{
|
||||
{Name: "i1"},
|
||||
{Name: "i2", SecurityContext: &corev1.SecurityContext{}},
|
||||
},
|
||||
EphemeralContainers: []corev1.EphemeralContainer{
|
||||
{EphemeralContainerCommon: corev1.EphemeralContainerCommon{Name: "e1"}},
|
||||
{EphemeralContainerCommon: corev1.EphemeralContainerCommon{Name: "e2", SecurityContext: &corev1.SecurityContext{}}},
|
||||
},
|
||||
},
|
||||
wantContainers: []string{"i1", "i2", "c1", "c2", "e1", "e2"},
|
||||
mask: AllContainers,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
defer SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, EphemeralContainersFeature, tc.ephemeralContainersEnabled)()
|
||||
|
||||
if tc.mask == setAllFeatureEnabledContainersDuringTest {
|
||||
tc.mask = AllFeatureEnabledContainers()
|
||||
}
|
||||
|
||||
gotContainers := []string{}
|
||||
VisitContainers(tc.spec, tc.mask, func(c *corev1.Container, containerType ContainerType) bool {
|
||||
gotContainers = append(gotContainers, c.Name)
|
||||
if c.SecurityContext != nil {
|
||||
c.SecurityContext = nil
|
||||
}
|
||||
return true
|
||||
})
|
||||
if !cmp.Equal(gotContainers, tc.wantContainers) {
|
||||
t.Errorf("VisitContainers() = %+v, want %+v", gotContainers, tc.wantContainers)
|
||||
}
|
||||
for _, c := range tc.spec.Containers {
|
||||
if c.SecurityContext != nil {
|
||||
t.Errorf("VisitContainers() did not drop SecurityContext for container %q", c.Name)
|
||||
}
|
||||
}
|
||||
for _, c := range tc.spec.InitContainers {
|
||||
if c.SecurityContext != nil {
|
||||
t.Errorf("VisitContainers() did not drop SecurityContext for init container %q", c.Name)
|
||||
}
|
||||
}
|
||||
for _, c := range tc.spec.EphemeralContainers {
|
||||
if c.SecurityContext != nil {
|
||||
t.Errorf("VisitContainers() did not drop SecurityContext for ephemeral container %q", c.Name)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// +lifted:source=https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/api/v1/pod/util_test.go#L394-L551
|
||||
// +lifted:changed
|
||||
|
||||
func TestPodSecrets(t *testing.T) {
|
||||
defer SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, EphemeralContainersFeature, true)()
|
||||
|
||||
// Stub containing all possible secret references in a pod.
|
||||
// The names of the referenced secrets match struct paths detected by reflection.
|
||||
pod := &corev1.Pod{
|
||||
Spec: corev1.PodSpec{
|
||||
Containers: []corev1.Container{{
|
||||
EnvFrom: []corev1.EnvFromSource{{
|
||||
SecretRef: &corev1.SecretEnvSource{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "Spec.Containers[*].EnvFrom[*].SecretRef"}}}},
|
||||
Env: []corev1.EnvVar{{
|
||||
ValueFrom: &corev1.EnvVarSource{
|
||||
SecretKeyRef: &corev1.SecretKeySelector{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "Spec.Containers[*].Env[*].ValueFrom.SecretKeyRef"}}}}}}},
|
||||
ImagePullSecrets: []corev1.LocalObjectReference{{
|
||||
Name: "Spec.ImagePullSecrets"}},
|
||||
InitContainers: []corev1.Container{{
|
||||
EnvFrom: []corev1.EnvFromSource{{
|
||||
SecretRef: &corev1.SecretEnvSource{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "Spec.InitContainers[*].EnvFrom[*].SecretRef"}}}},
|
||||
Env: []corev1.EnvVar{{
|
||||
ValueFrom: &corev1.EnvVarSource{
|
||||
SecretKeyRef: &corev1.SecretKeySelector{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "Spec.InitContainers[*].Env[*].ValueFrom.SecretKeyRef"}}}}}}},
|
||||
Volumes: []corev1.Volume{{
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
AzureFile: &corev1.AzureFileVolumeSource{
|
||||
SecretName: "Spec.Volumes[*].VolumeSource.AzureFile.SecretName"}}}, {
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
CephFS: &corev1.CephFSVolumeSource{
|
||||
SecretRef: &corev1.LocalObjectReference{
|
||||
Name: "Spec.Volumes[*].VolumeSource.CephFS.SecretRef"}}}}, {
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
Cinder: &corev1.CinderVolumeSource{
|
||||
SecretRef: &corev1.LocalObjectReference{
|
||||
Name: "Spec.Volumes[*].VolumeSource.Cinder.SecretRef"}}}}, {
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
FlexVolume: &corev1.FlexVolumeSource{
|
||||
SecretRef: &corev1.LocalObjectReference{
|
||||
Name: "Spec.Volumes[*].VolumeSource.FlexVolume.SecretRef"}}}}, {
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
Projected: &corev1.ProjectedVolumeSource{
|
||||
Sources: []corev1.VolumeProjection{{
|
||||
Secret: &corev1.SecretProjection{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "Spec.Volumes[*].VolumeSource.Projected.Sources[*].Secret"}}}}}}}, {
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
RBD: &corev1.RBDVolumeSource{
|
||||
SecretRef: &corev1.LocalObjectReference{
|
||||
Name: "Spec.Volumes[*].VolumeSource.RBD.SecretRef"}}}}, {
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
Secret: &corev1.SecretVolumeSource{
|
||||
SecretName: "Spec.Volumes[*].VolumeSource.Secret.SecretName"}}}, {
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
Secret: &corev1.SecretVolumeSource{
|
||||
SecretName: "Spec.Volumes[*].VolumeSource.Secret"}}}, {
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
ScaleIO: &corev1.ScaleIOVolumeSource{
|
||||
SecretRef: &corev1.LocalObjectReference{
|
||||
Name: "Spec.Volumes[*].VolumeSource.ScaleIO.SecretRef"}}}}, {
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
ISCSI: &corev1.ISCSIVolumeSource{
|
||||
SecretRef: &corev1.LocalObjectReference{
|
||||
Name: "Spec.Volumes[*].VolumeSource.ISCSI.SecretRef"}}}}, {
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
StorageOS: &corev1.StorageOSVolumeSource{
|
||||
SecretRef: &corev1.LocalObjectReference{
|
||||
Name: "Spec.Volumes[*].VolumeSource.StorageOS.SecretRef"}}}}, {
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
CSI: &corev1.CSIVolumeSource{
|
||||
NodePublishSecretRef: &corev1.LocalObjectReference{
|
||||
Name: "Spec.Volumes[*].VolumeSource.CSI.NodePublishSecretRef"}}}}},
|
||||
EphemeralContainers: []corev1.EphemeralContainer{{
|
||||
EphemeralContainerCommon: corev1.EphemeralContainerCommon{
|
||||
EnvFrom: []corev1.EnvFromSource{{
|
||||
SecretRef: &corev1.SecretEnvSource{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "Spec.EphemeralContainers[*].EphemeralContainerCommon.EnvFrom[*].SecretRef"}}}},
|
||||
Env: []corev1.EnvVar{{
|
||||
ValueFrom: &corev1.EnvVarSource{
|
||||
SecretKeyRef: &corev1.SecretKeySelector{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "Spec.EphemeralContainers[*].EphemeralContainerCommon.Env[*].ValueFrom.SecretKeyRef"}}}}}}}},
|
||||
},
|
||||
}
|
||||
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.EphemeralContainers[*].EphemeralContainerCommon.EnvFrom[*].SecretRef",
|
||||
"Spec.EphemeralContainers[*].EphemeralContainerCommon.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",
|
||||
"Spec.Volumes[*].VolumeSource.CSI.NodePublishSecretRef",
|
||||
)
|
||||
secretPaths := collectResourcePaths(t, "secret", nil, "", reflect.TypeOf(&corev1.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")
|
||||
}
|
||||
|
||||
// emptyPod is a stub containing empty object names
|
||||
emptyPod := &corev1.Pod{
|
||||
Spec: corev1.PodSpec{
|
||||
Containers: []corev1.Container{{
|
||||
EnvFrom: []corev1.EnvFromSource{{
|
||||
SecretRef: &corev1.SecretEnvSource{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: ""}}}}}},
|
||||
},
|
||||
}
|
||||
VisitPodSecretNames(emptyPod, func(name string) bool {
|
||||
t.Fatalf("expected no empty names collected, got %q", name)
|
||||
return false
|
||||
})
|
||||
}
|
||||
|
||||
// +lifted:source=https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/api/v1/pod/util_test.go#L553-L591
|
||||
|
||||
// collectResourcePaths traverses the object, computing all the struct paths that lead to fields with resourcename in the name.
|
||||
func collectResourcePaths(t *testing.T, resourcename string, path *field.Path, name string, tp reflect.Type) sets.String {
|
||||
resourcename = strings.ToLower(resourcename)
|
||||
resourcePaths := sets.NewString()
|
||||
|
||||
if tp.Kind() == reflect.Pointer {
|
||||
resourcePaths.Insert(collectResourcePaths(t, resourcename, path, name, tp.Elem()).List()...)
|
||||
return resourcePaths
|
||||
}
|
||||
|
||||
if strings.Contains(strings.ToLower(name), resourcename) {
|
||||
resourcePaths.Insert(path.String())
|
||||
}
|
||||
|
||||
switch tp.Kind() {
|
||||
case reflect.Pointer:
|
||||
resourcePaths.Insert(collectResourcePaths(t, resourcename, path, name, tp.Elem()).List()...)
|
||||
case reflect.Struct:
|
||||
// ObjectMeta is generic and therefore should never have a field with a specific resource's name;
|
||||
// it contains cycles so it's easiest to just skip it.
|
||||
if name == "ObjectMeta" {
|
||||
break
|
||||
}
|
||||
for i := 0; i < tp.NumField(); i++ {
|
||||
field := tp.Field(i)
|
||||
resourcePaths.Insert(collectResourcePaths(t, resourcename, path.Child(field.Name), field.Name, field.Type).List()...)
|
||||
}
|
||||
case reflect.Interface:
|
||||
t.Errorf("cannot find %s fields in interface{} field %s", resourcename, path.String())
|
||||
case reflect.Map:
|
||||
resourcePaths.Insert(collectResourcePaths(t, resourcename, path.Key("*"), "", tp.Elem()).List()...)
|
||||
case reflect.Slice:
|
||||
resourcePaths.Insert(collectResourcePaths(t, resourcename, path.Key("*"), "", tp.Elem()).List()...)
|
||||
default:
|
||||
// all primitive types
|
||||
}
|
||||
|
||||
return resourcePaths
|
||||
}
|
||||
|
||||
// +lifted:source=https://github.com/kubernetes/kubernetes/blob/release-1.23/pkg/api/v1/pod/util_test.go#L593-L695
|
||||
// +lifted:changed
|
||||
|
||||
func TestPodConfigmaps(t *testing.T) {
|
||||
defer SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, EphemeralContainersFeature, true)()
|
||||
|
||||
// Stub containing all possible ConfigMap references in a pod.
|
||||
// The names of the referenced ConfigMaps match struct paths detected by reflection.
|
||||
pod := &corev1.Pod{
|
||||
Spec: corev1.PodSpec{
|
||||
Containers: []corev1.Container{{
|
||||
EnvFrom: []corev1.EnvFromSource{{
|
||||
ConfigMapRef: &corev1.ConfigMapEnvSource{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "Spec.Containers[*].EnvFrom[*].ConfigMapRef"}}}},
|
||||
Env: []corev1.EnvVar{{
|
||||
ValueFrom: &corev1.EnvVarSource{
|
||||
ConfigMapKeyRef: &corev1.ConfigMapKeySelector{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "Spec.Containers[*].Env[*].ValueFrom.ConfigMapKeyRef"}}}}}}},
|
||||
EphemeralContainers: []corev1.EphemeralContainer{{
|
||||
EphemeralContainerCommon: corev1.EphemeralContainerCommon{
|
||||
EnvFrom: []corev1.EnvFromSource{{
|
||||
ConfigMapRef: &corev1.ConfigMapEnvSource{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "Spec.EphemeralContainers[*].EphemeralContainerCommon.EnvFrom[*].ConfigMapRef"}}}},
|
||||
Env: []corev1.EnvVar{{
|
||||
ValueFrom: &corev1.EnvVarSource{
|
||||
ConfigMapKeyRef: &corev1.ConfigMapKeySelector{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "Spec.EphemeralContainers[*].EphemeralContainerCommon.Env[*].ValueFrom.ConfigMapKeyRef"}}}}}}}},
|
||||
InitContainers: []corev1.Container{{
|
||||
EnvFrom: []corev1.EnvFromSource{{
|
||||
ConfigMapRef: &corev1.ConfigMapEnvSource{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "Spec.InitContainers[*].EnvFrom[*].ConfigMapRef"}}}},
|
||||
Env: []corev1.EnvVar{{
|
||||
ValueFrom: &corev1.EnvVarSource{
|
||||
ConfigMapKeyRef: &corev1.ConfigMapKeySelector{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "Spec.InitContainers[*].Env[*].ValueFrom.ConfigMapKeyRef"}}}}}}},
|
||||
Volumes: []corev1.Volume{{
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
Projected: &corev1.ProjectedVolumeSource{
|
||||
Sources: []corev1.VolumeProjection{{
|
||||
ConfigMap: &corev1.ConfigMapProjection{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "Spec.Volumes[*].VolumeSource.Projected.Sources[*].ConfigMap"}}}}}}}, {
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
ConfigMap: &corev1.ConfigMapVolumeSource{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "Spec.Volumes[*].VolumeSource.ConfigMap"}}}}},
|
||||
},
|
||||
}
|
||||
extractedNames := sets.NewString()
|
||||
VisitPodConfigmapNames(pod, func(name string) bool {
|
||||
extractedNames.Insert(name)
|
||||
return true
|
||||
})
|
||||
|
||||
// expectedPaths holds struct paths to fields with "ConfigMap" in the name that are references to ConfigMap API objects.
|
||||
// every path here should be represented as an example in the Pod stub above, with the ConfigMap name set to the path.
|
||||
expectedPaths := sets.NewString(
|
||||
"Spec.Containers[*].EnvFrom[*].ConfigMapRef",
|
||||
"Spec.Containers[*].Env[*].ValueFrom.ConfigMapKeyRef",
|
||||
"Spec.EphemeralContainers[*].EphemeralContainerCommon.EnvFrom[*].ConfigMapRef",
|
||||
"Spec.EphemeralContainers[*].EphemeralContainerCommon.Env[*].ValueFrom.ConfigMapKeyRef",
|
||||
"Spec.InitContainers[*].EnvFrom[*].ConfigMapRef",
|
||||
"Spec.InitContainers[*].Env[*].ValueFrom.ConfigMapKeyRef",
|
||||
"Spec.Volumes[*].VolumeSource.Projected.Sources[*].ConfigMap",
|
||||
"Spec.Volumes[*].VolumeSource.ConfigMap",
|
||||
)
|
||||
collectPaths := collectResourcePaths(t, "ConfigMap", nil, "", reflect.TypeOf(&corev1.Pod{}))
|
||||
if missingPaths := expectedPaths.Difference(collectPaths); len(missingPaths) > 0 {
|
||||
t.Logf("Missing expected paths:\n%s", strings.Join(missingPaths.List(), "\n"))
|
||||
t.Error("Missing expected paths. Verify VisitPodConfigmapNames() is correctly finding the missing paths, then correct expectedPaths")
|
||||
}
|
||||
if extraPaths := collectPaths.Difference(expectedPaths); len(extraPaths) > 0 {
|
||||
t.Logf("Extra paths:\n%s", strings.Join(extraPaths.List(), "\n"))
|
||||
t.Error("Extra fields with resource in the name found. Verify VisitPodConfigmapNames() is including these fields if appropriate, then correct expectedPaths")
|
||||
}
|
||||
|
||||
if missingNames := expectedPaths.Difference(extractedNames); len(missingNames) > 0 {
|
||||
t.Logf("Missing expected names:\n%s", strings.Join(missingNames.List(), "\n"))
|
||||
t.Error("Missing expected names. Verify the pod stub above includes these references, then verify VisitPodConfigmapNames() is correctly finding the missing names")
|
||||
}
|
||||
if extraNames := extractedNames.Difference(expectedPaths); len(extraNames) > 0 {
|
||||
t.Logf("Extra names:\n%s", strings.Join(extraNames.List(), "\n"))
|
||||
t.Error("Extra names extracted. Verify VisitPodConfigmapNames() is correctly extracting resource names")
|
||||
}
|
||||
|
||||
// emptyPod is a stub containing empty object names
|
||||
emptyPod := &corev1.Pod{
|
||||
Spec: corev1.PodSpec{
|
||||
Containers: []corev1.Container{{
|
||||
EnvFrom: []corev1.EnvFromSource{{
|
||||
ConfigMapRef: &corev1.ConfigMapEnvSource{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: ""}}}}}},
|
||||
},
|
||||
}
|
||||
VisitPodConfigmapNames(emptyPod, func(name string) bool {
|
||||
t.Fatalf("expected no empty names collected, got %q", name)
|
||||
return false
|
||||
})
|
||||
}
|
Loading…
Reference in New Issue