@@ -1222,6 +1222,37 @@ def test_flavor_unset_with_unexist_flavor(self):
12221222 exceptions .CommandError , self .cmd .take_action , parsed_args
12231223 )
12241224
1225+ def test_flavor_unset_project_deleted_project (self ):
1226+ # Simulate a project that has been deleted from Keystone
1227+ self .identity_sdk_client .find_project .side_effect = [
1228+ sdk_exceptions .ResourceNotFound ()
1229+ ]
1230+
1231+ deleted_project_id = 'deleted-project-uuid'
1232+ arglist = [
1233+ '--project' ,
1234+ deleted_project_id ,
1235+ self .flavor .id ,
1236+ ]
1237+ verifylist = [
1238+ ('project' , deleted_project_id ),
1239+ ('flavor' , self .flavor .id ),
1240+ ]
1241+ parsed_args = self .check_parser (self .cmd , arglist , verifylist )
1242+
1243+ # TODO(bug #2099702): This should succeed. When removing a project
1244+ # from a flavor's access list, the project may no longer exist in
1245+ # Keystone (deleted tenant). The command should pass the raw project
1246+ # ID through to Nova's removeTenantAccess API, which already handles
1247+ # this case since the fix for bug #1980845. Instead, the command
1248+ # fails because find_project_id_sdk() validates the project against
1249+ # Keystone with validate_actor_existence=True (the default) and
1250+ # raises CommandError when it doesn't exist.
1251+ self .assertRaises (
1252+ exceptions .CommandError , self .cmd .take_action , parsed_args
1253+ )
1254+ self .compute_client .flavor_remove_tenant_access .assert_not_called ()
1255+
12251256 def test_flavor_unset_nothing (self ):
12261257 arglist = [
12271258 self .flavor .id ,
0 commit comments