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

[AKS] Add a live test pipeline for aks-preview PR check-in #3292

Merged
merged 42 commits into from
May 17, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
7f415ad
add live test pipeline for aks
FumingZhang Apr 22, 2021
51cd3ea
* add readme and history
FumingZhang Apr 23, 2021
c90d0f4
fix condition bug in prepare_image.sh
FumingZhang Apr 23, 2021
94e93e9
add ci mode (only test diff)
FumingZhang Apr 25, 2021
3390af4
update variable names in bash scripts
FumingZhang Apr 25, 2021
57f08be
source bash scripts & add clean up script
FumingZhang Apr 25, 2021
6db5ef6
wrap predefined variables
FumingZhang Apr 25, 2021
5df5e6f
install git in image
FumingZhang Apr 25, 2021
f7163fd
remove ci mode in cli test
FumingZhang Apr 25, 2021
c446a0e
add azdev test sp env vars
FumingZhang Apr 26, 2021
0c21d3b
fix yaml bug
FumingZhang Apr 27, 2021
288deba
add init filter
FumingZhang Apr 28, 2021
f897d85
* replace azdev with az-aks-tool
FumingZhang Apr 29, 2021
325af8b
replace ResourceGroupPreparer with AKSCustomResourceGroupPreparer
FumingZhang Apr 29, 2021
f786816
fix import bug
FumingZhang Apr 29, 2021
9690bee
add license
FumingZhang Apr 29, 2021
11f2330
update filter
FumingZhang May 6, 2021
20fe1a7
update script
FumingZhang May 6, 2021
c17d64c
add unit tests
FumingZhang May 6, 2021
edafbe9
add license
FumingZhang May 7, 2021
e217974
* refine unit test & add coverage report for ext
FumingZhang May 8, 2021
a23b397
refine report upload
FumingZhang May 8, 2021
781ebf5
fix yaml
FumingZhang May 8, 2021
413166f
fix path
FumingZhang May 8, 2021
0ea8d41
remove dockerfile and local build option
FumingZhang May 8, 2021
c2d0456
fix unittest discover
FumingZhang May 8, 2021
73a5a5b
fix file missing & replace with /usr/bin/env
FumingZhang May 8, 2021
eb7e19d
fix unittest
FumingZhang May 8, 2021
ccff955
split out a single unit test pipeline & refine log
FumingZhang May 8, 2021
c13ccc4
update env passing
FumingZhang May 8, 2021
4a001a8
add missing license header
FumingZhang May 8, 2021
624e42c
replacing azdev
FumingZhang May 8, 2021
31c9b18
remove azdev dependency
FumingZhang May 10, 2021
12f008f
update unittest
FumingZhang May 10, 2021
8496d62
fix naming conflict
FumingZhang May 10, 2021
6fccd93
update readme & fix live run bug
FumingZhang May 10, 2021
81f7430
update folder structure
FumingZhang May 14, 2021
5e87e34
update test
FumingZhang May 14, 2021
5aefd43
update pipeline
FumingZhang May 14, 2021
1c83831
update filter mechanism
FumingZhang May 14, 2021
82a2e4f
update comment
FumingZhang May 17, 2021
9088573
remove init file
FumingZhang May 17, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/aks-preview/az_aks_tool/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
__pycache__
42 changes: 42 additions & 0 deletions src/aks-preview/az_aks_tool/cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------

import glob
import os
import logging

import az_aks_tool.const as const
import az_aks_tool.index as index
logger = logging.getLogger(__name__)


def get_cli_mod_data(mod_name=const.ACS_MOD_NAME, profile="latest"):
profile_split = profile.split('-')
profile_namespace = '_'.join([profile_split[-1]] + profile_split[:-1])

# key value pairs of all modules(in azcli & extention) and its absolute path, used later to find test indexes
path_table = index.get_path_table()
command_modules = path_table["mod"]
inverse_name_table = index.get_name_index(invert=True)

# construct 'import_name' & mod_data', used later to find test indexes
acs_mod_path = command_modules[mod_name]
mod_data = {
"alt_name": "{}{}".format(const.COMMAND_MODULE_PREFIX, mod_name),
"filepath": os.path.join(acs_mod_path, "tests", profile_namespace),
"base_path": "azure.cli.command_modules.{}.tests.{}".format(mod_name, profile_namespace),
"files": {}
}

cli_test = index.discover_module_tests(mod_name, mod_data)
return cli_test


def get_cli_test_index(module_data=None, mod_name=const.ACS_MOD_NAME, profile="latest"):
if mod_name in module_data:
mod_data = module_data[mod_name]
else:
mod_data = get_cli_mod_data(mod_name=mod_name, profile=profile)
return mod_data["files"]
17 changes: 17 additions & 0 deletions src/aks-preview/az_aks_tool/const.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------

import sys

IS_WINDOWS = sys.platform.lower() in ['windows', 'win32']

CLI_REPO_NAME = "azure-cli"
EXT_REPO_NAME = 'azure-cli-extensions'
COMMAND_MODULE_PREFIX = 'azure-cli-'
EXTENSION_PREFIX = 'azext_'
ACS_MOD_NAME = "acs"
AKS_PREVIEW_MOD_NAME = EXTENSION_PREFIX + "aks_preview" # azext_aks_preview

ENV_VAR_TEST_LIVE = 'AZURE_TEST_RUN_LIVE' # denotes that tests should be run live instead of played back
46 changes: 46 additions & 0 deletions src/aks-preview/az_aks_tool/ext.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------

