<p><strong>TL;DR:</strong> How can I flexibly decode a k8s API object and inspect its top-level <code>metav1.ObjectMeta</code> struct without knowing the object's <code>Kind</code> in advance?</p>

<hr>

<p>I'm writing an admission controller endpoint that unmarshals a <code>metav1.AdmissionReview</code> object's <code>Request.Object.Raw</code> field into a concrete object based on the <code>Request.Kind</code> field - e.g.</p>

<pre class="lang-golang prettyprint-override"><code>if kind == "Pod" {
    var pod core.Pod
    // ...
    if _, _, err := deserializer.Decode(admissionReview.Request.Object.Raw, nil, &amp;pod); err != nil {
        return nil, err
    }

    annotations := pod.ObjectMeta.Annotations
    // inspect/validate the annotations...
</code></pre>

<p>This requires knowing all possible types up front, or perhaps asking a user to supply a <code>map[kind]corev1.Object</code> that we can use to be more flexible.</p>

<p>What I'd like to instead achieve is something closer to:</p>

<pre class="lang-golang prettyprint-override"><code>var objMeta core.ObjectMeta
if _, _, err := deserializer.Decode(admissionReview.Request.Object.Raw, nil, &amp;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.
</code></pre>

<p>Is this possible? The k8s API surface is fairly extensive, and I've crawled through the <a href="https://godoc.org/k8s.io/apimachinery/pkg/apis/meta/v1#Object" rel="noreferrer">metav1 godoc</a>, corev1 godoc &amp; <a href="https://cs.k8s.io" rel="noreferrer">https://cs.k8s.io</a> for prior art without a decent example.</p>

<p>The closest I've found is possibly the <a href="https://godoc.org/k8s.io/apimachinery/pkg/apis/meta/v1#ObjectMetaAccessor" rel="noreferrer"><code>ObjectMetaAccessor</code></a> interface, but I'd need to get from an <code>AdmissionReview.Request.Object</code> (type <code>runtime.RawExtension</code>) to a <code>runtime.Object</code> first.</p>

elithrar
<p>There is a way to do this that I discovered recently, let me describe it here:</p>
<p>Quick disclaimer: I used admission/v1 and never tested with admission/v1beta1, which should work identically.</p>
<p>The data type of <code>admissionReview.Request.Object</code> is <code>runtime.RawExtension</code>, and the <code>k8s.io/apimachinery/pkg/runtime</code> provides a method that can convert the <code>runtime.RawExtension</code> to a <code>runtime.Object</code>. The method is called <code>runtime.Convert_runtime_RawExtension_To_runtime_Object(...)</code>. From there, you can easily convert to the <code>unstructured.Unstructured</code> data type, which has all the fields from the <code>MetaV1</code> object accessible with simple getter methods.</p>
<p>Here is a code snippet that lets you get this accomplished:</p>
<pre class="lang-golang prettyprint-override"><code>import (
    // ...
    &quot;k8s.io/apimachinery/pkg/apis/meta/v1/unstructured&quot;
    &quot;k8s.io/apimachinery/pkg/runtime&quot;
    // ...
)

// ...

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(&amp;ar.Request.Object, &amp;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.
    // ...
}
</code></pre>
<p>References:</p>
<ol>
<li><a href="https://godoc.org/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" rel="nofollow noreferrer">https://godoc.org/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured</a></li>
<li><a href="https://godoc.org/k8s.io/apimachinery/pkg/runtime#Convert_runtime_RawExtension_To_runtime_Object" rel="nofollow noreferrer">https://godoc.org/k8s.io/apimachinery/pkg/runtime#Convert_runtime_RawExtension_To_runtime_Object</a></li>
<li><a href="https://godoc.org/k8s.io/api/admission/v1#AdmissionRequest" rel="nofollow noreferrer">https://godoc.org/k8s.io/api/admission/v1#AdmissionRequest</a></li>
</ol>
