[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
|
// NOTE(robbiezhang): ACI CPU request must be times of 10m
|
||||||
cpuRequest := 1.00
|
cpuRequest := 1.00
|
||||||
if _, ok := container.Resources.Requests[v1.ResourceCPU]; ok {
|
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{
|
c.Resources = aci.ResourceRequirements{
|
||||||
Limits: aci.ResourceLimits{
|
Requests: &aci.ResourceRequests{
|
||||||
CPU: cpuLimit,
|
|
||||||
MemoryInGB: memoryLimit,
|
|
||||||
},
|
|
||||||
Requests: aci.ResourceRequests{
|
|
||||||
CPU: cpuRequest,
|
CPU: cpuRequest,
|
||||||
MemoryInGB: memoryRequest,
|
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)
|
containers = append(containers, c)
|
||||||
}
|
}
|
||||||
return containers, nil
|
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.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.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.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.Nil(t, cg.ContainerGroupProperties.Containers[0].Resources.Limits, "Limits should be nil")
|
||||||
assert.Equal(t, 1.5, cg.ContainerGroupProperties.Containers[0].Resources.Limits.MemoryInGB, "Limit Memory is not expected")
|
|
||||||
|
|
||||||
return http.StatusOK, cg
|
return http.StatusOK, cg
|
||||||
}
|
}
|
||||||
@@ -80,8 +79,8 @@ func TestCreatePodWithoutResourceSpec(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests create pod without resource spec
|
// Tests create pod with resource request only
|
||||||
func TestCreatePodWithResourceSpec(t *testing.T) {
|
func TestCreatePodWithResourceRequestOnly(t *testing.T) {
|
||||||
_, aciServerMocker, provider, err := prepareMocks()
|
_, aciServerMocker, provider, err := prepareMocks()
|
||||||
|
|
||||||
if err != nil {
|
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.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, 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.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.Nil(t, cg.ContainerGroupProperties.Containers[0].Resources.Limits, "Limits should be nil")
|
||||||
assert.Equal(t, 8.0, cg.ContainerGroupProperties.Containers[0].Resources.Limits.MemoryInGB, "Limit Memory is not expected")
|
|
||||||
|
|
||||||
return http.StatusOK, cg
|
return http.StatusOK, cg
|
||||||
}
|
}
|
||||||
@@ -121,8 +119,63 @@ func TestCreatePodWithResourceSpec(t *testing.T) {
|
|||||||
Name: "nginx",
|
Name: "nginx",
|
||||||
Resources: v1.ResourceRequirements{
|
Resources: v1.ResourceRequirements{
|
||||||
Requests: v1.ResourceList{
|
Requests: v1.ResourceList{
|
||||||
"cpu": resource.MustParse("1.98"),
|
"cpu": resource.MustParse("1.981"),
|
||||||
"memory": resource.MustParse("3.4G"),
|
"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{
|
Limits: v1.ResourceList{
|
||||||
"cpu": resource.MustParse("3999m"),
|
"cpu": resource.MustParse("3999m"),
|
||||||
|
|||||||
@@ -107,11 +107,51 @@ func TestCreateContainerGroupFails(t *testing.T) {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
if err == nil {
|
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") {
|
if !strings.Contains(err.Error(), "ResourceRequestsNotSpecified") {
|
||||||
t.Fatalf("expected ResourceSomeRequestsNotSpecified to be in the error message but got: %v", err)
|
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{
|
Resources: ResourceRequirements{
|
||||||
Requests: ResourceRequests{
|
Requests: &ResourceRequests{
|
||||||
CPU: 1,
|
CPU: 1,
|
||||||
MemoryInGB: 1,
|
MemoryInGB: 1,
|
||||||
},
|
},
|
||||||
Limits: ResourceLimits{
|
Limits: &ResourceLimits{
|
||||||
CPU: 1,
|
CPU: 1,
|
||||||
MemoryInGB: 1,
|
MemoryInGB: 1,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -236,8 +236,8 @@ type ResourceRequests struct {
|
|||||||
|
|
||||||
// ResourceRequirements is the resource requirements.
|
// ResourceRequirements is the resource requirements.
|
||||||
type ResourceRequirements struct {
|
type ResourceRequirements struct {
|
||||||
Requests ResourceRequests `json:"requests,omitempty"`
|
Requests *ResourceRequests `json:"requests,omitempty"`
|
||||||
Limits ResourceLimits `json:"limits,omitempty"`
|
Limits *ResourceLimits `json:"limits,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Usage is a single usage result
|
// Usage is a single usage result
|
||||||
|
|||||||
Reference in New Issue
Block a user