@@ -45,15 +45,15 @@ func newTestSyncCtx(getResourceFunc *func(ctx context.Context, config *rest.Conf
4545 & metav1.APIResourceList {
4646 GroupVersion : "v1" ,
4747 APIResources : []metav1.APIResource {
48- {Kind : "Pod" , Group : "" , Version : "v1" , Namespaced : true , Verbs : standardVerbs },
49- {Kind : "Service" , Group : "" , Version : "v1" , Namespaced : true , Verbs : standardVerbs },
50- {Kind : "Namespace" , Group : "" , Version : "v1" , Namespaced : false , Verbs : standardVerbs },
48+ {Name : "pods" , Kind : "Pod" , Group : "" , Version : "v1" , Namespaced : true , Verbs : standardVerbs },
49+ {Name : "services" , Kind : "Service" , Group : "" , Version : "v1" , Namespaced : true , Verbs : standardVerbs },
50+ {Name : "namespaces" , Kind : "Namespace" , Group : "" , Version : "v1" , Namespaced : false , Verbs : standardVerbs },
5151 },
5252 },
5353 & metav1.APIResourceList {
5454 GroupVersion : "apps/v1" ,
5555 APIResources : []metav1.APIResource {
56- {Kind : "Deployment" , Group : "apps" , Version : "v1" , Namespaced : true , Verbs : standardVerbs },
56+ {Name : "deployments" , Kind : "Deployment" , Group : "apps" , Version : "v1" , Namespaced : true , Verbs : standardVerbs },
5757 },
5858 })
5959 sc := syncContext {
@@ -807,6 +807,39 @@ func withReplaceAndServerSideApplyAnnotations(un *unstructured.Unstructured) *un
807807 return un
808808}
809809
810+ func TestSync_HookWithReplaceAndBeforeHookCreation_AlreadyDeleted (t * testing.T ) {
811+ // This test a race condition when Delete is called on an already deleted object
812+ // LiveObj is set, but then the resource is deleted asynchronously in kubernetes
813+ syncCtx := newTestSyncCtx (nil )
814+
815+ target := withReplaceAnnotation (testingutils .NewPod ())
816+ target .SetNamespace (testingutils .FakeArgoCDNamespace )
817+ target = testingutils .Annotate (target , synccommon .AnnotationKeyHookDeletePolicy , string (synccommon .HookDeletePolicyBeforeHookCreation ))
818+ target = testingutils .Annotate (target , synccommon .AnnotationKeyHook , string (synccommon .SyncPhasePreSync ))
819+ live := target .DeepCopy ()
820+
821+ syncCtx .resources = groupResources (ReconciliationResult {
822+ Live : []* unstructured.Unstructured {live },
823+ Target : []* unstructured.Unstructured {target },
824+ })
825+ syncCtx .hooks = []* unstructured.Unstructured {live }
826+
827+ client := fake .NewSimpleDynamicClient (runtime .NewScheme ())
828+ deleted := false
829+ client .PrependReactor ("delete" , "pods" , func (_ testcore.Action ) (bool , runtime.Object , error ) {
830+ deleted = true
831+ // simulate the race conditions where liveObj was not null, but is now deleted in k8s
832+ return true , nil , apierrors .NewNotFound (corev1 .Resource ("pods" ), live .GetName ())
833+ })
834+ syncCtx .dynamicIf = client
835+
836+ syncCtx .Sync ()
837+
838+ resourceOps , _ := syncCtx .resourceOps .(* kubetest.MockResourceOps )
839+ assert .Equal (t , "create" , resourceOps .GetLastResourceCommand (kube .GetResourceKey (target )))
840+ assert .True (t , deleted )
841+ }
842+
810843func TestSync_ServerSideApply (t * testing.T ) {
811844 testCases := []struct {
812845 name string
0 commit comments