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
|
// - function accuratePodRequirements(pod) requirements
|
||||||
// accurate total resource requirements for pod. Example:
|
// accurate total resource requirements for pod. Example:
|
||||||
// requirements = kube.accuratePodRequirements(pod)
|
// 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 {
|
func KubeLoader(ls *lua.LState) int {
|
||||||
mod := ls.SetFuncs(ls.NewTable(), kubeFuncs)
|
mod := ls.SetFuncs(ls.NewTable(), kubeFuncs)
|
||||||
ls.Push(mod)
|
ls.Push(mod)
|
||||||
|
@ -37,6 +40,7 @@ func KubeLoader(ls *lua.LState) int {
|
||||||
var kubeFuncs = map[string]lua.LGFunction{
|
var kubeFuncs = map[string]lua.LGFunction{
|
||||||
"resourceAdd": resourceAdd,
|
"resourceAdd": resourceAdd,
|
||||||
"accuratePodRequirements": accuratePodRequirements,
|
"accuratePodRequirements": accuratePodRequirements,
|
||||||
|
"getPodDependencies": getPodDependencies,
|
||||||
}
|
}
|
||||||
|
|
||||||
func resourceAdd(ls *lua.LState) int {
|
func resourceAdd(ls *lua.LState) int {
|
||||||
|
@ -78,6 +82,35 @@ func accuratePodRequirements(ls *lua.LState) int {
|
||||||
return 1
|
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 {
|
func checkResourceQuantity(ls *lua.LState, n int) resource.Quantity {
|
||||||
v := ls.Get(n)
|
v := ls.Get(n)
|
||||||
switch typ := v.Type(); typ {
|
switch typ := v.Type(); typ {
|
||||||
|
@ -91,3 +124,16 @@ func checkResourceQuantity(ls *lua.LState, n int) resource.Quantity {
|
||||||
return 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) {
|
func TestGetDeployPodDependencies(t *testing.T) {
|
||||||
newDeploy := appsv1.Deployment{
|
newDeploy1 := appsv1.Deployment{
|
||||||
TypeMeta: metav1.TypeMeta{
|
TypeMeta: metav1.TypeMeta{
|
||||||
APIVersion: "v1",
|
APIVersion: "v1",
|
||||||
Kind: "Deployment",
|
Kind: "Deployment",
|
||||||
|
@ -513,14 +513,24 @@ func TestGetDeployPodDependencies(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
newObj, _ := helper.ToUnstructured(&newDeploy)
|
newDeploy2 := newDeploy1.DeepCopy()
|
||||||
expect := make([]configv1alpha1.DependentObjectReference, 1)
|
newDeploy2.Namespace = ""
|
||||||
expect[0] = configv1alpha1.DependentObjectReference{
|
newObj1, _ := helper.ToUnstructured(&newDeploy1)
|
||||||
|
expect1 := make([]configv1alpha1.DependentObjectReference, 1)
|
||||||
|
expect1[0] = configv1alpha1.DependentObjectReference{
|
||||||
APIVersion: "v1",
|
APIVersion: "v1",
|
||||||
Kind: "ServiceAccount",
|
Kind: "ServiceAccount",
|
||||||
Namespace: "test",
|
Namespace: "test",
|
||||||
Name: "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 {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
curObj *unstructured.Unstructured
|
curObj *unstructured.Unstructured
|
||||||
|
@ -529,7 +539,7 @@ func TestGetDeployPodDependencies(t *testing.T) {
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "Get GetDeployPodDependencies",
|
name: "Get GetDeployPodDependencies",
|
||||||
curObj: newObj,
|
curObj: newObj1,
|
||||||
luaScript: `function GetDependencies(desiredObj)
|
luaScript: `function GetDependencies(desiredObj)
|
||||||
dependentSas = {}
|
dependentSas = {}
|
||||||
refs = {}
|
refs = {}
|
||||||
|
@ -549,7 +559,27 @@ func TestGetDeployPodDependencies(t *testing.T) {
|
||||||
end
|
end
|
||||||
return refs
|
return refs
|
||||||
end`,
|
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"
|
corev1 "k8s.io/api/core/v1"
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
|
||||||
|
|
||||||
configv1alpha1 "github.com/karmada-io/karmada/pkg/apis/config/v1alpha1"
|
configv1alpha1 "github.com/karmada-io/karmada/pkg/apis/config/v1alpha1"
|
||||||
"github.com/karmada-io/karmada/pkg/util"
|
"github.com/karmada-io/karmada/pkg/util"
|
||||||
|
@ -40,7 +39,7 @@ func getDeploymentDependencies(object *unstructured.Unstructured) ([]configv1alp
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return getDependenciesFromPodTemplate(podObj)
|
return helper.GetDependenciesFromPodTemplate(podObj)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getJobDependencies(object *unstructured.Unstructured) ([]configv1alpha1.DependentObjectReference, error) {
|
func getJobDependencies(object *unstructured.Unstructured) ([]configv1alpha1.DependentObjectReference, error) {
|
||||||
|
@ -55,7 +54,7 @@ func getJobDependencies(object *unstructured.Unstructured) ([]configv1alpha1.Dep
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return getDependenciesFromPodTemplate(podObj)
|
return helper.GetDependenciesFromPodTemplate(podObj)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getCronJobDependencies(object *unstructured.Unstructured) ([]configv1alpha1.DependentObjectReference, error) {
|
func getCronJobDependencies(object *unstructured.Unstructured) ([]configv1alpha1.DependentObjectReference, error) {
|
||||||
|
@ -70,7 +69,7 @@ func getCronJobDependencies(object *unstructured.Unstructured) ([]configv1alpha1
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return getDependenciesFromPodTemplate(podObj)
|
return helper.GetDependenciesFromPodTemplate(podObj)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getPodDependencies(object *unstructured.Unstructured) ([]configv1alpha1.DependentObjectReference, error) {
|
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 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) {
|
func getDaemonSetDependencies(object *unstructured.Unstructured) ([]configv1alpha1.DependentObjectReference, error) {
|
||||||
|
@ -95,7 +94,7 @@ func getDaemonSetDependencies(object *unstructured.Unstructured) ([]configv1alph
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return getDependenciesFromPodTemplate(podObj)
|
return helper.GetDependenciesFromPodTemplate(podObj)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getStatefulSetDependencies(object *unstructured.Unstructured) ([]configv1alpha1.DependentObjectReference, error) {
|
func getStatefulSetDependencies(object *unstructured.Unstructured) ([]configv1alpha1.DependentObjectReference, error) {
|
||||||
|
@ -110,89 +109,5 @@ func getStatefulSetDependencies(object *unstructured.Unstructured) ([]configv1al
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return getDependenciesFromPodTemplate(podObj)
|
return helper.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
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,545 +1 @@
|
||||||
package native
|
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 (
|
import (
|
||||||
corev1 "k8s.io/api/core/v1"
|
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.
|
// 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
|
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"
|
"testing"
|
||||||
|
|
||||||
corev1 "k8s.io/api/core/v1"
|
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) {
|
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