@@ -46,15 +46,15 @@ func newTestSyncCtx(getResourceFunc *func(ctx context.Context, config *rest.Conf
4646 & metav1.APIResourceList {
4747 GroupVersion : "v1" ,
4848 APIResources : []metav1.APIResource {
49- {Kind : "Pod" , Group : "" , Version : "v1" , Namespaced : true , Verbs : standardVerbs },
50- {Kind : "Service" , Group : "" , Version : "v1" , Namespaced : true , Verbs : standardVerbs },
51- {Kind : "Namespace" , Group : "" , Version : "v1" , Namespaced : false , Verbs : standardVerbs },
49+ {Name : "pods" , Kind : "Pod" , Group : "" , Version : "v1" , Namespaced : true , Verbs : standardVerbs },
50+ {Name : "services" , Kind : "Service" , Group : "" , Version : "v1" , Namespaced : true , Verbs : standardVerbs },
51+ {Name : "namespaces" , Kind : "Namespace" , Group : "" , Version : "v1" , Namespaced : false , Verbs : standardVerbs },
5252 },
5353 },
5454 & metav1.APIResourceList {
5555 GroupVersion : "apps/v1" ,
5656 APIResources : []metav1.APIResource {
57- {Kind : "Deployment" , Group : "apps" , Version : "v1" , Namespaced : true , Verbs : standardVerbs },
57+ {Name : "deployments" , Kind : "Deployment" , Group : "apps" , Version : "v1" , Namespaced : true , Verbs : standardVerbs },
5858 },
5959 })
6060 sc := syncContext {
@@ -854,6 +854,39 @@ func withReplaceAndServerSideApplyAnnotations(un *unstructured.Unstructured) *un
854854 return un
855855}
856856
857+ func TestSync_HookWithReplaceAndBeforeHookCreation_AlreadyDeleted (t * testing.T ) {
858+ // This test a race condition when Delete is called on an already deleted object
859+ // LiveObj is set, but then the resource is deleted asynchronously in kubernetes
860+ syncCtx := newTestSyncCtx (nil )
861+
862+ target := withReplaceAnnotation (testingutils .NewPod ())
863+ target .SetNamespace (testingutils .FakeArgoCDNamespace )
864+ target = testingutils .Annotate (target , synccommon .AnnotationKeyHookDeletePolicy , string (synccommon .HookDeletePolicyBeforeHookCreation ))
865+ target = testingutils .Annotate (target , synccommon .AnnotationKeyHook , string (synccommon .SyncPhasePreSync ))
866+ live := target .DeepCopy ()
867+
868+ syncCtx .resources = groupResources (ReconciliationResult {
869+ Live : []* unstructured.Unstructured {live },
870+ Target : []* unstructured.Unstructured {target },
871+ })
872+ syncCtx .hooks = []* unstructured.Unstructured {live }
873+
874+ client := fake .NewSimpleDynamicClient (runtime .NewScheme ())
875+ deleted := false
876+ client .PrependReactor ("delete" , "pods" , func (_ testcore.Action ) (bool , runtime.Object , error ) {
877+ deleted = true
878+ // simulate the race conditions where liveObj was not null, but is now deleted in k8s
879+ return true , nil , apierrors .NewNotFound (corev1 .Resource ("pods" ), live .GetName ())
880+ })
881+ syncCtx .dynamicIf = client
882+
883+ syncCtx .Sync ()
884+
885+ resourceOps , _ := syncCtx .resourceOps .(* kubetest.MockResourceOps )
886+ assert .Equal (t , "create" , resourceOps .GetLastResourceCommand (kube .GetResourceKey (target )))
887+ assert .True (t , deleted )
888+ }
889+
857890func TestSync_ServerSideApply (t * testing.T ) {
858891 testCases := []struct {
859892 name string
0 commit comments