[Azure] Make Resoures.Limits Optional (#175)

* Make Resources.Limits Optional

* Remove the accuracy check of the resources.limits
This commit is contained in:
Robbie Zhang
2018-04-27 10:27:40 -07:00
committed by GitHub
parent 40f94991c3
commit 228a1f7a5f
4 changed files with 126 additions and 38 deletions

View File

@@ -564,24 +564,6 @@ func (p *ACIProvider) getContainers(pod *v1.Pod) ([]aci.Container, error) {
})
}
// NOTE(robbiezhang): ACI CPU limit must be times of 10m
cpuLimit := 1.00
if _, ok := container.Resources.Limits[v1.ResourceCPU]; ok {
cpuLimit = float64(container.Resources.Limits.Cpu().MilliValue()/10.00) / 100.00
if cpuLimit < 0.01 {
cpuLimit = 0.01
}
}
// NOTE(robbiezhang): ACI Memory limit must be times of 0.1 GB
memoryLimit := 1.50
if _, ok := container.Resources.Limits[v1.ResourceMemory]; ok {
memoryLimit = float64(container.Resources.Limits.Memory().Value()/100000000.00) / 10.00
if memoryLimit < 0.10 {
memoryLimit = 0.10
}
}
// NOTE(robbiezhang): ACI CPU request must be times of 10m
cpuRequest := 1.00
if _, ok := container.Resources.Requests[v1.ResourceCPU]; ok {
@@ -601,16 +583,29 @@ func (p *ACIProvider) getContainers(pod *v1.Pod) ([]aci.Container, error) {
}
c.Resources = aci.ResourceRequirements{
Limits: aci.ResourceLimits{
CPU: cpuLimit,
MemoryInGB: memoryLimit,
},
Requests: aci.ResourceRequests{
Requests: &aci.ResourceRequests{
CPU: cpuRequest,
MemoryInGB: memoryRequest,
},
}
if container.Resources.Limits != nil {
cpuLimit := cpuRequest
if _, ok := container.Resources.Limits[v1.ResourceCPU]; ok {
cpuLimit = float64(container.Resources.Limits.Cpu().MilliValue()) / 1000.00
}
memoryLimit := memoryRequest
if _, ok := container.Resources.Limits[v1.ResourceMemory]; ok {
memoryLimit = float64(container.Resources.Limits.Memory().Value()) / 1000000000.00
}
c.Resources.Limits = &aci.ResourceLimits{
CPU: cpuLimit,
MemoryInGB: memoryLimit,
}
}
containers = append(containers, c)
}
return containers, nil

View File

@@ -55,8 +55,7 @@ func TestCreatePodWithoutResourceSpec(t *testing.T) {
assert.NotNil(t, cg.ContainerGroupProperties.Containers[0].Resources.Requests, "Container resource requests should not be nil")
assert.Equal(t, 1.0, cg.ContainerGroupProperties.Containers[0].Resources.Requests.CPU, "Request CPU is not expected")
assert.Equal(t, 1.5, cg.ContainerGroupProperties.Containers[0].Resources.Requests.MemoryInGB, "Request Memory is not expected")
assert.Equal(t, 1.0, cg.ContainerGroupProperties.Containers[0].Resources.Limits.CPU, "Limit CPU is not expected")
assert.Equal(t, 1.5, cg.ContainerGroupProperties.Containers[0].Resources.Limits.MemoryInGB, "Limit Memory is not expected")
assert.Nil(t, cg.ContainerGroupProperties.Containers[0].Resources.Limits, "Limits should be nil")
return http.StatusOK, cg
}
@@ -80,8 +79,8 @@ func TestCreatePodWithoutResourceSpec(t *testing.T) {
}
}
// Tests create pod without resource spec
func TestCreatePodWithResourceSpec(t *testing.T) {
// Tests create pod with resource request only
func TestCreatePodWithResourceRequestOnly(t *testing.T) {
_, aciServerMocker, provider, err := prepareMocks()
if err != nil {
@@ -104,8 +103,7 @@ func TestCreatePodWithResourceSpec(t *testing.T) {
assert.NotNil(t, cg.ContainerGroupProperties.Containers[0].Resources.Requests, "Container resource requests should not be nil")
assert.Equal(t, 1.98, cg.ContainerGroupProperties.Containers[0].Resources.Requests.CPU, "Request CPU is not expected")
assert.Equal(t, 3.4, cg.ContainerGroupProperties.Containers[0].Resources.Requests.MemoryInGB, "Request Memory is not expected")
assert.Equal(t, 3.99, cg.ContainerGroupProperties.Containers[0].Resources.Limits.CPU, "Limit CPU is not expected")
assert.Equal(t, 8.0, cg.ContainerGroupProperties.Containers[0].Resources.Limits.MemoryInGB, "Limit Memory is not expected")
assert.Nil(t, cg.ContainerGroupProperties.Containers[0].Resources.Limits, "Limits should be nil")
return http.StatusOK, cg
}
@@ -121,8 +119,63 @@ func TestCreatePodWithResourceSpec(t *testing.T) {
Name: "nginx",
Resources: v1.ResourceRequirements{
Requests: v1.ResourceList{
"cpu": resource.MustParse("1.98"),
"memory": resource.MustParse("3.4G"),
"cpu": resource.MustParse("1.981"),
"memory": resource.MustParse("3.49G"),
},
},
},
},
},
}
if err := provider.CreatePod(pod); err != nil {
t.Fatal("Failed to create pod", err)
}
}
// Tests create pod with both resource request and limit.
func TestCreatePodWithResourceRequestAndLimit(t *testing.T) {
_, aciServerMocker, provider, err := prepareMocks()
if err != nil {
t.Fatal("Unable to prepare the mocks", err)
}
podName := "pod-" + uuid.New().String()
podNamespace := "ns-" + uuid.New().String()
aciServerMocker.OnCreate = func(subscription, resourceGroup, containerGroup string, cg *aci.ContainerGroup) (int, interface{}) {
assert.Equal(t, fakeSubscription, subscription, "Subscription doesn't match")
assert.Equal(t, fakeResourceGroup, resourceGroup, "Resource group doesn't match")
assert.NotNil(t, cg, "Container group is nil")
assert.Equal(t, podNamespace + "-" + podName, containerGroup, "Container group name is not expected")
assert.NotNil(t, cg.ContainerGroupProperties, "Container group properties should not be nil")
assert.NotNil(t, cg.ContainerGroupProperties.Containers, "Containers should not be nil")
assert.Equal(t, 1, len(cg.ContainerGroupProperties.Containers), "1 Container is expected")
assert.Equal(t, "nginx", cg.ContainerGroupProperties.Containers[0].Name, "Container nginx is expected")
assert.NotNil(t, cg.ContainerGroupProperties.Containers[0].Resources, "Container resources should not be nil")
assert.NotNil(t, cg.ContainerGroupProperties.Containers[0].Resources.Requests, "Container resource requests should not be nil")
assert.Equal(t, 1.98, cg.ContainerGroupProperties.Containers[0].Resources.Requests.CPU, "Request CPU is not expected")
assert.Equal(t, 3.4, cg.ContainerGroupProperties.Containers[0].Resources.Requests.MemoryInGB, "Request Memory is not expected")
assert.Equal(t, 3.999, cg.ContainerGroupProperties.Containers[0].Resources.Limits.CPU, "Limit CPU is not expected")
assert.Equal(t, 8.01, cg.ContainerGroupProperties.Containers[0].Resources.Limits.MemoryInGB, "Limit Memory is not expected")
return http.StatusOK, cg
}
pod := &v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: podName,
Namespace: podNamespace,
},
Spec: v1.PodSpec{
Containers: []v1.Container{
v1.Container{
Name: "nginx",
Resources: v1.ResourceRequirements{
Requests: v1.ResourceList{
"cpu": resource.MustParse("1.981"),
"memory": resource.MustParse("3.49G"),
},
Limits: v1.ResourceList{
"cpu": resource.MustParse("3999m"),

View File

@@ -107,11 +107,51 @@ func TestCreateContainerGroupFails(t *testing.T) {
},
})
if err == nil {
t.Fatal("expected create container group to fail with ResourceSomeRequestsNotSpecified, but returned nil")
t.Fatal("expected create container group to fail with ResourceRequestsNotSpecified, but returned nil")
}
if !strings.Contains(err.Error(), "ResourceSomeRequestsNotSpecified") {
t.Fatalf("expected ResourceSomeRequestsNotSpecified to be in the error message but got: %v", err)
if !strings.Contains(err.Error(), "ResourceRequestsNotSpecified") {
t.Fatalf("expected ResourceRequestsNotSpecified to be in the error message but got: %v", err)
}
}
func TestCreateContainerGroupWithoutResourceLimit(t *testing.T) {
cg, err := client.CreateContainerGroup(resourceGroup, containerGroup, ContainerGroup{
Location: location,
ContainerGroupProperties: ContainerGroupProperties{
OsType: Linux,
Containers: []Container{
{
Name: "nginx",
ContainerProperties: ContainerProperties{
Image: "nginx",
Command: []string{"nginx", "-g", "daemon off;"},
Ports: []ContainerPort{
{
Protocol: ContainerNetworkProtocolTCP,
Port: 80,
},
},
Resources: ResourceRequirements{
Requests: &ResourceRequests{
CPU: 1,
MemoryInGB: 1,
},
},
},
},
},
},
})
if err != nil {
t.Fatal(err)
}
if cg.Name != containerGroup {
t.Fatalf("resource group name is %s, expected %s", cg.Name, containerGroup)
}
if err := client.DeleteContainerGroup(resourceGroup, containerGroup); err != nil {
t.Fatal(err)
}
}
@@ -133,11 +173,11 @@ func TestCreateContainerGroup(t *testing.T) {
},
},
Resources: ResourceRequirements{
Requests: ResourceRequests{
Requests: &ResourceRequests{
CPU: 1,
MemoryInGB: 1,
},
Limits: ResourceLimits{
Limits: &ResourceLimits{
CPU: 1,
MemoryInGB: 1,
},

View File

@@ -236,8 +236,8 @@ type ResourceRequests struct {
// ResourceRequirements is the resource requirements.
type ResourceRequirements struct {
Requests ResourceRequests `json:"requests,omitempty"`
Limits ResourceLimits `json:"limits,omitempty"`
Requests *ResourceRequests `json:"requests,omitempty"`
Limits *ResourceLimits `json:"limits,omitempty"`
}
// Usage is a single usage result