Skip to content

Commit

Permalink
pods will requeue for reconcile if nodes are not managed and requeste…
Browse files Browse the repository at this point in the history
…d eni (#463)

* pod will requeue for reconcile if nodes are not managed and requested eni

* log statement change

* looping through all container for eni requests

* adding ut for utils function
  • Loading branch information
yash97 authored Sep 12, 2024
1 parent 4ea11cb commit 80e7264
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 1 deletion.
5 changes: 5 additions & 0 deletions controllers/core/pod_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"github.com/aws/amazon-vpc-resource-controller-k8s/pkg/node"
"github.com/aws/amazon-vpc-resource-controller-k8s/pkg/node/manager"
"github.com/aws/amazon-vpc-resource-controller-k8s/pkg/resource"
"github.com/aws/amazon-vpc-resource-controller-k8s/pkg/utils"
"github.com/google/uuid"

"github.com/go-logr/logr"
Expand Down Expand Up @@ -112,6 +113,10 @@ func (r *PodReconciler) Reconcile(request custom.Request) (ctrl.Result, error) {
logger.V(1).Info("pod's node is not yet initialized by the manager, will retry", "Requested", request.NamespacedName.String(), "Cached pod name", pod.ObjectMeta.Name, "Cached pod namespace", pod.ObjectMeta.Namespace)
return PodRequeueRequest, nil
} else if !node.IsManaged() {
if utils.PodHasENIRequest(pod) {
r.Log.Info("pod's node is not managed, but has eni request, will retry", "Requested", request.NamespacedName.String(), "Cached pod name", pod.ObjectMeta.Name, "Cached pod namespace", pod.ObjectMeta.Namespace)
return PodRequeueRequest, nil
}
logger.V(1).Info("pod's node is not managed, skipping pod event", "Requested", request.NamespacedName.String(), "Cached pod name", pod.ObjectMeta.Name, "Cached pod namespace", pod.ObjectMeta.Namespace)
return ctrl.Result{}, nil
} else if !node.IsReady() {
Expand Down
3 changes: 2 additions & 1 deletion controllers/core/pod_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package controllers
import (
"errors"
"testing"
"time"

"github.com/aws/amazon-vpc-resource-controller-k8s/controllers/custom"
mock_condition "github.com/aws/amazon-vpc-resource-controller-k8s/mocks/amazon-vcp-resource-controller-k8s/pkg/condition"
Expand Down Expand Up @@ -188,7 +189,7 @@ func TestPodReconciler_Reconcile_NonManaged(t *testing.T) {

result, err := mock.PodReconciler.Reconcile(mockReq)
assert.NoError(t, err)
assert.Equal(t, result, controllerruntime.Result{})
assert.Equal(t, controllerruntime.Result{Requeue: true, RequeueAfter: time.Second}, result)
}

// TestPodReconciler_Reconcile_NoNodeAssigned tests that the request for a Pod with no Node assigned
Expand Down
16 changes: 16 additions & 0 deletions pkg/utils/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,13 @@ import (

vpcresourcesv1beta1 "github.com/aws/amazon-vpc-resource-controller-k8s/apis/vpcresources/v1beta1"
"github.com/aws/amazon-vpc-resource-controller-k8s/pkg/aws/vpc"
"github.com/aws/amazon-vpc-resource-controller-k8s/pkg/config"

"github.com/aws/aws-sdk-go/aws/arn"

"github.com/go-logr/logr"
corev1 "k8s.io/api/core/v1"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
Expand Down Expand Up @@ -232,3 +234,17 @@ func GetSourceAcctAndArn(roleARN, region, clusterName string) (string, string, s
sourceArn := fmt.Sprintf("arn:%s:eks:%s:%s:cluster/%s", parsedArn.Partition, region, parsedArn.AccountID, clusterName)
return parsedArn.AccountID, parsedArn.Partition, sourceArn, nil
}

// PodHasENIRequest will return true if first container of pod spec has request for eni indicating
// it needs trunk interface from vpc-rc
func PodHasENIRequest(pod *v1.Pod) bool {
if pod == nil {
return false
}
for _, container := range pod.Spec.Containers {
if _, hasEniRequest := container.Resources.Requests[config.ResourceNamePodENI]; hasEniRequest {
return true
}
}
return false
}
100 changes: 100 additions & 0 deletions pkg/utils/helper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,12 @@ import (

"github.com/samber/lo"
"github.com/stretchr/testify/assert"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

vpcresourcesv1beta1 "github.com/aws/amazon-vpc-resource-controller-k8s/apis/vpcresources/v1beta1"
"github.com/aws/amazon-vpc-resource-controller-k8s/pkg/config"
)

// TestRemoveDuplicatedSg tests if RemoveDuplicatedSg func works as expected.
Expand Down Expand Up @@ -579,3 +582,100 @@ func TestGetSourceAcctAndArn_NoRegion(t *testing.T) {
assert.Equal(t, "", part, "correct partiton should be retrieved")

}

func TestPodHasENIRequest(t *testing.T) {
tests := []struct {
name string
pod *v1.Pod
expected bool
}{
{
name: "Pod with ENI request in first container",
pod: &v1.Pod{
Spec: v1.PodSpec{
Containers: []v1.Container{
{
Resources: v1.ResourceRequirements{
Requests: v1.ResourceList{
config.ResourceNamePodENI: resource.MustParse("1"),
},
},
},
},
},
},
expected: true,
},
{
name: "Pod with multiple containers, no ENI request",
pod: &v1.Pod{
Spec: v1.PodSpec{
Containers: []v1.Container{
{
Resources: v1.ResourceRequirements{
Requests: v1.ResourceList{
v1.ResourceCPU: resource.MustParse("100m"),
},
},
},
{
Resources: v1.ResourceRequirements{
Requests: v1.ResourceList{
v1.ResourceMemory: resource.MustParse("128Mi"),
},
},
},
{
Resources: v1.ResourceRequirements{
Requests: v1.ResourceList{
v1.ResourceStorage: resource.MustParse("1Gi"),
},
},
},
},
},
},
expected: false,
},
{
name: "Pod without ENI request",
pod: &v1.Pod{
Spec: v1.PodSpec{
Containers: []v1.Container{
{
Resources: v1.ResourceRequirements{
Requests: v1.ResourceList{
v1.ResourceCPU: resource.MustParse("100m"),
},
},
},
},
},
},
expected: false,
},
{
name: "Pod with empty containers",
pod: &v1.Pod{
Spec: v1.PodSpec{
Containers: []v1.Container{},
},
},
expected: false,
},
{
name: "Nil pod",
pod: nil,
expected: false,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := PodHasENIRequest(tt.pod)
if result != tt.expected {
t.Errorf("PodHasENIRequest() = %v, want %v", result, tt.expected)
}
})
}
}

0 comments on commit 80e7264

Please sign in to comment.