[Azure] Make Resoures.Limits Optional (#175)
* Make Resources.Limits Optional * Remove the accuracy check of the resources.limits
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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"),
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user