@@ -33,6 +33,7 @@ import (
3333 "k8s.io/apimachinery/pkg/util/wait"
3434 "k8s.io/client-go/dynamic"
3535 "k8s.io/kops/tests/e2e/scenarios/ai-conformance/testartifacts"
36+ "sigs.k8s.io/yaml"
3637
3738 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3839)
@@ -199,18 +200,57 @@ func (h *ValidatorHarness) TestNamespace() string {
199200
200201 startTime := time .Now ()
201202
203+ deploymentGVR := schema.GroupVersionResource {Group : "apps" , Version : "v1" , Resource : "deployments" }
204+
205+ // HACK: Clean up deployments before deleting the namespace, to work around an issue where GPU pods can get stuck terminating due to finalizers related to GPU resource cleanup.
206+ h .Logf ("Deleting deployments in namespace %q" , ns )
207+ deleteOptions := metav1.DeleteOptions {}
208+ gracePeriod := int64 (1 )
209+ deleteOptions .GracePeriodSeconds = & gracePeriod
210+ if err := h .DynamicClient ().Resource (deploymentGVR ).Namespace (ns ).DeleteCollection (ctx , deleteOptions , metav1.ListOptions {}); err != nil {
211+ h .Errorf ("failed to delete deployments in namespace %q: %v" , ns , err )
212+ }
213+
202214 h .Logf ("Deleting test namespace %q" , ns )
203215 if err := h .DynamicClient ().Resource (namespaceGVR ).Delete (ctx , ns , metav1.DeleteOptions {}); err != nil {
204216 h .Errorf ("failed to delete test namespace: %v" , err )
205217 }
206218
219+ // Wait for deployment deletion to complete.
220+ if err := wait .PollUntilContextTimeout (ctx , 2 * time .Second , 5 * time .Minute , false , func (ctx context.Context ) (done bool , err error ) {
221+ deploymentList , err := h .DynamicClient ().Resource (deploymentGVR ).Namespace (ns ).List (ctx , metav1.ListOptions {})
222+ if err != nil {
223+ return false , fmt .Errorf ("error checking for deployment deletion: %w" , err )
224+ }
225+ if len (deploymentList .Items ) == 0 {
226+ return true , nil
227+ }
228+ var names []string
229+ for _ , deployment := range deploymentList .Items {
230+ names = append (names , deployment .GetName ())
231+ }
232+ h .Logf ("Waiting for %d deployments to be deleted (%v)..." , len (deploymentList .Items ), names )
233+
234+ y , _ := yaml .Marshal (deploymentList )
235+ h .Logf ("Current deployments in namespace %q: %s" , ns , string (y ))
236+
237+ return false , nil
238+ }); err != nil {
239+ h .Errorf ("error waiting for deployment deletion: %v" , err )
240+ }
241+
207242 // Wait for namespace deletion to complete so that we don't have leftover namespaces consuming resources.
208243 if err := wait .PollUntilContextTimeout (ctx , 2 * time .Second , 5 * time .Minute , false , func (ctx context.Context ) (done bool , err error ) {
209- if _ , err := h .DynamicClient ().Resource (namespaceGVR ).Get (ctx , ns , metav1.GetOptions {}); err != nil {
244+ if ns , err := h .DynamicClient ().Resource (namespaceGVR ).Get (ctx , ns , metav1.GetOptions {}); err != nil {
210245 if apierrors .IsNotFound (err ) {
211246 return true , nil
212247 }
213248 return false , fmt .Errorf ("error checking for namespace deletion: %w" , err )
249+ } else {
250+ h .Logf ("Waiting for namespace %q to be deleted..." , ns )
251+
252+ y , _ := yaml .Marshal (ns )
253+ h .Logf ("Current state of namespace %q: %s" , ns , string (y ))
214254 }
215255 return false , nil
216256 }); err != nil {
0 commit comments