import glob
import os
import logging

import az_aks_tool.const as const
import az_aks_tool.index as index
logger = logging.getLogger(__name__)


def get_ext_mod_data(mod_name=const.AKS_PREVIEW_MOD_NAME, profile="latest"):
profile_split = profile.split('-')
profile_namespace = '_'.join([profile_split[-1]] + profile_split[:-1])

# key value pairs of all modules(in azcli & extention) and its absolute path, used later to find test indexes
path_table = index.get_path_table()
extensions = path_table["ext"]
inverse_name_table = index.get_name_index(invert=True)

# construct 'import_name' & mod_data', used later to find test indexes
aks_preview_mod_path = extensions[mod_name]
glob_pattern = os.path.normcase(
os.path.join("{}*".format(const.EXTENSION_PREFIX)))
file_path = glob.glob(os.path.join(aks_preview_mod_path, glob_pattern))[0]
import_name = os.path.basename(file_path)
mod_data = {
"alt_name": inverse_name_table[mod_name],
"filepath": os.path.join(file_path, "tests", profile_namespace),
"base_path": "{}.tests.{}".format(import_name, profile_namespace),
"files": {}
}

ext_test = index.discover_module_tests(import_name, mod_data)
return ext_test


def get_ext_test_index(module_data=None, mod_name=const.AKS_PREVIEW_MOD_NAME, profile="latest"):
if mod_name in module_data:
mod_data = module_data[mod_name]
else:
mod_data = get_ext_mod_data(mod_name=mod_name, profile=profile)
return mod_data["files"]
120 changes: 120 additions & 0 deletions src/aks-preview/az_aks_tool/filter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------

import logging
from collections import Iterable
logger = logging.getLogger(__name__)


def extract_file_class_pairs(tag_list):
pairs = []
for k in tag_list:
tags = k.split(".")
if len(tags) == 2:
pairs.append((tags[0], tags[1]))
return pairs


def filter_valid_file_class_pairs(pairs, test_index):
valid_pairs = []
for pair in pairs:
if pair[0] in test_index and pair[1] in test_index[pair[0]]:
valid_pairs.append(pair)
logger.debug("Valid file & class pair: '{}'".format(pair))
else:
logger.debug("Invalid file & class pair: '{}'".format(pair))
return valid_pairs


def get_all_values_from_nested_dict(d):
for v in d.values():
if isinstance(v, dict):
yield from get_all_values_from_nested_dict(v)
else:
yield v


def flatten_nested_list(lis):
for item in lis:
if isinstance(item, Iterable) and not isinstance(item, str):
for x in flatten_nested_list(item):
yield x
else:
yield item


def filter_valid_test_cases(test_cases, test_index):
valid_test_cases = []
nested_test_cases = list(get_all_values_from_nested_dict(test_index))
falttened_test_cases = list(flatten_nested_list(nested_test_cases))
for test_case in test_cases:
if test_case in falttened_test_cases:
valid_test_cases.append(test_case)
logger.debug("Valid test case: '{}'".format(test_case))
else:
logger.debug("Invalid test case: '{}'".format(test_case))
return valid_test_cases


def get_test_cases(test_index, matrix, extra_coverage=None):
test_cases = []
coverage = matrix.get("coverage", {})
# default coverage
for fileName, className in coverage.items():
for c in className:
test_cases.extend(test_index[fileName][c])
# custom extra coverage
if extra_coverage:
# method 1: fileName.className
file_class_pairs = extract_file_class_pairs(extra_coverage)
valid_file_class_pairs = filter_valid_file_class_pairs(
file_class_pairs, test_index)
for valid_pair in valid_file_class_pairs:
test_cases.extend(
test_index[valid_pair[0]][valid_pair[1]])
# method 2: test cases
test_cases.extend(filter_valid_test_cases(
extra_coverage, test_index))
return list(set(test_cases))


def get_exclude_test_cases(test_index, matrix, extra_filter=None):
exclude_test_cases = []
exclude = matrix.get("exclude", {})
# default exclude
if not extra_filter or "default" in extra_filter:
matrix_test_cases = []
matrix_file_class_pairs = []
for k, v in exclude.items():
# method 1: reason -> test cases
matrix_test_cases.extend(v)
# method 2: fileName -> className
matrix_file_class_pairs.extend((k, x) for x in v)
# method 1: reason -> test cases
exclude_test_cases.extend(
filter_valid_test_cases(matrix_test_cases, test_index))
# method 2: fileName -> className
valid_matrix_file_class_pairs = filter_valid_file_class_pairs(
matrix_file_class_pairs, test_index)
for valid_matrix_pair in valid_matrix_file_class_pairs:
exclude_test_cases.extend(
test_index[valid_matrix_pair[0]][valid_matrix_pair[1]])
# custom extra_filter
if extra_filter:
# method 1: matrix exclude key
for k, v in exclude.items():
if k in extra_filter:
exclude_test_cases.extend(v)
# method 2: fileName.className
file_class_pairs = extract_file_class_pairs(extra_filter)
valid_file_class_pairs = filter_valid_file_class_pairs(
file_class_pairs, test_index)
for valid_pair in valid_file_class_pairs:
exclude_test_cases.extend(
test_index[valid_pair[0]][valid_pair[1]])
# method 3: test cases
exclude_test_cases.extend(
filter_valid_test_cases(extra_filter, test_index))
return list(set(exclude_test_cases))
Loading