Add a function getPodDependencies for InterpretDependency operation
Signed-off-by: yike21 <yike21@qq.com>
This commit is contained in:
parent
c62cc2b055
commit
9acd98faec
|
@ -28,6 +28,9 @@ const (
|
|||
// - function accuratePodRequirements(pod) requirements
|
||||
// accurate total resource requirements for pod. Example:
|
||||
// requirements = kube.accuratePodRequirements(pod)
|
||||
// - function getPodDependencies(podTemplate, namespace) dependencies
|
||||
// get total dependencies from podTemplate and namespace. Example:
|
||||
// dependencies = kube.getPodDependencies(podTemplate, namespace)
|
||||
func KubeLoader(ls *lua.LState) int {
|
||||
mod := ls.SetFuncs(ls.NewTable(), kubeFuncs)
|
||||
ls.Push(mod)
|
||||
|
@ -37,6 +40,7 @@ func KubeLoader(ls *lua.LState) int {
|
|||
var kubeFuncs = map[string]lua.LGFunction{
|
||||
"resourceAdd": resourceAdd,
|
||||
"accuratePodRequirements": accuratePodRequirements,
|
||||
"getPodDependencies": getPodDependencies,
|
||||
}
|
||||
|
||||
func resourceAdd(ls *lua.LState) int {
|
||||
|
@ -78,6 +82,35 @@ func accuratePodRequirements(ls *lua.LState) int {
|
|||
return 1
|
||||
}
|
||||
|
||||
func getPodDependencies(ls *lua.LState) int {
|
||||
n := ls.GetTop()
|
||||
if n != 2 {
|
||||
ls.RaiseError("getPodDependencies only accepts two argument")
|
||||
return 0
|
||||
}
|
||||
|
||||
podTemplate := ls.CheckTable(1)
|
||||
namespace := checkNamespace(ls, 2)
|
||||
|
||||
template := &corev1.PodTemplateSpec{}
|
||||
err := ConvertLuaResultInto(podTemplate, template)
|
||||
if err != nil {
|
||||
ls.RaiseError("fail to convert lua value %#v to corev1.PodTemplateSpec: %v", podTemplate, err)
|
||||
return 0
|
||||
}
|
||||
|
||||
pod := helper.GeneratePodFromTemplateAndNamespace(template, namespace)
|
||||
dependencies, _ := helper.GetDependenciesFromPodTemplate(pod)
|
||||
retValue, err := decodeValue(ls, dependencies)
|
||||
if err != nil {
|
||||
ls.RaiseError("fail to convert %#v to Lua value: %v", dependencies, err)
|
||||
return 0
|
||||
}
|
||||
|
||||
ls.Push(retValue)
|
||||
return 1
|
||||
}
|
||||
|
||||
func checkResourceQuantity(ls *lua.LState, n int) resource.Quantity {
|
||||
v := ls.Get(n)
|
||||
switch typ := v.Type(); typ {
|
||||
|
@ -91,3 +124,16 @@ func checkResourceQuantity(ls *lua.LState, n int) resource.Quantity {
|
|||
return resource.Quantity{}
|
||||
}
|
||||
}
|
||||
|
||||
func checkNamespace(ls *lua.LState, n int) string {
|
||||
v := ls.Get(n)
|
||||
switch typ := v.Type(); typ {
|
||||
case lua.LTNil:
|
||||
return "default"
|
||||
case lua.LTString, lua.LTNumber:
|
||||
return ls.CheckString(n)
|
||||
default:
|
||||
ls.TypeError(n, lua.LTString)
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
|
|
@ -496,7 +496,7 @@ func TestStatusReflection(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestGetDeployPodDependencies(t *testing.T) {
|
||||
newDeploy := appsv1.Deployment{
|
||||
newDeploy1 := appsv1.Deployment{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
APIVersion: "v1",
|
||||
Kind: "Deployment",
|
||||
|
@ -513,14 +513,24 @@ func TestGetDeployPodDependencies(t *testing.T) {
|
|||
},
|
||||
},
|
||||
}
|
||||
newObj, _ := helper.ToUnstructured(&newDeploy)
|
||||
expect := make([]configv1alpha1.DependentObjectReference, 1)
|
||||
expect[0] = configv1alpha1.DependentObjectReference{
|
||||
newDeploy2 := newDeploy1.DeepCopy()
|
||||
newDeploy2.Namespace = ""
|
||||
newObj1, _ := helper.ToUnstructured(&newDeploy1)
|
||||
expect1 := make([]configv1alpha1.DependentObjectReference, 1)
|
||||
expect1[0] = configv1alpha1.DependentObjectReference{
|
||||
APIVersion: "v1",
|
||||
Kind: "ServiceAccount",
|
||||
Namespace: "test",
|
||||
Name: "test",
|
||||
}
|
||||
newObj2, _ := helper.ToUnstructured(&newDeploy2)
|
||||
expect2 := make([]configv1alpha1.DependentObjectReference, 1)
|
||||
expect2[0] = configv1alpha1.DependentObjectReference{
|
||||
APIVersion: "v1",
|
||||
Kind: "ServiceAccount",
|
||||
Namespace: "default",
|
||||
Name: "test",
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
curObj *unstructured.Unstructured
|
||||
|
@ -529,7 +539,7 @@ func TestGetDeployPodDependencies(t *testing.T) {
|
|||
}{
|
||||
{
|
||||
name: "Get GetDeployPodDependencies",
|
||||
curObj: newObj,
|
||||
curObj: newObj1,
|
||||
luaScript: `function GetDependencies(desiredObj)
|
||||
dependentSas = {}
|
||||
refs = {}
|
||||
|
@ -549,7 +559,27 @@ func TestGetDeployPodDependencies(t *testing.T) {
|
|||
end
|
||||
return refs
|
||||
end`,
|
||||
want: expect,
|
||||
want: expect1,
|
||||
},
|
||||
{
|
||||
name: "Test getPodDependencies",
|
||||
curObj: newObj1,
|
||||
luaScript: `local kube = require("kube")
|
||||
function GetDependencies(desiredObj)
|
||||
dependencies = kube.getPodDependencies(desiredObj.spec.template, desiredObj.metadata.namespace)
|
||||
return dependencies
|
||||
end`,
|
||||
want: expect1,
|
||||
},
|
||||
{
|
||||
name: "Test getPodDependencies when desiredObj's namespace is empty",
|
||||
curObj: newObj2,
|
||||
luaScript: `local kube = require("kube")
|
||||
function GetDependencies(desiredObj)
|
||||
dependencies = kube.getPodDependencies(desiredObj.spec.template, desiredObj.metadata.namespace)
|
||||
return dependencies
|
||||
end`,
|
||||
want: expect2,
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@ import (
|
|||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
|
||||
configv1alpha1 "github.com/karmada-io/karmada/pkg/apis/config/v1alpha1"
|
||||
"github.com/karmada-io/karmada/pkg/util"
|
||||
|
@ -40,7 +39,7 @@ func getDeploymentDependencies(object *unstructured.Unstructured) ([]configv1alp
|
|||
return nil, err
|
||||
}
|
||||
|
||||
return getDependenciesFromPodTemplate(podObj)
|
||||
return helper.GetDependenciesFromPodTemplate(podObj)
|
||||
}
|
||||
|
||||
func getJobDependencies(object *unstructured.Unstructured) ([]configv1alpha1.DependentObjectReference, error) {
|
||||
|
@ -55,7 +54,7 @@ func getJobDependencies(object *unstructured.Unstructured) ([]configv1alpha1.Dep
|
|||
return nil, err
|
||||
}
|
||||
|
||||
return getDependenciesFromPodTemplate(podObj)
|
||||
return helper.GetDependenciesFromPodTemplate(podObj)
|
||||
}
|
||||
|
||||
func getCronJobDependencies(object *unstructured.Unstructured) ([]configv1alpha1.DependentObjectReference, error) {
|
||||
|
@ -70,7 +69,7 @@ func getCronJobDependencies(object *unstructured.Unstructured) ([]configv1alpha1
|
|||
return nil, err
|
||||
}
|
||||
|
||||
return getDependenciesFromPodTemplate(podObj)
|
||||
return helper.GetDependenciesFromPodTemplate(podObj)
|
||||
}
|
||||
|
||||
func getPodDependencies(object *unstructured.Unstructured) ([]configv1alpha1.DependentObjectReference, error) {
|
||||
|
@ -80,7 +79,7 @@ func getPodDependencies(object *unstructured.Unstructured) ([]configv1alpha1.Dep
|
|||
return nil, fmt.Errorf("failed to convert Pod from unstructured object: %v", err)
|
||||
}
|
||||
|
||||
return getDependenciesFromPodTemplate(podObj)
|
||||
return helper.GetDependenciesFromPodTemplate(podObj)
|
||||
}
|
||||
|
||||
func getDaemonSetDependencies(object *unstructured.Unstructured) ([]configv1alpha1.DependentObjectReference, error) {
|
||||
|
@ -95,7 +94,7 @@ func getDaemonSetDependencies(object *unstructured.Unstructured) ([]configv1alph
|
|||
return nil, err
|
||||
}
|
||||
|
||||
return getDependenciesFromPodTemplate(podObj)
|
||||
return helper.GetDependenciesFromPodTemplate(podObj)
|
||||
}
|
||||
|
||||
func getStatefulSetDependencies(object *unstructured.Unstructured) ([]configv1alpha1.DependentObjectReference, error) {
|
||||
|
@ -110,89 +109,5 @@ func getStatefulSetDependencies(object *unstructured.Unstructured) ([]configv1al
|
|||
return nil, err
|
||||
}
|
||||
|
||||
return getDependenciesFromPodTemplate(podObj)
|
||||
}
|
||||
|
||||
func getDependenciesFromPodTemplate(podObj *corev1.Pod) ([]configv1alpha1.DependentObjectReference, error) {
|
||||
dependentConfigMaps := getConfigMapNames(podObj)
|
||||
dependentSecrets := getSecretNames(podObj)
|
||||
dependentSas := getServiceAccountNames(podObj)
|
||||
dependentPVCs := getPVCNames(podObj)
|
||||
var dependentObjectRefs []configv1alpha1.DependentObjectReference
|
||||
for cm := range dependentConfigMaps {
|
||||
dependentObjectRefs = append(dependentObjectRefs, configv1alpha1.DependentObjectReference{
|
||||
APIVersion: "v1",
|
||||
Kind: "ConfigMap",
|
||||
Namespace: podObj.Namespace,
|
||||
Name: cm,
|
||||
})
|
||||
}
|
||||
|
||||
for secret := range dependentSecrets {
|
||||
dependentObjectRefs = append(dependentObjectRefs, configv1alpha1.DependentObjectReference{
|
||||
APIVersion: "v1",
|
||||
Kind: "Secret",
|
||||
Namespace: podObj.Namespace,
|
||||
Name: secret,
|
||||
})
|
||||
}
|
||||
for sa := range dependentSas {
|
||||
dependentObjectRefs = append(dependentObjectRefs, configv1alpha1.DependentObjectReference{
|
||||
APIVersion: "v1",
|
||||
Kind: "ServiceAccount",
|
||||
Namespace: podObj.Namespace,
|
||||
Name: sa,
|
||||
})
|
||||
}
|
||||
|
||||
for pvc := range dependentPVCs {
|
||||
dependentObjectRefs = append(dependentObjectRefs, configv1alpha1.DependentObjectReference{
|
||||
APIVersion: "v1",
|
||||
Kind: "PersistentVolumeClaim",
|
||||
Namespace: podObj.Namespace,
|
||||
Name: pvc,
|
||||
})
|
||||
}
|
||||
|
||||
return dependentObjectRefs, nil
|
||||
}
|
||||
|
||||
func getSecretNames(pod *corev1.Pod) sets.Set[string] {
|
||||
result := sets.New[string]()
|
||||
lifted.VisitPodSecretNames(pod, func(name string) bool {
|
||||
result.Insert(name)
|
||||
return true
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
func getServiceAccountNames(pod *corev1.Pod) sets.Set[string] {
|
||||
result := sets.New[string]()
|
||||
if pod.Spec.ServiceAccountName != "" && pod.Spec.ServiceAccountName != "default" {
|
||||
result.Insert(pod.Spec.ServiceAccountName)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func getConfigMapNames(pod *corev1.Pod) sets.Set[string] {
|
||||
result := sets.New[string]()
|
||||
lifted.VisitPodConfigmapNames(pod, func(name string) bool {
|
||||
result.Insert(name)
|
||||
return true
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
func getPVCNames(pod *corev1.Pod) sets.Set[string] {
|
||||
result := sets.New[string]()
|
||||
for i := range pod.Spec.Volumes {
|
||||
volume := pod.Spec.Volumes[i]
|
||||
if volume.PersistentVolumeClaim != nil {
|
||||
claimName := volume.PersistentVolumeClaim.ClaimName
|
||||
if len(claimName) != 0 {
|
||||
result.Insert(claimName)
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
return helper.GetDependenciesFromPodTemplate(podObj)
|
||||
}
|
||||
|
|
|
@ -1,545 +1 @@
|
|||
package native
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
|
||||
configv1alpha1 "github.com/karmada-io/karmada/pkg/apis/config/v1alpha1"
|
||||
"github.com/karmada-io/karmada/test/helper"
|
||||
)
|
||||
|
||||
var (
|
||||
namespace = "karmada-test"
|
||||
podName = "fake-pod"
|
||||
)
|
||||
|
||||
func TestGetSecretNames(t *testing.T) {
|
||||
emptySecretsPod := helper.NewPod(namespace, podName)
|
||||
|
||||
secretsPod := helper.NewPod(namespace, podName)
|
||||
secretsPod.Spec.ImagePullSecrets = []corev1.LocalObjectReference{
|
||||
{
|
||||
Name: "image-secret",
|
||||
},
|
||||
}
|
||||
secretsPod.Spec.InitContainers = []corev1.Container{
|
||||
{
|
||||
EnvFrom: []corev1.EnvFromSource{
|
||||
{
|
||||
SecretRef: &corev1.SecretEnvSource{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "initcontainer-envfrom-secret",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Env: []corev1.EnvVar{
|
||||
{
|
||||
ValueFrom: &corev1.EnvVarSource{
|
||||
SecretKeyRef: &corev1.SecretKeySelector{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "initcontainer-env-secret",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
secretsPod.Spec.Containers = []corev1.Container{
|
||||
{
|
||||
EnvFrom: []corev1.EnvFromSource{
|
||||
{
|
||||
SecretRef: &corev1.SecretEnvSource{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "container-envfrom-secret",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Env: []corev1.EnvVar{
|
||||
{
|
||||
ValueFrom: &corev1.EnvVarSource{
|
||||
SecretKeyRef: &corev1.SecretKeySelector{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "container-env-secret",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
secretsPod.Spec.EphemeralContainers = []corev1.EphemeralContainer{
|
||||
{
|
||||
EphemeralContainerCommon: corev1.EphemeralContainerCommon{
|
||||
EnvFrom: []corev1.EnvFromSource{
|
||||
{
|
||||
SecretRef: &corev1.SecretEnvSource{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "ephemeralcontainer-envfrom-secret",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Env: []corev1.EnvVar{
|
||||
{
|
||||
ValueFrom: &corev1.EnvVarSource{
|
||||
SecretKeyRef: &corev1.SecretKeySelector{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "ephemeralcontainer-env-secret",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
secretsPod.Spec.Volumes = []corev1.Volume{
|
||||
{
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
AzureFile: &corev1.AzureFileVolumeSource{
|
||||
SecretName: "azure-secret",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
CephFS: &corev1.CephFSVolumeSource{
|
||||
SecretRef: &corev1.LocalObjectReference{
|
||||
Name: "cephfs-secret",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
Cinder: &corev1.CinderVolumeSource{
|
||||
SecretRef: &corev1.LocalObjectReference{
|
||||
Name: "cinder-secret",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
FlexVolume: &corev1.FlexVolumeSource{
|
||||
SecretRef: &corev1.LocalObjectReference{
|
||||
Name: "flex-secret",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
Projected: &corev1.ProjectedVolumeSource{
|
||||
Sources: []corev1.VolumeProjection{
|
||||
{
|
||||
Secret: &corev1.SecretProjection{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "projected-secret",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
RBD: &corev1.RBDVolumeSource{
|
||||
SecretRef: &corev1.LocalObjectReference{
|
||||
Name: "rbd-secret",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
Secret: &corev1.SecretVolumeSource{
|
||||
SecretName: "secret-config",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
ScaleIO: &corev1.ScaleIOVolumeSource{
|
||||
SecretRef: &corev1.LocalObjectReference{
|
||||
Name: "scaleio-secret",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
ISCSI: &corev1.ISCSIVolumeSource{
|
||||
SecretRef: &corev1.LocalObjectReference{
|
||||
Name: "iscsi-secret",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
StorageOS: &corev1.StorageOSVolumeSource{
|
||||
SecretRef: &corev1.LocalObjectReference{
|
||||
Name: "storageos-secret",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
CSI: &corev1.CSIVolumeSource{
|
||||
NodePublishSecretRef: &corev1.LocalObjectReference{
|
||||
Name: "csi-secret",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
pod *corev1.Pod
|
||||
expected sets.Set[string]
|
||||
}{
|
||||
{
|
||||
name: "get secret names from pod without secrets",
|
||||
pod: emptySecretsPod,
|
||||
expected: make(sets.Set[string], 0),
|
||||
},
|
||||
{
|
||||
name: "get secret names from pod with secrets",
|
||||
pod: secretsPod,
|
||||
expected: sets.New("image-secret", "initcontainer-envfrom-secret", "initcontainer-env-secret", "container-envfrom-secret", "container-env-secret",
|
||||
"ephemeralcontainer-envfrom-secret", "ephemeralcontainer-env-secret", "azure-secret", "cephfs-secret", "cinder-secret", "flex-secret", "projected-secret",
|
||||
"rbd-secret", "secret-config", "scaleio-secret", "iscsi-secret", "storageos-secret", "csi-secret"),
|
||||
},
|
||||
}
|
||||
|
||||
for i := range tests {
|
||||
tt := tests[i]
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
res := getSecretNames(tt.pod)
|
||||
if !res.Equal(tt.expected) {
|
||||
t.Errorf("getSecretNames() = %v, want %v", res, tt.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetConfigMapNames(t *testing.T) {
|
||||
emptyConfigMapsPod := helper.NewPod(namespace, podName)
|
||||
|
||||
configMapsPod := helper.NewPod(namespace, podName)
|
||||
configMapsPod.Spec.InitContainers = []corev1.Container{
|
||||
{
|
||||
EnvFrom: []corev1.EnvFromSource{
|
||||
{
|
||||
ConfigMapRef: &corev1.ConfigMapEnvSource{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "initcontainer-envfrom-configmap",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Env: []corev1.EnvVar{
|
||||
{
|
||||
ValueFrom: &corev1.EnvVarSource{
|
||||
ConfigMapKeyRef: &corev1.ConfigMapKeySelector{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "initcontainer-env-configmap",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
configMapsPod.Spec.Containers = []corev1.Container{
|
||||
{
|
||||
EnvFrom: []corev1.EnvFromSource{
|
||||
{
|
||||
ConfigMapRef: &corev1.ConfigMapEnvSource{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "container-envfrom-configmap",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Env: []corev1.EnvVar{
|
||||
{
|
||||
ValueFrom: &corev1.EnvVarSource{
|
||||
ConfigMapKeyRef: &corev1.ConfigMapKeySelector{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "container-env-configmap",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
configMapsPod.Spec.EphemeralContainers = []corev1.EphemeralContainer{
|
||||
{
|
||||
EphemeralContainerCommon: corev1.EphemeralContainerCommon{
|
||||
EnvFrom: []corev1.EnvFromSource{
|
||||
{
|
||||
ConfigMapRef: &corev1.ConfigMapEnvSource{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "ephemeralcontainer-envfrom-configmap",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Env: []corev1.EnvVar{
|
||||
{
|
||||
ValueFrom: &corev1.EnvVarSource{
|
||||
ConfigMapKeyRef: &corev1.ConfigMapKeySelector{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "ephemeralcontainer-env-configmap",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
configMapsPod.Spec.Volumes = []corev1.Volume{
|
||||
{
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
Projected: &corev1.ProjectedVolumeSource{
|
||||
Sources: []corev1.VolumeProjection{
|
||||
{
|
||||
ConfigMap: &corev1.ConfigMapProjection{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "projected-configmap",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
ConfigMap: &corev1.ConfigMapVolumeSource{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "configmap-config",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
pod *corev1.Pod
|
||||
expected sets.Set[string]
|
||||
}{
|
||||
{
|
||||
name: "get configMap names from pod without configMaps",
|
||||
pod: emptyConfigMapsPod,
|
||||
expected: make(sets.Set[string], 0),
|
||||
},
|
||||
{
|
||||
name: "get configMap names from pod with configMaps",
|
||||
pod: configMapsPod,
|
||||
expected: sets.New("initcontainer-envfrom-configmap", "initcontainer-env-configmap", "container-envfrom-configmap", "container-env-configmap",
|
||||
"ephemeralcontainer-envfrom-configmap", "ephemeralcontainer-env-configmap", "projected-configmap", "configmap-config"),
|
||||
},
|
||||
}
|
||||
|
||||
for i := range tests {
|
||||
tt := tests[i]
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
res := getConfigMapNames(tt.pod)
|
||||
if !res.Equal(tt.expected) {
|
||||
t.Errorf("getConfigMapNames() = %v, want %v", res, tt.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetPVCNames(t *testing.T) {
|
||||
emptyPvcsPod := helper.NewPod(namespace, podName)
|
||||
pvcsPod := helper.NewPod(namespace, podName)
|
||||
pvcsPod.Spec.Volumes = []corev1.Volume{
|
||||
{
|
||||
Name: "foo-name",
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{
|
||||
ClaimName: "fake-foo",
|
||||
ReadOnly: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "bar-name",
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{
|
||||
ClaimName: "fake-bar",
|
||||
ReadOnly: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
pod *corev1.Pod
|
||||
expected sets.Set[string]
|
||||
}{
|
||||
{
|
||||
name: "get pvc names from pod without pvcs",
|
||||
pod: emptyPvcsPod,
|
||||
expected: make(sets.Set[string], 0),
|
||||
},
|
||||
{
|
||||
name: "get pvc names from pod with pvcs",
|
||||
pod: pvcsPod,
|
||||
expected: sets.New("fake-foo", "fake-bar"),
|
||||
},
|
||||
}
|
||||
|
||||
for i := range tests {
|
||||
tt := tests[i]
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
res := getPVCNames(tt.pod)
|
||||
if !res.Equal(tt.expected) {
|
||||
t.Errorf("getPVCNames() = %v, want %v", res, tt.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetDependenciesFromPodTemplate(t *testing.T) {
|
||||
emptyDependenciesPod := helper.NewPod(namespace, podName)
|
||||
|
||||
dependenciesPod := helper.NewPod(namespace, podName)
|
||||
dependenciesPod.Spec.Volumes = []corev1.Volume{
|
||||
{
|
||||
Name: "foo-name",
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
ConfigMap: &corev1.ConfigMapVolumeSource{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "fake-foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "bar-name",
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
Secret: &corev1.SecretVolumeSource{
|
||||
SecretName: "fake-bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "pvc-name",
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{
|
||||
ClaimName: "fake-pvc",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
dependenciesPod.Spec.ServiceAccountName = "fake-sa"
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
pod *corev1.Pod
|
||||
expected []configv1alpha1.DependentObjectReference
|
||||
}{
|
||||
{
|
||||
name: "get dependencies from PodTemplate without dependencies",
|
||||
pod: emptyDependenciesPod,
|
||||
expected: nil,
|
||||
},
|
||||
{
|
||||
name: "get dependencies from PodTemplate with dependencies",
|
||||
pod: dependenciesPod,
|
||||
expected: []configv1alpha1.DependentObjectReference{
|
||||
{
|
||||
APIVersion: "v1",
|
||||
Kind: "ConfigMap",
|
||||
Namespace: namespace,
|
||||
Name: "fake-foo",
|
||||
},
|
||||
{
|
||||
APIVersion: "v1",
|
||||
Kind: "Secret",
|
||||
Namespace: namespace,
|
||||
Name: "fake-bar",
|
||||
},
|
||||
{
|
||||
APIVersion: "v1",
|
||||
Kind: "ServiceAccount",
|
||||
Namespace: namespace,
|
||||
Name: "fake-sa",
|
||||
},
|
||||
{
|
||||
APIVersion: "v1",
|
||||
Kind: "PersistentVolumeClaim",
|
||||
Namespace: namespace,
|
||||
Name: "fake-pvc",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for i := range tests {
|
||||
tt := tests[i]
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
res, _ := getDependenciesFromPodTemplate(tt.pod)
|
||||
if len(res) == 0 {
|
||||
res = nil
|
||||
}
|
||||
if !reflect.DeepEqual(res, tt.expected) {
|
||||
t.Errorf("getDependenciesFromPodTemplate() = %v, want %v", res, tt.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_getServiceAccountNames(t *testing.T) {
|
||||
type args struct {
|
||||
pod *corev1.Pod
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want sets.Set[string]
|
||||
}{
|
||||
{
|
||||
name: "get ServiceAccountName from pod ",
|
||||
args: args{pod: &corev1.Pod{Spec: corev1.PodSpec{ServiceAccountName: "test"}}},
|
||||
want: sets.New("test"),
|
||||
},
|
||||
{
|
||||
name: "get default ServiceAccountName from pod ",
|
||||
args: args{pod: &corev1.Pod{Spec: corev1.PodSpec{ServiceAccountName: "default"}}},
|
||||
want: sets.New[string](),
|
||||
},
|
||||
}
|
||||
for i := range tests {
|
||||
tt := tests[i]
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
if got := getServiceAccountNames(tt.args.pod); !got.Equal(tt.want) {
|
||||
t.Errorf("getServiceAccountNames() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,11 @@ package helper
|
|||
|
||||
import (
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
|
||||
configv1alpha1 "github.com/karmada-io/karmada/pkg/apis/config/v1alpha1"
|
||||
"github.com/karmada-io/karmada/pkg/util/lifted"
|
||||
)
|
||||
|
||||
// GetPodCondition extracts the provided condition from the given status and returns that.
|
||||
|
@ -26,3 +31,103 @@ func GetPodConditionFromList(conditions []corev1.PodCondition, conditionType cor
|
|||
}
|
||||
return -1, nil
|
||||
}
|
||||
|
||||
// GeneratePodFromTemplateAndNamespace generate a simple pod object from the given podTemplate and namespace, then
|
||||
// returns the generated pod.
|
||||
func GeneratePodFromTemplateAndNamespace(template *corev1.PodTemplateSpec, namespace string) *corev1.Pod {
|
||||
pod := &corev1.Pod{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: namespace,
|
||||
},
|
||||
}
|
||||
|
||||
pod.Spec = *template.Spec.DeepCopy()
|
||||
return pod
|
||||
}
|
||||
|
||||
// GetDependenciesFromPodTemplate extracts the dependencies from the given pod and returns that.
|
||||
// returns DependentObjectReferences according to the pod, including ConfigMap, Secret, ServiceAccount and PersistentVolumeClaim.
|
||||
func GetDependenciesFromPodTemplate(podObj *corev1.Pod) ([]configv1alpha1.DependentObjectReference, error) {
|
||||
dependentConfigMaps := getConfigMapNames(podObj)
|
||||
dependentSecrets := getSecretNames(podObj)
|
||||
dependentSas := getServiceAccountNames(podObj)
|
||||
dependentPVCs := getPVCNames(podObj)
|
||||
var dependentObjectRefs []configv1alpha1.DependentObjectReference
|
||||
for cm := range dependentConfigMaps {
|
||||
dependentObjectRefs = append(dependentObjectRefs, configv1alpha1.DependentObjectReference{
|
||||
APIVersion: "v1",
|
||||
Kind: "ConfigMap",
|
||||
Namespace: podObj.Namespace,
|
||||
Name: cm,
|
||||
})
|
||||
}
|
||||
|
||||
for secret := range dependentSecrets {
|
||||
dependentObjectRefs = append(dependentObjectRefs, configv1alpha1.DependentObjectReference{
|
||||
APIVersion: "v1",
|
||||
Kind: "Secret",
|
||||
Namespace: podObj.Namespace,
|
||||
Name: secret,
|
||||
})
|
||||
}
|
||||
|
||||
for sa := range dependentSas {
|
||||
dependentObjectRefs = append(dependentObjectRefs, configv1alpha1.DependentObjectReference{
|
||||
APIVersion: "v1",
|
||||
Kind: "ServiceAccount",
|
||||
Namespace: podObj.Namespace,
|
||||
Name: sa,
|
||||
})
|
||||
}
|
||||
|
||||
for pvc := range dependentPVCs {
|
||||
dependentObjectRefs = append(dependentObjectRefs, configv1alpha1.DependentObjectReference{
|
||||
APIVersion: "v1",
|
||||
Kind: "PersistentVolumeClaim",
|
||||
Namespace: podObj.Namespace,
|
||||
Name: pvc,
|
||||
})
|
||||
}
|
||||
|
||||
return dependentObjectRefs, nil
|
||||
}
|
||||
|
||||
func getSecretNames(pod *corev1.Pod) sets.Set[string] {
|
||||
result := sets.New[string]()
|
||||
lifted.VisitPodSecretNames(pod, func(name string) bool {
|
||||
result.Insert(name)
|
||||
return true
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
func getServiceAccountNames(pod *corev1.Pod) sets.Set[string] {
|
||||
result := sets.New[string]()
|
||||
if pod.Spec.ServiceAccountName != "" && pod.Spec.ServiceAccountName != "default" {
|
||||
result.Insert(pod.Spec.ServiceAccountName)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func getConfigMapNames(pod *corev1.Pod) sets.Set[string] {
|
||||
result := sets.New[string]()
|
||||
lifted.VisitPodConfigmapNames(pod, func(name string) bool {
|
||||
result.Insert(name)
|
||||
return true
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
func getPVCNames(pod *corev1.Pod) sets.Set[string] {
|
||||
result := sets.New[string]()
|
||||
for i := range pod.Spec.Volumes {
|
||||
volume := pod.Spec.Volumes[i]
|
||||
if volume.PersistentVolumeClaim != nil {
|
||||
claimName := volume.PersistentVolumeClaim.ClaimName
|
||||
if len(claimName) != 0 {
|
||||
result.Insert(claimName)
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
|
|
@ -5,6 +5,16 @@ import (
|
|||
"testing"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
|
||||
configv1alpha1 "github.com/karmada-io/karmada/pkg/apis/config/v1alpha1"
|
||||
"github.com/karmada-io/karmada/test/helper"
|
||||
)
|
||||
|
||||
var (
|
||||
namespace = "karmada-test"
|
||||
podName = "fake-pod"
|
||||
)
|
||||
|
||||
func TestGetPodCondition(t *testing.T) {
|
||||
|
@ -165,3 +175,579 @@ func TestGetPodConditionFromList(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGeneratePodFromTemplateAndNamespace(t *testing.T) {
|
||||
pod1 := helper.NewPod(namespace, podName)
|
||||
pod2 := helper.NewPod(namespace, podName)
|
||||
pod2.Spec.ServiceAccountName = "fake-sa"
|
||||
type args struct {
|
||||
template *corev1.PodTemplateSpec
|
||||
namespace string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
expected corev1.Pod
|
||||
}{
|
||||
{
|
||||
name: "generate a simple pod from template and namespace without dependency",
|
||||
args: args{
|
||||
template: &corev1.PodTemplateSpec{Spec: pod1.Spec},
|
||||
namespace: "test1",
|
||||
},
|
||||
expected: corev1.Pod{
|
||||
ObjectMeta: metav1.ObjectMeta{Namespace: "test1"},
|
||||
Spec: *pod1.Spec.DeepCopy(),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "generate a simple pod from template and namespace",
|
||||
args: args{
|
||||
template: &corev1.PodTemplateSpec{Spec: pod2.Spec},
|
||||
namespace: "test2",
|
||||
},
|
||||
expected: corev1.Pod{
|
||||
ObjectMeta: metav1.ObjectMeta{Namespace: "test2"},
|
||||
Spec: *pod2.Spec.DeepCopy(),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for i := range tests {
|
||||
tt := tests[i]
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
if got := GeneratePodFromTemplateAndNamespace(tt.args.template, tt.args.namespace); !reflect.DeepEqual(*got, tt.expected) {
|
||||
t.Errorf("GeneratePodFromTemplateAndNamespace() = %v,\n want %v", got, tt.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetSecretNames(t *testing.T) {
|
||||
emptySecretsPod := helper.NewPod(namespace, podName)
|
||||
|
||||
secretsPod := helper.NewPod(namespace, podName)
|
||||
secretsPod.Spec.ImagePullSecrets = []corev1.LocalObjectReference{
|
||||
{
|
||||
Name: "image-secret",
|
||||
},
|
||||
}
|
||||
secretsPod.Spec.InitContainers = []corev1.Container{
|
||||
{
|
||||
EnvFrom: []corev1.EnvFromSource{
|
||||
{
|
||||
SecretRef: &corev1.SecretEnvSource{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "initcontainer-envfrom-secret",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Env: []corev1.EnvVar{
|
||||
{
|
||||
ValueFrom: &corev1.EnvVarSource{
|
||||
SecretKeyRef: &corev1.SecretKeySelector{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "initcontainer-env-secret",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
secretsPod.Spec.Containers = []corev1.Container{
|
||||
{
|
||||
EnvFrom: []corev1.EnvFromSource{
|
||||
{
|
||||
SecretRef: &corev1.SecretEnvSource{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "container-envfrom-secret",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Env: []corev1.EnvVar{
|
||||
{
|
||||
ValueFrom: &corev1.EnvVarSource{
|
||||
SecretKeyRef: &corev1.SecretKeySelector{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "container-env-secret",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
secretsPod.Spec.EphemeralContainers = []corev1.EphemeralContainer{
|
||||
{
|
||||
EphemeralContainerCommon: corev1.EphemeralContainerCommon{
|
||||
EnvFrom: []corev1.EnvFromSource{
|
||||
{
|
||||
SecretRef: &corev1.SecretEnvSource{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "ephemeralcontainer-envfrom-secret",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Env: []corev1.EnvVar{
|
||||
{
|
||||
ValueFrom: &corev1.EnvVarSource{
|
||||
SecretKeyRef: &corev1.SecretKeySelector{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "ephemeralcontainer-env-secret",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
secretsPod.Spec.Volumes = []corev1.Volume{
|
||||
{
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
AzureFile: &corev1.AzureFileVolumeSource{
|
||||
SecretName: "azure-secret",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
CephFS: &corev1.CephFSVolumeSource{
|
||||
SecretRef: &corev1.LocalObjectReference{
|
||||
Name: "cephfs-secret",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
Cinder: &corev1.CinderVolumeSource{
|
||||
SecretRef: &corev1.LocalObjectReference{
|
||||
Name: "cinder-secret",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
FlexVolume: &corev1.FlexVolumeSource{
|
||||
SecretRef: &corev1.LocalObjectReference{
|
||||
Name: "flex-secret",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
Projected: &corev1.ProjectedVolumeSource{
|
||||
Sources: []corev1.VolumeProjection{
|
||||
{
|
||||
Secret: &corev1.SecretProjection{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "projected-secret",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
RBD: &corev1.RBDVolumeSource{
|
||||
SecretRef: &corev1.LocalObjectReference{
|
||||
Name: "rbd-secret",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
Secret: &corev1.SecretVolumeSource{
|
||||
SecretName: "secret-config",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
ScaleIO: &corev1.ScaleIOVolumeSource{
|
||||
SecretRef: &corev1.LocalObjectReference{
|
||||
Name: "scaleio-secret",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
ISCSI: &corev1.ISCSIVolumeSource{
|
||||
SecretRef: &corev1.LocalObjectReference{
|
||||
Name: "iscsi-secret",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
StorageOS: &corev1.StorageOSVolumeSource{
|
||||
SecretRef: &corev1.LocalObjectReference{
|
||||
Name: "storageos-secret",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
CSI: &corev1.CSIVolumeSource{
|
||||
NodePublishSecretRef: &corev1.LocalObjectReference{
|
||||
Name: "csi-secret",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
pod *corev1.Pod
|
||||
expected sets.Set[string]
|
||||
}{
|
||||
{
|
||||
name: "get secret names from pod without secrets",
|
||||
pod: emptySecretsPod,
|
||||
expected: make(sets.Set[string], 0),
|
||||
},
|
||||
{
|
||||
name: "get secret names from pod with secrets",
|
||||
pod: secretsPod,
|
||||
expected: sets.New("image-secret", "initcontainer-envfrom-secret", "initcontainer-env-secret", "container-envfrom-secret", "container-env-secret",
|
||||
"ephemeralcontainer-envfrom-secret", "ephemeralcontainer-env-secret", "azure-secret", "cephfs-secret", "cinder-secret", "flex-secret", "projected-secret",
|
||||
"rbd-secret", "secret-config", "scaleio-secret", "iscsi-secret", "storageos-secret", "csi-secret"),
|
||||
},
|
||||
}
|
||||
|
||||
for i := range tests {
|
||||
tt := tests[i]
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
res := getSecretNames(tt.pod)
|
||||
if !res.Equal(tt.expected) {
|
||||
t.Errorf("getSecretNames() = %v, want %v", res, tt.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetConfigMapNames(t *testing.T) {
|
||||
emptyConfigMapsPod := helper.NewPod(namespace, podName)
|
||||
|
||||
configMapsPod := helper.NewPod(namespace, podName)
|
||||
configMapsPod.Spec.InitContainers = []corev1.Container{
|
||||
{
|
||||
EnvFrom: []corev1.EnvFromSource{
|
||||
{
|
||||
ConfigMapRef: &corev1.ConfigMapEnvSource{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "initcontainer-envfrom-configmap",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Env: []corev1.EnvVar{
|
||||
{
|
||||
ValueFrom: &corev1.EnvVarSource{
|
||||
ConfigMapKeyRef: &corev1.ConfigMapKeySelector{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "initcontainer-env-configmap",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
configMapsPod.Spec.Containers = []corev1.Container{
|
||||
{
|
||||
EnvFrom: []corev1.EnvFromSource{
|
||||
{
|
||||
ConfigMapRef: &corev1.ConfigMapEnvSource{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "container-envfrom-configmap",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Env: []corev1.EnvVar{
|
||||
{
|
||||
ValueFrom: &corev1.EnvVarSource{
|
||||
ConfigMapKeyRef: &corev1.ConfigMapKeySelector{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "container-env-configmap",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
configMapsPod.Spec.EphemeralContainers = []corev1.EphemeralContainer{
|
||||
{
|
||||
EphemeralContainerCommon: corev1.EphemeralContainerCommon{
|
||||
EnvFrom: []corev1.EnvFromSource{
|
||||
{
|
||||
ConfigMapRef: &corev1.ConfigMapEnvSource{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "ephemeralcontainer-envfrom-configmap",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Env: []corev1.EnvVar{
|
||||
{
|
||||
ValueFrom: &corev1.EnvVarSource{
|
||||
ConfigMapKeyRef: &corev1.ConfigMapKeySelector{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "ephemeralcontainer-env-configmap",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
configMapsPod.Spec.Volumes = []corev1.Volume{
|
||||
{
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
Projected: &corev1.ProjectedVolumeSource{
|
||||
Sources: []corev1.VolumeProjection{
|
||||
{
|
||||
ConfigMap: &corev1.ConfigMapProjection{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "projected-configmap",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
ConfigMap: &corev1.ConfigMapVolumeSource{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "configmap-config",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
pod *corev1.Pod
|
||||
expected sets.Set[string]
|
||||
}{
|
||||
{
|
||||
name: "get configMap names from pod without configMaps",
|
||||
pod: emptyConfigMapsPod,
|
||||
expected: make(sets.Set[string], 0),
|
||||
},
|
||||
{
|
||||
name: "get configMap names from pod with configMaps",
|
||||
pod: configMapsPod,
|
||||
expected: sets.New("initcontainer-envfrom-configmap", "initcontainer-env-configmap", "container-envfrom-configmap", "container-env-configmap",
|
||||
"ephemeralcontainer-envfrom-configmap", "ephemeralcontainer-env-configmap", "projected-configmap", "configmap-config"),
|
||||
},
|
||||
}
|
||||
|
||||
for i := range tests {
|
||||
tt := tests[i]
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
res := getConfigMapNames(tt.pod)
|
||||
if !res.Equal(tt.expected) {
|
||||
t.Errorf("getConfigMapNames() = %v, want %v", res, tt.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetPVCNames(t *testing.T) {
|
||||
emptyPvcsPod := helper.NewPod(namespace, podName)
|
||||
pvcsPod := helper.NewPod(namespace, podName)
|
||||
pvcsPod.Spec.Volumes = []corev1.Volume{
|
||||
{
|
||||
Name: "foo-name",
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{
|
||||
ClaimName: "fake-foo",
|
||||
ReadOnly: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "bar-name",
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{
|
||||
ClaimName: "fake-bar",
|
||||
ReadOnly: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
pod *corev1.Pod
|
||||
expected sets.Set[string]
|
||||
}{
|
||||
{
|
||||
name: "get pvc names from pod without pvcs",
|
||||
pod: emptyPvcsPod,
|
||||
expected: make(sets.Set[string], 0),
|
||||
},
|
||||
{
|
||||
name: "get pvc names from pod with pvcs",
|
||||
pod: pvcsPod,
|
||||
expected: sets.New("fake-foo", "fake-bar"),
|
||||
},
|
||||
}
|
||||
|
||||
for i := range tests {
|
||||
tt := tests[i]
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
res := getPVCNames(tt.pod)
|
||||
if !res.Equal(tt.expected) {
|
||||
t.Errorf("getPVCNames() = %v, want %v", res, tt.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetDependenciesFromPodTemplate(t *testing.T) {
|
||||
emptyDependenciesPod := helper.NewPod(namespace, podName)
|
||||
|
||||
dependenciesPod := helper.NewPod(namespace, podName)
|
||||
dependenciesPod.Spec.Volumes = []corev1.Volume{
|
||||
{
|
||||
Name: "foo-name",
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
ConfigMap: &corev1.ConfigMapVolumeSource{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "fake-foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "bar-name",
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
Secret: &corev1.SecretVolumeSource{
|
||||
SecretName: "fake-bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "pvc-name",
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{
|
||||
ClaimName: "fake-pvc",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
dependenciesPod.Spec.ServiceAccountName = "fake-sa"
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
pod *corev1.Pod
|
||||
expected []configv1alpha1.DependentObjectReference
|
||||
}{
|
||||
{
|
||||
name: "get dependencies from PodTemplate without dependencies",
|
||||
pod: emptyDependenciesPod,
|
||||
expected: nil,
|
||||
},
|
||||
{
|
||||
name: "get dependencies from PodTemplate with dependencies",
|
||||
pod: dependenciesPod,
|
||||
expected: []configv1alpha1.DependentObjectReference{
|
||||
{
|
||||
APIVersion: "v1",
|
||||
Kind: "ConfigMap",
|
||||
Namespace: namespace,
|
||||
Name: "fake-foo",
|
||||
},
|
||||
{
|
||||
APIVersion: "v1",
|
||||
Kind: "Secret",
|
||||
Namespace: namespace,
|
||||
Name: "fake-bar",
|
||||
},
|
||||
{
|
||||
APIVersion: "v1",
|
||||
Kind: "ServiceAccount",
|
||||
Namespace: namespace,
|
||||
Name: "fake-sa",
|
||||
},
|
||||
{
|
||||
APIVersion: "v1",
|
||||
Kind: "PersistentVolumeClaim",
|
||||
Namespace: namespace,
|
||||
Name: "fake-pvc",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for i := range tests {
|
||||
tt := tests[i]
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
res, _ := GetDependenciesFromPodTemplate(tt.pod)
|
||||
if len(res) == 0 {
|
||||
res = nil
|
||||
}
|
||||
if !reflect.DeepEqual(res, tt.expected) {
|
||||
t.Errorf("getDependenciesFromPodTemplate() = %v, want %v", res, tt.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_getServiceAccountNames(t *testing.T) {
|
||||
type args struct {
|
||||
pod *corev1.Pod
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want sets.Set[string]
|
||||
}{
|
||||
{
|
||||
name: "get ServiceAccountName from pod ",
|
||||
args: args{pod: &corev1.Pod{Spec: corev1.PodSpec{ServiceAccountName: "test"}}},
|
||||
want: sets.New("test"),
|
||||
},
|
||||
{
|
||||
name: "get default ServiceAccountName from pod ",
|
||||
args: args{pod: &corev1.Pod{Spec: corev1.PodSpec{ServiceAccountName: "default"}}},
|
||||
want: sets.New[string](),
|
||||
},
|
||||
}
|
||||
for i := range tests {
|
||||
tt := tests[i]
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
if got := getServiceAccountNames(tt.args.pod); !got.Equal(tt.want) {
|
||||
t.Errorf("getServiceAccountNames() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue