TL; DR::如何在不事先知道对象的metav1.ObjectMeta
的情况下灵活地解码k8s API对象并检查其顶级Kind
结构?
我正在编写一个准入控制器端点,该端点根据metav1.AdmissionReview
字段将Request.Object.Raw
对象的Request.Kind
字段解组为一个具体对象-例如
if kind == "Pod" {
var pod core.Pod
// ...
if _, _, err := deserializer.Decode(admissionReview.Request.Object.Raw, nil, &pod); err != nil {
return nil, err
}
annotations := pod.ObjectMeta.Annotations
// inspect/validate the annotations...
这需要预先知道所有可能的类型,或者要求用户提供map[kind]corev1.Object
,我们可以使用它来提高灵活性。
我想实现的目标更接近:
var objMeta core.ObjectMeta
if _, _, err := deserializer.Decode(admissionReview.Request.Object.Raw, nil, &objMeta); err != nil {
return nil, err
}
// if objMeta is populated, validate the fields, else
// assume it is an object that does not define an ObjectMeta
// as part of its schema.
这可能吗? k8s API涉及面非常广泛,在没有适当示例的情况下,我已经遍历了metav1 godoc,corev1 godoc和https://cs.k8s.io的现有技术。
我找到的最接近的可能是ObjectMetaAccessor
界面,但是我需要首先从AdmissionReview.Request.Object
(类型runtime.RawExtension
)到runtime.Object
。
答案 0 :(得分:1)
我相信您找不到想要的东西,因为在解码对象时,Kubernetes使用GetObjectKind并将结果与Scheme进行比较以将对象转换为具体类型,而不是而不是使用某些类似generic的方法并与对象的字段进行交互而不知道其具体类型。
因此,您可以改用反射,例如:
k8sObjValue := reflect.ValueOf(admissionReview.Request.Object.Raw).Elem()
k8sObjObjectMeta := k8sObjValue.FieldByName("ObjectMeta")
annotations, ok := k8sObjObjectMeta.FieldByName("Annotations").(map[string]string)
if !ok {
panic("failed to retrieve annotations")
}
编辑:
或更接近您的要求,转换为ObjectMeta对象
k8sObjValue := reflect.ValueOf(admissionReview.Request.Object.Raw).Elem()
objMeta, ok := k8sObjValue.FieldByName("ObjectMeta").(core.ObjectMeta)
if !ok {
panic("failed to retrieve object metadata")
}
答案 1 :(得分:1)
最近发现了一种执行此操作的方法,让我在这里进行描述:
快速免责声明:我使用了mission / v1,但从未使用admission / v1beta1进行过测试,该测试应该完全相同。
admissionReview.Request.Object
的数据类型为runtime.RawExtension
,k8s.io/apimachinery/pkg/runtime
提供了一种可以将runtime.RawExtension
转换为runtime.Object
的方法。该方法称为runtime.Convert_runtime_RawExtension_To_runtime_Object(...)
。从那里,您可以轻松地转换为unstructured.Unstructured
数据类型,该数据类型具有MetaV1
对象的所有字段,可以通过简单的getter方法进行访问。
下面是一个代码片段,可让您完成此任务:
import (
// ...
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
// ...
)
// ...
func dummyFunc(ar *v1.AdmissionReview) {
// ...
var obj runtime.Object
var scope conversion.Scope // While not actually used within the function, need to pass in
err := runtime.Convert_runtime_RawExtension_To_runtime_Object(&ar.Request.Object, &obj, scope)
if err != nil {
// ...
}
innerObj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(obj)
if err != nil {
// ...
}
u := unstructured.Unstructured{Object: innerObj}
// Now the `u` variable has all the meta info available with simple getters.
// Sample:
labels := u.GetLabels()
kind := u.GetKind()
// etc.
// ...
}
参考:
答案 2 :(得分:0)