From 0f59ade291becbdaa05c851e01d572e1249073ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20JACQUES?= Date: Mon, 5 Jun 2023 22:18:34 +0200 Subject: [PATCH] fix: container state. (#547) Co-authored-by: JACQUES Francois --- pkg/provider/aci.go | 7 ++++ pkg/provider/aci_init_container_test.go | 22 ++++++++++++ pkg/provider/aci_test.go | 21 +++++++++++ pkg/provider/containergroup_to_pod.go | 8 +++-- pkg/provider/containergroup_to_pod_test.go | 42 +++++++++++++++------- 5 files changed, 85 insertions(+), 15 deletions(-) diff --git a/pkg/provider/aci.go b/pkg/provider/aci.go index fb3835cc..0776feb3 100644 --- a/pkg/provider/aci.go +++ b/pkg/provider/aci.go @@ -1090,6 +1090,10 @@ func (p *ACIProvider) getInitContainers(ctx context.Context, pod *v1.Pod) ([]*az if hasLifecycleHook(initContainer) { log.G(ctx).Errorf("azure container instances initcontainers do not support lifecycle hooks") return nil, errdefs.InvalidInput("azure container instances initContainers do not support lifecycle hooks") + } + if initContainer.StartupProbe != nil { + log.G(ctx).Errorf("azure container instances initcontainers do not support startupProbe") + return nil, errdefs.InvalidInput("azure container instances initContainers do not support startupProbe") } newInitContainer := azaciv2.InitContainerDefinition{ @@ -1118,6 +1122,9 @@ func (p *ACIProvider) getContainers(pod *v1.Pod) ([]*azaciv2.Container, error) { } if hasLifecycleHook(podContainers[c]) { return nil, errdefs.InvalidInput("ACI does not support lifecycle hooks") + } + if podContainers[c].StartupProbe != nil { + return nil, errdefs.InvalidInput("ACI does not support startupProbe") } cmd := p.getCommand(podContainers[c]) ports := make([]*azaciv2.ContainerPort, 0, len(podContainers[c].Ports)) diff --git a/pkg/provider/aci_init_container_test.go b/pkg/provider/aci_init_container_test.go index 64bed9b5..114d4b34 100644 --- a/pkg/provider/aci_init_container_test.go +++ b/pkg/provider/aci_init_container_test.go @@ -188,6 +188,28 @@ func TestCreatePodWithInitContainers(t *testing.T) { }, expectedError: errdefs.InvalidInput("azure container instances initContainers do not support lifecycle hooks"), }, + { + description: "Init Containers with startup probe", + initContainers: []v1.Container{ + v1.Container{ + Name: "initContainer 01", + StartupProbe: &v1.Probe{ + ProbeHandler: v1.ProbeHandler{ + HTTPGet: &v1.HTTPGetAction{ + Port: intstr.FromInt(8080), + Path: "/", + }, + }, + InitialDelaySeconds: 10, + PeriodSeconds: 5, + TimeoutSeconds: 60, + SuccessThreshold: 3, + FailureThreshold: 5, + }, + }, + }, + expectedError: errdefs.InvalidInput("azure container instances initContainers do not support startupProbe"), + }, } for _, tc := range cases { t.Run(tc.description, func(t *testing.T) { diff --git a/pkg/provider/aci_test.go b/pkg/provider/aci_test.go index 58e2c62a..e8e11008 100644 --- a/pkg/provider/aci_test.go +++ b/pkg/provider/aci_test.go @@ -994,6 +994,27 @@ func TestCreatePodWithReadinessProbe(t *testing.T) { } } +func TestCreatePodWithStartupProbe(t *testing.T) { + podName := "pod-" + uuid.New().String() + podNamespace := "ns-" + uuid.New().String() + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + aciMocks := createNewACIMock() + + pod := testsutil.CreatePodObj(podName, podNamespace) + pod.Spec.Containers[0].StartupProbe = &corev1.Probe{} + + provider, err := createTestProvider(aciMocks, NewMockConfigMapLister(mockCtrl), + NewMockSecretLister(mockCtrl), NewMockPodLister(mockCtrl), nil) + if err != nil { + t.Fatal("failed to create the test provider", err) + } + + err = provider.CreatePod(context.Background(), pod) + assert.Check(t, err != nil, "Should fail creating pod with startup probe") +} + func TestCreatedPodWithContainerPort(t *testing.T) { port4040 := int32(4040) port5050 := int32(5050) diff --git a/pkg/provider/containergroup_to_pod.go b/pkg/provider/containergroup_to_pod.go index 000fe347..a9b354d8 100644 --- a/pkg/provider/containergroup_to_pod.go +++ b/pkg/provider/containergroup_to_pod.go @@ -65,12 +65,14 @@ func (p *ACIProvider) getPodStatusFromContainerGroup(ctx context.Context, cg *az firstContainerStartTime = *containersList[0].Properties.InstanceView.CurrentState.StartTime lastUpdateTime = firstContainerStartTime } - + containerState := aciContainerStateToContainerState(containersList[i].Properties.InstanceView.CurrentState) + started := containerState.Running != nil containerStatus := v1.ContainerStatus{ Name: *containersList[i].Name, - State: aciContainerStateToContainerState(containersList[i].Properties.InstanceView.CurrentState), + State: containerState, LastTerminationState: aciContainerStateToContainerState(containersList[i].Properties.InstanceView.PreviousState), Ready: getPodPhaseFromACIState(*containersList[i].Properties.InstanceView.CurrentState.State) == v1.PodRunning, + Started: &started, RestartCount: *containersList[i].Properties.InstanceView.RestartCount, Image: *containersList[i].Properties.Image, ImageID: "", @@ -131,7 +133,7 @@ func aciContainerStateToContainerState(cs *azaciv2.ContainerState) v1.ContainerS }, } // Handle the case of completion. - case "Succeeded": + case "Succeeded", "Terminated": return v1.ContainerState{ Terminated: &v1.ContainerStateTerminated{ StartedAt: metav1.NewTime(startTime), diff --git a/pkg/provider/containergroup_to_pod_test.go b/pkg/provider/containergroup_to_pod_test.go index 0ca66c21..acf9663f 100644 --- a/pkg/provider/containergroup_to_pod_test.go +++ b/pkg/provider/containergroup_to_pod_test.go @@ -6,6 +6,8 @@ package provider import ( "context" + "fmt" + "reflect" "testing" "time" @@ -34,22 +36,36 @@ func TestContainerGroupToPodStatus(t *testing.T) { t.Fatal("failed to create the test provider", err) } cases := []struct { - description string - containerGroup *azaciv2.ContainerGroup - expectedPodPhase v1.PodPhase - expectedPodConditions []v1.PodCondition + description string + containerGroup *azaciv2.ContainerGroup + expectedPodPhase v1.PodPhase + expectedPodConditions []v1.PodCondition + expectedContainerState string + expectedContainerStarted bool }{ { - description: "Container is Running/Succeeded", - containerGroup: testutil.CreateContainerGroupObj(cgName, cgName, "Succeeded", testutil.CreateACIContainersListObj("Running", "Initializing", startTime, finishTime, false, false, false), "Succeeded"), - expectedPodPhase: getPodPhaseFromACIState("Succeeded"), - expectedPodConditions: testutil.GetPodConditions(metav1.NewTime(cgCreationTime), metav1.NewTime(finishTime), v1.ConditionTrue), + description: "Container is Running/Succeeded", + containerGroup: testutil.CreateContainerGroupObj(cgName, cgName, "Succeeded", testutil.CreateACIContainersListObj("Running", "Initializing", startTime, finishTime, false, false, false), "Succeeded"), + expectedPodPhase: getPodPhaseFromACIState("Succeeded"), + expectedPodConditions: testutil.GetPodConditions(metav1.NewTime(cgCreationTime), metav1.NewTime(finishTime), v1.ConditionTrue), + expectedContainerState: "Running", + expectedContainerStarted: true, }, { - description: "Container Failed", - containerGroup: testutil.CreateContainerGroupObj(cgName, cgName, "Failed", testutil.CreateACIContainersListObj("Failed", "Running", startTime, finishTime, false, false, false), "Succeeded"), - expectedPodPhase: getPodPhaseFromACIState("Failed"), - expectedPodConditions: []v1.PodCondition{}, + description: "Container is Terminated/Succeeded", + containerGroup: testutil.CreateContainerGroupObj(cgName, cgName, "Succeeded", testutil.CreateACIContainersListObj("Terminated", "Initializing", startTime, finishTime, false, false, false), "Succeeded"), + expectedPodPhase: getPodPhaseFromACIState("Succeeded"), + expectedPodConditions: testutil.GetPodConditions(metav1.NewTime(cgCreationTime), metav1.NewTime(finishTime), v1.ConditionTrue), + expectedContainerState: "Terminated", + expectedContainerStarted: false, + }, + { + description: "Container Failed", + containerGroup: testutil.CreateContainerGroupObj(cgName, cgName, "Failed", testutil.CreateACIContainersListObj("Failed", "Running", startTime, finishTime, false, false, false), "Succeeded"), + expectedPodPhase: getPodPhaseFromACIState("Failed"), + expectedPodConditions: []v1.PodCondition{}, + expectedContainerState: "Terminated", + expectedContainerStarted: false, }, } for _, tc := range cases { @@ -58,6 +74,8 @@ func TestContainerGroupToPodStatus(t *testing.T) { assert.NilError(t, err, "no errors should be returned") assert.Equal(t, tc.expectedPodPhase, expectedStatus.Phase, "Pod phase is not as expected as current container group phase") assert.Equal(t, len(tc.expectedPodConditions), len(expectedStatus.Conditions), "Pod conditions are not as expected") + assert.Equal(t, tc.expectedContainerStarted, *expectedStatus.ContainerStatuses[0].Started, "Container should be started") + assert.Check(t, !reflect.ValueOf(expectedStatus.ContainerStatuses[0].State).FieldByName(tc.expectedContainerState).IsNil(), fmt.Sprintf("Container state should be %s", tc.expectedContainerState)) }) } }