@@ -86,7 +86,7 @@ func (cs *commandService) CreateConnection(
8686 podName := resource .GetContainerInfo ().GetHostname ()
8787 cs .logger .Info (fmt .Sprintf ("Creating connection for nginx pod: %s" , podName ))
8888
89- owner , err := cs .getPodOwner (podName )
89+ owner , _ , err := cs .getPodOwner (podName )
9090 if err != nil {
9191 response := & pb.CreateConnectionResponse {
9292 Response : & pb.CommandResponse {
@@ -281,6 +281,17 @@ func (cs *commandService) setInitialConfig(
281281 deployment .FileLock .Lock ()
282282 defer deployment .FileLock .Unlock ()
283283
284+ _ , pod , err := cs .getPodOwner (conn .PodName )
285+ if err != nil {
286+ cs .logAndSendErrorStatus (deployment , conn , err )
287+
288+ return grpcStatus .Error (codes .Internal , err .Error ())
289+ }
290+ if err := cs .validatePodImageVersion (pod , deployment .imageVersion ); err != nil {
291+ cs .logAndSendErrorStatus (deployment , conn , err )
292+ return grpcStatus .Errorf (codes .FailedPrecondition , "nginx image version validation failed: %s" , err .Error ())
293+ }
294+
284295 fileOverviews , configVersion := deployment .GetFileOverviews ()
285296
286297 cs .logger .Info ("Sending initial configuration to agent" , "pod" , conn .PodName , "configVersion" , configVersion )
@@ -443,7 +454,7 @@ func buildPlusAPIRequest(action *pb.NGINXPlusAction, instanceID string) *pb.Mana
443454 }
444455}
445456
446- func (cs * commandService ) getPodOwner (podName string ) (types.NamespacedName , error ) {
457+ func (cs * commandService ) getPodOwner (podName string ) (types.NamespacedName , * v1. Pod , error ) {
447458 ctx , cancel := context .WithTimeout (context .Background (), 30 * time .Second )
448459 defer cancel ()
449460
@@ -452,30 +463,31 @@ func (cs *commandService) getPodOwner(podName string) (types.NamespacedName, err
452463 FieldSelector : fields .SelectorFromSet (fields.Set {"metadata.name" : podName }),
453464 }
454465 if err := cs .k8sReader .List (ctx , & pods , listOpts ); err != nil {
455- return types.NamespacedName {}, fmt .Errorf ("error listing pods: %w" , err )
466+ return types.NamespacedName {}, nil , fmt .Errorf ("error listing pods: %w" , err )
456467 }
457468
458469 if len (pods .Items ) == 0 {
459- return types.NamespacedName {}, fmt .Errorf ("no pods found with name %q" , podName )
470+ return types.NamespacedName {}, nil , fmt .Errorf ("no pods found with name %q" , podName )
460471 }
461472
462473 if len (pods .Items ) > 1 {
463- return types.NamespacedName {}, fmt .Errorf ("should only be one pod with name %q" , podName )
474+ return types.NamespacedName {}, nil , fmt .Errorf ("should only be one pod with name %q" , podName )
464475 }
465- pod := pods .Items [0 ]
476+ pod := & pods .Items [0 ]
466477
467478 podOwnerRefs := pod .GetOwnerReferences ()
468479 if len (podOwnerRefs ) != 1 {
469- return types.NamespacedName {}, fmt .Errorf ("expected one owner reference of the nginx Pod, got %d" , len (podOwnerRefs ))
480+ tooManyOwnersError := "expected one owner reference of the nginx Pod, got %d"
481+ return types.NamespacedName {}, nil , fmt .Errorf (tooManyOwnersError , len (podOwnerRefs ))
470482 }
471483
472484 if podOwnerRefs [0 ].Kind != "ReplicaSet" && podOwnerRefs [0 ].Kind != "DaemonSet" {
473485 err := fmt .Errorf ("expected pod owner reference to be ReplicaSet or DaemonSet, got %s" , podOwnerRefs [0 ].Kind )
474- return types.NamespacedName {}, err
486+ return types.NamespacedName {}, nil , err
475487 }
476488
477489 if podOwnerRefs [0 ].Kind == "DaemonSet" {
478- return types.NamespacedName {Namespace : pod .Namespace , Name : podOwnerRefs [0 ].Name }, nil
490+ return types.NamespacedName {Namespace : pod .Namespace , Name : podOwnerRefs [0 ].Name }, pod , nil
479491 }
480492
481493 var replicaSet appsv1.ReplicaSet
@@ -497,16 +509,49 @@ func (cs *commandService) getPodOwner(podName string) (types.NamespacedName, err
497509 return true , nil
498510 },
499511 ); err != nil {
500- return types.NamespacedName {}, fmt .Errorf ("failed to get nginx Pod's ReplicaSet: %w" , replicaSetErr )
512+ return types.NamespacedName {}, nil , fmt .Errorf ("failed to get nginx Pod's ReplicaSet: %w" , replicaSetErr )
501513 }
502514
503515 replicaOwnerRefs := replicaSet .GetOwnerReferences ()
504516 if len (replicaOwnerRefs ) != 1 {
505517 err := fmt .Errorf ("expected one owner reference of the nginx ReplicaSet, got %d" , len (replicaOwnerRefs ))
506- return types.NamespacedName {}, err
518+ return types.NamespacedName {}, nil , err
507519 }
508520
509- return types.NamespacedName {Namespace : pod .Namespace , Name : replicaOwnerRefs [0 ].Name }, nil
521+ return types.NamespacedName {Namespace : pod .Namespace , Name : replicaOwnerRefs [0 ].Name }, pod , nil
522+ }
523+
524+ // validatePodImageVersion checks if the pod's nginx container image version matches the expected version
525+ // from its deployment. Returns an error if versions don't match.
526+ func (cs * commandService ) validatePodImageVersion (
527+ pod * v1.Pod ,
528+ expectedImage string ,
529+ ) error {
530+ findNginxContainerImage := func (containers []v1.Container ) string {
531+ for _ , container := range containers {
532+ if container .Name == "nginx" {
533+ return container .Image
534+ }
535+ }
536+ return ""
537+ }
538+
539+ // Find the nginx container in the pod
540+ podNginxImage := findNginxContainerImage (pod .Spec .Containers )
541+ if podNginxImage == "" {
542+ return fmt .Errorf ("nginx container not found in pod %q" , pod .Name )
543+ }
544+
545+ // Compare images
546+ if podNginxImage != expectedImage {
547+ return fmt .Errorf ("nginx image version mismatch: pod has %q but expected %q" , podNginxImage , expectedImage )
548+ }
549+
550+ cs .logger .V (1 ).Info ("Pod nginx image version validated successfully" ,
551+ "podName" , pod .Name ,
552+ "image" , podNginxImage )
553+
554+ return nil
510555}
511556
512557// UpdateDataPlaneStatus is called by agent on startup and upon any change in agent metadata,
0 commit comments