func TestResourceHelpers(t *testing.T) { cpuLimit := resource.MustParse("10") memoryLimit := resource.MustParse("10G") resourceSpec := ResourceRequirements{ Limits: ResourceList{ "cpu": cpuLimit, "memory": memoryLimit, "kube.io/storage": memoryLimit, }, } if res := resourceSpec.Limits.Cpu(); *res != cpuLimit { t.Errorf("expected cpulimit %v, got %v", cpuLimit, res) } if res := resourceSpec.Limits.Memory(); *res != memoryLimit { t.Errorf("expected memorylimit %v, got %v", memoryLimit, res) } resourceSpec = ResourceRequirements{ Limits: ResourceList{ "memory": memoryLimit, "kube.io/storage": memoryLimit, }, } if res := resourceSpec.Limits.Cpu(); res.Value() != 0 { t.Errorf("expected cpulimit %v, got %v", 0, res) } if res := resourceSpec.Limits.Memory(); *res != memoryLimit { t.Errorf("expected memorylimit %v, got %v", memoryLimit, res) } }
func TestLimitRangeUpdate(t *testing.T) { ns := api.NamespaceDefault limitRange := &api.LimitRange{ ObjectMeta: api.ObjectMeta{ Name: "abc", ResourceVersion: "1", }, Spec: api.LimitRangeSpec{ Limits: []api.LimitRangeItem{ { Type: api.LimitTypePod, Max: api.ResourceList{ api.ResourceCPU: resource.MustParse("100"), api.ResourceMemory: resource.MustParse("10000"), }, Min: api.ResourceList{ api.ResourceCPU: resource.MustParse("0"), api.ResourceMemory: resource.MustParse("100"), }, }, }, }, } c := &simple.Client{ Request: simple.Request{Method: "PUT", Path: testapi.Default.ResourcePath(getLimitRangesResourceName(), ns, "abc"), Query: simple.BuildQueryValues(nil)}, Response: simple.Response{StatusCode: 200, Body: limitRange}, } response, err := c.Setup(t).LimitRanges(ns).Update(limitRange) defer c.Close() c.Validate(t, response, err) }
func TestUpdateNode(t *testing.T) { requestNode := &api.Node{ ObjectMeta: api.ObjectMeta{ Name: "foo", ResourceVersion: "1", }, Status: api.NodeStatus{ Capacity: api.ResourceList{ api.ResourceCPU: resource.MustParse("1000m"), api.ResourceMemory: resource.MustParse("1Mi"), }, }, Spec: api.NodeSpec{ Unschedulable: true, }, } c := &simple.Client{ Request: simple.Request{ Method: "PUT", Path: testapi.Default.ResourcePath(getNodesResourceName(), "", "foo"), }, Response: simple.Response{StatusCode: 200, Body: requestNode}, } response, err := c.Setup(t).Nodes().Update(requestNode) defer c.Close() c.Validate(t, response, err) }
func TestPersistentVolumeGet(t *testing.T) { persistentVolume := &api.PersistentVolume{ ObjectMeta: api.ObjectMeta{ Name: "abc", Namespace: "foo", }, Spec: api.PersistentVolumeSpec{ Capacity: api.ResourceList{ api.ResourceName(api.ResourceStorage): resource.MustParse("10G"), }, PersistentVolumeSource: api.PersistentVolumeSource{ HostPath: &api.HostPathVolumeSource{Path: "/foo"}, }, }, } c := &simple.Client{ Request: simple.Request{ Method: "GET", Path: testapi.Default.ResourcePath(getPersistentVolumesResoureName(), "", "abc"), Query: simple.BuildQueryValues(nil), Body: nil, }, Response: simple.Response{StatusCode: 200, Body: persistentVolume}, } response, err := c.Setup(t).PersistentVolumes().Get("abc") defer c.Close() c.Validate(t, response, err) }
func TestDefaultRequestIsNotSetForReplicaSet(t *testing.T) { s := v1.PodSpec{} s.Containers = []v1.Container{ { Resources: v1.ResourceRequirements{ Limits: v1.ResourceList{ v1.ResourceCPU: resource.MustParse("100m"), }, }, }, } rs := &ReplicaSet{ Spec: ReplicaSetSpec{ Replicas: newInt32(3), Template: &v1.PodTemplateSpec{ ObjectMeta: v1.ObjectMeta{ Labels: map[string]string{ "foo": "bar", }, }, Spec: s, }, }, } output := roundTrip(t, runtime.Object(rs)) rs2 := output.(*ReplicaSet) defaultRequest := rs2.Spec.Template.Spec.Containers[0].Resources.Requests requestValue := defaultRequest[v1.ResourceCPU] if requestValue.String() != "0" { t.Errorf("Expected 0 request value, got: %s", requestValue.String()) } }
func TestDefaultRequestIsNotSetForReplicationController(t *testing.T) { s := versioned.PodSpec{} s.Containers = []versioned.Container{ { Resources: versioned.ResourceRequirements{ Limits: versioned.ResourceList{ versioned.ResourceCPU: resource.MustParse("100m"), }, }, }, } rc := &versioned.ReplicationController{ Spec: versioned.ReplicationControllerSpec{ Replicas: newInt(3), Template: &versioned.PodTemplateSpec{ ObjectMeta: versioned.ObjectMeta{ Labels: map[string]string{ "foo": "bar", }, }, Spec: s, }, }, } output := roundTrip(t, runtime.Object(rc)) rc2 := output.(*versioned.ReplicationController) defaultRequest := rc2.Spec.Template.Spec.Containers[0].Resources.Requests requestValue := defaultRequest[versioned.ResourceCPU] if requestValue.String() != "0" { t.Errorf("Expected 0 request value, got: %s", requestValue.String()) } }
func TestPersistentVolumeClaimGet(t *testing.T) { ns := api.NamespaceDefault persistentVolumeClaim := &api.PersistentVolumeClaim{ ObjectMeta: api.ObjectMeta{ Name: "abc", Namespace: "foo", }, Spec: api.PersistentVolumeClaimSpec{ AccessModes: []api.PersistentVolumeAccessMode{ api.ReadWriteOnce, api.ReadOnlyMany, }, Resources: api.ResourceRequirements{ Requests: api.ResourceList{ api.ResourceName(api.ResourceStorage): resource.MustParse("10G"), }, }, }, } c := &simple.Client{ Request: simple.Request{ Method: "GET", Path: testapi.Default.ResourcePath(getPersistentVolumeClaimsResoureName(), ns, "abc"), Query: simple.BuildQueryValues(nil), Body: nil, }, Response: simple.Response{StatusCode: 200, Body: persistentVolumeClaim}, } response, err := c.Setup(t).PersistentVolumeClaims(ns).Get("abc") defer c.Close() c.Validate(t, response, err) }
func ExampleMustParse() { memorySize := resource.MustParse("5Gi") fmt.Printf("memorySize = %v (%v)\n", memorySize.Value(), memorySize.Format) diskSize := resource.MustParse("5G") fmt.Printf("diskSize = %v (%v)\n", diskSize.Value(), diskSize.Format) cores := resource.MustParse("5300m") fmt.Printf("milliCores = %v (%v)\n", cores.MilliValue(), cores.Format) cores2 := resource.MustParse("5.4") fmt.Printf("milliCores = %v (%v)\n", cores2.MilliValue(), cores2.Format) // Output: // memorySize = 5368709120 (BinarySI) // diskSize = 5000000000 (DecimalSI) // milliCores = 5300 (DecimalSI) // milliCores = 5400 (DecimalSI) }
func TestSetDefaultLimitRangeItem(t *testing.T) { limitRange := &versioned.LimitRange{ ObjectMeta: versioned.ObjectMeta{ Name: "test-defaults", }, Spec: versioned.LimitRangeSpec{ Limits: []versioned.LimitRangeItem{{ Type: versioned.LimitTypeContainer, Max: versioned.ResourceList{ versioned.ResourceCPU: resource.MustParse("100m"), }, Min: versioned.ResourceList{ versioned.ResourceMemory: resource.MustParse("100Mi"), }, Default: versioned.ResourceList{}, DefaultRequest: versioned.ResourceList{}, }}, }, } output := roundTrip(t, runtime.Object(limitRange)) limitRange2 := output.(*versioned.LimitRange) defaultLimit := limitRange2.Spec.Limits[0].Default defaultRequest := limitRange2.Spec.Limits[0].DefaultRequest // verify that default cpu was set to the max defaultValue := defaultLimit[versioned.ResourceCPU] if defaultValue.String() != "100m" { t.Errorf("Expected default cpu: %s, got: %s", "100m", defaultValue.String()) } // verify that default request was set to the limit requestValue := defaultRequest[versioned.ResourceCPU] if requestValue.String() != "100m" { t.Errorf("Expected request cpu: %s, got: %s", "100m", requestValue.String()) } // verify that if a min is provided, it will be the default if no limit is specified requestMinValue := defaultRequest[versioned.ResourceMemory] if requestMinValue.String() != "100Mi" { t.Errorf("Expected request memory: %s, got: %s", "100Mi", requestMinValue.String()) } }
func TestResourceQuotaGet(t *testing.T) { ns := api.NamespaceDefault resourceQuota := &api.ResourceQuota{ ObjectMeta: api.ObjectMeta{ Name: "abc", Namespace: "foo", }, Spec: api.ResourceQuotaSpec{ Hard: api.ResourceList{ api.ResourceCPU: resource.MustParse("100"), api.ResourceMemory: resource.MustParse("10000"), api.ResourcePods: resource.MustParse("10"), api.ResourceServices: resource.MustParse("10"), api.ResourceReplicationControllers: resource.MustParse("10"), api.ResourceQuotas: resource.MustParse("10"), }, }, } c := &simple.Client{ Request: simple.Request{ Method: "GET", Path: testapi.Default.ResourcePath(getResourceQuotasResoureName(), ns, "abc"), Query: simple.BuildQueryValues(nil), Body: nil, }, Response: simple.Response{StatusCode: 200, Body: resourceQuota}, } response, err := c.Setup(t).ResourceQuotas(ns).Get("abc") defer c.Close() c.Validate(t, response, err) }
func TestSemantic(t *testing.T) { table := []struct { a, b interface{} shouldEqual bool }{ {resource.MustParse("0"), resource.Quantity{}, true}, {resource.Quantity{}, resource.MustParse("0"), true}, {resource.Quantity{}, resource.MustParse("1m"), false}, { resource.Quantity{Amount: inf.NewDec(5, 0), Format: resource.BinarySI}, resource.Quantity{Amount: inf.NewDec(5, 0), Format: resource.DecimalSI}, true, }, {resource.MustParse("2m"), resource.MustParse("1m"), false}, } for index, item := range table { if e, a := item.shouldEqual, Semantic.DeepEqual(item.a, item.b); e != a { t.Errorf("case[%d], expected %v, got %v.", index, e, a) } } }
func TestSetDefaultRequestsPod(t *testing.T) { // verify we default if limits are specified s := versioned.PodSpec{} s.Containers = []versioned.Container{ { Resources: versioned.ResourceRequirements{ Limits: versioned.ResourceList{ versioned.ResourceCPU: resource.MustParse("100m"), }, }, }, } pod := &versioned.Pod{ Spec: s, } output := roundTrip(t, runtime.Object(pod)) pod2 := output.(*versioned.Pod) defaultRequest := pod2.Spec.Containers[0].Resources.Requests requestValue := defaultRequest[versioned.ResourceCPU] if requestValue.String() != "100m" { t.Errorf("Expected request cpu: %s, got: %s", "100m", requestValue.String()) } // verify we do nothing if no limits are specified s = versioned.PodSpec{} s.Containers = []versioned.Container{{}} pod = &versioned.Pod{ Spec: s, } output = roundTrip(t, runtime.Object(pod)) pod2 = output.(*versioned.Pod) defaultRequest = pod2.Spec.Containers[0].Resources.Requests requestValue = defaultRequest[versioned.ResourceCPU] if requestValue.String() != "0" { t.Errorf("Expected 0 request value, got: %s", requestValue.String()) } }
func TestSetDefaultNodeStatusAllocatable(t *testing.T) { capacity := versioned.ResourceList{ versioned.ResourceCPU: resource.MustParse("1000m"), versioned.ResourceMemory: resource.MustParse("10G"), } allocatable := versioned.ResourceList{ versioned.ResourceCPU: resource.MustParse("500m"), versioned.ResourceMemory: resource.MustParse("5G"), } tests := []struct { capacity versioned.ResourceList allocatable versioned.ResourceList expectedAllocatable versioned.ResourceList }{{ // Everything set, no defaulting. capacity: capacity, allocatable: allocatable, expectedAllocatable: allocatable, }, { // Allocatable set, no defaulting. capacity: nil, allocatable: allocatable, expectedAllocatable: allocatable, }, { // Capacity set, allocatable defaults to capacity. capacity: capacity, allocatable: nil, expectedAllocatable: capacity, }, { // Nothing set, allocatable "defaults" to capacity. capacity: nil, allocatable: nil, expectedAllocatable: nil, }} copyResourceList := func(rl versioned.ResourceList) versioned.ResourceList { if rl == nil { return nil } copy := make(versioned.ResourceList, len(rl)) for k, v := range rl { copy[k] = *v.Copy() } return copy } resourceListsEqual := func(a versioned.ResourceList, b versioned.ResourceList) bool { if len(a) != len(b) { return false } for k, v := range a { vb, found := b[k] if !found { return false } if v.Cmp(vb) != 0 { return false } } return true } for i, testcase := range tests { node := versioned.Node{ Status: versioned.NodeStatus{ Capacity: copyResourceList(testcase.capacity), Allocatable: copyResourceList(testcase.allocatable), }, } node2 := roundTrip(t, runtime.Object(&node)).(*versioned.Node) actual := node2.Status.Allocatable expected := testcase.expectedAllocatable if !resourceListsEqual(expected, actual) { t.Errorf("[%d] Expected NodeStatus.Allocatable: %+v; Got: %+v", i, expected, actual) } } }
func TestResourceListConversion(t *testing.T) { bigMilliQuantity := resource.NewQuantity(resource.MaxMilliValue, resource.DecimalSI) bigMilliQuantity.Add(resource.MustParse("12345m")) tests := []struct { input versioned.ResourceList expected api.ResourceList }{ { // No changes necessary. input: versioned.ResourceList{ versioned.ResourceMemory: resource.MustParse("30M"), versioned.ResourceCPU: resource.MustParse("100m"), versioned.ResourceStorage: resource.MustParse("1G"), }, expected: api.ResourceList{ api.ResourceMemory: resource.MustParse("30M"), api.ResourceCPU: resource.MustParse("100m"), api.ResourceStorage: resource.MustParse("1G"), }, }, { // Nano-scale values should be rounded up to milli-scale. input: versioned.ResourceList{ versioned.ResourceCPU: resource.MustParse("3.000023m"), versioned.ResourceMemory: resource.MustParse("500.000050m"), }, expected: api.ResourceList{ api.ResourceCPU: resource.MustParse("4m"), api.ResourceMemory: resource.MustParse("501m"), }, }, { // Large values should still be accurate. input: versioned.ResourceList{ versioned.ResourceCPU: *bigMilliQuantity.Copy(), versioned.ResourceStorage: *bigMilliQuantity.Copy(), }, expected: api.ResourceList{ api.ResourceCPU: *bigMilliQuantity.Copy(), api.ResourceStorage: *bigMilliQuantity.Copy(), }, }, } output := api.ResourceList{} for i, test := range tests { err := api.Scheme.Convert(&test.input, &output) if err != nil { t.Fatalf("unexpected error for case %d: %v", i, err) } if !api.Semantic.DeepEqual(test.expected, output) { t.Errorf("unexpected conversion for case %d: Expected %+v; Got %+v", i, test.expected, output) } } }