func (p *pod) GetEffectiveAnnotation(key, container string) (string, bool) {
	if v, ok := p.Annotations[key+"/container."+container]; ok {
		return v, true
	}
	if v, ok := p.Annotations[key+"/pod"]; ok {
		return v, true
	}
	v, ok := p.Annotations[key]
	return v, ok
}
Get the effective annotation for the container.
package cache
import (
	"encoding/json"
	"strconv"
	"strings"
	v1 "k8s.io/api/core/v1"
	cri "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
	"github.com/intel/cri-resource-manager/pkg/apis/resmgr"
	"github.com/intel/cri-resource-manager/pkg/cgroups"
	"github.com/intel/cri-resource-manager/pkg/cri/resource-manager/kubernetes"
)
const (
	KeyResourceAnnotation = "intel.com/resources"
)
func (p *pod) fromRunRequest(req *cri.RunPodSandboxRequest) error {
	cfg := req.Config
	if cfg == nil {
		return cacheError("pod %s has no config", p.ID)
	}
	meta := cfg.Metadata
	if meta == nil {
		return cacheError("pod %s has no request metadata", p.ID)
	}
	p.containers = make(map[string]string)
	p.UID = meta.Uid
	p.Name = meta.Name
	p.Namespace = meta.Namespace
	p.State = PodState(int32(PodStateReady))
	p.Labels = cfg.Labels
	p.Annotations = cfg.Annotations
	p.CgroupParent = cfg.GetLinux().GetCgroupParent()
	if err := p.discoverQOSClass(); err != nil {
		p.cache.Error("%v", err)
	}
	p.parseResourceAnnotations()
	return nil
}
func (p *pod) fromListResponse(pod *cri.PodSandbox, status *PodStatus) error {
	meta := pod.Metadata
	if meta == nil {
		return cacheError("pod %s has no reply metadata", p.ID)
	}
	p.containers = make(map[string]string)
	p.UID = meta.Uid
	p.Name = meta.Name
	p.Namespace = meta.Namespace
	p.State = PodState(int32(pod.State))
	p.Labels = pod.Labels
	p.Annotations = pod.Annotations
	p.CgroupParent = status.CgroupParent
	if err := p.discoverQOSClass(); err != nil {
		p.cache.Error("%v", err)
	}
	p.parseResourceAnnotations()
	return nil
}
func (p *pod) GetInitContainers() []Container {
	if p.Resources == nil {
		return nil
	}
	containers := []Container{}
	for id, c := range p.cache.Containers {
		if id != c.CacheID {
			continue
		}
		if _, ok := p.Resources.InitContainers[c.ID]; ok {
			containers = append(containers, c)
		}
	}
	return containers
}
func (p *pod) GetContainers() []Container {
	containers := []Container{}
	for id, c := range p.cache.Containers {
		if c.PodID != p.ID || id != c.CacheID {
			continue
		}
		if p.Resources != nil {
			if _, ok := p.Resources.InitContainers[c.ID]; ok {
				continue
			}
		}
		containers = append(containers, c)
	}
	return containers
}
func (p *pod) getContainer(name string) *container {
	var found *container
	if id, ok := p.containers[name]; ok {
		return p.cache.Containers[id]
	}
	for _, c := range p.GetContainers() {
		cptr := c.(*container)
		p.containers[cptr.Name] = cptr.ID
		if cptr.Name == name {
			found = cptr
		}
	}
	return found
}
func (p *pod) GetContainer(name string) (Container, bool) {
	c := p.getContainer(name)
	return c, c != nil
}
func (p *pod) GetID() string {
	return p.ID
}
func (p *pod) GetUID() string {
	return p.UID
}
func (p *pod) GetName() string {
	return p.Name
}
func (p *pod) GetNamespace() string {
	return p.Namespace
}
func (p *pod) GetState() PodState {
	return p.State
}
func (p *pod) GetLabelKeys() []string {
	keys := make([]string, len(p.Labels))
	idx := 0
	for key := range p.Labels {
		keys[idx] = key
		idx++
	}
	return keys
}
func (p *pod) GetLabel(key string) (string, bool) {
	value, ok := p.Labels[key]
	return value, ok
}
func (p *pod) GetResmgrLabelKeys() []string {
	return keysInNamespace(p.Labels, kubernetes.ResmgrKeyNamespace)
}
func (p *pod) GetResmgrLabel(key string) (string, bool) {
	value, ok := p.Labels[kubernetes.ResmgrKey(key)]
	return value, ok
}
func (p *pod) GetAnnotationKeys() []string {
	keys := make([]string, len(p.Annotations))
	idx := 0
	for key := range p.Annotations {
		keys[idx] = key
		idx++
	}
	return keys
}
func (p *pod) GetAnnotation(key string) (string, bool) {
	value, ok := p.Annotations[key]
	return value, ok
}
func (p *pod) GetAnnotationObject(key string, objPtr interface{},
	decode func([]byte, interface{}) error) (bool, error) {
	var err error
	value, ok := p.GetAnnotation(key)
	if !ok {
		return false, nil
	}
	if decode != nil {
		err = decode([]byte(value), objPtr)
		return true, err
	}
	switch objPtr.(type) {
	case *string:
		*objPtr.(*string) = value
	case *bool:
		*objPtr.(*bool), err = strconv.ParseBool(value)
	case *int:
		var i int64
		i, err = strconv.ParseInt(value, 0, 0)
		*objPtr.(*int) = int(i)
	case *uint:
		var i uint64
		i, err = strconv.ParseUint(value, 0, 0)
		*objPtr.(*uint) = uint(i)
	case *int64:
		*objPtr.(*int64), err = strconv.ParseInt(value, 0, 64)
	case *uint64:
		*objPtr.(*uint64), err = strconv.ParseUint(value, 0, 64)
	default:
		err = json.Unmarshal([]byte(value), objPtr)
	}
	if err != nil {
		p.cache.Error("failed to decode annotation %s (%s): %v", key, value, err)
	}
	return true, err
}
func (p *pod) GetResmgrAnnotationKeys() []string {
	return keysInNamespace(p.Annotations, kubernetes.ResmgrKeyNamespace)
}
func (p *pod) GetResmgrAnnotation(key string) (string, bool) {
	return p.GetAnnotation(kubernetes.ResmgrKey(key))
}
func (p *pod) GetResmgrAnnotationObject(key string, objPtr interface{},
	decode func([]byte, interface{}) error) (bool, error) {
	return p.GetAnnotationObject(kubernetes.ResmgrKey(key), objPtr, decode)
}