Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

{Core} Add random_config_dir param in DummyCli #25689

Merged
merged 13 commits into from
Apr 13, 2023
Merged

Conversation

bebound
Copy link
Contributor

@bebound bebound commented Mar 6, 2023

Description

ARM64 machines are multi-core, and some errors occur because of concurrency, as all tests use same config dir.

I add a random_config_dir param in DummyCli. If it is True, the config dir will be ~/.azure/dummy_cli_config_dir/xxxxxxx.

If random config is enabled by default, the config file is created for each test, and the performance decrease a lot.
Azure.azure-cli Full Test spends 24 min instead of 16min.

I enable random_config_dir for the tests which use az config or az configure.
Example usage:

class ConfigTest(ScenarioTest):

    def __init__(self, *arg, **kwargs):
        super().__init__(*arg, random_config_dir=True, **kwargs)
2023-03-03T11:05:05.5590254Z [gw2] [ 65%] FAILED tests/test_cloud.py::TestCloud::test_remove_known_cloud 
2023-03-03T11:05:05.5590455Z 
2023-03-03T11:05:05.5590884Z =================================== FAILURES ===================================
2023-03-03T11:05:05.5591177Z ______________________ TestCloud.test_remove_known_cloud _______________________
2023-03-03T11:05:05.5592042Z [gw2] linux -- Python 3.10.10 /opt/az/bin/python3
2023-03-03T11:05:05.5592295Z self = <core.tests.test_cloud.TestCloud testMethod=test_remove_known_cloud>
2023-03-03T11:05:05.5592422Z 
2023-03-03T11:05:05.5592577Z     def test_remove_known_cloud(self):
2023-03-03T11:05:05.5592756Z >       cli = DummyCli()
2023-03-03T11:05:05.5592824Z 
2023-03-03T11:05:05.5593120Z /opt/az/lib/python3.10/site-packages/azure/cli/core/tests/test_cloud.py:216: 
2023-03-03T11:05:05.5593362Z _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
2023-03-03T11:05:05.5593706Z /opt/az/lib/python3.10/site-packages/azure/cli/core/mock.py:25: in __init__
2023-03-03T11:05:05.5593932Z     super(DummyCli, self).__init__(
2023-03-03T11:05:05.5594263Z /opt/az/lib/python3.10/site-packages/azure/cli/core/__init__.py:59: in __init__
2023-03-03T11:05:05.5594502Z     super(AzCli, self).__init__(**kwargs)
2023-03-03T11:05:05.5594818Z /opt/az/lib/python3.10/site-packages/knack/cli.py:82: in __init__
2023-03-03T11:05:05.5595028Z     self.config = config_cls(
2023-03-03T11:05:05.5595524Z /opt/az/lib/python3.10/site-packages/knack/config.py:75: in __init__
2023-03-03T11:05:05.5595793Z     self._config_file_chain.append(_ConfigFile(self.config_dir, self.config_path))
2023-03-03T11:05:05.5596156Z /opt/az/lib/python3.10/site-packages/knack/config.py:195: in __init__
2023-03-03T11:05:05.5596418Z     self.config_parser.read(config_path, encoding=CONFIG_FILE_ENCODING)
2023-03-03T11:05:05.5596652Z /opt/az/lib/python3.10/configparser.py:699: in read
2023-03-03T11:05:05.5596854Z     self._read(fp, filename)
2023-03-03T11:05:05.5597051Z _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
2023-03-03T11:05:05.5597146Z 
2023-03-03T11:05:05.5597321Z self = <configparser.ConfigParser object at 0xffff9808a770>
2023-03-03T11:05:05.5597664Z fp = <_io.TextIOWrapper name='/root/.azure/config' mode='r' encoding='utf-8'>
2023-03-03T11:05:05.5597957Z fpname = '/root/.azure/config'
2023-03-03T11:05:05.5598040Z 
2023-03-03T11:05:05.5598203Z     def _read(self, fp, fpname):
2023-03-03T11:05:05.5598387Z         """Parse a sectioned configuration file.
2023-03-03T11:05:05.5598554Z     
2023-03-03T11:05:05.5598736Z         Each section in a configuration file contains a header, indicated by
2023-03-03T11:05:05.5598980Z         a name in square brackets (`[]`), plus key/value options, indicated by
2023-03-03T11:05:05.5599218Z         `name` and `value` delimited with a specific substring (`=` or `:` by
2023-03-03T11:05:05.5599400Z         default).
2023-03-03T11:05:05.5599542Z     
2023-03-03T11:05:05.5599721Z         Values can span multiple lines, as long as they are indented deeper
2023-03-03T11:05:05.5600070Z         than the first line of the value. Depending on the parser's mode, blank
2023-03-03T11:05:05.5600312Z         lines may be treated as parts of multiline values or ignored.
2023-03-03T11:05:05.5600485Z     
2023-03-03T11:05:05.5600673Z         Configuration files may include comments, prefixed by specific
2023-03-03T11:05:05.5600918Z         characters (`#` and `;` by default). Comments may appear on their own
2023-03-03T11:05:05.5601152Z         in an otherwise empty line or may be entered in lines holding values or
2023-03-03T11:05:05.5601417Z         section names. Please note that comments get stripped off when reading configuration files.
2023-03-03T11:05:05.5601624Z         """
2023-03-03T11:05:05.5601770Z         elements_added = set()
2023-03-03T11:05:05.5601956Z         cursect = None                        # None, or a dictionary
2023-03-03T11:05:05.5602124Z         sectname = None
2023-03-03T11:05:05.5602282Z         optname = None
2023-03-03T11:05:05.5602434Z         lineno = 0
2023-03-03T11:05:05.5602582Z         indent_level = 0
2023-03-03T11:05:05.5602759Z         e = None                              # None, or an exception
2023-03-03T11:05:05.5602950Z         for lineno, line in enumerate(fp, start=1):
2023-03-03T11:05:05.5603141Z             comment_start = sys.maxsize
2023-03-03T11:05:05.5603465Z             # strip inline comments
2023-03-03T11:05:05.5603763Z             inline_prefixes = {p: -1 for p in self._inline_comment_prefixes}
2023-03-03T11:05:05.5604005Z             while comment_start == sys.maxsize and inline_prefixes:
2023-03-03T11:05:05.5604200Z                 next_prefixes = {}
2023-03-03T11:05:05.5604382Z                 for prefix, index in inline_prefixes.items():
2023-03-03T11:05:05.5604589Z                     index = line.find(prefix, index+1)
2023-03-03T11:05:05.5604760Z                     if index == -1:
2023-03-03T11:05:05.5604914Z                         continue
2023-03-03T11:05:05.5605086Z                     next_prefixes[prefix] = index
2023-03-03T11:05:05.5605373Z                     if index == 0 or (index > 0 and line[index-1].isspace()):
2023-03-03T11:05:05.5605592Z                         comment_start = min(comment_start, index)
2023-03-03T11:05:05.5605797Z                 inline_prefixes = next_prefixes
2023-03-03T11:05:05.5605976Z             # strip full line comments
2023-03-03T11:05:05.5606312Z             for prefix in self._comment_prefixes:
2023-03-03T11:05:05.5606506Z                 if line.strip().startswith(prefix):
2023-03-03T11:05:05.5606686Z                     comment_start = 0
2023-03-03T11:05:05.5606840Z                     break
2023-03-03T11:05:05.5607001Z             if comment_start == sys.maxsize:
2023-03-03T11:05:05.5607180Z                 comment_start = None
2023-03-03T11:05:05.5607376Z             value = line[:comment_start].strip()
2023-03-03T11:05:05.5607552Z             if not value:
2023-03-03T11:05:05.5607730Z                 if self._empty_lines_in_values:
2023-03-03T11:05:05.5607927Z                     # add empty line to the value, but only if there was no
2023-03-03T11:05:05.5608119Z                     # comment on the line
2023-03-03T11:05:05.5608294Z                     if (comment_start is None and
2023-03-03T11:05:05.5608466Z                         cursect is not None and
2023-03-03T11:05:05.5608632Z                         optname and
2023-03-03T11:05:05.5608798Z                         cursect[optname] is not None):
2023-03-03T11:05:05.5609098Z                         cursect[optname].append('') # newlines added at join
2023-03-03T11:05:05.5609286Z                 else:
2023-03-03T11:05:05.5609444Z                     # empty line marks end of value
2023-03-03T11:05:05.5609627Z                     indent_level = sys.maxsize
2023-03-03T11:05:05.5609790Z                 continue
2023-03-03T11:05:05.5609940Z             # continuation line?
2023-03-03T11:05:05.5610134Z             first_nonspace = self.NONSPACECRE.search(line)
2023-03-03T11:05:05.5610360Z             cur_indent_level = first_nonspace.start() if first_nonspace else 0
2023-03-03T11:05:05.5610584Z             if (cursect is not None and optname and
2023-03-03T11:05:05.5610779Z                 cur_indent_level > indent_level):
2023-03-03T11:05:05.5610961Z                 cursect[optname].append(value)
2023-03-03T11:05:05.5611153Z             # a section header or option header?
2023-03-03T11:05:05.5611322Z             else:
2023-03-03T11:05:05.5611483Z                 indent_level = cur_indent_level
2023-03-03T11:05:05.5611660Z                 # is it a section header?
2023-03-03T11:05:05.5611831Z                 mo = self.SECTCRE.match(value)
2023-03-03T11:05:05.5611996Z                 if mo:
2023-03-03T11:05:05.5612241Z                     sectname = mo.group('header')
2023-03-03T11:05:05.5612426Z                     if sectname in self._sections:
2023-03-03T11:05:05.5612627Z                         if self._strict and sectname in elements_added:
2023-03-03T11:05:05.5612844Z                             raise DuplicateSectionError(sectname, fpname,
2023-03-03T11:05:05.5613028Z                                                         lineno)
2023-03-03T11:05:05.5613206Z                         cursect = self._sections[sectname]
2023-03-03T11:05:05.5613392Z                         elements_added.add(sectname)
2023-03-03T11:05:05.5613747Z                     elif sectname == self.default_section:
2023-03-03T11:05:05.5613945Z                         cursect = self._defaults
2023-03-03T11:05:05.5614099Z                     else:
2023-03-03T11:05:05.5614259Z                         cursect = self._dict()
2023-03-03T11:05:05.5614443Z                         self._sections[sectname] = cursect
2023-03-03T11:05:05.5614648Z                         self._proxies[sectname] = SectionProxy(self, sectname)
2023-03-03T11:05:05.5614855Z                         elements_added.add(sectname)
2023-03-03T11:05:05.5615136Z                     # So sections can't start with a continuation line
2023-03-03T11:05:05.5615328Z                     optname = None
2023-03-03T11:05:05.5615501Z                 # no section header in the file?
2023-03-03T11:05:05.5615669Z                 elif cursect is None:
2023-03-03T11:05:05.5615870Z                     raise MissingSectionHeaderError(fpname, lineno, line)
2023-03-03T11:05:05.5616063Z                 # an option line?
2023-03-03T11:05:05.5616211Z                 else:
2023-03-03T11:05:05.5616510Z                     mo = self._optcre.match(value)
2023-03-03T11:05:05.5616672Z                     if mo:
2023-03-03T11:05:05.5616951Z                         optname, vi, optval = mo.group('option', 'vi', 'value')
2023-03-03T11:05:05.5617150Z                         if not optname:
2023-03-03T11:05:05.5617332Z                             e = self._handle_error(e, fpname, lineno, line)
2023-03-03T11:05:05.5617548Z                         optname = self.optionxform(optname.rstrip())
2023-03-03T11:05:05.5617742Z                         if (self._strict and
2023-03-03T11:05:05.5617923Z                             (sectname, optname) in elements_added):
2023-03-03T11:05:05.5618134Z >                           raise DuplicateOptionError(sectname, optname,
2023-03-03T11:05:05.5618323Z                                                        fpname, lineno)
2023-03-03T11:05:05.5618826Z E                           configparser.DuplicateOptionError: While reading from '/root/.azure/config' [line 31]: option 'cache_ttl' in section 'core' already exists
2023-03-03T11:05:05.5619016Z 
2023-03-03T11:05:05.5619208Z /opt/az/lib/python3.10/configparser.py:1098: DuplicateOptionError

History Notes

[Component Name 1] BREAKING CHANGE: az command a: Make some customer-facing breaking change
[Component Name 2] az command b: Add some customer-facing feature


This checklist is used to make sure that common guidelines for a pull request are followed.

@azure-client-tools-bot-prd
Copy link

azure-client-tools-bot-prd bot commented Mar 6, 2023

️✔️acr
️✔️2020-09-01-hybrid
️✔️3.10
️✔️3.9
️✔️latest
️✔️3.10
️✔️3.9
️✔️acs
️✔️2020-09-01-hybrid
️✔️3.10
️✔️3.9
️✔️latest
️✔️3.10
️✔️3.9
️✔️advisor
️✔️latest
️✔️3.10
️✔️3.9
️✔️ams
️✔️latest
️✔️3.10
️✔️3.9
️✔️apim
️✔️latest
️✔️3.10
️✔️3.9
️✔️appconfig
️✔️latest
️✔️3.10
️✔️3.9
️✔️appservice
️✔️latest
️✔️3.10
️✔️3.9
️✔️aro
️✔️latest
️✔️3.10
️✔️3.9
️✔️backup
️✔️latest
️✔️3.10
️✔️3.9
️✔️batch
️✔️latest
️✔️3.10
️✔️3.9
️✔️batchai
️✔️latest
️✔️3.10
️✔️3.9
️✔️billing
️✔️latest
️✔️3.10
️✔️3.9
️✔️botservice
️✔️latest
️✔️3.10
️✔️3.9
️✔️cdn
️✔️latest
️✔️3.10
️✔️3.9
️✔️cloud
️✔️latest
️✔️3.10
️✔️3.9
️✔️cognitiveservices
️✔️latest
️✔️3.10
️✔️3.9
️✔️config
️✔️latest
️✔️3.10
️✔️3.9
️✔️configure
️✔️latest
️✔️3.10
️✔️3.9
️✔️consumption
️✔️latest
️✔️3.10
️✔️3.9
️✔️container
️✔️latest
️✔️3.10
️✔️3.9
️✔️core
️✔️2018-03-01-hybrid
️✔️3.10
️✔️3.9
️✔️2019-03-01-hybrid
️✔️3.10
️✔️3.9
️✔️2020-09-01-hybrid
️✔️3.10
️✔️3.9
️✔️latest
️✔️3.10
️✔️3.9
️✔️cosmosdb
️✔️latest
️✔️3.10
️✔️3.9
️✔️databoxedge
️✔️2019-03-01-hybrid
️✔️3.10
️✔️3.9
️✔️2020-09-01-hybrid
️✔️3.10
️✔️3.9
️✔️latest
️✔️3.10
️✔️3.9
️✔️dla
️✔️latest
️✔️3.10
️✔️3.9
️✔️dls
️✔️latest
️✔️3.10
️✔️3.9
️✔️dms
️✔️latest
️✔️3.10
️✔️3.9
️✔️eventgrid
️✔️latest
️✔️3.10
️✔️3.9
️✔️eventhubs
️✔️latest
️✔️3.10
️✔️3.9
️✔️feedback
️✔️latest
️✔️3.10
️✔️3.9
️✔️find
️✔️latest
️✔️3.10
️✔️3.9
️✔️hdinsight
️✔️latest
️✔️3.10
️✔️3.9
️✔️identity
️✔️latest
️✔️3.10
️✔️3.9
️✔️iot
️✔️2019-03-01-hybrid
️✔️3.10
️✔️3.9
️✔️2020-09-01-hybrid
️✔️3.10
️✔️3.9
️✔️latest
️✔️3.10
️✔️3.9
️✔️keyvault
️✔️2018-03-01-hybrid
️✔️3.10
️✔️3.9
️✔️2020-09-01-hybrid
️✔️3.10
️✔️3.9
️✔️latest
️✔️3.10
️✔️3.9
️✔️kusto
️✔️latest
️✔️3.10
️✔️3.9
️✔️lab
️✔️latest
️✔️3.10
️✔️3.9
️✔️managedservices
️✔️latest
️✔️3.10
️✔️3.9
️✔️maps
️✔️latest
️✔️3.10
️✔️3.9
️✔️marketplaceordering
️✔️latest
️✔️3.10
️✔️3.9
️✔️monitor
️✔️latest
️✔️3.10
️✔️3.9
️✔️netappfiles
️✔️latest
️✔️3.10
️✔️3.9
️✔️network
️✔️2018-03-01-hybrid
️✔️3.10
️✔️3.9
️✔️latest
️✔️3.10
️✔️3.9
️✔️policyinsights
️✔️latest
️✔️3.10
️✔️3.9
️✔️privatedns
️✔️latest
️✔️3.10
️✔️3.9
️✔️profile
️✔️latest
️✔️3.10
️✔️3.9
️✔️rdbms
️✔️latest
️✔️3.10
️✔️3.9
️✔️redis
️✔️latest
️✔️3.10
️✔️3.9
️✔️relay
️✔️latest
️✔️3.10
️✔️3.9
️✔️resource
️✔️2018-03-01-hybrid
️✔️3.10
️✔️3.9
️✔️2019-03-01-hybrid
️✔️3.10
️✔️3.9
️✔️latest
️✔️3.10
️✔️3.9
️✔️role
️✔️latest
️✔️3.10
️✔️3.9
️✔️search
️✔️latest
️✔️3.10
️✔️3.9
️✔️security
️✔️latest
️✔️3.10
️✔️3.9
️✔️servicebus
️✔️latest
️✔️3.10
️✔️3.9
️✔️serviceconnector
️✔️latest
️✔️3.10
️✔️3.9
️✔️servicefabric
️✔️latest
️✔️3.10
️✔️3.9
️✔️signalr
️✔️latest
️✔️3.10
️✔️3.9
️✔️sql
️✔️latest
️✔️3.10
️✔️3.9
️✔️sqlvm
️✔️latest
️✔️3.10
️✔️3.9
️✔️storage
️✔️2018-03-01-hybrid
️✔️3.10
️✔️3.9
️✔️2019-03-01-hybrid
️✔️3.10
️✔️3.9
️✔️2020-09-01-hybrid
️✔️3.10
️✔️3.9
️✔️latest
️✔️3.10
️✔️3.9
️✔️synapse
️✔️latest
️✔️3.10
️✔️3.9
️✔️telemetry
️✔️2018-03-01-hybrid
️✔️3.10
️✔️3.9
️✔️2019-03-01-hybrid
️✔️3.10
️✔️3.9
️✔️2020-09-01-hybrid
️✔️3.10
️✔️3.9
️✔️latest
️✔️3.10
️✔️3.9
️✔️util
️✔️latest
️✔️3.10
️✔️3.9
️✔️vm
️✔️2018-03-01-hybrid
️✔️3.10
️✔️3.9
️✔️2019-03-01-hybrid
️✔️3.10
️✔️3.9
️✔️2020-09-01-hybrid
️✔️3.10
️✔️3.9
️✔️latest
️✔️3.10
️✔️3.9

@ghost ghost added Auto-Assign Auto assign by bot CI CI labels Mar 6, 2023
@ghost ghost requested review from wangzelin007, yonzhan, jiasli, kairu-ms and jsntcy March 6, 2023 06:55
@ghost ghost assigned wangzelin007 Mar 6, 2023
@ghost ghost added this to the March 2023 (2023-04-04) milestone Mar 6, 2023
@yonzhan
Copy link
Collaborator

yonzhan commented Mar 6, 2023

CI

@bebound bebound changed the title {CI} Use random config dir in DummyCli {Core} Add random_config_dir param in DummyCli Mar 8, 2023
@@ -568,7 +571,7 @@ def test_role_assignment_handle_conflicted_assignments(self, resource_group):

self.assertGreaterEqual(len(local_defaults_config), 1)
actual = set([(x['name'], x['source'], x['value']) for x in local_defaults_config if x['name'] == 'group'])
expected = set([('group', os.path.join(temp_dir, '.azure', 'config'), self.kwargs['rg'])])
expected = set([('group', os.path.join(temp_dir, os.path.basename(self.cli_ctx.config.config_dir), 'config'), self.kwargs['rg'])])
Copy link
Contributor Author

@bebound bebound Mar 9, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The config path is temp_dir+basename(config_dir)+'config' when --scope local

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's provide some concrete example.

Copy link
Contributor Author

@bebound bebound Mar 24, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If work dir is C:\Users\hanglei\AppData\Local\Temp\tmplxf_89ez, local config file is C:\Users\hanglei\AppData\Local\Temp\tmplxf_89ez\0azXbKR9OdJuZPFS\config

0azXbKR9OdJuZPFS is the base name of config dir: ~/.azure/dummy_cli_config_dir/0azXbKR9OdJuZPFS/

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The local config folder was constructed by knack.config.CLIConfig:

https://github.com/microsoft/knack/blob/e496c9590792572e680cb3ec959db175d9ba85dd/knack/config.py#L63

config_dir_name = os.path.basename(self.config_dir)
current_config_dir = os.path.join(current_dir, config_dir_name)

current_config_dir is constructed by combining current_dir with the random dir name, making the path a little bit weird.

@bebound bebound marked this pull request as ready for review March 9, 2023 03:59
@@ -181,7 +186,8 @@ class LocalContextScenarioTest(ScenarioTest):
def __init__(self, method_name, config_file=None, recording_name=None, recording_processors=None,
replay_processors=None, recording_patches=None, replay_patches=None, working_dir=None):
super(LocalContextScenarioTest, self).__init__(method_name, config_file, recording_name, recording_processors,
replay_processors, recording_patches, replay_patches)
replay_processors, recording_patches, replay_patches,
random_config_dir=True)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ConfigureGlobalDefaultsTest runs config param-persist off in tearDown. I think use random_config_dir is necessary

Copy link
Member

@jiasli jiasli Mar 17, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Local Context/Param Persist has been deprecated. Consider deleting related tests instead: #24726

Comment on lines +30 to +31
config_dir=os.path.join(GLOBAL_CONFIG_DIR, 'dummy_cli_config_dir',
random_string()) if random_config_dir else GLOBAL_CONFIG_DIR,
Copy link
Member

@jiasli jiasli Mar 17, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As an alternative, we may also consider using tempfile module: https://docs.python.org/3/library/tempfile.html

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, sorry I didn't make my point clear. I am simply providing an alternative solution. You solution is actually better since your location is easy to find. 😉

Comment on lines 143 to 144
import shutil
shutil.rmtree(self.cli_ctx.config.config_dir, ignore_errors=True)
Copy link
Member

@jiasli jiasli Mar 17, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well... yes. rmtree can fail intermittently on Windows. Consider using

def rmtree_with_retry(path):

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, yes. I forget that Windows bug.

from azure.cli.core._config import GLOBAL_CONFIG_DIR, ENV_VAR_PREFIX
from azure.cli.core._help import AzCliHelp
from azure.cli.core._output import AzOutputProducer

from knack.completion import ARGCOMPLETE_ENV_NAME

random_config_dir = kwargs.get('random_config_dir', False)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider making it an explicit kwarg.

@@ -255,6 +255,9 @@ def test_role_definition_scenario(self):

class RoleAssignmentScenarioTest(RoleScenarioTestBase):

def __init__(self, *arg, **kwargs):
super().__init__(*arg, random_config_dir=True, **kwargs)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

random_config_dir=True make tests under RoleAssignmentScenarioTest fail during live run, because the login context is lost.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, we need to merge #26475 first.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Auto-Assign Auto assign by bot CI CI
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants