Merge pull request #13985 from piosz/annotations
Auto commit by PR queue bot
This commit is contained in:
		@@ -36,6 +36,7 @@ var (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
 | 
						initialResourcesAnnotation = "kubernetes.io/initial-resources"
 | 
				
			||||||
	samplesThreshold           = 60
 | 
						samplesThreshold           = 60
 | 
				
			||||||
	week                       = 7 * 24 * time.Hour
 | 
						week                       = 7 * 24 * time.Hour
 | 
				
			||||||
	month                      = 30 * 24 * time.Hour
 | 
						month                      = 30 * 24 * time.Hour
 | 
				
			||||||
@@ -81,6 +82,7 @@ func (ir initialResources) Admit(a admission.Attributes) (err error) {
 | 
				
			|||||||
// The method veryfies whether resources should be set for the given pod and
 | 
					// The method veryfies whether resources should be set for the given pod and
 | 
				
			||||||
// if there is estimation available the method fills Request field.
 | 
					// if there is estimation available the method fills Request field.
 | 
				
			||||||
func (ir initialResources) estimateAndFillResourcesIfNotSet(pod *api.Pod) {
 | 
					func (ir initialResources) estimateAndFillResourcesIfNotSet(pod *api.Pod) {
 | 
				
			||||||
 | 
						annotations := []string{}
 | 
				
			||||||
	for i := range pod.Spec.Containers {
 | 
						for i := range pod.Spec.Containers {
 | 
				
			||||||
		c := &pod.Spec.Containers[i]
 | 
							c := &pod.Spec.Containers[i]
 | 
				
			||||||
		req := c.Resources.Requests
 | 
							req := c.Resources.Requests
 | 
				
			||||||
@@ -109,16 +111,29 @@ func (ir initialResources) estimateAndFillResourcesIfNotSet(pod *api.Pod) {
 | 
				
			|||||||
			c.Resources.Requests = api.ResourceList{}
 | 
								c.Resources.Requests = api.ResourceList{}
 | 
				
			||||||
			req = c.Resources.Requests
 | 
								req = c.Resources.Requests
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							setRes := []string{}
 | 
				
			||||||
		if cpu != nil {
 | 
							if cpu != nil {
 | 
				
			||||||
			glog.Infof("CPU estimation for container %v in pod %v/%v is %v", c.Name, pod.ObjectMeta.Namespace, pod.ObjectMeta.Name, cpu.String())
 | 
								glog.Infof("CPU estimation for container %v in pod %v/%v is %v", c.Name, pod.ObjectMeta.Namespace, pod.ObjectMeta.Name, cpu.String())
 | 
				
			||||||
 | 
								setRes = append(setRes, string(api.ResourceCPU))
 | 
				
			||||||
			req[api.ResourceCPU] = *cpu
 | 
								req[api.ResourceCPU] = *cpu
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if mem != nil {
 | 
							if mem != nil {
 | 
				
			||||||
			glog.Infof("Memory estimation for container %v in pod  %v/%v is %v", c.Name, pod.ObjectMeta.Namespace, pod.ObjectMeta.Name, mem.String())
 | 
								glog.Infof("Memory estimation for container %v in pod  %v/%v is %v", c.Name, pod.ObjectMeta.Namespace, pod.ObjectMeta.Name, mem.String())
 | 
				
			||||||
 | 
								setRes = append(setRes, string(api.ResourceMemory))
 | 
				
			||||||
			req[api.ResourceMemory] = *mem
 | 
								req[api.ResourceMemory] = *mem
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							if len(setRes) > 0 {
 | 
				
			||||||
 | 
								a := strings.Join(setRes, ", ") + " request for container " + c.Name
 | 
				
			||||||
 | 
								annotations = append(annotations, a)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if len(annotations) > 0 {
 | 
				
			||||||
 | 
							if pod.ObjectMeta.Annotations == nil {
 | 
				
			||||||
 | 
								pod.ObjectMeta.Annotations = make(map[string]string)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							val := "Initial Resources plugin set: " + strings.Join(annotations, "; ")
 | 
				
			||||||
 | 
							pod.ObjectMeta.Annotations[initialResourcesAnnotation] = val
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// TODO(piosz): verify the estimates fits in LimitRanger
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (ir initialResources) getEstimation(kind api.ResourceName, c *api.Container) (*resource.Quantity, error) {
 | 
					func (ir initialResources) getEstimation(kind api.ResourceName, c *api.Container) (*resource.Quantity, error) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -55,18 +55,18 @@ func addContainer(pod *api.Pod, name, image string, request api.ResourceList) {
 | 
				
			|||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func createPod(name string, image string, request api.ResourceList) api.Pod {
 | 
					func createPod(name string, image string, request api.ResourceList) *api.Pod {
 | 
				
			||||||
	pod := api.Pod{
 | 
						pod := &api.Pod{
 | 
				
			||||||
		ObjectMeta: api.ObjectMeta{Name: name, Namespace: "test"},
 | 
							ObjectMeta: api.ObjectMeta{Name: name, Namespace: "test"},
 | 
				
			||||||
		Spec:       api.PodSpec{},
 | 
							Spec:       api.PodSpec{},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	pod.Spec.Containers = []api.Container{}
 | 
						pod.Spec.Containers = []api.Container{}
 | 
				
			||||||
	addContainer(&pod, "c0", image, request)
 | 
						addContainer(pod, "c0", image, request)
 | 
				
			||||||
	return pod
 | 
						return pod
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func getPods() []api.Pod {
 | 
					func getPods() []*api.Pod {
 | 
				
			||||||
	return []api.Pod{
 | 
						return []*api.Pod{
 | 
				
			||||||
		createPod("p0", "image:v0", parseReq("", "")),
 | 
							createPod("p0", "image:v0", parseReq("", "")),
 | 
				
			||||||
		createPod("p1", "image:v1", parseReq("", "300")),
 | 
							createPod("p1", "image:v1", parseReq("", "300")),
 | 
				
			||||||
		createPod("p2", "image:v2", parseReq("300m", "")),
 | 
							createPod("p2", "image:v2", parseReq("300m", "")),
 | 
				
			||||||
@@ -88,9 +88,25 @@ func verifyPod(t *testing.T, pod *api.Pod, cpu, mem int64) {
 | 
				
			|||||||
	verifyContainer(t, &pod.Spec.Containers[0], cpu, mem)
 | 
						verifyContainer(t, &pod.Spec.Containers[0], cpu, mem)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func admit(t *testing.T, ir admission.Interface, pods []api.Pod) {
 | 
					func verifyAnnotation(t *testing.T, pod *api.Pod, expected string) {
 | 
				
			||||||
 | 
						a, ok := pod.ObjectMeta.Annotations[initialResourcesAnnotation]
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							t.Errorf("No annotation but expected %v", expected)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if a != expected {
 | 
				
			||||||
 | 
							t.Errorf("Wrong annatation set by Initial Resources: got %v, expected %v", a, expected)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func expectNoAnnotation(t *testing.T, pod *api.Pod) {
 | 
				
			||||||
 | 
						if a, ok := pod.ObjectMeta.Annotations[initialResourcesAnnotation]; ok {
 | 
				
			||||||
 | 
							t.Errorf("Expected no annatation but got %v", a)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func admit(t *testing.T, ir admission.Interface, pods []*api.Pod) {
 | 
				
			||||||
	for i := range pods {
 | 
						for i := range pods {
 | 
				
			||||||
		p := &pods[i]
 | 
							p := pods[i]
 | 
				
			||||||
		if err := ir.Admit(admission.NewAttributesRecord(p, "Pod", "test", p.ObjectMeta.Name, "pods", "", admission.Create, nil)); err != nil {
 | 
							if err := ir.Admit(admission.NewAttributesRecord(p, "Pod", "test", p.ObjectMeta.Name, "pods", "", admission.Create, nil)); err != nil {
 | 
				
			||||||
			t.Error(err)
 | 
								t.Error(err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -109,10 +125,15 @@ func TestEstimationBasedOnTheSameImage7d(t *testing.T) {
 | 
				
			|||||||
	pods := getPods()
 | 
						pods := getPods()
 | 
				
			||||||
	admit(t, ir, pods)
 | 
						admit(t, ir, pods)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	verifyPod(t, &pods[0], 100, 100)
 | 
						verifyPod(t, pods[0], 100, 100)
 | 
				
			||||||
	verifyPod(t, &pods[1], 100, 300)
 | 
						verifyPod(t, pods[1], 100, 300)
 | 
				
			||||||
	verifyPod(t, &pods[2], 300, 100)
 | 
						verifyPod(t, pods[2], 300, 100)
 | 
				
			||||||
	verifyPod(t, &pods[3], 300, 300)
 | 
						verifyPod(t, pods[3], 300, 300)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						verifyAnnotation(t, pods[0], "Initial Resources plugin set: cpu, memory request for container c0")
 | 
				
			||||||
 | 
						verifyAnnotation(t, pods[1], "Initial Resources plugin set: cpu request for container c0")
 | 
				
			||||||
 | 
						verifyAnnotation(t, pods[2], "Initial Resources plugin set: memory request for container c0")
 | 
				
			||||||
 | 
						expectNoAnnotation(t, pods[3])
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestEstimationBasedOnTheSameImage30d(t *testing.T) {
 | 
					func TestEstimationBasedOnTheSameImage30d(t *testing.T) {
 | 
				
			||||||
@@ -130,10 +151,10 @@ func TestEstimationBasedOnTheSameImage30d(t *testing.T) {
 | 
				
			|||||||
	pods := getPods()
 | 
						pods := getPods()
 | 
				
			||||||
	admit(t, ir, pods)
 | 
						admit(t, ir, pods)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	verifyPod(t, &pods[0], 100, 100)
 | 
						verifyPod(t, pods[0], 100, 100)
 | 
				
			||||||
	verifyPod(t, &pods[1], 100, 300)
 | 
						verifyPod(t, pods[1], 100, 300)
 | 
				
			||||||
	verifyPod(t, &pods[2], 300, 100)
 | 
						verifyPod(t, pods[2], 300, 100)
 | 
				
			||||||
	verifyPod(t, &pods[3], 300, 300)
 | 
						verifyPod(t, pods[3], 300, 300)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestEstimationBasedOnOtherImages(t *testing.T) {
 | 
					func TestEstimationBasedOnOtherImages(t *testing.T) {
 | 
				
			||||||
@@ -148,10 +169,10 @@ func TestEstimationBasedOnOtherImages(t *testing.T) {
 | 
				
			|||||||
	pods := getPods()
 | 
						pods := getPods()
 | 
				
			||||||
	admit(t, ir, pods)
 | 
						admit(t, ir, pods)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	verifyPod(t, &pods[0], 100, 100)
 | 
						verifyPod(t, pods[0], 100, 100)
 | 
				
			||||||
	verifyPod(t, &pods[1], 100, 300)
 | 
						verifyPod(t, pods[1], 100, 300)
 | 
				
			||||||
	verifyPod(t, &pods[2], 300, 100)
 | 
						verifyPod(t, pods[2], 300, 100)
 | 
				
			||||||
	verifyPod(t, &pods[3], 300, 300)
 | 
						verifyPod(t, pods[3], 300, 300)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestNoData(t *testing.T) {
 | 
					func TestNoData(t *testing.T) {
 | 
				
			||||||
@@ -160,7 +181,7 @@ func TestNoData(t *testing.T) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	ir := newInitialResources(&fakeSource{f: f})
 | 
						ir := newInitialResources(&fakeSource{f: f})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pods := []api.Pod{
 | 
						pods := []*api.Pod{
 | 
				
			||||||
		createPod("p0", "image:v0", parseReq("", "")),
 | 
							createPod("p0", "image:v0", parseReq("", "")),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	admit(t, ir, pods)
 | 
						admit(t, ir, pods)
 | 
				
			||||||
@@ -168,6 +189,8 @@ func TestNoData(t *testing.T) {
 | 
				
			|||||||
	if pods[0].Spec.Containers[0].Resources.Requests != nil {
 | 
						if pods[0].Spec.Containers[0].Resources.Requests != nil {
 | 
				
			||||||
		t.Errorf("Unexpected resource estimation")
 | 
							t.Errorf("Unexpected resource estimation")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						expectNoAnnotation(t, pods[0])
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestManyContainers(t *testing.T) {
 | 
					func TestManyContainers(t *testing.T) {
 | 
				
			||||||
@@ -180,13 +203,15 @@ func TestManyContainers(t *testing.T) {
 | 
				
			|||||||
	ir := newInitialResources(&fakeSource{f: f})
 | 
						ir := newInitialResources(&fakeSource{f: f})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pod := createPod("p", "image:v0", parseReq("", ""))
 | 
						pod := createPod("p", "image:v0", parseReq("", ""))
 | 
				
			||||||
	addContainer(&pod, "c1", "image:v1", parseReq("", "300"))
 | 
						addContainer(pod, "c1", "image:v1", parseReq("", "300"))
 | 
				
			||||||
	addContainer(&pod, "c2", "image:v2", parseReq("300m", ""))
 | 
						addContainer(pod, "c2", "image:v2", parseReq("300m", ""))
 | 
				
			||||||
	addContainer(&pod, "c3", "image:v3", parseReq("300m", "300"))
 | 
						addContainer(pod, "c3", "image:v3", parseReq("300m", "300"))
 | 
				
			||||||
	admit(t, ir, []api.Pod{pod})
 | 
						admit(t, ir, []*api.Pod{pod})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	verifyContainer(t, &pod.Spec.Containers[0], 100, 100)
 | 
						verifyContainer(t, &pod.Spec.Containers[0], 100, 100)
 | 
				
			||||||
	verifyContainer(t, &pod.Spec.Containers[1], 100, 300)
 | 
						verifyContainer(t, &pod.Spec.Containers[1], 100, 300)
 | 
				
			||||||
	verifyContainer(t, &pod.Spec.Containers[2], 300, 100)
 | 
						verifyContainer(t, &pod.Spec.Containers[2], 300, 100)
 | 
				
			||||||
	verifyContainer(t, &pod.Spec.Containers[3], 300, 300)
 | 
						verifyContainer(t, &pod.Spec.Containers[3], 300, 300)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						verifyAnnotation(t, pod, "Initial Resources plugin set: cpu, memory request for container c0; cpu request for container c1; memory request for container c2")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user